1/** 2 * (c) jSuites Javascript Web Components 3 * 4 * Website: https://jsuites.net 5 * Description: Create amazing web based applications. 6 * 7 * MIT License 8 * 9 */ 10;(function (global, factory) { 11 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 12 typeof define === 'function' && define.amd ? define(factory) : 13 global.jSuites = factory(); 14}(this, (function () { 15 16 'use strict'; 17 18var jSuites = {}; 19 20var Version = '4.17.5'; 21 22var Events = function() { 23 24 document.jsuitesComponents = []; 25 26 var find = function(DOMElement, component) { 27 if (DOMElement[component.type] && DOMElement[component.type] == component) { 28 return true; 29 } 30 if (DOMElement.component && DOMElement.component == component) { 31 return true; 32 } 33 if (DOMElement.parentNode) { 34 return find(DOMElement.parentNode, component); 35 } 36 return false; 37 } 38 39 var isOpened = function(e) { 40 if (document.jsuitesComponents && document.jsuitesComponents.length > 0) { 41 for (var i = 0; i < document.jsuitesComponents.length; i++) { 42 if (document.jsuitesComponents[i] && ! find(e, document.jsuitesComponents[i])) { 43 document.jsuitesComponents[i].close(); 44 } 45 } 46 } 47 } 48 49 // Width of the border 50 var cornerSize = 15; 51 52 // Current element 53 var element = null; 54 55 // Controllers 56 var editorAction = false; 57 58 // Event state 59 var state = { 60 x: null, 61 y: null, 62 } 63 64 // Tooltip element 65 var tooltip = document.createElement('div') 66 tooltip.classList.add('jtooltip'); 67 68 // Events 69 var mouseDown = function(e) { 70 // Check if this is the floating 71 var item = jSuites.findElement(e.target, 'jpanel'); 72 // Jfloating found 73 if (item && ! item.classList.contains("readonly")) { 74 // Add focus to the chart container 75 item.focus(); 76 // Keep the tracking information 77 var rect = e.target.getBoundingClientRect(); 78 editorAction = { 79 e: item, 80 x: e.clientX, 81 y: e.clientY, 82 w: rect.width, 83 h: rect.height, 84 d: item.style.cursor, 85 resizing: item.style.cursor ? true : false, 86 actioned: false, 87 } 88 89 // Make sure width and height styling is OK 90 if (! item.style.width) { 91 item.style.width = rect.width + 'px'; 92 } 93 94 if (! item.style.height) { 95 item.style.height = rect.height + 'px'; 96 } 97 98 // Remove any selection from the page 99 var s = window.getSelection(); 100 if (s.rangeCount) { 101 for (var i = 0; i < s.rangeCount; i++) { 102 s.removeRange(s.getRangeAt(i)); 103 } 104 } 105 106 e.preventDefault(); 107 e.stopPropagation(); 108 } else { 109 // No floating action found 110 editorAction = false; 111 } 112 113 // Verify current components tracking 114 if (e.changedTouches && e.changedTouches[0]) { 115 var x = e.changedTouches[0].clientX; 116 var y = e.changedTouches[0].clientY; 117 } else { 118 var x = e.clientX; 119 var y = e.clientY; 120 } 121 122 // Which component I am clicking 123 var path = e.path || (e.composedPath && e.composedPath()); 124 125 // If path available get the first element in the chain 126 if (path) { 127 element = path[0]; 128 } else { 129 // Try to guess using the coordinates 130 if (e.target && e.target.shadowRoot) { 131 var d = e.target.shadowRoot; 132 } else { 133 var d = document; 134 } 135 // Get the first target element 136 element = d.elementFromPoint(x, y); 137 } 138 139 isOpened(element); 140 } 141 142 var mouseUp = function(e) { 143 if (editorAction && editorAction.e) { 144 if (typeof(editorAction.e.refresh) == 'function' && state.actioned) { 145 editorAction.e.refresh(); 146 } 147 editorAction.e.style.cursor = ''; 148 } 149 150 // Reset 151 state = { 152 x: null, 153 y: null, 154 } 155 156 editorAction = false;
157 } 158 159 var mouseMove = function(e) { 160 if (editorAction) { 161 var x = e.clientX || e.pageX; 162 var y = e.clientY || e.pageY; 163 164 // Action on going 165 if (! editorAction.resizing) { 166 if (state.x == null && state.y == null) { 167 state.x = x; 168 state.y = y; 169 } 170 171 var dx = x - state.x; 172 var dy = y - state.y; 173 var top = editorAction.e.offsetTop + dy; 174 var left = editorAction.e.offsetLeft + dx; 175 176 // Update position 177 editorAction.e.style.top = top + 'px'; 178 editorAction.e.style.left = left + 'px'; 179 editorAction.e.style.cursor = "move"; 180 181 state.x = x; 182 state.y = y; 183 184 185 // Update element 186 if (typeof(editorAction.e.refresh) == 'function') { 187 state.actioned = true; 188 editorAction.e.refresh('position', top, left); 189 } 190 } else { 191 var width = null; 192 var height = null; 193 194 if (editorAction.d == 'e-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'se-resize') { 195 // Update width 196 width = editorAction.w + (x - editorAction.x); 197 editorAction.e.style.width = width + 'px'; 198 199 // Update Height 200 if (e.shiftKey) { 201 var newHeight = (x - editorAction.x) * (editorAction.h / editorAction.w); 202 height = editorAction.h + newHeight; 203 editorAction.e.style.height = height + 'px'; 204 } else { 205 var newHeight = false; 206 } 207 } 208 209 if (! newHeight) { 210 if (editorAction.d == 's-resize' || editorAction.d == 'se-resize' || editorAction.d == 'sw-resize') { 211 height = editorAction.h + (y - editorAction.y); 212 editorAction.e.style.height = height + 'px'; 213 } 214 } 215 216 // Update element 217 if (typeof(editorAction.e.refresh) == 'function') { 218 state.actioned = true; 219 editorAction.e.refresh('dimensions', width, height); 220 } 221 } 222 } else { 223 // Resizing action 224 var item = jSuites.findElement(e.target, 'jpanel'); 225 // Found eligible component 226 if (item) { 227 if (item.getAttribute('tabindex')) { 228 var rect = item.getBoundingClientRect(); 229 if (e.clientY - rect.top < cornerSize) { 230 if (rect.width - (e.clientX - rect.left) < cornerSize) { 231 item.style.cursor = 'ne-resize'; 232 } else if (e.clientX - rect.left < cornerSize) { 233 item.style.cursor = 'nw-resize'; 234 } else { 235 item.style.cursor = 'n-resize'; 236 } 237 } else if (rect.height - (e.clientY - rect.top) < cornerSize) { 238 if (rect.width - (e.clientX - rect.left) < cornerSize) { 239 item.style.cursor = 'se-resize'; 240 } else if (e.clientX - rect.left < cornerSize) { 241 item.style.cursor = 'sw-resize'; 242 } else { 243 item.style.cursor = 's-resize'; 244 } 245 } else if (rect.width - (e.clientX - rect.left) < cornerSize) { 246 item.style.cursor = 'e-resize'; 247 } else if (e.clientX - rect.left < cornerSize) { 248 item.style.cursor = 'w-resize'; 249 } else { 250 item.style.cursor = ''; 251 } 252 } 253 } 254 } 255 } 256 257 var mouseOver = function(e) { 258 var message = e.target.getAttribute('data-tooltip'); 259 if (message) { 260 // Instructions 261 tooltip.innerText = message; 262 263 // Position 264 if (e.changedTouches && e.changedTouches[0]) { 265 var x = e.changedTouches[0].clientX; 266 var y = e.changedTouches[0].clientY; 267 } else { 268 var x = e.clientX; 269 var y = e.clientY; 270 } 271 272 tooltip.style.top = y + 'px'; 273 tooltip.style.left = x + 'px'; 274 document.body.appendChild(tooltip); 275 } else if (tooltip.innerText) { 276 tooltip.innerText = ''; 277 document.body.removeChild(tooltip); 278 } 279 } 280 281 var dblClick = function(e) { 282 var item = jSuites.findElement(e.target, 'jpanel'); 283 if (item && typeof(item.dblclick) == 'function') { 284 // Create edition 285 item.dblclick(e); 286 } 287 } 288 289 var contextMenu = function(e) { 290 var item = document.activeElement; 291 if (item && typeof(item.contextmenu) == 'function') { 292 // Create edition 293 item.contextmenu(e); 294 295 e.preventDefault(); 296 e.stopImmediatePropagation(); 297 } else { 298 // Search for possible context menus 299 item = jSuites.findElement(e.target, function(o) { 300 return o.tagName && o.getAttribute('aria-contextmenu-id'); 301 }); 302 303 if (item) { 304 var o = document.querySelector('#' + item); 305 if (! o) { 306 console.error('JSUITES: contextmenu id not found: ' + item); 307 } else { 308 o.contextmenu.open(e); 309 e.preventDefault(); 310 e.stopImmediatePropagation(); 311 } 312 } 313 } 314 } 315 316 var keyDown = function(e) { 317 var item = document.activeElement; 318 if (item) { 319 if (e.key == "Delete" && typeof(item.delete) == 'function') { 320 item.delete(); 321 e.preventDefault(); 322 e.stopImmediatePropagation(); 323 } 324 } 325 326 if (document.jsuitesComponents && document.jsuitesComponents.length) { 327 if (item = document.jsuitesComponents[document.jsuitesComponents.length - 1]) { 328 if (e.key == "Escape" && typeof(item.isOpened) == 'function' && typeof(item.close) == 'function') { 329 if (item.isOpened()) { 330 item.close(); 331 e.preventDefault(); 332 e.stopImmediatePropagation(); 333 } 334 } 335 } 336 } 337 } 338 339 document.addEventListener('mouseup', mouseUp); 340 document.addEventListener("mousedown", mouseDown); 341 document.addEventListener('mousemove', mouseMove); 342 document.addEventListener('mouseover', mouseOver); 343 document.addEventListener('dblclick', dblClick); 344 document.addEventListener('keydown', keyDown); 345 document.addEventListener('contextmenu', contextMenu); 346} 347 348/** 349 * Global jsuites event 350 */ 351if (typeof(document) !== "undefined" && ! document.jsuitesComponents) { 352 Events(); 353} 354 355jSuites.version = Version; 356 357jSuites.setExtensions = function(o) { 358 if (typeof(o) == 'object') { 359 var k = Object.keys(o); 360 for (var i = 0; i < k.length; i++) { 361 jSuites[k[i]] = o[k[i]]; 362 } 363 } 364} 365 366jSuites.tracking = function(component, state) { 367 if (state == true) { 368 document.jsuitesComponents = document.jsuitesComponents.filter(function(v) { 369 return v !== null; 370 }); 371 372 // Start after all events 373 setTimeout(function() { 374 document.jsuitesComponents.push(component); 375 }, 0); 376 377 } else { 378 var index = document.jsuitesComponents.indexOf(component); 379 if (index >= 0) { 380 document.jsuitesComponents.splice(index, 1); 381 } 382 } 383} 384 385/** 386 * Get or set a property from a JSON from a string. 387 */ 388jSuites.path = function(str, val) { 389 str = str.split('.'); 390 if (str.length) { 391 var o = this; 392 var p = null; 393 while (str.length > 1) { 394 // Get the property 395 p = str.shift(); 396 // Check if the property exists 397 if (o.hasOwnProperty(p)) { 398 o = o[p]; 399 } else { 400 // Property does not exists 401 if (val === undefined) { 402 return undefined; 403 } else { 404 // Create the property 405 o[p] = {}; 406 // Next property 407 o = o[p]; 408 } 409 } 410 } 411 // Get the property 412 p = str.shift(); 413 // Set or get the value 414 if (val !== undefined) { 415 o[p] = val; 416 // Success 417 return true; 418 } else { 419 // Return the value 420 if (o) { 421 return o[p]; 422 } 423 } 424 } 425 // Something went wrong 426 return false;
vendor: 49,887 bytes, lines 427-1938
427} 428 429// Update dictionary 430jSuites.setDictionary = function(d) { 431 if (! document.dictionary) { 432 document.dictionary = {} 433 } 434 // Replace the key into the dictionary and append the new ones 435 var k = Object.keys(d); 436 for (var i = 0; i < k.length; i++) { 437 document.dictionary[k[i]] = d[k[i]]; 438 } 439 440 // Translations 441 var t = null; 442 for (var i = 0; i < jSuites.calendar.weekdays.length; i++) { 443 t = jSuites.translate(jSuites.calendar.weekdays[i]); 444 if (jSuites.calendar.weekdays[i]) { 445 jSuites.calendar.weekdays[i] = t; 446 jSuites.calendar.weekdaysShort[i] = t.substr(0,3); 447 } 448 } 449 for (var i = 0; i < jSuites.calendar.months.length; i++) { 450 t = jSuites.translate(jSuites.calendar.months[i]); 451 if (t) { 452 jSuites.calendar.months[i] = t; 453 jSuites.calendar.monthsShort[i] = t.substr(0,3); 454 } 455 } 456} 457 458// Translate 459jSuites.translate = function(t) { 460 if (typeof(document) !== "undefined" && document.dictionary) { 461 return document.dictionary[t] || t; 462 } else { 463 return t; 464 } 465} 466 467jSuites.ajax = (function(options, complete) { 468 if (Array.isArray(options)) { 469 // Create multiple request controller 470 var multiple = { 471 instance: [], 472 complete: complete, 473 } 474 475 if (options.length > 0) { 476 for (var i = 0; i < options.length; i++) { 477 options[i].multiple = multiple; 478 multiple.instance.push(jSuites.ajax(options[i])); 479 } 480 } 481 482 return multiple; 483 } 484 485 if (! options.data) { 486 options.data = {}; 487 } 488 489 if (options.type) { 490 options.method = options.type; 491 } 492 493 // Default method 494 if (! options.method) { 495 options.method = 'GET'; 496 } 497 498 // Default type 499 if (! options.dataType) { 500 options.dataType = 'json'; 501 } 502 503 if (options.data) { 504 // Parse object to variables format 505 var parseData = function (value, key) { 506 var vars = []; 507 if (value) { 508 var keys = Object.keys(value); 509 if (keys.length) { 510 for (var i = 0; i < keys.length; i++) { 511 if (key) { 512 var k = key + '[' + keys[i] + ']'; 513 } else { 514 var k = keys[i]; 515 } 516 517 if (value[k] instanceof FileList) { 518 vars[k] = value[keys[i]]; 519 } else if (value[keys[i]] === null || value[keys[i]] === undefined) { 520 vars[k] = ''; 521 } else if (typeof(value[keys[i]]) == 'object') { 522 var r = parseData(value[keys[i]], k); 523 var o = Object.keys(r); 524 for (var j = 0; j < o.length; j++) { 525 vars[o[j]] = r[o[j]]; 526 } 527 } else { 528 vars[k] = value[keys[i]]; 529 } 530 } 531 } 532 } 533 534 return vars; 535 } 536 537 var d = parseData(options.data); 538 var k = Object.keys(d); 539 540 // Data form 541 if (options.method == 'GET') { 542 if (k.length) { 543 var data = []; 544 for (var i = 0; i < k.length; i++) { 545 data.push(k[i] + '=' + encodeURIComponent(d[k[i]])); 546 } 547 548 if (options.url.indexOf('?') < 0) { 549 options.url += '?'; 550 } 551 options.url += data.join('&'); 552 } 553 } else { 554 var data = new FormData(); 555 for (var i = 0; i < k.length; i++) { 556 if (d[k[i]] instanceof FileList) { 557 if (d[k[i]].length) { 558 for (var j = 0; j < d[k[i]].length; j++) { 559 data.append(k[i], d[k[i]][j], d[k[i]][j].name); 560 } 561 } 562 } else { 563 data.append(k[i], d[k[i]]); 564 } 565 } 566 } 567 } 568 569 var httpRequest = new XMLHttpRequest(); 570 httpRequest.open(options.method, options.url, true); 571 httpRequest.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 572 573 // Content type 574 if (options.contentType) { 575 httpRequest.setRequestHeader('Content-Type', options.contentType); 576 } 577 578 // Headers 579 if (options.method == 'POST') { 580 httpRequest.setRequestHeader('Accept', 'application/json'); 581 } else { 582 if (options.dataType == 'blob') { 583 httpRequest.responseType = "blob"; 584 } else { 585 if (! options.contentType) { 586 if (options.dataType == 'json') { 587 httpRequest.setRequestHeader('Content-Type', 'text/json'); 588 } else if (options.dataType == 'html') { 589 httpRequest.setRequestHeader('Content-Type', 'text/html'); 590 } 591 } 592 } 593 } 594 595 // No cache 596 if (options.cache != true) { 597 httpRequest.setRequestHeader('pragma', 'no-cache'); 598 httpRequest.setRequestHeader('cache-control', 'no-cache'); 599 } 600 601 // Authentication 602 if (options.withCredentials == true) { 603 httpRequest.withCredentials = true 604 } 605 606 // Before send 607 if (typeof(options.beforeSend) == 'function') { 608 options.beforeSend(httpRequest); 609 } 610 611 // Before send 612 if (typeof(jSuites.ajax.beforeSend) == 'function') { 613 jSuites.ajax.beforeSend(httpRequest); 614 } 615 616 if (document.ajax && typeof(document.ajax.beforeSend) == 'function') { 617 document.ajax.beforeSend(httpRequest); 618 } 619 620 httpRequest.onload = function() { 621 if (httpRequest.status === 200) { 622 if (options.dataType == 'json') { 623 try { 624 var result = JSON.parse(httpRequest.responseText); 625 626 if (options.success && typeof(options.success) == 'function') { 627 options.success(result); 628 } 629 } catch(err) { 630 if (options.error && typeof(options.error) == 'function') { 631 options.error(err, result); 632 } 633 } 634 } else { 635 if (options.dataType == 'blob') { 636 var result = httpRequest.response; 637 } else { 638 var result = httpRequest.responseText; 639 } 640 641 if (options.success && typeof(options.success) == 'function') { 642 options.success(result); 643 } 644 } 645 } else { 646 if (options.error && typeof(options.error) == 'function') { 647 options.error(httpRequest.responseText, httpRequest.status); 648 } 649 } 650 651 // Global queue 652 if (jSuites.ajax.queue && jSuites.ajax.queue.length > 0) { 653 jSuites.ajax.send(jSuites.ajax.queue.shift()); 654 } 655 656 // Global complete method 657 if (jSuites.ajax.requests && jSuites.ajax.requests.length) { 658 // Get index of this request in the container 659 var index = jSuites.ajax.requests.indexOf(httpRequest); 660 // Remove from the ajax requests container 661 jSuites.ajax.requests.splice(index, 1); 662 // Deprected: Last one? 663 if (! jSuites.ajax.requests.length) { 664 // Object event 665 if (options.complete && typeof(options.complete) == 'function') { 666 options.complete(result); 667 } 668 } 669 // Group requests 670 if (options.group) { 671 if (jSuites.ajax.oncomplete && typeof(jSuites.ajax.oncomplete[options.group]) == 'function') { 672 if (! jSuites.ajax.pending(options.group)) { 673 jSuites.ajax.oncomplete[options.group](); 674 jSuites.ajax.oncomplete[options.group] = null; 675 } 676 } 677 } 678 // Multiple requests controller 679 if (options.multiple && options.multiple.instance) { 680 // Get index of this request in the container 681 var index = options.multiple.instance.indexOf(httpRequest); 682 // Remove from the ajax requests container 683 options.multiple.instance.splice(index, 1); 684 // If this is the last one call method complete 685 if (! options.multiple.instance.length) { 686 if (options.multiple.complete && typeof(options.multiple.complete) == 'function') { 687 options.multiple.complete(result); 688 } 689 } 690 } 691 } 692 } 693 694 // Keep the options 695 httpRequest.options = options; 696 // Data 697 httpRequest.data = data; 698 699 // Queue 700 if (options.queue == true && jSuites.ajax.requests.length > 0) { 701 jSuites.ajax.queue.push(httpRequest); 702 } else { 703 jSuites.ajax.send(httpRequest) 704 } 705 706 return httpRequest; 707}); 708 709jSuites.ajax.send = function(httpRequest) { 710 if (httpRequest.data) { 711 if (Array.isArray(httpRequest.data)) { 712 httpRequest.send(httpRequest.data.join('&')); 713 } else { 714 httpRequest.send(httpRequest.data); 715 } 716 } else { 717 httpRequest.send(); 718 } 719 720 jSuites.ajax.requests.push(httpRequest); 721} 722 723jSuites.ajax.exists = function(url, __callback) { 724 var http = new XMLHttpRequest(); 725 http.open('HEAD', url, false); 726 http.send(); 727 if (http.status) { 728 __callback(http.status); 729 } 730} 731 732jSuites.ajax.pending = function(group) { 733 var n = 0; 734 var o = jSuites.ajax.requests; 735 if (o && o.length) { 736 for (var i = 0; i < o.length; i++) { 737 if (! group || group == o[i].options.group) { 738 n++ 739 } 740 } 741 } 742 return n; 743} 744 745jSuites.ajax.oncomplete = {}; 746jSuites.ajax.requests = []; 747jSuites.ajax.queue = []; 748 749jSuites.alert = function(message) { 750 if (jSuites.getWindowWidth() < 800 && jSuites.dialog) { 751 jSuites.dialog.open({ 752 title:'Alert', 753 message:message, 754 }); 755 } else { 756 alert(message); 757 } 758} 759 760jSuites.animation = {}; 761 762jSuites.animation.slideLeft = function(element, direction, done) { 763 if (direction == true) { 764 element.classList.add('slide-left-in'); 765 setTimeout(function() { 766 element.classList.remove('slide-left-in'); 767 if (typeof(done) == 'function') { 768 done(); 769 } 770 }, 400); 771 } else { 772 element.classList.add('slide-left-out'); 773 setTimeout(function() { 774 element.classList.remove('slide-left-out'); 775 if (typeof(done) == 'function') { 776 done(); 777 } 778 }, 400); 779 } 780} 781 782jSuites.animation.slideRight = function(element, direction, done) { 783 if (direction == true) { 784 element.classList.add('slide-right-in'); 785 setTimeout(function() { 786 element.classList.remove('slide-right-in'); 787 if (typeof(done) == 'function') { 788 done(); 789 } 790 }, 400); 791 } else { 792 element.classList.add('slide-right-out'); 793 setTimeout(function() { 794 element.classList.remove('slide-right-out'); 795 if (typeof(done) == 'function') { 796 done(); 797 } 798 }, 400); 799 } 800} 801 802jSuites.animation.slideTop = function(element, direction, done) { 803 if (direction == true) { 804 element.classList.add('slide-top-in'); 805 setTimeout(function() { 806 element.classList.remove('slide-top-in'); 807 if (typeof(done) == 'function') { 808 done(); 809 } 810 }, 400); 811 } else { 812 element.classList.add('slide-top-out'); 813 setTimeout(function() { 814 element.classList.remove('slide-top-out'); 815 if (typeof(done) == 'function') { 816 done(); 817 } 818 }, 400); 819 } 820} 821 822jSuites.animation.slideBottom = function(element, direction, done) { 823 if (direction == true) { 824 element.classList.add('slide-bottom-in'); 825 setTimeout(function() { 826 element.classList.remove('slide-bottom-in'); 827 if (typeof(done) == 'function') { 828 done(); 829 } 830 }, 400); 831 } else { 832 element.classList.add('slide-bottom-out'); 833 setTimeout(function() { 834 element.classList.remove('slide-bottom-out'); 835 if (typeof(done) == 'function') { 836 done(); 837 } 838 }, 100); 839 } 840} 841 842jSuites.animation.fadeIn = function(element, done) { 843 element.style.display = ''; 844 element.classList.add('fade-in'); 845 setTimeout(function() { 846 element.classList.remove('fade-in'); 847 if (typeof(done) == 'function') { 848 done(); 849 } 850 }, 2000); 851} 852 853jSuites.animation.fadeOut = function(element, done) { 854 element.classList.add('fade-out'); 855 setTimeout(function() { 856 element.style.display = 'none'; 857 element.classList.remove('fade-out'); 858 if (typeof(done) == 'function') { 859 done(); 860 } 861 }, 1000); 862} 863 864jSuites.calendar = (function(el, options) { 865 // Already created, update options 866 if (el.calendar) { 867 return el.calendar.setOptions(options, true); 868 } 869 870 // New instance 871 var obj = { type:'calendar' }; 872 obj.options = {}; 873 874 // Date 875 obj.date = null; 876 877 /** 878 * Update options 879 */ 880 obj.setOptions = function(options, reset) { 881 // Default configuration 882 var defaults = { 883 // Render type: [ default | year-month-picker ] 884 type: 'default', 885 // Restrictions 886 validRange: null, 887 // Starting weekday - 0 for sunday, 6 for saturday 888 startingDay: null, 889 // Date format 890 format: 'DD/MM/YYYY', 891 // Allow keyboard date entry 892 readonly: true, 893 // Today is default 894 today: false, 895 // Show timepicker 896 time: false, 897 // Show the reset button 898 resetButton: true, 899 // Placeholder 900 placeholder: '', 901 // Translations can be done here 902 months: jSuites.calendar.monthsShort, 903 monthsFull: jSuites.calendar.months, 904 weekdays: jSuites.calendar.weekdays, 905 textDone: jSuites.translate('Done'), 906 textReset: jSuites.translate('Reset'), 907 textUpdate: jSuites.translate('Update'), 908 // Value 909 value: null, 910 // Fullscreen (this is automatic set for screensize < 800) 911 fullscreen: false, 912 // Create the calendar closed as default 913 opened: false, 914 // Events 915 onopen: null, 916 onclose: null, 917 onchange: null, 918 onupdate: null, 919 // Internal mode controller 920 mode: null, 921 position: null, 922 // Data type 923 dataType: null, 924 // Controls 925 controls: true, 926 } 927 928 // Loop through our object 929 for (var property in defaults) { 930 if (options && options.hasOwnProperty(property)) { 931 obj.options[property] = options[property]; 932 } else { 933 if (typeof(obj.options[property]) == 'undefined' || reset === true) { 934 obj.options[property] = defaults[property]; 935 } 936 } 937 } 938 939 // Reset button 940 if (obj.options.resetButton == false) { 941 calendarReset.style.display = 'none'; 942 } else { 943 calendarReset.style.display = ''; 944 } 945 946 // Readonly 947 if (obj.options.readonly) { 948 el.setAttribute('readonly', 'readonly'); 949 } else { 950 el.removeAttribute('readonly'); 951 } 952 953 // Placeholder 954 if (obj.options.placeholder) { 955 el.setAttribute('placeholder', obj.options.placeholder); 956 } else { 957 el.removeAttribute('placeholder'); 958 } 959 960 if (jSuites.isNumeric(obj.options.value) && obj.options.value > 0) { 961 obj.options.value = jSuites.calendar.numToDate(obj.options.value); 962 // Data type numeric 963 obj.options.dataType = 'numeric'; 964 } 965 966 // Texts 967 calendarReset.innerHTML = obj.options.textReset; 968 calendarConfirm.innerHTML = obj.options.textDone; 969 calendarControlsUpdateButton.innerHTML = obj.options.textUpdate; 970 971 // Define mask 972 el.setAttribute('data-mask', obj.options.format.toLowerCase()); 973 974 // Value 975 if (! obj.options.value && obj.options.today) { 976 var value = jSuites.calendar.now(); 977 } else { 978 var value = obj.options.value; 979 } 980 981 // Set internal date 982 if (value) { 983 // Force the update 984 obj.options.value = null; 985 // New value 986 obj.setValue(value); 987 } 988 989 return obj; 990 } 991 992 /** 993 * Open the calendar 994 */ 995 obj.open = function (value) { 996 if (! calendar.classList.contains('jcalendar-focus')) { 997 if (! calendar.classList.contains('jcalendar-inline')) { 998 // Current 999 jSuites.calendar.current = obj; 1000 // Start tracking 1001 jSuites.tracking(obj, true); 1002 // Create the days 1003 obj.getDays(); 1004 // Render months 1005 if (obj.options.type == 'year-month-picker') { 1006 obj.getMonths(); 1007 } 1008 // Get time 1009 if (obj.options.time) { 1010 calendarSelectHour.value = obj.date[3]; 1011 calendarSelectMin.value = obj.date[4]; 1012 } 1013 1014 // Show calendar 1015 calendar.classList.add('jcalendar-focus'); 1016 1017 // Get the position of the corner helper 1018 if (jSuites.getWindowWidth() < 800 || obj.options.fullscreen) { 1019 calendar.classList.add('jcalendar-fullsize'); 1020 // Animation 1021 jSuites.animation.slideBottom(calendarContent, 1); 1022 } else { 1023 calendar.classList.remove('jcalendar-fullsize'); 1024 1025 var rect = el.getBoundingClientRect(); 1026 var rectContent = calendarContent.getBoundingClientRect(); 1027 1028 if (obj.options.position) { 1029 calendarContainer.style.position = 'fixed'; 1030 if (window.innerHeight < rect.bottom + rectContent.height) { 1031 calendarContainer.style.top = (rect.top - (rectContent.height + 2)) + 'px'; 1032 } else { 1033 calendarContainer.style.top = (rect.top + rect.height + 2) + 'px'; 1034 } 1035 calendarContainer.style.left = rect.left + 'px'; 1036 } else { 1037 if (window.innerHeight < rect.bottom + rectContent.height) { 1038 var d = -1 * (rect.height + rectContent.height + 2); 1039 if (d + rect.top < 0) { 1040 d = -1 * (rect.top + rect.height); 1041 } 1042 calendarContainer.style.top = d + 'px'; 1043 } else { 1044 calendarContainer.style.top = 2 + 'px'; 1045 } 1046 1047 if (window.innerWidth < rect.left + rectContent.width) { 1048 var d = window.innerWidth - (rect.left + rectContent.width + 20); 1049 calendarContainer.style.left = d + 'px'; 1050 } else { 1051 calendarContainer.style.left = '0px'; 1052 } 1053 } 1054 } 1055 1056 // Events 1057 if (typeof(obj.options.onopen) == 'function') { 1058 obj.options.onopen(el); 1059 } 1060 } 1061 } 1062 } 1063 1064 obj.close = function (ignoreEvents, update) { 1065 if (calendar.classList.contains('jcalendar-focus')) { 1066 if (update !== false) { 1067 var element = calendar.querySelector('.jcalendar-selected'); 1068 1069 if (typeof(update) == 'string') { 1070 var value = update; 1071 } else if (! element || element.classList.contains('jcalendar-disabled')) { 1072 var value = obj.options.value 1073 } else { 1074 var value = obj.getValue(); 1075 } 1076 1077 obj.setValue(value); 1078 } 1079 1080 // Events 1081 if (! ignoreEvents && typeof(obj.options.onclose) == 'function') { 1082 obj.options.onclose(el); 1083 } 1084 // Hide 1085 calendar.classList.remove('jcalendar-focus'); 1086 // Stop tracking 1087 jSuites.tracking(obj, false); 1088 // Current 1089 jSuites.calendar.current = null; 1090 } 1091 1092 return obj.options.value; 1093 } 1094 1095 obj.prev = function() { 1096 // Check if the visualization is the days picker or years picker 1097 if (obj.options.mode == 'years') { 1098 obj.date[0] = obj.date[0] - 12; 1099 1100 // Update picker table of days 1101 obj.getYears(); 1102 } else if (obj.options.mode == 'months') { 1103 obj.date[0] = parseInt(obj.date[0]) - 1; 1104 // Update picker table of months 1105 obj.getMonths(); 1106 } else { 1107 // Go to the previous month 1108 if (obj.date[1] < 2) { 1109 obj.date[0] = obj.date[0] - 1; 1110 obj.date[1] = 12; 1111 } else { 1112 obj.date[1] = obj.date[1] - 1; 1113 } 1114 1115 // Update picker table of days 1116 obj.getDays(); 1117 } 1118 } 1119 1120 obj.next = function() { 1121 // Check if the visualization is the days picker or years picker 1122 if (obj.options.mode == 'years') { 1123 obj.date[0] = parseInt(obj.date[0]) + 12; 1124 1125 // Update picker table of days 1126 obj.getYears(); 1127 } else if (obj.options.mode == 'months') { 1128 obj.date[0] = parseInt(obj.date[0]) + 1; 1129 // Update picker table of months 1130 obj.getMonths(); 1131 } else { 1132 // Go to the previous month 1133 if (obj.date[1] > 11) { 1134 obj.date[0] = parseInt(obj.date[0]) + 1; 1135 obj.date[1] = 1; 1136 } else { 1137 obj.date[1] = parseInt(obj.date[1]) + 1; 1138 } 1139 1140 // Update picker table of days 1141 obj.getDays(); 1142 } 1143 } 1144 1145 /** 1146 * Set today 1147 */ 1148 obj.setToday = function() { 1149 // Today 1150 var value = new Date().toISOString().substr(0, 10); 1151 // Change value 1152 obj.setValue(value); 1153 // Value 1154 return value; 1155 } 1156 1157 obj.setValue = function(val) { 1158 if (! val) { 1159 val = '' + val; 1160 } 1161 // Values 1162 var newValue = val; 1163 var oldValue = obj.options.value; 1164 1165 if (oldValue != newValue) { 1166 // Set label 1167 if (! newValue) { 1168 obj.date = null; 1169 var val = ''; 1170 el.classList.remove('jcalendar_warning'); 1171 el.title = ''; 1172 } else { 1173 var value = obj.setLabel(newValue, obj.options); 1174 var date = newValue.split(' '); 1175 if (! date[1]) { 1176 date[1] = '00:00:00'; 1177 } 1178 var time = date[1].split(':') 1179 var date = date[0].split('-'); 1180 var y = parseInt(date[0]); 1181 var m = parseInt(date[1]); 1182 var d = parseInt(date[2]); 1183 var h = parseInt(time[0]); 1184 var i = parseInt(time[1]); 1185 obj.date = [ y, m, d, h, i, 0 ]; 1186 var val = obj.setLabel(newValue, obj.options); 1187 1188 // Current selection day 1189 var current = jSuites.calendar.now(new Date(y, m-1, d), true); 1190 1191 // Available ranges 1192 if (obj.options.validRange) { 1193 if (! obj.options.validRange[0] || current >= obj.options.validRange[0]) { 1194 var test1 = true; 1195 } else { 1196 var test1 = false; 1197 } 1198 1199 if (! obj.options.validRange[1] || current <= obj.options.validRange[1]) { 1200 var test2 = true; 1201 } else { 1202 var test2 = false; 1203 } 1204 1205 if (! (test1 && test2)) { 1206 el.classList.add('jcalendar_warning'); 1207 el.title = jSuites.translate('Date outside the valid range'); 1208 } else { 1209 el.classList.remove('jcalendar_warning'); 1210 el.title = ''; 1211 } 1212 } else { 1213 el.classList.remove('jcalendar_warning'); 1214 el.title = ''; 1215 } 1216 } 1217 1218 // New value 1219 obj.options.value = newValue; 1220 1221 if (typeof(obj.options.onchange) == 'function') { 1222 obj.options.onchange(el, newValue, oldValue); 1223 } 1224 1225 // Lemonade JS 1226 if (el.value != val) { 1227 el.value = val; 1228 if (typeof(el.oninput) == 'function') { 1229 el.oninput({ 1230 type: 'input', 1231 target: el, 1232 value: el.value 1233 }); 1234 } 1235 } 1236 } 1237 1238 obj.getDays(); 1239 // Render months 1240 if (obj.options.type == 'year-month-picker') { 1241 obj.getMonths(); 1242 } 1243 } 1244 1245 obj.getValue = function() { 1246 if (obj.date) { 1247 if (obj.options.time) { 1248 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); 1249 } else { 1250 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); 1251 } 1252 } else { 1253 return ""; 1254 } 1255 } 1256 1257 /** 1258 * Calendar 1259 */ 1260 obj.update = function(element, v) { 1261 if (element.classList.contains('jcalendar-disabled')) { 1262 // Do nothing 1263 } else { 1264 var elements = calendar.querySelector('.jcalendar-selected'); 1265 if (elements) { 1266 elements.classList.remove('jcalendar-selected'); 1267 } 1268 element.classList.add('jcalendar-selected'); 1269 1270 if (element.classList.contains('jcalendar-set-month')) { 1271 obj.date[1] = v; 1272 obj.date[2] = 1; // first day of the month 1273 } else { 1274 obj.date[2] = element.innerText; 1275 } 1276 1277 if (! obj.options.time) { 1278 obj.close(); 1279 } else { 1280 obj.date[3] = calendarSelectHour.value; 1281 obj.date[4] = calendarSelectMin.value; 1282 } 1283 } 1284 1285 // Update 1286 updateActions(); 1287 } 1288 1289 /** 1290 * Set to blank 1291 */ 1292 obj.reset = function() { 1293 // Close calendar 1294 obj.setValue(''); 1295 obj.date = null; 1296 obj.close(false, false); 1297 } 1298 1299 /** 1300 * Get calendar days 1301 */ 1302 obj.getDays = function() { 1303 // Mode 1304 obj.options.mode = 'days'; 1305 1306 // Setting current values in case of NULLs 1307 var date = new Date(); 1308 1309 // Current selection 1310 var year = obj.date && jSuites.isNumeric(obj.date[0]) ? obj.date[0] : parseInt(date.getFullYear()); 1311 var month = obj.date && jSuites.isNumeric(obj.date[1]) ? obj.date[1] : parseInt(date.getMonth()) + 1; 1312 var day = obj.date && jSuites.isNumeric(obj.date[2]) ? obj.date[2] : parseInt(date.getDate()); 1313 var hour = obj.date && jSuites.isNumeric(obj.date[3]) ? obj.date[3] : parseInt(date.getHours()); 1314 var min = obj.date && jSuites.isNumeric(obj.date[4]) ? obj.date[4] : parseInt(date.getMinutes()); 1315 1316 // Selection container 1317 obj.date = [ year, month, day, hour, min, 0 ]; 1318 1319 // Update title 1320 calendarLabelYear.innerHTML = year; 1321 calendarLabelMonth.innerHTML = obj.options.months[month - 1]; 1322 1323 // Current month and Year 1324 var isCurrentMonthAndYear = (date.getMonth() == month - 1) && (date.getFullYear() == year) ? true : false; 1325 var currentDay = date.getDate(); 1326 1327 // Number of days in the month 1328 var date = new Date(year, month, 0, 0, 0); 1329 var numberOfDays = date.getDate(); 1330 1331 // First day 1332 var date = new Date(year, month-1, 0, 0, 0); 1333 var firstDay = date.getDay() + 1; 1334 1335 // Index value 1336 var index = obj.options.startingDay || 0; 1337 1338 // First of day relative to the starting calendar weekday 1339 firstDay = firstDay - index; 1340 1341 // Reset table 1342 calendarBody.innerHTML = ''; 1343 1344 // Weekdays Row 1345 var row = document.createElement('tr'); 1346 row.setAttribute('align', 'center'); 1347 calendarBody.appendChild(row); 1348 1349 // Create weekdays row 1350 for (var i = 0; i < 7; i++) { 1351 var cell = document.createElement('td'); 1352 cell.classList.add('jcalendar-weekday') 1353 cell.innerHTML = obj.options.weekdays[index].substr(0,1); 1354 row.appendChild(cell); 1355 // Next week day 1356 index++; 1357 // Restart index 1358 if (index > 6) { 1359 index = 0; 1360 } 1361 } 1362 1363 // Index of days 1364 var index = 0; 1365 var d = 0; 1366 1367 // Calendar table 1368 for (var j = 0; j < 6; j++) { 1369 // Reset cells container 1370 var row = document.createElement('tr'); 1371 row.setAttribute('align', 'center'); 1372 row.style.height = '34px'; 1373 1374 // Create cells 1375 for (var i = 0; i < 7; i++) { 1376 // Create cell 1377 var cell = document.createElement('td'); 1378 cell.classList.add('jcalendar-set-day'); 1379 1380 if (index >= firstDay && index < (firstDay + numberOfDays)) { 1381 // Day cell 1382 d++; 1383 cell.innerHTML = d; 1384 1385 // Selected 1386 if (d == day) { 1387 cell.classList.add('jcalendar-selected'); 1388 } 1389 1390 // Current selection day is today 1391 if (isCurrentMonthAndYear && currentDay == d) { 1392 cell.style.fontWeight = 'bold'; 1393 } 1394 1395 // Current selection day 1396 var current = jSuites.calendar.now(new Date(year, month-1, d), true); 1397 1398 // Available ranges 1399 if (obj.options.validRange) { 1400 if (! obj.options.validRange[0] || current >= obj.options.validRange[0]) { 1401 var test1 = true; 1402 } else { 1403 var test1 = false; 1404 } 1405 1406 if (! obj.options.validRange[1] || current <= obj.options.validRange[1]) { 1407 var test2 = true; 1408 } else { 1409 var test2 = false; 1410 } 1411 1412 if (! (test1 && test2)) { 1413 cell.classList.add('jcalendar-disabled'); 1414 } 1415 } 1416 } 1417 // Day cell 1418 row.appendChild(cell); 1419 // Index 1420 index++; 1421 } 1422 1423 // Add cell to the calendar body 1424 calendarBody.appendChild(row); 1425 } 1426 1427 // Show time controls 1428 if (obj.options.time) { 1429 calendarControlsTime.style.display = ''; 1430 } else { 1431 calendarControlsTime.style.display = 'none'; 1432 } 1433 1434 // Update 1435 updateActions(); 1436 } 1437 1438 obj.getMonths = function() { 1439 // Mode 1440 obj.options.mode = 'months'; 1441 1442 // Loading month labels 1443 var months = obj.options.months; 1444 1445 // Value 1446 var value = obj.options.value; 1447 1448 // Current date 1449 var date = new Date(); 1450 var currentYear = parseInt(date.getFullYear()); 1451 var currentMonth = parseInt(date.getMonth()) + 1; 1452 var selectedYear = obj.date && jSuites.isNumeric(obj.date[0]) ? obj.date[0] : currentYear; 1453 var selectedMonth = obj.date && jSuites.isNumeric(obj.date[1]) ? obj.date[1] : currentMonth; 1454 1455 // Update title 1456 calendarLabelYear.innerHTML = obj.date[0]; 1457 calendarLabelMonth.innerHTML = months[selectedMonth-1]; 1458 1459 // Table 1460 var table = document.createElement('table'); 1461 table.setAttribute('width', '100%'); 1462 1463 // Row 1464 var row = null; 1465 1466 // Calendar table 1467 for (var i = 0; i < 12; i++) { 1468 if (! (i % 4)) { 1469 // Reset cells container 1470 var row = document.createElement('tr'); 1471 row.setAttribute('align', 'center'); 1472 table.appendChild(row); 1473 } 1474 1475 // Create cell 1476 var cell = document.createElement('td'); 1477 cell.classList.add('jcalendar-set-month'); 1478 cell.setAttribute('data-value', i+1); 1479 cell.innerText = months[i]; 1480 1481 if (obj.options.validRange) { 1482 var current = selectedYear + '-' + jSuites.two(i+1); 1483 if (! obj.options.validRange[0] || current >= obj.options.validRange[0].substr(0,7)) { 1484 var test1 = true; 1485 } else { 1486 var test1 = false; 1487 } 1488 1489 if (! obj.options.validRange[1] || current <= obj.options.validRange[1].substr(0,7)) { 1490 var test2 = true; 1491 } else { 1492 var test2 = false; 1493 } 1494 1495 if (! (test1 && test2)) { 1496 cell.classList.add('jcalendar-disabled'); 1497 } 1498 } 1499 1500 if (i+1 == selectedMonth) { 1501 cell.classList.add('jcalendar-selected'); 1502 } 1503 1504 if (currentYear == selectedYear && i+1 == currentMonth) { 1505 cell.style.fontWeight = 'bold'; 1506 } 1507 1508 row.appendChild(cell); 1509 } 1510 1511 calendarBody.innerHTML = '<tr><td colspan="7"></td></tr>'; 1512 calendarBody.children[0].children[0].appendChild(table); 1513 1514 // Update 1515 updateActions(); 1516 } 1517 1518 obj.getYears = function() { 1519 // Mode 1520 obj.options.mode = 'years'; 1521 1522 // Current date 1523 var date = new Date(); 1524 var currentYear = date.getFullYear(); 1525 var selectedYear = obj.date && jSuites.isNumeric(obj.date[0]) ? obj.date[0] : parseInt(date.getFullYear()); 1526 1527 // Array of years 1528 var y = []; 1529 for (var i = 0; i < 25; i++) { 1530 y[i] = parseInt(obj.date[0]) + (i - 12); 1531 } 1532 1533 // Assembling the year tables 1534 var table = document.createElement('table'); 1535 table.setAttribute('width', '100%'); 1536 1537 for (var i = 0; i < 25; i++) { 1538 if (! (i % 5)) { 1539 // Reset cells container 1540 var row = document.createElement('tr'); 1541 row.setAttribute('align', 'center'); 1542 table.appendChild(row); 1543 } 1544 1545 // Create cell 1546 var cell = document.createElement('td'); 1547 cell.classList.add('jcalendar-set-year'); 1548 cell.innerText = y[i]; 1549 1550 if (selectedYear == y[i]) { 1551 cell.classList.add('jcalendar-selected'); 1552 } 1553 1554 if (currentYear == y[i]) { 1555 cell.style.fontWeight = 'bold'; 1556 } 1557 1558 row.appendChild(cell); 1559 } 1560 1561 calendarBody.innerHTML = '<tr><td colspan="7"></td></tr>'; 1562 calendarBody.firstChild.firstChild.appendChild(table); 1563 1564 // Update 1565 updateActions(); 1566 } 1567 1568 obj.setLabel = function(value, mixed) { 1569 return jSuites.calendar.getDateString(value, mixed); 1570 } 1571 1572 obj.fromFormatted = function (value, format) { 1573 return jSuites.calendar.extractDateFromString(value, format); 1574 } 1575 1576 var mouseUpControls = function(e) { 1577 var element = jSuites.findElement(e.target, 'jcalendar-container'); 1578 if (element) { 1579 var action = e.target.className; 1580 1581 // Object id 1582 if (action == 'jcalendar-prev') { 1583 obj.prev(); 1584 } else if (action == 'jcalendar-next') { 1585 obj.next(); 1586 } else if (action == 'jcalendar-month') { 1587 obj.getMonths(); 1588 } else if (action == 'jcalendar-year') { 1589 obj.getYears(); 1590 } else if (action == 'jcalendar-set-year') { 1591 obj.date[0] = e.target.innerText; 1592 if (obj.options.type == 'year-month-picker') { 1593 obj.getMonths(); 1594 } else { 1595 obj.getDays(); 1596 } 1597 } else if (e.target.classList.contains('jcalendar-set-month')) { 1598 var month = parseInt(e.target.getAttribute('data-value')); 1599 if (obj.options.type == 'year-month-picker') { 1600 obj.update(e.target, month); 1601 } else { 1602 obj.date[1] = month; 1603 obj.getDays(); 1604 } 1605 } else if (action == 'jcalendar-confirm' || action == 'jcalendar-update' || action == 'jcalendar-close') { 1606 obj.close(); 1607 } else if (action == 'jcalendar-backdrop') { 1608 obj.close(false, false); 1609 } else if (action == 'jcalendar-reset') { 1610 obj.reset(); 1611 } else if (e.target.classList.contains('jcalendar-set-day') && e.target.innerText) { 1612 obj.update(e.target); 1613 } 1614 } else { 1615 obj.close(); 1616 } 1617 } 1618 1619 var keyUpControls = function(e) { 1620 if (e.target.value && e.target.value.length > 3) { 1621 var test = jSuites.calendar.extractDateFromString(e.target.value, obj.options.format); 1622 if (test) { 1623 obj.setValue(test); 1624 } 1625 } 1626 } 1627 1628 // Update actions button 1629 var updateActions = function() { 1630 var currentDay = calendar.querySelector('.jcalendar-selected'); 1631 1632 if (currentDay && currentDay.classList.contains('jcalendar-disabled')) { 1633 calendarControlsUpdateButton.setAttribute('disabled', 'disabled'); 1634 calendarSelectHour.setAttribute('disabled', 'disabled'); 1635 calendarSelectMin.setAttribute('disabled', 'disabled'); 1636 } else { 1637 calendarControlsUpdateButton.removeAttribute('disabled'); 1638 calendarSelectHour.removeAttribute('disabled'); 1639 calendarSelectMin.removeAttribute('disabled'); 1640 } 1641 1642 // Event 1643 if (typeof(obj.options.onupdate) == 'function') { 1644 obj.options.onupdate(el, obj.getValue()); 1645 } 1646 } 1647 1648 var calendar = null; 1649 var calendarReset = null; 1650 var calendarConfirm = null; 1651 var calendarContainer = null; 1652 var calendarContent = null; 1653 var calendarLabelYear = null; 1654 var calendarLabelMonth = null; 1655 var calendarTable = null; 1656 var calendarBody = null; 1657 1658 var calendarControls = null; 1659 var calendarControlsTime = null; 1660 var calendarControlsUpdate = null; 1661 var calendarControlsUpdateButton = null; 1662 var calendarSelectHour = null; 1663 var calendarSelectMin = null; 1664 1665 var init = function() { 1666 // Get value from initial element if that is an input 1667 if (el.tagName == 'INPUT' && el.value) { 1668 options.value = el.value; 1669 } 1670 1671 // Calendar DOM elements 1672 calendarReset = document.createElement('div'); 1673 calendarReset.className = 'jcalendar-reset'; 1674 1675 calendarConfirm = document.createElement('div'); 1676 calendarConfirm.className = 'jcalendar-confirm'; 1677 1678 calendarControls = document.createElement('div'); 1679 calendarControls.className = 'jcalendar-controls' 1680 calendarControls.style.borderBottom = '1px solid #ddd'; 1681 calendarControls.appendChild(calendarReset); 1682 calendarControls.appendChild(calendarConfirm); 1683 1684 calendarContainer = document.createElement('div'); 1685 calendarContainer.className = 'jcalendar-container'; 1686 calendarContent = document.createElement('div'); 1687 calendarContent.className = 'jcalendar-content'; 1688 calendarContainer.appendChild(calendarContent); 1689 1690 // Main element 1691 if (el.tagName == 'DIV') { 1692 calendar = el; 1693 calendar.classList.add('jcalendar-inline'); 1694 } else { 1695 // Add controls to the screen 1696 calendarContent.appendChild(calendarControls); 1697 1698 calendar = document.createElement('div'); 1699 calendar.className = 'jcalendar'; 1700 } 1701 calendar.classList.add('jcalendar-container'); 1702 calendar.appendChild(calendarContainer); 1703 1704 // Table container 1705 var calendarTableContainer = document.createElement('div'); 1706 calendarTableContainer.className = 'jcalendar-table'; 1707 calendarContent.appendChild(calendarTableContainer); 1708 1709 // Previous button 1710 var calendarHeaderPrev = document.createElement('td'); 1711 calendarHeaderPrev.setAttribute('colspan', '2'); 1712 calendarHeaderPrev.className = 'jcalendar-prev'; 1713 1714 // Header with year and month 1715 calendarLabelYear = document.createElement('span'); 1716 calendarLabelYear.className = 'jcalendar-year'; 1717 calendarLabelMonth = document.createElement('span'); 1718 calendarLabelMonth.className = 'jcalendar-month'; 1719 1720 var calendarHeaderTitle = document.createElement('td'); 1721 calendarHeaderTitle.className = 'jcalendar-header'; 1722 calendarHeaderTitle.setAttribute('colspan', '3'); 1723 calendarHeaderTitle.appendChild(calendarLabelMonth); 1724 calendarHeaderTitle.appendChild(calendarLabelYear); 1725 1726 var calendarHeaderNext = document.createElement('td'); 1727 calendarHeaderNext.setAttribute('colspan', '2'); 1728 calendarHeaderNext.className = 'jcalendar-next'; 1729 1730 var calendarHeader = document.createElement('thead'); 1731 var calendarHeaderRow = document.createElement('tr'); 1732 calendarHeaderRow.appendChild(calendarHeaderPrev); 1733 calendarHeaderRow.appendChild(calendarHeaderTitle); 1734 calendarHeaderRow.appendChild(calendarHeaderNext); 1735 calendarHeader.appendChild(calendarHeaderRow); 1736 1737 calendarTable = document.createElement('table'); 1738 calendarBody = document.createElement('tbody'); 1739 calendarTable.setAttribute('cellpadding', '0'); 1740 calendarTable.setAttribute('cellspacing', '0'); 1741 calendarTable.appendChild(calendarHeader); 1742 calendarTable.appendChild(calendarBody); 1743 calendarTableContainer.appendChild(calendarTable); 1744 1745 calendarSelectHour = document.createElement('select'); 1746 calendarSelectHour.className = 'jcalendar-select'; 1747 calendarSelectHour.onchange = function() { 1748 obj.date[3] = this.value; 1749 1750 // Event 1751 if (typeof(obj.options.onupdate) == 'function') { 1752 obj.options.onupdate(el, obj.getValue()); 1753 } 1754 } 1755 1756 for (var i = 0; i < 24; i++) { 1757 var element = document.createElement('option'); 1758 element.value = i; 1759 element.innerHTML = jSuites.two(i); 1760 calendarSelectHour.appendChild(element); 1761 } 1762 1763 calendarSelectMin = document.createElement('select'); 1764 calendarSelectMin.className = 'jcalendar-select'; 1765 calendarSelectMin.onchange = function() { 1766 obj.date[4] = this.value; 1767 1768 // Event 1769 if (typeof(obj.options.onupdate) == 'function') { 1770 obj.options.onupdate(el, obj.getValue()); 1771 } 1772 } 1773 1774 for (var i = 0; i < 60; i++) { 1775 var element = document.createElement('option'); 1776 element.value = i; 1777 element.innerHTML = jSuites.two(i); 1778 calendarSelectMin.appendChild(element); 1779 } 1780 1781 // Footer controls 1782 var calendarControlsFooter = document.createElement('div'); 1783 calendarControlsFooter.className = 'jcalendar-controls'; 1784 1785 calendarControlsTime = document.createElement('div'); 1786 calendarControlsTime.className = 'jcalendar-time'; 1787 calendarControlsTime.style.maxWidth = '140px'; 1788 calendarControlsTime.appendChild(calendarSelectHour); 1789 calendarControlsTime.appendChild(calendarSelectMin); 1790 1791 calendarControlsUpdateButton = document.createElement('button'); 1792 calendarControlsUpdateButton.setAttribute('type', 'button'); 1793 calendarControlsUpdateButton.className = 'jcalendar-update'; 1794 1795 calendarControlsUpdate = document.createElement('div'); 1796 calendarControlsUpdate.style.flexGrow = '10'; 1797 calendarControlsUpdate.appendChild(calendarControlsUpdateButton); 1798 calendarControlsFooter.appendChild(calendarControlsTime); 1799 1800 // Only show the update button for input elements 1801 if (el.tagName == 'INPUT') { 1802 calendarControlsFooter.appendChild(calendarControlsUpdate); 1803 } 1804 1805 calendarContent.appendChild(calendarControlsFooter); 1806 1807 var calendarBackdrop = document.createElement('div'); 1808 calendarBackdrop.className = 'jcalendar-backdrop'; 1809 calendar.appendChild(calendarBackdrop); 1810 1811 // Handle events 1812 el.addEventListener("keyup", keyUpControls); 1813 1814 // Add global events 1815 calendar.addEventListener("swipeleft", function(e) { 1816 jSuites.animation.slideLeft(calendarTable, 0, function() { 1817 obj.next(); 1818 jSuites.animation.slideRight(calendarTable, 1); 1819 }); 1820 e.preventDefault(); 1821 e.stopPropagation(); 1822 }); 1823 1824 calendar.addEventListener("swiperight", function(e) { 1825 jSuites.animation.slideRight(calendarTable, 0, function() { 1826 obj.prev(); 1827 jSuites.animation.slideLeft(calendarTable, 1); 1828 }); 1829 e.preventDefault(); 1830 e.stopPropagation(); 1831 }); 1832 1833 if ('ontouchend' in document.documentElement === true) { 1834 calendar.addEventListener("touchend", mouseUpControls); 1835 el.addEventListener("touchend", obj.open); 1836 } else { 1837 calendar.addEventListener("mouseup", mouseUpControls); 1838 el.addEventListener("mouseup", obj.open); 1839 } 1840 1841 // Global controls 1842 if (! jSuites.calendar.hasEvents) { 1843 // Execute only one time 1844 jSuites.calendar.hasEvents = true; 1845 // Enter and Esc 1846 document.addEventListener("keydown", jSuites.calendar.keydown); 1847 } 1848 1849 // Set configuration 1850 obj.setOptions(options); 1851 1852 // Append element to the DOM 1853 if (el.tagName == 'INPUT') { 1854 el.parentNode.insertBefore(calendar, el.nextSibling); 1855 // Add properties 1856 el.setAttribute('autocomplete', 'off'); 1857 // Element 1858 el.classList.add('jcalendar-input'); 1859 // Value 1860 el.value = obj.setLabel(obj.getValue(), obj.options); 1861 } else { 1862 // Get days 1863 obj.getDays(); 1864 // Hour 1865 if (obj.options.time) { 1866 calendarSelectHour.value = obj.date[3]; 1867 calendarSelectMin.value = obj.date[4]; 1868 } 1869 } 1870 1871 // Default opened 1872 if (obj.options.opened == true) { 1873 obj.open(); 1874 } 1875 1876 // Controls 1877 if (obj.options.controls == false) { 1878 calendarContainer.classList.add('jcalendar-hide-controls'); 1879 } 1880 1881 // Change method 1882 el.change = obj.setValue; 1883 1884 // Global generic value handler 1885 el.val = function(val) { 1886 if (val === undefined) { 1887 return obj.getValue(); 1888 } else { 1889 obj.setValue(val); 1890 } 1891 } 1892 1893 // Keep object available from the node 1894 el.calendar = calendar.calendar = obj; 1895 } 1896 1897 init(); 1898 1899 return obj; 1900}); 1901 1902jSuites.calendar.keydown = function(e) { 1903 var calendar = null; 1904 if (calendar = jSuites.calendar.current) { 1905 if (e.which == 13) { 1906 // ENTER 1907 calendar.close(false, true); 1908 } else if (e.which == 27) { 1909 // ESC 1910 calendar.close(false, false); 1911 } 1912 } 1913} 1914 1915jSuites.calendar.prettify = function(d, texts) { 1916 if (! texts) { 1917 var texts = { 1918 justNow: 'Just now', 1919 xMinutesAgo: '{0}m ago', 1920 xHoursAgo: '{0}h ago', 1921 xDaysAgo: '{0}d ago', 1922 xWeeksAgo: '{0}w ago', 1923 xMonthsAgo: '{0} mon ago', 1924 xYearsAgo: '{0}y ago', 1925 } 1926 } 1927 1928 var d1 = new Date(); 1929 var d2 = new Date(d); 1930 var total = parseInt((d1 - d2) / 1000 / 60); 1931 1932 String.prototype.format = function(o) { 1933 return this.replace('{0}', o); 1934 } 1935 1936 if (total == 0) { 1937 var text = texts.justNow; 1938 }
1938 else if (total < 90) { 1939 var text = texts.xMinutesAgo.format(total); 1940 } else if (total < 1440) { // One day 1941 var text = texts.xHoursAgo.format(Math.round(total/60)); 1942 } else if (total < 20160) { // 14 days 1943 var text = texts.xDaysAgo.format(Math.round(total / 1440)); 1944 } else if (total < 43200) { // 30 days 1945 var text = texts.xWeeksAgo.format(Math.round(total / 10080)); 1946 } else if (total < 1036800) { // 24 months 1947 var text = texts.xMonthsAgo.format(Math.round(total / 43200)); 1948 } else { // 24 months+ 1949 var text = texts.xYearsAgo.format(Math.round(total / 525600)); 1950 } 1951 1952 return text; 1953} 1954 1955jSuites.calendar.prettifyAll = function() { 1956 var elements = document.querySelectorAll('.prettydate'); 1957 for (var i = 0; i < elements.length; i++) { 1958 if (elements[i].getAttribute('data-date')) { 1959 elements[i].innerHTML = jSuites.calendar.prettify(elements[i].getAttribute('data-date')); 1960 } else { 1961 if (elements[i].innerHTML) { 1962 elements[i].setAttribute('title', elements[i].innerHTML); 1963 elements[i].setAttribute('data-date', elements[i].innerHTML); 1964 elements[i].innerHTML = jSuites.calendar.prettify(elements[i].innerHTML); 1965 } 1966 } 1967 } 1968} 1969 1970jSuites.calendar.now = function(date, dateOnly) { 1971 if (Array.isArray(date)) { 1972 var y = date[0]; 1973 var m = date[1]; 1974 var d = date[2]; 1975 var h = date[3]; 1976 var i = date[4]; 1977 var s = date[5]; 1978 } else { 1979 if (! date) { 1980 var date = new Date(); 1981 } 1982 var y = date.getFullYear(); 1983 var m = date.getMonth() + 1; 1984 var d = date.getDate(); 1985 var h = date.getHours(); 1986 var i = date.getMinutes(); 1987 var s = date.getSeconds(); 1988 } 1989 1990 if (dateOnly == true) { 1991 return jSuites.two(y) + '-' + jSuites.two(m) + '-' + jSuites.two(d); 1992 } else { 1993 return jSuites.two(y) + '-' + jSuites.two(m) + '-' + jSuites.two(d) + ' ' + jSuites.two(h) + ':' + jSuites.two(i) + ':' + jSuites.two(s); 1994 } 1995} 1996 1997jSuites.calendar.toArray = function(value) { 1998 var date = value.split(((value.indexOf('T') !== -1) ? 'T' : ' ')); 1999 var time = date[1]; 2000 var date = date[0].split('-'); 2001 var y = parseInt(date[0]); 2002 var m = parseInt(date[1]); 2003 var d = parseInt(date[2]); 2004 2005 if (time) { 2006 var time = time.split(':'); 2007 var h = parseInt(time[0]); 2008 var i = parseInt(time[1]); 2009 } else { 2010 var h = 0; 2011 var i = 0; 2012 } 2013 return [ y, m, d, h, i, 0 ]; 2014} 2015 2016// Helper to extract date from a string 2017jSuites.calendar.extractDateFromString = function(date, format) { 2018 var o = jSuites.mask(date, { mask: format }, true); 2019 2020 // Check if in format Excel (Need difference with format date or type detected is numeric) 2021 if (date > 0 && Number(date) == date && (o.values.join("") !== o.value || o.type == "numeric")) { 2022 var d = new Date(Math.round((date - 25569)*86400*1000)); 2023 return d.getFullYear() + "-" + jSuites.two(d.getMonth()) + "-" + jSuites.two(d.getDate()) + ' 00:00:00'; 2024 } 2025 2026 var complete = false; 2027 2028 if (o.values.length === o.tokens.length && o.values[o.values.length-1].length >= o.tokens[o.tokens.length-1].length) { 2029 complete = true; 2030 } 2031 2032 if (o.date[0] && o.date[1] && (o.date[2] || complete)) { 2033 if (! o.date[2]) { 2034 o.date[2] = 1; 2035 } 2036 2037 return o.date[0] + '-' + jSuites.two(o.date[1]) + '-' + jSuites.two(o.date[2]) + ' ' + jSuites.two(o.date[3]) + ':' + jSuites.two(o.date[4])+ ':' + jSuites.two(o.date[5]); 2038 } 2039 2040 return ''; 2041} 2042 2043var excelInitialTime = Date.UTC(1900, 0, 0); 2044var excelLeapYearBug = Date.UTC(1900, 1, 29); 2045var millisecondsPerDay = 86400000; 2046 2047/** 2048 * Date to number 2049 */ 2050jSuites.calendar.dateToNum = function(jsDate) { 2051 if (typeof(jsDate) === 'string') { 2052 jsDate = new Date(jsDate + ' GMT+0'); 2053 } 2054 var jsDateInMilliseconds = jsDate.getTime(); 2055 2056 if (jsDateInMilliseconds >= excelLeapYearBug) { 2057 jsDateInMilliseconds += millisecondsPerDay; 2058 } 2059 2060 jsDateInMilliseconds -= excelInitialTime; 2061 2062 return jsDateInMilliseconds / millisecondsPerDay; 2063} 2064 2065/** 2066 * Number to date 2067 */ 2068// !IMPORTANT! 2069// Excel incorrectly considers 1900 to be a leap year 2070jSuites.calendar.numToDate = function(excelSerialNumber) { 2071 var jsDateInMilliseconds = excelInitialTime + excelSerialNumber * millisecondsPerDay; 2072 2073 if (jsDateInMilliseconds >= excelLeapYearBug) { 2074 jsDateInMilliseconds -= millisecondsPerDay; 2075 } 2076 2077 const d = new Date(jsDateInMilliseconds); 2078 2079 var date = [ 2080 d.getUTCFullYear(), 2081 d.getUTCMonth()+1, 2082 d.getUTCDate(), 2083 d.getUTCHours(), 2084 d.getUTCMinutes(), 2085 d.getUTCSeconds(), 2086 ]; 2087 2088 return jSuites.calendar.now(date); 2089} 2090 2091// Helper to convert date into string 2092jSuites.calendar.getDateString = function(value, options) { 2093 if (! options) { 2094 var options = {}; 2095 } 2096 2097 // Labels 2098 if (options && typeof(options) == 'object') { 2099 var format = options.format; 2100 } else { 2101 var format = options; 2102 } 2103 2104 if (! format) { 2105 format = 'YYYY-MM-DD'; 2106 } 2107 2108 // Convert to number of hours 2109 if (format.indexOf('[h]') >= 0) { 2110 var result = 0; 2111 if (value && jSuites.isNumeric(value)) { 2112 result = parseFloat(24 * Number(value)); 2113 if (format.indexOf('mm') >= 0) { 2114 var h = (''+result).split('.'); 2115 if (h[1]) { 2116 var d = 60 * parseFloat('0.' + h[1]) 2117 d = parseFloat(d.toFixed(2)); 2118 } else { 2119 var d = 0; 2120 } 2121 result = parseInt(h[0]) + ':' + jSuites.two(d); 2122 } 2123 } 2124 return result; 2125 } 2126 2127 // Date instance 2128 if (value instanceof Date) { 2129 value = jSuites.calendar.now(value); 2130 } else if (value && jSuites.isNumeric(value)) { 2131 value = jSuites.calendar.numToDate(value); 2132 } 2133 2134 // Tokens 2135 var tokens = [ 'DAY', 'WD', 'DDDD', 'DDD', 'DD', 'D', 'Q', 'HH24', 'HH12', 'HH', 'H', 'AM/PM', 'MI', 'SS', 'MS', 'YYYY', 'YYY', 'YY', 'Y', 'MONTH', 'MON', 'MMMMM', 'MMMM', 'MMM', 'MM', 'M', '.' ]; 2136 2137 // Expression to extract all tokens from the string 2138 var e = new RegExp(tokens.join('|'), 'gi'); 2139 // Extract 2140 var t = format.match(e); 2141 2142 // Compatibility with excel 2143 for (var i = 0; i < t.length; i++) { 2144 if (t[i].toUpperCase() == 'MM') {
2145 // Not a month, correct to minutes 2146 if (t[i-1] && t[i-1].toUpperCase().indexOf('H') >= 0) { 2147 t[i] = 'mi'; 2148 } else if (t[i-2] && t[i-2].toUpperCase().indexOf('H') >= 0) { 2149 t[i] = 'mi'; 2150 } else if (t[i+1] && t[i+1].toUpperCase().indexOf('S') >= 0) { 2151 t[i] = 'mi'; 2152 } else if (t[i+2] && t[i+2].toUpperCase().indexOf('S') >= 0) { 2153 t[i] = 'mi'; 2154 } 2155 } 2156 } 2157 2158 // Object 2159 var o = { 2160 tokens: t 2161 } 2162 2163 // Value 2164 if (value) { 2165 var d = ''+value; 2166 var splitStr = (d.indexOf('T') !== -1) ? 'T' : ' '; 2167 d = d.split(splitStr); 2168 2169 var h = 0; 2170 var m = 0; 2171 var s = 0; 2172 2173 if (d[1]) { 2174 h = d[1].split(':'); 2175 m = h[1] ? h[1] : 0; 2176 s = h[2] ? h[2] : 0; 2177 h = h[0] ? h[0] : 0; 2178 } 2179 2180 d = d[0].split('-'); 2181 2182 if (d[0] && d[1] && d[2] && d[0] > 0 && d[1] > 0 && d[1] < 13 && d[2] > 0 && d[2] < 32) { 2183 2184 // Data 2185 o.data = [ d[0], d[1], d[2], h, m, s ]; 2186 2187 // Value 2188 o.value = []; 2189 2190 // Calendar instance 2191 var calendar = new Date(o.data[0], o.data[1]-1, o.data[2], o.data[3], o.data[4], o.data[5]); 2192 2193 // Get method 2194 var get = function(i) { 2195 // Token 2196 var t = this.tokens[i]; 2197 // Case token 2198 var s = t.toUpperCase(); 2199 var v = null; 2200 2201 if (s === 'YYYY') { 2202 v = this.data[0]; 2203 } else if (s === 'YYY') { 2204 v = this.data[0].substring(1,4); 2205 } else if (s === 'YY') { 2206 v = this.data[0].substring(2,4); 2207 } else if (s === 'Y') { 2208 v = this.data[0].substring(3,4); 2209 } else if (t === 'MON') { 2210 v = jSuites.calendar.months[calendar.getMonth()].substr(0,3).toUpperCase(); 2211 } else if (t === 'mon') { 2212 v = jSuites.calendar.months[calendar.getMonth()].substr(0,3).toLowerCase(); 2213 } else if (t === 'MONTH') { 2214 v = jSuites.calendar.months[calendar.getMonth()].toUpperCase(); 2215 } else if (t === 'month') { 2216 v = jSuites.calendar.months[calendar.getMonth()].toLowerCase(); 2217 } else if (s === 'MMMMM') { 2218 v = jSuites.calendar.months[calendar.getMonth()].substr(0, 1); 2219 } else if (s === 'MMMM' || t === 'Month') { 2220 v = jSuites.calendar.months[calendar.getMonth()]; 2221 } else if (s === 'MMM' || t == 'Mon') { 2222 v = jSuites.calendar.months[calendar.getMonth()].substr(0,3); 2223 } else if (s === 'MM') { 2224 v = jSuites.two(this.data[1]); 2225 } else if (s === 'M') { 2226 v = calendar.getMonth()+1; 2227 } else if (t === 'DAY') { 2228 v = jSuites.calendar.weekdays[calendar.getDay()].toUpperCase(); 2229 } else if (t === 'day') { 2230 v = jSuites.calendar.weekdays[calendar.getDay()].toLowerCase(); 2231 } else if (s === 'DDDD' || t == 'Day') { 2232 v = jSuites.calendar.weekdays[calendar.getDay()]; 2233 } else if (s === 'DDD') { 2234 v = jSuites.calendar.weekdays[calendar.getDay()].substr(0,3); 2235 } else if (s === 'DD') { 2236 v = jSuites.two(this.data[2]); 2237 } else if (s === 'D') { 2238 v = this.data[2]; 2239 } else if (s === 'Q') { 2240 v = Math.floor((calendar.getMonth() + 3) / 3); 2241 } else if (s === 'HH24' || s === 'HH') { 2242 v = jSuites.two(this.data[3]); 2243 } else if (s === 'HH12') { 2244 if (this.data[3] > 12) { 2245 v = jSuites.two(this.data[3] - 12); 2246 } else { 2247 v = jSuites.two(this.data[3]); 2248 } 2249 } else if (s === 'H') { 2250 v = this.data[3]; 2251 } else if (s === 'MI') { 2252 v = jSuites.two(this.data[4]); 2253 } else if (s === 'SS') { 2254 v = jSuites.two(this.data[5]); 2255 } else if (s === 'MS') { 2256 v = calendar.getMilliseconds(); 2257 } else if (s === 'AM/PM') { 2258 if (this.data[3] >= 12) { 2259 v = 'PM'; 2260 } else { 2261 v = 'AM'; 2262 } 2263 } else if (s === 'WD') { 2264 v = jSuites.calendar.weekdays[calendar.getDay()]; 2265 } 2266 2267 if (v === null) { 2268 this.value[i] = this.tokens[i]; 2269 } else { 2270 this.value[i] = v; 2271 } 2272 } 2273 2274 for (var i = 0; i < o.tokens.length; i++) { 2275 get.call(o, i); 2276 } 2277 // Put pieces together 2278 value = o.value.join(''); 2279 } else { 2280 value = ''; 2281 } 2282 } 2283 2284 return value; 2285} 2286 2287// Jsuites calendar labels 2288jSuites.calendar.weekdays = [ 'Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday' ]; 2289jSuites.calendar.months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; 2290jSuites.calendar.weekdaysShort = [ 'Sun','Mon','Tue','Wed','Thu','Fri','Sat' ]; 2291jSuites.calendar.monthsShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; 2292 2293 2294jSuites.color = (function(el, options) { 2295 // Already created, update options 2296 if (el.color) { 2297 return el.color.setOptions(options, true); 2298 } 2299 2300 // New instance 2301 var obj = { type: 'color' }; 2302 obj.options = {}; 2303 2304 var container = null; 2305 var backdrop = null; 2306 var content = null; 2307 var resetButton = null; 2308 var closeButton = null; 2309 var tabs = null; 2310 var jsuitesTabs = null; 2311 2312 /** 2313 * Update options 2314 */ 2315 obj.setOptions = function(options, reset) { 2316 /** 2317 * @typedef {Object} defaults 2318 * @property {(string|Array)} value - Initial value of the compontent 2319 * @property {string} placeholder - The default instruction text on the element 2320 * @property {requestCallback} onchange - Method to be execute after any changes on the element 2321 * @property {requestCallback} onclose - Method to be execute when the element is closed 2322 * @property {string} doneLabel - Label for button done 2323 * @property {string} resetLabel - Label for button reset 2324 * @property {string} resetValue - Value for button reset 2325 * @property {Bool} showResetButton - Active or note for button reset - default false 2326 */ 2327 var defaults = { 2328 placeholder: '', 2329 value: null, 2330 onopen: null, 2331 onclose: null, 2332 onchange: null, 2333 closeOnChange: true, 2334 palette: null, 2335 position: null, 2336 doneLabel: 'Done',
vendor: 98,231 bytes, lines 2337-5518
2337 resetLabel: 'Reset', 2338 fullscreen: false, 2339 opened: false, 2340 } 2341 2342 if (! options) { 2343 options = {}; 2344 } 2345 2346 if (options && ! options.palette) { 2347 // Default pallete 2348 options.palette = jSuites.palette(); 2349 } 2350 2351 // Loop through our object 2352 for (var property in defaults) { 2353 if (options && options.hasOwnProperty(property)) { 2354 obj.options[property] = options[property]; 2355 } else { 2356 if (typeof(obj.options[property]) == 'undefined' || reset === true) { 2357 obj.options[property] = defaults[property]; 2358 } 2359 } 2360 } 2361 2362 // Update the text of the controls, if they have already been created 2363 if (resetButton) { 2364 resetButton.innerHTML = obj.options.resetLabel; 2365 } 2366 if (closeButton) { 2367 closeButton.innerHTML = obj.options.doneLabel; 2368 } 2369 2370 // Update the pallete 2371 if (obj.options.palette && jsuitesTabs) { 2372 jsuitesTabs.updateContent(0, table()); 2373 } 2374 2375 // Value 2376 if (typeof obj.options.value === 'string') { 2377 el.value = obj.options.value; 2378 if (el.tagName === 'INPUT') { 2379 el.style.color = el.value; 2380 el.style.backgroundColor = el.value; 2381 } 2382 } 2383 2384 // Placeholder 2385 if (obj.options.placeholder) { 2386 el.setAttribute('placeholder', obj.options.placeholder); 2387 } else { 2388 if (el.getAttribute('placeholder')) { 2389 el.removeAttribute('placeholder'); 2390 } 2391 } 2392 2393 return obj; 2394 } 2395 2396 obj.select = function(color) { 2397 // Remove current selected mark 2398 var selected = container.querySelector('.jcolor-selected'); 2399 if (selected) { 2400 selected.classList.remove('jcolor-selected'); 2401 } 2402 2403 // Mark cell as selected 2404 if (obj.values[color]) { 2405 obj.values[color].classList.add('jcolor-selected'); 2406 } 2407 2408 obj.options.value = color; 2409 } 2410 2411 /** 2412 * Open color pallete 2413 */ 2414 obj.open = function() { 2415 if (! container.classList.contains('jcolor-focus')) { 2416 // Start tracking 2417 jSuites.tracking(obj, true); 2418 2419 // Show color picker 2420 container.classList.add('jcolor-focus'); 2421 2422 // Select current color 2423 if (obj.options.value) { 2424 obj.select(obj.options.value); 2425 } 2426 2427 // Reset margin 2428 content.style.marginTop = ''; 2429 content.style.marginLeft = ''; 2430 2431 var rectContent = content.getBoundingClientRect(); 2432 var availableWidth = jSuites.getWindowWidth(); 2433 var availableHeight = jSuites.getWindowHeight(); 2434 2435 if (availableWidth < 800 || obj.options.fullscreen == true) { 2436 content.classList.add('jcolor-fullscreen'); 2437 jSuites.animation.slideBottom(content, 1); 2438 backdrop.style.display = 'block'; 2439 } else { 2440 if (content.classList.contains('jcolor-fullscreen')) { 2441 content.classList.remove('jcolor-fullscreen'); 2442 backdrop.style.display = ''; 2443 } 2444 2445 if (obj.options.position) { 2446 content.style.position = 'fixed'; 2447 } else { 2448 content.style.position = ''; 2449 } 2450 2451 if (rectContent.left + rectContent.width > availableWidth) { 2452 content.style.marginLeft = -1 * (rectContent.left + rectContent.width - (availableWidth - 20)) + 'px'; 2453 } 2454 if (rectContent.top + rectContent.height > availableHeight) { 2455 content.style.marginTop = -1 * (rectContent.top + rectContent.height - (availableHeight - 20)) + 'px'; 2456 } 2457 } 2458 2459 2460 if (typeof(obj.options.onopen) == 'function') { 2461 obj.options.onopen(el); 2462 } 2463 2464 jsuitesTabs.setBorder(jsuitesTabs.getActive()); 2465 2466 // Update sliders 2467 if (obj.options.value) { 2468 var rgb = HexToRgb(obj.options.value); 2469 2470 rgbInputs.forEach(function(rgbInput, index) { 2471 rgbInput.value = rgb[index]; 2472 rgbInput.dispatchEvent(new Event('input')); 2473 }); 2474 } 2475 } 2476 } 2477 2478 /** 2479 * Close color pallete 2480 */ 2481 obj.close = function(ignoreEvents) { 2482 if (container.classList.contains('jcolor-focus')) { 2483 // Remove focus 2484 container.classList.remove('jcolor-focus'); 2485 // Make sure backdrop is hidden 2486 backdrop.style.display = ''; 2487 // Call related events 2488 if (! ignoreEvents && typeof(obj.options.onclose) == 'function') { 2489 obj.options.onclose(el); 2490 } 2491 // Stop the object 2492 jSuites.tracking(obj, false); 2493 } 2494 2495 return obj.options.value; 2496 } 2497 2498 /** 2499 * Set value 2500 */ 2501 obj.setValue = function(color) { 2502 if (! color) { 2503 color = ''; 2504 } 2505 2506 if (color != obj.options.value) { 2507 obj.options.value = color; 2508 slidersResult = color; 2509 2510 // Remove current selecded mark 2511 obj.select(color); 2512 2513 // Onchange 2514 if (typeof(obj.options.onchange) == 'function') { 2515 obj.options.onchange(el, color); 2516 } 2517 2518 // Changes 2519 if (el.value != obj.options.value) { 2520 // Set input value 2521 el.value = obj.options.value; 2522 if (el.tagName === 'INPUT') { 2523 el.style.color = el.value; 2524 el.style.backgroundColor = el.value; 2525 } 2526 2527 // Element onchange native 2528 if (typeof(el.oninput) == 'function') { 2529 el.oninput({ 2530 type: 'input', 2531 target: el, 2532 value: el.value 2533 }); 2534 } 2535 } 2536 2537 if (obj.options.closeOnChange == true) { 2538 obj.close(); 2539 } 2540 } 2541 } 2542 2543 /** 2544 * Get value 2545 */ 2546 obj.getValue = function() { 2547 return obj.options.value; 2548 } 2549 2550 var backdropClickControl = false; 2551 2552 // Converts a number in decimal to hexadecimal 2553 var decToHex = function(num) { 2554 var hex = num.toString(16); 2555 return hex.length === 1 ? "0" + hex : hex; 2556 } 2557 2558 // Converts a color in rgb to hexadecimal 2559 var rgbToHex = function(r, g, b) { 2560 return "#" + decToHex(r) + decToHex(g) + decToHex(b); 2561 } 2562 2563 // Converts a number in hexadecimal to decimal 2564 var hexToDec = function(hex) { 2565 return parseInt('0x' + hex); 2566 } 2567 2568 // Converts a color in hexadecimal to rgb 2569 var HexToRgb = function(hex) { 2570 return [hexToDec(hex.substr(1, 2)), hexToDec(hex.substr(3, 2)), hexToDec(hex.substr(5, 2))] 2571 } 2572 2573 var table = function() { 2574 // Content of the first tab 2575 var tableContainer = document.createElement('div'); 2576 tableContainer.className = 'jcolor-grid'; 2577 2578 // Cells 2579 obj.values = []; 2580 2581 // Table pallete 2582 var t = document.createElement('table'); 2583 t.setAttribute('cellpadding', '7'); 2584 t.setAttribute('cellspacing', '0'); 2585 2586 for (var j = 0; j < obj.options.palette.length; j++) { 2587 var tr = document.createElement('tr'); 2588 for (var i = 0; i < obj.options.palette[j].length; i++) { 2589 var td = document.createElement('td'); 2590 var color = obj.options.palette[j][i]; 2591 if (color.length < 7 && color.substr(0,1) !== '#') { 2592 color = '#' + color; 2593 } 2594 td.style.backgroundColor = color; 2595 td.setAttribute('data-value', color); 2596 td.innerHTML = ''; 2597 tr.appendChild(td); 2598 2599 // Selected color 2600 if (obj.options.value == color) { 2601 td.classList.add('jcolor-selected'); 2602 } 2603 2604 // Possible values 2605 obj.values[color] = td; 2606 } 2607 t.appendChild(tr); 2608 } 2609 2610 // Append to the table 2611 tableContainer.appendChild(t); 2612 2613 return tableContainer; 2614 } 2615 2616 // Canvas where the image will be rendered 2617 var canvas = document.createElement('canvas'); 2618 canvas.width = 200; 2619 canvas.height = 160; 2620 var context = canvas.getContext("2d"); 2621 2622 var resizeCanvas = function() { 2623 // Specifications necessary to correctly obtain colors later in certain positions 2624 var m = tabs.firstChild.getBoundingClientRect(); 2625 canvas.width = m.width - 14; 2626 gradient() 2627 } 2628 2629 var gradient = function() { 2630 var g = context.createLinearGradient(0, 0, canvas.width, 0); 2631 // Create color gradient 2632 g.addColorStop(0, "rgb(255,0,0)"); 2633 g.addColorStop(0.15, "rgb(255,0,255)"); 2634 g.addColorStop(0.33, "rgb(0,0,255)"); 2635 g.addColorStop(0.49, "rgb(0,255,255)"); 2636 g.addColorStop(0.67, "rgb(0,255,0)"); 2637 g.addColorStop(0.84, "rgb(255,255,0)"); 2638 g.addColorStop(1, "rgb(255,0,0)"); 2639 context.fillStyle = g; 2640 context.fillRect(0, 0, canvas.width, canvas.height); 2641 g = context.createLinearGradient(0, 0, 0, canvas.height); 2642 g.addColorStop(0, "rgba(255,255,255,1)"); 2643 g.addColorStop(0.5, "rgba(255,255,255,0)"); 2644 g.addColorStop(0.5, "rgba(0,0,0,0)"); 2645 g.addColorStop(1, "rgba(0,0,0,1)"); 2646 context.fillStyle = g; 2647 context.fillRect(0, 0, canvas.width, canvas.height); 2648 } 2649 2650 var hsl = function() { 2651 var element = document.createElement('div'); 2652 element.className = "jcolor-hsl"; 2653 2654 var point = document.createElement('div'); 2655 point.className = 'jcolor-point'; 2656 2657 var div = document.createElement('div'); 2658 div.appendChild(canvas); 2659 div.appendChild(point); 2660 element.appendChild(div); 2661 2662 // Moves the marquee point to the specified position 2663 var update = function(buttons, x, y) { 2664 if (buttons === 1) { 2665 var rect = element.getBoundingClientRect(); 2666 var left = x - rect.left; 2667 var top = y - rect.top; 2668 if (left < 0) { 2669 left = 0; 2670 } 2671 if (top < 0) { 2672 top = 0; 2673 } 2674 if (left > rect.width) { 2675 left = rect.width; 2676 } 2677 if (top > rect.height) { 2678 top = rect.height; 2679 } 2680 point.style.left = left + 'px'; 2681 point.style.top = top + 'px'; 2682 var pixel = context.getImageData(left, top, 1, 1).data; 2683 slidersResult = rgbToHex(pixel[0], pixel[1], pixel[2]); 2684 } 2685 } 2686 2687 // Applies the point's motion function to the div that contains it 2688 element.addEventListener('mousedown', function(e) { 2689 update(e.buttons, e.clientX, e.clientY); 2690 }); 2691 2692 element.addEventListener('mousemove', function(e) { 2693 update(e.buttons, e.clientX, e.clientY); 2694 }); 2695 2696 element.addEventListener('touchmove', function(e) { 2697 update(1, e.changedTouches[0].clientX, e.changedTouches[0].clientY); 2698 }); 2699 2700 return element; 2701 } 2702 2703 var slidersResult = ''; 2704 2705 var rgbInputs = []; 2706 2707 var changeInputColors = function() { 2708 if (slidersResult !== '') { 2709 for (var j = 0; j < rgbInputs.length; j++) { 2710 var currentColor = HexToRgb(slidersResult); 2711 2712 currentColor[j] = 0; 2713 2714 var newGradient = 'linear-gradient(90deg, rgb('; 2715 newGradient += currentColor.join(', '); 2716 newGradient += '), rgb('; 2717 2718 currentColor[j] = 255; 2719 2720 newGradient += currentColor.join(', '); 2721 newGradient += '))'; 2722 2723 rgbInputs[j].style.backgroundImage = newGradient; 2724 } 2725 } 2726 } 2727 2728 var sliders = function() { 2729 // Content of the third tab 2730 var slidersElement = document.createElement('div'); 2731 slidersElement.className = 'jcolor-sliders'; 2732 2733 var slidersBody = document.createElement('div'); 2734 2735 // Creates a range-type input with the specified name 2736 var createSliderInput = function(name) { 2737 var inputContainer = document.createElement('div'); 2738 inputContainer.className = 'jcolor-sliders-input-container'; 2739 2740 var label = document.createElement('label'); 2741 label.innerText = name; 2742 2743 var subContainer = document.createElement('div'); 2744 subContainer.className = 'jcolor-sliders-input-subcontainer'; 2745 2746 var input = document.createElement('input'); 2747 input.type = 'range'; 2748 input.min = 0; 2749 input.max = 255; 2750 input.value = 0; 2751 2752 inputContainer.appendChild(label); 2753 subContainer.appendChild(input); 2754 2755 var value = document.createElement('div'); 2756 value.innerText = input.value; 2757 2758 input.addEventListener('input', function() { 2759 value.innerText = input.value; 2760 }); 2761 2762 subContainer.appendChild(value); 2763 inputContainer.appendChild(subContainer); 2764 2765 slidersBody.appendChild(inputContainer); 2766 2767 return input; 2768 } 2769 2770 // Creates red, green and blue inputs 2771 rgbInputs = [ 2772 createSliderInput('Red'), 2773 createSliderInput('Green'), 2774 createSliderInput('Blue'), 2775 ]; 2776 2777 slidersElement.appendChild(slidersBody); 2778 2779 // Element that prints the current color 2780 var slidersResultColor = document.createElement('div'); 2781 slidersResultColor.className = 'jcolor-sliders-final-color'; 2782 2783 var resultElement = document.createElement('div'); 2784 resultElement.style.visibility = 'hidden'; 2785 resultElement.innerText = 'a'; 2786 slidersResultColor.appendChild(resultElement) 2787 2788 // Update the element that prints the current color 2789 var updateResult = function() { 2790 var resultColor = rgbToHex(parseInt(rgbInputs[0].value), parseInt(rgbInputs[1].value), parseInt(rgbInputs[2].value)); 2791 2792 resultElement.innerText = resultColor; 2793 resultElement.style.color = resultColor; 2794 resultElement.style.removeProperty('visibility'); 2795 2796 slidersResult = resultColor; 2797 } 2798 2799 // Apply the update function to color inputs 2800 rgbInputs.forEach(function(rgbInput) { 2801 rgbInput.addEventListener('input', function() { 2802 updateResult(); 2803 changeInputColors(); 2804 }); 2805 }); 2806 2807 slidersElement.appendChild(slidersResultColor); 2808 2809 return slidersElement; 2810 } 2811 2812 var init = function() { 2813 // Initial options 2814 obj.setOptions(options); 2815 2816 // Add a proper input tag when the element is an input 2817 if (el.tagName == 'INPUT') { 2818 el.classList.add('jcolor-input'); 2819 el.readOnly = true; 2820 } 2821 2822 // Table container 2823 container = document.createElement('div'); 2824 container.className = 'jcolor'; 2825 2826 // Table container 2827 backdrop = document.createElement('div'); 2828 backdrop.className = 'jcolor-backdrop'; 2829 container.appendChild(backdrop); 2830 2831 // Content 2832 content = document.createElement('div'); 2833 content.className = 'jcolor-content'; 2834 2835 // Controls 2836 var controls = document.createElement('div'); 2837 controls.className = 'jcolor-controls'; 2838 content.appendChild(controls); 2839 2840 // Reset button 2841 resetButton = document.createElement('div'); 2842 resetButton.className = 'jcolor-reset'; 2843 resetButton.innerHTML = obj.options.resetLabel; 2844 controls.appendChild(resetButton); 2845 2846 // Close button 2847 closeButton = document.createElement('div'); 2848 closeButton.className = 'jcolor-close'; 2849 closeButton.innerHTML = obj.options.doneLabel; 2850 controls.appendChild(closeButton); 2851 2852 // Element that will be used to create the tabs 2853 tabs = document.createElement('div'); 2854 content.appendChild(tabs); 2855 2856 // Starts the jSuites tabs component 2857 jsuitesTabs = jSuites.tabs(tabs, { 2858 animation: true, 2859 data: [ 2860 { 2861 title: 'Grid', 2862 contentElement: table(), 2863 }, 2864 { 2865 title: 'Spectrum', 2866 contentElement: hsl(), 2867 }, 2868 { 2869 title: 'Sliders', 2870 contentElement: sliders(), 2871 } 2872 ], 2873 onchange: function(element, instance, index) { 2874 if (index === 1) { 2875 resizeCanvas(); 2876 } else { 2877 var color = slidersResult !== '' ? slidersResult : obj.getValue(); 2878 2879 if (index === 2 && color) { 2880 var rgb = HexToRgb(color); 2881 2882 rgbInputs.forEach(function(rgbInput, index) { 2883 rgbInput.value = rgb[index]; 2884 rgbInput.dispatchEvent(new Event('input')); 2885 }); 2886 } 2887 } 2888 }, 2889 palette: 'modern', 2890 }); 2891 2892 container.appendChild(content); 2893 2894 // Insert picker after the element 2895 if (el.tagName == 'INPUT') { 2896 el.parentNode.insertBefore(container, el.nextSibling); 2897 } else { 2898 el.appendChild(container); 2899 } 2900 2901 container.addEventListener("click", function(e) { 2902 if (e.target.tagName == 'TD') { 2903 var value = e.target.getAttribute('data-value'); 2904 if (value) { 2905 obj.setValue(value); 2906 } 2907 } else if (e.target.classList.contains('jcolor-reset')) { 2908 obj.setValue(''); 2909 obj.close(); 2910 } else if (e.target.classList.contains('jcolor-close')) { 2911 if (jsuitesTabs.getActive() > 0) { 2912 obj.setValue(slidersResult); 2913 } 2914 obj.close(); 2915 } else if (e.target.classList.contains('jcolor-backdrop')) { 2916 obj.close(); 2917 } else { 2918 obj.open(); 2919 } 2920 }); 2921 2922 /** 2923 * If element is focus open the picker 2924 */ 2925 el.addEventListener("mouseup", function(e) { 2926 obj.open(); 2927 }); 2928 2929 // If the picker is open on the spectrum tab, it changes the canvas size when the window size is changed 2930 window.addEventListener('resize', function() { 2931 if (container.classList.contains('jcolor-focus') && jsuitesTabs.getActive() == 1) { 2932 resizeCanvas(); 2933 } 2934 }); 2935 2936 // Default opened 2937 if (obj.options.opened == true) { 2938 obj.open(); 2939 } 2940 2941 // Change 2942 el.change = obj.setValue; 2943 2944 // Global generic value handler 2945 el.val = function(val) { 2946 if (val === undefined) { 2947 return obj.getValue(); 2948 } else { 2949 obj.setValue(val); 2950 } 2951 } 2952 2953 // Keep object available from the node 2954 el.color = obj; 2955 2956 // Container shortcut 2957 container.color = obj; 2958 } 2959 2960 obj.toHex = function(rgb) { 2961 var hex = function(x) { 2962 return ("0" + parseInt(x).toString(16)).slice(-2); 2963 } 2964 if (rgb) { 2965 if (/^#[0-9A-F]{6}$/i.test(rgb)) { 2966 return rgb; 2967 } else { 2968 rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); 2969 if (rgb && rgb.length) { 2970 return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]); 2971 } else { 2972 return ""; 2973 } 2974 } 2975 } 2976 } 2977 2978 init(); 2979 2980 return obj; 2981}); 2982 2983 2984 2985jSuites.contextmenu = (function(el, options) { 2986 // New instance 2987 var obj = { type:'contextmenu'}; 2988 obj.options = {}; 2989 2990 // Default configuration 2991 var defaults = { 2992 items: null, 2993 onclick: null, 2994 }; 2995 2996 // Loop through our object 2997 for (var property in defaults) { 2998 if (options && options.hasOwnProperty(property)) { 2999 obj.options[property] = options[property]; 3000 } else { 3001 obj.options[property] = defaults[property]; 3002 } 3003 } 3004 3005 // Class definition 3006 el.classList.add('jcontextmenu'); 3007 3008 /** 3009 * Open contextmenu 3010 */ 3011 obj.open = function(e, items) { 3012 if (items) { 3013 // Update content 3014 obj.options.items = items; 3015 // Create items 3016 obj.create(items); 3017 } 3018 3019 // Close current contextmenu 3020 if (jSuites.contextmenu.current) { 3021 jSuites.contextmenu.current.close(); 3022 } 3023 3024 // Add to the opened components monitor 3025 jSuites.tracking(obj, true); 3026 3027 // Show context menu 3028 el.classList.add('jcontextmenu-focus'); 3029 3030 // Current 3031 jSuites.contextmenu.current = obj; 3032 3033 // Coordinates 3034 if ((obj.options.items && obj.options.items.length > 0) || el.children.length) { 3035 if (e.target) { 3036 if (e.changedTouches && e.changedTouches[0]) { 3037 x = e.changedTouches[0].clientX; 3038 y = e.changedTouches[0].clientY; 3039 } else { 3040 var x = e.clientX; 3041 var y = e.clientY; 3042 } 3043 } else { 3044 var x = e.x; 3045 var y = e.y; 3046 } 3047 3048 var rect = el.getBoundingClientRect(); 3049 3050 if (window.innerHeight < y + rect.height) { 3051 var h = y - rect.height; 3052 if (h < 0) { 3053 h = 0; 3054 } 3055 el.style.top = h + 'px'; 3056 } else { 3057 el.style.top = y + 'px'; 3058 } 3059 3060 if (window.innerWidth < x + rect.width) { 3061 if (x - rect.width > 0) { 3062 el.style.left = (x - rect.width) + 'px'; 3063 } else { 3064 el.style.left = '10px'; 3065 } 3066 } else { 3067 el.style.left = x + 'px'; 3068 } 3069 } 3070 } 3071 3072 obj.isOpened = function() { 3073 return el.classList.contains('jcontextmenu-focus') ? true : false; 3074 } 3075 3076 /** 3077 * Close menu 3078 */ 3079 obj.close = function() { 3080 if (el.classList.contains('jcontextmenu-focus')) { 3081 el.classList.remove('jcontextmenu-focus'); 3082 } 3083 jSuites.tracking(obj, false); 3084 } 3085 3086 /** 3087 * Create items based on the declared objectd 3088 * @param {object} items - List of object 3089 */ 3090 obj.create = function(items) { 3091 // Update content 3092 el.innerHTML = ''; 3093 3094 // Add header contextmenu 3095 var itemHeader = createHeader(); 3096 el.appendChild(itemHeader); 3097 3098 // Append items 3099 for (var i = 0; i < items.length; i++) { 3100 var itemContainer = createItemElement(items[i]); 3101 el.appendChild(itemContainer); 3102 } 3103 } 3104 3105 /** 3106 * createHeader for context menu 3107 * @private 3108 * @returns {HTMLElement} 3109 */ 3110 function createHeader() { 3111 var header = document.createElement('div'); 3112 header.classList.add("header"); 3113 header.addEventListener("click", function(e) { 3114 e.preventDefault(); 3115 e.stopPropagation(); 3116 }); 3117 var title = document.createElement('a'); 3118 title.classList.add("title"); 3119 title.innerHTML = jSuites.translate("Menu"); 3120 3121 header.appendChild(title); 3122 3123 var closeButton = document.createElement('a'); 3124 closeButton.classList.add("close"); 3125 closeButton.innerHTML = jSuites.translate("close"); 3126 closeButton.addEventListener("click", function(e) { 3127 obj.close(); 3128 }); 3129 3130 header.appendChild(closeButton); 3131 3132 return header; 3133 } 3134 3135 /** 3136 * Private function for create a new Item element 3137 * @param {type} item 3138 * @returns {jsuitesL#15.jSuites.contextmenu.createItemElement.itemContainer} 3139 */ 3140 function createItemElement(item) { 3141 if (item.type && (item.type == 'line' || item.type == 'divisor')) { 3142 var itemContainer = document.createElement('hr'); 3143 } else { 3144 var itemContainer = document.createElement('div'); 3145 var itemText = document.createElement('a'); 3146 itemText.innerHTML = item.title; 3147 3148 if (item.tooltip) { 3149 itemContainer.setAttribute('title', item.tooltip); 3150 } 3151 3152 if (item.icon) { 3153 itemContainer.setAttribute('data-icon', item.icon); 3154 } 3155 3156 if (item.id) { 3157 itemContainer.id = item.id; 3158 } 3159 3160 if (item.disabled) { 3161 itemContainer.className = 'jcontextmenu-disabled'; 3162 } else if (item.onclick) { 3163 itemContainer.method = item.onclick; 3164 itemContainer.addEventListener("mousedown", function(e) { 3165 e.preventDefault(); 3166 }); 3167 itemContainer.addEventListener("mouseup", function(e) { 3168 // Execute method 3169 this.method(this, e); 3170 }); 3171 } 3172 itemContainer.appendChild(itemText); 3173 3174 if (item.submenu) { 3175 var itemIconSubmenu = document.createElement('span'); 3176 itemIconSubmenu.innerHTML = "►"; 3177 itemContainer.appendChild(itemIconSubmenu); 3178 itemContainer.classList.add('jcontexthassubmenu'); 3179 var el_submenu = document.createElement('div'); 3180 // Class definition 3181 el_submenu.classList.add('jcontextmenu'); 3182 // Focusable 3183 el_submenu.setAttribute('tabindex', '900'); 3184 3185 // Append items 3186 var submenu = item.submenu; 3187 for (var i = 0; i < submenu.length; i++) { 3188 var itemContainerSubMenu = createItemElement(submenu[i]); 3189 el_submenu.appendChild(itemContainerSubMenu); 3190 } 3191 3192 itemContainer.appendChild(el_submenu); 3193 } else if (item.shortcut) { 3194 var itemShortCut = document.createElement('span'); 3195 itemShortCut.innerHTML = item.shortcut; 3196 itemContainer.appendChild(itemShortCut); 3197 } 3198 } 3199 return itemContainer; 3200 } 3201 3202 if (typeof(obj.options.onclick) == 'function') { 3203 el.addEventListener('click', function(e) { 3204 obj.options.onclick(obj, e); 3205 }); 3206 } 3207 3208 // Create items 3209 if (obj.options.items) { 3210 obj.create(obj.options.items); 3211 } 3212 3213 window.addEventListener("mousewheel", function() { 3214 obj.close(); 3215 }); 3216 3217 el.contextmenu = obj; 3218 3219 return obj; 3220}); 3221 3222 3223jSuites.dropdown = (function(el, options) { 3224 // Already created, update options 3225 if (el.dropdown) { 3226 return el.dropdown.setOptions(options, true); 3227 } 3228 3229 // New instance 3230 var obj = { type: 'dropdown' }; 3231 obj.options = {}; 3232 3233 // Success 3234 var success = function(data, val) { 3235 // Set data 3236 if (data && data.length) { 3237 // Sort 3238 if (obj.options.sortResults !== false) { 3239 if(typeof obj.options.sortResults == "function") { 3240 data.sort(obj.options.sortResults); 3241 } else { 3242 data.sort(sortData); 3243 } 3244 } 3245 3246 obj.setData(data); 3247 } 3248 3249 // Onload method 3250 if (typeof(obj.options.onload) == 'function') { 3251 obj.options.onload(el, obj, data, val); 3252 } 3253 3254 // Set value 3255 if (val) { 3256 applyValue(val); 3257 } 3258 3259 // Component value 3260 if (val === undefined || val === null) { 3261 obj.options.value = ''; 3262 } 3263 el.value = obj.options.value; 3264 3265 // Open dropdown 3266 if (obj.options.opened == true) { 3267 obj.open(); 3268 } 3269 } 3270 3271 3272 // Default sort 3273 var sortData = function(itemA, itemB) { 3274 var testA, testB; 3275 if(typeof itemA == "string") { 3276 testA = itemA; 3277 } else { 3278 if(itemA.text) { 3279 testA = itemA.text; 3280 } else if(itemA.name) { 3281 testA = itemA.name; 3282 } 3283 } 3284 3285 if(typeof itemB == "string") { 3286 testB = itemB; 3287 } else { 3288 if(itemB.text) { 3289 testB = itemB.text; 3290 } else if(itemB.name) { 3291 testB = itemB.name; 3292 } 3293 } 3294 3295 if (typeof testA == "string" || typeof testB == "string") { 3296 if (typeof testA != "string") { testA = ""+testA; } 3297 if (typeof testB != "string") { testB = ""+testB; } 3298 return testA.localeCompare(testB); 3299 } else { 3300 return testA - testB; 3301 } 3302 } 3303 3304 /** 3305 * Reset the options for the dropdown 3306 */ 3307 var resetValue = function() { 3308 // Reset value container 3309 obj.value = {}; 3310 // Remove selected 3311 for (var i = 0; i < obj.items.length; i++) { 3312 if (obj.items[i].selected == true) { 3313 if (obj.items[i].element) { 3314 obj.items[i].element.classList.remove('jdropdown-selected') 3315 } 3316 obj.items[i].selected = null; 3317 } 3318 } 3319 // Reset options 3320 obj.options.value = ''; 3321 // Reset value 3322 el.value = ''; 3323 } 3324 3325 /** 3326 * Apply values to the dropdown 3327 */ 3328 var applyValue = function(values) { 3329 // Reset the current values 3330 resetValue(); 3331 3332 // Read values 3333 if (values !== null) { 3334 if (! values) { 3335 if (typeof(obj.value['']) !== 'undefined') { 3336 obj.value[''] = ''; 3337 } 3338 } else { 3339 if (! Array.isArray(values)) { 3340 values = ('' + values).split(';'); 3341 } 3342 for (var i = 0; i < values.length; i++) { 3343 obj.value[values[i]] = ''; 3344 } 3345 } 3346 } 3347 3348 // Update the DOM 3349 for (var i = 0; i < obj.items.length; i++) { 3350 if (typeof(obj.value[Value(i)]) !== 'undefined') { 3351 if (obj.items[i].element) { 3352 obj.items[i].element.classList.add('jdropdown-selected') 3353 } 3354 obj.items[i].selected = true; 3355 3356 // Keep label 3357 obj.value[Value(i)] = Text(i); 3358 } 3359 } 3360 3361 // Global value 3362 obj.options.value = Object.keys(obj.value).join(';'); 3363 3364 // Update labels 3365 obj.header.value = obj.getText(); 3366 } 3367 3368 // Get the value of one item 3369 var Value = function(k, v) { 3370 // Legacy purposes 3371 if (! obj.options.format) { 3372 var property = 'value'; 3373 } else { 3374 var property = 'id'; 3375 } 3376 3377 if (obj.items[k]) { 3378 if (v !== undefined) { 3379 return obj.items[k].data[property] = v; 3380 } else { 3381 return obj.items[k].data[property]; 3382 } 3383 } 3384 3385 return ''; 3386 } 3387 3388 // Get the label of one item 3389 var Text = function(k, v) { 3390 // Legacy purposes 3391 if (! obj.options.format) { 3392 var property = 'text'; 3393 } else { 3394 var property = 'name'; 3395 } 3396 3397 if (obj.items[k]) { 3398 if (v !== undefined) { 3399 return obj.items[k].data[property] = v; 3400 } else { 3401 return obj.items[k].data[property]; 3402 } 3403 } 3404 3405 return ''; 3406 } 3407 3408 var getValue = function() { 3409 return Object.keys(obj.value); 3410 } 3411 3412 var getText = function() { 3413 var data = []; 3414 var k = Object.keys(obj.value); 3415 for (var i = 0; i < k.length; i++) { 3416 data.push(obj.value[k[i]]); 3417 } 3418 return data; 3419 } 3420 3421 obj.setOptions = function(options, reset) { 3422 if (! options) { 3423 options = {}; 3424 } 3425 3426 // Default configuration 3427 var defaults = { 3428 url: null, 3429 data: [], 3430 format: 0, 3431 multiple: false, 3432 autocomplete: false, 3433 remoteSearch: false, 3434 lazyLoading: false, 3435 type: null, 3436 width: null, 3437 maxWidth: null, 3438 opened: false, 3439 value: null, 3440 placeholder: '', 3441 newOptions: false, 3442 position: false, 3443 onchange: null, 3444 onload: null, 3445 onopen: null, 3446 onclose: null, 3447 onfocus: null, 3448 onblur: null, 3449 oninsert: null, 3450 onbeforeinsert: null, 3451 sortResults: false, 3452 autofocus: false, 3453 } 3454 3455 // Loop through our object 3456 for (var property in defaults) { 3457 if (options && options.hasOwnProperty(property)) { 3458 obj.options[property] = options[property]; 3459 } else { 3460 if (typeof(obj.options[property]) == 'undefined' || reset === true) { 3461 obj.options[property] = defaults[property]; 3462 } 3463 } 3464 } 3465 3466 // Force autocomplete search 3467 if (obj.options.remoteSearch == true || obj.options.type === 'searchbar') { 3468 obj.options.autocomplete = true; 3469 } 3470 3471 // New options 3472 if (obj.options.newOptions == true) { 3473 obj.header.classList.add('jdropdown-add'); 3474 } else { 3475 obj.header.classList.remove('jdropdown-add'); 3476 } 3477 3478 // Autocomplete 3479 if (obj.options.autocomplete == true) { 3480 obj.header.removeAttribute('readonly'); 3481 } else { 3482 obj.header.setAttribute('readonly', 'readonly'); 3483 } 3484 3485 // Place holder 3486 if (obj.options.placeholder) { 3487 obj.header.setAttribute('placeholder', obj.options.placeholder); 3488 } else { 3489 obj.header.removeAttribute('placeholder'); 3490 } 3491 3492 // Remove specific dropdown typing to add again 3493 el.classList.remove('jdropdown-searchbar'); 3494 el.classList.remove('jdropdown-picker'); 3495 el.classList.remove('jdropdown-list'); 3496 3497 if (obj.options.type == 'searchbar') { 3498 el.classList.add('jdropdown-searchbar'); 3499 } else if (obj.options.type == 'list') { 3500 el.classList.add('jdropdown-list'); 3501 } else if (obj.options.type == 'picker') { 3502 el.classList.add('jdropdown-picker'); 3503 } else { 3504 if (jSuites.getWindowWidth() < 800) { 3505 if (obj.options.autocomplete) { 3506 el.classList.add('jdropdown-searchbar'); 3507 obj.options.type = 'searchbar'; 3508 } else { 3509 el.classList.add('jdropdown-picker'); 3510 obj.options.type = 'picker'; 3511 } 3512 } else { 3513 if (obj.options.width) { 3514 el.style.width = obj.options.width; 3515 el.style.minWidth = obj.options.width; 3516 } else { 3517 el.style.removeProperty('width'); 3518 el.style.removeProperty('min-width'); 3519 } 3520 3521 el.classList.add('jdropdown-default'); 3522 obj.options.type = 'default'; 3523 } 3524 } 3525 3526 // Close button 3527 if (obj.options.type == 'searchbar') { 3528 containerHeader.appendChild(closeButton); 3529 } else { 3530 container.insertBefore(closeButton, container.firstChild); 3531 } 3532 3533 // Load the content 3534 if (obj.options.url && ! options.data) { 3535 jSuites.ajax({ 3536 url: obj.options.url, 3537 method: 'GET', 3538 dataType: 'json', 3539 success: function(data) { 3540 if (data) { 3541 success(data, obj.options.value); 3542 } 3543 } 3544 }); 3545 } else { 3546 success(obj.options.data, obj.options.value); 3547 } 3548 3549 // Return the instance 3550 return obj; 3551 } 3552 3553 // Helpers 3554 var containerHeader = null; 3555 var container = null; 3556 var content = null; 3557 var closeButton = null; 3558 var resetButton = null; 3559 var backdrop = null; 3560 3561 var keyTimer = null; 3562 3563 /** 3564 * Init dropdown 3565 */ 3566 var init = function() { 3567 // Do not accept null 3568 if (! options) { 3569 options = {}; 3570 } 3571 3572 // If the element is a SELECT tag, create a configuration object 3573 if (el.tagName == 'SELECT') { 3574 var ret = jSuites.dropdown.extractFromDom(el, options); 3575 el = ret.el; 3576 options = ret.options; 3577 } 3578 3579 // Place holder 3580 if (! options.placeholder && el.getAttribute('placeholder')) { 3581 options.placeholder = el.getAttribute('placeholder'); 3582 } 3583 3584 // Value container 3585 obj.value = {}; 3586 // Containers 3587 obj.items = []; 3588 obj.groups = []; 3589 // Search options 3590 obj.search = ''; 3591 obj.results = null; 3592 3593 // Create dropdown 3594 el.classList.add('jdropdown'); 3595 3596 // Header container 3597 containerHeader = document.createElement('div'); 3598 containerHeader.className = 'jdropdown-container-header'; 3599 3600 // Header 3601 obj.header = document.createElement('input'); 3602 obj.header.className = 'jdropdown-header jss_object'; 3603 obj.header.type = 'text'; 3604 obj.header.setAttribute('autocomplete', 'off'); 3605 obj.header.onfocus = function() { 3606 if (typeof(obj.options.onfocus) == 'function') { 3607 obj.options.onfocus(el); 3608 } 3609 } 3610 3611 obj.header.onblur = function() { 3612 if (typeof(obj.options.onblur) == 'function') { 3613 obj.options.onblur(el); 3614 } 3615 } 3616 3617 obj.header.onkeyup = function(e) { 3618 if (obj.options.autocomplete == true && ! keyTimer) { 3619 if (obj.search != obj.header.value.trim()) { 3620 keyTimer = setTimeout(function() { 3621 obj.find(obj.header.value.trim()); 3622 keyTimer = null; 3623 }, 400); 3624 } 3625 3626 if (! el.classList.contains('jdropdown-focus')) { 3627 obj.open(); 3628 } 3629 } else { 3630 if (! obj.options.autocomplete) { 3631 obj.next(e.key); 3632 } 3633 } 3634 } 3635 3636 // Global controls 3637 if (! jSuites.dropdown.hasEvents) { 3638 // Execute only one time 3639 jSuites.dropdown.hasEvents = true; 3640 // Enter and Esc 3641 document.addEventListener("keydown", jSuites.dropdown.keydown); 3642 } 3643 3644 // Container 3645 container = document.createElement('div'); 3646 container.className = 'jdropdown-container'; 3647 3648 // Dropdown content 3649 content = document.createElement('div'); 3650 content.className = 'jdropdown-content'; 3651 3652 // Close button 3653 closeButton = document.createElement('div'); 3654 closeButton.className = 'jdropdown-close'; 3655 closeButton.innerHTML = 'Done'; 3656 3657 // Reset button 3658 resetButton = document.createElement('div'); 3659 resetButton.className = 'jdropdown-reset'; 3660 resetButton.innerHTML = 'x'; 3661 resetButton.onclick = function() { 3662 obj.reset(); 3663 obj.close(); 3664 } 3665 3666 // Create backdrop 3667 backdrop = document.createElement('div'); 3668 backdrop.className = 'jdropdown-backdrop'; 3669 3670 // Append elements 3671 containerHeader.appendChild(obj.header); 3672 3673 container.appendChild(content); 3674 el.appendChild(containerHeader); 3675 el.appendChild(container); 3676 el.appendChild(backdrop); 3677 3678 // Set the otiptions 3679 obj.setOptions(options); 3680 3681 if ('ontouchsend' in document.documentElement === true) { 3682 el.addEventListener('touchsend', jSuites.dropdown.mouseup); 3683 } else { 3684 el.addEventListener('mouseup', jSuites.dropdown.mouseup); 3685 } 3686 3687 // Lazyloading 3688 if (obj.options.lazyLoading == true) { 3689 jSuites.lazyLoading(content, { 3690 loadUp: obj.loadUp, 3691 loadDown: obj.loadDown, 3692 }); 3693 } 3694 3695 content.onwheel = function(e) { 3696 e.stopPropagation(); 3697 } 3698 3699 // Change method 3700 el.change = obj.setValue; 3701 3702 // Global generic value handler 3703 el.val = function(val) { 3704 if (val === undefined) { 3705 return obj.getValue(obj.options.multiple ? true : false); 3706 } else { 3707 obj.setValue(val); 3708 } 3709 } 3710 3711 // Keep object available from the node 3712 el.dropdown = obj; 3713 } 3714 3715 /** 3716 * Get the current remote source of data URL 3717 */ 3718 obj.getUrl = function() { 3719 return obj.options.url; 3720 } 3721 3722 /** 3723 * Set the new data from a remote source 3724 * @param {string} url - url from the remote source 3725 * @param {function} callback - callback when the data is loaded 3726 */ 3727 obj.setUrl = function(url, callback) { 3728 obj.options.url = url; 3729 3730 jSuites.ajax({ 3731 url: obj.options.url, 3732 method: 'GET', 3733 dataType: 'json', 3734 success: function(data) { 3735 obj.setData(data); 3736 // Callback 3737 if (typeof(callback) == 'function') { 3738 callback(obj); 3739 } 3740 } 3741 }); 3742 } 3743 3744 /** 3745 * Set ID for one item 3746 */ 3747 obj.setId = function(item, v) { 3748 // Legacy purposes 3749 if (! obj.options.format) { 3750 var property = 'value'; 3751 } else { 3752 var property = 'id'; 3753 } 3754 3755 if (typeof(item) == 'object') { 3756 item[property] = v; 3757 } else { 3758 obj.items[item].data[property] = v; 3759 } 3760 } 3761 3762 /** 3763 * Add a new item 3764 * @param {string} title - title of the new item 3765 * @param {string} id - value/id of the new item 3766 */ 3767 obj.add = function(title, id) { 3768 if (! title) { 3769 var current = obj.options.autocomplete == true ? obj.header.value : ''; 3770 var title = prompt(jSuites.translate('Add A New Option'), current); 3771 if (! title) { 3772 return false; 3773 } 3774 } 3775 3776 // Id 3777 if (! id) { 3778 id = jSuites.guid(); 3779 } 3780 3781 // Create new item 3782 if (! obj.options.format) { 3783 var item = { 3784 value: id, 3785 text: title, 3786 } 3787 } else { 3788 var item = { 3789 id: id, 3790 name: title, 3791 } 3792 } 3793 3794 // Callback 3795 if (typeof(obj.options.onbeforeinsert) == 'function') { 3796 var ret = obj.options.onbeforeinsert(obj, item); 3797 if (ret === false) { 3798 return false; 3799 } else if (ret) { 3800 item = ret; 3801 } 3802 } 3803 3804 // Add item to the main list 3805 obj.options.data.push(item); 3806 3807 // Create DOM 3808 var newItem = obj.createItem(item); 3809 3810 // Append DOM to the list 3811 content.appendChild(newItem.element); 3812 3813 // Callback 3814 if (typeof(obj.options.oninsert) == 'function') { 3815 obj.options.oninsert(obj, item, newItem); 3816 } 3817 3818 // Show content 3819 if (content.style.display == 'none') { 3820 content.style.display = ''; 3821 } 3822 3823 // Search? 3824 if (obj.results) { 3825 obj.results.push(newItem); 3826 } 3827 3828 return item; 3829 } 3830 3831 /** 3832 * Create a new item 3833 */ 3834 obj.createItem = function(data, group, groupName) { 3835 // Keep the correct source of data 3836 if (! obj.options.format) { 3837 if (! data.value && data.id !== undefined) { 3838 data.value = data.id; 3839 //delete data.id; 3840 } 3841 if (! data.text && data.name !== undefined) { 3842 data.text = data.name; 3843 //delete data.name; 3844 } 3845 } else { 3846 if (! data.id && data.value !== undefined) { 3847 data.id = data.value; 3848 //delete data.value; 3849 } 3850 if (! data.name && data.text !== undefined) { 3851 data.name = data.text 3852 //delete data.text; 3853 } 3854 } 3855 3856 // Create item 3857 var item = {}; 3858 item.element = document.createElement('div'); 3859 item.element.className = 'jdropdown-item'; 3860 item.element.indexValue = obj.items.length; 3861 item.data = data; 3862 3863 // Groupd DOM 3864 if (group) { 3865 item.group = group; 3866 } 3867 3868 // Id 3869 if (data.id) { 3870 item.element.setAttribute('id', data.id); 3871 } 3872 3873 // Disabled 3874 if (data.disabled == true) { 3875 item.element.setAttribute('data-disabled', true); 3876 } 3877 3878 // Tooltip 3879 if (data.tooltip) { 3880 item.element.setAttribute('title', data.tooltip); 3881 } 3882 3883 // Image 3884 if (data.image) { 3885 var image = document.createElement('img'); 3886 image.className = 'jdropdown-image'; 3887 image.src = data.image; 3888 if (! data.title) { 3889 image.classList.add('jdropdown-image-small'); 3890 } 3891 item.element.appendChild(image); 3892 } else if (data.icon) { 3893 var icon = document.createElement('span'); 3894 icon.className = "jdropdown-icon material-icons"; 3895 icon.innerText = data.icon; 3896 if (! data.title) { 3897 icon.classList.add('jdropdown-icon-small'); 3898 } 3899 if (data.color) { 3900 icon.style.color = data.color; 3901 } 3902 item.element.appendChild(icon); 3903 } else if (data.color) { 3904 var color = document.createElement('div'); 3905 color.className = 'jdropdown-color'; 3906 color.style.backgroundColor = data.color; 3907 item.element.appendChild(color); 3908 } 3909 3910 // Set content 3911 if (! obj.options.format) { 3912 var text = data.text; 3913 } else { 3914 var text = data.name; 3915 } 3916 3917 var node = document.createElement('div'); 3918 node.className = 'jdropdown-description'; 3919 node.innerHTML = text || ' '; 3920 3921 // Title 3922 if (data.title) { 3923 var title = document.createElement('div'); 3924 title.className = 'jdropdown-title'; 3925 title.innerText = data.title; 3926 node.appendChild(title); 3927 } 3928 3929 // Set content 3930 if (! obj.options.format) { 3931 var val = data.value; 3932 } else { 3933 var val = data.id; 3934 } 3935 3936 // Value 3937 if (obj.value[val]) { 3938 item.element.classList.add('jdropdown-selected'); 3939 item.selected = true; 3940 } 3941 3942 // Keep DOM accessible 3943 obj.items.push(item); 3944 3945 // Add node to item 3946 item.element.appendChild(node); 3947 3948 return item; 3949 } 3950 3951 obj.appendData = function(data) { 3952 // Create elements 3953 if (data.length) { 3954 // Helpers 3955 var items = []; 3956 var groups = []; 3957 3958 // Prepare data 3959 for (var i = 0; i < data.length; i++) { 3960 // Process groups 3961 if (data[i].group) { 3962 if (! groups[data[i].group]) { 3963 groups[data[i].group] = []; 3964 } 3965 groups[data[i].group].push(i); 3966 } else { 3967 items.push(i); 3968 } 3969 } 3970 3971 // Number of items counter 3972 var counter = 0; 3973 3974 // Groups 3975 var groupNames = Object.keys(groups); 3976 3977 // Append groups in case exists 3978 if (groupNames.length > 0) { 3979 for (var i = 0; i < groupNames.length; i++) { 3980 // Group container 3981 var group = document.createElement('div'); 3982 group.className = 'jdropdown-group'; 3983 // Group name 3984 var groupName = document.createElement('div'); 3985 groupName.className = 'jdropdown-group-name'; 3986 groupName.innerHTML = groupNames[i]; 3987 // Group arrow 3988 var groupArrow = document.createElement('i'); 3989 groupArrow.className = 'jdropdown-group-arrow jdropdown-group-arrow-down'; 3990 groupName.appendChild(groupArrow); 3991 // Group items 3992 var groupContent = document.createElement('div'); 3993 groupContent.className = 'jdropdown-group-items'; 3994 for (var j = 0; j < groups[groupNames[i]].length; j++) { 3995 var item = obj.createItem(data[groups[groupNames[i]][j]], group, groupNames[i]); 3996 3997 if (obj.options.lazyLoading == false || counter < 200) { 3998 groupContent.appendChild(item.element); 3999 counter++; 4000 } 4001 } 4002 // Group itens 4003 group.appendChild(groupName); 4004 group.appendChild(groupContent); 4005 // Keep group DOM 4006 obj.groups.push(group); 4007 // Only add to the screen if children on the group 4008 if (groupContent.children.length > 0) { 4009 // Add DOM to the content 4010 content.appendChild(group); 4011 } 4012 } 4013 } 4014 4015 if (items.length) { 4016 for (var i = 0; i < items.length; i++) { 4017 var item = obj.createItem(data[items[i]]); 4018 if (obj.options.lazyLoading == false || counter < 200) { 4019 content.appendChild(item.element); 4020 counter++; 4021 } 4022 } 4023 } 4024 } 4025 } 4026 4027 obj.setData = function(data) { 4028 // Reset current value 4029 resetValue(); 4030 4031 // Make sure the content container is blank 4032 content.innerHTML = ''; 4033 4034 // Reset 4035 obj.header.value = ''; 4036 4037 // Reset items and values 4038 obj.items = []; 4039 4040 // Prepare data 4041 if (data && data.length) { 4042 for (var i = 0; i < data.length; i++) { 4043 // Compatibility 4044 if (typeof(data[i]) != 'object') { 4045 // Correct format 4046 if (! obj.options.format) { 4047 data[i] = { 4048 value: data[i], 4049 text: data[i] 4050 } 4051 } else { 4052 data[i] = { 4053 id: data[i], 4054 name: data[i] 4055 } 4056 } 4057 } 4058 } 4059 4060 // Append data 4061 obj.appendData(data); 4062 4063 // Update data 4064 obj.options.data = data; 4065 } else { 4066 // Update data 4067 obj.options.data = []; 4068 } 4069 4070 obj.close(); 4071 } 4072 4073 obj.getData = function() { 4074 return obj.options.data; 4075 } 4076 4077 /** 4078 * Get position of the item 4079 */ 4080 obj.getPosition = function(val) { 4081 for (var i = 0; i < obj.items.length; i++) { 4082 if (Value(i) == val) { 4083 return i; 4084 } 4085 } 4086 return false; 4087 } 4088 4089 /** 4090 * Get dropdown current text 4091 */ 4092 obj.getText = function(asArray) { 4093 // Get value 4094 var v = getText(); 4095 // Return value 4096 if (asArray) { 4097 return v; 4098 } else { 4099 return v.join('; '); 4100 } 4101 } 4102 4103 /** 4104 * Get dropdown current value 4105 */ 4106 obj.getValue = function(asArray) { 4107 // Get value 4108 var v = getValue(); 4109 // Return value 4110 if (asArray) { 4111 return v; 4112 } else { 4113 return v.join(';'); 4114 } 4115 } 4116 4117 /** 4118 * Change event 4119 */ 4120 var change = function(oldValue) { 4121 // Lemonade JS 4122 if (el.value != obj.options.value) { 4123 el.value = obj.options.value; 4124 if (typeof(el.oninput) == 'function') { 4125 el.oninput({ 4126 type: 'input', 4127 target: el, 4128 value: el.value 4129 }); 4130 } 4131 } 4132 4133 // Events 4134 if (typeof(obj.options.onchange) == 'function') { 4135 obj.options.onchange(el, obj, oldValue, obj.options.value); 4136 } 4137 } 4138 4139 /** 4140 * Set value 4141 */ 4142 obj.setValue = function(newValue) { 4143 // Current value 4144 var oldValue = obj.getValue(); 4145 // New value 4146 if (Array.isArray(newValue)) { 4147 newValue = newValue.join(';') 4148 } 4149 4150 if (oldValue !== newValue) { 4151 // Set value 4152 applyValue(newValue); 4153 4154 // Change 4155 change(oldValue); 4156 } 4157 } 4158 4159 obj.resetSelected = function() { 4160 obj.setValue(null); 4161 } 4162 4163 obj.selectIndex = function(index, force) { 4164 // Make sure is a number 4165 var index = parseInt(index); 4166 4167 // Only select those existing elements 4168 if (obj.items && obj.items[index] && (force === true || obj.items[index].data.disabled !== true)) { 4169 // Reset cursor to a new position 4170 obj.setCursor(index, false); 4171 4172 // Behaviour 4173 if (! obj.options.multiple) { 4174 // Update value 4175 if (obj.items[index].selected) { 4176 obj.setValue(null); 4177 } else { 4178 obj.setValue(Value(index)); 4179 } 4180 4181 // Close component 4182 obj.close(); 4183 } else { 4184 // Old value 4185 var oldValue = obj.options.value; 4186 4187 // Toggle option 4188 if (obj.items[index].selected) { 4189 obj.items[index].element.classList.remove('jdropdown-selected'); 4190 obj.items[index].selected = false; 4191 4192 delete obj.value[Value(index)]; 4193 } else { 4194 // Select element 4195 obj.items[index].element.classList.add('jdropdown-selected'); 4196 obj.items[index].selected = true; 4197 4198 // Set value 4199 obj.value[Value(index)] = Text(index); 4200 } 4201 4202 // Global value 4203 obj.options.value = Object.keys(obj.value).join(';'); 4204 4205 // Update labels for multiple dropdown 4206 if (obj.options.autocomplete == false) { 4207 obj.header.value = getText().join('; '); 4208 } 4209 4210 // Events 4211 change(oldValue); 4212 } 4213 } 4214 } 4215 4216 obj.selectItem = function(item) { 4217 obj.selectIndex(item.indexValue); 4218 } 4219 4220 var exists = function(k, result) { 4221 for (var j = 0; j < result.length; j++) { 4222 if (! obj.options.format) { 4223 if (result[j].value == k) { 4224 return true; 4225 } 4226 } else { 4227 if (result[j].id == k) { 4228 return true; 4229 } 4230 } 4231 } 4232 return false; 4233 } 4234 4235 obj.find = function(str) { 4236 if (obj.search == str.trim()) { 4237 return false; 4238 } 4239 4240 // Search term 4241 obj.search = str; 4242 4243 // Reset index 4244 obj.setCursor(); 4245 4246 // Remove nodes from all groups 4247 if (obj.groups.length) { 4248 for (var i = 0; i < obj.groups.length; i++) { 4249 obj.groups[i].lastChild.innerHTML = ''; 4250 } 4251 } 4252 4253 // Remove all nodes 4254 content.innerHTML = ''; 4255 4256 // Remove current items in the remote search 4257 if (obj.options.remoteSearch == true) { 4258 // Reset results 4259 obj.results = null; 4260 // URL 4261 var url = obj.options.url + (obj.options.url.indexOf('?') > 0 ? '&' : '?') + 'q=' + str; 4262 // Remote search 4263 jSuites.ajax({ 4264 url: url, 4265 method: 'GET', 4266 dataType: 'json', 4267 success: function(result) { 4268 // Reset items 4269 obj.items = []; 4270 4271 // Add the current selected items to the results in case they are not there 4272 var current = Object.keys(obj.value); 4273 if (current.length) { 4274 for (var i = 0; i < current.length; i++) { 4275 if (! exists(current[i], result)) { 4276 if (! obj.options.format) { 4277 result.unshift({ value: current[i], text: obj.value[current[i]] }); 4278 } else { 4279 result.unshift({ id: current[i], name: obj.value[current[i]] }); 4280 } 4281 } 4282 } 4283 } 4284 // Append data 4285 obj.appendData(result); 4286 // Show or hide results 4287 if (! result.length) { 4288 content.style.display = 'none'; 4289 } else { 4290 content.style.display = ''; 4291 } 4292 } 4293 }); 4294 } else { 4295 // Search terms 4296 str = new RegExp(str, 'gi'); 4297 4298 // Reset search 4299 var results = []; 4300 4301 // Append options 4302 for (var i = 0; i < obj.items.length; i++) { 4303 // Item label 4304 var label = Text(i); 4305 // Item title 4306 var title = obj.items[i].data.title || ''; 4307 // Group name 4308 var groupName = obj.items[i].data.group || ''; 4309 // Synonym 4310 var synonym = obj.items[i].data.synonym || ''; 4311 if (synonym) { 4312 synonym = synonym.join(' '); 4313 } 4314 4315 if (str == null || obj.items[i].selected == true || label.match(str) || title.match(str) || groupName.match(str) || synonym.match(str)) { 4316 results.push(obj.items[i]); 4317 } 4318 } 4319 4320 if (! results.length) { 4321 content.style.display = 'none'; 4322 4323 // Results 4324 obj.results = null; 4325 } else { 4326 content.style.display = ''; 4327 4328 // Results 4329 obj.results = results; 4330 4331 // Show 200 items at once 4332 var number = results.length || 0; 4333 4334 // Lazyloading 4335 if (obj.options.lazyLoading == true && number > 200) { 4336 number = 200; 4337 } 4338 4339 for (var i = 0; i < number; i++) { 4340 if (obj.results[i].group) { 4341 if (! obj.results[i].group.parentNode) { 4342 content.appendChild(obj.results[i].group); 4343 } 4344 obj.results[i].group.lastChild.appendChild(obj.results[i].element); 4345 } else { 4346 content.appendChild(obj.results[i].element); 4347 } 4348 } 4349 } 4350 } 4351 4352 // Auto focus 4353 if (obj.options.autofocus == true) { 4354 obj.first(); 4355 } 4356 } 4357 4358 obj.open = function() { 4359 // Focus 4360 if (! el.classList.contains('jdropdown-focus')) { 4361 // Current dropdown 4362 jSuites.dropdown.current = obj; 4363 4364 // Start tracking 4365 jSuites.tracking(obj, true); 4366 4367 // Add focus 4368 el.classList.add('jdropdown-focus'); 4369 4370 // Animation 4371 if (jSuites.getWindowWidth() < 800) { 4372 if (obj.options.type == null || obj.options.type == 'picker') { 4373 jSuites.animation.slideBottom(container, 1); 4374 } 4375 } 4376 4377 // Filter 4378 if (obj.options.autocomplete == true) { 4379 obj.header.value = obj.search; 4380 obj.header.focus(); 4381 } 4382 4383 // Set cursor for the first or first selected element 4384 var k = getValue(); 4385 if (k[0]) { 4386 var cursor = obj.getPosition(k[0]); 4387 if (cursor !== false) { 4388 obj.setCursor(cursor); 4389 } 4390 } 4391 4392 // Container Size 4393 if (! obj.options.type || obj.options.type == 'default') { 4394 var rect = el.getBoundingClientRect(); 4395 var rectContainer = container.getBoundingClientRect(); 4396 4397 if (obj.options.position) { 4398 container.style.position = 'fixed'; 4399 if (window.innerHeight < rect.bottom + rectContainer.height) { 4400 container.style.top = ''; 4401 container.style.bottom = (window.innerHeight - rect.top ) + 1 + 'px'; 4402 } else { 4403 container.style.top = rect.bottom + 'px'; 4404 container.style.bottom = ''; 4405 } 4406 container.style.left = rect.left + 'px'; 4407 } else { 4408 if (window.innerHeight < rect.bottom + rectContainer.height) { 4409 container.style.top = ''; 4410 container.style.bottom = rect.height + 1 + 'px'; 4411 } else { 4412 container.style.top = ''; 4413 container.style.bottom = ''; 4414 } 4415 } 4416 4417 container.style.minWidth = rect.width + 'px'; 4418 4419 if (obj.options.maxWidth) { 4420 container.style.maxWidth = obj.options.maxWidth; 4421 } 4422 4423 if (! obj.items.length && obj.options.autocomplete == true) { 4424 content.style.display = 'none'; 4425 } else { 4426 content.style.display = ''; 4427 } 4428 } 4429 } 4430 4431 // Events 4432 if (typeof(obj.options.onopen) == 'function') { 4433 obj.options.onopen(el); 4434 } 4435 } 4436 4437 obj.close = function(ignoreEvents) { 4438 if (el.classList.contains('jdropdown-focus')) { 4439 // Update labels 4440 obj.header.value = obj.getText(); 4441 // Remove cursor 4442 obj.setCursor(); 4443 // Events 4444 if (! ignoreEvents && typeof(obj.options.onclose) == 'function') { 4445 obj.options.onclose(el); 4446 } 4447 // Blur 4448 if (obj.header.blur) { 4449 obj.header.blur(); 4450 } 4451 // Remove focus 4452 el.classList.remove('jdropdown-focus'); 4453 // Start tracking 4454 jSuites.tracking(obj, false); 4455 // Current dropdown 4456 jSuites.dropdown.current = null; 4457 } 4458 4459 return obj.getValue(); 4460 } 4461 4462 /** 4463 * Set cursor 4464 */ 4465 obj.setCursor = function(index, setPosition) { 4466 // Remove current cursor 4467 if (obj.currentIndex != null) { 4468 // Remove visual cursor 4469 if (obj.items && obj.items[obj.currentIndex]) { 4470 obj.items[obj.currentIndex].element.classList.remove('jdropdown-cursor'); 4471 } 4472 } 4473 4474 if (index == undefined) { 4475 obj.currentIndex = null; 4476 } else { 4477 index = parseInt(index); 4478 4479 // Cursor only for visible items 4480 if (obj.items[index].element.parentNode) { 4481 obj.items[index].element.classList.add('jdropdown-cursor'); 4482 obj.currentIndex = index; 4483 4484 // Update scroll to the cursor element 4485 if (setPosition !== false && obj.items[obj.currentIndex].element) { 4486 var container = content.scrollTop; 4487 var element = obj.items[obj.currentIndex].element; 4488 content.scrollTop = element.offsetTop - element.scrollTop + element.clientTop - 95; 4489 } 4490 } 4491 } 4492 } 4493 4494 // Compatibility 4495 obj.resetCursor = obj.setCursor; 4496 obj.updateCursor = obj.setCursor; 4497 4498 /** 4499 * Reset cursor and selected items 4500 */ 4501 obj.reset = function() { 4502 // Reset cursor 4503 obj.setCursor(); 4504 4505 // Reset selected 4506 obj.setValue(null); 4507 } 4508 4509 /** 4510 * First available item 4511 */ 4512 obj.first = function() { 4513 if (obj.options.lazyLoading === true) { 4514 obj.loadFirst(); 4515 } 4516 4517 var items = content.querySelectorAll('.jdropdown-item'); 4518 if (items.length) { 4519 var newIndex = items[0].indexValue; 4520 obj.setCursor(newIndex); 4521 } 4522 } 4523 4524 /** 4525 * Last available item 4526 */ 4527 obj.last = function() { 4528 if (obj.options.lazyLoading === true) { 4529 obj.loadLast(); 4530 } 4531 4532 var items = content.querySelectorAll('.jdropdown-item'); 4533 if (items.length) { 4534 var newIndex = items[items.length-1].indexValue; 4535 obj.setCursor(newIndex); 4536 } 4537 } 4538 4539 obj.next = function(letter) { 4540 var newIndex = null; 4541 4542 if (letter) { 4543 if (letter.length == 1) { 4544 // Current index 4545 var current = obj.currentIndex || -1; 4546 // Letter 4547 letter = letter.toLowerCase(); 4548 4549 var e = null; 4550 var l = null; 4551 var items = content.querySelectorAll('.jdropdown-item'); 4552 if (items.length) { 4553 for (var i = 0; i < items.length; i++) { 4554 if (items[i].indexValue > current) { 4555 if (e = obj.items[items[i].indexValue]) { 4556 if (l = e.element.innerText[0]) { 4557 l = l.toLowerCase(); 4558 if (letter == l) { 4559 newIndex = items[i].indexValue; 4560 break; 4561 } 4562 } 4563 } 4564 } 4565 } 4566 obj.setCursor(newIndex); 4567 } 4568 } 4569 } else { 4570 if (obj.currentIndex == undefined || obj.currentIndex == null) { 4571 obj.first(); 4572 } else { 4573 var element = obj.items[obj.currentIndex].element; 4574 4575 var next = element.nextElementSibling; 4576 if (next) { 4577 if (next.classList.contains('jdropdown-group')) { 4578 next = next.lastChild.firstChild; 4579 } 4580 newIndex = next.indexValue; 4581 } else { 4582 if (element.parentNode.classList.contains('jdropdown-group-items')) { 4583 if (next = element.parentNode.parentNode.nextElementSibling) { 4584 if (next.classList.contains('jdropdown-group')) { 4585 next = next.lastChild.firstChild; 4586 } else if (next.classList.contains('jdropdown-item')) { 4587 newIndex = next.indexValue; 4588 } else { 4589 next = null; 4590 } 4591 } 4592 4593 if (next) { 4594 newIndex = next.indexValue; 4595 } 4596 } 4597 } 4598 4599 if (newIndex !== null) { 4600 obj.setCursor(newIndex); 4601 } 4602 } 4603 } 4604 } 4605 4606 obj.prev = function() { 4607 var newIndex = null; 4608 4609 if (obj.currentIndex === null) { 4610 obj.first(); 4611 } else { 4612 var element = obj.items[obj.currentIndex].element; 4613 4614 var prev = element.previousElementSibling; 4615 if (prev) { 4616 if (prev.classList.contains('jdropdown-group')) { 4617 prev = prev.lastChild.lastChild; 4618 } 4619 newIndex = prev.indexValue; 4620 } else { 4621 if (element.parentNode.classList.contains('jdropdown-group-items')) { 4622 if (prev = element.parentNode.parentNode.previousElementSibling) { 4623 if (prev.classList.contains('jdropdown-group')) { 4624 prev = prev.lastChild.lastChild; 4625 } else if (prev.classList.contains('jdropdown-item')) { 4626 newIndex = prev.indexValue; 4627 } else { 4628 prev = null 4629 } 4630 } 4631 4632 if (prev) { 4633 newIndex = prev.indexValue; 4634 } 4635 } 4636 } 4637 } 4638 4639 if (newIndex !== null) { 4640 obj.setCursor(newIndex); 4641 } 4642 } 4643 4644 obj.loadFirst = function() { 4645 // Search 4646 if (obj.results) { 4647 var results = obj.results; 4648 } else { 4649 var results = obj.items; 4650 } 4651 4652 // Show 200 items at once 4653 var number = results.length || 0; 4654 4655 // Lazyloading 4656 if (obj.options.lazyLoading == true && number > 200) { 4657 number = 200; 4658 } 4659 4660 // Reset container 4661 content.innerHTML = ''; 4662 4663 // First 200 items 4664 for (var i = 0; i < number; i++) { 4665 if (results[i].group) { 4666 if (! results[i].group.parentNode) { 4667 content.appendChild(results[i].group); 4668 } 4669 results[i].group.lastChild.appendChild(results[i].element); 4670 } else { 4671 content.appendChild(results[i].element); 4672 } 4673 } 4674 4675 // Scroll go to the begin 4676 content.scrollTop = 0; 4677 } 4678 4679 obj.loadLast = function() { 4680 // Search 4681 if (obj.results) { 4682 var results = obj.results; 4683 } else { 4684 var results = obj.items; 4685 } 4686 4687 // Show first page 4688 var number = results.length; 4689 4690 // Max 200 items 4691 if (number > 200) { 4692 number = number - 200; 4693 4694 // Reset container 4695 content.innerHTML = ''; 4696 4697 // First 200 items 4698 for (var i = number; i < results.length; i++) { 4699 if (results[i].group) { 4700 if (! results[i].group.parentNode) { 4701 content.appendChild(results[i].group); 4702 } 4703 results[i].group.lastChild.appendChild(results[i].element); 4704 } else { 4705 content.appendChild(results[i].element); 4706 } 4707 } 4708 4709 // Scroll go to the begin 4710 content.scrollTop = content.scrollHeight; 4711 } 4712 } 4713 4714 obj.loadUp = function() { 4715 var test = false; 4716 4717 // Search 4718 if (obj.results) { 4719 var results = obj.results; 4720 } else { 4721 var results = obj.items; 4722 } 4723 4724 var items = content.querySelectorAll('.jdropdown-item'); 4725 var fistItem = items[0].indexValue; 4726 fistItem = obj.items[fistItem]; 4727 var index = results.indexOf(fistItem) - 1; 4728 4729 if (index > 0) { 4730 var number = 0; 4731 4732 while (index > 0 && results[index] && number < 200) { 4733 if (results[index].group) { 4734 if (! results[index].group.parentNode) { 4735 content.insertBefore(results[index].group, content.firstChild); 4736 } 4737 results[index].group.lastChild.insertBefore(results[index].element, results[index].group.lastChild.firstChild); 4738 } else { 4739 content.insertBefore(results[index].element, content.firstChild); 4740 } 4741 4742 index--; 4743 number++; 4744 } 4745 4746 // New item added 4747 test = true; 4748 } 4749 4750 return test; 4751 } 4752 4753 obj.loadDown = function() { 4754 var test = false; 4755 4756 // Search 4757 if (obj.results) { 4758 var results = obj.results; 4759 } else { 4760 var results = obj.items; 4761 } 4762 4763 var items = content.querySelectorAll('.jdropdown-item'); 4764 var lastItem = items[items.length-1].indexValue; 4765 lastItem = obj.items[lastItem]; 4766 var index = results.indexOf(lastItem) + 1; 4767 4768 if (index < results.length) { 4769 var number = 0; 4770 while (index < results.length && results[index] && number < 200) { 4771 if (results[index].group) { 4772 if (! results[index].group.parentNode) { 4773 content.appendChild(results[index].group); 4774 } 4775 results[index].group.lastChild.appendChild(results[index].element); 4776 } else { 4777 content.appendChild(results[index].element); 4778 } 4779 4780 index++; 4781 number++; 4782 } 4783 4784 // New item added 4785 test = true; 4786 } 4787 4788 return test; 4789 } 4790 4791 init(); 4792 4793 return obj; 4794}); 4795 4796jSuites.dropdown.keydown = function(e) { 4797 var dropdown = null; 4798 if (dropdown = jSuites.dropdown.current) { 4799 if (e.which == 13 || e.which == 9) { // enter or tab 4800 if (dropdown.header.value && dropdown.currentIndex == null && dropdown.options.newOptions) { 4801 // if they typed something in, but it matched nothing, and newOptions are allowed, start that flow 4802 dropdown.add(); 4803 } else { 4804 // Quick Select/Filter 4805 if (dropdown.currentIndex == null && dropdown.options.autocomplete == true && dropdown.header.value != "") { 4806 dropdown.find(dropdown.header.value); 4807 } 4808 dropdown.selectIndex(dropdown.currentIndex); 4809 } 4810 } else if (e.which == 38) { // up arrow 4811 if (dropdown.currentIndex == null) { 4812 dropdown.first(); 4813 } else if (dropdown.currentIndex > 0) { 4814 dropdown.prev(); 4815 } 4816 e.preventDefault(); 4817 } else if (e.which == 40) { // down arrow 4818 if (dropdown.currentIndex == null) { 4819 dropdown.first(); 4820 } else if (dropdown.currentIndex + 1 < dropdown.items.length) { 4821 dropdown.next(); 4822 } 4823 e.preventDefault(); 4824 } else if (e.which == 36) { 4825 dropdown.first(); 4826 if (! e.target.classList.contains('jdropdown-header')) { 4827 e.preventDefault(); 4828 } 4829 } else if (e.which == 35) { 4830 dropdown.last(); 4831 if (! e.target.classList.contains('jdropdown-header')) { 4832 e.preventDefault(); 4833 } 4834 } else if (e.which == 27) { 4835 dropdown.close(); 4836 } else if (e.which == 33) { // page up 4837 if (dropdown.currentIndex == null) { 4838 dropdown.first(); 4839 } else if (dropdown.currentIndex > 0) { 4840 for (var i = 0; i < 7; i++) { 4841 dropdown.prev() 4842 } 4843 } 4844 e.preventDefault(); 4845 } else if (e.which == 34) { // page down 4846 if (dropdown.currentIndex == null) { 4847 dropdown.first(); 4848 } else if (dropdown.currentIndex + 1 < dropdown.items.length) { 4849 for (var i = 0; i < 7; i++) { 4850 dropdown.next() 4851 } 4852 } 4853 e.preventDefault(); 4854 } 4855 } 4856} 4857 4858jSuites.dropdown.mouseup = function(e) { 4859 var element = jSuites.findElement(e.target, 'jdropdown'); 4860 if (element) { 4861 var dropdown = element.dropdown; 4862 if (e.target.classList.contains('jdropdown-header')) { 4863 if (element.classList.contains('jdropdown-focus') && element.classList.contains('jdropdown-default')) { 4864 var rect = element.getBoundingClientRect(); 4865 4866 if (e.changedTouches && e.changedTouches[0]) { 4867 var x = e.changedTouches[0].clientX; 4868 var y = e.changedTouches[0].clientY; 4869 } else { 4870 var x = e.clientX; 4871 var y = e.clientY; 4872 } 4873 4874 if (rect.width - (x - rect.left) < 30) { 4875 if (e.target.classList.contains('jdropdown-add')) { 4876 dropdown.add(); 4877 } else { 4878 dropdown.close(); 4879 } 4880 } else { 4881 if (dropdown.options.autocomplete == false) { 4882 dropdown.close(); 4883 } 4884 } 4885 } else { 4886 dropdown.open(); 4887 } 4888 } else if (e.target.classList.contains('jdropdown-group-name')) { 4889 var items = e.target.nextSibling.children; 4890 if (e.target.nextSibling.style.display != 'none') { 4891 for (var i = 0; i < items.length; i++) { 4892 if (items[i].style.display != 'none') { 4893 dropdown.selectItem(items[i]); 4894 } 4895 } 4896 } 4897 } else if (e.target.classList.contains('jdropdown-group-arrow')) { 4898 if (e.target.classList.contains('jdropdown-group-arrow-down')) { 4899 e.target.classList.remove('jdropdown-group-arrow-down'); 4900 e.target.classList.add('jdropdown-group-arrow-up'); 4901 e.target.parentNode.nextSibling.style.display = 'none'; 4902 } else { 4903 e.target.classList.remove('jdropdown-group-arrow-up'); 4904 e.target.classList.add('jdropdown-group-arrow-down'); 4905 e.target.parentNode.nextSibling.style.display = ''; 4906 } 4907 } else if (e.target.classList.contains('jdropdown-item')) { 4908 dropdown.selectItem(e.target); 4909 } else if (e.target.classList.contains('jdropdown-image')) { 4910 dropdown.selectItem(e.target.parentNode); 4911 } else if (e.target.classList.contains('jdropdown-description')) { 4912 dropdown.selectItem(e.target.parentNode); 4913 } else if (e.target.classList.contains('jdropdown-title')) { 4914 dropdown.selectItem(e.target.parentNode.parentNode); 4915 } else if (e.target.classList.contains('jdropdown-close') || e.target.classList.contains('jdropdown-backdrop')) { 4916 dropdown.close(); 4917 } 4918 } 4919} 4920 4921jSuites.dropdown.extractFromDom = function(el, options) { 4922 // Keep reference 4923 var select = el; 4924 if (! options) { 4925 options = {}; 4926 } 4927 // Prepare configuration 4928 if (el.getAttribute('multiple') && (! options || options.multiple == undefined)) { 4929 options.multiple = true; 4930 } 4931 if (el.getAttribute('placeholder') && (! options || options.placeholder == undefined)) { 4932 options.placeholder = el.getAttribute('placeholder'); 4933 } 4934 if (el.getAttribute('data-autocomplete') && (! options || options.autocomplete == undefined)) { 4935 options.autocomplete = true; 4936 } 4937 if (! options || options.width == undefined) { 4938 options.width = el.offsetWidth; 4939 } 4940 if (el.value && (! options || options.value == undefined)) { 4941 options.value = el.value; 4942 } 4943 if (! options || options.data == undefined) { 4944 options.data = []; 4945 for (var j = 0; j < el.children.length; j++) { 4946 if (el.children[j].tagName == 'OPTGROUP') { 4947 for (var i = 0; i < el.children[j].children.length; i++) { 4948 options.data.push({ 4949 value: el.children[j].children[i].value, 4950 text: el.children[j].children[i].innerHTML, 4951 group: el.children[j].getAttribute('label'), 4952 }); 4953 } 4954 } else { 4955 options.data.push({ 4956 value: el.children[j].value, 4957 text: el.children[j].innerHTML, 4958 }); 4959 } 4960 } 4961 } 4962 if (! options || options.onchange == undefined) { 4963 options.onchange = function(a,b,c,d) { 4964 if (options.multiple == true) { 4965 if (obj.items[b].classList.contains('jdropdown-selected')) { 4966 select.options[b].setAttribute('selected', 'selected'); 4967 } else { 4968 select.options[b].removeAttribute('selected'); 4969 } 4970 } else { 4971 select.value = d; 4972 } 4973 } 4974 } 4975 // Create DIV 4976 var div = document.createElement('div'); 4977 el.parentNode.insertBefore(div, el); 4978 el.style.display = 'none'; 4979 el = div; 4980 4981 return { el:el, options:options }; 4982} 4983 4984jSuites.editor = (function(el, options) { 4985 // New instance 4986 var obj = { type:'editor' }; 4987 obj.options = {}; 4988 4989 // Default configuration 4990 var defaults = { 4991 // Load data from a remove location 4992 url: null, 4993 // Initial HTML content 4994 value: '', 4995 // Initial snippet 4996 snippet: null, 4997 // Add toolbar 4998 toolbar: true, 4999 toolbarOnTop: false, 5000 // Website parser is to read websites and images from cross domain 5001 remoteParser: null, 5002 // Placeholder 5003 placeholder: null, 5004 // Parse URL 5005 filterPaste: true, 5006 // Accept drop files 5007 dropZone: true, 5008 dropAsSnippet: false, 5009 acceptImages: true, 5010 acceptFiles: false, 5011 maxFileSize: 5000000, 5012 allowImageResize: true, 5013 // Style 5014 maxHeight: null, 5015 height: null, 5016 focus: false, 5017 // Events 5018 onclick: null, 5019 onfocus: null, 5020 onblur: null, 5021 onload: null, 5022 onkeyup: null, 5023 onkeydown: null, 5024 onchange: null, 5025 extensions: null, 5026 type: null, 5027 }; 5028 5029 // Loop through our object 5030 for (var property in defaults) { 5031 if (options && options.hasOwnProperty(property)) { 5032 obj.options[property] = options[property]; 5033 } else { 5034 obj.options[property] = defaults[property]; 5035 } 5036 } 5037 5038 // Private controllers 5039 var editorTimer = null; 5040 var editorAction = null; 5041 var files = []; 5042 5043 // Keep the reference for the container 5044 obj.el = el; 5045 5046 if (typeof(obj.options.onclick) == 'function') { 5047 el.onclick = function(e) { 5048 obj.options.onclick(el, obj, e); 5049 } 5050 } 5051 5052 // Prepare container 5053 el.classList.add('jeditor-container'); 5054 5055 // Snippet 5056 var snippet = document.createElement('div'); 5057 snippet.className = 'jsnippet'; 5058 snippet.setAttribute('contenteditable', false); 5059 5060 // Toolbar 5061 var toolbar = document.createElement('div'); 5062 toolbar.className = 'jeditor-toolbar'; 5063 5064 obj.editor = document.createElement('div'); 5065 obj.editor.setAttribute('contenteditable', true); 5066 obj.editor.setAttribute('spellcheck', false); 5067 obj.editor.classList.add('jeditor'); 5068 5069 // Placeholder 5070 if (obj.options.placeholder) { 5071 obj.editor.setAttribute('data-placeholder', obj.options.placeholder); 5072 } 5073 5074 // Max height 5075 if (obj.options.maxHeight || obj.options.height) { 5076 obj.editor.style.overflowY = 'auto'; 5077 5078 if (obj.options.maxHeight) { 5079 obj.editor.style.maxHeight = obj.options.maxHeight; 5080 } 5081 if (obj.options.height) { 5082 obj.editor.style.height = obj.options.height; 5083 } 5084 } 5085 5086 // Set editor initial value 5087 if (obj.options.url) { 5088 jSuites.ajax({ 5089 url: obj.options.url, 5090 dataType: 'html', 5091 success: function(result) { 5092 obj.editor.innerHTML = result; 5093 5094 jSuites.editor.setCursor(obj.editor, obj.options.focus == 'initial' ? true : false); 5095 } 5096 }) 5097 } else { 5098 if (obj.options.value) { 5099 obj.editor.innerHTML = obj.options.value; 5100 } else { 5101 // Create from existing elements 5102 for (var i = 0; i < el.children.length; i++) { 5103 obj.editor.appendChild(el.children[i]); 5104 } 5105 } 5106 } 5107 5108 // Make sure element is empty 5109 el.innerHTML = ''; 5110 5111 /** 5112 * Onchange event controllers 5113 */ 5114 var change = function(e) { 5115 if (typeof(obj.options.onchange) == 'function') { 5116 obj.options.onchange(el, obj, e); 5117 } 5118 5119 // Update value 5120 obj.options.value = obj.getData(); 5121 5122 // Lemonade JS 5123 if (el.value != obj.options.value) { 5124 el.value = obj.options.value; 5125 if (typeof(el.oninput) == 'function') { 5126 el.oninput({ 5127 type: 'input', 5128 target: el, 5129 value: el.value 5130 }); 5131 } 5132 } 5133 } 5134 5135 /** 5136 * Extract images from a HTML string 5137 */ 5138 var extractImageFromHtml = function(html) { 5139 // Create temp element 5140 var div = document.createElement('div'); 5141 div.innerHTML = html; 5142 5143 // Extract images 5144 var img = div.querySelectorAll('img'); 5145 5146 if (img.length) { 5147 for (var i = 0; i < img.length; i++) { 5148 obj.addImage(img[i].src); 5149 } 5150 } 5151 } 5152 5153 /** 5154 * Insert node at caret 5155 */ 5156 var insertNodeAtCaret = function(newNode) { 5157 var sel, range; 5158 5159 if (window.getSelection) { 5160 sel = window.getSelection(); 5161 if (sel.rangeCount) { 5162 range = sel.getRangeAt(0); 5163 var selectedText = range.toString(); 5164 range.deleteContents(); 5165 range.insertNode(newNode); 5166 // move the cursor after element 5167 range.setStartAfter(newNode); 5168 range.setEndAfter(newNode); 5169 sel.removeAllRanges(); 5170 sel.addRange(range); 5171 } 5172 } 5173 } 5174 5175 var updateTotalImages = function() { 5176 var o = null; 5177 if (o = snippet.children[0]) { 5178 // Make sure is a grid 5179 if (! o.classList.contains('jslider-grid')) { 5180 o.classList.add('jslider-grid'); 5181 } 5182 // Quantify of images 5183 var number = o.children.length; 5184 // Set the configuration of the grid 5185 o.setAttribute('data-number', number > 4 ? 4 : number); 5186 // Total of images inside the grid 5187 if (number > 4) { 5188 o.setAttribute('data-total', number - 4); 5189 } else { 5190 o.removeAttribute('data-total'); 5191 } 5192 } 5193 } 5194 5195 /** 5196 * Append image to the snippet 5197 */ 5198 var appendImage = function(image) { 5199 if (! snippet.innerHTML) { 5200 obj.appendSnippet({}); 5201 } 5202 snippet.children[0].appendChild(image); 5203 updateTotalImages(); 5204 } 5205 5206 /** 5207 * Append snippet 5208 * @Param object data 5209 */ 5210 obj.appendSnippet = function(data) { 5211 // Reset snippet 5212 snippet.innerHTML = ''; 5213 5214 // Attributes 5215 var a = [ 'image', 'title', 'description', 'host', 'url' ]; 5216 5217 for (var i = 0; i < a.length; i++) { 5218 var div = document.createElement('div'); 5219 div.className = 'jsnippet-' + a[i]; 5220 div.setAttribute('data-k', a[i]); 5221 snippet.appendChild(div); 5222 if (data[a[i]]) { 5223 if (a[i] == 'image') { 5224 if (! Array.isArray(data.image)) { 5225 data.image = [ data.image ]; 5226 } 5227 for (var j = 0; j < data.image.length; j++) { 5228 var img = document.createElement('img'); 5229 img.src = data.image[j]; 5230 div.appendChild(img); 5231 } 5232 } else { 5233 div.innerHTML = data[a[i]]; 5234 } 5235 } 5236 } 5237 5238 obj.editor.appendChild(document.createElement('br')); 5239 obj.editor.appendChild(snippet); 5240 } 5241 5242 /** 5243 * Set editor value 5244 */ 5245 obj.setData = function(o) { 5246 if (typeof(o) == 'object') { 5247 obj.editor.innerHTML = o.content; 5248 } else { 5249 obj.editor.innerHTML = o; 5250 } 5251 5252 if (obj.options.focus) { 5253 jSuites.editor.setCursor(obj.editor, true); 5254 } 5255 5256 // Reset files container 5257 files = []; 5258 } 5259 5260 obj.getFiles = function() { 5261 var f = obj.editor.querySelectorAll('.jfile'); 5262 var d = []; 5263 for (var i = 0; i < f.length; i++) { 5264 if (files[f[i].src]) { 5265 d.push(files[f[i].src]); 5266 } 5267 } 5268 return d; 5269 } 5270 5271 obj.getText = function() { 5272 return obj.editor.innerText; 5273 } 5274 5275 /** 5276 * Get editor data 5277 */ 5278 obj.getData = function(json) { 5279 if (! json) { 5280 var data = obj.editor.innerHTML; 5281 } else { 5282 var data = { 5283 content : '', 5284 } 5285 5286 // Get snippet 5287 if (snippet.innerHTML) { 5288 var index = 0; 5289 data.snippet = {}; 5290 for (var i = 0; i < snippet.children.length; i++) { 5291 // Get key from element 5292 var key = snippet.children[i].getAttribute('data-k'); 5293 if (key) { 5294 if (key == 'image') { 5295 if (! data.snippet.image) { 5296 data.snippet.image = []; 5297 } 5298 // Get all images 5299 for (var j = 0; j < snippet.children[i].children.length; j++) { 5300 data.snippet.image.push(snippet.children[i].children[j].getAttribute('src')) 5301 } 5302 } else { 5303 data.snippet[key] = snippet.children[i].innerHTML; 5304 } 5305 } 5306 } 5307 } 5308 5309 // Get files 5310 var f = Object.keys(files); 5311 if (f.length) { 5312 data.files = []; 5313 for (var i = 0; i < f.length; i++) { 5314 data.files.push(files[f[i]]); 5315 } 5316 } 5317 5318 // Get content 5319 var d = document.createElement('div'); 5320 d.innerHTML = obj.editor.innerHTML; 5321 var s = d.querySelector('.jsnippet'); 5322 if (s) { 5323 s.remove(); 5324 } 5325 5326 var text = d.innerHTML; 5327 text = text.replace(/<br>/g, "\n"); 5328 text = text.replace(/<\/div>/g, "<\/div>\n"); 5329 text = text.replace(/<(?:.|\n)*?>/gm, ""); 5330 data.content = text.trim(); 5331 5332 // Process extensions 5333 processExtensions('getData', data); 5334 } 5335 5336 return data; 5337 } 5338 5339 // Reset 5340 obj.reset = function() { 5341 obj.editor.innerHTML = ''; 5342 snippet.innerHTML = ''; 5343 files = []; 5344 } 5345 5346 obj.addPdf = function(data) { 5347 if (data.result.substr(0,4) != 'data') { 5348 console.error('Invalid source'); 5349 } else { 5350 var canvas = document.createElement('canvas'); 5351 canvas.width = 60; 5352 canvas.height = 60; 5353 5354 var img = new Image(); 5355 var ctx = canvas.getContext('2d'); 5356 ctx.drawImage(img, 0, 0, canvas.width, canvas.height); 5357 5358 canvas.toBlob(function(blob) { 5359 var newImage = document.createElement('img'); 5360 newImage.src = window.URL.createObjectURL(blob); 5361 newImage.title = data.name; 5362 newImage.className = 'jfile pdf'; 5363 5364 files[newImage.src] = { 5365 file: newImage.src, 5366 extension: 'pdf', 5367 content: data.result, 5368 } 5369 5370 //insertNodeAtCaret(newImage); 5371 document.execCommand('insertHtml', false, newImage.outerHTML); 5372 }); 5373 } 5374 } 5375 5376 obj.addImage = function(src, asSnippet) { 5377 if (! src) { 5378 src = ''; 5379 } 5380 5381 if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) { 5382 console.error('remoteParser not defined in your initialization'); 5383 } else { 5384 // This is to process cross domain images 5385 if (src.substr(0,4) == 'data') { 5386 var extension = src.split(';') 5387 extension = extension[0].split('/'); 5388 extension = extension[1]; 5389 } else { 5390 var extension = src.substr(src.lastIndexOf('.') + 1); 5391 // Work for cross browsers 5392 src = obj.options.remoteParser + src; 5393 } 5394 5395 var img = new Image(); 5396 5397 img.onload = function onload() { 5398 var canvas = document.createElement('canvas'); 5399 canvas.width = img.width; 5400 canvas.height = img.height; 5401 5402 var ctx = canvas.getContext('2d'); 5403 ctx.drawImage(img, 0, 0, canvas.width, canvas.height); 5404 5405 canvas.toBlob(function(blob) { 5406 var newImage = document.createElement('img'); 5407 newImage.src = window.URL.createObjectURL(blob); 5408 newImage.classList.add('jfile'); 5409 newImage.setAttribute('tabindex', '900'); 5410 newImage.setAttribute('width', img.width); 5411 newImage.setAttribute('height', img.height); 5412 files[newImage.src] = { 5413 file: newImage.src, 5414 extension: extension, 5415 content: canvas.toDataURL(), 5416 } 5417 5418 if (obj.options.dropAsSnippet || asSnippet) { 5419 appendImage(newImage); 5420 // Just to understand the attachment is part of a snippet 5421 files[newImage.src].snippet = true; 5422 } else { 5423 //insertNodeAtCaret(newImage); 5424 document.execCommand('insertHtml', false, newImage.outerHTML); 5425 } 5426 5427 change(); 5428 }); 5429 }; 5430 5431 img.src = src; 5432 } 5433 } 5434 5435 obj.addFile = function(files) { 5436 var reader = []; 5437 5438 for (var i = 0; i < files.length; i++) { 5439 if (files[i].size > obj.options.maxFileSize) { 5440 alert('The file is too big'); 5441 } else { 5442 // Only PDF or Images 5443 var type = files[i].type.split('/'); 5444 5445 if (type[0] == 'image') { 5446 type = 1; 5447 } else if (type[1] == 'pdf') { 5448 type = 2; 5449 } else { 5450 type = 0; 5451 } 5452 5453 if (type) { 5454 // Create file 5455 reader[i] = new FileReader(); 5456 reader[i].index = i; 5457 reader[i].type = type; 5458 reader[i].name = files[i].name; 5459 reader[i].date = files[i].lastModified; 5460 reader[i].size = files[i].size; 5461 reader[i].addEventListener("load", function (data) { 5462 // Get result 5463 if (data.target.type == 2) { 5464 if (obj.options.acceptFiles == true) { 5465 obj.addPdf(data.target); 5466 } 5467 } else { 5468 obj.addImage(data.target.result); 5469 } 5470 }, false); 5471 5472 reader[i].readAsDataURL(files[i]) 5473 } else { 5474 alert('The extension is not allowed'); 5475 } 5476 } 5477 } 5478 } 5479 5480 // Destroy 5481 obj.destroy = function() { 5482 obj.editor.removeEventListener('mouseup', editorMouseUp); 5483 obj.editor.removeEventListener('mousedown', editorMouseDown); 5484 obj.editor.removeEventListener('mousemove', editorMouseMove); 5485 obj.editor.removeEventListener('keyup', editorKeyUp); 5486 obj.editor.removeEventListener('keydown', editorKeyDown); 5487 obj.editor.removeEventListener('dragstart', editorDragStart); 5488 obj.editor.removeEventListener('dragenter', editorDragEnter); 5489 obj.editor.removeEventListener('dragover', editorDragOver); 5490 obj.editor.removeEventListener('drop', editorDrop); 5491 obj.editor.removeEventListener('paste', editorPaste); 5492 obj.editor.removeEventListener('blur', editorBlur); 5493 obj.editor.removeEventListener('focus', editorFocus); 5494 5495 el.editor = null; 5496 el.classList.remove('jeditor-container'); 5497 5498 toolbar.remove(); 5499 snippet.remove(); 5500 obj.editor.remove(); 5501 } 5502 5503 obj.upload = function() { 5504 jSuites.click(obj.file); 5505 } 5506 5507 // Elements to be removed 5508 var remove = [ 5509 HTMLUnknownElement, 5510 HTMLAudioElement, 5511 HTMLEmbedElement, 5512 HTMLIFrameElement, 5513 HTMLTextAreaElement, 5514 HTMLInputElement, 5515 HTMLScriptElement 5516 ]; 5517 5518 // Valid properties
5519 var validProperty = ['width', 'height', 'align', 'border', 'src', 'tabindex']; 5520 5521 // Valid CSS attributes 5522 var validStyle = ['color', 'font-weight', 'font-size', 'background', 'background-color', 'margin']; 5523 5524 var parse = function(element) { 5525 // Remove attributes 5526 if (element.attributes && element.attributes.length) { 5527 var image = null; 5528 var style = null; 5529 // Process style attribute 5530 var elementStyle = element.getAttribute('style'); 5531 if (elementStyle) { 5532 style = []; 5533 var t = elementStyle.split(';'); 5534 for (var j = 0; j < t.length; j++) { 5535 var v = t[j].trim().split(':'); 5536 if (validStyle.indexOf(v[0].trim()) >= 0) { 5537 var k = v.shift(); 5538 var v = v.join(':'); 5539 style.push(k + ':' + v); 5540 } 5541 } 5542 } 5543 // Process image 5544 if (element.tagName.toUpperCase() == 'IMG') { 5545 if (! obj.options.acceptImages || ! element.src) { 5546 element.parentNode.removeChild(element); 5547 } else { 5548 // Check if is data 5549 element.setAttribute('tabindex', '900'); 5550 // Check attributes for persistance 5551 obj.addImage(element.src); 5552 } 5553 } 5554 // Remove attributes 5555 var attr = []; 5556 var numAttributes = element.attributes.length - 1; 5557 if (numAttributes > 0) { 5558 for (var i = numAttributes; i >= 0 ; i--) { 5559 attr.push(element.attributes[i].name); 5560 } 5561 attr.forEach(function(v) { 5562 if (validProperty.indexOf(v) == -1) { 5563 element.removeAttribute(v); 5564 } 5565 }); 5566 } 5567 element.style = ''; 5568 // Add valid style 5569 if (style && style.length) { 5570 element.setAttribute('style', style.join(';')); 5571 } 5572 } 5573 // Parse children 5574 if (element.children.length) { 5575 for (var i = 0; i < element.children.length; i++) { 5576 parse(element.children[i]); 5577 } 5578 } 5579 5580 if (remove.indexOf(element.constructor) >= 0) { 5581 element.remove(); 5582 } 5583 } 5584 5585 var select = function(e) { 5586 var s = window.getSelection() 5587 var r = document.createRange(); 5588 r.selectNode(e); 5589 s.addRange(r) 5590 } 5591 5592 var filter = function(data) { 5593 if (data) { 5594 data = data.replace(new RegExp('<!--(.*?)-->', 'gsi'), ''); 5595 } 5596 var parser = new DOMParser(); 5597 var d = parser.parseFromString(data, "text/html"); 5598 parse(d); 5599 var span = document.createElement('span'); 5600 span.innerHTML = d.firstChild.innerHTML; 5601 return span; 5602 } 5603 5604 var editorPaste = function(e) { 5605 if (obj.options.filterPaste == true) { 5606 if (e.clipboardData || e.originalEvent.clipboardData) { 5607 var html = (e.originalEvent || e).clipboardData.getData('text/html'); 5608 var text = (e.originalEvent || e).clipboardData.getData('text/plain'); 5609 var file = (e.originalEvent || e).clipboardData.files 5610 } else if (window.clipboardData) { 5611 var html = window.clipboardData.getData('Html'); 5612 var text = window.clipboardData.getData('Text'); 5613 var file = window.clipboardData.files 5614 } 5615 5616 if (file.length) { 5617 // Paste a image from the clipboard 5618 obj.addFile(file); 5619 } else { 5620 if (! html) { 5621 html = text.split('\r\n'); 5622 if (! e.target.innerText) { 5623 html.map(function(v) { 5624 var d = document.createElement('div'); 5625 d.innerText = v; 5626 obj.editor.appendChild(d); 5627 }); 5628 } else { 5629 html = html.map(function(v) { 5630 return '<div>' + v + '</div>'; 5631 }); 5632 document.execCommand('insertHtml', false, html.join('')); 5633 } 5634 } else { 5635 var d = filter(html); 5636 // Paste to the editor
vendor: 56,226 bytes, lines 5637-7384
5637 //insertNodeAtCaret(d); 5638 document.execCommand('insertHtml', false, d.innerHTML); 5639 } 5640 } 5641 5642 e.preventDefault(); 5643 } 5644 } 5645 5646 var editorDragStart = function(e) { 5647 if (editorAction && editorAction.e) { 5648 e.preventDefault(); 5649 } 5650 } 5651 5652 var editorDragEnter = function(e) { 5653 if (editorAction || obj.options.dropZone == false) { 5654 // Do nothing 5655 } else { 5656 el.classList.add('jeditor-dragging'); 5657 e.preventDefault(); 5658 } 5659 } 5660 5661 var editorDragOver = function(e) { 5662 if (editorAction || obj.options.dropZone == false) { 5663 // Do nothing 5664 } else { 5665 if (editorTimer) { 5666 clearTimeout(editorTimer); 5667 } 5668 5669 editorTimer = setTimeout(function() { 5670 el.classList.remove('jeditor-dragging'); 5671 }, 100); 5672 e.preventDefault(); 5673 } 5674 } 5675 5676 var editorDrop = function(e) { 5677 if (editorAction || obj.options.dropZone == false) { 5678 // Do nothing 5679 } else { 5680 // Position caret on the drop 5681 var range = null; 5682 if (document.caretRangeFromPoint) { 5683 range=document.caretRangeFromPoint(e.clientX, e.clientY); 5684 } else if (e.rangeParent) { 5685 range=document.createRange(); 5686 range.setStart(e.rangeParent,e.rangeOffset); 5687 } 5688 var sel = window.getSelection(); 5689 sel.removeAllRanges(); 5690 sel.addRange(range); 5691 sel.anchorNode.parentNode.focus(); 5692 5693 var html = (e.originalEvent || e).dataTransfer.getData('text/html'); 5694 var text = (e.originalEvent || e).dataTransfer.getData('text/plain'); 5695 var file = (e.originalEvent || e).dataTransfer.files; 5696 5697 if (file.length) { 5698 obj.addFile(file); 5699 } else if (text) { 5700 extractImageFromHtml(html); 5701 } 5702 5703 el.classList.remove('jeditor-dragging'); 5704 e.preventDefault(); 5705 } 5706 } 5707 5708 var editorBlur = function(e) { 5709 // Process extensions 5710 processExtensions('onevent', e); 5711 // Apply changes 5712 change(e); 5713 // Blur 5714 if (typeof(obj.options.onblur) == 'function') { 5715 obj.options.onblur(el, obj, e); 5716 } 5717 } 5718 5719 var editorFocus = function(e) { 5720 // Focus 5721 if (typeof(obj.options.onfocus) == 'function') { 5722 obj.options.onfocus(el, obj, e); 5723 } 5724 } 5725 5726 var editorKeyUp = function(e) { 5727 if (! obj.editor.innerHTML) { 5728 obj.editor.innerHTML = '<div><br></div>'; 5729 } 5730 if (typeof(obj.options.onkeyup) == 'function') { 5731 obj.options.onkeyup(el, obj, e); 5732 } 5733 } 5734 5735 var editorKeyDown = function(e) { 5736 // Process extensions 5737 processExtensions('onevent', e); 5738 5739 if (e.key == 'Delete') { 5740 if (e.target.tagName == 'IMG') { 5741 var parent = e.target.parentNode; 5742 select(e.target); 5743 if (parent.classList.contains('jsnippet-image')) { 5744 updateTotalImages(); 5745 } 5746 } 5747 } 5748 5749 if (typeof(obj.options.onkeydown) == 'function') { 5750 obj.options.onkeydown(el, obj, e); 5751 } 5752 } 5753 5754 var editorMouseUp = function(e) { 5755 if (editorAction && editorAction.e) { 5756 editorAction.e.classList.remove('resizing'); 5757 5758 if (editorAction.e.changed == true) { 5759 var image = editorAction.e.cloneNode() 5760 image.width = parseInt(editorAction.e.style.width) || editorAction.e.getAttribute('width'); 5761 image.height = parseInt(editorAction.e.style.height) || editorAction.e.getAttribute('height'); 5762 editorAction.e.style.width = ''; 5763 editorAction.e.style.height = ''; 5764 select(editorAction.e); 5765 document.execCommand('insertHtml', false, image.outerHTML); 5766 } 5767 } 5768 5769 editorAction = false; 5770 } 5771 5772 var editorMouseDown = function(e) { 5773 var close = function(snippet) { 5774 var rect = snippet.getBoundingClientRect(); 5775 if (rect.width - (e.clientX - rect.left) < 40 && e.clientY - rect.top < 40) { 5776 snippet.innerHTML = ''; 5777 snippet.remove(); 5778 } 5779 } 5780 5781 if (e.target.tagName == 'IMG') { 5782 if (e.target.style.cursor) { 5783 var rect = e.target.getBoundingClientRect(); 5784 editorAction = { 5785 e: e.target, 5786 x: e.clientX, 5787 y: e.clientY, 5788 w: rect.width, 5789 h: rect.height, 5790 d: e.target.style.cursor, 5791 } 5792 5793 if (! e.target.getAttribute('width')) { 5794 e.target.setAttribute('width', rect.width) 5795 } 5796 5797 if (! e.target.getAttribute('height')) { 5798 e.target.setAttribute('height', rect.height) 5799 } 5800 5801 var s = window.getSelection(); 5802 if (s.rangeCount) { 5803 for (var i = 0; i < s.rangeCount; i++) { 5804 s.removeRange(s.getRangeAt(i)); 5805 } 5806 } 5807 5808 e.target.classList.add('resizing'); 5809 } else { 5810 editorAction = true; 5811 } 5812 } else { 5813 if (e.target.classList.contains('jsnippet')) { 5814 close(e.target); 5815 } else if (e.target.parentNode.classList.contains('jsnippet')) { 5816 close(e.target.parentNode); 5817 } 5818 5819 editorAction = true; 5820 } 5821 } 5822 5823 var editorMouseMove = function(e) { 5824 if (e.target.tagName == 'IMG' && ! e.target.parentNode.classList.contains('jsnippet-image') && obj.options.allowImageResize == true) { 5825 if (e.target.getAttribute('tabindex')) { 5826 var rect = e.target.getBoundingClientRect(); 5827 if (e.clientY - rect.top < 5) { 5828 if (rect.width - (e.clientX - rect.left) < 5) { 5829 e.target.style.cursor = 'ne-resize'; 5830 } else if (e.clientX - rect.left < 5) { 5831 e.target.style.cursor = 'nw-resize'; 5832 } else { 5833 e.target.style.cursor = 'n-resize'; 5834 } 5835 } else if (rect.height - (e.clientY - rect.top) < 5) { 5836 if (rect.width - (e.clientX - rect.left) < 5) { 5837 e.target.style.cursor = 'se-resize'; 5838 } else if (e.clientX - rect.left < 5) { 5839 e.target.style.cursor = 'sw-resize'; 5840 } else { 5841 e.target.style.cursor = 's-resize'; 5842 } 5843 } else if (rect.width - (e.clientX - rect.left) < 5) { 5844 e.target.style.cursor = 'e-resize'; 5845 } else if (e.clientX - rect.left < 5) { 5846 e.target.style.cursor = 'w-resize'; 5847 } else { 5848 e.target.style.cursor = ''; 5849 } 5850 } 5851 } 5852 5853 // Move 5854 if (e.which == 1 && editorAction && editorAction.d) { 5855 if (editorAction.d == 'e-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'se-resize') { 5856 editorAction.e.style.width = (editorAction.w + (e.clientX - editorAction.x)); 5857 5858 if (e.shiftKey) { 5859 var newHeight = (e.clientX - editorAction.x) * (editorAction.h / editorAction.w); 5860 editorAction.e.style.height = editorAction.h + newHeight; 5861 } else { 5862 var newHeight = null; 5863 } 5864 } 5865 5866 if (! newHeight) { 5867 if (editorAction.d == 's-resize' || editorAction.d == 'se-resize' || editorAction.d == 'sw-resize') { 5868 if (! e.shiftKey) { 5869 editorAction.e.style.height = editorAction.h + (e.clientY - editorAction.y); 5870 } 5871 } 5872 } 5873 5874 editorAction.e.changed = true; 5875 } 5876 } 5877 5878 var processExtensions = function(method, data) { 5879 if (obj.options.extensions) { 5880 var ext = Object.keys(obj.options.extensions); 5881 if (ext.length) { 5882 for (var i = 0; i < ext.length; i++) 5883 if (obj.options.extensions[ext[i]] && typeof(obj.options.extensions[ext[i]][method]) == 'function') { 5884 obj.options.extensions[ext[i]][method].call(obj, data); 5885 } 5886 } 5887 } 5888 } 5889 5890 var loadExtensions = function() { 5891 if (obj.options.extensions) { 5892 var ext = Object.keys(obj.options.extensions); 5893 if (ext.length) { 5894 for (var i = 0; i < ext.length; i++) { 5895 if (obj.options.extensions[ext[i]] && typeof (obj.options.extensions[ext[i]]) == 'function') { 5896 obj.options.extensions[ext[i]] = obj.options.extensions[ext[i]](el, obj); 5897 } 5898 } 5899 } 5900 } 5901 } 5902 5903 document.addEventListener('mouseup', editorMouseUp); 5904 document.addEventListener('mousemove', editorMouseMove); 5905 obj.editor.addEventListener('mousedown', editorMouseDown); 5906 obj.editor.addEventListener('keyup', editorKeyUp); 5907 obj.editor.addEventListener('keydown', editorKeyDown); 5908 obj.editor.addEventListener('dragstart', editorDragStart); 5909 obj.editor.addEventListener('dragenter', editorDragEnter); 5910 obj.editor.addEventListener('dragover', editorDragOver); 5911 obj.editor.addEventListener('drop', editorDrop); 5912 obj.editor.addEventListener('paste', editorPaste); 5913 obj.editor.addEventListener('focus', editorFocus); 5914 obj.editor.addEventListener('blur', editorBlur); 5915 5916 // Append editor to the container 5917 el.appendChild(obj.editor); 5918 // Snippet 5919 if (obj.options.snippet) { 5920 obj.appendSnippet(obj.options.snippet); 5921 } 5922 5923 // Add toolbar 5924 if (obj.options.toolbar) { 5925 // Default toolbar configuration 5926 if (Array.isArray(obj.options.toolbar)) { 5927 var toolbarOptions = { 5928 container: true, 5929 responsive: true, 5930 items: obj.options.toolbar 5931 } 5932 } else if (obj.options.toolbar === true) { 5933 var toolbarOptions = { 5934 container: true, 5935 responsive: true, 5936 items: [], 5937 } 5938 } else { 5939 var toolbarOptions = obj.options.toolbar; 5940 } 5941 5942 // Default items 5943 if (! (toolbarOptions.items && toolbarOptions.items.length)) { 5944 toolbarOptions.items = jSuites.editor.getDefaultToolbar(obj); 5945 } 5946 5947 if (obj.options.toolbarOnTop) { 5948 // Add class 5949 el.classList.add('toolbar-on-top'); 5950 // Append to the DOM 5951 el.insertBefore(toolbar, el.firstChild); 5952 } else { 5953 // Add padding to the editor 5954 obj.editor.style.padding = '15px'; 5955 // Append to the DOM 5956 el.appendChild(toolbar); 5957 } 5958 5959 // Create toolbar 5960 jSuites.toolbar(toolbar, toolbarOptions); 5961 5962 toolbar.addEventListener('click', function() { 5963 obj.editor.focus(); 5964 }) 5965 } 5966 5967 // Upload file 5968 obj.file = document.createElement('input'); 5969 obj.file.style.display = 'none'; 5970 obj.file.type = 'file'; 5971 obj.file.setAttribute('accept', 'image/*'); 5972 obj.file.onchange = function() { 5973 obj.addFile(this.files); 5974 } 5975 el.appendChild(obj.file); 5976 5977 // Focus to the editor 5978 if (obj.editor.innerHTML && obj.options.focus) { 5979 jSuites.editor.setCursor(obj.editor, obj.options.focus == 'initial' ? true : false); 5980 } 5981 5982 // Change method 5983 el.change = obj.setData; 5984 5985 // Global generic value handler 5986 el.val = function(val) { 5987 if (val === undefined) { 5988 // Data type 5989 var o = el.getAttribute('data-html') === 'true' ? false : true; 5990 return obj.getData(o); 5991 } else { 5992 obj.setData(val); 5993 } 5994 } 5995 5996 loadExtensions(); 5997 5998 el.editor = obj; 5999 6000 // Onload 6001 if (typeof(obj.options.onload) == 'function') { 6002 obj.options.onload(el, obj, obj.editor); 6003 } 6004 6005 return obj; 6006}); 6007 6008jSuites.editor.setCursor = function(element, first) { 6009 element.focus(); 6010 document.execCommand('selectAll'); 6011 var sel = window.getSelection(); 6012 var range = sel.getRangeAt(0); 6013 if (first == true) { 6014 var node = range.startContainer; 6015 var size = 0; 6016 } else { 6017 var node = range.endContainer; 6018 var size = node.length; 6019 } 6020 range.setStart(node, size); 6021 range.setEnd(node, size); 6022 sel.removeAllRanges(); 6023 sel.addRange(range); 6024} 6025 6026jSuites.editor.getDefaultToolbar = function(obj) { 6027 6028 var color = function(a,b,c) { 6029 if (! c.color) { 6030 var t = null; 6031 var colorPicker = jSuites.color(c, { 6032 onchange: function(o, v) { 6033 if (c.k === 'color') { 6034 document.execCommand('foreColor', false, v); 6035 } else { 6036 document.execCommand('backColor', false, v); 6037 } 6038 } 6039 }); 6040 c.color.open(); 6041 } 6042 } 6043 6044 var items = []; 6045 6046 items.push({ 6047 content: 'undo', 6048 onclick: function() { 6049 document.execCommand('undo'); 6050 } 6051 }); 6052 6053 items.push({ 6054 content: 'redo', 6055 onclick: function() { 6056 document.execCommand('redo'); 6057 } 6058 }); 6059 6060 items.push({ 6061 type: 'divisor' 6062 }); 6063 6064 if (obj.options.toolbarOnTop) { 6065 items.push({ 6066 type: 'select', 6067 width: '140px', 6068 options: ['Default', 'Verdana', 'Arial', 'Courier New'], 6069 render: function (e) { 6070 return '<span style="font-family:' + e + '">' + e + '</span>'; 6071 }, 6072 onchange: function (a,b,c,d,e) { 6073 document.execCommand("fontName", false, d); 6074 } 6075 }); 6076 6077 items.push({ 6078 type: 'select', 6079 content: 'format_size', 6080 options: ['x-small', 'small', 'medium', 'large', 'x-large'], 6081 render: function (e) { 6082 return '<span style="font-size:' + e + '">' + e + '</span>'; 6083 }, 6084 onchange: function (a,b,c,d,e) { 6085 //var html = `<span style="font-size: ${c}">${text}</span>`; 6086 //document.execCommand('insertHtml', false, html); 6087 document.execCommand("fontSize", false, parseInt(e)+1); 6088 //var f = window.getSelection().anchorNode.parentNode 6089 //f.removeAttribute("size"); 6090 //f.style.fontSize = d; 6091 } 6092 }); 6093 6094 items.push({ 6095 type: 'select', 6096 options: ['format_align_left', 'format_align_center', 'format_align_right', 'format_align_justify'], 6097 render: function (e) { 6098 return '<i class="material-icons">' + e + '</i>'; 6099 }, 6100 onchange: function (a,b,c,d,e) { 6101 var options = ['JustifyLeft','justifyCenter','justifyRight','justifyFull']; 6102 document.execCommand(options[e]); 6103 } 6104 }); 6105 6106 items.push({ 6107 type: 'divisor' 6108 }); 6109 6110 items.push({ 6111 content: 'format_color_text', 6112 k: 'color', 6113 onclick: color, 6114 }); 6115 6116 items.push({ 6117 content: 'format_color_fill', 6118 k: 'background-color', 6119 onclick: color, 6120 }); 6121 } 6122 6123 items.push({ 6124 content: 'format_bold', 6125 onclick: function(a,b,c) { 6126 document.execCommand('bold'); 6127 6128 if (document.queryCommandState("bold")) { 6129 c.classList.add('selected'); 6130 } else { 6131 c.classList.remove('selected'); 6132 } 6133 } 6134 }); 6135 6136 items.push({ 6137 content: 'format_italic', 6138 onclick: function(a,b,c) { 6139 document.execCommand('italic'); 6140 6141 if (document.queryCommandState("italic")) { 6142 c.classList.add('selected'); 6143 } else { 6144 c.classList.remove('selected'); 6145 } 6146 } 6147 }); 6148 6149 items.push({ 6150 content: 'format_underline', 6151 onclick: function(a,b,c) { 6152 document.execCommand('underline'); 6153 6154 if (document.queryCommandState("underline")) { 6155 c.classList.add('selected'); 6156 } else { 6157 c.classList.remove('selected'); 6158 } 6159 } 6160 }); 6161 6162 items.push({ 6163 type:'divisor' 6164 }); 6165 6166 items.push({ 6167 content: 'format_list_bulleted', 6168 onclick: function(a,b,c) { 6169 document.execCommand('insertUnorderedList'); 6170 6171 if (document.queryCommandState("insertUnorderedList")) { 6172 c.classList.add('selected'); 6173 } else { 6174 c.classList.remove('selected'); 6175 } 6176 } 6177 }); 6178 6179 items.push({ 6180 content: 'format_list_numbered', 6181 onclick: function(a,b,c) { 6182 document.execCommand('insertOrderedList'); 6183 6184 if (document.queryCommandState("insertOrderedList")) { 6185 c.classList.add('selected'); 6186 } else { 6187 c.classList.remove('selected'); 6188 } 6189 } 6190 }); 6191 6192 items.push({ 6193 content: 'format_indent_increase', 6194 onclick: function(a,b,c) { 6195 document.execCommand('indent', true, null); 6196 6197 if (document.queryCommandState("indent")) { 6198 c.classList.add('selected'); 6199 } else { 6200 c.classList.remove('selected'); 6201 } 6202 } 6203 }); 6204 6205 items.push({ 6206 content: 'format_indent_decrease', 6207 onclick: function() { 6208 document.execCommand('outdent'); 6209 6210 if (document.queryCommandState("outdent")) { 6211 this.classList.add('selected'); 6212 } else { 6213 this.classList.remove('selected'); 6214 } 6215 } 6216 }); 6217 6218 if (obj.options.toolbarOnTop) { 6219 items.push({ 6220 type: 'divisor' 6221 }); 6222 6223 items.push({ 6224 content: 'photo', 6225 onclick: function () { 6226 obj.upload(); 6227 } 6228 }); 6229 6230 items.push({ 6231 type: 'select', 6232 content: 'table_view', 6233 columns: 10, 6234 right: true, 6235 options: [ 6236 '0x0', '1x0', '2x0', '3x0', '4x0', '5x0', '6x0', '7x0', '8x0', '9x0', 6237 '0x1', '1x1', '2x1', '3x1', '4x1', '5x1', '6x1', '7x1', '8x1', '9x1', 6238 '0x2', '1x2', '2x2', '3x2', '4x2', '5x2', '6x2', '7x2', '8x2', '9x2', 6239 '0x3', '1x3', '2x3', '3x3', '4x3', '5x3', '6x3', '7x3', '8x3', '9x3', 6240 '0x4', '1x4', '2x4', '3x4', '4x4', '5x4', '6x4', '7x4', '8x4', '9x4', 6241 '0x5', '1x5', '2x5', '3x5', '4x5', '5x5', '6x5', '7x5', '8x5', '9x5', 6242 '0x6', '1x6', '2x6', '3x6', '4x6', '5x6', '6x6', '7x6', '8x6', '9x6', 6243 '0x7', '1x7', '2x7', '3x7', '4x7', '5x7', '6x7', '7x7', '8x7', '9x7', 6244 '0x8', '1x8', '2x8', '3x8', '4x8', '5x8', '6x8', '7x8', '8x8', '9x8', 6245 '0x9', '1x9', '2x9', '3x9', '4x9', '5x9', '6x9', '7x9', '8x9', '9x9', 6246 ], 6247 render: function (e, item) { 6248 if (item) { 6249 item.onmouseover = this.onmouseover; 6250 e = e.split('x'); 6251 item.setAttribute('data-x', e[0]); 6252 item.setAttribute('data-y', e[1]); 6253 } 6254 var element = document.createElement('div'); 6255 item.style.margin = '1px'; 6256 item.style.border = '1px solid #ddd'; 6257 return element; 6258 }, 6259 onmouseover: function (e) { 6260 var x = parseInt(e.target.getAttribute('data-x')); 6261 var y = parseInt(e.target.getAttribute('data-y')); 6262 for (var i = 0; i < e.target.parentNode.children.length; i++) { 6263 var element = e.target.parentNode.children[i]; 6264 var ex = parseInt(element.getAttribute('data-x')); 6265 var ey = parseInt(element.getAttribute('data-y')); 6266 if (ex <= x && ey <= y) { 6267 element.style.backgroundColor = '#cae1fc'; 6268 element.style.borderColor = '#2977ff'; 6269 } else { 6270 element.style.backgroundColor = ''; 6271 element.style.borderColor = '#ddd'; 6272 } 6273 } 6274 }, 6275 onchange: function (a, b, c) { 6276 c = c.split('x'); 6277 var table = document.createElement('table'); 6278 var tbody = document.createElement('tbody'); 6279 for (var y = 0; y <= c[1]; y++) { 6280 var tr = document.createElement('tr'); 6281 for (var x = 0; x <= c[0]; x++) { 6282 var td = document.createElement('td'); 6283 td.innerHTML = ''; 6284 tr.appendChild(td); 6285 } 6286 tbody.appendChild(tr); 6287 } 6288 table.appendChild(tbody); 6289 table.setAttribute('width', '100%'); 6290 table.setAttribute('cellpadding', '6'); 6291 table.setAttribute('cellspacing', '0'); 6292 document.execCommand('insertHTML', false, table.outerHTML); 6293 } 6294 }); 6295 } 6296 6297 return items; 6298} 6299 6300 6301jSuites.form = (function(el, options) { 6302 var obj = {}; 6303 obj.options = {}; 6304 6305 // Default configuration 6306 var defaults = { 6307 url: null, 6308 message: 'Are you sure? There are unsaved information in your form', 6309 ignore: false, 6310 currentHash: null, 6311 submitButton:null, 6312 validations: null, 6313 onbeforeload: null, 6314 onload: null, 6315 onbeforesave: null, 6316 onsave: null, 6317 onbeforeremove: null, 6318 onremove: null, 6319 onerror: function(el, message) { 6320 jSuites.alert(message); 6321 } 6322 }; 6323 6324 // Loop through our object 6325 for (var property in defaults) { 6326 if (options && options.hasOwnProperty(property)) { 6327 obj.options[property] = options[property]; 6328 } else { 6329 obj.options[property] = defaults[property]; 6330 } 6331 } 6332 6333 // Validations 6334 if (! obj.options.validations) { 6335 obj.options.validations = {}; 6336 } 6337 6338 // Submit Button 6339 if (! obj.options.submitButton) { 6340 obj.options.submitButton = el.querySelector('input[type=submit]'); 6341 } 6342 6343 if (obj.options.submitButton && obj.options.url) { 6344 obj.options.submitButton.onclick = function() { 6345 obj.save(); 6346 } 6347 } 6348 6349 if (! obj.options.validations.email) { 6350 obj.options.validations.email = jSuites.validations.email; 6351 } 6352 6353 if (! obj.options.validations.length) { 6354 obj.options.validations.length = jSuites.validations.length; 6355 } 6356 6357 if (! obj.options.validations.required) { 6358 obj.options.validations.required = jSuites.validations.required; 6359 } 6360 6361 obj.setUrl = function(url) { 6362 obj.options.url = url; 6363 } 6364 6365 obj.load = function() { 6366 jSuites.ajax({ 6367 url: obj.options.url, 6368 method: 'GET', 6369 dataType: 'json', 6370 queue: true, 6371 success: function(data) { 6372 // Overwrite values from the backend 6373 if (typeof(obj.options.onbeforeload) == 'function') { 6374 var ret = obj.options.onbeforeload(el, data); 6375 if (ret) { 6376 data = ret; 6377 } 6378 } 6379 // Apply values to the form 6380 jSuites.form.setElements(el, data); 6381 // Onload methods 6382 if (typeof(obj.options.onload) == 'function') { 6383 obj.options.onload(el, data); 6384 } 6385 } 6386 }); 6387 } 6388 6389 obj.save = function() { 6390 var test = obj.validate(); 6391 6392 if (test) { 6393 obj.options.onerror(el, test); 6394 } else { 6395 var data = jSuites.form.getElements(el, true); 6396 6397 if (typeof(obj.options.onbeforesave) == 'function') { 6398 var data = obj.options.onbeforesave(el, data); 6399 6400 if (data === false) { 6401 return; 6402 } 6403 } 6404 6405 jSuites.ajax({ 6406 url: obj.options.url, 6407 method: 'POST', 6408 dataType: 'json', 6409 data: data, 6410 success: function(result) { 6411 if (typeof(obj.options.onsave) == 'function') { 6412 obj.options.onsave(el, data, result); 6413 } 6414 } 6415 }); 6416 } 6417 } 6418 6419 obj.remove = function() { 6420 if (typeof(obj.options.onbeforeremove) == 'function') { 6421 var ret = obj.options.onbeforeremove(el, obj); 6422 if (ret === false) { 6423 return false; 6424 } 6425 } 6426 6427 jSuites.ajax({ 6428 url: obj.options.url, 6429 method: 'DELETE', 6430 dataType: 'json', 6431 success: function(result) { 6432 if (typeof(obj.options.onremove) == 'function') { 6433 obj.options.onremove(el, obj, result); 6434 } 6435 6436 obj.reset(); 6437 } 6438 }); 6439 } 6440 6441 var addError = function(element) { 6442 // Add error in the element 6443 element.classList.add('error'); 6444 // Submit button 6445 if (obj.options.submitButton) { 6446 obj.options.submitButton.setAttribute('disabled', true); 6447 } 6448 // Return error message 6449 var error = element.getAttribute('data-error') || 'There is an error in the form'; 6450 element.setAttribute('title', error); 6451 return error; 6452 } 6453 6454 var delError = function(element) { 6455 var error = false; 6456 // Remove class from this element 6457 element.classList.remove('error'); 6458 element.removeAttribute('title'); 6459 // Get elements in the form 6460 var elements = el.querySelectorAll("input, select, textarea, div[name]"); 6461 // Run all elements 6462 for (var i = 0; i < elements.length; i++) { 6463 if (elements[i].getAttribute('data-validation')) { 6464 if (elements[i].classList.contains('error')) { 6465 error = true; 6466 } 6467 } 6468 } 6469 6470 if (obj.options.submitButton) { 6471 if (error) { 6472 obj.options.submitButton.setAttribute('disabled', true); 6473 } else { 6474 obj.options.submitButton.removeAttribute('disabled'); 6475 } 6476 } 6477 } 6478 6479 obj.validateElement = function(element) { 6480 // Test results 6481 var test = false; 6482 // Value 6483 var value = jSuites.form.getValue(element); 6484 // Validation 6485 var validation = element.getAttribute('data-validation'); 6486 // Parse 6487 if (typeof(obj.options.validations[validation]) == 'function' && ! obj.options.validations[validation](value, element)) { 6488 // Not passed in the test 6489 test = addError(element); 6490 } else { 6491 if (element.classList.contains('error')) { 6492 delError(element); 6493 } 6494 } 6495 6496 return test; 6497 } 6498 6499 obj.reset = function() { 6500 // Get elements in the form 6501 var name = null; 6502 var elements = el.querySelectorAll("input, select, textarea, div[name]"); 6503 // Run all elements 6504 for (var i = 0; i < elements.length; i++) { 6505 if (name = elements[i].getAttribute('name')) { 6506 if (elements[i].type == 'checkbox' || elements[i].type == 'radio') { 6507 elements[i].checked = false; 6508 } else { 6509 if (typeof(elements[i].val) == 'function') { 6510 elements[i].val(''); 6511 } else { 6512 elements[i].value = ''; 6513 } 6514 } 6515 } 6516 } 6517 } 6518 6519 // Run form validation 6520 obj.validate = function() { 6521 var test = []; 6522 // Get elements in the form 6523 var elements = el.querySelectorAll("input, select, textarea, div[name]"); 6524 // Run all elements 6525 for (var i = 0; i < elements.length; i++) { 6526 // Required 6527 if (elements[i].getAttribute('data-validation')) { 6528 var res = obj.validateElement(elements[i]); 6529 if (res) { 6530 test.push(res); 6531 } 6532 } 6533 } 6534 if (test.length > 0) { 6535 return test.join('<br>'); 6536 } else { 6537 return false; 6538 } 6539 } 6540 6541 // Check the form 6542 obj.getError = function() { 6543 // Validation 6544 return obj.validation() ? true : false; 6545 } 6546 6547 // Return the form hash 6548 obj.setHash = function() { 6549 return obj.getHash(jSuites.form.getElements(el)); 6550 } 6551 6552 // Get the form hash 6553 obj.getHash = function(str) { 6554 var hash = 0, i, chr; 6555 6556 if (str.length === 0) { 6557 return hash; 6558 } else { 6559 for (i = 0; i < str.length; i++) { 6560 chr = str.charCodeAt(i); 6561 hash = ((hash << 5) - hash) + chr; 6562 hash |= 0; 6563 } 6564 } 6565 6566 return hash; 6567 } 6568 6569 // Is there any change in the form since start tracking? 6570 obj.isChanged = function() { 6571 var hash = obj.setHash(); 6572 return (obj.options.currentHash != hash); 6573 } 6574 6575 // Restart tracking 6576 obj.resetTracker = function() { 6577 obj.options.currentHash = obj.setHash(); 6578 obj.options.ignore = false; 6579 } 6580 6581 // Ignore flag 6582 obj.setIgnore = function(ignoreFlag) { 6583 obj.options.ignore = ignoreFlag ? true : false; 6584 } 6585 6586 // Start tracking in one second 6587 setTimeout(function() { 6588 obj.options.currentHash = obj.setHash(); 6589 }, 1000); 6590 6591 // Validations 6592 el.addEventListener("keyup", function(e) { 6593 if (e.target.getAttribute('data-validation')) { 6594 obj.validateElement(e.target); 6595 } 6596 }); 6597 6598 // Alert 6599 if (! jSuites.form.hasEvents) { 6600 window.addEventListener("beforeunload", function (e) { 6601 if (obj.isChanged() && obj.options.ignore == false) { 6602 var confirmationMessage = obj.options.message? obj.options.message : "\o/"; 6603 6604 if (confirmationMessage) { 6605 if (typeof e == 'undefined') { 6606 e = window.event; 6607 } 6608 6609 if (e) { 6610 e.returnValue = confirmationMessage; 6611 } 6612 6613 return confirmationMessage; 6614 } else { 6615 return void(0); 6616 } 6617 } 6618 }); 6619 6620 jSuites.form.hasEvents = true; 6621 } 6622 6623 el.form = obj; 6624 6625 return obj; 6626}); 6627 6628// Get value from one element 6629jSuites.form.getValue = function(element) { 6630 var value = null; 6631 if (element.type == 'checkbox') { 6632 if (element.checked == true) { 6633 value = element.value || true; 6634 } 6635 } else if (element.type == 'radio') { 6636 if (element.checked == true) { 6637 value = element.value; 6638 } 6639 } else if (element.type == 'file') { 6640 value = element.files; 6641 } else if (element.tagName == 'select' && element.multiple == true) { 6642 value = []; 6643 var options = element.querySelectorAll("options[selected]"); 6644 for (var j = 0; j < options.length; j++) { 6645 value.push(options[j].value); 6646 } 6647 } else if (typeof(element.val) == 'function') { 6648 value = element.val(); 6649 } else { 6650 value = element.value || ''; 6651 } 6652 6653 return value; 6654} 6655 6656// Get form elements 6657jSuites.form.getElements = function(el, asArray) { 6658 var data = {}; 6659 var name = null; 6660 var elements = el.querySelectorAll("input, select, textarea, div[name]"); 6661 6662 for (var i = 0; i < elements.length; i++) { 6663 if (name = elements[i].getAttribute('name')) { 6664 data[name] = jSuites.form.getValue(elements[i]) || ''; 6665 } 6666 } 6667 6668 return asArray == true ? data : JSON.stringify(data); 6669} 6670 6671//Get form elements 6672jSuites.form.setElements = function(el, data) { 6673 var name = null; 6674 var value = null; 6675 var elements = el.querySelectorAll("input, select, textarea, div[name]"); 6676 for (var i = 0; i < elements.length; i++) { 6677 // Attributes 6678 var type = elements[i].getAttribute('type'); 6679 if (name = elements[i].getAttribute('name')) { 6680 // Transform variable names in pathname 6681 name = name.replace(new RegExp(/\[(.*?)\]/ig), '.$1'); 6682 value = null; 6683 // Seach for the data in the path 6684 if (name.match(/\./)) { 6685 var tmp = jSuites.path.call(data, name) || ''; 6686 if (typeof(tmp) !== 'undefined') { 6687 value = tmp; 6688 } 6689 } else { 6690 if (typeof(data[name]) !== 'undefined') { 6691 value = data[name]; 6692 } 6693 } 6694 // Set the values 6695 if (value !== null) { 6696 if (type == 'checkbox' || type == 'radio') { 6697 elements[i].checked = value ? true : false; 6698 } else if (type == 'file') { 6699 // Do nothing 6700 } else { 6701 if (typeof (elements[i].val) == 'function') { 6702 elements[i].val(value); 6703 } else { 6704 elements[i].value = value; 6705 } 6706 } 6707 } 6708 } 6709 } 6710} 6711 6712// Legacy 6713jSuites.tracker = jSuites.form; 6714 6715jSuites.focus = function(el) { 6716 if (el.innerText.length) { 6717 var range = document.createRange(); 6718 var sel = window.getSelection(); 6719 var node = el.childNodes[el.childNodes.length-1]; 6720 range.setStart(node, node.length) 6721 range.collapse(true) 6722 sel.removeAllRanges() 6723 sel.addRange(range) 6724 el.scrollLeft = el.scrollWidth; 6725 } 6726} 6727 6728jSuites.isNumeric = (function (num) { 6729 if (typeof(num) === 'string') { 6730 num = num.trim(); 6731 } 6732 return !isNaN(num) && num !== null && num !== ''; 6733}); 6734 6735jSuites.guid = function() { 6736 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { 6737 var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); 6738 return v.toString(16); 6739 }); 6740} 6741 6742jSuites.getNode = function() { 6743 var node = document.getSelection().anchorNode; 6744 if (node) { 6745 return (node.nodeType == 3 ? node.parentNode : node); 6746 } else { 6747 return null; 6748 } 6749} 6750/** 6751 * Generate hash from a string 6752 */ 6753jSuites.hash = function(str) { 6754 var hash = 0, i, chr; 6755 6756 if (str.length === 0) { 6757 return hash; 6758 } else { 6759 for (i = 0; i < str.length; i++) { 6760 chr = str.charCodeAt(i); 6761 if (chr > 32) { 6762 hash = ((hash << 5) - hash) + chr; 6763 hash |= 0; 6764 } 6765 } 6766 } 6767 return hash; 6768} 6769 6770/** 6771 * Generate a random color 6772 */ 6773jSuites.randomColor = function(h) { 6774 var lum = -0.25; 6775 var hex = String('#' + Math.random().toString(16).slice(2, 8).toUpperCase()).replace(/[^0-9a-f]/gi, ''); 6776 if (hex.length < 6) { 6777 hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; 6778 } 6779 var rgb = [], c, i; 6780 for (i = 0; i < 3; i++) { 6781 c = parseInt(hex.substr(i * 2, 2), 16); 6782 c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16); 6783 rgb.push(("00" + c).substr(c.length)); 6784 } 6785 6786 // Return hex 6787 if (h == true) { 6788 return '#' + jSuites.two(rgb[0].toString(16)) + jSuites.two(rgb[1].toString(16)) + jSuites.two(rgb[2].toString(16)); 6789 } 6790 6791 return rgb; 6792} 6793 6794jSuites.getWindowWidth = function() { 6795 var w = window, 6796 d = document, 6797 e = d.documentElement, 6798 g = d.getElementsByTagName('body')[0], 6799 x = w.innerWidth || e.clientWidth || g.clientWidth; 6800 return x; 6801} 6802 6803jSuites.getWindowHeight = function() { 6804 var w = window, 6805 d = document, 6806 e = d.documentElement, 6807 g = d.getElementsByTagName('body')[0], 6808 y = w.innerHeight|| e.clientHeight|| g.clientHeight; 6809 return y; 6810} 6811 6812jSuites.getPosition = function(e) { 6813 if (e.changedTouches && e.changedTouches[0]) { 6814 var x = e.changedTouches[0].pageX; 6815 var y = e.changedTouches[0].pageY; 6816 } else { 6817 var x = (window.Event) ? e.pageX : e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft); 6818 var y = (window.Event) ? e.pageY : e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); 6819 } 6820 6821 return [ x, y ]; 6822} 6823 6824jSuites.click = function(el) { 6825 if (el.click) { 6826 el.click(); 6827 } else { 6828 var evt = new MouseEvent('click', { 6829 bubbles: true, 6830 cancelable: true, 6831 view: window 6832 }); 6833 el.dispatchEvent(evt); 6834 } 6835} 6836 6837jSuites.findElement = function(element, condition) { 6838 var foundElement = false; 6839 6840 function path (element) { 6841 if (element && ! foundElement) { 6842 if (typeof(condition) == 'function') { 6843 foundElement = condition(element) 6844 } else if (typeof(condition) == 'string') { 6845 if (element.classList && element.classList.contains(condition)) { 6846 foundElement = element; 6847 } 6848 } 6849 } 6850 6851 if (element.parentNode && ! foundElement) { 6852 path(element.parentNode); 6853 } 6854 } 6855 6856 path(element); 6857 6858 return foundElement; 6859} 6860 6861// Two digits 6862jSuites.two = function(value) { 6863 value = '' + value; 6864 if (value.length == 1) { 6865 value = '0' + value; 6866 } 6867 return value; 6868} 6869 6870jSuites.sha512 = (function(str) { 6871 function int64(msint_32, lsint_32) { 6872 this.highOrder = msint_32; 6873 this.lowOrder = lsint_32; 6874 } 6875 6876 var H = [new int64(0x6a09e667, 0xf3bcc908), new int64(0xbb67ae85, 0x84caa73b), 6877 new int64(0x3c6ef372, 0xfe94f82b), new int64(0xa54ff53a, 0x5f1d36f1), 6878 new int64(0x510e527f, 0xade682d1), new int64(0x9b05688c, 0x2b3e6c1f), 6879 new int64(0x1f83d9ab, 0xfb41bd6b), new int64(0x5be0cd19, 0x137e2179)]; 6880 6881 var K = [new int64(0x428a2f98, 0xd728ae22), new int64(0x71374491, 0x23ef65cd), 6882 new int64(0xb5c0fbcf, 0xec4d3b2f), new int64(0xe9b5dba5, 0x8189dbbc), 6883 new int64(0x3956c25b, 0xf348b538), new int64(0x59f111f1, 0xb605d019), 6884 new int64(0x923f82a4, 0xaf194f9b), new int64(0xab1c5ed5, 0xda6d8118), 6885 new int64(0xd807aa98, 0xa3030242), new int64(0x12835b01, 0x45706fbe), 6886 new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, 0xd5ffb4e2), 6887 new int64(0x72be5d74, 0xf27b896f), new int64(0x80deb1fe, 0x3b1696b1), 6888 new int64(0x9bdc06a7, 0x25c71235), new int64(0xc19bf174, 0xcf692694), 6889 new int64(0xe49b69c1, 0x9ef14ad2), new int64(0xefbe4786, 0x384f25e3), 6890 new int64(0x0fc19dc6, 0x8b8cd5b5), new int64(0x240ca1cc, 0x77ac9c65), 6891 new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483), 6892 new int64(0x5cb0a9dc, 0xbd41fbd4), new int64(0x76f988da, 0x831153b5), 6893 new int64(0x983e5152, 0xee66dfab), new int64(0xa831c66d, 0x2db43210), 6894 new int64(0xb00327c8, 0x98fb213f), new int64(0xbf597fc7, 0xbeef0ee4), 6895 new int64(0xc6e00bf3, 0x3da88fc2), new int64(0xd5a79147, 0x930aa725), 6896 new int64(0x06ca6351, 0xe003826f), new int64(0x14292967, 0x0a0e6e70), 6897 new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926), 6898 new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, 0x9d95b3df), 6899 new int64(0x650a7354, 0x8baf63de), new int64(0x766a0abb, 0x3c77b2a8), 6900 new int64(0x81c2c92e, 0x47edaee6), new int64(0x92722c85, 0x1482353b), 6901 new int64(0xa2bfe8a1, 0x4cf10364), new int64(0xa81a664b, 0xbc423001), 6902 new int64(0xc24b8b70, 0xd0f89791), new int64(0xc76c51a3, 0x0654be30), 6903 new int64(0xd192e819, 0xd6ef5218), new int64(0xd6990624, 0x5565a910), 6904 new int64(0xf40e3585, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8), 6905 new int64(0x19a4c116, 0xb8d2d0c8), new int64(0x1e376c08, 0x5141ab53), 6906 new int64(0x2748774c, 0xdf8eeb99), new int64(0x34b0bcb5, 0xe19b48a8), 6907 new int64(0x391c0cb3, 0xc5c95a63), new int64(0x4ed8aa4a, 0xe3418acb), 6908 new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, 0xd6b2b8a3), 6909 new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60), 6910 new int64(0x84c87814, 0xa1f0ab72), new int64(0x8cc70208, 0x1a6439ec), 6911 new int64(0x90befffa, 0x23631e28), new int64(0xa4506ceb, 0xde82bde9), 6912 new int64(0xbef9a3f7, 0xb2c67915), new int64(0xc67178f2, 0xe372532b), 6913 new int64(0xca273ece, 0xea26619c), new int64(0xd186b8c7, 0x21c0c207), 6914 new int64(0xeada7dd6, 0xcde0eb1e), new int64(0xf57d4f7f, 0xee6ed178), 6915 new int64(0x06f067aa, 0x72176fba), new int64(0x0a637dc5, 0xa2c898a6), 6916 new int64(0x113f9804, 0xbef90dae), new int64(0x1b710b35, 0x131c471b), 6917 new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493), 6918 new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, 0x9c100d4c), 6919 new int64(0x4cc5d4be, 0xcb3e42b6), new int64(0x597f299c, 0xfc657e2a), 6920 new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)]; 6921 6922 var W = new Array(64); 6923 var a, b, c, d, e, f, g, h, i, j; 6924 var T1, T2; 6925 var charsize = 8; 6926 6927 function utf8_encode(str) { 6928 return unescape(encodeURIComponent(str)); 6929 } 6930 6931 function str2binb(str) { 6932 var bin = []; 6933 var mask = (1 << charsize) - 1; 6934 var len = str.length * charsize; 6935 6936 for (var i = 0; i < len; i += charsize) { 6937 bin[i >> 5] |= (str.charCodeAt(i / charsize) & mask) << (32 - charsize - (i % 32)); 6938 } 6939 6940 return bin; 6941 } 6942 6943 function binb2hex(binarray) { 6944 var hex_tab = "0123456789abcdef"; 6945 var str = ""; 6946 var length = binarray.length * 4; 6947 var srcByte; 6948 6949 for (var i = 0; i < length; i += 1) { 6950 srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8); 6951 str += hex_tab.charAt((srcByte >> 4) & 0xF) + hex_tab.charAt(srcByte & 0xF); 6952 } 6953 6954 return str; 6955 } 6956 6957 function safe_add_2(x, y) { 6958 var lsw, msw, lowOrder, highOrder; 6959 6960 lsw = (x.lowOrder & 0xFFFF) + (y.lowOrder & 0xFFFF); 6961 msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16); 6962 lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 6963 6964 lsw = (x.highOrder & 0xFFFF) + (y.highOrder & 0xFFFF) + (msw >>> 16); 6965 msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16); 6966 highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 6967 6968 return new int64(highOrder, lowOrder); 6969 } 6970 6971 function safe_add_4(a, b, c, d) { 6972 var lsw, msw, lowOrder, highOrder; 6973 6974 lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF); 6975 msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16); 6976 lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 6977 6978 lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (msw >>> 16); 6979 msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16); 6980 highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 6981 6982 return new int64(highOrder, lowOrder); 6983 } 6984 6985 function safe_add_5(a, b, c, d, e) { 6986 var lsw, msw, lowOrder, highOrder; 6987 6988 lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF) + (e.lowOrder & 0xFFFF); 6989 msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (e.lowOrder >>> 16) + (lsw >>> 16); 6990 lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 6991 6992 lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (e.highOrder & 0xFFFF) + (msw >>> 16); 6993 msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (e.highOrder >>> 16) + (lsw >>> 16); 6994 highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 6995 6996 return new int64(highOrder, lowOrder); 6997 } 6998 6999 function maj(x, y, z) { 7000 return new int64( 7001 (x.highOrder & y.highOrder) ^ (x.highOrder & z.highOrder) ^ (y.highOrder & z.highOrder), 7002 (x.lowOrder & y.lowOrder) ^ (x.lowOrder & z.lowOrder) ^ (y.lowOrder & z.lowOrder) 7003 ); 7004 } 7005 7006 function ch(x, y, z) { 7007 return new int64( 7008 (x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder), 7009 (x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder) 7010 ); 7011 } 7012 7013 function rotr(x, n) { 7014 if (n <= 32) { 7015 return new int64( 7016 (x.highOrder >>> n) | (x.lowOrder << (32 - n)), 7017 (x.lowOrder >>> n) | (x.highOrder << (32 - n)) 7018 ); 7019 } else { 7020 return new int64( 7021 (x.lowOrder >>> n) | (x.highOrder << (32 - n)), 7022 (x.highOrder >>> n) | (x.lowOrder << (32 - n)) 7023 ); 7024 } 7025 } 7026 7027 function sigma0(x) { 7028 var rotr28 = rotr(x, 28); 7029 var rotr34 = rotr(x, 34); 7030 var rotr39 = rotr(x, 39); 7031 7032 return new int64( 7033 rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder, 7034 rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder 7035 ); 7036 } 7037 7038 function sigma1(x) { 7039 var rotr14 = rotr(x, 14); 7040 var rotr18 = rotr(x, 18); 7041 var rotr41 = rotr(x, 41); 7042 7043 return new int64( 7044 rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder, 7045 rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder 7046 ); 7047 } 7048 7049 function gamma0(x) { 7050 var rotr1 = rotr(x, 1), rotr8 = rotr(x, 8), shr7 = shr(x, 7); 7051 7052 return new int64( 7053 rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder, 7054 rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder 7055 ); 7056 } 7057 7058 function gamma1(x) { 7059 var rotr19 = rotr(x, 19); 7060 var rotr61 = rotr(x, 61); 7061 var shr6 = shr(x, 6); 7062 7063 return new int64( 7064 rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder, 7065 rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder 7066 ); 7067 } 7068 7069 function shr(x, n) { 7070 if (n <= 32) { 7071 return new int64( 7072 x.highOrder >>> n, 7073 x.lowOrder >>> n | (x.highOrder << (32 - n)) 7074 ); 7075 } else { 7076 return new int64( 7077 0, 7078 x.highOrder << (32 - n) 7079 ); 7080 } 7081 } 7082 7083 var str = utf8_encode(str); 7084 var strlen = str.length*charsize; 7085 str = str2binb(str); 7086 7087 str[strlen >> 5] |= 0x80 << (24 - strlen % 32); 7088 str[(((strlen + 128) >> 10) << 5) + 31] = strlen; 7089 7090 for (var i = 0; i < str.length; i += 32) { 7091 a = H[0]; 7092 b = H[1]; 7093 c = H[2]; 7094 d = H[3]; 7095 e = H[4]; 7096 f = H[5]; 7097 g = H[6]; 7098 h = H[7]; 7099 7100 for (var j = 0; j < 80; j++) { 7101 if (j < 16) { 7102 W[j] = new int64(str[j*2 + i], str[j*2 + i + 1]); 7103 } else { 7104 W[j] = safe_add_4(gamma1(W[j - 2]), W[j - 7], gamma0(W[j - 15]), W[j - 16]); 7105 } 7106 7107 T1 = safe_add_5(h, sigma1(e), ch(e, f, g), K[j], W[j]); 7108 T2 = safe_add_2(sigma0(a), maj(a, b, c)); 7109 h = g; 7110 g = f; 7111 f = e; 7112 e = safe_add_2(d, T1); 7113 d = c; 7114 c = b; 7115 b = a; 7116 a = safe_add_2(T1, T2); 7117 } 7118 7119 H[0] = safe_add_2(a, H[0]); 7120 H[1] = safe_add_2(b, H[1]); 7121 H[2] = safe_add_2(c, H[2]); 7122 H[3] = safe_add_2(d, H[3]); 7123 H[4] = safe_add_2(e, H[4]); 7124 H[5] = safe_add_2(f, H[5]); 7125 H[6] = safe_add_2(g, H[6]); 7126 H[7] = safe_add_2(h, H[7]); 7127 } 7128 7129 var binarray = []; 7130 for (var i = 0; i < H.length; i++) { 7131 binarray.push(H[i].highOrder); 7132 binarray.push(H[i].lowOrder); 7133 } 7134 7135 return binb2hex(binarray); 7136}); 7137 7138 7139jSuites.image = jSuites.upload = (function(el, options) { 7140 var obj = {}; 7141 obj.options = {}; 7142 7143 // Default configuration 7144 var defaults = { 7145 type: 'image', 7146 extension: '*', 7147 input: false, 7148 minWidth: false, 7149 maxWidth: null, 7150 maxHeight: null, 7151 maxJpegSizeBytes: null, // For example, 350Kb would be 350000 7152 onchange: null, 7153 multiple: false, 7154 remoteParser: null, 7155 text:{ 7156 extensionNotAllowed:'The extension is not allowed', 7157 } 7158 }; 7159 7160 // Loop through our object 7161 for (var property in defaults) { 7162 if (options && options.hasOwnProperty(property)) { 7163 obj.options[property] = options[property]; 7164 } else { 7165 obj.options[property] = defaults[property]; 7166 } 7167 } 7168 7169 // Multiple 7170 if (obj.options.multiple == true) { 7171 el.setAttribute('data-multiple', true); 7172 } 7173 7174 // Container 7175 el.content = []; 7176 7177 // Upload icon 7178 el.classList.add('jupload'); 7179 7180 if (obj.options.input == true) { 7181 el.classList.add('input'); 7182 } 7183 7184 obj.add = function(data) { 7185 // Reset container for single files 7186 if (obj.options.multiple == false) { 7187 el.content = []; 7188 el.innerText = ''; 7189 } 7190 7191 // Append to the element 7192 if (obj.options.type == 'image') { 7193 var img = document.createElement('img'); 7194 img.setAttribute('src', data.file); 7195 img.setAttribute('tabindex', -1); 7196 if (! el.getAttribute('name')) { 7197 img.className = 'jfile'; 7198 img.content = data; 7199 } 7200 el.appendChild(img); 7201 } else { 7202 if (data.name) { 7203 var name = data.name; 7204 } else { 7205 var name = data.file; 7206 } 7207 var div = document.createElement('div'); 7208 div.innerText = name || obj.options.type; 7209 div.classList.add('jupload-item'); 7210 div.setAttribute('tabindex', -1); 7211 el.appendChild(div); 7212 } 7213 7214 if (data.content) { 7215 data.file = jSuites.guid(); 7216 } 7217 7218 // Push content 7219 el.content.push(data); 7220 7221 // Onchange 7222 if (typeof(obj.options.onchange) == 'function') { 7223 obj.options.onchange(el, data); 7224 } 7225 } 7226 7227 obj.addFromFile = function(file) { 7228 var type = file.type.split('/'); 7229 if (type[0] == obj.options.type) { 7230 var readFile = new FileReader(); 7231 readFile.addEventListener("load", function (v) { 7232 var data = { 7233 file: v.srcElement.result, 7234 extension: file.name.substr(file.name.lastIndexOf('.') + 1), 7235 name: file.name, 7236 size: file.size, 7237 lastmodified: file.lastModified, 7238 content: v.srcElement.result, 7239 } 7240 7241 obj.add(data); 7242 }); 7243 7244 readFile.readAsDataURL(file); 7245 } else { 7246 alert(obj.options.text.extensionNotAllowed); 7247 } 7248 } 7249 7250 obj.addFromUrl = function(src) { 7251 if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) { 7252 console.error('remoteParser not defined in your initialization'); 7253 } else { 7254 // This is to process cross domain images 7255 if (src.substr(0,4) == 'data') { 7256 var extension = src.split(';') 7257 extension = extension[0].split('/'); 7258 var type = extension[0].replace('data:',''); 7259 if (type == obj.options.type) { 7260 var data = { 7261 file: src, 7262 name: '', 7263 extension: extension[1], 7264 content: src, 7265 } 7266 obj.add(data); 7267 } else { 7268 alert(obj.options.text.extensionNotAllowed); 7269 } 7270 } else { 7271 var extension = src.substr(src.lastIndexOf('.') + 1); 7272 // Work for cross browsers 7273 src = obj.options.remoteParser + src; 7274 // Get remove content 7275 jSuites.ajax({ 7276 url: src, 7277 type: 'GET', 7278 dataType: 'blob', 7279 success: function(data) { 7280 //add(extension[0].replace('data:',''), data); 7281 } 7282 }) 7283 } 7284 } 7285 } 7286 7287 var getDataURL = function(canvas, type) { 7288 var compression = 0.92; 7289 var lastContentLength = null; 7290 var content = canvas.toDataURL(type, compression); 7291 while (obj.options.maxJpegSizeBytes && type === 'image/jpeg' && 7292 content.length > obj.options.maxJpegSizeBytes && content.length !== lastContentLength) { 7293 // Apply the compression 7294 compression *= 0.9; 7295 lastContentLength = content.length; 7296 content = canvas.toDataURL(type, compression); 7297 } 7298 return content; 7299 } 7300 7301 var mime = obj.options.type + '/' + obj.options.extension; 7302 var input = document.createElement('input'); 7303 input.type = 'file'; 7304 input.setAttribute('accept', mime); 7305 input.onchange = function() { 7306 for (var i = 0; i < this.files.length; i++) { 7307 obj.addFromFile(this.files[i]); 7308 } 7309 } 7310 7311 // Allow multiple files 7312 if (obj.options.multiple == true) { 7313 input.setAttribute('multiple', true); 7314 } 7315 7316 var current = null; 7317 7318 el.addEventListener("click", function(e) { 7319 current = null; 7320 if (! el.children.length || e.target === el) { 7321 jSuites.click(input); 7322 } else { 7323 if (e.target.parentNode == el) { 7324 current = e.target; 7325 } 7326 } 7327 }); 7328 7329 el.addEventListener("dblclick", function(e) { 7330 jSuites.click(input); 7331 }); 7332 7333 el.addEventListener('dragenter', function(e) { 7334 el.style.border = '1px dashed #000'; 7335 }); 7336 7337 el.addEventListener('dragleave', function(e) { 7338 el.style.border = '1px solid #eee'; 7339 }); 7340 7341 el.addEventListener('dragstop', function(e) { 7342 el.style.border = '1px solid #eee'; 7343 }); 7344 7345 el.addEventListener('dragover', function(e) { 7346 e.preventDefault(); 7347 }); 7348 7349 el.addEventListener('keydown', function(e) { 7350 if (current && e.which == 46) { 7351 var index = Array.prototype.indexOf.call(el.children, current); 7352 if (index >= 0) { 7353 el.content.splice(index, 1); 7354 current.remove(); 7355 current = null; 7356 } 7357 } 7358 }); 7359 7360 el.addEventListener('drop', function(e) { 7361 e.preventDefault(); 7362 e.stopPropagation(); 7363 7364 var html = (e.originalEvent || e).dataTransfer.getData('text/html'); 7365 var file = (e.originalEvent || e).dataTransfer.files; 7366 7367 if (file.length) { 7368 for (var i = 0; i < e.dataTransfer.files.length; i++) { 7369 obj.addFromFile(e.dataTransfer.files[i]); 7370 } 7371 } else if (html) { 7372 if (obj.options.multiple == false) { 7373 el.innerText = ''; 7374 } 7375 7376 // Create temp element 7377 var div = document.createElement('div'); 7378 div.innerHTML = html; 7379 7380 // Extract images 7381 var img = div.querySelectorAll('img'); 7382 7383 if (img.length) { 7384 for (var i = 0; i < img.length; i++) {
7385 obj.addFromUrl(img[i].src); 7386 } 7387 } 7388 } 7389 7390 el.style.border = '1px solid #eee'; 7391 7392 return false; 7393 }); 7394 7395 el.val = function(val) { 7396 if (val === undefined) { 7397 return el.content && el.content.length ? el.content : null; 7398 } else { 7399 // Reset 7400 el.innerText = ''; 7401 el.content = []; 7402 7403 if (val) { 7404 if (Array.isArray(val)) { 7405 for (var i = 0; i < val.length; i++) { 7406 if (typeof(val[i]) == 'string') { 7407 obj.add({ file: val[i] }); 7408 } else { 7409 obj.add(val[i]); 7410 } 7411 } 7412 } else if (typeof(val) == 'string') { 7413 obj.add({ file: val }); 7414 } 7415 } 7416 } 7417 } 7418 7419 el.upload = el.image = obj; 7420 7421 return obj; 7422}); 7423 7424jSuites.image.create = function(data) { 7425 var img = document.createElement('img'); 7426 img.setAttribute('src', data.file); 7427 img.className = 'jfile'; 7428 img.setAttribute('tabindex', -1); 7429 img.content = data; 7430 7431 return img; 7432} 7433 7434 7435jSuites.lazyLoading = (function(el, options) { 7436 var obj = {} 7437 7438 // Mandatory options 7439 if (! options.loadUp || typeof(options.loadUp) != 'function') { 7440 options.loadUp = function() { 7441 return false; 7442 } 7443 } 7444 if (! options.loadDown || typeof(options.loadDown) != 'function') { 7445 options.loadDown = function() { 7446 return false; 7447 } 7448 } 7449 // Timer ms 7450 if (! options.timer) { 7451 options.timer = 100; 7452 } 7453 7454 // Timer 7455 var timeControlLoading = null; 7456 7457 // Controls 7458 var scrollControls = function(e) { 7459 if (timeControlLoading == null) { 7460 var event = false; 7461 var scrollTop = el.scrollTop; 7462 if (el.scrollTop + (el.clientHeight * 2) >= el.scrollHeight) { 7463 if (options.loadDown()) { 7464 if (scrollTop == el.scrollTop) { 7465 el.scrollTop = el.scrollTop - (el.clientHeight); 7466 } 7467 event = true; 7468 } 7469 } else if (el.scrollTop <= el.clientHeight) { 7470 if (options.loadUp()) { 7471 if (scrollTop == el.scrollTop) { 7472 el.scrollTop = el.scrollTop + (el.clientHeight); 7473 } 7474 event = true; 7475 } 7476 } 7477 7478 timeControlLoading = setTimeout(function() { 7479 timeControlLoading = null; 7480 }, options.timer); 7481 7482 if (event) { 7483 if (typeof(options.onupdate) == 'function') { 7484 options.onupdate(); 7485 } 7486 } 7487 } 7488 } 7489 7490 // Onscroll 7491 el.onscroll = function(e) { 7492 scrollControls(e); 7493 } 7494 7495 el.onwheel = function(e) { 7496 scrollControls(e); 7497 } 7498 7499 return obj; 7500}); 7501 7502jSuites.loading = (function() { 7503 var obj = {}; 7504 7505 var loading = null; 7506 7507 obj.show = function(timeout) { 7508 if (! loading) { 7509 loading = document.createElement('div'); 7510 loading.className = 'jloading'; 7511 } 7512 document.body.appendChild(loading); 7513 7514 // Max timeout in seconds 7515 if (timeout > 0) { 7516 setTimeout(function() { 7517 obj.hide(); 7518 }, timeout * 1000) 7519 } 7520 } 7521 7522 obj.hide = function() { 7523 if (loading && loading.parentNode) { 7524 document.body.removeChild(loading); 7525 } 7526 } 7527 7528 return obj; 7529})(); 7530 7531jSuites.mask = (function() { 7532 // Currency 7533 var tokens = { 7534 // Text 7535 text: [ '@' ], 7536 // Currency tokens 7537 currency: [ '#(.{1})##0?(.{1}0+)?( ?;(.*)?)?', '#' ], 7538 // Percentage 7539 percentage: [ '0{1}(.{1}0+)?%' ], 7540 // Number 7541 numeric: [ '0{1}(.{1}0+)?' ], 7542 // Data tokens 7543 datetime: [ 'YYYY', 'YYY', 'YY', 'MMMMM', 'MMMM', 'MMM', 'MM', 'DDDDD', 'DDDD', 'DDD', 'DD', 'DY', 'DAY', 'WD', 'D', 'Q', 'MONTH', 'MON', 'HH24', 'HH12', 'HH', '\\[H\\]', 'H', 'AM/PM', 'PM', 'AM', 'MI', 'SS', 'MS', 'Y', 'M' ], 7544 // Other 7545 general: [ 'A', '0', '[0-9a-zA-Z\$]+', '.'] 7546 } 7547 7548 var getDate = function() { 7549 if (this.mask.toLowerCase().indexOf('[h]') !== -1) { 7550 var m = 0; 7551 if (this.date[4]) { 7552 m = parseFloat(this.date[4] / 60); 7553 } 7554 var v = parseInt(this.date[3]) + m; 7555 v /= 24; 7556 } else if (! (this.date[0] && this.date[1] && this.date[2]) && (this.date[3] || this.date[4])) { 7557 v = jSuites.two(this.date[3]) + ':' + jSuites.two(this.date[4]) + ':' + jSuites.two(this.date[5]) 7558 } else { 7559 if (this.date[0] && this.date[1] && ! this.date[2]) { 7560 this.date[2] = 1; 7561 } 7562 v = jSuites.two(this.date[0]) + '-' + jSuites.two(this.date[1]) + '-' + jSuites.two(this.date[2]); 7563 7564 if (this.date[3] || this.date[4] || this.date[5]) { 7565 v += ' ' + jSuites.two(this.date[3]) + ':' + jSuites.two(this.date[4]) + ':' + jSuites.two(this.date[5]); 7566 } 7567 } 7568 7569 return v; 7570 } 7571 7572 var extractDate = function() { 7573 var v = ''; 7574 if (! (this.date[0] && this.date[1] && this.date[2]) && (this.date[3] || this.date[4])) { 7575 if (this.mask.toLowerCase().indexOf('[h]') !== -1) { 7576 v = parseInt(this.date[3]); 7577 } else { 7578 v = parseInt(this.date[3]) % 24; 7579 } 7580 if (this.date[4]) { 7581 v += parseFloat(this.date[4] / 60); 7582 } 7583 v /= 24; 7584 } else if (this.date[0] || this.date[1] || this.date[2] || this.date[3] || this.date[4] || this.date[5]) { 7585 if (this.date[0] && this.date[1] && ! this.date[2]) { 7586 this.date[2] = 1; 7587 } 7588 var t = jSuites.calendar.now(this.date); 7589 v = jSuites.calendar.dateToNum(t); 7590 if (this.date[4]) { 7591 v += parseFloat(this.date[4] / 60); 7592 } 7593 } 7594 return v; 7595 } 7596 7597 var isBlank = function(v) { 7598 return v === null || v === '' || v === undefined ? true : false;
7599 } 7600 7601 var isFormula = function(value) { 7602 return (''+value).chartAt(0) == '='; 7603 } 7604 7605 var isNumeric = function(t) { 7606 return t === 'currency' || t === 'percentage' || t === 'numeric' ? true : false; 7607 } 7608 /** 7609 * Get the decimal defined in the mask configuration 7610 */ 7611 var getDecimal = function(v) { 7612 if (v && Number(v) == v) { 7613 return '.'; 7614 } else { 7615 if (this.options.decimal) { 7616 return this.options.decimal; 7617 } else { 7618 if (this.locale) { 7619 var t = Intl.NumberFormat(this.locale).format(1.1); 7620 return this.options.decimal = t[1]; 7621 } else { 7622 if (! v) { 7623 v = this.mask; 7624 } 7625 var e = new RegExp('0{1}(.{1})0+', 'ig'); 7626 var t = e.exec(v); 7627 if (t && t[1] && t[1].length == 1) { 7628 // Save decimal 7629 this.options.decimal = t[1]; 7630 // Return decimal 7631 return t[1]; 7632 } else { 7633 // Did not find any decimal last resort the default 7634 var e = new RegExp('#{1}(.{1})#+', 'ig'); 7635 var t = e.exec(v); 7636 if (t && t[1] && t[1].length == 1) { 7637 if (t[1] === ',') { 7638 this.options.decimal = '.'; 7639 } else { 7640 this.options.decimal = ','; 7641 } 7642 } else { 7643 this.options.decimal = '1.1'.toLocaleString().substring(1,2); 7644 } 7645 } 7646 } 7647 } 7648 } 7649 7650 if (this.options.decimal) { 7651 return this.options.decimal; 7652 } else { 7653 return null; 7654 } 7655 } 7656 7657 var ParseValue = function(v, decimal) { 7658 if (v == '') { 7659 return ''; 7660 } 7661 7662 // Get decimal 7663 if (! decimal) { 7664 decimal = getDecimal.call(this); 7665 } 7666 7667 // New value 7668 v = (''+v).split(decimal); 7669 7670 // Signal 7671 var signal = v[0].match(/[-]+/g); 7672 if (signal && signal.length) { 7673 signal = true; 7674 } else { 7675 signal = false; 7676 } 7677 7678 v[0] = v[0].match(/[0-9]+/g); 7679 7680 if (v[0]) { 7681 if (signal) { 7682 v[0].unshift('-'); 7683 } 7684 v[0] = v[0].join(''); 7685 } else { 7686 if (signal) { 7687 v[0] = '-'; 7688 } 7689 } 7690 7691 if (v[0] || v[1]) { 7692 if (v[1] !== undefined) { 7693 v[1] = v[1].match(/[0-9]+/g); 7694 if (v[1]) { 7695 v[1] = v[1].join(''); 7696 } else { 7697 v[1] = ''; 7698 } 7699 } 7700 } else { 7701 return ''; 7702 } 7703 return v; 7704 } 7705 7706 var FormatValue = function(v, event) { 7707 if (v == '') { 7708 return ''; 7709 } 7710 // Get decimal 7711 var d = getDecimal.call(this); 7712 // Convert value 7713 var o = this.options; 7714 // Parse value 7715 v = ParseValue.call(this, v); 7716 if (v == '') { 7717 return ''; 7718 } 7719 // Temporary value 7720 if (v[0]) { 7721 var t = parseFloat(v[0] + '.1'); 7722 if (o.style == 'percent') { 7723 t /= 100; 7724 } 7725 } else { 7726 var t = null; 7727 } 7728 7729 if ((v[0] == '-' || v[0] == '-00') && ! v[1] && (event && event.inputType == "deleteContentBackward")) { 7730 return ''; 7731 } 7732 7733 var n = new Intl.NumberFormat(this.locale, o).format(t); 7734 n = n.split(d); 7735 if (typeof(n[1]) !== 'undefined') { 7736 var s = n[1].replace(/[0-9]*/g, ''); 7737 if (s) { 7738 n[2] = s; 7739 } 7740 } 7741 7742 if (v[1] !== undefined) { 7743 n[1] = d + v[1]; 7744 } else { 7745 n[1] = ''; 7746 } 7747 7748 return n.join(''); 7749 } 7750 7751 var Format = function(e, event) { 7752 var v = Value.call(e); 7753 if (! v) { 7754 return; 7755 } 7756 7757 // Get decimal 7758 var d = getDecimal.call(this); 7759 var n = FormatValue.call(this, v, event); 7760 var t = (n.length) - v.length; 7761 var index = Caret.call(e) + t; 7762 // Set value and update caret 7763 Value.call(e, n, index, true); 7764 } 7765 7766 var Extract = function(v) { 7767 // Keep the raw value 7768 var current = ParseValue.call(this, v); 7769 if (current) { 7770 // Negative values 7771 if (current[0] === '-') { 7772 current[0] = '-0'; 7773 } 7774 return parseFloat(current.join('.')); 7775 } 7776 return null; 7777 } 7778 7779 /** 7780 * Caret getter and setter methods 7781 */
7782 var Caret = function(index, adjustNumeric) { 7783 if (index === undefined) { 7784 if (this.tagName == 'DIV') { 7785 var pos = 0; 7786 var s = window.getSelection(); 7787 if (s) { 7788 if (s.rangeCount !== 0) { 7789 var r = s.getRangeAt(0); 7790 var p = r.cloneRange(); 7791 p.selectNodeContents(this); 7792 p.setEnd(r.endContainer, r.endOffset); 7793 pos = p.toString().length; 7794 } 7795 } 7796 return pos; 7797 } else { 7798 return this.selectionStart; 7799 } 7800 } else { 7801 // Get the current value 7802 var n = Value.call(this); 7803 7804 // Review the position 7805 if (adjustNumeric) { 7806 var p = null; 7807 for (var i = 0; i < n.length; i++) { 7808 if (n[i].match(/[\-0-9]/g) || n[i] == '.' || n[i] == ',') { 7809 p = i; 7810 } 7811 } 7812 7813 // If the string has no numbers 7814 if (p === null) { 7815 p = n.indexOf(' '); 7816 } 7817 7818 if (index >= p) { 7819 index = p + 1; 7820 } 7821 } 7822 7823 // Do not update caret 7824 if (index > n.length) { 7825 index = n.length; 7826 } 7827 7828 if (index) { 7829 // Set caret 7830 if (this.tagName == 'DIV') { 7831 var s = window.getSelection(); 7832 var r = document.createRange(); 7833 7834 if (this.childNodes[0]) { 7835 r.setStart(this.childNodes[0], index); 7836 s.removeAllRanges(); 7837 s.addRange(r); 7838 } 7839 } else { 7840 this.selectionStart = index; 7841 this.selectionEnd = index; 7842 } 7843 } 7844 } 7845 } 7846 7847 /** 7848 * Value getter and setter method 7849 */ 7850 var Value = function(v, updateCaret, adjustNumeric) { 7851 if (this.tagName == 'DIV') { 7852 if (v === undefined) { 7853 var v = this.innerText; 7854 if (this.value && this.value.length > v.length) { 7855 v = this.value; 7856 } 7857 return v; 7858 } else { 7859 if (this.innerText !== v) { 7860 this.innerText = v; 7861 7862 if (updateCaret) { 7863 Caret.call(this, updateCaret, adjustNumeric); 7864 } 7865 } 7866 } 7867 } else { 7868 if (v === undefined) { 7869 return this.value; 7870 } else { 7871 if (this.value !== v) { 7872 this.value = v; 7873 if (updateCaret) { 7874 Caret.call(this, updateCaret, adjustNumeric); 7875 } 7876 } 7877 } 7878 } 7879 } 7880 7881 // Labels 7882 var weekDaysFull = jSuites.calendar.weekdays; 7883 var weekDays = jSuites.calendar.weekdaysShort; 7884 var monthsFull = jSuites.calendar.months; 7885 var months = jSuites.calendar.monthsShort; 7886 7887 var parser = { 7888 'YEAR': function(v, s) { 7889 var y = ''+new Date().getFullYear(); 7890 7891 if (typeof(this.values[this.index]) === 'undefined') { 7892 this.values[this.index] = ''; 7893 } 7894 if (parseInt(v) >= 0 && parseInt(v) <= 10) { 7895 if (this.values[this.index].length < s) { 7896 this.values[this.index] += v; 7897 } 7898 } 7899 if (this.values[this.index].length == s) { 7900 if (s == 2) { 7901 var y = y.substr(0,2) + this.values[this.index]; 7902 } else if (s == 3) { 7903 var y = y.substr(0,1) + this.values[this.index]; 7904 } else if (s == 4) { 7905 var y = this.values[this.index]; 7906 } 7907 this.date[0] = y; 7908 this.index++; 7909 } 7910 }, 7911 'YYYY': function(v) { 7912 parser.YEAR.call(this, v, 4); 7913 }, 7914 'YYY': function(v) { 7915 parser.YEAR.call(this, v, 3); 7916 }, 7917 'YY': function(v) { 7918 parser.YEAR.call(this, v, 2); 7919 }, 7920 'FIND': function(v, a) { 7921 if (isBlank(this.values[this.index])) { 7922 this.values[this.index] = ''; 7923 } 7924 if (this.event && this.event.inputType && this.event.inputType.indexOf('delete') > -1) { 7925 this.values[this.index] += v; 7926 return; 7927 } 7928 var pos = 0; 7929 var count = 0; 7930 var value = (this.values[this.index] + v).toLowerCase(); 7931 for (var i = 0; i < a.length; i++) { 7932 if (a[i].toLowerCase().indexOf(value) == 0) { 7933 pos = i; 7934 count++; 7935 } 7936 } 7937 if (count > 1) { 7938 this.values[this.index] += v; 7939 } else if (count == 1) { 7940 // Jump number of chars 7941 var t = (a[pos].length - this.values[this.index].length) - 1; 7942 this.position += t; 7943 7944 this.values[this.index] = a[pos]; 7945 this.index++; 7946 return pos; 7947 } 7948 }, 7949 'MMM': function(v) { 7950 var ret = parser.FIND.call(this, v, months); 7951 if (ret !== undefined) { 7952 this.date[1] = ret + 1; 7953 } 7954 }, 7955 'MON': function(v) { 7956 parser['MMM'].call(this, v); 7957 }, 7958 'MMMM': function(v) { 7959 var ret = parser.FIND.call(this, v, monthsFull); 7960 if (ret !== undefined) { 7961 this.date[1] = ret + 1; 7962 } 7963 }, 7964 'MONTH': function(v) { 7965 parser['MMMM'].call(this, v); 7966 }, 7967 'MMMMM': function(v) { 7968 if (isBlank(this.values[this.index])) { 7969 this.values[this.index] = ''; 7970 } 7971 var pos = 0; 7972 var count = 0; 7973 var value = (this.values[this.index] + v).toLowerCase(); 7974 for (var i = 0; i < monthsFull.length; i++) { 7975 if (monthsFull[i][0].toLowerCase().indexOf(value) == 0) { 7976 this.values[this.index] = monthsFull[i][0]; 7977 this.date[1] = i + 1; 7978 this.index++; 7979 break; 7980 } 7981 } 7982 }, 7983 'MM': function(v) { 7984 if (isBlank(this.values[this.index])) { 7985 if (parseInt(v) > 1 && parseInt(v) < 10) { 7986 this.date[1] = this.values[this.index] = '0' + v; 7987 this.index++; 7988 } else if (parseInt(v) < 2) { 7989 this.values[this.index] = v; 7990 } 7991 } else { 7992 if (this.values[this.index] == 1 && parseInt(v) < 3) { 7993 this.date[1] = this.values[this.index] += v; 7994 this.index++; 7995 } else if (this.values[this.index] == 0 && parseInt(v) > 0 && parseInt(v) < 10) { 7996 this.date[1] = this.values[this.index] += v; 7997 this.index++; 7998 } 7999 } 8000 }, 8001 'M': function(v) { 8002 var test = false;
8003 if (parseInt(v) >= 0 && parseInt(v) < 10) { 8004 if (isBlank(this.values[this.index])) { 8005 this.values[this.index] = v; 8006 if (v > 1) { 8007 this.date[1] = this.values[this.index]; 8008 this.index++; 8009 } 8010 } else { 8011 if (this.values[this.index] == 1 && parseInt(v) < 3) { 8012 this.date[1] = this.values[this.index] += v; 8013 this.index++; 8014 } else if (this.values[this.index] == 0 && parseInt(v) > 0) { 8015 this.date[1] = this.values[this.index] += v; 8016 this.index++; 8017 } else { 8018 var test = true; 8019 } 8020 } 8021 } else { 8022 var test = true; 8023 } 8024 8025 // Re-test 8026 if (test == true) { 8027 var t = parseInt(this.values[this.index]); 8028 if (t > 0 && t < 12) { 8029 this.date[2] = this.values[this.index]; 8030 this.index++; 8031 // Repeat the character 8032 this.position--; 8033 } 8034 } 8035 }, 8036 'D': function(v) { 8037 var test = false; 8038 if (parseInt(v) >= 0 && parseInt(v) < 10) { 8039 if (isBlank(this.values[this.index])) { 8040 this.values[this.index] = v; 8041 if (parseInt(v) > 3) { 8042 this.date[2] = this.values[this.index]; 8043 this.index++; 8044 } 8045 } else { 8046 if (this.values[this.index] == 3 && parseInt(v) < 2) { 8047 this.date[2] = this.values[this.index] += v; 8048 this.index++; 8049 } else if (this.values[this.index] == 1 || this.values[this.index] == 2) { 8050 this.date[2] = this.values[this.index] += v; 8051 this.index++; 8052 } else if (this.values[this.index] == 0 && parseInt(v) > 0) { 8053 this.date[2] = this.values[this.index] += v; 8054 this.index++; 8055 } else { 8056 var test = true; 8057 } 8058 } 8059 } else { 8060 var test = true; 8061 } 8062 8063 // Re-test 8064 if (test == true) { 8065 var t = parseInt(this.values[this.index]); 8066 if (t > 0 && t < 32) { 8067 this.date[2] = this.values[this.index]; 8068 this.index++; 8069 // Repeat the character 8070 this.position--; 8071 } 8072 } 8073 }, 8074 'DD': function(v) { 8075 if (isBlank(this.values[this.index])) { 8076 if (parseInt(v) > 3 && parseInt(v) < 10) { 8077 this.date[2] = this.values[this.index] = '0' + v; 8078 this.index++; 8079 } else if (parseInt(v) < 10) { 8080 this.values[this.index] = v; 8081 } 8082 } else { 8083 if (this.values[this.index] == 3 && parseInt(v) < 2) { 8084 this.date[2] = this.values[this.index] += v; 8085 this.index++; 8086 } else if ((this.values[this.index] == 1 || this.values[this.index] == 2) && parseInt(v) < 10) { 8087 this.date[2] = this.values[this.index] += v; 8088 this.index++; 8089 } else if (this.values[this.index] == 0 && parseInt(v) > 0 && parseInt(v) < 10) { 8090 this.date[2] = this.values[this.index] += v; 8091 this.index++; 8092 } 8093 } 8094 }, 8095 'DDD': function(v) { 8096 parser.FIND.call(this, v, weekDays); 8097 }, 8098 'DY': function(v) { 8099 parser['DDD'].call(this, v); 8100 }, 8101 'DDDD': function(v) { 8102 parser.FIND.call(this, v, weekDaysFull); 8103 }, 8104 'DAY': function(v) { 8105 parser['DDDD'].call(this, v); 8106 }, 8107 'HH12': function(v, two) { 8108 if (isBlank(this.values[this.index])) { 8109 if (parseInt(v) > 1 && parseInt(v) < 10) { 8110 if (two) { 8111 v = 0 + v; 8112 } 8113 this.date[3] = this.values[this.index] = v; 8114 this.index++; 8115 } else if (parseInt(v) < 10) { 8116 this.values[this.index] = v; 8117 } 8118 } else { 8119 if (this.values[this.index] == 1 && parseInt(v) < 3) { 8120 this.date[3] = this.values[this.index] += v; 8121 this.index++; 8122 } else if (this.values[this.index] < 1 && parseInt(v) < 10) { 8123 this.date[3] = this.values[this.index] += v; 8124 this.index++; 8125 } 8126 } 8127 }, 8128 'HH24': function(v, two) { 8129 var test = false;
8130 if (parseInt(v) >= 0 && parseInt(v) < 10) { 8131 if (this.values[this.index] == null || this.values[this.index] == '') { 8132 if (parseInt(v) > 2 && parseInt(v) < 10) { 8133 if (two) { 8134 v = 0 + v; 8135 } 8136 this.date[3] = this.values[this.index] = v; 8137 this.index++; 8138 } else if (parseInt(v) < 10) { 8139 this.values[this.index] = v; 8140 } 8141 } else { 8142 if (this.values[this.index] == 2 && parseInt(v) < 4) { 8143 this.date[3] = this.values[this.index] += v; 8144 this.index++; 8145 } else if (this.values[this.index] < 2 && parseInt(v) < 10) { 8146 this.date[3] = this.values[this.index] += v; 8147 this.index++; 8148 } 8149 } 8150 } 8151 }, 8152 'HH': function(v) { 8153 parser['HH24'].call(this, v, 1); 8154 }, 8155 'H': function(v) { 8156 parser['HH24'].call(this, v, 0); 8157 }, 8158 '\\[H\\]': function(v) { 8159 if (this.values[this.index] == undefined) { 8160 this.values[this.index] = ''; 8161 } 8162 if (v.match(/[0-9]/g)) { 8163 this.date[3] = this.values[this.index] += v; 8164 } else { 8165 if (this.values[this.index].match(/[0-9]/g)) { 8166 this.date[3] = this.values[this.index]; 8167 this.index++; 8168 // Repeat the character 8169 this.position--; 8170 } 8171 } 8172 }, 8173 'N60': function(v, i) { 8174 if (this.values[this.index] == null || this.values[this.index] == '') { 8175 if (parseInt(v) > 5 && parseInt(v) < 10) { 8176 this.date[i] = this.values[this.index] = '0' + v; 8177 this.index++; 8178 } else if (parseInt(v) < 10) { 8179 this.values[this.index] = v; 8180 } 8181 } else { 8182 if (parseInt(v) < 10) { 8183 this.date[i] = this.values[this.index] += v; 8184 this.index++; 8185 } 8186 } 8187 }, 8188 'MI': function(v) { 8189 parser.N60.call(this, v, 4); 8190 }, 8191 'SS': function(v) { 8192 parser.N60.call(this, v, 5); 8193 }, 8194 'AM/PM': function(v) { 8195 this.values[this.index] = ''; 8196 if (v) { 8197 if (this.date[3] > 12) { 8198 this.values[this.index] = 'PM'; 8199 } else { 8200 this.values[this.index] = 'AM'; 8201 } 8202 } 8203 this.index++; 8204 }, 8205 'WD': function(v) { 8206 if (typeof(this.values[this.index]) === 'undefined') { 8207 this.values[this.index] = ''; 8208 } 8209 if (parseInt(v) >= 0 && parseInt(v) < 7) { 8210 this.values[this.index] = v; 8211 } 8212 if (this.value[this.index].length == 1) { 8213 this.index++; 8214 } 8215 }, 8216 '0{1}(.{1}0+)?': function(v) { 8217 // Get decimal 8218 var decimal = getDecimal.call(this); 8219 // Negative number 8220 var neg = false; 8221 // Create if is blank 8222 if (isBlank(this.values[this.index])) { 8223 this.values[this.index] = ''; 8224 } else { 8225 if (this.values[this.index] == '-') { 8226 neg = true; 8227 } 8228 } 8229 var current = ParseValue.call(this, this.values[this.index], decimal); 8230 if (current) { 8231 this.values[this.index] = current.join(decimal); 8232 } 8233 // New entry 8234 if (parseInt(v) >= 0 && parseInt(v) < 10) { 8235 // Replace the zero for a number 8236 if (this.values[this.index] == '0' && v > 0) { 8237 this.values[this.index] = ''; 8238 } else if (this.values[this.index] == '-0' && v > 0) { 8239 this.values[this.index] = '-'; 8240 } 8241 // Don't add up zeros because does not mean anything here 8242 if ((this.values[this.index] != '0' && this.values[this.index] != '-0') || v == decimal) { 8243 this.values[this.index] += v; 8244 } 8245 } else if (decimal && v == decimal) { 8246 if (this.values[this.index].indexOf(decimal) == -1) { 8247 if (! this.values[this.index]) { 8248 this.values[this.index] = '0'; 8249 } 8250 this.values[this.index] += v; 8251 } 8252 } else if (v == '-') { 8253 // Negative signed 8254 neg = true; 8255 } 8256 8257 if (neg === true && this.values[this.index][0] !== '-') { 8258 this.values[this.index] = '-' + this.values[this.index]; 8259 } 8260 }, 8261 '0{1}(.{1}0+)?%': function(v) { 8262 parser['0{1}(.{1}0+)?'].call(this, v); 8263 8264 if (this.values[this.index].match(/[\-0-9]/g)) { 8265 if (this.values[this.index] && this.values[this.index].indexOf('%') == -1) { 8266 this.values[this.index] += '%'; 8267 } 8268 } else { 8269 this.values[this.index] = ''; 8270 } 8271 }, 8272 '#(.{1})##0?(.{1}0+)?( ?;(.*)?)?': function(v) { 8273 // Parse number 8274 parser['0{1}(.{1}0+)?'].call(this, v); 8275 // Get decimal 8276 var decimal = getDecimal.call(this); 8277 // Get separator 8278 var separator = this.tokens[this.index].substr(1,1); 8279 // Negative 8280 var negative = this.values[this.index][0] === '-' ? true : false;
8281 // Current value 8282 var current = ParseValue.call(this, this.values[this.index], decimal); 8283 8284 // Get main and decimal parts 8285 if (current !== '') { 8286 // Format number 8287 var n = current[0].match(/[0-9]/g); 8288 if (n) { 8289 // Format 8290 n = n.join(''); 8291 var t = []; 8292 var s = 0; 8293 for (var j = n.length - 1; j >= 0 ; j--) { 8294 t.push(n[j]); 8295 s++; 8296 if (! (s % 3)) { 8297 t.push(separator); 8298 } 8299 } 8300 t = t.reverse(); 8301 current[0] = t.join(''); 8302 if (current[0].substr(0,1) == separator) { 8303 current[0] = current[0].substr(1); 8304 } 8305 } else { 8306 current[0] = ''; 8307 } 8308 8309 // Value 8310 this.values[this.index] = current.join(decimal); 8311 8312 // Negative 8313 if (negative) { 8314 this.values[this.index] = '-' + this.values[this.index]; 8315 } 8316 } 8317 }, 8318 '0': function(v) { 8319 if (v.match(/[0-9]/g)) { 8320 this.values[this.index] = v; 8321 this.index++; 8322 } 8323 }, 8324 '[0-9a-zA-Z$]+': function(v) { 8325 if (isBlank(this.values[this.index])) { 8326 this.values[this.index] = ''; 8327 } 8328 var t = this.tokens[this.index]; 8329 var s = this.values[this.index]; 8330 var i = s.length; 8331 8332 if (t[i] == v) { 8333 this.values[this.index] += v; 8334 8335 if (this.values[this.index] == t) { 8336 this.index++; 8337 } 8338 } else { 8339 this.values[this.index] = t; 8340 this.index++; 8341 8342 if (v.match(/[\-0-9]/g)) { 8343 // Repeat the character 8344 this.position--; 8345 } 8346 } 8347 }, 8348 'A': function(v) { 8349 if (v.match(/[a-zA-Z]/gi)) { 8350 this.values[this.index] = v; 8351 this.index++; 8352 } 8353 }, 8354 '.': function(v) { 8355 parser['[0-9a-zA-Z$]+'].call(this, v); 8356 }, 8357 '@': function(v) { 8358 if (isBlank(this.values[this.index])) { 8359 this.values[this.index] = ''; 8360 } 8361 this.values[this.index] += v; 8362 } 8363 } 8364 8365 /** 8366 * Get the tokens in the mask string 8367 */ 8368 var getTokens = function(str) { 8369 if (this.type == 'general') { 8370 var t = [].concat(tokens.general); 8371 } else { 8372 var t = [].concat(tokens.currency, tokens.datetime, tokens.percentage, tokens.numeric, tokens.text, tokens.general); 8373 } 8374 // Expression to extract all tokens from the string 8375 var e = new RegExp(t.join('|'), 'gi'); 8376 // Extract 8377 return str.match(e); 8378 } 8379 8380 /** 8381 * Get the method of one given token 8382 */ 8383 var getMethod = function(str) { 8384 if (! this.type) { 8385 var types = Object.keys(tokens); 8386 } else if (this.type == 'text') { 8387 var types = [ 'text' ]; 8388 } else if (this.type == 'general') { 8389 var types = [ 'general' ]; 8390 } else if (this.type == 'datetime') { 8391 var types = [ 'numeric', 'datetime', 'general' ]; 8392 } else { 8393 var types = [ 'currency', 'percentage', 'numeric', 'general' ]; 8394 } 8395 8396 // Found 8397 for (var i = 0; i < types.length; i++) { 8398 var type = types[i]; 8399 for (var j = 0; j < tokens[type].length; j++) { 8400 var e = new RegExp(tokens[type][j], 'gi'); 8401 var r = str.match(e); 8402 if (r) { 8403 return { type: type, method: tokens[type][j] } 8404 } 8405 } 8406 } 8407 } 8408 8409 /** 8410 * Identify each method for each token 8411 */ 8412 var getMethods = function(t) { 8413 var result = []; 8414 for (var i = 0; i < t.length; i++) { 8415 var m = getMethod.call(this, t[i]); 8416 if (m) { 8417 result.push(m.method); 8418 } else { 8419 result.push(null); 8420 } 8421 } 8422 8423 // Compatibility with excel 8424 for (var i = 0; i < result.length; i++) { 8425 if (result[i] == 'MM') {
8426 // Not a month, correct to minutes 8427 if (result[i-1] && result[i-1].indexOf('H') >= 0) { 8428 result[i] = 'MI'; 8429 } else if (result[i-2] && result[i-2].indexOf('H') >= 0) { 8430 result[i] = 'MI'; 8431 } else if (result[i+1] && result[i+1].indexOf('S') >= 0) { 8432 result[i] = 'MI'; 8433 } else if (result[i+2] && result[i+2].indexOf('S') >= 0) { 8434 result[i] = 'MI'; 8435 } 8436 } 8437 } 8438 8439 return result; 8440 } 8441 8442 /** 8443 * Get the type for one given token 8444 */ 8445 var getType = function(str) { 8446 var m = getMethod.call(this, str); 8447 if (m) { 8448 var type = m.type; 8449 } 8450 8451 if (type) { 8452 var numeric = 0; 8453 // Make sure the correct type 8454 var t = getTokens.call(this, str); 8455 for (var i = 0; i < t.length; i++) { 8456 m = getMethod.call(this, t[i]); 8457 if (m && isNumeric(m.type)) { 8458 numeric++; 8459 } 8460 } 8461 if (numeric > 1) { 8462 type = 'general'; 8463 } 8464 } 8465 8466 return type; 8467 } 8468 8469 /** 8470 * Parse character per character using the detected tokens in the mask 8471 */ 8472 var parse = function() { 8473 // Parser method for this position 8474 if (typeof(parser[this.methods[this.index]]) == 'function') { 8475 parser[this.methods[this.index]].call(this, this.value[this.position]); 8476 this.position++; 8477 } else { 8478 this.values[this.index] = this.tokens[this.index]; 8479 this.index++; 8480 } 8481 } 8482 8483 var isFormula = function(value) { 8484 var v = (''+value)[0]; 8485 return v == '=' ? true : false; 8486 } 8487 8488 var toPlainString = function(num) { 8489 return (''+ +num).replace(/(-?)(\d*)\.?(\d*)e([+-]\d+)/, 8490 function(a,b,c,d,e) { 8491 return e < 0 8492 ? b + '0.' + Array(1-e-c.length).join(0) + c + d 8493 : b + c + d + Array(e-d.length+1).join(0); 8494 }); 8495 } 8496 8497 /** 8498 * Mask function 8499 * @param {mixed|string} JS input or a string to be parsed 8500 * @param {object|string} When the first param is a string, the second is the mask or object with the mask options 8501 */ 8502 var obj = function(e, config, returnObject) { 8503 // Options 8504 var r = null; 8505 var t = null; 8506 var o = { 8507 // Element 8508 input: null, 8509 // Current value 8510 value: null, 8511 // Mask options 8512 options: {}, 8513 // New values for each token found 8514 values: [], 8515 // Token position 8516 index: 0, 8517 // Character position 8518 position: 0, 8519 // Date raw values 8520 date: [0,0,0,0,0,0], 8521 // Raw number for the numeric values 8522 number: 0, 8523 } 8524 8525 // This is a JavaScript Event 8526 if (typeof(e) == 'object') { 8527 // Element 8528 o.input = e.target; 8529 // Current value 8530 o.value = Value.call(e.target); 8531 // Current caret position 8532 o.caret = Caret.call(e.target); 8533 // Mask 8534 if (t = e.target.getAttribute('data-mask')) { 8535 o.mask = t; 8536 } 8537 // Type 8538 if (t = e.target.getAttribute('data-type')) { 8539 o.type = t; 8540 } 8541 // Options 8542 if (e.target.mask) { 8543 if (e.target.mask.options) { 8544 o.options = e.target.mask.options; 8545 } 8546 if (e.target.mask.locale) { 8547 o.locale = e.target.mask.locale; 8548 } 8549 } else { 8550 // Locale 8551 if (t = e.target.getAttribute('data-locale')) { 8552 o.locale = t; 8553 if (o.mask) { 8554 o.options.style = o.mask; 8555 } 8556 } 8557 } 8558 // Extra configuration 8559 if (e.target.attributes && e.target.attributes.length) { 8560 for (var i = 0; i < e.target.attributes.length; i++) { 8561 var k = e.target.attributes[i].name; 8562 var v = e.target.attributes[i].value; 8563 if (k.substr(0,4) == 'data') { 8564 o.options[k.substr(5)] = v; 8565 } 8566 } 8567 } 8568 } else { 8569 // Options 8570 if (typeof(config) == 'string') { 8571 // Mask 8572 o.mask = config; 8573 } else { 8574 // Mask 8575 var k = Object.keys(config); 8576 for (var i = 0; i < k.length; i++) { 8577 o[k[i]] = config[k[i]]; 8578 } 8579 } 8580 8581 if (typeof(e) === 'number') { 8582 // Get decimal 8583 getDecimal.call(o, o.mask); 8584 // Replace to the correct decimal 8585 e = (''+e).replace('.', o.options.decimal); 8586 } 8587 8588 // Current 8589 o.value = e; 8590 8591 if (o.input) { 8592 // Value 8593 Value.call(o.input, e); 8594 // Focus 8595 jSuites.focus(o.input); 8596 // Caret 8597 o.caret = Caret.call(o.input); 8598 } 8599 } 8600 8601 // Mask detected start the process 8602 if (! isFormula(o.value) && (o.mask || o.locale)) { 8603 // Compatibility fixes 8604 if (o.mask) { 8605 // Remove [] 8606 o.mask = o.mask.replace(new RegExp(/\[h]/),'|h|'); 8607 o.mask = o.mask.replace(new RegExp(/\[.*?\]/),''); 8608 o.mask = o.mask.replace(new RegExp(/\|h\|/),'[h]'); 8609 if (o.mask.indexOf(';') !== -1) { 8610 var t = o.mask.split(';'); 8611 o.mask = t[0]; 8612 } 8613 // Excel mask TODO: Improve 8614 if (o.mask.indexOf('##') !== -1) { 8615 var d = o.mask.split(';'); 8616 if (d[0]) { 8617 d[0] = d[0].replace('*', '\t'); 8618 d[0] = d[0].replace(new RegExp(/_-/g), ' '); 8619 d[0] = d[0].replace(new RegExp(/_/g), ''); 8620 d[0] = d[0].replace('##0.###','##0.000'); 8621 d[0] = d[0].replace('##0.##','##0.00'); 8622 d[0] = d[0].replace('##0.#','##0.0'); 8623 d[0] = d[0].replace('##0,###','##0,000'); 8624 d[0] = d[0].replace('##0,##','##0,00'); 8625 d[0] = d[0].replace('##0,#','##0,0'); 8626 } 8627 o.mask = d[0]; 8628 } 8629 // Get type 8630 if (! o.type) { 8631 o.type = getType.call(o, o.mask); 8632 } 8633 // Get tokens 8634 o.tokens = getTokens.call(o, o.mask); 8635 } 8636 8637 // On new input 8638 if (typeof(e) !== 'object' || ! e.inputType || ! e.inputType.indexOf('insert') || ! e.inputType.indexOf('delete')) { 8639 // Start transformation 8640 if (o.locale) { 8641 if (o.input) { 8642 Format.call(o, o.input, e); 8643 } else { 8644 var newValue = FormatValue.call(o, o.value); 8645 } 8646 } else { 8647 // Get tokens 8648 o.methods = getMethods.call(o, o.tokens); 8649 o.event = e; 8650 8651 // Go through all tokes 8652 while (o.position < o.value.length && typeof(o.tokens[o.index]) !== 'undefined') { 8653 // Get the appropriate parser 8654 parse.call(o); 8655 } 8656 8657 // New value 8658 var newValue = o.values.join(''); 8659 8660 // Add tokens to the end of string only if string is not empty 8661 if (isNumeric(o.type) && newValue !== '') { 8662 // Complement things in the end of the mask 8663 while (typeof(o.tokens[o.index]) !== 'undefined') { 8664 var t = getMethod.call(o, o.tokens[o.index]); 8665 if (t && t.type == 'general') { 8666 o.values[o.index] = o.tokens[o.index]; 8667 } 8668 o.index++; 8669 } 8670 8671 var adjustNumeric = true; 8672 } else { 8673 var adjustNumeric = false;
8674 } 8675 8676 // New value 8677 newValue = o.values.join(''); 8678 8679 // Reset value 8680 if (o.input) { 8681 t = newValue.length - o.value.length; 8682 if (t > 0) { 8683 var caret = o.caret + t; 8684 } else { 8685 var caret = o.caret; 8686 } 8687 Value.call(o.input, newValue, caret, adjustNumeric); 8688 } 8689 } 8690 } 8691 8692 // Update raw data 8693 if (o.input) { 8694 var label = null; 8695 if (isNumeric(o.type)) { 8696 // Extract the number 8697 o.number = Extract.call(o, Value.call(o.input)); 8698 // Keep the raw data as a property of the tag 8699 if (o.type == 'percentage') { 8700 label = o.number / 100; 8701 } else { 8702 label = o.number; 8703 } 8704 } else if (o.type == 'datetime') { 8705 label = getDate.call(o); 8706 8707 if (o.date[0] && o.date[1] && o.date[2]) { 8708 o.input.setAttribute('data-completed', true); 8709 } 8710 } 8711 8712 if (label) { 8713 o.input.setAttribute('data-value', label); 8714 } 8715 } 8716 8717 if (newValue !== undefined) { 8718 if (returnObject) { 8719 return o; 8720 } else { 8721 return newValue; 8722 } 8723 } 8724 } 8725 } 8726 8727 // Get the type of the mask 8728 obj.getType = getType; 8729 8730 // Extract the tokens from a mask 8731 obj.prepare = function(str, o) { 8732 if (! o) { 8733 o = {}; 8734 } 8735 return getTokens.call(o, str); 8736 } 8737 8738 /** 8739 * Apply the mask to a element (legacy) 8740 */ 8741 obj.apply = function(e) { 8742 var v = Value.call(e.target); 8743 if (e.key.length == 1) { 8744 v += e.key; 8745 } 8746 Value.call(e.target, obj(v, e.target.getAttribute('data-mask'))); 8747 } 8748 8749 /** 8750 * Legacy support 8751 */ 8752 obj.run = function(value, mask, decimal) { 8753 return obj(value, { mask: mask, decimal: decimal }); 8754 } 8755 8756 /** 8757 * Extract number from masked string 8758 */ 8759 obj.extract = function(v, options, returnObject) { 8760 if (isBlank(v)) { 8761 return v; 8762 } 8763 if (typeof(options) != 'object') { 8764 return value; 8765 } else { 8766 options = Object.assign({}, options); 8767 8768 if (! options.options) { 8769 options.options = {}; 8770 } 8771 } 8772 8773 // Compatibility 8774 if (! options.mask && options.format) { 8775 options.mask = options.format; 8776 } 8777 8778 // Remove [] 8779 if (options.mask) { 8780 if (options.mask.indexOf(';') !== -1) { 8781 var t = options.mask.split(';'); 8782 options.mask = t[0]; 8783 } 8784 options.mask = options.mask.replace(new RegExp(/\[h]/),'|h|'); 8785 options.mask = options.mask.replace(new RegExp(/\[.*?\]/),''); 8786 options.mask = options.mask.replace(new RegExp(/\|h\|/),'[h]'); 8787 } 8788 8789 // Get decimal 8790 getDecimal.call(options, options.mask); 8791 8792 var type = null; 8793 if (options.type == 'percent' || options.options.style == 'percent') { 8794 type = 'percentage'; 8795 } else if (options.mask) { 8796 type = getType.call(options, options.mask); 8797 } 8798 8799 if (type === 'general') { 8800 var o = obj(v, options, true); 8801 8802 value = v; 8803 } else if (type === 'datetime') { 8804 if (v instanceof Date) { 8805 var t = jSuites.calendar.getDateString(value, options.mask); 8806 } 8807 8808 var o = obj(v, options, true); 8809 8810 if (jSuites.isNumeric(v)) { 8811 value = v; 8812 } else { 8813 var value = extractDate.call(o); 8814 } 8815 } else { 8816 var value = Extract.call(options, v); 8817 // Percentage 8818 if (type == 'percentage') { 8819 value /= 100; 8820 } 8821 var o = options; 8822 } 8823 8824 o.value = value; 8825 8826 if (! o.type && type) { 8827 o.type = type; 8828 } 8829 8830 if (returnObject) { 8831 return o; 8832 } else { 8833 return value; 8834 } 8835 } 8836 8837 /**
8838 * Render 8839 */ 8840 obj.render = function(value, options, fullMask) { 8841 if (isBlank(value)) { 8842 return value; 8843 } 8844 8845 if (typeof(options) != 'object') { 8846 return value; 8847 } else { 8848 options = Object.assign({}, options); 8849 8850 if (! options.options) { 8851 options.options = {}; 8852 } 8853 } 8854 8855 // Compatibility 8856 if (! options.mask && options.format) { 8857 options.mask = options.format; 8858 } 8859 8860 // Remove [] 8861 if (options.mask) { 8862 if (options.mask.indexOf(';') !== -1) { 8863 var t = options.mask.split(';'); 8864 options.mask = t[0]; 8865 } 8866 options.mask = options.mask.replace(new RegExp(/\[h]/),'|h|'); 8867 options.mask = options.mask.replace(new RegExp(/\[.*?\]/),''); 8868 options.mask = options.mask.replace(new RegExp(/\|h\|/),'[h]'); 8869 } 8870 8871 var type = null; 8872 if (options.type == 'percent' || options.options.style == 'percent') { 8873 type = 'percentage'; 8874 } else if (options.mask) { 8875 type = getType.call(options, options.mask); 8876 } else if (value instanceof Date) { 8877 type = 'datetime'; 8878 } 8879 8880 // Fill with blanks 8881 var fillWithBlanks = false; 8882 8883 if (type =='datetime' || options.type == 'calendar') { 8884 var t = jSuites.calendar.getDateString(value, options.mask); 8885 if (t) { 8886 value = t; 8887 } 8888 if (options.mask && fullMask) { 8889 fillWithBlanks = true; 8890 } 8891 } else { 8892 // Percentage 8893 if (type == 'percentage') { 8894 value *= 100; 8895 } 8896 // Number of decimal places 8897 if (typeof(value) === 'number') { 8898 var t = null; 8899 if (options.mask && fullMask && ((''+value).indexOf('e') === -1)) { 8900 var d = getDecimal.call(options, options.mask); 8901 if (options.mask.indexOf(d) !== -1) { 8902 d = options.mask.split(d); 8903 d = (''+d[1].match(/[0-9]+/g)) 8904 d = d.length; 8905 t = value.toFixed(d); 8906 } else { 8907 t = value.toFixed(0); 8908 } 8909 } else if (options.locale && fullMask) { 8910 // Append zeros 8911 var d = (''+value).split('.'); 8912 if (options.options) { 8913 if (typeof(d[1]) === 'undefined') { 8914 d[1] = ''; 8915 } 8916 var len = d[1].length; 8917 if (options.options.minimumFractionDigits > len) { 8918 for (var i = 0; i < options.options.minimumFractionDigits - len; i++) { 8919 d[1] += '0'; 8920 } 8921 } 8922 } 8923 if (! d[1].length) { 8924 t = d[0] 8925 } else { 8926 t = d.join('.'); 8927 } 8928 var len = d[1].length; 8929 if (options.options && options.options.maximumFractionDigits < len) { 8930 t = parseFloat(t).toFixed(options.options.maximumFractionDigits); 8931 } 8932 } else { 8933 t = toPlainString(value); 8934 } 8935 8936 if (t !== null) { 8937 value = t; 8938 // Get decimal 8939 getDecimal.call(options, options.mask); 8940 // Replace to the correct decimal 8941 if (options.options.decimal) { 8942 value = value.replace('.', options.options.decimal); 8943 } 8944 } 8945 } else { 8946 if (options.mask && fullMask) { 8947 fillWithBlanks = true; 8948 } 8949 } 8950 } 8951 8952 if (fillWithBlanks) { 8953 var s = options.mask.length - value.length; 8954 if (s > 0) { 8955 for (var i = 0; i < s; i++) { 8956 value += ' '; 8957 } 8958 } 8959 } 8960 8961 value = obj(value, options); 8962 8963 // Numeric mask, number of zeros 8964 if (fullMask && type === 'numeric') { 8965 var maskZeros = options.mask.match(new RegExp(/^[0]+$/gm)); 8966 if (maskZeros && maskZeros.length === 1) { 8967 var maskLength = maskZeros[0].length; 8968 if (maskLength > 3) { 8969 value = '' + value; 8970 while (value.length < maskLength) { 8971 value = '0' + value; 8972 } 8973 } 8974 } 8975 } 8976 8977 return value; 8978 } 8979 8980 obj.set = function(e, m) { 8981 if (m) { 8982 e.setAttribute('data-mask', m); 8983 // Reset the value 8984 var event = new Event('input', { 8985 bubbles: true, 8986 cancelable: true, 8987 }); 8988 e.dispatchEvent(event); 8989 } 8990 } 8991 8992 if (typeof document !== 'undefined') { 8993 document.addEventListener('input', function(e) { 8994 if (e.target.getAttribute('data-mask') || e.target.mask) { 8995 obj(e); 8996 } 8997 }); 8998 } 8999 9000 return obj; 9001})(); 9002 9003jSuites.modal = (function(el, options) { 9004 var obj = {}; 9005 obj.options = {}; 9006 9007 // Default configuration 9008 var defaults = { 9009 url: null, 9010 onopen: null, 9011 onclose: null, 9012 onload: null,
vendor: 77,883 bytes, lines 9013-11549
9013 closed: false, 9014 width: null, 9015 height: null, 9016 title: null, 9017 padding: null, 9018 backdrop: true, 9019 icon: null, 9020 }; 9021 9022 // Loop through our object 9023 for (var property in defaults) { 9024 if (options && options.hasOwnProperty(property)) { 9025 obj.options[property] = options[property]; 9026 } else { 9027 obj.options[property] = defaults[property]; 9028 } 9029 } 9030 9031 // Title 9032 if (! obj.options.title && el.getAttribute('title')) { 9033 obj.options.title = el.getAttribute('title'); 9034 } 9035 9036 var temp = document.createElement('div'); 9037 while (el.children[0]) { 9038 temp.appendChild(el.children[0]); 9039 } 9040 9041 obj.title = document.createElement('div'); 9042 obj.title.className = 'jmodal_title'; 9043 if (obj.options.icon) { 9044 obj.title.setAttribute('data-icon', obj.options.icon); 9045 } 9046 9047 obj.content = document.createElement('div'); 9048 obj.content.className = 'jmodal_content'; 9049 obj.content.innerHTML = el.innerHTML; 9050 9051 while (temp.children[0]) { 9052 obj.content.appendChild(temp.children[0]); 9053 } 9054 9055 obj.container = document.createElement('div'); 9056 obj.container.className = 'jmodal'; 9057 obj.container.appendChild(obj.title); 9058 obj.container.appendChild(obj.content); 9059 9060 if (obj.options.padding) { 9061 obj.content.style.padding = obj.options.padding; 9062 } 9063 if (obj.options.width) { 9064 obj.container.style.width = obj.options.width; 9065 } 9066 if (obj.options.height) { 9067 obj.container.style.height = obj.options.height; 9068 } 9069 if (obj.options.title) { 9070 var title = document.createElement('h4'); 9071 title.innerText = obj.options.title; 9072 obj.title.appendChild(title); 9073 } 9074 9075 el.innerHTML = ''; 9076 el.style.display = 'none'; 9077 el.appendChild(obj.container); 9078 9079 // Backdrop 9080 if (obj.options.backdrop) { 9081 var backdrop = document.createElement('div'); 9082 backdrop.className = 'jmodal_backdrop'; 9083 backdrop.onclick = function () { 9084 obj.close(); 9085 } 9086 el.appendChild(backdrop); 9087 } 9088 9089 obj.open = function() { 9090 el.style.display = 'block'; 9091 // Fullscreen 9092 var rect = obj.container.getBoundingClientRect(); 9093 if (jSuites.getWindowWidth() < rect.width) { 9094 obj.container.style.top = ''; 9095 obj.container.style.left = ''; 9096 obj.container.classList.add('jmodal_fullscreen'); 9097 jSuites.animation.slideBottom(obj.container, 1); 9098 } else { 9099 if (obj.options.backdrop) { 9100 backdrop.style.display = 'block'; 9101 } 9102 } 9103 // Event 9104 if (typeof(obj.options.onopen) == 'function') { 9105 obj.options.onopen(el, obj); 9106 } 9107 } 9108 9109 obj.resetPosition = function() { 9110 obj.container.style.top = ''; 9111 obj.container.style.left = ''; 9112 } 9113 9114 obj.isOpen = function() { 9115 return el.style.display != 'none' ? true : false; 9116 } 9117 9118 obj.close = function() { 9119 if (obj.isOpen()) { 9120 el.style.display = 'none'; 9121 if (obj.options.backdrop) { 9122 // Backdrop 9123 backdrop.style.display = ''; 9124 } 9125 // Remove fullscreen class 9126 obj.container.classList.remove('jmodal_fullscreen'); 9127 // Event 9128 if (typeof(obj.options.onclose) == 'function') { 9129 obj.options.onclose(el, obj); 9130 } 9131 } 9132 } 9133 9134 if (! jSuites.modal.hasEvents) { 9135 // Position 9136 var tracker = null; 9137 9138 document.addEventListener('keydown', function(e) { 9139 if (e.which == 27) { 9140 var modals = document.querySelectorAll('.jmodal'); 9141 for (var i = 0; i < modals.length; i++) { 9142 modals[i].parentNode.modal.close(); 9143 } 9144 } 9145 }); 9146 9147 document.addEventListener('mouseup', function(e) { 9148 var item = jSuites.findElement(e.target, 'jmodal'); 9149 if (item) { 9150 // Get target info 9151 var rect = item.getBoundingClientRect(); 9152 9153 if (e.changedTouches && e.changedTouches[0]) { 9154 var x = e.changedTouches[0].clientX; 9155 var y = e.changedTouches[0].clientY; 9156 } else { 9157 var x = e.clientX; 9158 var y = e.clientY; 9159 } 9160 9161 if (rect.width - (x - rect.left) < 50 && (y - rect.top) < 50) { 9162 item.parentNode.modal.close(); 9163 } 9164 } 9165 9166 if (tracker) { 9167 tracker.element.style.cursor = 'auto'; 9168 tracker = null; 9169 } 9170 }); 9171 9172 document.addEventListener('mousedown', function(e) { 9173 var item = jSuites.findElement(e.target, 'jmodal'); 9174 if (item) { 9175 // Get target info 9176 var rect = item.getBoundingClientRect(); 9177 9178 if (e.changedTouches && e.changedTouches[0]) { 9179 var x = e.changedTouches[0].clientX; 9180 var y = e.changedTouches[0].clientY; 9181 } else { 9182 var x = e.clientX; 9183 var y = e.clientY; 9184 } 9185 9186 if (rect.width - (x - rect.left) < 50 && (y - rect.top) < 50) { 9187 // Do nothing 9188 } else { 9189 if (y - rect.top < 50) { 9190 if (document.selection) { 9191 document.selection.empty(); 9192 } else if ( window.getSelection ) { 9193 window.getSelection().removeAllRanges(); 9194 } 9195 9196 tracker = { 9197 left: rect.left, 9198 top: rect.top, 9199 x: e.clientX, 9200 y: e.clientY, 9201 width: rect.width, 9202 height: rect.height, 9203 element: item, 9204 } 9205 } 9206 } 9207 } 9208 }); 9209 9210 document.addEventListener('mousemove', function(e) { 9211 if (tracker) { 9212 e = e || window.event; 9213 if (e.buttons) { 9214 var mouseButton = e.buttons; 9215 } else if (e.button) { 9216 var mouseButton = e.button; 9217 } else { 9218 var mouseButton = e.which; 9219 } 9220 9221 if (mouseButton) { 9222 tracker.element.style.top = (tracker.top + (e.clientY - tracker.y) + (tracker.height / 2)) + 'px'; 9223 tracker.element.style.left = (tracker.left + (e.clientX - tracker.x) + (tracker.width / 2)) + 'px'; 9224 tracker.element.style.cursor = 'move'; 9225 } else { 9226 tracker.element.style.cursor = 'auto'; 9227 } 9228 } 9229 }); 9230 9231 jSuites.modal.hasEvents = true; 9232 } 9233 9234 if (obj.options.url) { 9235 jSuites.ajax({ 9236 url: obj.options.url, 9237 method: 'GET', 9238 dataType: 'text/html', 9239 success: function(data) { 9240 obj.content.innerHTML = data; 9241 9242 if (! obj.options.closed) { 9243 obj.open(); 9244 } 9245 9246 if (typeof(obj.options.onload) === 'function') { 9247 obj.options.onload(obj); 9248 } 9249 } 9250 }); 9251 } else { 9252 if (! obj.options.closed) { 9253 obj.open(); 9254 } 9255 9256 if (typeof(obj.options.onload) === 'function') { 9257 obj.options.onload(obj); 9258 } 9259 } 9260 9261 // Keep object available from the node 9262 el.modal = obj; 9263 9264 return obj; 9265}); 9266 9267 9268jSuites.notification = (function(options) { 9269 var obj = {}; 9270 obj.options = {}; 9271 9272 // Default configuration 9273 var defaults = { 9274 icon: null, 9275 name: 'Notification', 9276 date: null, 9277 error: null, 9278 title: null, 9279 message: null, 9280 timeout: 4000, 9281 autoHide: true, 9282 closeable: true, 9283 }; 9284 9285 // Loop through our object 9286 for (var property in defaults) { 9287 if (options && options.hasOwnProperty(property)) { 9288 obj.options[property] = options[property]; 9289 } else { 9290 obj.options[property] = defaults[property]; 9291 } 9292 } 9293 9294 var notification = document.createElement('div'); 9295 notification.className = 'jnotification'; 9296 9297 if (obj.options.error) { 9298 notification.classList.add('jnotification-error'); 9299 } 9300 9301 var notificationContainer = document.createElement('div'); 9302 notificationContainer.className = 'jnotification-container'; 9303 notification.appendChild(notificationContainer); 9304 9305 var notificationHeader = document.createElement('div'); 9306 notificationHeader.className = 'jnotification-header'; 9307 notificationContainer.appendChild(notificationHeader); 9308 9309 var notificationImage = document.createElement('div'); 9310 notificationImage.className = 'jnotification-image'; 9311 notificationHeader.appendChild(notificationImage); 9312 9313 if (obj.options.icon) { 9314 var notificationIcon = document.createElement('img'); 9315 notificationIcon.src = obj.options.icon; 9316 notificationImage.appendChild(notificationIcon); 9317 } 9318 9319 var notificationName = document.createElement('div'); 9320 notificationName.className = 'jnotification-name'; 9321 notificationName.innerHTML = obj.options.name; 9322 notificationHeader.appendChild(notificationName); 9323 9324 if (obj.options.closeable == true) { 9325 var notificationClose = document.createElement('div'); 9326 notificationClose.className = 'jnotification-close'; 9327 notificationClose.onclick = function() { 9328 obj.hide(); 9329 } 9330 notificationHeader.appendChild(notificationClose); 9331 } 9332 9333 var notificationDate = document.createElement('div'); 9334 notificationDate.className = 'jnotification-date'; 9335 notificationHeader.appendChild(notificationDate); 9336 9337 var notificationContent = document.createElement('div'); 9338 notificationContent.className = 'jnotification-content'; 9339 notificationContainer.appendChild(notificationContent); 9340 9341 if (obj.options.title) { 9342 var notificationTitle = document.createElement('div'); 9343 notificationTitle.className = 'jnotification-title'; 9344 notificationTitle.innerHTML = obj.options.title; 9345 notificationContent.appendChild(notificationTitle); 9346 } 9347 9348 var notificationMessage = document.createElement('div'); 9349 notificationMessage.className = 'jnotification-message'; 9350 notificationMessage.innerHTML = obj.options.message; 9351 notificationContent.appendChild(notificationMessage); 9352 9353 obj.show = function() { 9354 document.body.appendChild(notification); 9355 if (jSuites.getWindowWidth() > 800) { 9356 jSuites.animation.fadeIn(notification); 9357 } else { 9358 jSuites.animation.slideTop(notification, 1); 9359 } 9360 } 9361 9362 obj.hide = function() { 9363 if (jSuites.getWindowWidth() > 800) { 9364 jSuites.animation.fadeOut(notification, function() { 9365 if (notification.parentNode) { 9366 notification.parentNode.removeChild(notification); 9367 if (notificationTimeout) { 9368 clearTimeout(notificationTimeout); 9369 } 9370 } 9371 }); 9372 } else { 9373 jSuites.animation.slideTop(notification, 0, function() { 9374 if (notification.parentNode) { 9375 notification.parentNode.removeChild(notification); 9376 if (notificationTimeout) { 9377 clearTimeout(notificationTimeout); 9378 } 9379 } 9380 }); 9381 } 9382 }; 9383 9384 obj.show(); 9385 9386 if (obj.options.autoHide == true) { 9387 var notificationTimeout = setTimeout(function() { 9388 obj.hide(); 9389 }, obj.options.timeout); 9390 } 9391 9392 if (jSuites.getWindowWidth() < 800) { 9393 notification.addEventListener("swipeup", function(e) { 9394 obj.hide(); 9395 e.preventDefault(); 9396 e.stopPropagation(); 9397 }); 9398 } 9399 9400 return obj; 9401}); 9402 9403jSuites.notification.isVisible = function() { 9404 var j = document.querySelector('.jnotification'); 9405 return j && j.parentNode ? true : false; 9406} 9407 9408// More palettes https://coolors.co/ or https://gka.github.io/palettes/#/10|s|003790,005647,ffffe0|ffffe0,ff005e,93003a|1|1 9409jSuites.palette = (function() { 9410 /** 9411 * Available palettes 9412 */ 9413 var palette = { 9414 material: [ 9415 [ "#ffebee", "#fce4ec", "#f3e5f5", "#e8eaf6", "#e3f2fd", "#e0f7fa", "#e0f2f1", "#e8f5e9", "#f1f8e9", "#f9fbe7", "#fffde7", "#fff8e1", "#fff3e0", "#fbe9e7", "#efebe9", "#fafafa", "#eceff1" ], 9416 [ "#ffcdd2", "#f8bbd0", "#e1bee7", "#c5cae9", "#bbdefb", "#b2ebf2", "#b2dfdb", "#c8e6c9", "#dcedc8", "#f0f4c3", "#fff9c4", "#ffecb3", "#ffe0b2", "#ffccbc", "#d7ccc8", "#f5f5f5", "#cfd8dc" ], 9417 [ "#ef9a9a", "#f48fb1", "#ce93d8", "#9fa8da", "#90caf9", "#80deea", "#80cbc4", "#a5d6a7", "#c5e1a5", "#e6ee9c", "#fff59d", "#ffe082", "#ffcc80", "#ffab91", "#bcaaa4", "#eeeeee", "#b0bec5" ], 9418 [ "#e57373", "#f06292", "#ba68c8", "#7986cb", "#64b5f6", "#4dd0e1", "#4db6ac", "#81c784", "#aed581", "#dce775", "#fff176", "#ffd54f", "#ffb74d", "#ff8a65", "#a1887f", "#e0e0e0", "#90a4ae" ], 9419 [ "#ef5350", "#ec407a", "#ab47bc", "#5c6bc0", "#42a5f5", "#26c6da", "#26a69a", "#66bb6a", "#9ccc65", "#d4e157", "#ffee58", "#ffca28", "#ffa726", "#ff7043", "#8d6e63", "#bdbdbd", "#78909c" ], 9420 [ "#f44336", "#e91e63", "#9c27b0", "#3f51b5", "#2196f3", "#00bcd4", "#009688", "#4caf50", "#8bc34a", "#cddc39", "#ffeb3b", "#ffc107", "#ff9800", "#ff5722", "#795548", "#9e9e9e", "#607d8b" ], 9421 [ "#e53935", "#d81b60", "#8e24aa", "#3949ab", "#1e88e5", "#00acc1", "#00897b", "#43a047", "#7cb342", "#c0ca33", "#fdd835", "#ffb300", "#fb8c00", "#f4511e", "#6d4c41", "#757575", "#546e7a" ], 9422 [ "#d32f2f", "#c2185b", "#7b1fa2", "#303f9f", "#1976d2", "#0097a7", "#00796b", "#388e3c", "#689f38", "#afb42b", "#fbc02d", "#ffa000", "#f57c00", "#e64a19", "#5d4037", "#616161", "#455a64" ], 9423 [ "#c62828", "#ad1457", "#6a1b9a", "#283593", "#1565c0", "#00838f", "#00695c", "#2e7d32", "#558b2f", "#9e9d24", "#f9a825", "#ff8f00", "#ef6c00", "#d84315", "#4e342e", "#424242", "#37474f" ], 9424 [ "#b71c1c", "#880e4f", "#4a148c", "#1a237e", "#0d47a1", "#006064", "#004d40", "#1b5e20", "#33691e", "#827717", "#f57f17", "#ff6f00", "#e65100", "#bf360c", "#3e2723", "#212121", "#263238" ], 9425 ], 9426 fire: [ 9427 ["0b1a6d","840f38","b60718","de030b","ff0c0c","fd491c","fc7521","faa331","fbb535","ffc73a"], 9428 ["071147","5f0b28","930513","be0309","ef0000","fa3403","fb670b","f9991b","faad1e","ffc123"], 9429 ["03071e","370617","6a040f","9d0208","d00000","dc2f02","e85d04","f48c06","faa307","ffba08"], 9430 ["020619","320615","61040d","8c0207","bc0000","c82a02","d05203","db7f06","e19405","efab00"], 9431 ["020515","2d0513","58040c","7f0206","aa0000","b62602","b94903","c57205","ca8504","d89b00"], 9432 ], 9433 baby: [ 9434 ["eddcd2","fff1e6","fde2e4","fad2e1","c5dedd","dbe7e4","f0efeb","d6e2e9","bcd4e6","99c1de"], 9435 ["e1c4b3","ffd5b5","fab6ba","f5a8c4","aacecd","bfd5cf","dbd9d0","baceda","9dc0db","7eb1d5"], 9436 ["daa990","ffb787","f88e95","f282a9","8fc4c3","a3c8be","cec9b3","9dbcce","82acd2","649dcb"], 9437 ["d69070","ff9c5e","f66770","f05f8f","74bbb9","87bfae","c5b993","83aac3","699bca","4d89c2"], 9438 ["c97d5d","f58443","eb4d57","e54a7b","66a9a7","78ae9c","b5a67e","7599b1","5c88b7","4978aa"], 9439 ], 9440 chart: [ 9441 ['#C1D37F','#4C5454','#FFD275','#66586F','#D05D5B','#C96480','#95BF8F','#6EA240','#0F0F0E','#EB8258','#95A3B3','#995D81'], 9442 ], 9443 } 9444 9445 /** 9446 * Get a pallete 9447 */ 9448 var component = function(o) { 9449 // Otherwise get palette value 9450 if (palette[o]) { 9451 return palette[o]; 9452 } else { 9453 return palette.material; 9454 } 9455 } 9456 9457 component.get = function(o) { 9458 // Otherwise get palette value 9459 if (palette[o]) { 9460 return palette[o]; 9461 } else { 9462 return palette; 9463 } 9464 } 9465 9466 component.set = function(o, v) { 9467 palette[o] = v; 9468 } 9469 9470 return component; 9471})(); 9472 9473 9474jSuites.picker = (function(el, options) { 9475 // Already created, update options 9476 if (el.picker) { 9477 return el.picker.setOptions(options, true); 9478 } 9479 9480 // New instance 9481 var obj = { type: 'picker' }; 9482 obj.options = {}; 9483 9484 var dropdownHeader = null; 9485 var dropdownContent = null; 9486 9487 /** 9488 * The element passed is a DOM element 9489 */ 9490 var isDOM = function(o) { 9491 return (o instanceof Element || o instanceof HTMLDocument); 9492 } 9493 9494 /** 9495 * Create the content options 9496 */ 9497 var createContent = function() { 9498 dropdownContent.innerHTML = ''; 9499 9500 // Create items 9501 var keys = Object.keys(obj.options.data); 9502 9503 // Go though all options 9504 for (var i = 0; i < keys.length; i++) { 9505 // Item 9506 var dropdownItem = document.createElement('div'); 9507 dropdownItem.classList.add('jpicker-item'); 9508 dropdownItem.k = keys[i]; 9509 dropdownItem.v = obj.options.data[keys[i]]; 9510 // Label 9511 var item = obj.getLabel(keys[i], dropdownItem); 9512 if (isDOM(item)) { 9513 dropdownItem.appendChild(item); 9514 } else { 9515 dropdownItem.innerHTML = item; 9516 } 9517 // Append 9518 dropdownContent.appendChild(dropdownItem); 9519 } 9520 } 9521 9522 /** 9523 * Set or reset the options for the picker 9524 */ 9525 obj.setOptions = function(options, reset) { 9526 // Default configuration 9527 var defaults = { 9528 value: 0, 9529 data: null, 9530 render: null, 9531 onchange: null, 9532 onmouseover: null, 9533 onselect: null, 9534 onopen: null, 9535 onclose: null, 9536 onload: null, 9537 width: null, 9538 header: true, 9539 right: false, 9540 bottom: false, 9541 content: false, 9542 columns: null, 9543 grid: null, 9544 height: null, 9545 } 9546 9547 // Legacy purpose only 9548 if (options && options.options) { 9549 options.data = options.options; 9550 } 9551 9552 // Loop through the initial configuration 9553 for (var property in defaults) { 9554 if (options && options.hasOwnProperty(property)) { 9555 obj.options[property] = options[property]; 9556 } else { 9557 if (typeof(obj.options[property]) == 'undefined' || reset === true) { 9558 obj.options[property] = defaults[property]; 9559 } 9560 } 9561 } 9562 9563 // Start using the options 9564 if (obj.options.header === false) { 9565 dropdownHeader.style.display = 'none'; 9566 } else { 9567 dropdownHeader.style.display = ''; 9568 } 9569 9570 // Width 9571 if (obj.options.width) { 9572 dropdownHeader.style.width = parseInt(obj.options.width) + 'px'; 9573 } else { 9574 dropdownHeader.style.width = ''; 9575 } 9576 9577 // Height 9578 if (obj.options.height) { 9579 dropdownContent.style.maxHeight = obj.options.height + 'px'; 9580 dropdownContent.style.overflow = 'scroll'; 9581 } else { 9582 dropdownContent.style.overflow = ''; 9583 } 9584 9585 if (obj.options.columns > 0) { 9586 if (! obj.options.grid) { 9587 dropdownContent.classList.add('jpicker-columns'); 9588 dropdownContent.style.width = obj.options.width ? obj.options.width : 36 * obj.options.columns + 'px'; 9589 } else { 9590 dropdownContent.classList.add('jpicker-grid'); 9591 dropdownContent.style.gridTemplateColumns = 'repeat(' + obj.options.grid + ', 1fr)'; 9592 } 9593 } 9594 9595 if (isNaN(obj.options.value)) { 9596 obj.options.value = '0'; 9597 } 9598 9599 // Create list from data 9600 createContent(); 9601 9602 // Set value 9603 obj.setValue(obj.options.value); 9604 9605 // Set options all returns the own instance 9606 return obj; 9607 } 9608 9609 obj.getValue = function() { 9610 return obj.options.value; 9611 } 9612 9613 obj.setValue = function(v) { 9614 // Set label 9615 obj.setLabel(v); 9616 9617 // Update value 9618 obj.options.value = String(v); 9619 9620 // Lemonade JS 9621 if (el.value != obj.options.value) { 9622 el.value = obj.options.value; 9623 if (typeof(el.oninput) == 'function') { 9624 el.oninput({ 9625 type: 'input', 9626 target: el, 9627 value: el.value 9628 }); 9629 } 9630 } 9631 9632 if (dropdownContent.children[v].getAttribute('type') !== 'generic') { 9633 obj.close(); 9634 } 9635 } 9636 9637 obj.getLabel = function(v, item) { 9638 var label = obj.options.data[v] || null; 9639 if (typeof(obj.options.render) == 'function') { 9640 label = obj.options.render(label, item); 9641 } 9642 return label; 9643 } 9644 9645 obj.setLabel = function(v) { 9646 var item; 9647 9648 if (obj.options.content) { 9649 item = '<i class="material-icons">' + obj.options.content + '</i>'; 9650 } else { 9651 item = obj.getLabel(v, null); 9652 } 9653 // Label 9654 if (isDOM(item)) { 9655 dropdownHeader.innerHTML = ''; 9656 dropdownHeader.appendChild(item); 9657 } else { 9658 dropdownHeader.innerHTML = item; 9659 } 9660 } 9661 9662 obj.open = function() { 9663 if (! el.classList.contains('jpicker-focus')) { 9664 // Start tracking the element 9665 jSuites.tracking(obj, true); 9666 9667 // Open picker 9668 el.classList.add('jpicker-focus'); 9669 el.focus(); 9670 9671 var top = 0; 9672 var left = 0; 9673 9674 dropdownContent.style.marginLeft = ''; 9675 9676 var rectHeader = dropdownHeader.getBoundingClientRect(); 9677 var rectContent = dropdownContent.getBoundingClientRect(); 9678 9679 if (window.innerHeight < rectHeader.bottom + rectContent.height || obj.options.bottom) { 9680 top = -1 * (rectContent.height + 4); 9681 } else { 9682 top = rectHeader.height + 4; 9683 } 9684 9685 if (obj.options.right === true) { 9686 left = -1 * rectContent.width + rectHeader.width; 9687 } 9688 9689 if (rectContent.left + left < 0) { 9690 left = left + rectContent.left + 10; 9691 } 9692 if (rectContent.left + rectContent.width > window.innerWidth) { 9693 left = -1 * (10 + rectContent.left + rectContent.width - window.innerWidth); 9694 } 9695 9696 dropdownContent.style.marginTop = parseInt(top) + 'px'; 9697 dropdownContent.style.marginLeft = parseInt(left) + 'px'; 9698 9699 //dropdownContent.style.marginTop 9700 if (typeof obj.options.onopen == 'function') { 9701 obj.options.onopen(el, obj); 9702 } 9703 } 9704 } 9705 9706 obj.close = function() { 9707 if (el.classList.contains('jpicker-focus')) { 9708 el.classList.remove('jpicker-focus'); 9709 9710 // Start tracking the element 9711 jSuites.tracking(obj, false); 9712 9713 if (typeof obj.options.onclose == 'function') { 9714 obj.options.onclose(el, obj); 9715 } 9716 } 9717 } 9718 9719 /** 9720 * Create floating picker 9721 */ 9722 var init = function() { 9723 // Class 9724 el.classList.add('jpicker'); 9725 el.setAttribute('tabindex', '900'); 9726 el.onmousedown = function(e) { 9727 if (! el.classList.contains('jpicker-focus')) { 9728 obj.open(); 9729 } 9730 } 9731 9732 // Dropdown Header 9733 dropdownHeader = document.createElement('div'); 9734 dropdownHeader.classList.add('jpicker-header'); 9735 9736 // Dropdown content 9737 dropdownContent = document.createElement('div'); 9738 dropdownContent.classList.add('jpicker-content'); 9739 dropdownContent.onclick = function(e) { 9740 var item = jSuites.findElement(e.target, 'jpicker-item'); 9741 if (item) { 9742 if (item.parentNode === dropdownContent) { 9743 // Update label 9744 obj.setValue(item.k); 9745 // Call method 9746 if (typeof(obj.options.onchange) == 'function') { 9747 obj.options.onchange.call(obj, el, obj, item.v, item.v, item.k, e); 9748 } 9749 } 9750 } 9751 } 9752 9753 // Append content and header 9754 el.appendChild(dropdownHeader); 9755 el.appendChild(dropdownContent); 9756 9757 // Default value 9758 el.value = options.value || 0; 9759 9760 // Set options 9761 obj.setOptions(options); 9762 9763 if (typeof(obj.options.onload) == 'function') { 9764 obj.options.onload(el, obj); 9765 } 9766 9767 // Change 9768 el.change = obj.setValue; 9769 9770 // Global generic value handler 9771 el.val = function(val) { 9772 if (val === undefined) { 9773 return obj.getValue(); 9774 } else { 9775 obj.setValue(val); 9776 } 9777 } 9778 9779 // Reference 9780 el.picker = obj; 9781 } 9782 9783 init(); 9784 9785 return obj; 9786}); 9787 9788jSuites.progressbar = (function(el, options) { 9789 var obj = {}; 9790 obj.options = {}; 9791 9792 // Default configuration 9793 var defaults = { 9794 value: 0, 9795 onchange: null, 9796 width: null, 9797 }; 9798 9799 // Loop through the initial configuration 9800 for (var property in defaults) { 9801 if (options && options.hasOwnProperty(property)) { 9802 obj.options[property] = options[property]; 9803 } else { 9804 obj.options[property] = defaults[property]; 9805 } 9806 } 9807 9808 // Class 9809 el.classList.add('jprogressbar'); 9810 el.setAttribute('tabindex', 1); 9811 el.setAttribute('data-value', obj.options.value); 9812 9813 var bar = document.createElement('div'); 9814 bar.style.width = obj.options.value + '%'; 9815 bar.style.color = '#fff'; 9816 el.appendChild(bar); 9817 9818 if (obj.options.width) { 9819 el.style.width = obj.options.width; 9820 } 9821 9822 // Set value 9823 obj.setValue = function(value) { 9824 value = parseInt(value); 9825 obj.options.value = value; 9826 bar.style.width = value + '%'; 9827 el.setAttribute('data-value', value + '%'); 9828 9829 if (value < 6) { 9830 el.style.color = '#000'; 9831 } else { 9832 el.style.color = '#fff'; 9833 } 9834 9835 // Update value 9836 obj.options.value = value; 9837 9838 if (typeof(obj.options.onchange) == 'function') { 9839 obj.options.onchange(el, value); 9840 } 9841 9842 // Lemonade JS 9843 if (el.value != obj.options.value) { 9844 el.value = obj.options.value; 9845 if (typeof(el.oninput) == 'function') { 9846 el.oninput({ 9847 type: 'input', 9848 target: el, 9849 value: el.value 9850 }); 9851 } 9852 } 9853 } 9854 9855 obj.getValue = function() { 9856 return obj.options.value; 9857 } 9858 9859 var action = function(e) { 9860 if (e.which) { 9861 // Get target info 9862 var rect = el.getBoundingClientRect(); 9863 9864 if (e.changedTouches && e.changedTouches[0]) { 9865 var x = e.changedTouches[0].clientX; 9866 var y = e.changedTouches[0].clientY; 9867 } else { 9868 var x = e.clientX; 9869 var y = e.clientY; 9870 } 9871 9872 obj.setValue(Math.round((x - rect.left) / rect.width * 100)); 9873 } 9874 } 9875 9876 // Events 9877 if ('touchstart' in document.documentElement === true) { 9878 el.addEventListener('touchstart', action); 9879 el.addEventListener('touchend', action); 9880 } else { 9881 el.addEventListener('mousedown', action); 9882 el.addEventListener("mousemove", action); 9883 } 9884 9885 // Change 9886 el.change = obj.setValue; 9887 9888 // Global generic value handler 9889 el.val = function(val) { 9890 if (val === undefined) { 9891 return obj.getValue(); 9892 } else { 9893 obj.setValue(val); 9894 } 9895 } 9896 9897 // Reference 9898 el.progressbar = obj; 9899 9900 return obj; 9901}); 9902 9903jSuites.rating = (function(el, options) { 9904 // Already created, update options 9905 if (el.rating) { 9906 return el.rating.setOptions(options, true); 9907 } 9908 9909 // New instance 9910 var obj = {}; 9911 obj.options = {}; 9912 9913 obj.setOptions = function(options, reset) { 9914 // Default configuration 9915 var defaults = { 9916 number: 5, 9917 value: 0, 9918 tooltip: [ 'Very bad', 'Bad', 'Average', 'Good', 'Very good' ], 9919 onchange: null, 9920 }; 9921 9922 // Loop through the initial configuration 9923 for (var property in defaults) { 9924 if (options && options.hasOwnProperty(property)) { 9925 obj.options[property] = options[property]; 9926 } else { 9927 if (typeof(obj.options[property]) == 'undefined' || reset === true) { 9928 obj.options[property] = defaults[property]; 9929 } 9930 } 9931 } 9932 9933 // Make sure the container is empty 9934 el.innerHTML = ''; 9935 9936 // Add elements 9937 for (var i = 0; i < obj.options.number; i++) { 9938 var div = document.createElement('div'); 9939 div.setAttribute('data-index', (i + 1)) 9940 div.setAttribute('title', obj.options.tooltip[i]) 9941 el.appendChild(div); 9942 } 9943 9944 // Selected option 9945 if (obj.options.value) { 9946 for (var i = 0; i < obj.options.number; i++) { 9947 if (i < obj.options.value) { 9948 el.children[i].classList.add('jrating-selected'); 9949 } 9950 } 9951 } 9952 9953 return obj; 9954 } 9955 9956 // Set value 9957 obj.setValue = function(index) { 9958 for (var i = 0; i < obj.options.number; i++) { 9959 if (i < index) { 9960 el.children[i].classList.add('jrating-selected'); 9961 } else { 9962 el.children[i].classList.remove('jrating-over'); 9963 el.children[i].classList.remove('jrating-selected'); 9964 } 9965 } 9966 9967 obj.options.value = index; 9968 9969 if (typeof(obj.options.onchange) == 'function') { 9970 obj.options.onchange(el, index); 9971 } 9972 9973 // Lemonade JS 9974 if (el.value != obj.options.value) { 9975 el.value = obj.options.value; 9976 if (typeof(el.oninput) == 'function') { 9977 el.oninput({ 9978 type: 'input', 9979 target: el, 9980 value: el.value 9981 }); 9982 } 9983 } 9984 } 9985 9986 obj.getValue = function() { 9987 return obj.options.value; 9988 } 9989 9990 var init = function() { 9991 // Start plugin 9992 obj.setOptions(options); 9993 9994 // Class 9995 el.classList.add('jrating'); 9996 9997 // Events 9998 el.addEventListener("click", function(e) { 9999 var index = e.target.getAttribute('data-index'); 10000 if (index != undefined) { 10001 if (index == obj.options.value) { 10002 obj.setValue(0); 10003 } else { 10004 obj.setValue(index); 10005 } 10006 } 10007 }); 10008 10009 el.addEventListener("mouseover", function(e) { 10010 var index = e.target.getAttribute('data-index'); 10011 for (var i = 0; i < obj.options.number; i++) { 10012 if (i < index) { 10013 el.children[i].classList.add('jrating-over'); 10014 } else { 10015 el.children[i].classList.remove('jrating-over'); 10016 } 10017 } 10018 }); 10019 10020 el.addEventListener("mouseout", function(e) { 10021 for (var i = 0; i < obj.options.number; i++) { 10022 el.children[i].classList.remove('jrating-over'); 10023 } 10024 }); 10025 10026 // Change 10027 el.change = obj.setValue; 10028 10029 // Global generic value handler 10030 el.val = function(val) { 10031 if (val === undefined) { 10032 return obj.getValue(); 10033 } else { 10034 obj.setValue(val); 10035 } 10036 } 10037 10038 // Reference 10039 el.rating = obj; 10040 } 10041 10042 init(); 10043 10044 return obj; 10045}); 10046 10047 10048jSuites.search = (function(el, options) { 10049 if (el.search) { 10050 return el.search; 10051 } 10052 10053 var index = null; 10054 10055 var select = function(e) { 10056 if (e.target.classList.contains('jsearch_item')) { 10057 var element = e.target; 10058 } else { 10059 var element = e.target.parentNode; 10060 } 10061 10062 obj.selectIndex(element); 10063 e.preventDefault(); 10064 } 10065 10066 var createList = function(data) { 10067 // Reset container 10068 container.innerHTML = ''; 10069 // Print results 10070 if (! data.length) { 10071 // Show container 10072 el.style.display = ''; 10073 } else { 10074 // Show container 10075 el.style.display = 'block'; 10076 10077 // Show items (only 10) 10078 var len = data.length < 11 ? data.length : 10; 10079 for (var i = 0; i < len; i++) { 10080 if (typeof(data[i]) == 'string') { 10081 var text = data[i]; 10082 var value = data[i]; 10083 } else { 10084 // Legacy 10085 var text = data[i].text; 10086 if (! text && data[i].name) { 10087 text = data[i].name; 10088 } 10089 var value = data[i].value; 10090 if (! value && data[i].id) { 10091 value = data[i].id; 10092 } 10093 } 10094 10095 var div = document.createElement('div'); 10096 div.setAttribute('data-value', value); 10097 div.setAttribute('data-text', text); 10098 div.className = 'jsearch_item'; 10099 10100 if (data[i].id) { 10101 div.setAttribute('id', data[i].id) 10102 } 10103 10104 if (obj.options.forceSelect && i == 0) { 10105 div.classList.add('selected'); 10106 } 10107 var img = document.createElement('img'); 10108 if (data[i].image) { 10109 img.src = data[i].image; 10110 } else { 10111 img.style.display = 'none'; 10112 } 10113 div.appendChild(img); 10114 10115 var item = document.createElement('div'); 10116 item.innerHTML = text; 10117 div.appendChild(item); 10118 10119 // Append item to the container 10120 container.appendChild(div); 10121 } 10122 } 10123 } 10124 10125 var execute = function(str) { 10126 if (str != obj.terms) { 10127 // New terms 10128 obj.terms = str; 10129 // New index 10130 if (obj.options.forceSelect) { 10131 index = 0; 10132 } else { 10133 index = null; 10134 } 10135 // Array or remote search 10136 if (Array.isArray(obj.options.data)) { 10137 var test = function(o) { 10138 if (typeof(o) == 'string') { 10139 if ((''+o).toLowerCase().search(str.toLowerCase()) >= 0) { 10140 return true; 10141 } 10142 } else { 10143 for (var key in o) { 10144 var value = o[key]; 10145 if ((''+value).toLowerCase().search(str.toLowerCase()) >= 0) { 10146 return true; 10147 } 10148 } 10149 } 10150 return false; 10151 } 10152 10153 var results = obj.options.data.filter(function(item) { 10154 return test(item); 10155 }); 10156 10157 // Show items 10158 createList(results); 10159 } else { 10160 // Get remove results 10161 jSuites.ajax({ 10162 url: obj.options.data + str, 10163 method: 'GET', 10164 dataType: 'json', 10165 success: function(data) { 10166 // Show items 10167 createList(data); 10168 } 10169 }); 10170 } 10171 } 10172 } 10173 10174 // Search timer 10175 var timer = null; 10176 10177 // Search methods 10178 var obj = function(str) { 10179 if (timer) { 10180 clearTimeout(timer); 10181 } 10182 timer = setTimeout(function() { 10183 execute(str); 10184 }, 500); 10185 } 10186 if(options.forceSelect === null) { 10187 options.forceSelect = true; 10188 } 10189 obj.options = { 10190 data: options.data || null, 10191 input: options.input || null, 10192 searchByNode: options.searchByNode || null, 10193 onselect: options.onselect || null, 10194 forceSelect: options.forceSelect, 10195 onbeforesearch: options.onbeforesearch || null, 10196 }; 10197 10198 obj.selectIndex = function(item) { 10199 var id = item.getAttribute('id'); 10200 var text = item.getAttribute('data-text'); 10201 var value = item.getAttribute('data-value'); 10202 // Onselect 10203 if (typeof(obj.options.onselect) == 'function') { 10204 obj.options.onselect(obj, text, value, id); 10205 } 10206 // Close container 10207 obj.close(); 10208 } 10209 10210 obj.open = function() { 10211 el.style.display = 'block'; 10212 } 10213 10214 obj.close = function() { 10215 if (timer) { 10216 clearTimeout(timer); 10217 } 10218 // Current terms 10219 obj.terms = ''; 10220 // Remove results 10221 container.innerHTML = ''; 10222 // Hide 10223 el.style.display = ''; 10224 } 10225 10226 obj.isOpened = function() { 10227 return el.style.display ? true : false; 10228 } 10229 10230 obj.keydown = function(e) { 10231 if (obj.isOpened()) { 10232 if (e.key == 'Enter') { 10233 // Enter 10234 if (index!==null && container.children[index]) { 10235 obj.selectIndex(container.children[index]); 10236 e.preventDefault(); 10237 } else { 10238 obj.close(); 10239 } 10240 } else if (e.key === 'ArrowUp') { 10241 // Up 10242 if (index!==null && container.children[0]) { 10243 container.children[index].classList.remove('selected'); 10244 if(!obj.options.forceSelect && index === 0) { 10245 index = null; 10246 } else { 10247 index = Math.max(0, index-1); 10248 container.children[index].classList.add('selected'); 10249 } 10250 } 10251 e.preventDefault(); 10252 } else if (e.key === 'ArrowDown') { 10253 // Down 10254 if(index == null) { 10255 index = -1; 10256 } else { 10257 container.children[index].classList.remove('selected'); 10258 } 10259 if (index < 9 && container.children[index+1]) { 10260 index++; 10261 } 10262 container.children[index].classList.add('selected'); 10263 e.preventDefault(); 10264 } 10265 } 10266 } 10267 10268 obj.keyup = function(e) { 10269 if (! obj.options.searchByNode && obj.options.input) { 10270 if (obj.options.input.tagName === 'DIV') { 10271 var terms = obj.options.input.innerText; 10272 } else { 10273 var terms = obj.options.input.value; 10274 } 10275 } else { 10276 // Current node 10277 var node = jSuites.getNode(); 10278 if (node) { 10279 var terms = node.innerText; 10280 } 10281 } 10282 10283 if (typeof(obj.options.onbeforesearch) == 'function') { 10284 var ret = obj.options.onbeforesearch(obj, terms); 10285 if (ret) { 10286 terms = ret; 10287 } else { 10288 if (ret === false) { 10289 // Ignore event 10290 return; 10291 } 10292 } 10293 } 10294 10295 obj(terms); 10296 } 10297 10298 // Add events 10299 if (obj.options.input) { 10300 obj.options.input.addEventListener("keyup", obj.keyup); 10301 obj.options.input.addEventListener("keydown", obj.keydown); 10302 } 10303 10304 // Append element 10305 var container = document.createElement('div'); 10306 container.classList.add('jsearch_container'); 10307 container.onmousedown = select; 10308 el.appendChild(container); 10309 10310 el.classList.add('jsearch'); 10311 el.search = obj; 10312 10313 return obj; 10314}); 10315 10316 10317jSuites.slider = (function(el, options) { 10318 var obj = {}; 10319 obj.options = {}; 10320 obj.currentImage = null; 10321 10322 if (options) { 10323 obj.options = options; 10324 } 10325 10326 // Focus 10327 el.setAttribute('tabindex', '900') 10328 10329 // Items 10330 obj.options.items = []; 10331 10332 if (! el.classList.contains('jslider')) { 10333 el.classList.add('jslider'); 10334 el.classList.add('unselectable'); 10335 10336 if (obj.options.height) { 10337 el.style.minHeight = obj.options.height; 10338 } 10339 if (obj.options.width) { 10340 el.style.width = obj.options.width; 10341 } 10342 if (obj.options.grid) { 10343 el.classList.add('jslider-grid'); 10344 var number = el.children.length; 10345 if (number > 4) { 10346 el.setAttribute('data-total', number - 4); 10347 } 10348 el.setAttribute('data-number', (number > 4 ? 4 : number)); 10349 } 10350 10351 // Add slider counter 10352 var counter = document.createElement('div'); 10353 counter.classList.add('jslider-counter'); 10354 10355 // Move children inside 10356 if (el.children.length > 0) { 10357 // Keep children items 10358 for (var i = 0; i < el.children.length; i++) { 10359 obj.options.items.push(el.children[i]); 10360 10361 // counter click event 10362 var item = document.createElement('div'); 10363 item.onclick = function() { 10364 var index = Array.prototype.slice.call(counter.children).indexOf(this); 10365 obj.show(obj.currentImage = obj.options.items[index]); 10366 } 10367 counter.appendChild(item); 10368 } 10369 } 10370 // Add caption 10371 var caption = document.createElement('div'); 10372 caption.className = 'jslider-caption'; 10373 10374 // Add close buttom 10375 var controls = document.createElement('div'); 10376 var close = document.createElement('div'); 10377 close.className = 'jslider-close'; 10378 close.innerHTML = ''; 10379 10380 close.onclick = function() { 10381 obj.close(); 10382 } 10383 controls.appendChild(caption); 10384 controls.appendChild(close); 10385 } 10386 10387 obj.updateCounter = function(index) { 10388 for (var i = 0; i < counter.children.length; i ++) { 10389 if (counter.children[i].classList.contains('jslider-counter-focus')) { 10390 counter.children[i].classList.remove('jslider-counter-focus'); 10391 break; 10392 } 10393 } 10394 counter.children[index].classList.add('jslider-counter-focus'); 10395 } 10396 10397 obj.show = function(target) { 10398 if (! target) { 10399 var target = el.children[0]; 10400 } 10401 10402 // Focus element 10403 el.classList.add('jslider-focus'); 10404 el.classList.remove('jslider-grid'); 10405 el.appendChild(controls); 10406 el.appendChild(counter); 10407 10408 // Update counter 10409 var index = obj.options.items.indexOf(target); 10410 obj.updateCounter(index); 10411 10412 // Remove display 10413 for (var i = 0; i < el.children.length; i++) { 10414 el.children[i].style.display = ''; 10415 } 10416 target.style.display = 'block'; 10417 10418 // Is there any previous 10419 if (target.previousElementSibling) { 10420 el.classList.add('jslider-left'); 10421 } else { 10422 el.classList.remove('jslider-left'); 10423 } 10424 10425 // Is there any next 10426 if (target.nextElementSibling && target.nextElementSibling.tagName == 'IMG') { 10427 el.classList.add('jslider-right'); 10428 } else { 10429 el.classList.remove('jslider-right'); 10430 } 10431 10432 obj.currentImage = target; 10433 10434 // Vertical image 10435 if (obj.currentImage.offsetHeight > obj.currentImage.offsetWidth) { 10436 obj.currentImage.classList.add('jslider-vertical'); 10437 } 10438 10439 controls.children[0].innerText = obj.currentImage.getAttribute('title'); 10440 } 10441 10442 obj.open = function() { 10443 obj.show(); 10444 10445 // Event 10446 if (typeof(obj.options.onopen) == 'function') { 10447 obj.options.onopen(el); 10448 } 10449 } 10450 10451 obj.close = function() { 10452 // Remove control classes 10453 el.classList.remove('jslider-focus'); 10454 el.classList.remove('jslider-left'); 10455 el.classList.remove('jslider-right'); 10456 // Show as a grid depending on the configuration 10457 if (obj.options.grid) { 10458 el.classList.add('jslider-grid'); 10459 } 10460 // Remove display 10461 for (var i = 0; i < el.children.length; i++) { 10462 el.children[i].style.display = ''; 10463 } 10464 // Remove controls from the component 10465 counter.remove(); 10466 controls.remove(); 10467 // Current image 10468 obj.currentImage = null; 10469 // Event 10470 if (typeof(obj.options.onclose) == 'function') { 10471 obj.options.onclose(el); 10472 } 10473 } 10474 10475 obj.reset = function() { 10476 el.innerHTML = ''; 10477 } 10478 10479 obj.next = function() { 10480 var nextImage = obj.currentImage.nextElementSibling; 10481 if (nextImage && nextImage.tagName === 'IMG') { 10482 obj.show(obj.currentImage.nextElementSibling); 10483 } 10484 } 10485 10486 obj.prev = function() { 10487 if (obj.currentImage.previousElementSibling) { 10488 obj.show(obj.currentImage.previousElementSibling); 10489 } 10490 } 10491 10492 var mouseUp = function(e) { 10493 // Open slider 10494 if (e.target.tagName == 'IMG') { 10495 obj.show(e.target); 10496 } else if (! e.target.classList.contains('jslider-close') && ! (e.target.parentNode.classList.contains('jslider-counter') || e.target.classList.contains('jslider-counter'))){ 10497 // Arrow controls 10498 var offsetX = e.offsetX || e.changedTouches[0].clientX; 10499 if (e.target.clientWidth - offsetX < 40) { 10500 // Show next image 10501 obj.next(); 10502 } else if (offsetX < 40) { 10503 // Show previous image 10504 obj.prev(); 10505 } 10506 } 10507 } 10508 10509 if ('ontouchend' in document.documentElement === true) { 10510 el.addEventListener('touchend', mouseUp); 10511 } else { 10512 el.addEventListener('mouseup', mouseUp); 10513 } 10514 10515 // Add global events 10516 el.addEventListener("swipeleft", function(e) { 10517 obj.next(); 10518 e.preventDefault(); 10519 e.stopPropagation(); 10520 }); 10521 10522 el.addEventListener("swiperight", function(e) { 10523 obj.prev(); 10524 e.preventDefault(); 10525 e.stopPropagation(); 10526 }); 10527 10528 el.addEventListener('keydown', function(e) { 10529 if (e.which == 27) { 10530 obj.close(); 10531 } 10532 }); 10533 10534 el.slider = obj; 10535 10536 return obj; 10537}); 10538 10539jSuites.sorting = (function(el, options) { 10540 var obj = {}; 10541 obj.options = {}; 10542 10543 var defaults = { 10544 pointer: null, 10545 direction: null, 10546 ondragstart: null, 10547 ondragend: null, 10548 ondrop: null, 10549 } 10550 10551 var dragElement = null; 10552 10553 // Loop through the initial configuration 10554 for (var property in defaults) { 10555 if (options && options.hasOwnProperty(property)) { 10556 obj.options[property] = options[property]; 10557 } else { 10558 obj.options[property] = defaults[property]; 10559 } 10560 } 10561 10562 el.classList.add('jsorting'); 10563 10564 el.addEventListener('dragstart', function(e) { 10565 var position = Array.prototype.indexOf.call(e.target.parentNode.children, e.target); 10566 dragElement = { 10567 element: e.target, 10568 o: position, 10569 d: position 10570 } 10571 e.target.style.opacity = '0.25'; 10572 10573 if (typeof(obj.options.ondragstart) == 'function') { 10574 obj.options.ondragstart(el, e.target, e); 10575 } 10576 }); 10577 10578 el.addEventListener('dragover', function(e) { 10579 e.preventDefault(); 10580 10581 if (getElement(e.target) && dragElement) { 10582 if (e.target.getAttribute('draggable') == 'true' && dragElement.element != e.target) { 10583 if (! obj.options.direction) { 10584 var condition = e.target.clientHeight / 2 > e.offsetY; 10585 } else { 10586 var condition = e.target.clientWidth / 2 > e.offsetX; 10587 } 10588 10589 if (condition) { 10590 e.target.parentNode.insertBefore(dragElement.element, e.target); 10591 } else { 10592 e.target.parentNode.insertBefore(dragElement.element, e.target.nextSibling); 10593 } 10594 10595 dragElement.d = Array.prototype.indexOf.call(e.target.parentNode.children, dragElement.element); 10596 } 10597 } 10598 }); 10599 10600 el.addEventListener('dragleave', function(e) { 10601 e.preventDefault(); 10602 }); 10603 10604 el.addEventListener('dragend', function(e) { 10605 e.preventDefault(); 10606 10607 if (dragElement) { 10608 if (typeof(obj.options.ondragend) == 'function') { 10609 obj.options.ondragend(el, dragElement.element, e); 10610 } 10611 10612 // Cancelled put element to the original position 10613 if (dragElement.o < dragElement.d) { 10614 e.target.parentNode.insertBefore(dragElement.element, e.target.parentNode.children[dragElement.o]); 10615 } else { 10616 e.target.parentNode.insertBefore(dragElement.element, e.target.parentNode.children[dragElement.o].nextSibling); 10617 } 10618 10619 dragElement.element.style.opacity = ''; 10620 dragElement = null; 10621 } 10622 }); 10623 10624 el.addEventListener('drop', function(e) { 10625 e.preventDefault(); 10626 10627 if (dragElement && (dragElement.o != dragElement.d)) { 10628 if (typeof(obj.options.ondrop) == 'function') { 10629 obj.options.ondrop(el, dragElement.o, dragElement.d, dragElement.element, e.target, e); 10630 } 10631 } 10632 10633 dragElement.element.style.opacity = ''; 10634 dragElement = null; 10635 }); 10636 10637 var getElement = function(element) { 10638 var sorting = false; 10639 10640 function path (element) { 10641 if (element.className) { 10642 if (element.classList.contains('jsorting')) { 10643 sorting = true; 10644 } 10645 } 10646 10647 if (! sorting) { 10648 path(element.parentNode); 10649 } 10650 } 10651 10652 path(element); 10653 10654 return sorting; 10655 } 10656 10657 for (var i = 0; i < el.children.length; i++) { 10658 if (! el.children[i].hasAttribute('draggable')) { 10659 el.children[i].setAttribute('draggable', 'true'); 10660 } 10661 } 10662 10663 el.val = function() { 10664 var id = null; 10665 var data = []; 10666 for (var i = 0; i < el.children.length; i++) { 10667 if (id = el.children[i].getAttribute('data-id')) { 10668 data.push(id); 10669 } 10670 } 10671 return data; 10672 } 10673 10674 return el; 10675}); 10676 10677jSuites.tabs = (function(el, options) { 10678 var obj = {}; 10679 obj.options = {}; 10680 10681 // Default configuration 10682 var defaults = { 10683 data: [], 10684 position: null, 10685 allowCreate: false, 10686 allowChangePosition: false, 10687 onclick: null, 10688 onload: null, 10689 onchange: null, 10690 oncreate: null, 10691 ondelete: null, 10692 onbeforecreate: null, 10693 onchangeposition: null, 10694 animation: false, 10695 hideHeaders: false, 10696 padding: null, 10697 palette: null, 10698 maxWidth: null, 10699 } 10700 10701 // Loop through the initial configuration 10702 for (var property in defaults) { 10703 if (options && options.hasOwnProperty(property)) { 10704 obj.options[property] = options[property]; 10705 } else { 10706 obj.options[property] = defaults[property]; 10707 } 10708 } 10709 10710 // Class 10711 el.classList.add('jtabs'); 10712 10713 var prev = null; 10714 var next = null; 10715 var border = null; 10716 10717 // Helpers 10718 var setBorder = function(index) { 10719 if (obj.options.animation) { 10720 setTimeout(function() { 10721 var rect = obj.headers.children[index].getBoundingClientRect(); 10722 10723 if (obj.options.palette == 'modern') { 10724 border.style.width = rect.width - 4 + 'px'; 10725 border.style.left = obj.headers.children[index].offsetLeft + 2 + 'px'; 10726 } else { 10727 border.style.width = rect.width + 'px'; 10728 border.style.left = obj.headers.children[index].offsetLeft + 'px'; 10729 } 10730 10731 if (obj.options.position == 'bottom') { 10732 border.style.top = '0px'; 10733 } else { 10734 border.style.bottom = '0px'; 10735 } 10736 }, 150); 10737 } 10738 } 10739 10740 var updateControls = function(x) { 10741 if (typeof(obj.headers.scrollTo) == 'function') { 10742 obj.headers.scrollTo({ 10743 left: x, 10744 behavior: 'smooth', 10745 }); 10746 } else { 10747 obj.headers.scrollLeft = x; 10748 } 10749 10750 if (x <= 1) { 10751 prev.classList.add('disabled'); 10752 } else { 10753 prev.classList.remove('disabled'); 10754 } 10755 10756 if (x >= obj.headers.scrollWidth - obj.headers.offsetWidth) { 10757 next.classList.add('disabled'); 10758 } else { 10759 next.classList.remove('disabled'); 10760 } 10761 10762 if (obj.headers.scrollWidth <= obj.headers.offsetWidth) { 10763 prev.style.display = 'none'; 10764 next.style.display = 'none'; 10765 } else { 10766 prev.style.display = ''; 10767 next.style.display = ''; 10768 } 10769 } 10770 10771 obj.setBorder = setBorder; 10772 10773 // Set value 10774 obj.open = function(index) { 10775 var previous = null; 10776 for (var i = 0; i < obj.headers.children.length; i++) { 10777 if (obj.headers.children[i].classList.contains('jtabs-selected')) { 10778 // Current one 10779 previous = i; 10780 } 10781 // Remote selected 10782 obj.headers.children[i].classList.remove('jtabs-selected'); 10783 if (obj.content.children[i]) { 10784 obj.content.children[i].classList.remove('jtabs-selected'); 10785 } 10786 } 10787 10788 obj.headers.children[index].classList.add('jtabs-selected'); 10789 if (obj.content.children[index]) { 10790 obj.content.children[index].classList.add('jtabs-selected'); 10791 } 10792 10793 if (previous != index && typeof(obj.options.onchange) == 'function') { 10794 if (obj.content.children[index]) { 10795 obj.options.onchange(el, obj, index, obj.headers.children[index], obj.content.children[index]); 10796 } 10797 } 10798 10799 // Hide 10800 if (obj.options.hideHeaders == true && (obj.headers.children.length < 3 && obj.options.allowCreate == false)) { 10801 obj.headers.parentNode.style.display = 'none'; 10802 } else { 10803 // Set border 10804 setBorder(index); 10805 10806 obj.headers.parentNode.style.display = ''; 10807 10808 var x1 = obj.headers.children[index].offsetLeft; 10809 var x2 = x1 + obj.headers.children[index].offsetWidth; 10810 var r1 = obj.headers.scrollLeft; 10811 var r2 = r1 + obj.headers.offsetWidth; 10812 10813 if (! (r1 <= x1 && r2 >= x2)) { 10814 // Out of the viewport 10815 updateControls(x1 - 1); 10816 } 10817 } 10818 } 10819 10820 obj.selectIndex = function(a) { 10821 var index = Array.prototype.indexOf.call(obj.headers.children, a); 10822 if (index >= 0) { 10823 obj.open(index); 10824 } 10825 10826 return index; 10827 } 10828 10829 obj.rename = function(i, title) { 10830 if (! title) { 10831 title = prompt('New title', obj.headers.children[i].innerText); 10832 } 10833 obj.headers.children[i].innerText = title; 10834 obj.open(i); 10835 } 10836 10837 obj.create = function(title, url) { 10838 if (typeof(obj.options.onbeforecreate) == 'function') { 10839 var ret = obj.options.onbeforecreate(el); 10840 if (ret === false) { 10841 return false; 10842 } else { 10843 title = ret; 10844 } 10845 } 10846 10847 var div = obj.appendElement(title); 10848 10849 if (typeof(obj.options.oncreate) == 'function') { 10850 obj.options.oncreate(el, div) 10851 } 10852 10853 setBorder(); 10854 10855 return div; 10856 } 10857 10858 obj.remove = function(index) { 10859 return obj.deleteElement(index); 10860 } 10861 10862 obj.nextNumber = function() { 10863 var num = 0; 10864 for (var i = 0; i < obj.headers.children.length; i++) { 10865 var tmp = obj.headers.children[i].innerText.match(/[0-9].*/); 10866 if (tmp > num) { 10867 num = parseInt(tmp); 10868 } 10869 } 10870 if (! num) { 10871 num = 1; 10872 } else { 10873 num++; 10874 } 10875 10876 return num; 10877 } 10878 10879 obj.deleteElement = function(index) { 10880 if (! obj.headers.children[index]) { 10881 return false; 10882 } else { 10883 obj.headers.removeChild(obj.headers.children[index]); 10884 obj.content.removeChild(obj.content.children[index]); 10885 } 10886 10887 obj.open(0); 10888 10889 if (typeof(obj.options.ondelete) == 'function') { 10890 obj.options.ondelete(el, index) 10891 } 10892 } 10893 10894 obj.appendElement = function(title, cb) { 10895 if (! title) { 10896 var title = prompt('Title?', ''); 10897 } 10898 10899 if (title) { 10900 // Add content 10901 var div = document.createElement('div'); 10902 obj.content.appendChild(div); 10903 10904 // Add headers 10905 var h = document.createElement('div'); 10906 h.innerHTML = title; 10907 h.content = div; 10908 obj.headers.insertBefore(h, obj.headers.lastChild); 10909 10910 // Sortable 10911 if (obj.options.allowChangePosition) { 10912 h.setAttribute('draggable', 'true'); 10913 } 10914 // Open new tab 10915 obj.selectIndex(h); 10916 10917 // Callback 10918 if (typeof(cb) == 'function') { 10919 cb(div, h); 10920 } 10921 10922 // Return element 10923 return div; 10924 } 10925 } 10926 10927 obj.getActive = function() { 10928 for (var i = 0; i < obj.headers.children.length; i++) { 10929 if (obj.headers.children[i].classList.contains('jtabs-selected')) { 10930 return i 10931 } 10932 } 10933 return 0; 10934 } 10935 10936 obj.updateContent = function(position, newContent) { 10937 if (typeof newContent !== 'string') { 10938 var contentItem = newContent; 10939 } else { 10940 var contentItem = document.createElement('div'); 10941 contentItem.innerHTML = newContent; 10942 } 10943 10944 if (obj.content.children[position].classList.contains('jtabs-selected')) { 10945 newContent.classList.add('jtabs-selected'); 10946 } 10947 10948 obj.content.replaceChild(newContent, obj.content.children[position]); 10949 10950 setBorder(); 10951 } 10952 10953 obj.updatePosition = function(f, t) { 10954 // Ondrop update position of content 10955 if (f > t) { 10956 obj.content.insertBefore(obj.content.children[f], obj.content.children[t]); 10957 } else { 10958 obj.content.insertBefore(obj.content.children[f], obj.content.children[t].nextSibling); 10959 } 10960 10961 // Open destination tab 10962 obj.open(t); 10963 10964 // Call event 10965 if (typeof(obj.options.onchangeposition) == 'function') { 10966 obj.options.onchangeposition(obj.headers, f, t); 10967 } 10968 } 10969 10970 obj.move = function(f, t) { 10971 if (f > t) { 10972 obj.headers.insertBefore(obj.headers.children[f], obj.headers.children[t]); 10973 } else { 10974 obj.headers.insertBefore(obj.headers.children[f], obj.headers.children[t].nextSibling); 10975 } 10976 10977 obj.updatePosition(f, t); 10978 } 10979 10980 obj.setBorder = setBorder; 10981 10982 obj.init = function() { 10983 el.innerHTML = ''; 10984 10985 // Make sure the component is blank 10986 obj.headers = document.createElement('div'); 10987 obj.content = document.createElement('div'); 10988 obj.headers.classList.add('jtabs-headers'); 10989 obj.content.classList.add('jtabs-content'); 10990 10991 if (obj.options.palette) { 10992 el.classList.add('jtabs-modern'); 10993 } else { 10994 el.classList.remove('jtabs-modern'); 10995 } 10996 10997 // Padding 10998 if (obj.options.padding) { 10999 obj.content.style.padding = parseInt(obj.options.padding) + 'px'; 11000 } 11001 11002 // Header 11003 var header = document.createElement('div'); 11004 header.className = 'jtabs-headers-container'; 11005 header.appendChild(obj.headers); 11006 if (obj.options.maxWidth) { 11007 header.style.maxWidth = parseInt(obj.options.maxWidth) + 'px'; 11008 } 11009 11010 // Controls 11011 var controls = document.createElement('div'); 11012 controls.className = 'jtabs-controls'; 11013 controls.setAttribute('draggable', 'false'); 11014 header.appendChild(controls); 11015 11016 // Append DOM elements 11017 if (obj.options.position == 'bottom') { 11018 el.appendChild(obj.content); 11019 el.appendChild(header); 11020 } else { 11021 el.appendChild(header); 11022 el.appendChild(obj.content); 11023 } 11024 11025 // New button 11026 if (obj.options.allowCreate == true) { 11027 var add = document.createElement('div'); 11028 add.className = 'jtabs-add'; 11029 add.onclick = function() { 11030 obj.create(); 11031 } 11032 controls.appendChild(add); 11033 } 11034 11035 prev = document.createElement('div'); 11036 prev.className = 'jtabs-prev'; 11037 prev.onclick = function() { 11038 updateControls(obj.headers.scrollLeft - obj.headers.offsetWidth); 11039 } 11040 controls.appendChild(prev); 11041 11042 next = document.createElement('div'); 11043 next.className = 'jtabs-next'; 11044 next.onclick = function() { 11045 updateControls(obj.headers.scrollLeft + obj.headers.offsetWidth); 11046 } 11047 controls.appendChild(next); 11048 11049 // Data 11050 for (var i = 0; i < obj.options.data.length; i++) { 11051 // Title 11052 if (obj.options.data[i].titleElement) { 11053 var headerItem = obj.options.data[i].titleElement; 11054 } else { 11055 var headerItem = document.createElement('div'); 11056 } 11057 // Icon 11058 if (obj.options.data[i].icon) { 11059 var iconContainer = document.createElement('div'); 11060 var icon = document.createElement('i'); 11061 icon.classList.add('material-icons'); 11062 icon.innerHTML = obj.options.data[i].icon; 11063 iconContainer.appendChild(icon); 11064 headerItem.appendChild(iconContainer); 11065 } 11066 // Title 11067 if (obj.options.data[i].title) { 11068 var title = document.createTextNode(obj.options.data[i].title); 11069 headerItem.appendChild(title); 11070 } 11071 // Width 11072 if (obj.options.data[i].width) { 11073 headerItem.style.width = obj.options.data[i].width; 11074 } 11075 // Content 11076 if (obj.options.data[i].contentElement) { 11077 var contentItem = obj.options.data[i].contentElement; 11078 } else { 11079 var contentItem = document.createElement('div'); 11080 contentItem.innerHTML = obj.options.data[i].content; 11081 } 11082 obj.headers.appendChild(headerItem); 11083 obj.content.appendChild(contentItem); 11084 } 11085 11086 // Animation 11087 border = document.createElement('div'); 11088 border.className = 'jtabs-border'; 11089 obj.headers.appendChild(border); 11090 11091 if (obj.options.animation) { 11092 el.classList.add('jtabs-animation'); 11093 } 11094 11095 // Events 11096 obj.headers.addEventListener("click", function(e) { 11097 if (e.target.parentNode.classList.contains('jtabs-headers')) { 11098 var target = e.target; 11099 } else { 11100 if (e.target.tagName == 'I') { 11101 var target = e.target.parentNode.parentNode; 11102 } else { 11103 var target = e.target.parentNode; 11104 } 11105 } 11106 11107 var index = obj.selectIndex(target); 11108 11109 if (typeof(obj.options.onclick) == 'function') { 11110 obj.options.onclick(el, obj, index, obj.headers.children[index], obj.content.children[index]); 11111 } 11112 }); 11113 11114 obj.headers.addEventListener("contextmenu", function(e) { 11115 obj.selectIndex(e.target); 11116 }); 11117 11118 if (obj.headers.children.length) { 11119 // Open first tab 11120 obj.open(0); 11121 } 11122 11123 // Update controls 11124 updateControls(0); 11125 11126 if (obj.options.allowChangePosition == true) { 11127 jSuites.sorting(obj.headers, { 11128 direction: 1, 11129 ondrop: function(a,b,c) { 11130 obj.updatePosition(b,c); 11131 }, 11132 }); 11133 } 11134 11135 if (typeof(obj.options.onload) == 'function') { 11136 obj.options.onload(el, obj); 11137 } 11138 } 11139 11140 // Loading existing nodes as the data 11141 if (el.children[0] && el.children[0].children.length) { 11142 // Create from existing elements 11143 for (var i = 0; i < el.children[0].children.length; i++) { 11144 var item = obj.options.data && obj.options.data[i] ? obj.options.data[i] : {}; 11145 11146 if (el.children[1] && el.children[1].children[i]) { 11147 item.titleElement = el.children[0].children[i]; 11148 item.contentElement = el.children[1].children[i]; 11149 } else { 11150 item.contentElement = el.children[0].children[i]; 11151 } 11152 11153 obj.options.data[i] = item; 11154 } 11155 } 11156 11157 // Remote controller flag 11158 var loadingRemoteData = false; 11159 11160 // Create from data 11161 if (obj.options.data) { 11162 // Append children 11163 for (var i = 0; i < obj.options.data.length; i++) { 11164 if (obj.options.data[i].url) { 11165 jSuites.ajax({ 11166 url: obj.options.data[i].url, 11167 type: 'GET', 11168 dataType: 'text/html', 11169 index: i, 11170 success: function(result) { 11171 obj.options.data[this.index].content = result; 11172 }, 11173 complete: function() { 11174 obj.init(); 11175 } 11176 }); 11177 11178 // Flag loading 11179 loadingRemoteData = true; 11180 } 11181 } 11182 } 11183 11184 if (! loadingRemoteData) { 11185 obj.init(); 11186 } 11187 11188 el.tabs = obj; 11189 11190 return obj; 11191}); 11192 11193jSuites.tags = (function(el, options) { 11194 // Redefine configuration 11195 if (el.tags) { 11196 return el.tags.setOptions(options, true); 11197 } 11198 11199 var obj = { type:'tags' }; 11200 obj.options = {}; 11201 11202 // Limit 11203 var limit = function() { 11204 return obj.options.limit && el.children.length >= obj.options.limit ? true : false; 11205 } 11206 11207 // Search helpers 11208 var search = null; 11209 var searchContainer = null; 11210 11211 obj.setOptions = function(options, reset) { 11212 /** 11213 * @typedef {Object} defaults 11214 * @property {(string|Array)} value - Initial value of the compontent 11215 * @property {number} limit - Max number of tags inside the element 11216 * @property {string} search - The URL for suggestions 11217 * @property {string} placeholder - The default instruction text on the element 11218 * @property {validation} validation - Method to validate the tags 11219 * @property {requestCallback} onbeforechange - Method to be execute before any changes on the element 11220 * @property {requestCallback} onchange - Method to be execute after any changes on the element 11221 * @property {requestCallback} onfocus - Method to be execute when on focus 11222 * @property {requestCallback} onblur - Method to be execute when on blur 11223 * @property {requestCallback} onload - Method to be execute when the element is loaded 11224 */ 11225 var defaults = { 11226 value: '', 11227 limit: null, 11228 limitMessage: null, 11229 search: null, 11230 placeholder: null, 11231 validation: null, 11232 onbeforepaste: null, 11233 onbeforechange: null, 11234 onlimit: null, 11235 onchange: null, 11236 onfocus: null, 11237 onblur: null, 11238 onload: null, 11239 colors: null, 11240 } 11241 11242 // Loop through though the default configuration 11243 for (var property in defaults) { 11244 if (options && options.hasOwnProperty(property)) { 11245 obj.options[property] = options[property]; 11246 } else { 11247 if (typeof(obj.options[property]) == 'undefined' || reset === true) { 11248 obj.options[property] = defaults[property]; 11249 } 11250 } 11251 } 11252 11253 // Placeholder 11254 if (obj.options.placeholder) { 11255 el.setAttribute('data-placeholder', obj.options.placeholder); 11256 } else { 11257 el.removeAttribute('data-placeholder'); 11258 } 11259 el.placeholder = obj.options.placeholder; 11260 11261 // Update value 11262 obj.setValue(obj.options.value); 11263 11264 // Validate items 11265 filter(); 11266 11267 // Create search box 11268 if (obj.options.search) { 11269 if (! searchContainer) { 11270 searchContainer = document.createElement('div'); 11271 el.parentNode.insertBefore(searchContainer, el.nextSibling); 11272 11273 // Create container 11274 search = jSuites.search(searchContainer, { 11275 data: obj.options.search, 11276 onselect: function(a,b,c) { 11277 obj.selectIndex(b,c); 11278 } 11279 }); 11280 } 11281 } else { 11282 if (searchContainer) { 11283 search = null; 11284 searchContainer.remove(); 11285 searchContainer = null; 11286 } 11287 } 11288 11289 return obj; 11290 } 11291 11292 /** 11293 * Add a new tag to the element 11294 * @param {(?string|Array)} value - The value of the new element 11295 */ 11296 obj.add = function(value, focus) { 11297 if (typeof(obj.options.onbeforechange) == 'function') { 11298 var ret = obj.options.onbeforechange(el, obj, obj.options.value, value); 11299 if (ret === false) { 11300 return false; 11301 } else { 11302 if (ret != null) { 11303 value = ret; 11304 } 11305 } 11306 } 11307 11308 // Make sure search is closed 11309 if (search) { 11310 search.close(); 11311 } 11312 11313 if (limit()) { 11314 if (typeof(obj.options.onlimit) == 'function') { 11315 obj.options.onlimit(obj, obj.options.limit); 11316 } else if (obj.options.limitMessage) { 11317 alert(obj.options.limitMessage + ' ' + obj.options.limit); 11318 } 11319 } else { 11320 // Get node 11321 var node = jSuites.getNode(); 11322 11323 if (node && node.parentNode && node.parentNode.classList.contains('jtags') && 11324 node.nextSibling && (! (node.nextSibling.innerText && node.nextSibling.innerText.trim()))) { 11325 div = node.nextSibling; 11326 } else { 11327 // Remove not used last item 11328 if (el.lastChild) { 11329 if (! el.lastChild.innerText.trim()) { 11330 el.removeChild(el.lastChild); 11331 } 11332 } 11333 11334 // Mix argument string or array 11335 if (! value || typeof(value) == 'string') { 11336 var div = createElement(value, value, node); 11337 } else { 11338 for (var i = 0; i <= value.length; i++) { 11339 if (! limit()) { 11340 if (! value[i] || typeof(value[i]) == 'string') { 11341 var t = value[i] || ''; 11342 var v = null; 11343 } else { 11344 var t = value[i].text; 11345 var v = value[i].value; 11346 } 11347 11348 // Add element 11349 var div = createElement(t, v); 11350 } 11351 } 11352 } 11353 11354 // Change 11355 change(); 11356 } 11357 11358 // Place caret 11359 if (focus) { 11360 setFocus(div); 11361 } 11362 } 11363 } 11364 11365 obj.setLimit = function(limit) { 11366 obj.options.limit = limit; 11367 var n = el.children.length - limit; 11368 while (el.children.length > limit) { 11369 el.removeChild(el.lastChild); 11370 } 11371 } 11372 11373 // Remove a item node 11374 obj.remove = function(node) { 11375 // Remove node 11376 node.parentNode.removeChild(node); 11377 // Make sure element is not blank 11378 if (! el.children.length) { 11379 obj.add('', true); 11380 } else { 11381 change(); 11382 } 11383 } 11384 11385 /** 11386 * Get all tags in the element 11387 * @return {Array} data - All tags as an array 11388 */ 11389 obj.getData = function() { 11390 var data = []; 11391 for (var i = 0; i < el.children.length; i++) { 11392 // Get value 11393 var text = el.children[i].innerText.replace("\n", ""); 11394 // Get id 11395 var value = el.children[i].getAttribute('data-value'); 11396 if (! value) { 11397 value = text; 11398 } 11399 // Item 11400 if (text || value) { 11401 data.push({ text: text, value: value }); 11402 } 11403 } 11404 return data; 11405 } 11406 11407 /** 11408 * Get the value of one tag. Null for all tags 11409 * @param {?number} index - Tag index number. Null for all tags. 11410 * @return {string} value - All tags separated by comma 11411 */ 11412 obj.getValue = function(index) { 11413 var value = null; 11414 11415 if (index != null) { 11416 // Get one individual value 11417 value = el.children[index].getAttribute('data-value'); 11418 if (! value) { 11419 value = el.children[index].innerText.replace("\n", ""); 11420 } 11421 } else { 11422 // Get all 11423 var data = []; 11424 for (var i = 0; i < el.children.length; i++) { 11425 value = el.children[i].innerText.replace("\n", ""); 11426 if (value) { 11427 data.push(obj.getValue(i)); 11428 } 11429 } 11430 value = data.join(','); 11431 } 11432 11433 return value; 11434 } 11435 11436 /** 11437 * Set the value of the element based on a string separeted by (,|;|\r\n) 11438 * @param {mixed} value - A string or array object with values 11439 */ 11440 obj.setValue = function(mixed) { 11441 if (! mixed) { 11442 obj.reset(); 11443 } else { 11444 if (el.value != mixed) { 11445 if (Array.isArray(mixed)) { 11446 obj.add(mixed); 11447 } else { 11448 // Remove whitespaces 11449 var text = (''+mixed).trim(); 11450 // Tags 11451 var data = extractTags(text); 11452 // Reset 11453 el.innerHTML = ''; 11454 // Add tags to the element 11455 obj.add(data); 11456 } 11457 } 11458 } 11459 } 11460 11461 /** 11462 * Reset the data from the element 11463 */ 11464 obj.reset = function() { 11465 // Empty class 11466 el.classList.add('jtags-empty'); 11467 // Empty element 11468 el.innerHTML = '<div></div>'; 11469 // Execute changes 11470 change(); 11471 } 11472 11473 /** 11474 * Verify if all tags in the element are valid 11475 * @return {boolean} 11476 */ 11477 obj.isValid = function() { 11478 var test = 0; 11479 for (var i = 0; i < el.children.length; i++) { 11480 if (el.children[i].classList.contains('jtags_error')) { 11481 test++; 11482 } 11483 } 11484 return test == 0 ? true : false; 11485 } 11486 11487 /** 11488 * Add one element from the suggestions to the element 11489 * @param {object} item - Node element in the suggestions container 11490 */ 11491 obj.selectIndex = function(text, value) { 11492 var node = jSuites.getNode(); 11493 if (node) { 11494 // Append text to the caret 11495 node.innerText = text; 11496 // Set node id 11497 if (value) { 11498 node.setAttribute('data-value', value); 11499 } 11500 // Remove any error 11501 node.classList.remove('jtags_error'); 11502 if (! limit()) { 11503 // Add new item 11504 obj.add('', true); 11505 } 11506 } 11507 } 11508 11509 /** 11510 * Search for suggestions 11511 * @param {object} node - Target node for any suggestions 11512 */ 11513 obj.search = function(node) { 11514 // Search for 11515 var terms = node.innerText; 11516 } 11517 11518 // Destroy tags element 11519 obj.destroy = function() { 11520 // Bind events 11521 el.removeEventListener('mouseup', tagsMouseUp); 11522 el.removeEventListener('keydown', tagsKeyDown); 11523 el.removeEventListener('keyup', tagsKeyUp); 11524 el.removeEventListener('paste', tagsPaste); 11525 el.removeEventListener('focus', tagsFocus); 11526 el.removeEventListener('blur', tagsBlur); 11527 11528 // Remove element 11529 el.parentNode.removeChild(el); 11530 } 11531 11532 var setFocus = function(node) { 11533 if (el.children.length) { 11534 var range = document.createRange(); 11535 var sel = window.getSelection(); 11536 if (! node) { 11537 var node = el.childNodes[el.childNodes.length-1]; 11538 } 11539 range.setStart(node, node.length) 11540 range.collapse(true) 11541 sel.removeAllRanges() 11542 sel.addRange(range) 11543 el.scrollLeft = el.scrollWidth; 11544 } 11545 } 11546 11547 var createElement = function(label, value, node) { 11548 var div = document.createElement('div'); 11549 div.innerHTML
vendor: 9,474 bytes, lines 11549-11882
11549 = label ? label : ''; 11550 if (value) { 11551 div.setAttribute('data-value', value); 11552 } 11553 11554 if (node && node.parentNode.classList.contains('jtags')) { 11555 el.insertBefore(div, node.nextSibling); 11556 } else { 11557 el.appendChild(div); 11558 } 11559 11560 return div; 11561 } 11562 11563 var change = function() { 11564 // Value 11565 var value = obj.getValue(); 11566 11567 if (value != obj.options.value) { 11568 obj.options.value = value; 11569 if (typeof(obj.options.onchange) == 'function') { 11570 obj.options.onchange(el, obj, obj.options.value); 11571 } 11572 11573 // Lemonade JS 11574 if (el.value != obj.options.value) { 11575 el.value = obj.options.value; 11576 if (typeof(el.oninput) == 'function') { 11577 el.oninput({ 11578 type: 'input', 11579 target: el, 11580 value: el.value 11581 }); 11582 } 11583 } 11584 } 11585 11586 filter(); 11587 } 11588 11589 /** 11590 * Filter tags 11591 */ 11592 var filter = function() { 11593 for (var i = 0; i < el.children.length; i++) { 11594 if (el.children[i].tagName === 'DIV') { 11595 // Create label design 11596 if (!obj.getValue(i)) { 11597 el.children[i].classList.remove('jtags_label'); 11598 } else { 11599 el.children[i].classList.add('jtags_label'); 11600 11601 // Validation in place 11602 if (typeof (obj.options.validation) == 'function') { 11603 if (obj.getValue(i)) { 11604 if (!obj.options.validation(el.children[i], el.children[i].innerText, el.children[i].getAttribute('data-value'))) { 11605 el.children[i].classList.add('jtags_error'); 11606 } else { 11607 el.children[i].classList.remove('jtags_error'); 11608 } 11609 } else { 11610 el.children[i].classList.remove('jtags_error'); 11611 } 11612 } else { 11613 el.children[i].classList.remove('jtags_error'); 11614 } 11615 } 11616 } 11617 } 11618 11619 isEmpty(); 11620 } 11621 11622 var isEmpty = function() { 11623 // Can't be empty 11624 if (! el.innerText.trim()) { 11625 if (! el.children.length || el.children[0].tagName === 'BR') { 11626 el.innerHTML = ''; 11627 setFocus(createElement()); 11628 } 11629 } else { 11630 el.classList.remove('jtags-empty'); 11631 } 11632 } 11633 11634 /** 11635 * Extract tags from a string 11636 * @param {string} text - Raw string 11637 * @return {Array} data - Array with extracted tags 11638 */ 11639 var extractTags = function(text) { 11640 /** @type {Array} */ 11641 var data = []; 11642 11643 /** @type {string} */ 11644 var word = ''; 11645 11646 // Remove whitespaces 11647 text = text.trim(); 11648 11649 if (text) { 11650 for (var i = 0; i < text.length; i++) { 11651 if (text[i] == ',' || text[i] == ';' || text[i] == '\n') { 11652 if (word) { 11653 data.push(word.trim()); 11654 word = ''; 11655 } 11656 } else { 11657 word += text[i]; 11658 } 11659 } 11660 11661 if (word) { 11662 data.push(word); 11663 } 11664 } 11665 11666 return data; 11667 } 11668 11669 /** @type {number} */ 11670 var anchorOffset = 0; 11671 11672 /** 11673 * Processing event keydown on the element 11674 * @param e {object} 11675 */ 11676 var tagsKeyDown = function(e) { 11677 // Anchoroffset 11678 anchorOffset = window.getSelection().anchorOffset; 11679 11680 // Verify if is empty 11681 isEmpty(); 11682 11683 // Comma 11684 if (e.key === 'Tab' || e.key === ';' || e.key === ',') { 11685 var n = window.getSelection().anchorOffset; 11686 if (n > 1) { 11687 if (limit()) { 11688 if (typeof(obj.options.onlimit) == 'function') { 11689 obj.options.onlimit(obj, obj.options.limit) 11690 } 11691 } else { 11692 obj.add('', true); 11693 } 11694 } 11695 e.preventDefault(); 11696 } else if (e.key == 'Enter') { 11697 if (! search || ! search.isOpened()) { 11698 var n = window.getSelection().anchorOffset; 11699 if (n > 1) { 11700 if (! limit()) { 11701 obj.add('', true); 11702 } 11703 } 11704 e.preventDefault(); 11705 } 11706 } else if (e.key == 'Backspace') { 11707 // Back space - do not let last item to be removed 11708 if (el.children.length == 1 && window.getSelection().anchorOffset < 1) { 11709 e.preventDefault(); 11710 } 11711 } 11712 11713 // Search events 11714 if (search) { 11715 search.keydown(e); 11716 } 11717 11718 // Verify if is empty 11719 isEmpty(); 11720 } 11721 11722 /** 11723 * Processing event keyup on the element 11724 * @param e {object} 11725 */ 11726 var tagsKeyUp = function(e) { 11727 if (e.which == 39) { 11728 // Right arrow 11729 var n = window.getSelection().anchorOffset; 11730 if (n > 1 && n == anchorOffset) { 11731 obj.add('', true); 11732 } 11733 } else if (e.which == 13 || e.which == 38 || e.which == 40) { 11734 e.preventDefault(); 11735 } else { 11736 if (search) { 11737 search.keyup(e); 11738 } 11739 } 11740 11741 filter(); 11742 } 11743 11744 /** 11745 * Processing event paste on the element 11746 * @param e {object} 11747 */ 11748 var tagsPaste = function(e) { 11749 if (e.clipboardData || e.originalEvent.clipboardData) { 11750 var text = (e.originalEvent || e).clipboardData.getData('text/plain'); 11751 } else if (window.clipboardData) { 11752 var text = window.clipboardData.getData('Text'); 11753 } 11754 11755 var data = extractTags(text); 11756 11757 if (typeof(obj.options.onbeforepaste) == 'function') { 11758 var ret = obj.options.onbeforepaste(el, obj, data); 11759 if (ret === false) { 11760 e.preventDefault(); 11761 return false; 11762 } else { 11763 if (ret) { 11764 data = ret; 11765 } 11766 } 11767 } 11768 11769 if (data.length > 1) { 11770 obj.add(data, true); 11771 e.preventDefault(); 11772 } else if (data[0]) { 11773 document.execCommand('insertText', false, data[0]) 11774 e.preventDefault(); 11775 } 11776 } 11777 11778 /** 11779 * Processing event mouseup on the element 11780 * @param e {object} 11781 */ 11782 var tagsMouseUp = function(e) { 11783 if (e.target.parentNode && e.target.parentNode.classList.contains('jtags')) { 11784 if (e.target.classList.contains('jtags_label') || e.target.classList.contains('jtags_error')) { 11785 var rect = e.target.getBoundingClientRect(); 11786 if (rect.width - (e.clientX - rect.left) < 16) { 11787 obj.remove(e.target); 11788 } 11789 } 11790 } 11791 11792 // Set focus in the last item 11793 if (e.target == el) { 11794 setFocus(); 11795 } 11796 } 11797 11798 var tagsFocus = function() { 11799 if (! el.classList.contains('jtags-focus')) { 11800 if (! el.children.length || obj.getValue(el.children.length - 1)) { 11801 if (! limit()) { 11802 createElement(''); 11803 } 11804 } 11805 11806 if (typeof(obj.options.onfocus) == 'function') { 11807 obj.options.onfocus(el, obj, obj.getValue()); 11808 } 11809 11810 el.classList.add('jtags-focus'); 11811 } 11812 } 11813 11814 var tagsBlur = function() { 11815 if (el.classList.contains('jtags-focus')) { 11816 if (search) { 11817 search.close(); 11818 } 11819 11820 for (var i = 0; i < el.children.length - 1; i++) { 11821 // Create label design 11822 if (! obj.getValue(i)) { 11823 el.removeChild(el.children[i]); 11824 } 11825 } 11826 11827 change(); 11828 11829 el.classList.remove('jtags-focus'); 11830 11831 if (typeof(obj.options.onblur) == 'function') { 11832 obj.options.onblur(el, obj, obj.getValue()); 11833 } 11834 } 11835 } 11836 11837 var init = function() { 11838 // Bind events 11839 if ('touchend' in document.documentElement === true) { 11840 el.addEventListener('touchend', tagsMouseUp); 11841 } else { 11842 el.addEventListener('mouseup', tagsMouseUp); 11843 } 11844 11845 el.addEventListener('keydown', tagsKeyDown); 11846 el.addEventListener('keyup', tagsKeyUp); 11847 el.addEventListener('paste', tagsPaste); 11848 el.addEventListener('focus', tagsFocus); 11849 el.addEventListener('blur', tagsBlur); 11850 11851 // Editable 11852 el.setAttribute('contenteditable', true); 11853 11854 // Prepare container 11855 el.classList.add('jtags'); 11856 11857 // Initial options 11858 obj.setOptions(options); 11859 11860 if (typeof(obj.options.onload) == 'function') { 11861 obj.options.onload(el, obj); 11862 } 11863 11864 // Change methods 11865 el.change = obj.setValue; 11866 11867 // Global generic value handler 11868 el.val = function(val) { 11869 if (val === undefined) { 11870 return obj.getValue(); 11871 } else { 11872 obj.setValue(val); 11873 } 11874 } 11875 11876 el.tags = obj; 11877 } 11878 11879 init(); 11880 11881 return obj; 11882}
vendor: 7,559 bytes, lines 11882-12110
11882); 11883 11884jSuites.toolbar = (function(el, options) { 11885 // New instance 11886 var obj = { type:'toolbar' }; 11887 obj.options = {}; 11888 11889 // Default configuration 11890 var defaults = { 11891 app: null, 11892 container: false, 11893 badge: false, 11894 title: false, 11895 responsive: false, 11896 maxWidth: null, 11897 bottom: true, 11898 items: [], 11899 } 11900 11901 // Loop through our object 11902 for (var property in defaults) { 11903 if (options && options.hasOwnProperty(property)) { 11904 obj.options[property] = options[property]; 11905 } else { 11906 obj.options[property] = defaults[property]; 11907 } 11908 } 11909 11910 if (! el && options.app && options.app.el) { 11911 el = document.createElement('div'); 11912 options.app.el.appendChild(el); 11913 } 11914 11915 // Arrow 11916 var toolbarArrow = document.createElement('div'); 11917 toolbarArrow.classList.add('jtoolbar-item'); 11918 toolbarArrow.classList.add('jtoolbar-arrow'); 11919 11920 var toolbarFloating = document.createElement('div'); 11921 toolbarFloating.classList.add('jtoolbar-floating'); 11922 toolbarArrow.appendChild(toolbarFloating); 11923 11924 obj.selectItem = function(element) { 11925 var elements = toolbarContent.children; 11926 for (var i = 0; i < elements.length; i++) { 11927 if (element != elements[i]) { 11928 elements[i].classList.remove('jtoolbar-selected'); 11929 } 11930 } 11931 element.classList.add('jtoolbar-selected'); 11932 } 11933 11934 obj.hide = function() { 11935 jSuites.animation.slideBottom(el, 0, function() { 11936 el.style.display = 'none'; 11937 }); 11938 } 11939 11940 obj.show = function() { 11941 el.style.display = ''; 11942 jSuites.animation.slideBottom(el, 1); 11943 } 11944 11945 obj.get = function() { 11946 return el; 11947 } 11948 11949 obj.setBadge = function(index, value) { 11950 toolbarContent.children[index].children[1].firstChild.innerHTML = value; 11951 } 11952 11953 obj.destroy = function() { 11954 toolbar.remove(); 11955 el.innerHTML = ''; 11956 } 11957 11958 obj.update = function(a, b) { 11959 for (var i = 0; i < toolbarContent.children.length; i++) { 11960 // Toolbar element 11961 var toolbarItem = toolbarContent.children[i]; 11962 // State management 11963 if (typeof(toolbarItem.updateState) == 'function') { 11964 toolbarItem.updateState(el, obj, toolbarItem, a, b); 11965 } 11966 } 11967 for (var i = 0; i < toolbarFloating.children.length; i++) { 11968 // Toolbar element 11969 var toolbarItem = toolbarFloating.children[i]; 11970 // State management 11971 if (typeof(toolbarItem.updateState) == 'function') { 11972 toolbarItem.updateState(el, obj, toolbarItem, a, b); 11973 } 11974 } 11975 } 11976 11977 obj.create = function(items) { 11978 // Reset anything in the toolbar 11979 toolbarContent.innerHTML = ''; 11980 // Create elements in the toolbar 11981 for (var i = 0; i < items.length; i++) { 11982 var toolbarItem = document.createElement('div'); 11983 toolbarItem.classList.add('jtoolbar-item'); 11984 11985 if (items[i].width) { 11986 toolbarItem.style.width = parseInt(items[i].width) + 'px'; 11987 } 11988 11989 if (items[i].k) { 11990 toolbarItem.k = items[i].k; 11991 } 11992 11993 if (items[i].tooltip) { 11994 toolbarItem.setAttribute('title', items[i].tooltip); 11995 } 11996 11997 // Id 11998 if (items[i].id) { 11999 toolbarItem.setAttribute('id', items[i].id); 12000 } 12001 12002 // Selected 12003 if (items[i].updateState) { 12004 toolbarItem.updateState = items[i].updateState; 12005 } 12006 12007 if (items[i].active) { 12008 toolbarItem.classList.add('jtoolbar-active'); 12009 } 12010 12011 if (items[i].disabled) { 12012 toolbarItem.classList.add('jtoolbar-disabled'); 12013 } 12014 12015 if (items[i].type == 'select' || items[i].type == 'dropdown') { 12016 jSuites.picker(toolbarItem, items[i]); 12017 } else if (items[i].type == 'divisor') { 12018 toolbarItem.classList.add('jtoolbar-divisor'); 12019 } else if (items[i].type == 'label') { 12020 toolbarItem.classList.add('jtoolbar-label'); 12021 toolbarItem.innerHTML = items[i].content; 12022 } else { 12023 // Material icons 12024 var toolbarIcon = document.createElement('i'); 12025 if (typeof(items[i].class) === 'undefined') { 12026 toolbarIcon.classList.add('material-icons'); 12027 } else { 12028 var c = items[i].class.split(' '); 12029 for (var j = 0; j < c.length; j++) { 12030 toolbarIcon.classList.add(c[j]); 12031 } 12032 } 12033 toolbarIcon.innerHTML = items[i].content ? items[i].content : ''; 12034 toolbarItem.appendChild(toolbarIcon); 12035 12036 // Badge options 12037 if (obj.options.badge == true) { 12038 var toolbarBadge = document.createElement('div'); 12039 toolbarBadge.classList.add('jbadge'); 12040 var toolbarBadgeContent = document.createElement('div'); 12041 toolbarBadgeContent.innerHTML = items[i].badge ? items[i].badge : ''; 12042 toolbarBadge.appendChild(toolbarBadgeContent); 12043 toolbarItem.appendChild(toolbarBadge); 12044 } 12045 12046 // Title 12047 if (items[i].title) { 12048 if (obj.options.title == true) { 12049 var toolbarTitle = document.createElement('span'); 12050 toolbarTitle.innerHTML = items[i].title; 12051 toolbarItem.appendChild(toolbarTitle); 12052 } else { 12053 toolbarItem.setAttribute('title', items[i].title); 12054 } 12055 } 12056 12057 if (obj.options.app && items[i].route) { 12058 // Route 12059 toolbarItem.route = items[i].route; 12060 // Onclick for route 12061 toolbarItem.onclick = function() { 12062 obj.options.app.pages(this.route); 12063 } 12064 // Create pages 12065 obj.options.app.pages(items[i].route, { 12066 toolbarItem: toolbarItem, 12067 closed: true 12068 }); 12069 } 12070 } 12071 12072 if (items[i].onclick) { 12073 toolbarItem.onclick = items[i].onclick.bind(items[i], el, obj, toolbarItem); 12074 } 12075 12076 toolbarContent.appendChild(toolbarItem); 12077 } 12078 12079 // Fits to the page 12080 setTimeout(function() { 12081 obj.refresh(); 12082 }, 0); 12083 } 12084 12085 obj.open = function() { 12086 toolbarArrow.classList.add('jtoolbar-arrow-selected'); 12087 12088 var rectElement = el.getBoundingClientRect(); 12089 var rect = toolbarFloating.getBoundingClientRect(); 12090 if (rect.bottom > window.innerHeight || obj.options.bottom) { 12091 toolbarFloating.style.bottom = '0'; 12092 } else { 12093 toolbarFloating.style.removeProperty('bottom'); 12094 } 12095 12096 toolbarFloating.style.right = '0'; 12097 12098 toolbarArrow.children[0].focus(); 12099 // Start tracking 12100 jSuites.tracking(obj, true); 12101 } 12102 12103 obj.close = function() { 12104 toolbarArrow.classList.remove('jtoolbar-arrow-selected') 12105 // End tracking 12106 jSuites.tracking(obj, false); 12107 } 12108 12109 obj.refresh = function() { 12110 if (obj.options.responsive == true) {
12111 // Width of the c 12112 var rect = el.parentNode.getBoundingClientRect(); 12113 if (! obj.options.maxWidth) { 12114 obj.options.maxWidth = rect.width; 12115 } 12116 // Available parent space 12117 var available = parseInt(obj.options.maxWidth); 12118 // Remove arrow 12119 if (toolbarArrow.parentNode) { 12120 toolbarArrow.parentNode.removeChild(toolbarArrow); 12121 } 12122 // Move all items to the toolbar 12123 while (toolbarFloating.firstChild) { 12124 toolbarContent.appendChild(toolbarFloating.firstChild); 12125 } 12126 // Toolbar is larger than the parent, move elements to the floating element 12127 if (available < toolbarContent.offsetWidth) { 12128 // Give space to the floating element 12129 available -= 50; 12130 // Move to the floating option 12131 while (toolbarContent.lastChild && available < toolbarContent.offsetWidth) { 12132 toolbarFloating.insertBefore(toolbarContent.lastChild, toolbarFloating.firstChild); 12133 } 12134 } 12135 // Show arrow 12136 if (toolbarFloating.children.length > 0) { 12137 toolbarContent.appendChild(toolbarArrow); 12138 } 12139 } 12140 } 12141 12142 obj.setReadonly = function(state) { 12143 state = state ? 'add' : 'remove'; 12144 el.classList[state]('jtoolbar-disabled'); 12145 } 12146 12147 el.onclick = function(e) { 12148 var element = jSuites.findElement(e.target, 'jtoolbar-item'); 12149 if (element) { 12150 obj.selectItem(element); 12151 } 12152 12153 if (e.target.classList.contains('jtoolbar-arrow')) { 12154 obj.open(); 12155 } 12156 } 12157 12158 window.addEventListener('resize', function() { 12159 obj.refresh(); 12160 }); 12161 12162 // Toolbar 12163 el.classList.add('jtoolbar'); 12164 // Reset content 12165 el.innerHTML = ''; 12166 // Container 12167 if (obj.options.container == true) { 12168 el.classList.add('jtoolbar-container'); 12169 } 12170 // Content 12171 var toolbarContent = document.createElement('div'); 12172 el.appendChild(toolbarContent); 12173 // Special toolbar for mobile applications 12174 if (obj.options.app) { 12175 el.classList.add('jtoolbar-mobile'); 12176 } 12177 // Create toolbar 12178 obj.create(obj.options.items); 12179 // Shortcut 12180 el.toolbar = obj; 12181 12182 return obj; 12183}); 12184 12185jSuites.validations = (function() { 12186 /** 12187 * Options: Object, 12188 * Properties: 12189 * Constraint, 12190 * Reference, 12191 * Value 12192 */ 12193 12194 var isNumeric = function(num) { 12195 return !isNaN(num) && num !== null && num !== ''; 12196 } 12197 12198 var numberCriterias = { 12199 'between': function(value, range) { 12200 return value >= range[0] && value <= range[1]; 12201 }, 12202 'not between': function(value, range) { 12203 return value < range[0] || value > range[1]; 12204 }, 12205 '<': function(value, range) { 12206 return value < range[0]; 12207 }, 12208 '<=': function(value, range) { 12209 return value <= range[0]; 12210 }, 12211 '>': function(value, range) { 12212 return value > range[0]; 12213 }, 12214 '>=': function(value, range) { 12215 return value >= range[0]; 12216 }, 12217 '=': function(value, range) { 12218 return value == range[0]; 12219 }, 12220 '!=': function(value, range) { 12221 return value != range[0]; 12222 }, 12223 } 12224 12225 var dateCriterias = { 12226 'valid date': function() { 12227 return true; 12228 }, 12229 '=': function(value, range) { 12230 return value === range[0]; 12231 }, 12232 '<': function(value, range) { 12233 return value < range[0]; 12234 }, 12235 '<=': function(value, range) { 12236 return value <= range[0]; 12237 }, 12238 '>': function(value, range) { 12239 return value > range[0]; 12240 }, 12241 '>=': function(value, range) { 12242 return value >= range[0]; 12243 }, 12244 'between': function(value, range) { 12245 return value >= range[0] && value <= range[1]; 12246 }, 12247 'not between': function(value, range) { 12248 return value < range[0] || value > range[1]; 12249 }, 12250 } 12251 12252 var textCriterias = { 12253 'contains': function(value, range) { 12254 return value.includes(range[0]); 12255 }, 12256 'not contains': function(value, range) { 12257 return !value.includes(range[0]); 12258 }, 12259 'begins with': function(value, range) { 12260 return value.startsWith(range[0]); 12261 }, 12262 'ends with': function(value, range) { 12263 return value.endsWith(range[0]); 12264 }, 12265 '=': function(value, range) { 12266 return value === range[0]; 12267 }, 12268 'valid email': function(value) { 12269 var pattern = new RegExp(/^[^\s@]+@[^\s@]+\.[^\s@]+$/); 12270 12271 return pattern.test(value); 12272 }, 12273 'valid url': function(value) { 12274 var pattern = new RegExp(/(((https?:\/\/)|(www\.))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]+)/ig); 12275 12276 return pattern.test(value); 12277 }, 12278 } 12279 12280 // Component router 12281 var component = function(value, options) { 12282 if (typeof(component[options.type]) === 'function') { 12283 if (options.allowBlank && value === '') { 12284 return true; 12285 } 12286 12287 return component[options.type](value, options); 12288 } 12289 return null; 12290 } 12291 12292 component.url = function() { 12293 var pattern = new RegExp(/(((https?:\/\/)|(www\.))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]+)/ig); 12294 return pattern.test(data) ? true : false;
12295 } 12296 12297 component.email = function(data) { 12298 var pattern = new RegExp(/^[^\s@]+@[^\s@]+\.[^\s@]+$/); 12299 return data && pattern.test(data) ? true : false; 12300 } 12301 12302 component.required = function(data) { 12303 return data.trim() ? true : false; 12304 } 12305 12306 component.exist = function(data, options) { 12307 return !!data.toString(); 12308 } 12309 12310 component['not exist'] = function(data, options) { 12311 return !data.toString(); 12312 } 12313 12314 component.empty = function(data) { 12315 return !data.toString(); 12316 } 12317 12318 component.notEmpty = function(data) { 12319 return !!data.toString(); 12320 } 12321 12322 component.number = function(data, options) { 12323 if (! isNumeric(data)) { 12324 return false; 12325 } 12326 12327 if (!options || !options.criteria) { 12328 return true; 12329 } 12330 12331 if (!numberCriterias[options.criteria]) { 12332 return false; 12333 } 12334 12335 var values = options.value.map(function(num) { 12336 return parseFloat(num); 12337 }) 12338 12339 return numberCriterias[options.criteria](data, values); 12340 }; 12341 12342 component.login = function(data) { 12343 var pattern = new RegExp(/^[a-zA-Z0-9\_\-\.\s+]+$/); 12344 return data && pattern.test(data) ? true : false; 12345 } 12346 12347 component.list = function(data, options) { 12348 var dataType = typeof data; 12349 if (dataType !== 'string' && dataType !== 'number') { 12350 return false; 12351 } 12352 if (typeof(options.value[0]) === 'string') { 12353 var list = options.value[0].split(','); 12354 } else { 12355 var list = options.value[0]; 12356 } 12357 12358 var validOption = list.findIndex(function name(item) { 12359 return item == data; 12360 }); 12361 12362 return validOption > -1; 12363 } 12364 12365 component.date = function(data, options) { 12366 if (new Date(data) == 'Invalid Date') { 12367 return false; 12368 } 12369 12370 if (!options || !options.criteria) { 12371 return true; 12372 } 12373 12374 if (!dateCriterias[options.criteria]) { 12375 return false; 12376 } 12377 12378 var values = options.value.map(function(date) { 12379 return new Date(date).getTime(); 12380 }); 12381 12382 return dateCriterias[options.criteria](new Date(data).getTime(), values); 12383 } 12384 12385 component.text = function(data, options) { 12386 if (typeof data !== 'string') { 12387 return false; 12388 } 12389 12390 if (!options || !options.criteria) { 12391 return true; 12392 } 12393 12394 if (!textCriterias[options.criteria]) { 12395 return false; 12396 } 12397 12398 return textCriterias[options.criteria](data, options.value); 12399 } 12400 12401 component.textLength = function(data, options) { 12402 data = data.toString(); 12403 12404 return component.number(data.length, options); 12405 } 12406 12407 return component; 12408})(); 12409 12410 12411 12412 return jSuites; 12413 12414})));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.