Source: node_modules/jsuites/dist/jsuites.js

  1. /**
  2. * (c) jSuites Javascript Web Components (v2.7)
  3. *
  4. * Author: Paul Hodel <paul.hodel@gmail.com>
  5. * Website: https://bossanova.uk/jsuites/
  6. * Description: Create amazing web based applications.
  7. *
  8. * MIT License
  9. *
  10. */
  11. ;(function (global, factory) {
  12. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  13. typeof define === 'function' && define.amd ? define(factory) :
  14. global.jSuites = factory();
  15. }(this, (function () {
  16. 'use strict';
  17. var jSuites = function(options) {
  18. var obj = {}
  19. obj.init = function() {
  20. // Find root element
  21. var app = document.querySelector('.japp');
  22. // Root element
  23. if (app) {
  24. obj.el = app;
  25. } else {
  26. obj.el = document.body;
  27. }
  28. }
  29. obj.guid = function() {
  30. var guid = '';
  31. for (var i = 0; i < 32; i++) {
  32. guid += Math.floor(Math.random()*0xF).toString(0xF);
  33. }
  34. return guid;
  35. }
  36. obj.getWindowWidth = function() {
  37. var w = window,
  38. d = document,
  39. e = d.documentElement,
  40. g = d.getElementsByTagName('body')[0],
  41. x = w.innerWidth || e.clientWidth || g.clientWidth;
  42. return x;
  43. }
  44. obj.getWindowHeight = function() {
  45. var w = window,
  46. d = document,
  47. e = d.documentElement,
  48. g = d.getElementsByTagName('body')[0],
  49. y = w.innerHeight|| e.clientHeight|| g.clientHeight;
  50. return y;
  51. }
  52. obj.getPosition = function(e) {
  53. if (e.changedTouches && e.changedTouches[0]) {
  54. var x = e.changedTouches[0].pageX;
  55. var y = e.changedTouches[0].pageY;
  56. } else {
  57. var x = (window.Event) ? e.pageX : e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
  58. var y = (window.Event) ? e.pageY : e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
  59. }
  60. return [ x, y ];
  61. }
  62. obj.click = function(el) {
  63. if (el.click) {
  64. el.click();
  65. } else {
  66. var evt = new MouseEvent('click', {
  67. bubbles: true,
  68. cancelable: true,
  69. view: window
  70. });
  71. el.dispatchEvent(evt);
  72. }
  73. }
  74. obj.getElement = function(element, className) {
  75. var foundElement = false;
  76. function path (element) {
  77. if (element.className) {
  78. if (element.classList.contains(className)) {
  79. foundElement = element;
  80. }
  81. }
  82. if (element.parentNode) {
  83. path(element.parentNode);
  84. }
  85. }
  86. path(element);
  87. return foundElement;
  88. }
  89. obj.getLinkElement = function(element) {
  90. var targetElement = false;
  91. function path (element) {
  92. if ((element.tagName == 'A' || element.tagName == 'DIV') && element.getAttribute('data-href')) {
  93. targetElement = element;
  94. }
  95. if (element.parentNode) {
  96. path(element.parentNode);
  97. }
  98. }
  99. path(element);
  100. return targetElement;
  101. }
  102. obj.getFormElements = function(formObject) {
  103. var ret = {};
  104. if (formObject) {
  105. var elements = formObject.querySelectorAll("input, select, textarea");
  106. } else {
  107. var elements = document.querySelectorAll("input, select, textarea");
  108. }
  109. for (var i = 0; i < elements.length; i++) {
  110. var element = elements[i];
  111. var name = element.name;
  112. var value = element.value;
  113. if (name) {
  114. ret[name] = value;
  115. }
  116. }
  117. return ret;
  118. }
  119. obj.exists = function(url, __callback) {
  120. var http = new XMLHttpRequest();
  121. http.open('HEAD', url, false);
  122. http.send();
  123. if (http.status) {
  124. __callback(http.status);
  125. }
  126. }
  127. obj.getFiles = function(element) {
  128. if (! element) {
  129. console.error('No element defined in the arguments of your method');
  130. }
  131. // Get attachments
  132. var files = element.querySelectorAll('.jfile');
  133. if (files.length > 0) {
  134. var data = [];
  135. for (var i = 0; i < files.length; i++) {
  136. var file = {};
  137. var src = files[i].getAttribute('src');
  138. if (files[i].classList.contains('jremove')) {
  139. file.remove = 1;
  140. } else {
  141. if (src.substr(0,4) == 'data') {
  142. file.content = src.substr(src.indexOf(',') + 1);
  143. file.extension = files[i].getAttribute('data-extension');
  144. } else {
  145. file.file = src;
  146. file.extension = files[i].getAttribute('data-extension');
  147. if (! file.extension) {
  148. file.extension = src.substr(src.lastIndexOf('.') + 1);
  149. }
  150. if (jSuites.files[file.file]) {
  151. file.content = jSuites.files[file.file];
  152. }
  153. }
  154. // Optional file information
  155. if (files[i].getAttribute('data-name')) {
  156. file.name = files[i].getAttribute('data-name');
  157. }
  158. if (files[i].getAttribute('data-file')) {
  159. file.file = files[i].getAttribute('data-file');
  160. }
  161. if (files[i].getAttribute('data-size')) {
  162. file.size = files[i].getAttribute('data-size');
  163. }
  164. if (files[i].getAttribute('data-date')) {
  165. file.date = files[i].getAttribute('data-date');
  166. }
  167. if (files[i].getAttribute('data-cover')) {
  168. file.cover = files[i].getAttribute('data-cover');
  169. }
  170. }
  171. // TODO SMALL thumbs?
  172. data[i] = file;
  173. }
  174. return data;
  175. }
  176. }
  177. obj.ajax = function(options) {
  178. if (! options.data) {
  179. options.data = {};
  180. }
  181. if (options.type) {
  182. options.method = options.type;
  183. }
  184. if (options.data) {
  185. var data = [];
  186. var keys = Object.keys(options.data);
  187. if (keys.length) {
  188. for (var i = 0; i < keys.length; i++) {
  189. if (typeof(options.data[keys[i]]) == 'object') {
  190. var o = options.data[keys[i]];
  191. for (var j = 0; j < o.length; j++) {
  192. if (typeof(o[j]) == 'string') {
  193. data.push(keys[i] + '[' + j + ']=' + encodeURIComponent(o[j]));
  194. } else {
  195. var prop = Object.keys(o[j]);
  196. for (var z = 0; z < prop.length; z++) {
  197. data.push(keys[i] + '[' + j + '][' + prop[z] + ']=' + encodeURIComponent(o[j][prop[z]]));
  198. }
  199. }
  200. }
  201. } else {
  202. data.push(keys[i] + '=' + encodeURIComponent(options.data[keys[i]]));
  203. }
  204. }
  205. }
  206. if (options.method == 'GET' && data.length > 0) {
  207. if (options.url.indexOf('?') < 0) {
  208. options.url += '?';
  209. }
  210. options.url += data.join('&');
  211. }
  212. }
  213. var httpRequest = new XMLHttpRequest();
  214. httpRequest.open(options.method, options.url, true);
  215. if (options.method == 'POST') {
  216. httpRequest.setRequestHeader('Accept', 'application/json');
  217. httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  218. } else {
  219. if (options.dataType == 'json') {
  220. httpRequest.setRequestHeader('Content-Type', 'text/json');
  221. }
  222. }
  223. // No cache
  224. httpRequest.setRequestHeader('pragma', 'no-cache');
  225. httpRequest.setRequestHeader('cache-control', 'no-cache');
  226. httpRequest.onload = function() {
  227. if (httpRequest.status === 200) {
  228. if (options.dataType == 'json') {
  229. try {
  230. var result = JSON.parse(httpRequest.responseText);
  231. if (options.success && typeof(options.success) == 'function') {
  232. options.success(result);
  233. }
  234. } catch(err) {
  235. if (options.error && typeof(options.error) == 'function') {
  236. options.error(result);
  237. }
  238. }
  239. } else {
  240. var result = httpRequest.responseText;
  241. if (options.success && typeof(options.success) == 'function') {
  242. options.success(result);
  243. }
  244. }
  245. } else {
  246. if (options.error && typeof(options.error) == 'function') {
  247. options.error(httpRequest.responseText);
  248. }
  249. }
  250. // Global complete method
  251. if (obj.ajax.requests && obj.ajax.requests.length) {
  252. // Get index of this request in the container
  253. var index = obj.ajax.requests.indexOf(httpRequest)
  254. // Remove from the ajax requests container
  255. obj.ajax.requests.splice(index, 1);
  256. // Last one?
  257. if (! obj.ajax.requests.length) {
  258. if (options.complete && typeof(options.complete) == 'function') {
  259. options.complete(result);
  260. }
  261. }
  262. }
  263. }
  264. if (data) {
  265. httpRequest.send(data.join('&'));
  266. } else {
  267. httpRequest.send();
  268. }
  269. obj.ajax.requests.push(httpRequest);
  270. return httpRequest;
  271. }
  272. obj.ajax.requests = [];
  273. obj.slideLeft = function(element, direction, done) {
  274. if (direction == true) {
  275. element.classList.add('slide-left-in');
  276. setTimeout(function() {
  277. element.classList.remove('slide-left-in');
  278. if (typeof(done) == 'function') {
  279. done();
  280. }
  281. }, 400);
  282. } else {
  283. element.classList.add('slide-left-out');
  284. setTimeout(function() {
  285. element.classList.remove('slide-left-out');
  286. if (typeof(done) == 'function') {
  287. done();
  288. }
  289. }, 400);
  290. }
  291. }
  292. obj.slideRight = function(element, direction, done) {
  293. if (direction == true) {
  294. element.classList.add('slide-right-in');
  295. setTimeout(function() {
  296. element.classList.remove('slide-right-in');
  297. if (typeof(done) == 'function') {
  298. done();
  299. }
  300. }, 400);
  301. } else {
  302. element.classList.add('slide-right-out');
  303. setTimeout(function() {
  304. element.classList.remove('slide-right-out');
  305. if (typeof(done) == 'function') {
  306. done();
  307. }
  308. }, 400);
  309. }
  310. }
  311. obj.slideTop = function(element, direction, done) {
  312. if (direction == true) {
  313. element.classList.add('slide-top-in');
  314. setTimeout(function() {
  315. element.classList.remove('slide-top-in');
  316. if (typeof(done) == 'function') {
  317. done();
  318. }
  319. }, 400);
  320. } else {
  321. element.classList.add('slide-top-out');
  322. setTimeout(function() {
  323. element.classList.remove('slide-top-out');
  324. if (typeof(done) == 'function') {
  325. done();
  326. }
  327. }, 400);
  328. }
  329. }
  330. obj.slideBottom = function(element, direction, done) {
  331. if (direction == true) {
  332. element.classList.add('slide-bottom-in');
  333. setTimeout(function() {
  334. element.classList.remove('slide-bottom-in');
  335. if (typeof(done) == 'function') {
  336. done();
  337. }
  338. }, 400);
  339. } else {
  340. element.classList.add('slide-bottom-out');
  341. setTimeout(function() {
  342. element.classList.remove('slide-bottom-out');
  343. if (typeof(done) == 'function') {
  344. done();
  345. }
  346. }, 100);
  347. }
  348. }
  349. obj.fadeIn = function(element, done) {
  350. element.classList.add('fade-in');
  351. setTimeout(function() {
  352. element.classList.remove('fade-in');
  353. if (typeof(done) == 'function') {
  354. done();
  355. }
  356. }, 2000);
  357. }
  358. obj.fadeOut = function(element, done) {
  359. element.classList.add('fade-out');
  360. setTimeout(function() {
  361. element.classList.remove('fade-out');
  362. if (typeof(done) == 'function') {
  363. done();
  364. }
  365. }, 1000);
  366. }
  367. obj.keyDownControls = function(e) {
  368. if (e.which == 27) {
  369. var nodes = document.querySelectorAll('.jslider');
  370. if (nodes.length > 0) {
  371. for (var i = 0; i < nodes.length; i++) {
  372. nodes[i].slider.close();
  373. }
  374. }
  375. if (document.querySelector('.jdialog')) {
  376. jSuites.dialog.close();
  377. }
  378. } else if (e.which == 13) {
  379. if (document.querySelector('.jdialog')) {
  380. if (typeof(jSuites.dialog.options.onconfirm) == 'function') {
  381. jSuites.dialog.options.onconfirm();
  382. }
  383. jSuites.dialog.close();
  384. }
  385. }
  386. // Verify mask
  387. if (jSuites.mask) {
  388. jSuites.mask.apply(e);
  389. }
  390. }
  391. var actionUpControl = function(e) {
  392. var element = null;
  393. if (element = jSuites.getLinkElement(e.target)) {
  394. var link = element.getAttribute('data-href');
  395. if (link == '#back') {
  396. window.history.back();
  397. } else if (link == '#panel') {
  398. jSuites.panel();
  399. } else {
  400. jSuites.pages(link);
  401. }
  402. }
  403. }
  404. var controlSwipeLeft = function(e) {
  405. var element = jSuites.getElement(e.target, 'option');
  406. if (element && element.querySelector('.option-actions')) {
  407. element.scrollTo({
  408. left: 100,
  409. behavior: 'smooth'
  410. });
  411. } else {
  412. var element = jSuites.getElement(e.target, 'jcalendar');
  413. if (element && jSuites.calendar.current) {
  414. jSuites.calendar.current.prev();
  415. } else {
  416. if (jSuites.panel) {
  417. var element = jSuites.panel.get();
  418. if (element) {
  419. if (element.style.display != 'none') {
  420. jSuites.panel.close();
  421. }
  422. }
  423. }
  424. }
  425. }
  426. }
  427. var controlSwipeRight = function(e) {
  428. var element = jSuites.getElement(e.target, 'option');
  429. if (element && element.querySelector('.option-actions')) {
  430. element.scrollTo({
  431. left: 0,
  432. behavior: 'smooth'
  433. });
  434. } else {
  435. var element = jSuites.getElement(e.target, 'jcalendar');
  436. if (element && jSuites.calendar.current) {
  437. jSuites.calendar.current.next();
  438. } else {
  439. if (jSuites.panel) {
  440. var element = jSuites.panel.get();
  441. if (element) {
  442. if (element.style.display == 'none') {
  443. jSuites.panel();
  444. }
  445. }
  446. }
  447. }
  448. }
  449. }
  450. var actionOverControl = function(e) {
  451. // Tooltip
  452. if (jSuites.tooltip) {
  453. jSuites.tooltip(e);
  454. }
  455. }
  456. var actionOutControl = function(e) {
  457. // Tooltip
  458. if (jSuites.tooltip) {
  459. jSuites.tooltip.hide();
  460. }
  461. }
  462. // Create page container
  463. document.addEventListener('swipeleft', controlSwipeLeft);
  464. document.addEventListener('swiperight', controlSwipeRight);
  465. document.addEventListener('keydown', obj.keyDownControls);
  466. if ('ontouchend' in document.documentElement === true) {
  467. document.addEventListener('touchend', actionUpControl);
  468. } else {
  469. document.addEventListener('mouseup', actionUpControl);
  470. }
  471. // Onmouseover
  472. document.addEventListener('mouseover', actionOverControl);
  473. document.addEventListener('mouseout', actionOutControl);
  474. document.addEventListener('DOMContentLoaded', function() {
  475. obj.init();
  476. });
  477. // Pop state control
  478. window.onpopstate = function(e) {
  479. if (e.state && e.state.route) {
  480. if (jSuites.pages.get(e.state.route)) {
  481. jSuites.pages(e.state.route, { ignoreHistory:true });
  482. }
  483. }
  484. }
  485. return obj;
  486. }();
  487. jSuites.files = [];
  488. jSuites.calendar = (function(el, options) {
  489. var obj = {};
  490. obj.options = {};
  491. // Global container
  492. if (! jSuites.calendar.current) {
  493. jSuites.calendar.current = null;
  494. }
  495. // Default configuration
  496. var defaults = {
  497. // Date format
  498. format: 'DD/MM/YYYY',
  499. // Allow keyboard date entry
  500. readonly: true,
  501. // Today is default
  502. today: false,
  503. // Show timepicker
  504. time: false,
  505. // Show the reset button
  506. resetButton: true,
  507. // Placeholder
  508. placeholder: '',
  509. // Translations can be done here
  510. months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  511. weekdays: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
  512. weekdays_short: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
  513. // Value
  514. value: null,
  515. // Events
  516. onclose: null,
  517. onchange: null,
  518. // Fullscreen (this is automatic set for screensize < 800)
  519. fullscreen: false,
  520. // Internal mode controller
  521. mode: null,
  522. position: null,
  523. // Create the calendar closed as default
  524. opened: false,
  525. };
  526. // Loop through our object
  527. for (var property in defaults) {
  528. if (options && options.hasOwnProperty(property)) {
  529. obj.options[property] = options[property];
  530. } else {
  531. obj.options[property] = defaults[property];
  532. }
  533. }
  534. // Value
  535. if (! obj.options.value && el.value) {
  536. obj.options.value = el.value;
  537. }
  538. // Make sure use upper case in the format
  539. obj.options.format = obj.options.format.toUpperCase();
  540. if (obj.options.value) {
  541. var date = obj.options.value.split(' ');
  542. var time = date[1];
  543. var date = date[0].split('-');
  544. var y = parseInt(date[0]);
  545. var m = parseInt(date[1]);
  546. var d = parseInt(date[2]);
  547. if (time) {
  548. var time = time.split(':');
  549. var h = parseInt(time[0]);
  550. var i = parseInt(time[1]);
  551. } else {
  552. var h = 0;
  553. var i = 0;
  554. }
  555. } else {
  556. var date = new Date();
  557. var y = date.getFullYear();
  558. var m = date.getMonth() + 1;
  559. var d = date.getDate();
  560. var h = date.getHours();
  561. var i = date.getMinutes();
  562. }
  563. // Current value
  564. obj.date = [ y, m, d, h, i, 0 ];
  565. // Two digits
  566. var two = function(value) {
  567. value = '' + value;
  568. if (value.length == 1) {
  569. value = '0' + value;
  570. }
  571. return value;
  572. }
  573. // Element
  574. el.classList.add('jcalendar-input');
  575. // Calendar elements
  576. var calendarReset = document.createElement('div');
  577. calendarReset.className = 'jcalendar-reset';
  578. calendarReset.innerHTML = 'Reset';
  579. var calendarConfirm = document.createElement('div');
  580. calendarConfirm.className = 'jcalendar-confirm';
  581. calendarConfirm.innerHTML = 'Done';
  582. var calendarControls = document.createElement('div');
  583. calendarControls.className = 'jcalendar-controls'
  584. if (obj.options.resetButton) {
  585. calendarControls.appendChild(calendarReset);
  586. }
  587. calendarControls.appendChild(calendarConfirm);
  588. var calendarContainer = document.createElement('div');
  589. calendarContainer.className = 'jcalendar-container';
  590. var calendarContent = document.createElement('div');
  591. calendarContent.className = 'jcalendar-content';
  592. calendarContent.appendChild(calendarControls);
  593. calendarContainer.appendChild(calendarContent);
  594. // Main element
  595. var calendar = document.createElement('div');
  596. calendar.className = 'jcalendar';
  597. calendar.appendChild(calendarContainer);
  598. // Previous button
  599. var calendarHeaderPrev = document.createElement('td');
  600. calendarHeaderPrev.setAttribute('colspan', '2');
  601. calendarHeaderPrev.className = 'jcalendar-prev';
  602. // Header with year and month
  603. var calendarLabelYear = document.createElement('span');
  604. calendarLabelYear.className = 'jcalendar-year';
  605. var calendarLabelMonth = document.createElement('span');
  606. calendarLabelMonth.className = 'jcalendar-month';
  607. var calendarHeaderTitle = document.createElement('td');
  608. calendarHeaderTitle.className = 'jcalendar-header';
  609. calendarHeaderTitle.setAttribute('colspan', '3');
  610. calendarHeaderTitle.appendChild(calendarLabelMonth);
  611. calendarHeaderTitle.appendChild(calendarLabelYear);
  612. var calendarHeaderNext = document.createElement('td');
  613. calendarHeaderNext.setAttribute('colspan', '2');
  614. calendarHeaderNext.className = 'jcalendar-next';
  615. var calendarHeaderRow = document.createElement('tr');
  616. calendarHeaderRow.appendChild(calendarHeaderPrev);
  617. calendarHeaderRow.appendChild(calendarHeaderTitle);
  618. calendarHeaderRow.appendChild(calendarHeaderNext);
  619. var calendarHeader = document.createElement('thead');
  620. calendarHeader.appendChild(calendarHeaderRow);
  621. var calendarBody = document.createElement('tbody');
  622. var calendarFooter = document.createElement('tfoot');
  623. // Calendar table
  624. var calendarTable = document.createElement('table');
  625. calendarTable.setAttribute('cellpadding', '0');
  626. calendarTable.setAttribute('cellspacing', '0');
  627. calendarTable.appendChild(calendarHeader);
  628. calendarTable.appendChild(calendarBody);
  629. calendarTable.appendChild(calendarFooter);
  630. calendarContent.appendChild(calendarTable);
  631. var calendarSelectHour = document.createElement('select');
  632. calendarSelectHour.className = 'jcalendar-select';
  633. calendarSelectHour.onchange = function() {
  634. obj.date[3] = this.value;
  635. }
  636. for (var i = 0; i < 24; i++) {
  637. var element = document.createElement('option');
  638. element.value = i;
  639. element.innerHTML = two(i);
  640. calendarSelectHour.appendChild(element);
  641. }
  642. var calendarSelectMin = document.createElement('select');
  643. calendarSelectMin.className = 'jcalendar-select';
  644. calendarSelectMin.onchange = function() {
  645. obj.date[4] = this.value;
  646. }
  647. for (var i = 0; i < 60; i++) {
  648. var element = document.createElement('option');
  649. element.value = i;
  650. element.innerHTML = two(i);
  651. calendarSelectMin.appendChild(element);
  652. }
  653. // Footer controls
  654. var calendarControls = document.createElement('div');
  655. calendarControls.className = 'jcalendar-controls';
  656. var calendarControlsTime = document.createElement('div');
  657. calendarControlsTime.className = 'jcalendar-time';
  658. calendarControlsTime.style.maxWidth = '140px';
  659. calendarControlsTime.appendChild(calendarSelectHour);
  660. calendarControlsTime.appendChild(calendarSelectMin);
  661. var calendarControlsUpdate = document.createElement('div');
  662. calendarControlsUpdate.style.flexGrow = '10';
  663. calendarControlsUpdate.innerHTML = '<input type="button" class="jcalendar-update" value="Update">'
  664. calendarControls.appendChild(calendarControlsTime);
  665. calendarControls.appendChild(calendarControlsUpdate);
  666. calendarContent.appendChild(calendarControls);
  667. var calendarBackdrop = document.createElement('div');
  668. calendarBackdrop.className = 'jcalendar-backdrop';
  669. calendar.appendChild(calendarBackdrop);
  670. // Methods
  671. obj.open = function (value) {
  672. if (! calendar.classList.contains('jcalendar-focus')) {
  673. if (jSuites.calendar.current) {
  674. jSuites.calendar.current.close();
  675. }
  676. // Current
  677. jSuites.calendar.current = obj;
  678. // Show calendar
  679. calendar.classList.add('jcalendar-focus');
  680. // Get days
  681. obj.getDays();
  682. // Hour
  683. if (obj.options.time) {
  684. calendarSelectHour.value = obj.date[3];
  685. calendarSelectMin.value = obj.date[4];
  686. }
  687. // Get the position of the corner helper
  688. if (jSuites.getWindowWidth() < 800 || obj.options.fullscreen) {
  689. // Full
  690. calendar.classList.add('jcalendar-fullsize');
  691. // Animation
  692. jSuites.slideBottom(calendarContent, 1);
  693. } else {
  694. const rect = el.getBoundingClientRect();
  695. const rectContent = calendarContent.getBoundingClientRect();
  696. if (obj.options.position) {
  697. calendarContainer.style.position = 'fixed';
  698. if (window.innerHeight < rect.bottom + rectContent.height) {
  699. calendarContainer.style.top = (rect.top - (rectContent.height + 2)) + 'px';
  700. } else {
  701. calendarContainer.style.top = (rect.top + rect.height + 2) + 'px';
  702. }
  703. calendarContainer.style.left = rect.left + 'px';
  704. } else {
  705. if (window.innerHeight < rect.bottom + rectContent.height) {
  706. calendarContainer.style.bottom = (1 * rect.height + rectContent.height + 2) + 'px';
  707. } else {
  708. calendarContainer.style.top = 2 + 'px';
  709. }
  710. }
  711. }
  712. }
  713. }
  714. obj.close = function (ignoreEvents, update) {
  715. // Current
  716. jSuites.calendar.current = null;
  717. if (update != false && el.tagName == 'INPUT') {
  718. obj.setValue(obj.getValue());
  719. }
  720. // Animation
  721. if (! ignoreEvents && typeof(obj.options.onclose) == 'function') {
  722. obj.options.onclose(el);
  723. }
  724. // Hide
  725. calendar.classList.remove('jcalendar-focus');
  726. return obj.getValue();
  727. }
  728. obj.prev = function() {
  729. // Check if the visualization is the days picker or years picker
  730. if (obj.options.mode == 'years') {
  731. obj.date[0] = obj.date[0] - 12;
  732. // Update picker table of days
  733. obj.getYears();
  734. } else {
  735. // Go to the previous month
  736. if (obj.date[1] < 2) {
  737. obj.date[0] = obj.date[0] - 1;
  738. obj.date[1] = 12;
  739. } else {
  740. obj.date[1] = obj.date[1] - 1;
  741. }
  742. // Update picker table of days
  743. obj.getDays();
  744. }
  745. }
  746. obj.next = function() {
  747. // Check if the visualization is the days picker or years picker
  748. if (obj.options.mode == 'years') {
  749. obj.date[0] = parseInt(obj.date[0]) + 12;
  750. // Update picker table of days
  751. obj.getYears();
  752. } else {
  753. // Go to the previous month
  754. if (obj.date[1] > 11) {
  755. obj.date[0] = obj.date[0] + 1;
  756. obj.date[1] = 1;
  757. } else {
  758. obj.date[1] = obj.date[1] + 1;
  759. }
  760. // Update picker table of days
  761. obj.getDays();
  762. }
  763. }
  764. obj.setValue = function(val) {
  765. if (val) {
  766. // Keep value
  767. obj.options.value = val;
  768. // Set label
  769. var value = obj.setLabel(val, obj.options.format);
  770. var date = obj.options.value.split(' ');
  771. if (! date[1]) {
  772. date[1] = '00:00:00';
  773. }
  774. var time = date[1].split(':')
  775. var date = date[0].split('-');
  776. var y = parseInt(date[0]);
  777. var m = parseInt(date[1]);
  778. var d = parseInt(date[2]);
  779. var h = parseInt(time[0]);
  780. var i = parseInt(time[1]);
  781. obj.date = [ y, m, d, h, i, 0 ];
  782. var val = obj.setLabel(val, obj.options.format);
  783. if (el.value != val) {
  784. el.value = val;
  785. // On change
  786. if (typeof(obj.options.onchange) == 'function') {
  787. obj.options.onchange(el, val, obj.date);
  788. }
  789. }
  790. obj.getDays();
  791. }
  792. }
  793. obj.getValue = function() {
  794. if (obj.date) {
  795. if (obj.options.time) {
  796. return two(obj.date[0]) + '-' + two(obj.date[1]) + '-' + two(obj.date[2]) + ' ' + two(obj.date[3]) + ':' + two(obj.date[4]) + ':' + two(0);
  797. } else {
  798. return two(obj.date[0]) + '-' + two(obj.date[1]) + '-' + two(obj.date[2]) + ' ' + two(0) + ':' + two(0) + ':' + two(0);
  799. }
  800. } else {
  801. return "";
  802. }
  803. }
  804. /**
  805. * Update calendar
  806. */
  807. obj.update = function(element) {
  808. obj.date[2] = element.innerText;
  809. if (! obj.options.time) {
  810. obj.close();
  811. } else {
  812. obj.date[3] = calendarSelectHour.value;
  813. obj.date[4] = calendarSelectMin.value;
  814. }
  815. var elements = calendar.querySelector('.jcalendar-selected');
  816. if (elements) {
  817. elements.classList.remove('jcalendar-selected');
  818. }
  819. element.classList.add('jcalendar-selected')
  820. }
  821. /**
  822. * Set to blank
  823. */
  824. obj.reset = function() {
  825. // Clear element
  826. obj.date = null;
  827. // Reset element
  828. el.value = '';
  829. // Close calendar
  830. obj.close();
  831. }
  832. /**
  833. * Get calendar days
  834. */
  835. obj.getDays = function() {
  836. // Mode
  837. obj.options.mode = 'days';
  838. // Variables
  839. var d = 0;
  840. var today = 0;
  841. var today_d = 0;
  842. var calendar_day;
  843. // Setting current values in case of NULLs
  844. var date = new Date();
  845. var year = obj.date && obj.date[0] ? obj.date[0] : parseInt(date.getFullYear());
  846. var month = obj.date && obj.date[1] ? obj.date[1] : parseInt(date.getMonth()) + 1;
  847. var day = obj.date && obj.date[2] ? obj.date[2] : parseInt(date.getDay());
  848. var hour = obj.date && obj.date[3] ? obj.date[3] : parseInt(date.getHours());
  849. var min = obj.date && obj.date[4] ? obj.date[4] : parseInt(date.getMinutes());
  850. obj.date = [year, month, day, hour, min, 0 ];
  851. // Update title
  852. calendarLabelYear.innerHTML = year;
  853. calendarLabelMonth.innerHTML = obj.options.months[month - 1];
  854. // Flag if this is the current month and year
  855. if ((date.getMonth() == month-1) && (date.getFullYear() == year)) {
  856. today = 1;
  857. today_d = date.getDate();
  858. }
  859. var date = new Date(year, month, 0, 0, 0);
  860. var nd = date.getDate();
  861. var date = new Date(year, month-1, 0, hour, min);
  862. var fd = date.getDay() + 1;
  863. // Reset table
  864. calendarBody.innerHTML = '';
  865. // Weekdays Row
  866. var row = document.createElement('tr');
  867. row.setAttribute('align', 'center');
  868. calendarBody.appendChild(row);
  869. for (var i = 0; i < 7; i++) {
  870. var cell = document.createElement('td');
  871. cell.setAttribute('width', '30');
  872. cell.classList.add('jcalendar-weekday')
  873. cell.innerHTML = obj.options.weekdays_short[i];
  874. row.appendChild(cell);
  875. }
  876. // Avoid a blank line
  877. if (fd == 7) {
  878. var j = 7;
  879. } else {
  880. var j = 0;
  881. }
  882. // Days inside the table
  883. var row = document.createElement('tr');
  884. row.setAttribute('align', 'center');
  885. calendarBody.appendChild(row);
  886. // Days in the month
  887. for (var i = j; i < (Math.ceil((nd + fd) / 7) * 7); i++) {
  888. // Create row
  889. if ((i > 0) && (!(i % 7))) {
  890. var row = document.createElement('tr');
  891. row.setAttribute('align', 'center');
  892. calendarBody.appendChild(row);
  893. }
  894. if ((i >= fd) && (i < nd + fd)) {
  895. d += 1;
  896. } else {
  897. d = 0;
  898. }
  899. // Create cell
  900. var cell = document.createElement('td');
  901. cell.setAttribute('width', '30');
  902. cell.classList.add('jcalendar-set-day');
  903. row.appendChild(cell);
  904. if (d == 0) {
  905. cell.innerHTML = '';
  906. } else {
  907. if (d < 10) {
  908. cell.innerHTML = 0 + d;
  909. } else {
  910. cell.innerHTML = d;
  911. }
  912. }
  913. // Selected
  914. if (d && d == day) {
  915. cell.classList.add('jcalendar-selected');
  916. }
  917. // Sundays
  918. if (! (i % 7)) {
  919. cell.style.color = 'red';
  920. }
  921. // Today
  922. if ((today == 1) && (today_d == d)) {
  923. cell.style.fontWeight = 'bold';
  924. }
  925. }
  926. // Show time controls
  927. if (obj.options.time) {
  928. calendarControlsTime.style.display = '';
  929. } else {
  930. calendarControlsTime.style.display = 'none';
  931. }
  932. }
  933. obj.getMonths = function() {
  934. // Mode
  935. obj.options.mode = 'months';
  936. // Loading month labels
  937. var months = obj.options.months;
  938. // Update title
  939. calendarLabelYear.innerHTML = obj.date[0];
  940. calendarLabelMonth.innerHTML = '';
  941. // Create months table
  942. var html = '<td colspan="7"><table width="100%"><tr align="center">';
  943. for (i = 0; i < 12; i++) {
  944. if ((i > 0) && (!(i % 4))) {
  945. html += '</tr><tr align="center">';
  946. }
  947. var month = parseInt(i) + 1;
  948. html += '<td class="jcalendar-set-month" data-value="' + month + '">' + months[i] +'</td>';
  949. }
  950. html += '</tr></table></td>';
  951. calendarBody.innerHTML = html;
  952. }
  953. obj.getYears = function() {
  954. // Mode
  955. obj.options.mode = 'years';
  956. // Array of years
  957. var y = [];
  958. for (i = 0; i < 25; i++) {
  959. y[i] = parseInt(obj.date[0]) + (i - 12);
  960. }
  961. // Assembling the year tables
  962. var html = '<td colspan="7"><table width="100%"><tr align="center">';
  963. for (i = 0; i < 25; i++) {
  964. if ((i > 0) && (!(i % 5))) {
  965. html += '</tr><tr align="center">';
  966. }
  967. html += '<td class="jcalendar-set-year">'+ y[i] +'</td>';
  968. }
  969. html += '</tr></table></td>';
  970. calendarBody.innerHTML = html;
  971. }
  972. obj.setLabel = function(value, format) {
  973. return jSuites.calendar.getDateString(value, format);
  974. }
  975. obj.fromFormatted = function (value, format) {
  976. return jSuites.calendar.extractDateFromString(value, format);
  977. }
  978. // Add properties
  979. el.setAttribute('autocomplete', 'off');
  980. el.setAttribute('data-mask', obj.options.format.toLowerCase());
  981. if (obj.options.readonly) {
  982. el.setAttribute('readonly', 'readonly');
  983. }
  984. if (obj.options.placeholder) {
  985. el.setAttribute('placeholder', obj.options.placeholder);
  986. }
  987. var mouseUpControls = function(e) {
  988. var action = e.target.className;
  989. // Object id
  990. if (action == 'jcalendar-prev') {
  991. obj.prev();
  992. e.stopPropagation();
  993. e.preventDefault();
  994. } else if (action == 'jcalendar-next') {
  995. obj.next();
  996. e.stopPropagation();
  997. e.preventDefault();
  998. } else if (action == 'jcalendar-month') {
  999. obj.getMonths();
  1000. e.stopPropagation();
  1001. e.preventDefault();
  1002. } else if (action == 'jcalendar-year') {
  1003. obj.getYears();
  1004. e.stopPropagation();
  1005. e.preventDefault();
  1006. } else if (action == 'jcalendar-set-year') {
  1007. obj.date[0] = e.target.innerText;
  1008. obj.getDays();
  1009. e.stopPropagation();
  1010. e.preventDefault();
  1011. } else if (action == 'jcalendar-set-month') {
  1012. obj.date[1] = parseInt(e.target.getAttribute('data-value'));
  1013. obj.getDays();
  1014. e.stopPropagation();
  1015. e.preventDefault();
  1016. } else if (action == 'jcalendar-confirm' || action == 'jcalendar-update') {
  1017. obj.close();
  1018. e.stopPropagation();
  1019. e.preventDefault();
  1020. } else if (action == 'jcalendar-close') {
  1021. obj.close();
  1022. e.stopPropagation();
  1023. e.preventDefault();
  1024. } else if (action == 'jcalendar-backdrop') {
  1025. obj.close(false, false);
  1026. e.stopPropagation();
  1027. e.preventDefault();
  1028. } else if (action == 'jcalendar-reset') {
  1029. obj.reset();
  1030. e.stopPropagation();
  1031. e.preventDefault();
  1032. } else if (e.target.classList.contains('jcalendar-set-day')) {
  1033. if (e.target.innerText) {
  1034. obj.update(e.target);
  1035. e.stopPropagation();
  1036. e.preventDefault();
  1037. }
  1038. }
  1039. }
  1040. var keyUpControls = function(e) {
  1041. if (e.target.value && e.target.value.length > 3) {
  1042. var test = jSuites.calendar.extractDateFromString(e.target.value, obj.options.format);
  1043. if (test) {
  1044. if (e.target.getAttribute('data-completed') == 'true') {
  1045. obj.setValue(test);
  1046. }
  1047. }
  1048. }
  1049. }
  1050. var verifyControls = function(e) {
  1051. console.log(e.target.className)
  1052. }
  1053. // Handle events
  1054. el.addEventListener("keyup", keyUpControls);
  1055. // Add global events
  1056. calendar.addEventListener("swipeleft", function(e) {
  1057. jSuites.slideLeft(calendarTable, 0, function() {
  1058. obj.next();
  1059. jSuites.slideRight(calendarTable, 1);
  1060. });
  1061. e.preventDefault();
  1062. e.stopPropagation();
  1063. });
  1064. calendar.addEventListener("swiperight", function(e) {
  1065. jSuites.slideRight(calendarTable, 0, function() {
  1066. obj.prev();
  1067. jSuites.slideLeft(calendarTable, 1);
  1068. });
  1069. e.preventDefault();
  1070. e.stopPropagation();
  1071. });
  1072. if ('ontouchend' in document.documentElement === true) {
  1073. calendar.addEventListener("touchend", mouseUpControls);
  1074. el.addEventListener("touchend", function(e) {
  1075. obj.open();
  1076. });
  1077. } else {
  1078. calendar.addEventListener("mouseup", mouseUpControls);
  1079. el.addEventListener("mouseup", function(e) {
  1080. obj.open();
  1081. });
  1082. }
  1083. // Append element to the DOM
  1084. el.parentNode.insertBefore(calendar, el.nextSibling);
  1085. // Keep object available from the node
  1086. el.calendar = obj;
  1087. if (obj.options.opened == true) {
  1088. obj.open();
  1089. }
  1090. return obj;
  1091. });
  1092. jSuites.calendar.prettify = function(d, texts) {
  1093. if (! texts) {
  1094. var texts = {
  1095. justNow: 'Just now',
  1096. xMinutesAgo: '{0}m ago',
  1097. xHoursAgo: '{0}h ago',
  1098. xDaysAgo: '{0}d ago',
  1099. xWeeksAgo: '{0}w ago',
  1100. xMonthsAgo: '{0} mon ago',
  1101. xYearsAgo: '{0}y ago',
  1102. }
  1103. }
  1104. var d1 = new Date();
  1105. var d2 = new Date(d);
  1106. var total = parseInt((d1 - d2) / 1000 / 60);
  1107. String.prototype.format = function(o) {
  1108. return this.replace('{0}', o);
  1109. }
  1110. if (total == 0) {
  1111. var text = texts.justNow;
  1112. } else if (total < 90) {
  1113. var text = texts.xMinutesAgo.format(total);
  1114. } else if (total < 1440) { // One day
  1115. var text = texts.xHoursAgo.format(Math.round(total/60));
  1116. } else if (total < 20160) { // 14 days
  1117. var text = texts.xDaysAgo.format(Math.round(total / 1440));
  1118. } else if (total < 43200) { // 30 days
  1119. var text = texts.xWeeksAgo.format(Math.round(total / 10080));
  1120. } else if (total < 1036800) { // 24 months
  1121. var text = texts.xMonthsAgo.format(Math.round(total / 43200));
  1122. } else { // 24 months+
  1123. var text = texts.xYearsAgo.format(Math.round(total / 525600));
  1124. }
  1125. return text;
  1126. }
  1127. jSuites.calendar.prettifyAll = function() {
  1128. var elements = document.querySelectorAll('.prettydate');
  1129. for (var i = 0; i < elements.length; i++) {
  1130. if (elements[i].getAttribute('data-date')) {
  1131. elements[i].innerHTML = jSuites.calendar.prettify(elements[i].getAttribute('data-date'));
  1132. } else {
  1133. elements[i].setAttribute('data-date', elements[i].innerHTML);
  1134. elements[i].innerHTML = jSuites.calendar.prettify(elements[i].innerHTML);
  1135. }
  1136. }
  1137. }
  1138. jSuites.calendar.now = function() {
  1139. var date = new Date();
  1140. var y = date.getFullYear();
  1141. var m = date.getMonth() + 1;
  1142. var d = date.getDate();
  1143. var h = date.getHours();
  1144. var i = date.getMinutes();
  1145. var s = date.getSeconds();
  1146. // Two digits
  1147. var two = function(value) {
  1148. value = '' + value;
  1149. if (value.length == 1) {
  1150. value = '0' + value;
  1151. }
  1152. return value;
  1153. }
  1154. return two(y) + '-' + two(m) + '-' + two(d) + ' ' + two(h) + ':' + two(i) + ':' + two(s);
  1155. }
  1156. // Helper to extract date from a string
  1157. jSuites.calendar.extractDateFromString = function(date, format) {
  1158. var v1 = '' + date;
  1159. var v2 = format.replace(/[0-9]/g,'');
  1160. var test = 1;
  1161. // Get year
  1162. var y = v2.search("YYYY");
  1163. y = v1.substr(y,4);
  1164. if (parseInt(y) != y) {
  1165. test = 0;
  1166. }
  1167. // Get month
  1168. var m = v2.search("MM");
  1169. m = v1.substr(m,2);
  1170. if (parseInt(m) != m || d > 12) {
  1171. test = 0;
  1172. }
  1173. // Get day
  1174. var d = v2.search("DD");
  1175. d = v1.substr(d,2);
  1176. if (parseInt(d) != d || d > 31) {
  1177. test = 0;
  1178. }
  1179. // Get hour
  1180. var h = v2.search("HH");
  1181. if (h >= 0) {
  1182. h = v1.substr(h,2);
  1183. if (! parseInt(h) || h > 23) {
  1184. h = '00';
  1185. }
  1186. } else {
  1187. h = '00';
  1188. }
  1189. // Get minutes
  1190. var i = v2.search("MI");
  1191. if (i >= 0) {
  1192. i = v1.substr(i,2);
  1193. if (! parseInt(i) || i > 59) {
  1194. i = '00';
  1195. }
  1196. } else {
  1197. i = '00';
  1198. }
  1199. // Get seconds
  1200. var s = v2.search("SS");
  1201. if (s >= 0) {
  1202. s = v1.substr(s,2);
  1203. if (! parseInt(s) || s > 59) {
  1204. s = '00';
  1205. }
  1206. } else {
  1207. s = '00';
  1208. }
  1209. if (test == 1 && date.length == v2.length) {
  1210. // Update source
  1211. var data = y + '-' + m + '-' + d + ' ' + h + ':' + i + ':' + s;
  1212. return data;
  1213. }
  1214. return '';
  1215. }
  1216. // Helper to convert date into string
  1217. jSuites.calendar.getDateString = function(value, format) {
  1218. // Default calendar
  1219. if (! format) {
  1220. var format = 'DD/MM/YYYY';
  1221. }
  1222. if (value) {
  1223. var d = ''+value;
  1224. d = d.split(' ');
  1225. var h = '';
  1226. var m = '';
  1227. var s = '';
  1228. if (d[1]) {
  1229. h = d[1].split(':');
  1230. m = h[1] ? h[1] : '00';
  1231. s = h[2] ? h[2] : '00';
  1232. h = h[0] ? h[0] : '00';
  1233. } else {
  1234. h = '00';
  1235. m = '00';
  1236. s = '00';
  1237. }
  1238. d = d[0].split('-');
  1239. if (d[0] && d[1] && d[2] && d[0] > 0 && d[1] > 0 && d[1] < 13 && d[2] > 0 && d[2] < 32) {
  1240. var calendar = new Date(d[0], d[1]-1, d[2]);
  1241. var weekday = new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
  1242. var months = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
  1243. d[1] = (d[1].length < 2 ? '0' : '') + d[1];
  1244. d[2] = (d[2].length < 2 ? '0' : '') + d[2];
  1245. h = (h.length < 2 ? '0' : '') + h;
  1246. m = (m.length < 2 ? '0' : '') + m;
  1247. s = (s.length < 2 ? '0' : '') + s;
  1248. value = format;
  1249. value = value.replace('WD', weekday[calendar.getDay()]);
  1250. value = value.replace('DD', d[2]);
  1251. value = value.replace('MM', d[1]);
  1252. value = value.replace('YYYY', d[0]);
  1253. value = value.replace('YY', d[0].substring(2,4));
  1254. value = value.replace('MON', months[parseInt(d[1])-1].toUpperCase());
  1255. if (h) {
  1256. value = value.replace('HH24', h);
  1257. }
  1258. if (h > 12) {
  1259. value = value.replace('HH12', h - 12);
  1260. value = value.replace('HH', h);
  1261. } else {
  1262. value = value.replace('HH12', h);
  1263. value = value.replace('HH', h);
  1264. }
  1265. value = value.replace('MI', m);
  1266. value = value.replace('MM', m);
  1267. value = value.replace('SS', s);
  1268. } else {
  1269. value = '';
  1270. }
  1271. }
  1272. return value;
  1273. }
  1274. jSuites.calendar.isOpen = function(e) {
  1275. if (jSuites.calendar.current) {
  1276. if (! e.target.className || e.target.className.indexOf('jcalendar') == -1) {
  1277. jSuites.calendar.current.close();
  1278. }
  1279. }
  1280. }
  1281. if ('ontouchstart' in document.documentElement === true) {
  1282. document.addEventListener("touchstart", jSuites.calendar.isOpen);
  1283. } else {
  1284. document.addEventListener("mousedown", jSuites.calendar.isOpen);
  1285. }
  1286. jSuites.color = (function(el, options) {
  1287. var obj = {};
  1288. obj.options = {};
  1289. obj.values = [];
  1290. // Global container
  1291. if (! jSuites.color.current) {
  1292. jSuites.color.current = null;
  1293. }
  1294. /**
  1295. * @typedef {Object} defaults
  1296. * @property {(string|Array)} value - Initial value of the compontent
  1297. * @property {string} placeholder - The default instruction text on the element
  1298. * @property {requestCallback} onchange - Method to be execute after any changes on the element
  1299. * @property {requestCallback} onclose - Method to be execute when the element is closed
  1300. */
  1301. var defaults = {
  1302. placeholder: '',
  1303. value: null,
  1304. onclose: null,
  1305. onchange: null,
  1306. };
  1307. // Loop through our object
  1308. for (var property in defaults) {
  1309. if (options && options.hasOwnProperty(property)) {
  1310. obj.options[property] = options[property];
  1311. } else {
  1312. obj.options[property] = defaults[property];
  1313. }
  1314. }
  1315. var palette = {
  1316. "red": {
  1317. "50": "#ffebee",
  1318. "100": "#ffcdd2",
  1319. "200": "#ef9a9a",
  1320. "300": "#e57373",
  1321. "400": "#ef5350",
  1322. "500": "#f44336",
  1323. "600": "#e53935",
  1324. "700": "#d32f2f",
  1325. "800": "#c62828",
  1326. "900": "#b71c1c",
  1327. },
  1328. "pink": {
  1329. "50": "#fce4ec",
  1330. "100": "#f8bbd0",
  1331. "200": "#f48fb1",
  1332. "300": "#f06292",
  1333. "400": "#ec407a",
  1334. "500": "#e91e63",
  1335. "600": "#d81b60",
  1336. "700": "#c2185b",
  1337. "800": "#ad1457",
  1338. "900": "#880e4f",
  1339. },
  1340. "purple": {
  1341. "50": "#f3e5f5",
  1342. "100": "#e1bee7",
  1343. "200": "#ce93d8",
  1344. "300": "#ba68c8",
  1345. "400": "#ab47bc",
  1346. "500": "#9c27b0",
  1347. "600": "#8e24aa",
  1348. "700": "#7b1fa2",
  1349. "800": "#6a1b9a",
  1350. "900": "#4a148c",
  1351. },
  1352. "indigo": {
  1353. "50": "#e8eaf6",
  1354. "100": "#c5cae9",
  1355. "200": "#9fa8da",
  1356. "300": "#7986cb",
  1357. "400": "#5c6bc0",
  1358. "500": "#3f51b5",
  1359. "600": "#3949ab",
  1360. "700": "#303f9f",
  1361. "800": "#283593",
  1362. "900": "#1a237e",
  1363. },
  1364. "blue": {
  1365. "50": "#e3f2fd",
  1366. "100": "#bbdefb",
  1367. "200": "#90caf9",
  1368. "300": "#64b5f6",
  1369. "400": "#42a5f5",
  1370. "500": "#2196f3",
  1371. "600": "#1e88e5",
  1372. "700": "#1976d2",
  1373. "800": "#1565c0",
  1374. "900": "#0d47a1",
  1375. },
  1376. "cyan": {
  1377. "50": "#e0f7fa",
  1378. "100": "#b2ebf2",
  1379. "200": "#80deea",
  1380. "300": "#4dd0e1",
  1381. "400": "#26c6da",
  1382. "500": "#00bcd4",
  1383. "600": "#00acc1",
  1384. "700": "#0097a7",
  1385. "800": "#00838f",
  1386. "900": "#006064",
  1387. },
  1388. "teal": {
  1389. "50": "#e0f2f1",
  1390. "100": "#b2dfdb",
  1391. "200": "#80cbc4",
  1392. "300": "#4db6ac",
  1393. "400": "#26a69a",
  1394. "500": "#009688",
  1395. "600": "#00897b",
  1396. "700": "#00796b",
  1397. "800": "#00695c",
  1398. "900": "#004d40",
  1399. },
  1400. "green": {
  1401. "50": "#e8f5e9",
  1402. "100": "#c8e6c9",
  1403. "200": "#a5d6a7",
  1404. "300": "#81c784",
  1405. "400": "#66bb6a",
  1406. "500": "#4caf50",
  1407. "600": "#43a047",
  1408. "700": "#388e3c",
  1409. "800": "#2e7d32",
  1410. "900": "#1b5e20",
  1411. },
  1412. "lightgreen": {
  1413. "50": "#f1f8e9",
  1414. "100": "#dcedc8",
  1415. "200": "#c5e1a5",
  1416. "300": "#aed581",
  1417. "400": "#9ccc65",
  1418. "500": "#8bc34a",
  1419. "600": "#7cb342",
  1420. "700": "#689f38",
  1421. "800": "#558b2f",
  1422. "900": "#33691e",
  1423. },
  1424. "lime": {
  1425. "50": "#f9fbe7",
  1426. "100": "#f0f4c3",
  1427. "200": "#e6ee9c",
  1428. "300": "#dce775",
  1429. "400": "#d4e157",
  1430. "500": "#cddc39",
  1431. "600": "#c0ca33",
  1432. "700": "#afb42b",
  1433. "800": "#9e9d24",
  1434. "900": "#827717",
  1435. },
  1436. "yellow": {
  1437. "50": "#fffde7",
  1438. "100": "#fff9c4",
  1439. "200": "#fff59d",
  1440. "300": "#fff176",
  1441. "400": "#ffee58",
  1442. "500": "#ffeb3b",
  1443. "600": "#fdd835",
  1444. "700": "#fbc02d",
  1445. "800": "#f9a825",
  1446. "900": "#f57f17",
  1447. },
  1448. "amber": {
  1449. "50": "#fff8e1",
  1450. "100": "#ffecb3",
  1451. "200": "#ffe082",
  1452. "300": "#ffd54f",
  1453. "400": "#ffca28",
  1454. "500": "#ffc107",
  1455. "600": "#ffb300",
  1456. "700": "#ffa000",
  1457. "800": "#ff8f00",
  1458. "900": "#ff6f00",
  1459. },
  1460. "orange": {
  1461. "50": "#fff3e0",
  1462. "100": "#ffe0b2",
  1463. "200": "#ffcc80",
  1464. "300": "#ffb74d",
  1465. "400": "#ffa726",
  1466. "500": "#ff9800",
  1467. "600": "#fb8c00",
  1468. "700": "#f57c00",
  1469. "800": "#ef6c00",
  1470. "900": "#e65100",
  1471. },
  1472. "deeporange": {
  1473. "50": "#fbe9e7",
  1474. "100": "#ffccbc",
  1475. "200": "#ffab91",
  1476. "300": "#ff8a65",
  1477. "400": "#ff7043",
  1478. "500": "#ff5722",
  1479. "600": "#f4511e",
  1480. "700": "#e64a19",
  1481. "800": "#d84315",
  1482. "900": "#bf360c",
  1483. },
  1484. "brown": {
  1485. "50": "#efebe9",
  1486. "100": "#d7ccc8",
  1487. "200": "#bcaaa4",
  1488. "300": "#a1887f",
  1489. "400": "#8d6e63",
  1490. "500": "#795548",
  1491. "600": "#6d4c41",
  1492. "700": "#5d4037",
  1493. "800": "#4e342e",
  1494. "900": "#3e2723"
  1495. },
  1496. "grey": {
  1497. "50": "#fafafa",
  1498. "100": "#f5f5f5",
  1499. "200": "#eeeeee",
  1500. "300": "#e0e0e0",
  1501. "400": "#bdbdbd",
  1502. "500": "#9e9e9e",
  1503. "600": "#757575",
  1504. "700": "#616161",
  1505. "800": "#424242",
  1506. "900": "#212121"
  1507. },
  1508. "bluegrey": {
  1509. "50": "#eceff1",
  1510. "100": "#cfd8dc",
  1511. "200": "#b0bec5",
  1512. "300": "#90a4ae",
  1513. "400": "#78909c",
  1514. "500": "#607d8b",
  1515. "600": "#546e7a",
  1516. "700": "#455a64",
  1517. "800": "#37474f",
  1518. "900": "#263238"
  1519. }
  1520. };
  1521. var x = 0;
  1522. var y = 0;
  1523. var colors = [];
  1524. var col = Object.keys(palette);
  1525. var shade = Object.keys(palette[col[0]]);
  1526. for (var i = 0; i < col.length; i++) {
  1527. for (var j = 0; j < shade.length; j++) {
  1528. if (! colors[j]) {
  1529. colors[j] = [];
  1530. }
  1531. colors[j][i] = palette[col[i]][shade[j]];
  1532. }
  1533. };
  1534. // Value
  1535. if (obj.options.value) {
  1536. el.value = obj.options.value;
  1537. }
  1538. // Table container
  1539. var container = document.createElement('div');
  1540. container.className = 'jcolor';
  1541. // Table container
  1542. var backdrop = document.createElement('div');
  1543. backdrop.className = 'jcolor-backdrop';
  1544. container.appendChild(backdrop);
  1545. // Content
  1546. var content = document.createElement('div');
  1547. content.className = 'jcolor-content';
  1548. // Close button
  1549. var closeButton = document.createElement('div');
  1550. closeButton.className = 'jcolor-close';
  1551. closeButton.innerHTML = 'Done';
  1552. closeButton.onclick = function() {
  1553. obj.close();
  1554. }
  1555. content.appendChild(closeButton);
  1556. // Table pallete
  1557. var table = document.createElement('table');
  1558. table.setAttribute('cellpadding', '7');
  1559. table.setAttribute('cellspacing', '0');
  1560. for (var i = 0; i < colors.length; i++) {
  1561. var tr = document.createElement('tr');
  1562. for (var j = 0; j < colors[i].length; j++) {
  1563. var td = document.createElement('td');
  1564. td.style.backgroundColor = colors[i][j];
  1565. td.setAttribute('data-value', colors[i][j]);
  1566. td.innerHTML = '';
  1567. tr.appendChild(td);
  1568. // Selected color
  1569. if (obj.options.value == colors[i][j]) {
  1570. td.classList.add('jcolor-selected');
  1571. }
  1572. // Possible values
  1573. obj.values[colors[i][j]] = td;
  1574. }
  1575. table.appendChild(tr);
  1576. }
  1577. /**
  1578. * Open color pallete
  1579. */
  1580. obj.open = function() {
  1581. if (jSuites.color.current) {
  1582. if (jSuites.color.current != obj) {
  1583. jSuites.color.current.close();
  1584. }
  1585. }
  1586. if (! jSuites.color.current) {
  1587. // Persist element
  1588. jSuites.color.current = obj;
  1589. // Show colorpicker
  1590. container.classList.add('jcolor-focus');
  1591. const rectContent = content.getBoundingClientRect();
  1592. if (jSuites.getWindowWidth() < 800) {
  1593. content.style.top = '';
  1594. content.classList.add('jcolor-fullscreen');
  1595. jSuites.slideBottom(content, 1);
  1596. backdrop.style.display = 'block';
  1597. } else {
  1598. if (content.classList.contains('jcolor-fullscreen')) {
  1599. content.classList.remove('jcolor-fullscreen');
  1600. backdrop.style.display = '';
  1601. }
  1602. const rect = el.getBoundingClientRect();
  1603. if (window.innerHeight < rect.bottom + rectContent.height) {
  1604. content.style.top = -1 * (rectContent.height + 2) + 'px';
  1605. } else {
  1606. content.style.top = rect.height + 'px';
  1607. }
  1608. }
  1609. container.focus();
  1610. }
  1611. }
  1612. /**
  1613. * Close color pallete
  1614. */
  1615. obj.close = function(ignoreEvents) {
  1616. if (jSuites.color.current) {
  1617. jSuites.color.current = null;
  1618. if (! ignoreEvents && typeof(obj.options.onclose) == 'function') {
  1619. obj.options.onclose(el);
  1620. }
  1621. container.classList.remove('jcolor-focus');
  1622. }
  1623. // Make sure backdrop is hidden
  1624. backdrop.style.display = '';
  1625. return obj.options.value;
  1626. }
  1627. /**
  1628. * Set value
  1629. */
  1630. obj.setValue = function(color) {
  1631. if (color) {
  1632. el.value = color;
  1633. obj.options.value = color;
  1634. }
  1635. // Remove current selecded mark
  1636. var selected = container.querySelector('.jcolor-selected');
  1637. if (selected) {
  1638. selected.classList.remove('jcolor-selected');
  1639. }
  1640. // Mark cell as selected
  1641. obj.values[color].classList.add('jcolor-selected');
  1642. // Onchange
  1643. if (typeof(obj.options.onchange) == 'function') {
  1644. obj.options.onchange(el, color);
  1645. }
  1646. }
  1647. /**
  1648. * Get value
  1649. */
  1650. obj.getValue = function() {
  1651. return obj.options.value;
  1652. }
  1653. /**
  1654. * If element is focus open the picker
  1655. */
  1656. el.addEventListener("focus", function(e) {
  1657. obj.open();
  1658. });
  1659. el.addEventListener("mousedown", function(e) {
  1660. obj.open();
  1661. });
  1662. // Select color
  1663. container.addEventListener("mouseup", function(e) {
  1664. if (e.target.tagName == 'TD') {
  1665. jSuites.color.current.setValue(e.target.getAttribute('data-value'));
  1666. jSuites.color.current.close();
  1667. }
  1668. });
  1669. // Close controller
  1670. document.addEventListener("mousedown", function(e) {
  1671. if (jSuites.color.current) {
  1672. var element = jSuites.getElement(e.target, 'jcolor');
  1673. if (! element) {
  1674. jSuites.color.current.close();
  1675. }
  1676. }
  1677. });
  1678. // Possible to focus the container
  1679. container.setAttribute('tabindex', '900');
  1680. // Placeholder
  1681. if (obj.options.placeholder) {
  1682. el.setAttribute('placeholder', obj.options.placeholder);
  1683. }
  1684. // Append to the table
  1685. content.appendChild(table);
  1686. container.appendChild(content);
  1687. // Insert picker after the element
  1688. el.parentNode.insertBefore(container, el);
  1689. // Keep object available from the node
  1690. el.color = obj;
  1691. return obj;
  1692. });
  1693. jSuites.contextmenu = (function(el, options) {
  1694. var obj = {};
  1695. obj.options = {};
  1696. // Default configuration
  1697. var defaults = {
  1698. items: null,
  1699. onclick: null,
  1700. };
  1701. // Loop through our object
  1702. for (var property in defaults) {
  1703. if (options && options.hasOwnProperty(property)) {
  1704. obj.options[property] = options[property];
  1705. } else {
  1706. obj.options[property] = defaults[property];
  1707. }
  1708. }
  1709. // Class definition
  1710. el.classList.add('jcontextmenu');
  1711. // Focusable
  1712. el.setAttribute('tabindex', '900');
  1713. /**
  1714. * Open contextmenu
  1715. */
  1716. obj.open = function(e, items) {
  1717. if (items) {
  1718. // Update content
  1719. obj.options.items = items;
  1720. // Create items
  1721. obj.create(items);
  1722. }
  1723. // Coordinates
  1724. if (e.target) {
  1725. var x = e.clientX;
  1726. var y = e.clientY;
  1727. } else {
  1728. var x = e.x;
  1729. var y = e.y;
  1730. }
  1731. el.classList.add('jcontextmenu-focus');
  1732. el.focus();
  1733. const rect = el.getBoundingClientRect();
  1734. if (window.innerHeight < y + rect.height) {
  1735. el.style.top = (y - rect.height) + 'px';
  1736. } else {
  1737. el.style.top = y + 'px';
  1738. }
  1739. if (window.innerWidth < x + rect.width) {
  1740. if (x - rect.width > 0) {
  1741. el.style.left = (x - rect.width) + 'px';
  1742. } else {
  1743. el.style.left = '10px';
  1744. }
  1745. } else {
  1746. el.style.left = x + 'px';
  1747. }
  1748. }
  1749. /**
  1750. * Close menu
  1751. */
  1752. obj.close = function() {
  1753. if (el.classList.contains('jcontextmenu-focus')) {
  1754. el.classList.remove('jcontextmenu-focus');
  1755. }
  1756. }
  1757. /**
  1758. * Create items based on the declared objectd
  1759. * @param {object} items - List of object
  1760. */
  1761. obj.create = function(items) {
  1762. // Update content
  1763. el.innerHTML = '';
  1764. // Append items
  1765. for (var i = 0; i < items.length; i++) {
  1766. if (items[i].type && items[i].type == 'line') {
  1767. var itemContainer = document.createElement('hr');
  1768. } else {
  1769. var itemContainer = document.createElement('div');
  1770. var itemText = document.createElement('a');
  1771. itemText.innerHTML = items[i].title;
  1772. if (items[i].disabled) {
  1773. itemContainer.className = 'jcontextmenu-disabled';
  1774. } else if (items[i].onclick) {
  1775. itemContainer.method = items[i].onclick;
  1776. itemContainer.addEventListener("mouseup", function() {
  1777. // Execute method
  1778. this.method(this);
  1779. });
  1780. }
  1781. itemContainer.appendChild(itemText);
  1782. if (items[i].shortcut) {
  1783. var itemShortCut = document.createElement('span');
  1784. itemShortCut.innerHTML = items[i].shortcut;
  1785. itemContainer.appendChild(itemShortCut);
  1786. }
  1787. }
  1788. el.appendChild(itemContainer);
  1789. }
  1790. }
  1791. if (typeof(obj.options.onclick) == 'function') {
  1792. el.addEventListener('click', function(e) {
  1793. obj.options.onclick(obj);
  1794. });
  1795. }
  1796. el.addEventListener('blur', function(e) {
  1797. setTimeout(function() {
  1798. obj.close();
  1799. }, 120);
  1800. });
  1801. window.addEventListener("mousewheel", function() {
  1802. obj.close();
  1803. });
  1804. // Create items
  1805. if (obj.options.items) {
  1806. obj.create(obj.options.items);
  1807. }
  1808. el.contextmenu = obj;
  1809. return obj;
  1810. });
  1811. jSuites.contextmenu.getElement = function(element) {
  1812. var foundId = 0;
  1813. function path (element) {
  1814. if (element.parentNode && element.getAttribute('aria-contextmenu-id')) {
  1815. foundId = element.getAttribute('aria-contextmenu-id')
  1816. } else {
  1817. if (element.parentNode) {
  1818. path(element.parentNode);
  1819. }
  1820. }
  1821. }
  1822. path(element);
  1823. return foundId;
  1824. }
  1825. document.addEventListener("contextmenu", function(e) {
  1826. var id = jSuites.contextmenu.getElement(e.target);
  1827. if (id) {
  1828. var element = document.querySelector('#' + id);
  1829. if (! element) {
  1830. console.error('JSUITES: Contextmenu id not found');
  1831. } else {
  1832. element.contextmenu.open(e);
  1833. e.preventDefault();
  1834. }
  1835. }
  1836. });
  1837. /**
  1838. * Dialog v1.0.1
  1839. * Author: paul.hodel@gmail.com
  1840. * https://github.com/paulhodel/jtools
  1841. */
  1842. jSuites.dialog = (function() {
  1843. var obj = {};
  1844. obj.options = {};
  1845. var dialog = document.createElement('div');
  1846. dialog.setAttribute('tabindex', '901');
  1847. dialog.className = 'jdialog';
  1848. dialog.id = 'dialog';
  1849. var dialogHeader = document.createElement('div');
  1850. dialogHeader.className = 'jdialog-header';
  1851. var dialogTitle = document.createElement('div');
  1852. dialogTitle.className = 'jdialog-title';
  1853. dialogHeader.appendChild(dialogTitle);
  1854. var dialogMessage = document.createElement('div');
  1855. dialogMessage.className = 'jdialog-message';
  1856. dialogHeader.appendChild(dialogMessage);
  1857. var dialogFooter = document.createElement('div');
  1858. dialogFooter.className = 'jdialog-footer';
  1859. var dialogContainer = document.createElement('div');
  1860. dialogContainer.className = 'jdialog-container';
  1861. dialogContainer.appendChild(dialogHeader);
  1862. dialogContainer.appendChild(dialogFooter);
  1863. // Confirm
  1864. var dialogConfirm = document.createElement('div');
  1865. var dialogConfirmButton = document.createElement('input');
  1866. dialogConfirmButton.value = obj.options.confirmLabel;
  1867. dialogConfirmButton.type = 'button';
  1868. dialogConfirmButton.onclick = function() {
  1869. if (typeof(obj.options.onconfirm) == 'function') {
  1870. obj.options.onconfirm();
  1871. }
  1872. obj.close();
  1873. };
  1874. dialogConfirm.appendChild(dialogConfirmButton);
  1875. dialogFooter.appendChild(dialogConfirm);
  1876. // Cancel
  1877. var dialogCancel = document.createElement('div');
  1878. var dialogCancelButton = document.createElement('input');
  1879. dialogCancelButton.value = obj.options.cancelLabel;
  1880. dialogCancelButton.type = 'button';
  1881. dialogCancelButton.onclick = function() {
  1882. if (typeof(obj.options.oncancel) == 'function') {
  1883. obj.options.oncancel();
  1884. }
  1885. obj.close();
  1886. }
  1887. dialogCancel.appendChild(dialogCancelButton);
  1888. dialogFooter.appendChild(dialogCancel);
  1889. // Dialog
  1890. dialog.appendChild(dialogContainer);
  1891. obj.open = function(options) {
  1892. obj.options = options;
  1893. if (obj.options.title) {
  1894. dialogTitle.innerHTML = obj.options.title;
  1895. }
  1896. if (obj.options.message) {
  1897. dialogMessage.innerHTML = obj.options.message;
  1898. }
  1899. if (! obj.options.confirmLabel) {
  1900. obj.options.confirmLabel = 'OK';
  1901. }
  1902. dialogConfirmButton.value = obj.options.confirmLabel;
  1903. if (! obj.options.cancelLabel) {
  1904. obj.options.cancelLabel = 'Cancel';
  1905. }
  1906. dialogCancelButton.value = obj.options.cancelLabel;
  1907. if (obj.options.type == 'confirm') {
  1908. dialogCancelButton.parentNode.style.display = '';
  1909. } else {
  1910. dialogCancelButton.parentNode.style.display = 'none';
  1911. }
  1912. // Append element to the app
  1913. dialog.style.opacity = 100;
  1914. // Append to the page
  1915. if (jSuites.el) {
  1916. jSuites.el.appendChild(dialog);
  1917. } else {
  1918. document.body.appendChild(dialog);
  1919. }
  1920. // Focus
  1921. dialog.focus();
  1922. // Show
  1923. setTimeout(function() {
  1924. dialogContainer.style.opacity = 100;
  1925. }, 0);
  1926. };
  1927. obj.close = function() {
  1928. dialog.style.opacity = 0;
  1929. dialogContainer.style.opacity = 0;
  1930. setTimeout(function() {
  1931. dialog.remove();
  1932. }, 100);
  1933. };
  1934. return obj;
  1935. })();
  1936. jSuites.confirm = (function(message, onconfirm) {
  1937. if (jSuites.getWindowWidth() < 800) {
  1938. jSuites.dialog.open({
  1939. type: 'confirm',
  1940. message: message,
  1941. title: 'Confirmation',
  1942. onconfirm: onconfirm,
  1943. });
  1944. } else {
  1945. if (confirm(message)) {
  1946. onconfirm();
  1947. }
  1948. }
  1949. });
  1950. jSuites.alert = function(message) {
  1951. if (jSuites.getWindowWidth() < 800) {
  1952. jSuites.dialog.open({
  1953. title:'Alert',
  1954. message:message,
  1955. });
  1956. } else {
  1957. alert(message);
  1958. }
  1959. }
  1960. jSuites.dropdown = (function(el, options) {
  1961. var obj = {};
  1962. obj.options = {};
  1963. // If the element is a SELECT tag, create a configuration object
  1964. if (el.tagName == 'SELECT') {
  1965. var ret = jSuites.dropdown.extractFromDom(el, options);
  1966. el = ret.el;
  1967. options = ret.options;
  1968. }
  1969. // Default configuration
  1970. var defaults = {
  1971. url: null,
  1972. data: [],
  1973. multiple: false,
  1974. autocomplete: false,
  1975. type: null,
  1976. width: null,
  1977. opened: false,
  1978. value: null,
  1979. placeholder: '',
  1980. position: false,
  1981. onchange: null,
  1982. onload: null,
  1983. onopen: null,
  1984. onclose: null,
  1985. onblur: null,
  1986. };
  1987. // Loop through our object
  1988. for (var property in defaults) {
  1989. if (options && options.hasOwnProperty(property)) {
  1990. obj.options[property] = options[property];
  1991. } else {
  1992. obj.options[property] = defaults[property];
  1993. }
  1994. }
  1995. // Global container
  1996. if (! jSuites.dropdown.current) {
  1997. jSuites.dropdown.current = null;
  1998. }
  1999. // Containers
  2000. obj.items = [];
  2001. obj.groups = [];
  2002. obj.selected = [];
  2003. // Create dropdown
  2004. el.classList.add('jdropdown');
  2005. if (obj.options.type == 'searchbar') {
  2006. el.classList.add('jdropdown-searchbar');
  2007. } else if (obj.options.type == 'list') {
  2008. el.classList.add('jdropdown-list');
  2009. } else if (obj.options.type == 'picker') {
  2010. el.classList.add('jdropdown-picker');
  2011. } else {
  2012. if (jSuites.getWindowWidth() < 800) {
  2013. el.classList.add('jdropdown-picker');
  2014. obj.options.type = 'picker';
  2015. } else {
  2016. if (obj.options.width) {
  2017. el.style.width = obj.options.width;
  2018. el.style.minWidth = obj.options.width;
  2019. }
  2020. el.classList.add('jdropdown-default');
  2021. obj.options.type = 'default';
  2022. }
  2023. }
  2024. // Header container
  2025. var containerHeader = document.createElement('div');
  2026. containerHeader.className = 'jdropdown-container-header';
  2027. // Header
  2028. var header = document.createElement('input');
  2029. header.className = 'jdropdown-header';
  2030. if (typeof(obj.options.onblur) == 'function') {
  2031. header.onblur = function() {
  2032. obj.options.onblur(el);
  2033. }
  2034. }
  2035. // Container
  2036. var container = document.createElement('div');
  2037. container.className = 'jdropdown-container';
  2038. // Dropdown content
  2039. var content = document.createElement('div');
  2040. content.className = 'jdropdown-content';
  2041. // Close button
  2042. var closeButton = document.createElement('div');
  2043. closeButton.className = 'jdropdown-close';
  2044. closeButton.innerHTML = 'Done';
  2045. // Create backdrop
  2046. var backdrop = document.createElement('div');
  2047. backdrop.className = 'jdropdown-backdrop';
  2048. // Autocomplete
  2049. if (obj.options.autocomplete == true) {
  2050. el.setAttribute('data-autocomplete', true);
  2051. // Handler
  2052. var keyTimer = null;
  2053. header.addEventListener('keyup', function(e) {
  2054. if (keyTimer) {
  2055. clearTimeout(keyTimer);
  2056. }
  2057. keyTimer = setTimeout(function() {
  2058. obj.find(header.value);
  2059. keyTimer = null;
  2060. }, 500);
  2061. if (! el.classList.contains('jdropdown-focus')) {
  2062. if (e.which > 65) {
  2063. obj.open();
  2064. }
  2065. }
  2066. });
  2067. } else {
  2068. header.setAttribute('readonly', 'readonly');
  2069. }
  2070. // Place holder
  2071. if (! obj.options.placeholder && el.getAttribute('placeholder')) {
  2072. obj.options.placeholder = el.getAttribute('placeholder');
  2073. }
  2074. if (obj.options.placeholder) {
  2075. header.setAttribute('placeholder', obj.options.placeholder);
  2076. }
  2077. // Append elements
  2078. containerHeader.appendChild(header);
  2079. if (obj.options.type == 'searchbar') {
  2080. containerHeader.appendChild(closeButton);
  2081. } else {
  2082. container.appendChild(closeButton);
  2083. }
  2084. container.appendChild(content);
  2085. el.appendChild(containerHeader);
  2086. el.appendChild(container);
  2087. el.appendChild(backdrop);
  2088. /**
  2089. * Init dropdown
  2090. */
  2091. obj.init = function() {
  2092. if (obj.options.url) {
  2093. jSuites.ajax({
  2094. url: obj.options.url,
  2095. method: 'GET',
  2096. dataType: 'json',
  2097. success: function(data) {
  2098. if (data) {
  2099. // Set data
  2100. obj.setData(data);
  2101. // Set value
  2102. if (obj.options.value != null) {
  2103. obj.setValue(obj.options.value);
  2104. }
  2105. // Onload method
  2106. if (typeof(obj.options.onload) == 'function') {
  2107. obj.options.onload(el, obj, data);
  2108. }
  2109. }
  2110. }
  2111. });
  2112. } else {
  2113. // Set data
  2114. obj.setData();
  2115. // Set value
  2116. if (obj.options.value != null) {
  2117. obj.setValue(obj.options.value);
  2118. }
  2119. // Onload
  2120. if (typeof(obj.options.onload) == 'function') {
  2121. obj.options.onload(el, obj, data);
  2122. }
  2123. }
  2124. // Open dropdown
  2125. if (obj.options.opened == true) {
  2126. obj.open();
  2127. }
  2128. }
  2129. obj.getUrl = function() {
  2130. return obj.options.url;
  2131. }
  2132. obj.setUrl = function(url) {
  2133. obj.options.url = url;
  2134. jSuites.ajax({
  2135. url: obj.options.url,
  2136. method: 'GET',
  2137. dataType: 'json',
  2138. success: function(data) {
  2139. obj.setData(data);
  2140. }
  2141. });
  2142. }
  2143. /**
  2144. * Create a new item
  2145. */
  2146. obj.createItem = function(data) {
  2147. // Create item
  2148. var item = {};
  2149. item.element = document.createElement('div');
  2150. item.element.className = 'jdropdown-item';
  2151. item.value = data.id;
  2152. item.text = data.name;
  2153. item.textLowerCase = '' + data.name.toLowerCase();
  2154. // Image
  2155. if (data.image) {
  2156. var image = document.createElement('img');
  2157. image.className = 'jdropdown-image';
  2158. image.src = data.image;
  2159. if (! data.title) {
  2160. image.classList.add('jdropdown-image-small');
  2161. }
  2162. item.element.appendChild(image);
  2163. }
  2164. // Set content
  2165. var node = document.createElement('div');
  2166. node.className = 'jdropdown-description';
  2167. node.innerHTML = data.name;
  2168. // Title
  2169. if (data.title) {
  2170. var title = document.createElement('div');
  2171. title.className = 'jdropdown-title';
  2172. title.innerHTML = data.title;
  2173. node.appendChild(title);
  2174. }
  2175. // Add node to item
  2176. item.element.appendChild(node);
  2177. return item;
  2178. }
  2179. obj.setData = function(data) {
  2180. // Update data
  2181. if (data) {
  2182. obj.options.data = data;
  2183. }
  2184. // Data
  2185. var data = obj.options.data;
  2186. // Make sure the content container is blank
  2187. content.innerHTML = '';
  2188. // Reset
  2189. obj.reset();
  2190. // Reset items
  2191. obj.items = [];
  2192. // Helpers
  2193. var items = [];
  2194. var groups = [];
  2195. // Create elements
  2196. if (data.length) {
  2197. // Prepare data
  2198. for (var i = 0; i < data.length; i++) {
  2199. // Compatibility
  2200. if (typeof(data[i]) != 'object') {
  2201. // Correct format
  2202. obj.options.data[i] = data[i] = { id: data[i], name: data[i] };
  2203. }
  2204. // Process groups
  2205. if (data[i].group) {
  2206. if (! groups[data[i].group]) {
  2207. groups[data[i].group] = [];
  2208. }
  2209. groups[data[i].group].push(i);
  2210. } else {
  2211. items.push(i);
  2212. }
  2213. }
  2214. // Groups
  2215. var groupNames = Object.keys(groups);
  2216. // Append groups in case exists
  2217. if (groupNames.length > 0) {
  2218. for (var i = 0; i < groupNames.length; i++) {
  2219. // Group container
  2220. var group = document.createElement('div');
  2221. group.className = 'jdropdown-group';
  2222. // Group name
  2223. var groupName = document.createElement('div');
  2224. groupName.className = 'jdropdown-group-name';
  2225. groupName.innerHTML = groupNames[i];
  2226. // Group arrow
  2227. var groupArrow = document.createElement('i');
  2228. groupArrow.className = 'jdropdown-group-arrow jdropdown-group-arrow-down';
  2229. groupName.appendChild(groupArrow);
  2230. // Group items
  2231. var groupContent = document.createElement('div');
  2232. groupContent.className = 'jdropdown-group-items';
  2233. for (var j = 0; j < groups[groupNames[i]].length; j++) {
  2234. var item = obj.createItem(data[groups[groupNames[i]][j]]);
  2235. groupContent.appendChild(item.element);
  2236. // Items
  2237. obj.items.push(item);
  2238. }
  2239. // Group itens
  2240. group.appendChild(groupName);
  2241. group.appendChild(groupArrow);
  2242. group.appendChild(groupContent);
  2243. content.appendChild(group);
  2244. }
  2245. }
  2246. if (items.length) {
  2247. for (var i = 0; i < items.length; i++) {
  2248. var item = obj.createItem(data[items[i]]);
  2249. obj.items.push(item);
  2250. content.appendChild(item.element);
  2251. }
  2252. }
  2253. // Create the Indexes
  2254. for (var i = 0; i < obj.items.length; i++) {
  2255. obj.items[i].element.setAttribute('data-index', i);
  2256. }
  2257. }
  2258. }
  2259. obj.getText = function(asArray) {
  2260. // Result
  2261. var result = [];
  2262. // Append options
  2263. for (var i = 0; i < obj.selected.length; i++) {
  2264. if (obj.items[obj.selected[i]]) {
  2265. result.push(obj.items[obj.selected[i]].text);
  2266. }
  2267. }
  2268. if (asArray) {
  2269. return result;
  2270. } else {
  2271. return result.join('; ');
  2272. }
  2273. }
  2274. obj.getValue = function(asArray) {
  2275. // Result
  2276. var result = [];
  2277. // Append options
  2278. for (var i = 0; i < obj.selected.length; i++) {
  2279. if (obj.items[obj.selected[i]]) {
  2280. result.push(obj.items[obj.selected[i]].value);
  2281. }
  2282. }
  2283. if (asArray) {
  2284. return result;
  2285. } else {
  2286. return result.join(';');
  2287. }
  2288. }
  2289. obj.setValue = function(value) {
  2290. // Remove values
  2291. for (var i = 0; i < obj.selected.length; i++) {
  2292. obj.items[obj.selected[i]].element.classList.remove('jdropdown-selected')
  2293. }
  2294. // Reset selected
  2295. obj.selected = [];
  2296. // Set values
  2297. if (value != null) {
  2298. if (Array.isArray(value)) {
  2299. for (var i = 0; i < obj.items.length; i++) {
  2300. for (var j = 0; j < value.length; j++) {
  2301. if (obj.items[i].value == value[j]) {
  2302. // Keep index of the selected item
  2303. obj.selected.push(i);
  2304. // Visual selection
  2305. obj.items[i].element.classList.add('jdropdown-selected');
  2306. }
  2307. }
  2308. }
  2309. } else {
  2310. for (var i = 0; i < obj.items.length; i++) {
  2311. if (obj.items[i].value == value) {
  2312. // Keep index of the selected item
  2313. obj.selected.push(i);
  2314. // Visual selection
  2315. obj.items[i].element.classList.add('jdropdown-selected');
  2316. }
  2317. }
  2318. }
  2319. }
  2320. // Update labels
  2321. obj.updateLabel();
  2322. }
  2323. obj.selectIndex = function(index) {
  2324. // Only select those existing elements
  2325. if (obj.items && obj.items[index]) {
  2326. var index = index = parseInt(index);
  2327. // Current selection
  2328. var oldValue = obj.getValue();
  2329. var oldLabel = obj.getText();
  2330. // Remove cursor style
  2331. if (obj.currentIndex != null) {
  2332. obj.items[obj.currentIndex].element.classList.remove('jdropdown-cursor');
  2333. }
  2334. // Set cursor style
  2335. obj.items[index].element.classList.add('jdropdown-cursor');
  2336. // Update cursor position
  2337. obj.currentIndex = index;
  2338. // Focus behaviour
  2339. if (! obj.options.multiple) {
  2340. // Unselect option
  2341. if (obj.items[index].element.classList.contains('jdropdown-selected')) {
  2342. // Reset selected
  2343. obj.resetSelected();
  2344. } else {
  2345. // Reset selected
  2346. obj.resetSelected();
  2347. // Update selected item
  2348. obj.items[index].element.classList.add('jdropdown-selected');
  2349. // Add to the selected list
  2350. obj.selected.push(index);
  2351. // Close
  2352. obj.close();
  2353. }
  2354. } else {
  2355. // Toggle option
  2356. if (obj.items[index].element.classList.contains('jdropdown-selected')) {
  2357. obj.items[index].element.classList.remove('jdropdown-selected');
  2358. // Remove from selected list
  2359. var indexToRemove = obj.selected.indexOf(index);
  2360. // Remove select
  2361. obj.selected.splice(indexToRemove, 1);
  2362. } else {
  2363. // Select element
  2364. obj.items[index].element.classList.add('jdropdown-selected');
  2365. // Add to the selected list
  2366. obj.selected.push(index);
  2367. }
  2368. // Update labels for multiple dropdown
  2369. if (! obj.options.autocomplete) {
  2370. obj.updateLabel();
  2371. }
  2372. }
  2373. // Current selection
  2374. var newValue = obj.getValue();
  2375. var newLabel = obj.getText();
  2376. // Events
  2377. if (typeof(obj.options.onchange) == 'function') {
  2378. obj.options.onchange(el, index, oldValue, newValue, oldLabel, newLabel);
  2379. }
  2380. }
  2381. }
  2382. obj.selectItem = function(item) {
  2383. if (jSuites.dropdown.current) {
  2384. var index = item.getAttribute('data-index');
  2385. if (index != null) {
  2386. obj.selectIndex(index);
  2387. }
  2388. }
  2389. }
  2390. obj.find = function(str) {
  2391. // Force lowercase
  2392. var str = str ? str.toLowerCase() : null;
  2393. // Append options
  2394. for (var i = 0; i < obj.items.length; i++) {
  2395. if (str == null || obj.items[i].textLowerCase.indexOf(str) != -1) {
  2396. obj.items[i].element.style.display = '';
  2397. } else {
  2398. if (obj.selected.indexOf(i) == -1) {
  2399. obj.items[i].element.style.display = 'none';
  2400. } else {
  2401. obj.items[i].element.style.display = '';
  2402. }
  2403. }
  2404. }
  2405. var numVisibleItems = function(items) {
  2406. var visible = 0;
  2407. for (var j = 0; j < items.length; j++) {
  2408. if (items[j].style.display != 'none') {
  2409. visible++;
  2410. }
  2411. }
  2412. return visible;
  2413. }
  2414. // Hide groups
  2415. /*for (var i = 0; i < obj.groups.length; i++) {
  2416. if (numVisibleItems(obj.groups[i].querySelectorAll('.jdropdown-item'))) {
  2417. obj.groups[i].children[0].style.display = '';
  2418. } else {
  2419. obj.groups[i].children[0].style.display = 'none';
  2420. }
  2421. }*/
  2422. }
  2423. obj.updateLabel = function() {
  2424. // Update label
  2425. header.value = obj.getText();
  2426. }
  2427. obj.open = function() {
  2428. if (jSuites.dropdown.current != el) {
  2429. if (jSuites.dropdown.current) {
  2430. jSuites.dropdown.current.dropdown.close();
  2431. }
  2432. jSuites.dropdown.current = el;
  2433. }
  2434. // Focus
  2435. if (! el.classList.contains('jdropdown-focus')) {
  2436. // Add focus
  2437. el.classList.add('jdropdown-focus');
  2438. // Animation
  2439. if (jSuites.getWindowWidth() < 800) {
  2440. if (obj.options.type == null || obj.options.type == 'picker') {
  2441. jSuites.slideBottom(container, 1);
  2442. }
  2443. }
  2444. // Filter
  2445. if (obj.options.autocomplete == true) {
  2446. // Redo search
  2447. obj.find();
  2448. // Clear search field
  2449. header.value = '';
  2450. header.focus();
  2451. }
  2452. // Set cursor for the first or first selected element
  2453. var cursor = (obj.selected && obj.selected[0]) ? obj.selected[0] : 0;
  2454. obj.updateCursor(cursor);
  2455. // Container Size
  2456. if (! obj.options.type || obj.options.type == 'default') {
  2457. const rect = el.getBoundingClientRect();
  2458. const rectContainer = container.getBoundingClientRect();
  2459. if (obj.options.position) {
  2460. container.style.position = 'fixed';
  2461. if (window.innerHeight < rect.bottom + rectContainer.height) {
  2462. container.style.top = '';
  2463. container.style.bottom = (window.innerHeight - rect.top ) + 1 + 'px';
  2464. } else {
  2465. container.style.top = rect.bottom + 'px';
  2466. container.style.bottom = '';
  2467. }
  2468. container.style.left = rect.left + 'px';
  2469. } else {
  2470. if (window.innerHeight < rect.bottom + rectContainer.height) {
  2471. container.style.top = '';
  2472. container.style.bottom = rect.height + 1 + 'px';
  2473. } else {
  2474. container.style.top = '';
  2475. container.style.bottom = '';
  2476. }
  2477. }
  2478. container.style.minWidth = rect.width + 'px';
  2479. }
  2480. }
  2481. // Events
  2482. if (typeof(obj.options.onopen) == 'function') {
  2483. obj.options.onopen(el);
  2484. }
  2485. }
  2486. obj.close = function(ignoreEvents) {
  2487. if (jSuites.dropdown.current) {
  2488. // Remove controller
  2489. jSuites.dropdown.current = null
  2490. // Remove cursor
  2491. obj.resetCursor();
  2492. // Update labels
  2493. obj.updateLabel();
  2494. // Events
  2495. if (! ignoreEvents && typeof(obj.options.onclose) == 'function') {
  2496. obj.options.onclose(el);
  2497. }
  2498. // Blur
  2499. if (header.blur) {
  2500. header.blur();
  2501. }
  2502. // Remove focus
  2503. el.classList.remove('jdropdown-focus');
  2504. }
  2505. return obj.getValue();
  2506. }
  2507. /**
  2508. * Update position cursor
  2509. */
  2510. obj.updateCursor = function(index) {
  2511. // Set new cursor
  2512. if (obj.items && obj.items[index] && obj.items[index].element) {
  2513. // Reset cursor
  2514. obj.resetCursor();
  2515. // Set new cursor
  2516. obj.items[index].element.classList.add('jdropdown-cursor');
  2517. // Update position
  2518. obj.currentIndex = parseInt(index);
  2519. // Update scroll to the cursor element
  2520. var container = content.scrollTop;
  2521. var element = obj.items[obj.currentIndex].element;
  2522. content.scrollTop = element.offsetTop - element.scrollTop + element.clientTop - 95;
  2523. }
  2524. }
  2525. /**
  2526. * Reset cursor
  2527. */
  2528. obj.resetCursor = function() {
  2529. // Remove current cursor
  2530. if (obj.currentIndex != null) {
  2531. // Remove visual cursor
  2532. if (obj.items && obj.items[obj.currentIndex]) {
  2533. obj.items[obj.currentIndex].element.classList.remove('jdropdown-cursor');
  2534. }
  2535. // Reset cursor
  2536. obj.currentIndex = null;
  2537. }
  2538. }
  2539. /**
  2540. * Reset cursor
  2541. */
  2542. obj.resetSelected = function() {
  2543. // Unselected all
  2544. if (obj.selected) {
  2545. // Remove visual selection
  2546. for (var i = 0; i < obj.selected.length; i++) {
  2547. if (obj.items[obj.selected[i]]) {
  2548. obj.items[obj.selected[i]].element.classList.remove('jdropdown-selected');
  2549. }
  2550. }
  2551. // Reset current selected items
  2552. obj.selected = [];
  2553. }
  2554. }
  2555. /**
  2556. * Reset cursor and selected items
  2557. */
  2558. obj.reset = function() {
  2559. // Reset cursor
  2560. obj.resetCursor();
  2561. // Reset selected
  2562. obj.resetSelected();
  2563. // Update labels
  2564. obj.updateLabel();
  2565. }
  2566. /**
  2567. * First visible item
  2568. */
  2569. obj.firstVisible = function() {
  2570. var newIndex = null;
  2571. for (var i = 0; i < obj.items.length; i++) {
  2572. if (obj.items[i].element.style.display != 'none') {
  2573. newIndex = i;
  2574. break;
  2575. }
  2576. }
  2577. if (newIndex == null) {
  2578. return false;
  2579. }
  2580. obj.updateCursor(newIndex);
  2581. }
  2582. /**
  2583. * Navigation
  2584. */
  2585. obj.first = function() {
  2586. var newIndex = null;
  2587. for (var i = obj.currentIndex - 1; i >= 0; i--) {
  2588. if (obj.items[i].element.style.display != 'none') {
  2589. newIndex = i;
  2590. }
  2591. }
  2592. if (newIndex == null) {
  2593. return false;
  2594. }
  2595. obj.updateCursor(newIndex);
  2596. }
  2597. obj.last = function() {
  2598. var newIndex = null;
  2599. for (var i = obj.currentIndex + 1; i < obj.items.length; i++) {
  2600. if (obj.items[i].element.style.display != 'none') {
  2601. newIndex = i;
  2602. }
  2603. }
  2604. if (newIndex == null) {
  2605. return false;
  2606. }
  2607. obj.updateCursor(newIndex);
  2608. }
  2609. obj.next = function() {
  2610. var newIndex = null;
  2611. for (var i = obj.currentIndex + 1; i < obj.items.length; i++) {
  2612. if (obj.items[i].element.style.display != 'none') {
  2613. newIndex = i;
  2614. break;
  2615. }
  2616. }
  2617. if (newIndex == null) {
  2618. return false;
  2619. }
  2620. obj.updateCursor(newIndex);
  2621. }
  2622. obj.prev = function() {
  2623. var newIndex = null;
  2624. for (var i = obj.currentIndex - 1; i >= 0; i--) {
  2625. if (obj.items[i].element.style.display != 'none') {
  2626. newIndex = i;
  2627. break;
  2628. }
  2629. }
  2630. if (newIndex == null) {
  2631. return false;
  2632. }
  2633. obj.updateCursor(newIndex);
  2634. }
  2635. if (! jSuites.dropdown.hasEvents) {
  2636. if ('ontouchsend' in document.documentElement === true) {
  2637. document.addEventListener('touchsend', jSuites.dropdown.mouseup);
  2638. } else {
  2639. document.addEventListener('mouseup', jSuites.dropdown.mouseup);
  2640. }
  2641. document.addEventListener('keydown', jSuites.dropdown.onkeydown);
  2642. jSuites.dropdown.hasEvents = true;
  2643. }
  2644. // Start dropdown
  2645. obj.init();
  2646. // Keep object available from the node
  2647. el.dropdown = obj;
  2648. return obj;
  2649. });
  2650. jSuites.dropdown.hasEvents = false;
  2651. jSuites.dropdown.mouseup = function(e) {
  2652. var element = jSuites.getElement(e.target, 'jdropdown');
  2653. if (element) {
  2654. var dropdown = element.dropdown;
  2655. if (e.target.classList.contains('jdropdown-header')) {
  2656. if (element.classList.contains('jdropdown-focus') && element.classList.contains('jdropdown-default')) {
  2657. dropdown.close();
  2658. } else {
  2659. dropdown.open();
  2660. }
  2661. } else if (e.target.classList.contains('jdropdown-group-name')) {
  2662. var items = e.target.nextSibling.children;
  2663. if (e.target.nextSibling.style.display != 'none') {
  2664. for (var i = 0; i < items.length; i++) {
  2665. if (items[i].style.display != 'none') {
  2666. dropdown.selectItem(items[i]);
  2667. }
  2668. }
  2669. }
  2670. } else if (e.target.classList.contains('jdropdown-group-arrow')) {
  2671. if (e.target.classList.contains('jdropdown-group-arrow-down')) {
  2672. e.target.classList.remove('jdropdown-group-arrow-down');
  2673. e.target.classList.add('jdropdown-group-arrow-up');
  2674. e.target.parentNode.nextSibling.style.display = 'none';
  2675. } else {
  2676. e.target.classList.remove('jdropdown-group-arrow-up');
  2677. e.target.classList.add('jdropdown-group-arrow-down');
  2678. e.target.parentNode.nextSibling.style.display = '';
  2679. }
  2680. } else if (e.target.classList.contains('jdropdown-item')) {
  2681. dropdown.selectItem(e.target);
  2682. } else if (e.target.classList.contains('jdropdown-image')) {
  2683. dropdown.selectIndex(e.target.parentNode.getAttribute('data-index'));
  2684. } else if (e.target.classList.contains('jdropdown-description')) {
  2685. dropdown.selectIndex(e.target.parentNode.getAttribute('data-index'));
  2686. } else if (e.target.classList.contains('jdropdown-title')) {
  2687. dropdown.selectIndex(e.target.parentNode.parentNode.getAttribute('data-index'));
  2688. } else if (e.target.classList.contains('jdropdown-close') || e.target.classList.contains('jdropdown-backdrop')) {
  2689. // Close
  2690. dropdown.close();
  2691. }
  2692. e.stopPropagation();
  2693. e.preventDefault();
  2694. } else {
  2695. if (jSuites.dropdown.current) {
  2696. jSuites.dropdown.current.dropdown.close();
  2697. }
  2698. }
  2699. }
  2700. // Keydown controls
  2701. jSuites.dropdown.onkeydown = function(e) {
  2702. if (jSuites.dropdown.current) {
  2703. // Element
  2704. var element = jSuites.dropdown.current.dropdown;
  2705. // Index
  2706. var index = element.currentIndex;
  2707. if (e.shiftKey) {
  2708. } else {
  2709. if (e.which == 13 || e.which == 27 || e.which == 35 || e.which == 36 || e.which == 38 || e.which == 40) {
  2710. // Move cursor
  2711. if (e.which == 13) {
  2712. element.selectIndex(index)
  2713. } else if (e.which == 38) {
  2714. if (index == null) {
  2715. element.firstVisible();
  2716. } else if (index > 0) {
  2717. element.prev();
  2718. }
  2719. } else if (e.which == 40) {
  2720. if (index == null) {
  2721. element.firstVisible();
  2722. } else if (index + 1 < element.options.data.length) {
  2723. element.next();
  2724. }
  2725. } else if (e.which == 36) {
  2726. element.first();
  2727. } else if (e.which == 35) {
  2728. element.last();
  2729. } else if (e.which == 27) {
  2730. element.close();
  2731. }
  2732. e.stopPropagation();
  2733. e.preventDefault();
  2734. }
  2735. }
  2736. }
  2737. }
  2738. jSuites.dropdown.extractFromDom = function(el, options) {
  2739. // Keep reference
  2740. var select = el;
  2741. if (! options) {
  2742. options = {};
  2743. }
  2744. // Prepare configuration
  2745. if (el.getAttribute('multiple') && (! options || options.multiple == undefined)) {
  2746. options.multiple = true;
  2747. }
  2748. if (el.getAttribute('placeholder') && (! options || options.placeholder == undefined)) {
  2749. options.placeholder = el.getAttribute('placeholder');
  2750. }
  2751. if (el.getAttribute('data-autocomplete') && (! options || options.autocomplete == undefined)) {
  2752. options.autocomplete = true;
  2753. }
  2754. if (! options || options.width == undefined) {
  2755. options.width = el.offsetWidth;
  2756. }
  2757. if (el.value && (! options || options.value == undefined)) {
  2758. options.value = el.value;
  2759. }
  2760. if (! options || options.data == undefined) {
  2761. options.data = [];
  2762. for (var j = 0; j < el.children.length; j++) {
  2763. if (el.children[j].tagName == 'OPTGROUP') {
  2764. for (var i = 0; i < el.children[j].children.length; i++) {
  2765. options.data.push({
  2766. id: el.children[j].children[i].value,
  2767. name: el.children[j].children[i].innerHTML,
  2768. group: el.children[j].getAttribute('label'),
  2769. });
  2770. }
  2771. } else {
  2772. options.data.push({
  2773. id: el.children[j].value,
  2774. name: el.children[j].innerHTML,
  2775. });
  2776. }
  2777. }
  2778. }
  2779. if (! options || options.onchange == undefined) {
  2780. options.onchange = function(a,b,c,d) {
  2781. if (options.multiple == true) {
  2782. if (obj.items[b].classList.contains('jdropdown-selected')) {
  2783. select.options[b].setAttribute('selected', 'selected');
  2784. } else {
  2785. select.options[b].removeAttribute('selected');
  2786. }
  2787. } else {
  2788. select.value = d;
  2789. }
  2790. }
  2791. }
  2792. // Create DIV
  2793. var div = document.createElement('div');
  2794. el.parentNode.insertBefore(div, el);
  2795. el.style.display = 'none';
  2796. el = div;
  2797. return { el:el, options:options };
  2798. }
  2799. /**
  2800. * (c) jTools Text Editor
  2801. * https://github.com/paulhodel/jtools
  2802. *
  2803. * @author: Paul Hodel <paul.hodel@gmail.com>
  2804. * @description: Inline richtext editor
  2805. */
  2806. jSuites.editor = (function(el, options) {
  2807. var obj = {};
  2808. obj.options = {};
  2809. // Default configuration
  2810. var defaults = {
  2811. // Initial HTML content
  2812. value: null,
  2813. // Initial snippet
  2814. snippet: null,
  2815. // Add toolbar
  2816. toolbar: null,
  2817. // Max height
  2818. maxHeight: null,
  2819. // Website parser is to read websites and images from cross domain
  2820. remoteParser: null,
  2821. // Key from youtube to read properties from URL
  2822. youtubeKey: null,
  2823. // User list
  2824. userSearch: null,
  2825. // Parse URL
  2826. parseURL: false,
  2827. // Accept drop files
  2828. dropZone: true,
  2829. dropAsAttachment: false,
  2830. acceptImages: true,
  2831. acceptFiles: false,
  2832. maxFileSize: 5000000,
  2833. // Border
  2834. border: true,
  2835. padding: true,
  2836. focus: false,
  2837. // Events
  2838. onclick: null,
  2839. onfocus: null,
  2840. onblur: null,
  2841. onload: null,
  2842. onenter: null,
  2843. onkeyup: null,
  2844. onkeydown: null,
  2845. };
  2846. // Loop through our object
  2847. for (var property in defaults) {
  2848. if (options && options.hasOwnProperty(property)) {
  2849. obj.options[property] = options[property];
  2850. } else {
  2851. obj.options[property] = defaults[property];
  2852. }
  2853. }
  2854. // Private controllers
  2855. var imageResize = 0;
  2856. var editorTimer = null;
  2857. var editorAction = null;
  2858. // Make sure element is empty
  2859. el.innerHTML = '';
  2860. // Prepare container
  2861. el.classList.add('jeditor-container');
  2862. // Padding
  2863. if (obj.options.padding == true) {
  2864. el.classList.add('jeditor-padding');
  2865. }
  2866. // Border
  2867. if (obj.options.border == false) {
  2868. el.style.border = '0px';
  2869. }
  2870. // Snippet
  2871. var snippet = document.createElement('div');
  2872. snippet.className = 'snippet';
  2873. snippet.setAttribute('contenteditable', false);
  2874. // Toolbar
  2875. var toolbar = document.createElement('div');
  2876. toolbar.className = 'jeditor-toolbar';
  2877. // Create editor
  2878. var editor = document.createElement('div');
  2879. editor.setAttribute('contenteditable', true);
  2880. editor.setAttribute('spellcheck', false);
  2881. editor.className = 'jeditor';
  2882. // Max height
  2883. if (obj.options.maxHeight) {
  2884. editor.style.overflowY = 'auto';
  2885. editor.style.maxHeight = obj.options.maxHeight;
  2886. }
  2887. // Set editor initial value
  2888. if (obj.options.value) {
  2889. var value = obj.options.value;
  2890. } else {
  2891. var value = el.innerHTML ? el.innerHTML : '';
  2892. }
  2893. if (! value) {
  2894. var value = '<br>';
  2895. }
  2896. /**
  2897. * Extract images from a HTML string
  2898. */
  2899. var extractImageFromHtml = function(html) {
  2900. // Create temp element
  2901. var div = document.createElement('div');
  2902. div.innerHTML = html;
  2903. // Extract images
  2904. var img = div.querySelectorAll('img');
  2905. if (img.length) {
  2906. for (var i = 0; i < img.length; i++) {
  2907. obj.addImage(img[i].src);
  2908. }
  2909. }
  2910. }
  2911. /**
  2912. * Insert node at caret
  2913. */
  2914. var insertNodeAtCaret = function(newNode) {
  2915. var sel, range;
  2916. if (window.getSelection) {
  2917. sel = window.getSelection();
  2918. if (sel.rangeCount) {
  2919. range = sel.getRangeAt(0);
  2920. var selectedText = range.toString();
  2921. range.deleteContents();
  2922. range.insertNode(newNode);
  2923. // move the cursor after element
  2924. range.setStartAfter(newNode);
  2925. range.setEndAfter(newNode);
  2926. sel.removeAllRanges();
  2927. sel.addRange(range);
  2928. }
  2929. }
  2930. }
  2931. /**
  2932. * Append snippet or thumbs in the editor
  2933. * @Param object data
  2934. */
  2935. var appendElement = function(data) {
  2936. // Reset snippet
  2937. snippet.innerHTML = '';
  2938. if (data.image) {
  2939. var div = document.createElement('div');
  2940. div.className = 'snippet-image';
  2941. div.setAttribute('data-k', 'image');
  2942. snippet.appendChild(div);
  2943. var image = document.createElement('img');
  2944. image.src = data.image;
  2945. div.appendChild(image);
  2946. }
  2947. var div = document.createElement('div');
  2948. div.className = 'snippet-title';
  2949. div.setAttribute('data-k', 'title');
  2950. div.innerHTML = data.title;
  2951. snippet.appendChild(div);
  2952. var div = document.createElement('div');
  2953. div.className = 'snippet-description';
  2954. div.setAttribute('data-k', 'description');
  2955. div.innerHTML = data.description;
  2956. snippet.appendChild(div);
  2957. var div = document.createElement('div');
  2958. div.className = 'snippet-host';
  2959. div.setAttribute('data-k', 'host');
  2960. div.innerHTML = data.host;
  2961. snippet.appendChild(div);
  2962. var div = document.createElement('div');
  2963. div.className = 'snippet-url';
  2964. div.setAttribute('data-k', 'url');
  2965. div.innerHTML = data.url;
  2966. snippet.appendChild(div);
  2967. editor.appendChild(snippet);
  2968. }
  2969. var verifyEditor = function() {
  2970. clearTimeout(editorTimer);
  2971. editorTimer = setTimeout(function() {
  2972. var snippet = editor.querySelector('.snippet');
  2973. var thumbsContainer = el.querySelector('.jeditor-thumbs-container');
  2974. if (! snippet && ! thumbsContainer) {
  2975. var html = editor.innerHTML.replace(/\n/g, ' ');
  2976. var container = document.createElement('div');
  2977. container.innerHTML = html;
  2978. var thumbsContainer = container.querySelector('.jeditor-thumbs-container');
  2979. if (thumbsContainer) {
  2980. thumbsContainer.remove();
  2981. }
  2982. var text = container.innerText;
  2983. var url = jSuites.editor.detectUrl(text);
  2984. if (url) {
  2985. if (url[0].substr(-3) == 'jpg' || url[0].substr(-3) == 'png' || url[0].substr(-3) == 'gif') {
  2986. if (jSuites.editor.getDomain(url[0]) == window.location.hostname) {
  2987. obj.importImage(url[0], '');
  2988. } else {
  2989. obj.importImage(obj.options.remoteParser + url[0], '');
  2990. }
  2991. } else {
  2992. var id = jSuites.editor.youtubeParser(url[0]);
  2993. if (id) {
  2994. obj.getYoutube(id);
  2995. } else {
  2996. obj.getWebsite(url[0]);
  2997. }
  2998. }
  2999. }
  3000. }
  3001. }, 1000);
  3002. }
  3003. obj.parseContent = function() {
  3004. verifyEditor();
  3005. }
  3006. /**
  3007. * Get metadata from a youtube video
  3008. */
  3009. obj.getYoutube = function(id) {
  3010. if (! obj.options.youtubeKey) {
  3011. console.error('The youtubeKey is not defined');
  3012. } else {
  3013. jSuites.ajax({
  3014. url: 'https://www.googleapis.com/youtube/v3/videos?part=snippet,statistics&key=' + obj.options.youtubeKey + '&id=' + id,
  3015. method: 'GET',
  3016. dataType: 'json',
  3017. success: function(result) {
  3018. // Only valid elements to be appended
  3019. if (result.items && result.items[0]) {
  3020. var p = {
  3021. title: '',
  3022. description: '',
  3023. image: '',
  3024. host: 'www.youtube.com',
  3025. url: 'https://www.youtube.com?watch=' + id,
  3026. }
  3027. if (result.items[0].snippet.title) {
  3028. p.title = result.items[0].snippet.title;
  3029. }
  3030. if (result.items[0].snippet.description) {
  3031. p.description = result.items[0].snippet.description;
  3032. if (p.description.length > 150) {
  3033. p.description = p.description.substr(0, 150) + '...';
  3034. }
  3035. }
  3036. if (result.items[0].snippet.thumbnails.medium.url) {
  3037. p.image = result.items[0].snippet.thumbnails.medium.url;
  3038. }
  3039. appendElement(p);
  3040. }
  3041. }
  3042. });
  3043. }
  3044. }
  3045. /**
  3046. * Get meta information from a website
  3047. */
  3048. obj.getWebsite = function(url) {
  3049. if (! obj.options.remoteParser) {
  3050. console.log('The remoteParser is not defined');
  3051. } else {
  3052. jSuites.ajax({
  3053. url: obj.options.remoteParser + encodeURI(url.trim()),
  3054. method: 'GET',
  3055. dataType: 'json',
  3056. success: function(result) {
  3057. var p = {
  3058. title: '',
  3059. description: '',
  3060. image: '',
  3061. host: url,
  3062. url: url,
  3063. }
  3064. if (result.title) {
  3065. p.title = result.title;
  3066. }
  3067. if (result.description) {
  3068. p.description = result.description;
  3069. }
  3070. if (result.image) {
  3071. p.image = result.image;
  3072. } else if (result['og:image']) {
  3073. p.image = result['og:image'];
  3074. }
  3075. if (result.host) {
  3076. p.host = result.host;
  3077. }
  3078. if (result.url) {
  3079. p.url = result.url;
  3080. }
  3081. appendElement(p);
  3082. }
  3083. });
  3084. }
  3085. }
  3086. /**
  3087. * Set editor value
  3088. */
  3089. obj.setData = function(html) {
  3090. editor.innerHTML = html;
  3091. cursor();
  3092. }
  3093. /**
  3094. * Get editor data
  3095. */
  3096. obj.getData = function(json) {
  3097. if (! json) {
  3098. var data = editor.innerHTML;
  3099. } else {
  3100. var data = {
  3101. content : '',
  3102. }
  3103. // Get tag users
  3104. var tagged = editor.querySelectorAll('.post-tag');
  3105. if (tagged.length) {
  3106. data.users = [];
  3107. for (var i = 0; i < tagged.length; i++) {
  3108. var userId = tagged[i].getAttribute('data-user');
  3109. if (userId) {
  3110. data.users.push(userId);
  3111. }
  3112. }
  3113. data.users = data.users.join(',');
  3114. }
  3115. if (snippet.innerHTML) {
  3116. var index = 0;
  3117. data.snippet = {};
  3118. for (var i = 0; i < snippet.children.length; i++) {
  3119. // Get key from element
  3120. var key = snippet.children[i].getAttribute('data-k');
  3121. if (key) {
  3122. if (key == 'image') {
  3123. data.snippet.image = snippet.children[i].children[0].getAttribute('src');
  3124. } else {
  3125. data.snippet[key] = snippet.children[i].innerHTML;
  3126. }
  3127. }
  3128. }
  3129. snippet.innerHTML = '';
  3130. snippet.remove();
  3131. }
  3132. var text = editor.innerHTML;
  3133. text = text.replace(/<br>/g, "\n");
  3134. text = text.replace(/<\/div>/g, "<\/div>\n");
  3135. text = text.replace(/<(?:.|\n)*?>/gm, "");
  3136. data.content = text.trim();
  3137. data = JSON.stringify(data);
  3138. }
  3139. return data;
  3140. }
  3141. // Reset
  3142. obj.reset = function() {
  3143. editor.innerHTML = '';
  3144. }
  3145. obj.addPdf = function(data) {
  3146. if (data.result.substr(0,4) != 'data') {
  3147. console.error('Invalid source');
  3148. } else {
  3149. var canvas = document.createElement('canvas');
  3150. canvas.width = 60;
  3151. canvas.height = 60;
  3152. var img = new Image();
  3153. var ctx = canvas.getContext('2d');
  3154. ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  3155. canvas.toBlob(function(blob) {
  3156. var newImage = document.createElement('img');
  3157. newImage.src = window.URL.createObjectURL(blob);
  3158. newImage.setAttribute('data-extension', 'pdf');
  3159. if (data.name) {
  3160. newImage.setAttribute('data-name', data.name);
  3161. }
  3162. if (data.size) {
  3163. newImage.setAttribute('data-size', data.size);
  3164. }
  3165. if (data.date) {
  3166. newImage.setAttribute('data-date', data.date);
  3167. }
  3168. newImage.className = 'jfile pdf';
  3169. insertNodeAtCaret(newImage);
  3170. jSuites.files[newImage.src] = data.result.substr(data.result.indexOf(',') + 1);
  3171. });
  3172. }
  3173. }
  3174. obj.addImage = function(src, name, size, date) {
  3175. if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) {
  3176. console.error('remoteParser not defined in your initialization');
  3177. } else {
  3178. // This is to process cross domain images
  3179. if (src.substr(0,4) == 'data') {
  3180. var extension = src.split(';')
  3181. extension = extension[0].split('/');
  3182. extension = extension[1];
  3183. } else {
  3184. var extension = src.substr(src.lastIndexOf('.') + 1);
  3185. // Work for cross browsers
  3186. src = obj.options.remoteParser + src;
  3187. }
  3188. var img = new Image();
  3189. img.onload = function onload() {
  3190. var canvas = document.createElement('canvas');
  3191. canvas.width = img.width;
  3192. canvas.height = img.height;
  3193. var ctx = canvas.getContext('2d');
  3194. ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  3195. canvas.toBlob(function(blob) {
  3196. var newImage = document.createElement('img');
  3197. newImage.src = window.URL.createObjectURL(blob);
  3198. newImage.setAttribute('tabindex', '900');
  3199. newImage.setAttribute('data-extension', extension);
  3200. if (name) {
  3201. newImage.setAttribute('data-name', name);
  3202. }
  3203. if (size) {
  3204. newImage.setAttribute('data-size', size);
  3205. }
  3206. if (date) {
  3207. newImage.setAttribute('data-date', date);
  3208. }
  3209. newImage.className = 'jfile';
  3210. var content = canvas.toDataURL();
  3211. insertNodeAtCaret(newImage);
  3212. jSuites.files[newImage.src] = content.substr(content.indexOf(',') + 1);
  3213. });
  3214. };
  3215. img.src = src;
  3216. }
  3217. }
  3218. obj.addFile = function(files) {
  3219. var reader = [];
  3220. for (var i = 0; i < files.length; i++) {
  3221. if (files[i].size > obj.options.maxFileSize) {
  3222. alert('The file is too big');
  3223. } else {
  3224. // Only PDF or Images
  3225. var type = files[i].type.split('/');
  3226. if (type[0] == 'image') {
  3227. type = 1;
  3228. } else if (type[1] == 'pdf') {
  3229. type = 2;
  3230. } else {
  3231. type = 0;
  3232. }
  3233. if (type) {
  3234. // Create file
  3235. reader[i] = new FileReader();
  3236. reader[i].index = i;
  3237. reader[i].type = type;
  3238. reader[i].name = files[i].name;
  3239. reader[i].date = files[i].lastModified;
  3240. reader[i].size = files[i].size;
  3241. reader[i].addEventListener("load", function (data) {
  3242. // Get result
  3243. if (data.target.type == 2) {
  3244. if (obj.options.acceptFiles == true) {
  3245. obj.addPdf(data.target);
  3246. }
  3247. } else {
  3248. obj.addImage(data.target.result, data.target.name, data.total, data.target.lastModified);
  3249. }
  3250. }, false);
  3251. reader[i].readAsDataURL(files[i])
  3252. } else {
  3253. alert('The extension is not allowed');
  3254. }
  3255. }
  3256. }
  3257. }
  3258. // Destroy
  3259. obj.destroy = function() {
  3260. editor.removeEventListener('mouseup', editorMouseUp);
  3261. editor.removeEventListener('mousedown', editorMouseDown);
  3262. editor.removeEventListener('mousemove', editorMouseMove);
  3263. editor.removeEventListener('keyup', editorKeyUp);
  3264. editor.removeEventListener('keydown', editorKeyDown);
  3265. editor.removeEventListener('dragstart', editorDragStart);
  3266. editor.removeEventListener('dragenter', editorDragEnter);
  3267. editor.removeEventListener('dragover', editorDragOver);
  3268. editor.removeEventListener('drop', editorDrop);
  3269. editor.removeEventListener('paste', editorPaste);
  3270. if (typeof(obj.options.onblur) == 'function') {
  3271. editor.removeEventListener('blur', editorBlur);
  3272. }
  3273. if (typeof(obj.options.onfocus) == 'function') {
  3274. editor.removeEventListener('focus', editorFocus);
  3275. }
  3276. el.editor = null;
  3277. el.classList.remove('jeditor-container');
  3278. toolbar.remove();
  3279. snippet.remove();
  3280. editor.remove();
  3281. }
  3282. var isLetter = function (str) {
  3283. var regex = /([\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]+)/g;
  3284. return str.match(regex) ? 1 : 0;
  3285. }
  3286. // Event handlers
  3287. var editorMouseUp = function(e) {
  3288. editorAction = false;
  3289. }
  3290. var editorMouseDown = function(e) {
  3291. var close = function(snippet) {
  3292. var rect = snippet.getBoundingClientRect();
  3293. if (rect.width - (e.clientX - rect.left) < 40 && e.clientY - rect.top < 40) {
  3294. snippet.innerHTML = '';
  3295. snippet.remove();
  3296. }
  3297. }
  3298. if (e.target.tagName == 'IMG') {
  3299. if (e.target.style.cursor) {
  3300. var rect = e.target.getBoundingClientRect();
  3301. editorAction = {
  3302. e: e.target,
  3303. x: e.clientX,
  3304. y: e.clientY,
  3305. w: rect.width,
  3306. h: rect.height,
  3307. d: e.target.style.cursor,
  3308. }
  3309. if (! e.target.style.width) {
  3310. e.target.style.width = rect.width + 'px';
  3311. }
  3312. if (! e.target.style.height) {
  3313. e.target.style.height = rect.height + 'px';
  3314. }
  3315. var s = window.getSelection();
  3316. if (s.rangeCount) {
  3317. for (var i = 0; i < s.rangeCount; i++) {
  3318. s.removeRange(s.getRangeAt(i));
  3319. }
  3320. }
  3321. } else {
  3322. editorAction = true;
  3323. }
  3324. } else {
  3325. if (e.target.classList.contains('snippet')) {
  3326. close(e.target);
  3327. } else if (e.target.parentNode.classList.contains('snippet')) {
  3328. close(e.target.parentNode);
  3329. }
  3330. editorAction = true;
  3331. }
  3332. }
  3333. var editorMouseMove = function(e) {
  3334. if (e.target.tagName == 'IMG') {
  3335. if (e.target.getAttribute('tabindex')) {
  3336. var rect = e.target.getBoundingClientRect();
  3337. if (e.clientY - rect.top < 5) {
  3338. if (rect.width - (e.clientX - rect.left) < 5) {
  3339. e.target.style.cursor = 'ne-resize';
  3340. } else if (e.clientX - rect.left < 5) {
  3341. e.target.style.cursor = 'nw-resize';
  3342. } else {
  3343. e.target.style.cursor = 'n-resize';
  3344. }
  3345. } else if (rect.height - (e.clientY - rect.top) < 5) {
  3346. if (rect.width - (e.clientX - rect.left) < 5) {
  3347. e.target.style.cursor = 'se-resize';
  3348. } else if (e.clientX - rect.left < 5) {
  3349. e.target.style.cursor = 'sw-resize';
  3350. } else {
  3351. e.target.style.cursor = 's-resize';
  3352. }
  3353. } else if (rect.width - (e.clientX - rect.left) < 5) {
  3354. e.target.style.cursor = 'e-resize';
  3355. } else if (e.clientX - rect.left < 5) {
  3356. e.target.style.cursor = 'w-resize';
  3357. } else {
  3358. e.target.style.cursor = '';
  3359. }
  3360. }
  3361. }
  3362. // Move
  3363. if (e.which == 1 && editorAction && editorAction.d) {
  3364. if (editorAction.d == 'e-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'se-resize') {
  3365. editorAction.e.style.width = (editorAction.w + (e.clientX - editorAction.x)) + 'px';
  3366. if (e.shiftKey) {
  3367. var newHeight = (e.clientX - editorAction.x) * (editorAction.h / editorAction.w);
  3368. editorAction.e.style.height = editorAction.h + newHeight + 'px';
  3369. } else {
  3370. var newHeight = null;
  3371. }
  3372. }
  3373. if (! newHeight) {
  3374. if (editorAction.d == 's-resize' || editorAction.d == 'se-resize' || editorAction.d == 'sw-resize') {
  3375. if (! e.shiftKey) {
  3376. editorAction.e.style.height = editorAction.h + (e.clientY - editorAction.y);
  3377. }
  3378. }
  3379. }
  3380. }
  3381. }
  3382. var editorKeyUp = function(e) {
  3383. if (! editor.innerHTML) {
  3384. editor.innerHTML = '<div><br></div>';
  3385. }
  3386. if (typeof(obj.options.onkeyup) == 'function') {
  3387. obj.options.onkeyup(e, el);
  3388. }
  3389. }
  3390. var editorKeyDown = function(e) {
  3391. // Check for URL
  3392. if (obj.options.parseURL == true) {
  3393. verifyEditor();
  3394. }
  3395. // Closable
  3396. if (typeof(obj.options.onenter) == 'function' && e.which == 13) {
  3397. var data = obj.getData();
  3398. obj.options.onenter(obj, el, data, e);
  3399. }
  3400. if (typeof(obj.options.onkeydown) == 'function') {
  3401. obj.options.onkeydown(e, el);
  3402. }
  3403. }
  3404. var editorPaste = function(e) {
  3405. if (e.clipboardData || e.originalEvent.clipboardData) {
  3406. var html = (e.originalEvent || e).clipboardData.getData('text/html');
  3407. var text = (e.originalEvent || e).clipboardData.getData('text/plain');
  3408. var file = (e.originalEvent || e).clipboardData.files
  3409. } else if (window.clipboardData) {
  3410. var html = window.clipboardData.getData('Html');
  3411. var text = window.clipboardData.getData('Text');
  3412. var file = window.clipboardData.files
  3413. }
  3414. if (file.length) {
  3415. // Paste a image from the clipboard
  3416. obj.addFile(file);
  3417. } else {
  3418. // Paste text
  3419. text = text.split('\r\n');
  3420. var str = '';
  3421. if (e.target.nodeName == 'DIV' && ! e.target.classList.contains('jeditor')) {
  3422. for (var i = 0; i < text.length; i++) {
  3423. if (text[i]) {
  3424. str += text[i] + "<br>\r\n";
  3425. }
  3426. }
  3427. } else {
  3428. for (var i = 0; i < text.length; i++) {
  3429. if (text[i]) {
  3430. str += '<div>' + text[i] + '</div>';
  3431. } else {
  3432. str += '<div><br></div>';
  3433. }
  3434. }
  3435. }
  3436. // Insert text
  3437. document.execCommand('insertHtml', false, str);
  3438. // Extra images from the paste
  3439. if (obj.options.acceptImages == true) {
  3440. extractImageFromHtml(html);
  3441. }
  3442. }
  3443. e.preventDefault();
  3444. }
  3445. var editorDragStart = function(e) {
  3446. if (editorAction && editorAction.e) {
  3447. e.preventDefault();
  3448. }
  3449. }
  3450. var editorDragEnter = function(e) {
  3451. if (editorAction || obj.options.dropZone == false) {
  3452. // Do nothing
  3453. } else {
  3454. el.classList.add('jeditor-dragging');
  3455. }
  3456. }
  3457. var editorDragOver = function(e) {
  3458. if (editorAction || obj.options.dropZone == false) {
  3459. // Do nothing
  3460. } else {
  3461. if (editorTimer) {
  3462. clearTimeout(editorTimer);
  3463. }
  3464. editorTimer = setTimeout(function() {
  3465. el.classList.remove('jeditor-dragging');
  3466. }, 100);
  3467. }
  3468. }
  3469. var editorDrop = function(e) {
  3470. if (editorAction || obj.options.dropZone == false) {
  3471. // Do nothing
  3472. } else {
  3473. // Position caret on the drop
  3474. var range = null;
  3475. if (document.caretRangeFromPoint) {
  3476. range=document.caretRangeFromPoint(e.clientX, e.clientY);
  3477. } else if (e.rangeParent) {
  3478. range=document.createRange();
  3479. range.setStart(e.rangeParent,e.rangeOffset);
  3480. }
  3481. var sel = window.getSelection();
  3482. sel.removeAllRanges();
  3483. sel.addRange(range);
  3484. sel.anchorNode.parentNode.focus();
  3485. var html = (e.originalEvent || e).dataTransfer.getData('text/html');
  3486. var text = (e.originalEvent || e).dataTransfer.getData('text/plain');
  3487. var file = (e.originalEvent || e).dataTransfer.files;
  3488. if (file.length) {
  3489. obj.addFile(file);
  3490. } else if (text) {
  3491. extractImageFromHtml(html);
  3492. }
  3493. el.classList.remove('jeditor-dragging');
  3494. e.preventDefault();
  3495. }
  3496. }
  3497. var editorBlur = function() {
  3498. obj.options.onblur(obj, el, obj.getData());
  3499. }
  3500. var editorFocus = function() {
  3501. obj.options.onfocus(obj, el, obj.getData());
  3502. }
  3503. editor.addEventListener('mouseup', editorMouseUp);
  3504. editor.addEventListener('mousedown', editorMouseDown);
  3505. editor.addEventListener('mousemove', editorMouseMove);
  3506. editor.addEventListener('keyup', editorKeyUp);
  3507. editor.addEventListener('keydown', editorKeyDown);
  3508. editor.addEventListener('dragstart', editorDragStart);
  3509. editor.addEventListener('dragenter', editorDragEnter);
  3510. editor.addEventListener('dragover', editorDragOver);
  3511. editor.addEventListener('drop', editorDrop);
  3512. editor.addEventListener('paste', editorPaste);
  3513. // Blur
  3514. if (typeof(obj.options.onblur) == 'function') {
  3515. editor.addEventListener('blur', editorBlur);
  3516. }
  3517. // Focus
  3518. if (typeof(obj.options.onfocus) == 'function') {
  3519. editor.addEventListener('focus', editorFocus);
  3520. }
  3521. // Onload
  3522. if (typeof(obj.options.onload) == 'function') {
  3523. obj.options.onload(el, editor);
  3524. }
  3525. // Set value to the editor
  3526. editor.innerHTML = value;
  3527. // Append editor to the containre
  3528. el.appendChild(editor);
  3529. // Snippet
  3530. if (obj.options.snippet) {
  3531. appendElement(obj.options.snippet);
  3532. }
  3533. // Default toolbar
  3534. if (obj.options.toolbar == null) {
  3535. obj.options.toolbar = jSuites.editor.getDefaultToolbar();
  3536. }
  3537. // Add toolbar
  3538. if (obj.options.toolbar) {
  3539. for (var i = 0; i < obj.options.toolbar.length; i++) {
  3540. if (obj.options.toolbar[i].icon) {
  3541. var item = document.createElement('div');
  3542. item.style.userSelect = 'none';
  3543. var itemIcon = document.createElement('i');
  3544. itemIcon.className = 'material-icons';
  3545. itemIcon.innerHTML = obj.options.toolbar[i].icon;
  3546. itemIcon.onclick = (function (a) {
  3547. var b = a;
  3548. return function () {
  3549. obj.options.toolbar[b].onclick(el, obj, this)
  3550. };
  3551. })(i);
  3552. item.appendChild(itemIcon);
  3553. toolbar.appendChild(item);
  3554. } else {
  3555. if (obj.options.toolbar[i].type == 'divisor') {
  3556. var item = document.createElement('div');
  3557. item.className = 'jeditor-toolbar-divisor';
  3558. toolbar.appendChild(item);
  3559. } else if (obj.options.toolbar[i].type == 'button') {
  3560. var item = document.createElement('div');
  3561. item.classList.add('jeditor-toolbar-button');
  3562. item.innerHTML = obj.options.toolbar[i].value;
  3563. toolbar.appendChild(item);
  3564. }
  3565. }
  3566. }
  3567. el.appendChild(toolbar);
  3568. }
  3569. // Focus to the editor
  3570. if (obj.options.focus) {
  3571. jSuites.editor.setCursor(editor, obj.options.focus == 'initial' ? true : false);
  3572. }
  3573. el.editor = obj;
  3574. return obj;
  3575. });
  3576. jSuites.editor.setCursor = function(element, first) {
  3577. element.focus();
  3578. document.execCommand('selectAll');
  3579. var sel = window.getSelection();
  3580. var range = sel.getRangeAt(0);
  3581. if (first == true) {
  3582. var node = range.startContainer;
  3583. var size = 0;
  3584. } else {
  3585. var node = range.endContainer;
  3586. var size = node.length;
  3587. }
  3588. range.setStart(node, size);
  3589. range.setEnd(node, size);
  3590. sel.removeAllRanges();
  3591. sel.addRange(range);
  3592. }
  3593. jSuites.editor.getDomain = function(url) {
  3594. return url.replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0].split(/:/g)[0];
  3595. }
  3596. jSuites.editor.detectUrl = function(text) {
  3597. var expression = /(((https?:\/\/)|(www\.))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]+)/ig;
  3598. var links = text.match(expression);
  3599. if (links) {
  3600. if (links[0].substr(0,3) == 'www') {
  3601. links[0] = 'http://' + links[0];
  3602. }
  3603. }
  3604. return links;
  3605. }
  3606. jSuites.editor.youtubeParser = function(url) {
  3607. var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;
  3608. var match = url.match(regExp);
  3609. return (match && match[7].length == 11) ? match[7] : false;
  3610. }
  3611. jSuites.editor.getDefaultToolbar = function() {
  3612. return [
  3613. {
  3614. icon:'undo',
  3615. onclick: function() {
  3616. document.execCommand('undo');
  3617. }
  3618. },
  3619. {
  3620. icon:'redo',
  3621. onclick: function() {
  3622. document.execCommand('redo');
  3623. }
  3624. },
  3625. {
  3626. type:'divisor'
  3627. },
  3628. {
  3629. icon:'format_bold',
  3630. onclick: function(a,b,c) {
  3631. document.execCommand('bold');
  3632. if (document.queryCommandState("bold")) {
  3633. c.classList.add('selected');
  3634. } else {
  3635. c.classList.remove('selected');
  3636. }
  3637. }
  3638. },
  3639. {
  3640. icon:'format_italic',
  3641. onclick: function(a,b,c) {
  3642. document.execCommand('italic');
  3643. if (document.queryCommandState("italic")) {
  3644. c.classList.add('selected');
  3645. } else {
  3646. c.classList.remove('selected');
  3647. }
  3648. }
  3649. },
  3650. {
  3651. icon:'format_underline',
  3652. onclick: function(a,b,c) {
  3653. document.execCommand('underline');
  3654. if (document.queryCommandState("underline")) {
  3655. c.classList.add('selected');
  3656. } else {
  3657. c.classList.remove('selected');
  3658. }
  3659. }
  3660. },
  3661. {
  3662. type:'divisor'
  3663. },
  3664. {
  3665. icon:'format_list_bulleted',
  3666. onclick: function(a,b,c) {
  3667. document.execCommand('insertUnorderedList');
  3668. if (document.queryCommandState("insertUnorderedList")) {
  3669. c.classList.add('selected');
  3670. } else {
  3671. c.classList.remove('selected');
  3672. }
  3673. }
  3674. },
  3675. {
  3676. icon:'format_list_numbered',
  3677. onclick: function(a,b,c) {
  3678. document.execCommand('insertOrderedList');
  3679. if (document.queryCommandState("insertOrderedList")) {
  3680. c.classList.add('selected');
  3681. } else {
  3682. c.classList.remove('selected');
  3683. }
  3684. }
  3685. },
  3686. {
  3687. icon:'format_indent_increase',
  3688. onclick: function(a,b,c) {
  3689. document.execCommand('indent', true, null);
  3690. if (document.queryCommandState("indent")) {
  3691. c.classList.add('selected');
  3692. } else {
  3693. c.classList.remove('selected');
  3694. }
  3695. }
  3696. },
  3697. {
  3698. icon:'format_indent_decrease',
  3699. onclick: function(a,b,c) {
  3700. document.execCommand('outdent');
  3701. if (document.queryCommandState("outdent")) {
  3702. c.classList.add('selected');
  3703. } else {
  3704. c.classList.remove('selected');
  3705. }
  3706. }
  3707. }
  3708. /*{
  3709. type:'select',
  3710. items: ['Verdana','Arial','Courier New'],
  3711. onchange: function() {
  3712. }
  3713. },
  3714. {
  3715. type:'select',
  3716. items: ['10px','12px','14px','16px','18px','20px','22px'],
  3717. onchange: function() {
  3718. }
  3719. },
  3720. {
  3721. icon:'format_align_left',
  3722. onclick: function() {
  3723. document.execCommand('JustifyLeft');
  3724. if (document.queryCommandState("JustifyLeft")) {
  3725. this.classList.add('selected');
  3726. } else {
  3727. this.classList.remove('selected');
  3728. }
  3729. }
  3730. },
  3731. {
  3732. icon:'format_align_center',
  3733. onclick: function() {
  3734. document.execCommand('justifyCenter');
  3735. if (document.queryCommandState("justifyCenter")) {
  3736. this.classList.add('selected');
  3737. } else {
  3738. this.classList.remove('selected');
  3739. }
  3740. }
  3741. },
  3742. {
  3743. icon:'format_align_right',
  3744. onclick: function() {
  3745. document.execCommand('justifyRight');
  3746. if (document.queryCommandState("justifyRight")) {
  3747. this.classList.add('selected');
  3748. } else {
  3749. this.classList.remove('selected');
  3750. }
  3751. }
  3752. },
  3753. {
  3754. icon:'format_align_justify',
  3755. onclick: function() {
  3756. document.execCommand('justifyFull');
  3757. if (document.queryCommandState("justifyFull")) {
  3758. this.classList.add('selected');
  3759. } else {
  3760. this.classList.remove('selected');
  3761. }
  3762. }
  3763. },
  3764. {
  3765. icon:'format_list_bulleted',
  3766. onclick: function() {
  3767. document.execCommand('insertUnorderedList');
  3768. if (document.queryCommandState("insertUnorderedList")) {
  3769. this.classList.add('selected');
  3770. } else {
  3771. this.classList.remove('selected');
  3772. }
  3773. }
  3774. }*/
  3775. ];
  3776. }
  3777. jSuites.image = (function(el, options) {
  3778. var obj = {};
  3779. obj.options = {};
  3780. // Default configuration
  3781. var defaults = {
  3782. minWidth: false,
  3783. onchange: null,
  3784. singleFile: true,
  3785. remoteParser: null,
  3786. text:{
  3787. extensionNotAllowed:'The extension is not allowed',
  3788. imageTooSmall:'The resolution is too low, try a image with a better resolution. width > 800px',
  3789. }
  3790. };
  3791. // Loop through our object
  3792. for (var property in defaults) {
  3793. if (options && options.hasOwnProperty(property)) {
  3794. obj.options[property] = options[property];
  3795. } else {
  3796. obj.options[property] = defaults[property];
  3797. }
  3798. }
  3799. // Upload icon
  3800. el.classList.add('jupload');
  3801. // Add image
  3802. obj.addImage = function(file) {
  3803. if (! file.date) {
  3804. file.date = '';
  3805. }
  3806. var img = document.createElement('img');
  3807. img.setAttribute('data-date', file.lastmodified ? file.lastmodified : file.date);
  3808. img.setAttribute('data-name', file.name);
  3809. img.setAttribute('data-size', file.size);
  3810. img.setAttribute('data-small', file.small ? file.small : '');
  3811. img.setAttribute('data-cover', file.cover ? 1 : 0);
  3812. img.setAttribute('data-extension', file.extension);
  3813. img.setAttribute('src', file.file);
  3814. img.className = 'jfile';
  3815. img.style.width = '100%';
  3816. return img;
  3817. }
  3818. // Add image
  3819. obj.addImages = function(files) {
  3820. if (obj.options.singleFile == true) {
  3821. el.innerHTML = '';
  3822. }
  3823. for (var i = 0; i < files.length; i++) {
  3824. el.appendChild(obj.addImage(files[i]));
  3825. }
  3826. }
  3827. obj.addFromFile = function(file) {
  3828. var type = file.type.split('/');
  3829. if (type[0] == 'image') {
  3830. if (obj.options.singleFile == true) {
  3831. el.innerHTML = '';
  3832. }
  3833. var imageFile = new FileReader();
  3834. imageFile.addEventListener("load", function (v) {
  3835. var img = new Image();
  3836. img.onload = function onload() {
  3837. var canvas = document.createElement('canvas');
  3838. canvas.width = img.width;
  3839. canvas.height = img.height;
  3840. var ctx = canvas.getContext('2d');
  3841. ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  3842. var data = {
  3843. file: canvas.toDataURL(),
  3844. extension: file.name.substr(file.name.lastIndexOf('.') + 1),
  3845. name: file.name,
  3846. size: file.size,
  3847. lastmodified: file.lastModified,
  3848. }
  3849. var newImage = obj.addImage(data);
  3850. el.appendChild(newImage);
  3851. // Onchange
  3852. if (typeof(obj.options.onchange) == 'function') {
  3853. obj.options.onchange(newImage);
  3854. }
  3855. };
  3856. img.src = v.srcElement.result;
  3857. });
  3858. imageFile.readAsDataURL(file);
  3859. } else {
  3860. alert(text.extentionNotAllowed);
  3861. }
  3862. }
  3863. obj.addFromUrl = function(src) {
  3864. if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) {
  3865. console.error('remoteParser not defined in your initialization');
  3866. } else {
  3867. // This is to process cross domain images
  3868. if (src.substr(0,4) == 'data') {
  3869. var extension = src.split(';')
  3870. extension = extension[0].split('/');
  3871. extension = extension[1];
  3872. } else {
  3873. var extension = src.substr(src.lastIndexOf('.') + 1);
  3874. // Work for cross browsers
  3875. src = obj.options.remoteParser + src;
  3876. }
  3877. var img = new Image();
  3878. img.onload = function onload() {
  3879. var canvas = document.createElement('canvas');
  3880. canvas.width = img.width;
  3881. canvas.height = img.height;
  3882. var ctx = canvas.getContext('2d');
  3883. ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  3884. canvas.toBlob(function(blob) {
  3885. var data = {
  3886. file: window.URL.createObjectURL(blob),
  3887. extension: extension
  3888. }
  3889. var newImage = obj.addImage(data);
  3890. el.appendChild(newImage);
  3891. // Keep base64 ready to go
  3892. var content = canvas.toDataURL();
  3893. jSuites.files[data.file] = content.substr(content.indexOf(',') + 1);
  3894. // Onchange
  3895. if (typeof(obj.options.onchange) == 'function') {
  3896. obj.options.onchange(newImage);
  3897. }
  3898. });
  3899. };
  3900. img.src = src;
  3901. }
  3902. }
  3903. var attachmentInput = document.createElement('input');
  3904. attachmentInput.type = 'file';
  3905. attachmentInput.setAttribute('accept', 'image/*');
  3906. attachmentInput.onchange = function() {
  3907. for (var i = 0; i < this.files.length; i++) {
  3908. obj.addFromFile(this.files[i]);
  3909. }
  3910. }
  3911. el.addEventListener("dblclick", function(e) {
  3912. jSuites.click(attachmentInput);
  3913. });
  3914. el.addEventListener('dragenter', function(e) {
  3915. el.style.border = '1px dashed #000';
  3916. });
  3917. el.addEventListener('dragleave', function(e) {
  3918. el.style.border = '1px solid #eee';
  3919. });
  3920. el.addEventListener('dragstop', function(e) {
  3921. el.style.border = '1px solid #eee';
  3922. });
  3923. el.addEventListener('dragover', function(e) {
  3924. e.preventDefault();
  3925. });
  3926. el.addEventListener('drop', function(e) {
  3927. e.preventDefault();
  3928. e.stopPropagation();
  3929. var html = (e.originalEvent || e).dataTransfer.getData('text/html');
  3930. var file = (e.originalEvent || e).dataTransfer.files;
  3931. if (file.length) {
  3932. for (var i = 0; i < e.dataTransfer.files.length; i++) {
  3933. obj.addFromFile(e.dataTransfer.files[i]);
  3934. }
  3935. } else if (html) {
  3936. if (obj.options.singleFile == true) {
  3937. el.innerHTML = '';
  3938. }
  3939. // Create temp element
  3940. var div = document.createElement('div');
  3941. div.innerHTML = html;
  3942. // Extract images
  3943. var img = div.querySelectorAll('img');
  3944. if (img.length) {
  3945. for (var i = 0; i < img.length; i++) {
  3946. obj.addFromUrl(img[i].src);
  3947. }
  3948. }
  3949. }
  3950. el.style.border = '1px solid #eee';
  3951. return false;
  3952. });
  3953. el.image = obj;
  3954. return obj;
  3955. });
  3956. /**
  3957. * (c) jLoading
  3958. * https://github.com/paulhodel/jtools
  3959. *
  3960. * @author: Paul Hodel <paul.hodel@gmail.com>
  3961. * @description: Page loading spin
  3962. */
  3963. jSuites.loading = (function() {
  3964. var obj = {};
  3965. var loading = document.createElement('div');
  3966. loading.className = 'jloading';
  3967. obj.show = function() {
  3968. document.body.appendChild(loading);
  3969. };
  3970. obj.hide = function() {
  3971. document.body.removeChild(loading);
  3972. };
  3973. return obj;
  3974. })();
  3975. /**
  3976. * (c) jLogin
  3977. * https://github.com/paulhodel/jtools
  3978. *
  3979. * @author: Paul Hodel <paul.hodel@gmail.com>
  3980. * @description: Login helper
  3981. */
  3982. jSuites.login = (function(el, options) {
  3983. var obj = {};
  3984. obj.options = {};
  3985. // Default configuration
  3986. var defaults = {
  3987. url: window.location.href,
  3988. prepareRequest: null,
  3989. accessToken: null,
  3990. deviceToken: null,
  3991. facebookUrl: null,
  3992. maxHeight: null,
  3993. onload: null,
  3994. onerror: null,
  3995. message: null,
  3996. logo: null,
  3997. newProfile: false,
  3998. newProfileUrl: false,
  3999. newProfileLogin: false,
  4000. fullscreen: false,
  4001. };
  4002. // Loop through our object
  4003. for (var property in defaults) {
  4004. if (options && options.hasOwnProperty(property)) {
  4005. obj.options[property] = options[property];
  4006. } else {
  4007. obj.options[property] = defaults[property];
  4008. }
  4009. }
  4010. // Message console container
  4011. if (! obj.options.message) {
  4012. var messageElement = document.querySelector('.message');
  4013. if (messageElement) {
  4014. obj.options.message = messageElement;
  4015. }
  4016. }
  4017. // Action
  4018. var action = null;
  4019. // Container
  4020. var container = document.createElement('form');
  4021. el.appendChild(container);
  4022. // Logo
  4023. var divLogo = document.createElement('div');
  4024. divLogo.className = 'jlogin-logo'
  4025. container.appendChild(divLogo);
  4026. if (obj.options.logo) {
  4027. var logo = document.createElement('img');
  4028. logo.src = obj.options.logo;
  4029. divLogo.appendChild(logo);
  4030. }
  4031. // Code
  4032. var labelCode = document.createElement('label');
  4033. labelCode.innerHTML = 'Please enter here the code received';
  4034. var inputCode = document.createElement('input');
  4035. inputCode.type = 'number';
  4036. inputCode.id = 'code';
  4037. inputCode.setAttribute('maxlength', 6);
  4038. var divCode = document.createElement('div');
  4039. divCode.appendChild(labelCode);
  4040. divCode.appendChild(inputCode);
  4041. // Hash
  4042. var inputHash = document.createElement('input');
  4043. inputHash.type = 'hidden';
  4044. inputHash.name = 'h';
  4045. var divHash = document.createElement('div');
  4046. divHash.appendChild(inputHash);
  4047. // Recovery
  4048. var inputRecovery = document.createElement('input');
  4049. inputRecovery.type = 'hidden';
  4050. inputRecovery.name = 'recovery';
  4051. inputRecovery.value = '1';
  4052. var divRecovery = document.createElement('div');
  4053. divRecovery.appendChild(inputRecovery);
  4054. // Login
  4055. var labelLogin = document.createElement('label');
  4056. labelLogin.innerHTML = 'Login';
  4057. var inputLogin = document.createElement('input');
  4058. inputLogin.type = 'text';
  4059. inputLogin.name = 'login';
  4060. inputLogin.setAttribute('autocomplete', 'off');
  4061. inputLogin.onkeyup = function() {
  4062. this.value = this.value.toLowerCase().replace(/[^a-zA-Z0-9_+]+/gi, '');
  4063. }
  4064. var divLogin = document.createElement('div');
  4065. divLogin.appendChild(labelLogin);
  4066. divLogin.appendChild(inputLogin);
  4067. // Name
  4068. var labelName = document.createElement('label');
  4069. labelName.innerHTML = 'Name';
  4070. var inputName = document.createElement('input');
  4071. inputName.type = 'text';
  4072. inputName.name = 'name';
  4073. var divName = document.createElement('div');
  4074. divName.appendChild(labelName);
  4075. divName.appendChild(inputName);
  4076. // Email
  4077. var labelUsername = document.createElement('label');
  4078. labelUsername.innerHTML = 'E-mail';
  4079. var inputUsername = document.createElement('input');
  4080. inputUsername.type = 'text';
  4081. inputUsername.name = 'username';
  4082. inputUsername.setAttribute('autocomplete', 'new-username');
  4083. var divUsername = document.createElement('div');
  4084. divUsername.appendChild(labelUsername);
  4085. divUsername.appendChild(inputUsername);
  4086. // Password
  4087. var labelPassword = document.createElement('label');
  4088. labelPassword.innerHTML = 'Password';
  4089. var inputPassword = document.createElement('input');
  4090. inputPassword.type = 'password';
  4091. inputPassword.name = 'password';
  4092. inputPassword.setAttribute('autocomplete', 'new-password');
  4093. var divPassword = document.createElement('div');
  4094. divPassword.appendChild(labelPassword);
  4095. divPassword.appendChild(inputPassword);
  4096. divPassword.onkeydown = function(e) {
  4097. if (e.keyCode == 13) {
  4098. obj.execute();
  4099. }
  4100. }
  4101. // Repeat password
  4102. var labelRepeatPassword = document.createElement('label');
  4103. labelRepeatPassword.innerHTML = 'Password';
  4104. var inputRepeatPassword = document.createElement('input');
  4105. inputRepeatPassword.type = 'password';
  4106. inputRepeatPassword.name = 'password';
  4107. var divRepeatPassword = document.createElement('div');
  4108. divRepeatPassword.appendChild(labelRepeatPassword);
  4109. divRepeatPassword.appendChild(inputRepeatPassword);
  4110. // Remember checkbox
  4111. var labelRemember = document.createElement('label');
  4112. labelRemember.innerHTML = 'Remember me on this device';
  4113. var inputRemember = document.createElement('input');
  4114. inputRemember.type = 'checkbox';
  4115. inputRemember.name = 'remember';
  4116. inputRemember.value = '1';
  4117. labelRemember.appendChild(inputRemember);
  4118. var divRememberButton = document.createElement('div');
  4119. divRememberButton.className = 'rememberButton';
  4120. divRememberButton.appendChild(labelRemember);
  4121. // Login button
  4122. var actionButton = document.createElement('input');
  4123. actionButton.type = 'button';
  4124. actionButton.value = 'Log In';
  4125. actionButton.onclick = function() {
  4126. obj.execute();
  4127. }
  4128. var divActionButton = document.createElement('div');
  4129. divActionButton.appendChild(actionButton);
  4130. // Cancel button
  4131. var cancelButton = document.createElement('div');
  4132. cancelButton.innerHTML = 'Cancel';
  4133. cancelButton.className = 'cancelButton';
  4134. cancelButton.onclick = function() {
  4135. obj.requestAccess();
  4136. }
  4137. var divCancelButton = document.createElement('div');
  4138. divCancelButton.appendChild(cancelButton);
  4139. // Captcha
  4140. var labelCaptcha = document.createElement('label');
  4141. labelCaptcha.innerHTML = 'Please type here the code below';
  4142. var inputCaptcha = document.createElement('input');
  4143. inputCaptcha.type = 'text';
  4144. inputCaptcha.name = 'captcha';
  4145. var imageCaptcha = document.createElement('img');
  4146. var divCaptcha = document.createElement('div');
  4147. divCaptcha.className = 'jlogin-captcha';
  4148. divCaptcha.appendChild(labelCaptcha);
  4149. divCaptcha.appendChild(inputCaptcha);
  4150. divCaptcha.appendChild(imageCaptcha);
  4151. // Facebook
  4152. var facebookButton = document.createElement('div');
  4153. facebookButton.innerHTML = 'Login with Facebook';
  4154. facebookButton.className = 'facebookButton';
  4155. var divFacebookButton = document.createElement('div');
  4156. divFacebookButton.appendChild(facebookButton);
  4157. divFacebookButton.onclick = function() {
  4158. obj.requestLoginViaFacebook();
  4159. }
  4160. // Forgot password
  4161. var inputRequest = document.createElement('span');
  4162. inputRequest.innerHTML = 'Request a new password';
  4163. var divRequestButton = document.createElement('div');
  4164. divRequestButton.className = 'requestButton';
  4165. divRequestButton.appendChild(inputRequest);
  4166. divRequestButton.onclick = function() {
  4167. obj.requestNewPassword();
  4168. }
  4169. // Create a new Profile
  4170. var inputNewProfile = document.createElement('span');
  4171. inputNewProfile.innerHTML = 'Create a new profile';
  4172. var divNewProfileButton = document.createElement('div');
  4173. divNewProfileButton.className = 'newProfileButton';
  4174. divNewProfileButton.appendChild(inputNewProfile);
  4175. divNewProfileButton.onclick = function() {
  4176. obj.newProfile();
  4177. }
  4178. el.className = 'jlogin';
  4179. if (obj.options.fullscreen == true) {
  4180. el.classList.add('jlogin-fullscreen');
  4181. }
  4182. /**
  4183. * Show message
  4184. */
  4185. obj.showMessage = function(data) {
  4186. var message = (typeof(data) == 'object') ? data.message : data;
  4187. if (typeof(obj.options.showMessage) == 'function') {
  4188. obj.options.showMessage(data);
  4189. } else {
  4190. jSuites.alert(data);
  4191. }
  4192. }
  4193. /**
  4194. * New profile
  4195. */
  4196. obj.newProfile = function() {
  4197. container.innerHTML = '';
  4198. container.appendChild(divLogo);
  4199. if (obj.options.newProfileLogin) {
  4200. container.appendChild(divLogin);
  4201. }
  4202. container.appendChild(divName);
  4203. container.appendChild(divUsername);
  4204. container.appendChild(divActionButton);
  4205. container.appendChild(divFacebookButton);
  4206. container.appendChild(divCancelButton);
  4207. // Reset inputs
  4208. inputLogin.value = '';
  4209. inputUsername.value = '';
  4210. inputPassword.value = '';
  4211. // Button
  4212. actionButton.value = 'Create new profile';
  4213. // Action
  4214. action = 'newProfile';
  4215. }
  4216. /**
  4217. * Request the email with the recovery instructions
  4218. */
  4219. obj.requestNewPassword = function() {
  4220. if (Array.prototype.indexOf.call(container.children, divCaptcha) >= 0) {
  4221. var captcha = true;
  4222. }
  4223. container.innerHTML = '';
  4224. container.appendChild(divLogo);
  4225. container.appendChild(divRecovery);
  4226. container.appendChild(divUsername);
  4227. if (captcha) {
  4228. container.appendChild(divCaptcha);
  4229. }
  4230. container.appendChild(divActionButton);
  4231. container.appendChild(divCancelButton);
  4232. actionButton.value = 'Request a new password';
  4233. inputRecovery.value = 1;
  4234. // Action
  4235. action = 'requestNewPassword';
  4236. }
  4237. /**
  4238. * Confirm recovery code
  4239. */
  4240. obj.codeConfirmation = function() {
  4241. container.innerHTML = '';
  4242. container.appendChild(divLogo);
  4243. container.appendChild(divHash);
  4244. container.appendChild(divCode);
  4245. container.appendChild(divActionButton);
  4246. container.appendChild(divCancelButton);
  4247. actionButton.value = 'Confirm code';
  4248. inputRecovery.value = 2;
  4249. // Action
  4250. action = 'codeConfirmation';
  4251. }
  4252. /**
  4253. * Update my password
  4254. */
  4255. obj.changeMyPassword = function(hash) {
  4256. container.innerHTML = '';
  4257. container.appendChild(divLogo);
  4258. container.appendChild(divHash);
  4259. container.appendChild(divPassword);
  4260. container.appendChild(divRepeatPassword);
  4261. container.appendChild(divActionButton);
  4262. container.appendChild(divCancelButton);
  4263. actionButton.value = 'Change my password';
  4264. inputHash.value = hash;
  4265. // Action
  4266. action = 'changeMyPassword';
  4267. }
  4268. /**
  4269. * Request access default method
  4270. */
  4271. obj.requestAccess = function() {
  4272. container.innerHTML = '';
  4273. container.appendChild(divLogo);
  4274. container.appendChild(divUsername);
  4275. container.appendChild(divPassword);
  4276. container.appendChild(divActionButton);
  4277. container.appendChild(divFacebookButton);
  4278. container.appendChild(divRequestButton);
  4279. container.appendChild(divRememberButton);
  4280. container.appendChild(divRequestButton);
  4281. if (obj.options.newProfile == true) {
  4282. container.appendChild(divNewProfileButton);
  4283. }
  4284. // Button
  4285. actionButton.value = 'Login';
  4286. // Password
  4287. inputPassword.value = '';
  4288. // Email persistence
  4289. if (window.localStorage.getItem('username')) {
  4290. inputUsername.value = window.localStorage.getItem('username');
  4291. inputPassword.focus();
  4292. } else {
  4293. inputUsername.focus();
  4294. }
  4295. // Action
  4296. action = 'requestAccess';
  4297. }
  4298. /**
  4299. * Request login via facebook
  4300. */
  4301. obj.requestLoginViaFacebook = function() {
  4302. if (typeof(deviceNotificationToken) == 'undefined') {
  4303. FB.getLoginStatus(function(response) {
  4304. if (! response.status || response.status != 'connected') {
  4305. FB.login(function(response) {
  4306. if (response.authResponse) {
  4307. obj.execute({ f:response.authResponse.accessToken });
  4308. } else {
  4309. obj.showMessage('Not authorized by facebook');
  4310. }
  4311. }, {scope: 'public_profile,email'});
  4312. } else {
  4313. obj.execute({ f:response.authResponse.accessToken });
  4314. }
  4315. }, true);
  4316. } else {
  4317. jDestroy = function() {
  4318. fbLogin.removeEventListener('loadstart', jStart);
  4319. fbLogin.removeEventListener('loaderror', jError);
  4320. fbLogin.removeEventListener('exit', jExit);
  4321. fbLogin.close();
  4322. fbLogin = null;
  4323. }
  4324. jStart = function(event) {
  4325. var url = event.url;
  4326. if (url.indexOf("access_token") >= 0) {
  4327. setTimeout(function(){
  4328. var u = url.match(/=(.*?)&/);
  4329. if (u[1].length > 32) {
  4330. obj.execute({ f:u[1] });
  4331. }
  4332. jDestroy();
  4333. },500);
  4334. }
  4335. if (url.indexOf("error=access_denied") >= 0) {
  4336. setTimeout(jDestroy ,500);
  4337. // Not authorized by facebook
  4338. obj.showMessage('Not authorized by facebook');
  4339. }
  4340. }
  4341. jError = function(event) {
  4342. jDestroy();
  4343. }
  4344. jExit = function(event) {
  4345. jDestroy();
  4346. }
  4347. fbLogin = window.open(this.facebookUrl, "_blank", "location=no,closebuttoncaption=Exit,disallowoverscroll=yes,toolbar=no");
  4348. fbLogin.addEventListener('loadstart', jStart);
  4349. fbLogin.addEventListener('loaderror', jError);
  4350. fbLogin.addEventListener('exit', jExit);
  4351. }
  4352. // Action
  4353. action = 'requestLoginViaFacebook';
  4354. }
  4355. // Perform request
  4356. obj.execute = function(data) {
  4357. // New profile
  4358. if (action == 'newProfile') {
  4359. var pattern = new RegExp(/^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/);
  4360. if (! inputUsername.value || ! pattern.test(inputUsername.value)) {
  4361. var message = 'Invalid e-mail address';
  4362. }
  4363. var pattern = new RegExp(/^[a-zA-Z0-9\_\-\.\s+]+$/);
  4364. if (! inputLogin.value || ! pattern.test(inputLogin.value)) {
  4365. var message = 'Invalid username, please use only characters and numbers';
  4366. }
  4367. if (message) {
  4368. obj.showMessage(message);
  4369. return false;
  4370. }
  4371. }
  4372. // Keep email
  4373. if (inputUsername.value != '') {
  4374. window.localStorage.setItem('username', inputUsername.value);
  4375. }
  4376. // Captcha
  4377. if (Array.prototype.indexOf.call(container.children, divCaptcha) >= 0) {
  4378. if (inputCaptcha.value == '') {
  4379. obj.showMessage('Please enter the captch code below');
  4380. return false;
  4381. }
  4382. }
  4383. // Url
  4384. var url = obj.options.url;
  4385. // Device token
  4386. if (obj.options.deviceToken) {
  4387. url += '?token=' + obj.options.deviceToken;
  4388. }
  4389. // Callback
  4390. var onsuccess = function(result) {
  4391. if (result) {
  4392. // Successfully response
  4393. if (result.success == 1) {
  4394. // Recovery process
  4395. if (action == 'requestNewPassword') {
  4396. obj.codeConfirmation();
  4397. } else if (action == 'codeConfirmation') {
  4398. obj.requestAccess();
  4399. } else if (action == 'newProfile') {
  4400. obj.requestAccess();
  4401. // New profile
  4402. result.newProfile = true;
  4403. }
  4404. // Token
  4405. if (result.token) {
  4406. // Set token
  4407. obj.options.accessToken = result.token;
  4408. // Save token
  4409. window.localStorage.setItem('Access-Token', result.token);
  4410. }
  4411. }
  4412. // Show message
  4413. if (result.message) {
  4414. // Show message
  4415. obj.showMessage(result.message)
  4416. }
  4417. // Request captcha code
  4418. if (! result.data) {
  4419. if (Array.prototype.indexOf.call(container.children, divCaptcha) >= 0) {
  4420. divCaptcha.remove();
  4421. }
  4422. } else {
  4423. container.insertBefore(divCaptcha, divActionButton);
  4424. imageCaptcha.setAttribute('src', 'data:image/png;base64,' + result.data);
  4425. }
  4426. // Give time to user see the message
  4427. if (result.hash) {
  4428. // Change password
  4429. obj.changeMyPassword(result.hash);
  4430. } else if (result.url) {
  4431. // App initialization
  4432. if (result.success == 1) {
  4433. if (typeof(obj.options.onload) == 'function') {
  4434. obj.options.onload(result);
  4435. } else {
  4436. if (result.message) {
  4437. setTimeout(function() { window.location.href = result.url; }, 2000);
  4438. } else {
  4439. window.location.href = result.url;
  4440. }
  4441. }
  4442. } else {
  4443. if (typeof(obj.options.onerror) == 'function') {
  4444. obj.options.onerror(result);
  4445. }
  4446. }
  4447. }
  4448. }
  4449. }
  4450. // Password
  4451. if (! data) {
  4452. var data = jSuites.getFormElements(el);
  4453. // Encode passworfd
  4454. if (data.password) {
  4455. data.password = jSuites.login.sha512(data.password);
  4456. }
  4457. // Recovery code
  4458. if (Array.prototype.indexOf.call(container.children, divCode) >= 0 && inputCode.value) {
  4459. data.h = jSuites.login.sha512(inputCode.value);
  4460. }
  4461. }
  4462. // Loading
  4463. el.classList.add('jlogin-loading');
  4464. // Url
  4465. var url = (action == 'newProfile' && obj.options.newProfileUrl) ? obj.options.newProfileUrl : obj.options.url;
  4466. // Remote call
  4467. jSuites.ajax({
  4468. url: url,
  4469. method: 'POST',
  4470. dataType: 'json',
  4471. data: data,
  4472. success: function(result) {
  4473. // Remove loading
  4474. el.classList.remove('jlogin-loading');
  4475. // Callback
  4476. onsuccess(result);
  4477. },
  4478. error: function(result) {
  4479. // Error
  4480. el.classList.remove('jlogin-loading');
  4481. if (typeof(obj.options.onerror) == 'function') {
  4482. obj.options.onerror(result);
  4483. }
  4484. }
  4485. });
  4486. }
  4487. obj.requestAccess();
  4488. return obj;
  4489. });
  4490. jSuites.login.sha512 = (function(str) {
  4491. function int64(msint_32, lsint_32) {
  4492. this.highOrder = msint_32;
  4493. this.lowOrder = lsint_32;
  4494. }
  4495. var H = [new int64(0x6a09e667, 0xf3bcc908), new int64(0xbb67ae85, 0x84caa73b),
  4496. new int64(0x3c6ef372, 0xfe94f82b), new int64(0xa54ff53a, 0x5f1d36f1),
  4497. new int64(0x510e527f, 0xade682d1), new int64(0x9b05688c, 0x2b3e6c1f),
  4498. new int64(0x1f83d9ab, 0xfb41bd6b), new int64(0x5be0cd19, 0x137e2179)];
  4499. var K = [new int64(0x428a2f98, 0xd728ae22), new int64(0x71374491, 0x23ef65cd),
  4500. new int64(0xb5c0fbcf, 0xec4d3b2f), new int64(0xe9b5dba5, 0x8189dbbc),
  4501. new int64(0x3956c25b, 0xf348b538), new int64(0x59f111f1, 0xb605d019),
  4502. new int64(0x923f82a4, 0xaf194f9b), new int64(0xab1c5ed5, 0xda6d8118),
  4503. new int64(0xd807aa98, 0xa3030242), new int64(0x12835b01, 0x45706fbe),
  4504. new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, 0xd5ffb4e2),
  4505. new int64(0x72be5d74, 0xf27b896f), new int64(0x80deb1fe, 0x3b1696b1),
  4506. new int64(0x9bdc06a7, 0x25c71235), new int64(0xc19bf174, 0xcf692694),
  4507. new int64(0xe49b69c1, 0x9ef14ad2), new int64(0xefbe4786, 0x384f25e3),
  4508. new int64(0x0fc19dc6, 0x8b8cd5b5), new int64(0x240ca1cc, 0x77ac9c65),
  4509. new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
  4510. new int64(0x5cb0a9dc, 0xbd41fbd4), new int64(0x76f988da, 0x831153b5),
  4511. new int64(0x983e5152, 0xee66dfab), new int64(0xa831c66d, 0x2db43210),
  4512. new int64(0xb00327c8, 0x98fb213f), new int64(0xbf597fc7, 0xbeef0ee4),
  4513. new int64(0xc6e00bf3, 0x3da88fc2), new int64(0xd5a79147, 0x930aa725),
  4514. new int64(0x06ca6351, 0xe003826f), new int64(0x14292967, 0x0a0e6e70),
  4515. new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
  4516. new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, 0x9d95b3df),
  4517. new int64(0x650a7354, 0x8baf63de), new int64(0x766a0abb, 0x3c77b2a8),
  4518. new int64(0x81c2c92e, 0x47edaee6), new int64(0x92722c85, 0x1482353b),
  4519. new int64(0xa2bfe8a1, 0x4cf10364), new int64(0xa81a664b, 0xbc423001),
  4520. new int64(0xc24b8b70, 0xd0f89791), new int64(0xc76c51a3, 0x0654be30),
  4521. new int64(0xd192e819, 0xd6ef5218), new int64(0xd6990624, 0x5565a910),
  4522. new int64(0xf40e3585, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
  4523. new int64(0x19a4c116, 0xb8d2d0c8), new int64(0x1e376c08, 0x5141ab53),
  4524. new int64(0x2748774c, 0xdf8eeb99), new int64(0x34b0bcb5, 0xe19b48a8),
  4525. new int64(0x391c0cb3, 0xc5c95a63), new int64(0x4ed8aa4a, 0xe3418acb),
  4526. new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, 0xd6b2b8a3),
  4527. new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
  4528. new int64(0x84c87814, 0xa1f0ab72), new int64(0x8cc70208, 0x1a6439ec),
  4529. new int64(0x90befffa, 0x23631e28), new int64(0xa4506ceb, 0xde82bde9),
  4530. new int64(0xbef9a3f7, 0xb2c67915), new int64(0xc67178f2, 0xe372532b),
  4531. new int64(0xca273ece, 0xea26619c), new int64(0xd186b8c7, 0x21c0c207),
  4532. new int64(0xeada7dd6, 0xcde0eb1e), new int64(0xf57d4f7f, 0xee6ed178),
  4533. new int64(0x06f067aa, 0x72176fba), new int64(0x0a637dc5, 0xa2c898a6),
  4534. new int64(0x113f9804, 0xbef90dae), new int64(0x1b710b35, 0x131c471b),
  4535. new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
  4536. new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, 0x9c100d4c),
  4537. new int64(0x4cc5d4be, 0xcb3e42b6), new int64(0x597f299c, 0xfc657e2a),
  4538. new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)];
  4539. var W = new Array(64);
  4540. var a, b, c, d, e, f, g, h, i, j;
  4541. var T1, T2;
  4542. var charsize = 8;
  4543. function utf8_encode(str) {
  4544. return unescape(encodeURIComponent(str));
  4545. }
  4546. function str2binb(str) {
  4547. var bin = [];
  4548. var mask = (1 << charsize) - 1;
  4549. var len = str.length * charsize;
  4550. for (var i = 0; i < len; i += charsize) {
  4551. bin[i >> 5] |= (str.charCodeAt(i / charsize) & mask) << (32 - charsize - (i % 32));
  4552. }
  4553. return bin;
  4554. }
  4555. function binb2hex(binarray) {
  4556. var hex_tab = "0123456789abcdef";
  4557. var str = "";
  4558. var length = binarray.length * 4;
  4559. var srcByte;
  4560. for (var i = 0; i < length; i += 1) {
  4561. srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8);
  4562. str += hex_tab.charAt((srcByte >> 4) & 0xF) + hex_tab.charAt(srcByte & 0xF);
  4563. }
  4564. return str;
  4565. }
  4566. function safe_add_2(x, y) {
  4567. var lsw, msw, lowOrder, highOrder;
  4568. lsw = (x.lowOrder & 0xFFFF) + (y.lowOrder & 0xFFFF);
  4569. msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16);
  4570. lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
  4571. lsw = (x.highOrder & 0xFFFF) + (y.highOrder & 0xFFFF) + (msw >>> 16);
  4572. msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16);
  4573. highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
  4574. return new int64(highOrder, lowOrder);
  4575. }
  4576. function safe_add_4(a, b, c, d) {
  4577. var lsw, msw, lowOrder, highOrder;
  4578. lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF);
  4579. msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16);
  4580. lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
  4581. lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (msw >>> 16);
  4582. msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16);
  4583. highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
  4584. return new int64(highOrder, lowOrder);
  4585. }
  4586. function safe_add_5(a, b, c, d, e) {
  4587. var lsw, msw, lowOrder, highOrder;
  4588. lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF) + (e.lowOrder & 0xFFFF);
  4589. msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (e.lowOrder >>> 16) + (lsw >>> 16);
  4590. lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
  4591. lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (e.highOrder & 0xFFFF) + (msw >>> 16);
  4592. msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (e.highOrder >>> 16) + (lsw >>> 16);
  4593. highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
  4594. return new int64(highOrder, lowOrder);
  4595. }
  4596. function maj(x, y, z) {
  4597. return new int64(
  4598. (x.highOrder & y.highOrder) ^ (x.highOrder & z.highOrder) ^ (y.highOrder & z.highOrder),
  4599. (x.lowOrder & y.lowOrder) ^ (x.lowOrder & z.lowOrder) ^ (y.lowOrder & z.lowOrder)
  4600. );
  4601. }
  4602. function ch(x, y, z) {
  4603. return new int64(
  4604. (x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder),
  4605. (x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder)
  4606. );
  4607. }
  4608. function rotr(x, n) {
  4609. if (n <= 32) {
  4610. return new int64(
  4611. (x.highOrder >>> n) | (x.lowOrder << (32 - n)),
  4612. (x.lowOrder >>> n) | (x.highOrder << (32 - n))
  4613. );
  4614. } else {
  4615. return new int64(
  4616. (x.lowOrder >>> n) | (x.highOrder << (32 - n)),
  4617. (x.highOrder >>> n) | (x.lowOrder << (32 - n))
  4618. );
  4619. }
  4620. }
  4621. function sigma0(x) {
  4622. var rotr28 = rotr(x, 28);
  4623. var rotr34 = rotr(x, 34);
  4624. var rotr39 = rotr(x, 39);
  4625. return new int64(
  4626. rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder,
  4627. rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder
  4628. );
  4629. }
  4630. function sigma1(x) {
  4631. var rotr14 = rotr(x, 14);
  4632. var rotr18 = rotr(x, 18);
  4633. var rotr41 = rotr(x, 41);
  4634. return new int64(
  4635. rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder,
  4636. rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder
  4637. );
  4638. }
  4639. function gamma0(x) {
  4640. var rotr1 = rotr(x, 1), rotr8 = rotr(x, 8), shr7 = shr(x, 7);
  4641. return new int64(
  4642. rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder,
  4643. rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder
  4644. );
  4645. }
  4646. function gamma1(x) {
  4647. var rotr19 = rotr(x, 19);
  4648. var rotr61 = rotr(x, 61);
  4649. var shr6 = shr(x, 6);
  4650. return new int64(
  4651. rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder,
  4652. rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder
  4653. );
  4654. }
  4655. function shr(x, n) {
  4656. if (n <= 32) {
  4657. return new int64(
  4658. x.highOrder >>> n,
  4659. x.lowOrder >>> n | (x.highOrder << (32 - n))
  4660. );
  4661. } else {
  4662. return new int64(
  4663. 0,
  4664. x.highOrder << (32 - n)
  4665. );
  4666. }
  4667. }
  4668. var str = utf8_encode(str);
  4669. var strlen = str.length*charsize;
  4670. str = str2binb(str);
  4671. str[strlen >> 5] |= 0x80 << (24 - strlen % 32);
  4672. str[(((strlen + 128) >> 10) << 5) + 31] = strlen;
  4673. for (var i = 0; i < str.length; i += 32) {
  4674. a = H[0];
  4675. b = H[1];
  4676. c = H[2];
  4677. d = H[3];
  4678. e = H[4];
  4679. f = H[5];
  4680. g = H[6];
  4681. h = H[7];
  4682. for (var j = 0; j < 80; j++) {
  4683. if (j < 16) {
  4684. W[j] = new int64(str[j*2 + i], str[j*2 + i + 1]);
  4685. } else {
  4686. W[j] = safe_add_4(gamma1(W[j - 2]), W[j - 7], gamma0(W[j - 15]), W[j - 16]);
  4687. }
  4688. T1 = safe_add_5(h, sigma1(e), ch(e, f, g), K[j], W[j]);
  4689. T2 = safe_add_2(sigma0(a), maj(a, b, c));
  4690. h = g;
  4691. g = f;
  4692. f = e;
  4693. e = safe_add_2(d, T1);
  4694. d = c;
  4695. c = b;
  4696. b = a;
  4697. a = safe_add_2(T1, T2);
  4698. }
  4699. H[0] = safe_add_2(a, H[0]);
  4700. H[1] = safe_add_2(b, H[1]);
  4701. H[2] = safe_add_2(c, H[2]);
  4702. H[3] = safe_add_2(d, H[3]);
  4703. H[4] = safe_add_2(e, H[4]);
  4704. H[5] = safe_add_2(f, H[5]);
  4705. H[6] = safe_add_2(g, H[6]);
  4706. H[7] = safe_add_2(h, H[7]);
  4707. }
  4708. var binarray = [];
  4709. for (var i = 0; i < H.length; i++) {
  4710. binarray.push(H[i].highOrder);
  4711. binarray.push(H[i].lowOrder);
  4712. }
  4713. return binb2hex(binarray);
  4714. });
  4715. /**
  4716. * (c) jTools Input Mask
  4717. * https://github.com/paulhodel/jtools
  4718. *
  4719. * @author: Paul Hodel <paul.hodel@gmail.com>
  4720. * @description: Input mask
  4721. */
  4722. jSuites.mask = (function() {
  4723. var obj = {};
  4724. var index = 0;
  4725. var values = []
  4726. var pieces = [];
  4727. obj.run = function(value, mask, decimal) {
  4728. if (value && mask) {
  4729. if (! decimal) {
  4730. decimal = '.';
  4731. }
  4732. if (value == Number(value)) {
  4733. var number = (''+value).split('.');
  4734. var value = number[0];
  4735. var valueDecimal = number[1];
  4736. } else {
  4737. value = '' + value;
  4738. }
  4739. index = 0;
  4740. values = [];
  4741. // Create mask token
  4742. obj.prepare(mask);
  4743. // Current value
  4744. var currentValue = value;
  4745. if (currentValue) {
  4746. // Checking current value
  4747. for (var i = 0; i < currentValue.length; i++) {
  4748. if (currentValue[i] != null) {
  4749. obj.process(currentValue[i]);
  4750. }
  4751. }
  4752. }
  4753. if (valueDecimal) {
  4754. obj.process(decimal);
  4755. var currentValue = valueDecimal;
  4756. if (currentValue) {
  4757. // Checking current value
  4758. for (var i = 0; i < currentValue.length; i++) {
  4759. if (currentValue[i] != null) {
  4760. obj.process(currentValue[i]);
  4761. }
  4762. }
  4763. }
  4764. }
  4765. // Formatted value
  4766. return values.join('');
  4767. } else {
  4768. return '';
  4769. }
  4770. }
  4771. obj.apply = function(e) {
  4772. var mask = e.target.getAttribute('data-mask');
  4773. if (mask && e.keyCode > 46) {
  4774. index = 0;
  4775. values = [];
  4776. // Create mask token
  4777. obj.prepare(mask);
  4778. // Current value
  4779. if (e.target.selectionStart < e.target.selectionEnd) {
  4780. var currentValue = e.target.value.substring(0, e.target.selectionStart);
  4781. } else {
  4782. var currentValue = e.target.value;
  4783. }
  4784. if (currentValue) {
  4785. // Checking current value
  4786. for (var i = 0; i < currentValue.length; i++) {
  4787. if (currentValue[i] != null) {
  4788. obj.process(currentValue[i]);
  4789. }
  4790. }
  4791. }
  4792. // New input
  4793. obj.process(obj.fromKeyCode(e));
  4794. // Update value to the element
  4795. e.target.value = values.join('');
  4796. if (pieces.length == values.length && pieces[pieces.length-1].length == values[values.length-1].length) {
  4797. e.target.setAttribute('data-completed', 'true');
  4798. } else {
  4799. e.target.setAttribute('data-completed', 'false');
  4800. }
  4801. // Prevent default
  4802. e.preventDefault();
  4803. }
  4804. }
  4805. /**
  4806. * Process inputs and save to values
  4807. */
  4808. obj.process = function(input) {
  4809. do {
  4810. if (pieces[index] == 'mm') {
  4811. if (values[index] == null || values[index] == '') {
  4812. if (parseInt(input) > 1 && parseInt(input) < 10) {
  4813. values[index] = '0' + input;
  4814. index++;
  4815. return true;
  4816. } else if (parseInt(input) < 10) {
  4817. values[index] = input;
  4818. return true;
  4819. } else {
  4820. return false;
  4821. }
  4822. } else {
  4823. if (values[index] == 1 && values[index] < 2 && parseInt(input) < 3) {
  4824. values[index] += input;
  4825. index++;
  4826. return true;
  4827. } else if (values[index] == 0 && values[index] < 10) {
  4828. values[index] += input;
  4829. index++;
  4830. return true;
  4831. } else {
  4832. return false
  4833. }
  4834. }
  4835. } else if (pieces[index] == 'dd') {
  4836. if (values[index] == null || values[index] == '') {
  4837. if (parseInt(input) > 3 && parseInt(input) < 10) {
  4838. values[index] = '0' + input;
  4839. index++;
  4840. return true;
  4841. } else if (parseInt(input) < 10) {
  4842. values[index] = input;
  4843. return true;
  4844. } else {
  4845. return false;
  4846. }
  4847. } else {
  4848. if (values[index] == 3 && parseInt(input) < 2) {
  4849. values[index] += input;
  4850. index++;
  4851. return true;
  4852. } else if (values[index] < 3 && parseInt(input) < 10) {
  4853. values[index] += input;
  4854. index++;
  4855. return true;
  4856. } else {
  4857. return false
  4858. }
  4859. }
  4860. } else if (pieces[index] == 'hh24') {
  4861. if (values[index] == null || values[index] == '') {
  4862. if (parseInt(input) > 2 && parseInt(input) < 10) {
  4863. values[index] = '0' + input;
  4864. index++;
  4865. return true;
  4866. } else if (parseInt(input) < 10) {
  4867. values[index] = input;
  4868. return true;
  4869. } else {
  4870. return false;
  4871. }
  4872. } else {
  4873. if (values[index] == 2 && parseInt(input) < 4) {
  4874. values[index] += input;
  4875. index++;
  4876. return true;
  4877. } else if (values[index] < 2 && parseInt(input) < 10) {
  4878. values[index] += input;
  4879. index++;
  4880. return true;
  4881. } else {
  4882. return false
  4883. }
  4884. }
  4885. } else if (pieces[index] == 'hh') {
  4886. if (values[index] == null || values[index] == '') {
  4887. if (parseInt(input) > 1 && parseInt(input) < 10) {
  4888. values[index] = '0' + input;
  4889. index++;
  4890. return true;
  4891. } else if (parseInt(input) < 10) {
  4892. values[index] = input;
  4893. return true;
  4894. } else {
  4895. return false;
  4896. }
  4897. } else {
  4898. if (values[index] == 1 && parseInt(input) < 3) {
  4899. values[index] += input;
  4900. index++;
  4901. return true;
  4902. } else if (values[index] < 1 && parseInt(input) < 10) {
  4903. values[index] += input;
  4904. index++;
  4905. return true;
  4906. } else {
  4907. return false
  4908. }
  4909. }
  4910. } else if (pieces[index] == 'mi' || pieces[index] == 'ss') {
  4911. if (values[index] == null || values[index] == '') {
  4912. if (parseInt(input) > 5 && parseInt(input) < 10) {
  4913. values[index] = '0' + input;
  4914. index++;
  4915. return true;
  4916. } else if (parseInt(input) < 10) {
  4917. values[index] = input;
  4918. return true;
  4919. } else {
  4920. return false;
  4921. }
  4922. } else {
  4923. if (parseInt(input) < 10) {
  4924. values[index] += input;
  4925. index++;
  4926. return true;
  4927. } else {
  4928. return false
  4929. }
  4930. }
  4931. } else if (pieces[index] == 'yy' || pieces[index] == 'yyyy') {
  4932. if (parseInt(input) < 10) {
  4933. if (values[index] == null || values[index] == '') {
  4934. values[index] = input;
  4935. } else {
  4936. values[index] += input;
  4937. }
  4938. if (values[index].length == pieces[index].length) {
  4939. index++;
  4940. }
  4941. return true;
  4942. } else {
  4943. return false;
  4944. }
  4945. } else if (pieces[index] == '#' || pieces[index] == '#.##' || pieces[index] == '#,##' || pieces[index] == '# ##') {
  4946. if (input.match(/[0-9]/g)) {
  4947. if (pieces[index] == '#.##') {
  4948. var separator = '.';
  4949. } else if (pieces[index] == '#,##') {
  4950. var separator = ',';
  4951. } else if (pieces[index] == '# ##') {
  4952. var separator = ' ';
  4953. } else {
  4954. var separator = '';
  4955. }
  4956. if (values[index] == null || values[index] == '') {
  4957. values[index] = input;
  4958. } else {
  4959. values[index] += input;
  4960. if (separator) {
  4961. values[index] = values[index].match(/[0-9]/g).join('');
  4962. var t = [];
  4963. var s = 0;
  4964. for (var j = values[index].length - 1; j >= 0 ; j--) {
  4965. t.push(values[index][j]);
  4966. s++;
  4967. if (! (s % 3)) {
  4968. t.push(separator);
  4969. }
  4970. }
  4971. t = t.reverse();
  4972. values[index] = t.join('');
  4973. if (values[index].substr(0,1) == separator) {
  4974. values[index] = values[index].substr(1);
  4975. }
  4976. }
  4977. }
  4978. return true;
  4979. } else {
  4980. if (pieces[index] == '#.##' && input == '.') {
  4981. // Do nothing
  4982. } else if (pieces[index] == '#,##' && input == ',') {
  4983. // Do nothing
  4984. } else if (pieces[index] == '# ##' && input == ' ') {
  4985. // Do nothing
  4986. } else {
  4987. if (values[index]) {
  4988. index++;
  4989. if (pieces[index]) {
  4990. if (pieces[index] == input) {
  4991. values[index] = input;
  4992. return true;
  4993. } else {
  4994. if (pieces[index] == '0' && pieces[index+1] == input) {
  4995. index++;
  4996. values[index] = input;
  4997. return true;
  4998. }
  4999. }
  5000. }
  5001. }
  5002. }
  5003. return false;
  5004. }
  5005. } else if (pieces[index] == '0') {
  5006. if (input.match(/[0-9]/g)) {
  5007. values[index] = input;
  5008. index++;
  5009. return true;
  5010. } else {
  5011. return false;
  5012. }
  5013. } else if (pieces[index] == 'a') {
  5014. if (input.match(/[a-zA-Z]/g)) {
  5015. values[index] = input;
  5016. index++;
  5017. return true;
  5018. } else {
  5019. return false;
  5020. }
  5021. } else {
  5022. if (pieces[index] != null) {
  5023. if (pieces[index] == '\\a') {
  5024. var v = 'a';
  5025. } else if (pieces[index] == '\\0') {
  5026. var v = '0';
  5027. } else if (pieces[index] == '[-]') {
  5028. if (input == '-' || input == '+') {
  5029. var v = input;
  5030. } else {
  5031. var v = ' ';
  5032. }
  5033. } else {
  5034. var v = pieces[index];
  5035. }
  5036. values[index] = v;
  5037. if (input == v) {
  5038. index++;
  5039. return true;
  5040. }
  5041. }
  5042. }
  5043. index++;
  5044. } while (pieces[index]);
  5045. }
  5046. /**
  5047. * Create tokens for the mask
  5048. */
  5049. obj.prepare = function(mask) {
  5050. pieces = [];
  5051. for (var i = 0; i < mask.length; i++) {
  5052. if (mask[i].match(/[0-9]|[a-z]|\\/g)) {
  5053. if (mask[i] == 'y' && mask[i+1] == 'y' && mask[i+2] == 'y' && mask[i+3] == 'y') {
  5054. pieces.push('yyyy');
  5055. i += 3;
  5056. } else if (mask[i] == 'y' && mask[i+1] == 'y') {
  5057. pieces.push('yy');
  5058. i++;
  5059. } else if (mask[i] == 'm' && mask[i+1] == 'm' && mask[i+2] == 'm' && mask[i+3] == 'm') {
  5060. pieces.push('mmmm');
  5061. i += 3;
  5062. } else if (mask[i] == 'm' && mask[i+1] == 'm' && mask[i+2] == 'm') {
  5063. pieces.push('mmm');
  5064. i += 2;
  5065. } else if (mask[i] == 'm' && mask[i+1] == 'm') {
  5066. pieces.push('mm');
  5067. i++;
  5068. } else if (mask[i] == 'd' && mask[i+1] == 'd') {
  5069. pieces.push('dd');
  5070. i++;
  5071. } else if (mask[i] == 'h' && mask[i+1] == 'h' && mask[i+2] == '2' && mask[i+3] == '4') {
  5072. pieces.push('hh24');
  5073. i += 3;
  5074. } else if (mask[i] == 'h' && mask[i+1] == 'h') {
  5075. pieces.push('hh');
  5076. i++;
  5077. } else if (mask[i] == 'm' && mask[i+1] == 'i') {
  5078. pieces.push('mi');
  5079. i++;
  5080. } else if (mask[i] == 's' && mask[i+1] == 's') {
  5081. pieces.push('ss');
  5082. i++;
  5083. } else if (mask[i] == 'a' && mask[i+1] == 'm') {
  5084. pieces.push('am');
  5085. i++;
  5086. } else if (mask[i] == 'p' && mask[i+1] == 'm') {
  5087. pieces.push('pm');
  5088. i++;
  5089. } else if (mask[i] == '\\' && mask[i+1] == '0') {
  5090. pieces.push('\\0');
  5091. i++;
  5092. } else if (mask[i] == '\\' && mask[i+1] == 'a') {
  5093. pieces.push('\\a');
  5094. i++;
  5095. } else {
  5096. pieces.push(mask[i]);
  5097. }
  5098. } else {
  5099. if (mask[i] == '#' && mask[i+1] == '.' && mask[i+2] == '#' && mask[i+3] == '#') {
  5100. pieces.push('#.##');
  5101. i += 3;
  5102. } else if (mask[i] == '#' && mask[i+1] == ',' && mask[i+2] == '#' && mask[i+3] == '#') {
  5103. pieces.push('#,##');
  5104. i += 3;
  5105. } else if (mask[i] == '#' && mask[i+1] == ' ' && mask[i+2] == '#' && mask[i+3] == '#') {
  5106. pieces.push('# ##');
  5107. i += 3;
  5108. } else if (mask[i] == '[' && mask[i+1] == '-' && mask[i+2] == ']') {
  5109. pieces.push('[-]');
  5110. i += 2;
  5111. } else {
  5112. pieces.push(mask[i]);
  5113. }
  5114. }
  5115. }
  5116. }
  5117. /**
  5118. * Thanks for the collaboration
  5119. */
  5120. obj.fromKeyCode = function(e) {
  5121. var _to_ascii = {
  5122. '188': '44',
  5123. '109': '45',
  5124. '190': '46',
  5125. '191': '47',
  5126. '192': '96',
  5127. '220': '92',
  5128. '222': '39',
  5129. '221': '93',
  5130. '219': '91',
  5131. '173': '45',
  5132. '187': '61', //IE Key codes
  5133. '186': '59', //IE Key codes
  5134. '189': '45' //IE Key codes
  5135. }
  5136. var shiftUps = {
  5137. "96": "~",
  5138. "49": "!",
  5139. "50": "@",
  5140. "51": "#",
  5141. "52": "$",
  5142. "53": "%",
  5143. "54": "^",
  5144. "55": "&",
  5145. "56": "*",
  5146. "57": "(",
  5147. "48": ")",
  5148. "45": "_",
  5149. "61": "+",
  5150. "91": "{",
  5151. "93": "}",
  5152. "92": "|",
  5153. "59": ":",
  5154. "39": "\"",
  5155. "44": "<",
  5156. "46": ">",
  5157. "47": "?"
  5158. };
  5159. var c = e.which;
  5160. if (_to_ascii.hasOwnProperty(c)) {
  5161. c = _to_ascii[c];
  5162. }
  5163. if (!e.shiftKey && (c >= 65 && c <= 90)) {
  5164. c = String.fromCharCode(c + 32);
  5165. } else if (e.shiftKey && shiftUps.hasOwnProperty(c)) {
  5166. c = shiftUps[c];
  5167. } else if (96 <= c && c <= 105) {
  5168. c = String.fromCharCode(c - 48);
  5169. } else {
  5170. c = String.fromCharCode(c);
  5171. }
  5172. return c;
  5173. }
  5174. return obj;
  5175. })();
  5176. jSuites.mobile = (function(el, options) {
  5177. var obj = {};
  5178. obj.options = {};
  5179. if (jSuites.el) {
  5180. jSuites.el.addEventListener('mousedown', function(e) {
  5181. if (e.target.classList.contains('option-title')) {
  5182. if (e.target.classList.contains('selected')) {
  5183. e.target.classList.remove('selected');
  5184. } else {
  5185. e.target.classList.add('selected');
  5186. }
  5187. }
  5188. });
  5189. }
  5190. return obj;
  5191. })();
  5192. jSuites.pages = (function() {
  5193. var container = null;
  5194. var current = null;
  5195. // Create a page
  5196. var createPage = function(options, callback) {
  5197. // Create page
  5198. var page = document.createElement('div');
  5199. page.classList.add('page');
  5200. // Always hidden
  5201. page.style.display = 'none';
  5202. // Keep options
  5203. page.options = options ? options : {};
  5204. if (! current) {
  5205. container.appendChild(page);
  5206. } else {
  5207. container.insertBefore(page, current.nextSibling);
  5208. }
  5209. jSuites.ajax({
  5210. url: page.options.url,
  5211. method: 'GET',
  5212. success: function(result) {
  5213. // Push to refresh controls
  5214. jSuites.refresh(page, page.options.onpush);
  5215. // Open page
  5216. page.innerHTML = result;
  5217. // Get javascript
  5218. var script = page.getElementsByTagName('script');
  5219. // Run possible inline scripts
  5220. for (var i = 0; i < script.length; i++) {
  5221. // Get type
  5222. var type = script[i].getAttribute('type');
  5223. if (! type || type == 'text/javascript') {
  5224. eval(script[i].innerHTML);
  5225. }
  5226. }
  5227. // Set title
  5228. page.setTitle = function(text) {
  5229. this.children[0].children[0].children[1].innerHTML = text;
  5230. }
  5231. // Show page
  5232. if (! page.options.closed) {
  5233. showPage(page);
  5234. }
  5235. // Onload callback
  5236. if (typeof(page.options.onload) == 'function') {
  5237. page.options.onload(page);
  5238. }
  5239. // Force callback
  5240. if (typeof(callback) == 'function') {
  5241. callback(page);
  5242. }
  5243. }
  5244. });
  5245. return page;
  5246. }
  5247. var showPage = function(page, ignoreHistory, callback) {
  5248. if (current) {
  5249. if (current == page) {
  5250. current = page;
  5251. } else {
  5252. // Keep scroll in the top
  5253. window.scrollTo({ top: 0 });
  5254. // Show page
  5255. page.style.display = '';
  5256. var a = Array.prototype.indexOf.call(container.children, current);
  5257. var b = Array.prototype.indexOf.call(container.children, page);
  5258. // Leave
  5259. if (typeof(current.options.onleave) == 'function') {
  5260. current.options.onleave(current, page, ignoreHistory);
  5261. }
  5262. jSuites.slideLeft(container, (a < b ? 0 : 1), function() {
  5263. current.style.display = 'none';
  5264. current = page;
  5265. });
  5266. // Enter
  5267. if (typeof(page.options.onenter) == 'function') {
  5268. page.options.onenter(page, current, ignoreHistory);
  5269. }
  5270. }
  5271. } else {
  5272. // Show
  5273. page.style.display = '';
  5274. // Keep current
  5275. current = page;
  5276. // Enter
  5277. if (typeof(page.options.onenter) == 'function') {
  5278. page.options.onenter(page);
  5279. }
  5280. }
  5281. // Add history
  5282. if (! ignoreHistory) {
  5283. // Add history
  5284. window.history.pushState({ route: page.options.route }, page.options.title, page.options.route);
  5285. }
  5286. // Callback
  5287. if (typeof(callback) == 'function') {
  5288. callback(page);
  5289. }
  5290. }
  5291. // Init method
  5292. var obj = function(route, mixed) {
  5293. // Create page container
  5294. if (! container) {
  5295. container = document.querySelector('.pages');
  5296. if (! container) {
  5297. container = document.createElement('div');
  5298. container.className = 'pages';
  5299. }
  5300. // Append container to the application
  5301. if (jSuites.el) {
  5302. jSuites.el.appendChild(container);
  5303. } else {
  5304. document.body.appendChild(container);
  5305. }
  5306. }
  5307. if (! obj.pages[route]) {
  5308. if (! route) {
  5309. alert('Error, no route provided');
  5310. } else {
  5311. if (typeof(mixed) == 'function') {
  5312. var options = {};
  5313. var callback = mixed;
  5314. } else {
  5315. // Page options
  5316. var options = mixed ? mixed : {};
  5317. }
  5318. // Closed
  5319. options.closed = mixed && mixed.closed ? 1 : 0;
  5320. // Keep Route
  5321. options.route = route;
  5322. // New page url
  5323. if (! options.url) {
  5324. var routePath = route.split('#');
  5325. options.url = jSuites.pages.path + routePath[0] + '.html';
  5326. }
  5327. // Title
  5328. if (! options.title) {
  5329. options.title = 'Untitled';
  5330. }
  5331. // Create new page
  5332. obj.pages[route] = createPage(options, callback ? callback : null);
  5333. }
  5334. } else {
  5335. // Update config
  5336. if (mixed) {
  5337. // History
  5338. var ignoreHistory = 0;
  5339. if (typeof(mixed) == 'function') {
  5340. var callback = mixed;
  5341. } else {
  5342. if (typeof(mixed.onenter) == 'function') {
  5343. obj.pages[route].options.onenter = mixed.onenter;
  5344. }
  5345. if (typeof(mixed.onleave) == 'function') {
  5346. obj.pages[route].options.onleave = mixed.onleave;
  5347. }
  5348. // Ignore history
  5349. ignoreHistory = mixed.ignoreHistory ? 1 : 0;
  5350. }
  5351. }
  5352. showPage(obj.pages[route], ignoreHistory, callback ? callback : null);
  5353. }
  5354. }
  5355. obj.pages = {};
  5356. // Get page
  5357. obj.get = function(route) {
  5358. if (obj.pages[route]) {
  5359. return obj.pages[route];
  5360. }
  5361. }
  5362. obj.getContainer = function() {
  5363. return container;
  5364. }
  5365. obj.destroy = function() {
  5366. // Current is null
  5367. current = null;
  5368. // Destroy containers
  5369. obj.pages = {};
  5370. // Reset container
  5371. if (container) {
  5372. container.innerHTML = '';
  5373. }
  5374. }
  5375. return obj;
  5376. })();
  5377. // Path
  5378. jSuites.pages.path = 'pages';
  5379. // Panel
  5380. jSuites.panel = (function() {
  5381. // No initial panel declared
  5382. var panel = null;
  5383. var obj = function(route) {
  5384. if (! panel) {
  5385. obj.create(jSuites.pages.path + route + '.html');
  5386. }
  5387. // Show panel
  5388. panel.style.display = '';
  5389. // Add animation
  5390. if (panel.classList.contains('panel-left')) {
  5391. jSuites.slideLeft(panel, 1);
  5392. } else {
  5393. jSuites.slideRight(panel, 1);
  5394. }
  5395. }
  5396. obj.create = function(route) {
  5397. if (! panel) {
  5398. // Create element
  5399. panel = document.createElement('div');
  5400. panel.classList.add('panel');
  5401. panel.classList.add('panel-left');
  5402. panel.style.display = 'none';
  5403. // Bind to the app
  5404. if (jSuites.el) {
  5405. jSuites.el.appendChild(panel);
  5406. } else {
  5407. document.body.appendChild(panel);
  5408. }
  5409. }
  5410. // Remote content
  5411. if (route) {
  5412. var url = jSuites.pages.path + route + '.html';
  5413. jSuites.ajax({
  5414. url: url,
  5415. method: 'GET',
  5416. success: function(result) {
  5417. // Set content
  5418. panel.innerHTML = result;
  5419. // Get javascript
  5420. var script = panel.getElementsByTagName('script');
  5421. // Run possible inline scripts
  5422. for (var i = 0; i < script.length; i++) {
  5423. // Get type
  5424. var type = script[i].getAttribute('type');
  5425. if (! type || type == 'text/javascript') {
  5426. eval(script[i].innerHTML);
  5427. }
  5428. }
  5429. }
  5430. });
  5431. }
  5432. }
  5433. obj.close = function() {
  5434. if (panel) {
  5435. // Animation
  5436. if (panel.classList.contains('panel-left')) {
  5437. jSuites.slideLeft(panel, 0, function() {
  5438. panel.style.display = 'none';
  5439. });
  5440. } else {
  5441. jSuites.slideRight(panel, 0, function() {
  5442. panel.style.display = 'none';
  5443. });
  5444. }
  5445. }
  5446. }
  5447. obj.get = function() {
  5448. return panel;
  5449. }
  5450. obj.destroy = function() {
  5451. panel.remove();
  5452. panel = null;
  5453. }
  5454. return obj;
  5455. })();
  5456. jSuites.toolbar = (function(el, options) {
  5457. var obj = {};
  5458. obj.options = options;
  5459. obj.selectItem = function(element) {
  5460. var elements = toolbarContent.children;
  5461. for (var i = 0; i < elements.length; i++) {
  5462. elements[i].classList.remove('selected');
  5463. }
  5464. element.classList.add('selected');
  5465. }
  5466. obj.hide = function() {
  5467. jSuites.slideBottom(toolbar, 0, function() {
  5468. toolbar.style.display = 'none';
  5469. });
  5470. }
  5471. obj.show = function() {
  5472. toolbar.style.display = '';
  5473. jSuites.slideBottom(toolbar, 1);
  5474. }
  5475. obj.get = function() {
  5476. return toolbar;
  5477. }
  5478. obj.setBadge = function(index, value) {
  5479. toolbarContent.children[index].children[1].firstChild.innerHTML = value;
  5480. }
  5481. obj.destroy = function() {
  5482. toolbar.remove();
  5483. toolbar = null;
  5484. }
  5485. var toolbar = document.createElement('div');
  5486. toolbar.classList.add('jtoolbar');
  5487. toolbar.onclick = function(e) {
  5488. var element = jSuites.getElement(e.target, 'jtoolbar-item');
  5489. if (element) {
  5490. obj.selectItem(element);
  5491. }
  5492. }
  5493. var toolbarContent = document.createElement('div');
  5494. toolbar.appendChild(toolbarContent);
  5495. for (var i = 0; i < options.items.length; i++) {
  5496. var toolbarItem = document.createElement('div');
  5497. toolbarItem.classList.add('jtoolbar-item');
  5498. if (options.items[i].route) {
  5499. toolbarItem.setAttribute('data-href', options.items[i].route);
  5500. jSuites.pages(options.items[i].route, {
  5501. closed: true,
  5502. onenter: function() {
  5503. obj.selectItem(toolbarItem);
  5504. }
  5505. });
  5506. }
  5507. if (options.items[i].icon) {
  5508. var toolbarIcon = document.createElement('i');
  5509. toolbarIcon.classList.add('material-icons');
  5510. toolbarIcon.innerHTML = options.items[i].icon;
  5511. toolbarItem.appendChild(toolbarIcon);
  5512. }
  5513. var toolbarBadge = document.createElement('div');
  5514. toolbarBadge.classList.add('jbadge');
  5515. var toolbarBadgeContent = document.createElement('div');
  5516. toolbarBadgeContent.innerHTML = options.items[i].badge ? options.items[i].badge : '';
  5517. toolbarBadge.appendChild(toolbarBadgeContent);
  5518. toolbarItem.appendChild(toolbarBadge);
  5519. if (options.items[i].title) {
  5520. var toolbarTitle = document.createElement('span');
  5521. toolbarTitle.innerHTML = options.items[i].title;
  5522. toolbarItem.appendChild(toolbarTitle);
  5523. }
  5524. toolbarContent.appendChild(toolbarItem);
  5525. }
  5526. el.toolbar = obj;
  5527. el.appendChild(toolbar);
  5528. return obj;
  5529. });
  5530. jSuites.actionsheet = (function() {
  5531. var actionsheet = document.createElement('div');
  5532. actionsheet.className = 'jactionsheet';
  5533. actionsheet.style.display = 'none';
  5534. var actionContent = document.createElement('div');
  5535. actionContent.className = 'jactionsheet-content';
  5536. actionsheet.appendChild(actionContent);
  5537. var obj = function(options) {
  5538. if (options) {
  5539. obj.options = options;
  5540. }
  5541. // Reset container
  5542. actionContent.innerHTML = '';
  5543. // Create new elements
  5544. for (var i = 0; i < obj.options.length; i++) {
  5545. var actionGroup = document.createElement('div');
  5546. actionGroup.className = 'jactionsheet-group';
  5547. for (var j = 0; j < obj.options[i].length; j++) {
  5548. var v = obj.options[i][j];
  5549. var actionItem = document.createElement('div');
  5550. var actionInput = document.createElement('input');
  5551. actionInput.type = 'button';
  5552. actionInput.value = v.title;
  5553. if (v.className) {
  5554. actionInput.className = v.className;
  5555. }
  5556. if (v.onclick) {
  5557. actionInput.onclick = v.onclick;
  5558. }
  5559. if (v.action == 'cancel') {
  5560. actionInput.style.color = 'red';
  5561. }
  5562. actionItem.appendChild(actionInput);
  5563. actionGroup.appendChild(actionItem);
  5564. }
  5565. actionContent.appendChild(actionGroup);
  5566. }
  5567. // Show
  5568. actionsheet.style.display = '';
  5569. // Append
  5570. jSuites.el.appendChild(actionsheet);
  5571. // Animation
  5572. jSuites.slideBottom(actionContent, true);
  5573. }
  5574. obj.close = function() {
  5575. if (actionsheet.style.display != 'none') {
  5576. // Remove any existing actionsheet
  5577. jSuites.slideBottom(actionContent, false, function() {
  5578. actionsheet.remove();
  5579. actionsheet.style.display = 'none';
  5580. });
  5581. }
  5582. }
  5583. var mouseUp = function(e) {
  5584. obj.close();
  5585. }
  5586. actionsheet.addEventListener('mouseup', mouseUp);
  5587. obj.options = {};
  5588. return obj;
  5589. })();
  5590. /**
  5591. * (c) jSuites modal
  5592. * https://github.com/paulhodel/jsuites
  5593. *
  5594. * @author: Paul Hodel <paul.hodel@gmail.com>
  5595. * @description: Modal
  5596. */
  5597. jSuites.modal = (function(el, options) {
  5598. var obj = {};
  5599. obj.options = {};
  5600. // Default configuration
  5601. var defaults = {
  5602. url: null,
  5603. onopen: null,
  5604. onclose: null,
  5605. closed: false,
  5606. width: null,
  5607. height: null,
  5608. title: null,
  5609. };
  5610. // Loop through our object
  5611. for (var property in defaults) {
  5612. if (options && options.hasOwnProperty(property)) {
  5613. obj.options[property] = options[property];
  5614. } else {
  5615. obj.options[property] = defaults[property];
  5616. }
  5617. }
  5618. // Title
  5619. if (! obj.options.title && el.getAttribute('title')) {
  5620. obj.options.title = el.getAttribute('title');
  5621. }
  5622. var temp = document.createElement('div');
  5623. for (var i = 0; i < el.children.length; i++) {
  5624. temp.appendChild(el.children[i]);
  5625. }
  5626. obj.content = document.createElement('div');
  5627. obj.content.className = 'jmodal_content';
  5628. obj.content.innerHTML = el.innerHTML;
  5629. for (var i = 0; i < temp.children.length; i++) {
  5630. obj.content.appendChild(temp.children[i]);
  5631. }
  5632. obj.container = document.createElement('div');
  5633. obj.container.className = 'jmodal';
  5634. obj.container.appendChild(obj.content);
  5635. if (obj.options.width) {
  5636. obj.container.style.width = obj.options.width;
  5637. }
  5638. if (obj.options.height) {
  5639. obj.container.style.height = obj.options.height;
  5640. }
  5641. if (obj.options.title) {
  5642. obj.container.setAttribute('title', obj.options.title);
  5643. } else {
  5644. obj.container.classList.add('no-title');
  5645. }
  5646. el.innerHTML = '';
  5647. el.style.display = 'none';
  5648. el.appendChild(obj.container);
  5649. // Backdrop
  5650. var backdrop = document.createElement('div');
  5651. backdrop.className = 'jmodal_backdrop';
  5652. el.appendChild(backdrop);
  5653. obj.open = function() {
  5654. el.style.display = 'block';
  5655. // Fullscreen
  5656. const rect = obj.container.getBoundingClientRect();
  5657. if (jSuites.getWindowWidth() < rect.width) {
  5658. obj.container.style.top = '';
  5659. obj.container.style.left = '';
  5660. obj.container.classList.add('jmodal_fullscreen');
  5661. jSuites.slideBottom(obj.container, 1);
  5662. } else {
  5663. backdrop.style.display = 'block';
  5664. }
  5665. // Current
  5666. jSuites.modal.current = obj;
  5667. // Event
  5668. if (typeof(obj.options.onopen) == 'function') {
  5669. obj.options.onopen(el, obj);
  5670. }
  5671. }
  5672. obj.resetPosition = function() {
  5673. obj.container.style.top = '';
  5674. obj.container.style.left = '';
  5675. }
  5676. obj.isOpen = function() {
  5677. return el.style.display != 'none' ? true : false;
  5678. }
  5679. obj.close = function() {
  5680. el.style.display = 'none';
  5681. // Backdrop
  5682. backdrop.style.display = '';
  5683. // Current
  5684. jSuites.modal.current = null;
  5685. // Remove fullscreen class
  5686. obj.container.classList.remove('jmodal_fullscreen');
  5687. // Event
  5688. if (typeof(obj.options.onclose) == 'function') {
  5689. obj.options.onclose(el, obj);
  5690. }
  5691. }
  5692. if (! jSuites.modal.hasEvents) {
  5693. jSuites.modal.current = obj;
  5694. if ('ontouchstart' in document.documentElement === true) {
  5695. document.addEventListener("touchstart", jSuites.modal.mouseDownControls);
  5696. } else {
  5697. document.addEventListener('mousedown', jSuites.modal.mouseDownControls);
  5698. document.addEventListener('mousemove', jSuites.modal.mouseMoveControls);
  5699. document.addEventListener('mouseup', jSuites.modal.mouseUpControls);
  5700. }
  5701. document.addEventListener('keydown', jSuites.modal.keyDownControls);
  5702. jSuites.modal.hasEvents = true;
  5703. }
  5704. if (obj.options.url) {
  5705. jSuites.ajax({
  5706. url: obj.options.url,
  5707. method: 'GET',
  5708. success: function(data) {
  5709. obj.content.innerHTML = data;
  5710. if (! obj.options.closed) {
  5711. obj.open();
  5712. }
  5713. }
  5714. });
  5715. } else {
  5716. if (! obj.options.closed) {
  5717. obj.open();
  5718. }
  5719. }
  5720. // Keep object available from the node
  5721. el.modal = obj;
  5722. return obj;
  5723. });
  5724. jSuites.modal.current = null;
  5725. jSuites.modal.position = null;
  5726. jSuites.modal.keyDownControls = function(e) {
  5727. if (e.which == 27) {
  5728. if (jSuites.modal.current) {
  5729. jSuites.modal.current.close();
  5730. }
  5731. }
  5732. }
  5733. jSuites.modal.mouseUpControls = function(e) {
  5734. if (jSuites.modal.current) {
  5735. jSuites.modal.current.container.style.cursor = 'auto';
  5736. }
  5737. jSuites.modal.position = null;
  5738. }
  5739. jSuites.modal.mouseMoveControls = function(e) {
  5740. if (jSuites.modal.current && jSuites.modal.position) {
  5741. if (e.which == 1 || e.which == 3) {
  5742. var position = jSuites.modal.position;
  5743. jSuites.modal.current.container.style.top = (position[1] + (e.clientY - position[3]) + (position[5] / 2)) + 'px';
  5744. jSuites.modal.current.container.style.left = (position[0] + (e.clientX - position[2]) + (position[4] / 2)) + 'px';
  5745. jSuites.modal.current.container.style.cursor = 'move';
  5746. } else {
  5747. jSuites.modal.current.container.style.cursor = 'auto';
  5748. }
  5749. }
  5750. }
  5751. jSuites.modal.mouseDownControls = function(e) {
  5752. jSuites.modal.position = [];
  5753. if (e.target.classList.contains('jmodal')) {
  5754. setTimeout(function() {
  5755. // Get target info
  5756. var rect = e.target.getBoundingClientRect();
  5757. if (e.changedTouches && e.changedTouches[0]) {
  5758. var x = e.changedTouches[0].clientX;
  5759. var y = e.changedTouches[0].clientY;
  5760. } else {
  5761. var x = e.clientX;
  5762. var y = e.clientY;
  5763. }
  5764. if (rect.width - (x - rect.left) < 50 && (y - rect.top) < 50) {
  5765. setTimeout(function() {
  5766. jSuites.modal.current.close();
  5767. }, 100);
  5768. } else {
  5769. if (e.target.getAttribute('title') && (y - rect.top) < 50) {
  5770. if (document.selection) {
  5771. document.selection.empty();
  5772. } else if ( window.getSelection ) {
  5773. window.getSelection().removeAllRanges();
  5774. }
  5775. jSuites.modal.position = [
  5776. rect.left,
  5777. rect.top,
  5778. e.clientX,
  5779. e.clientY,
  5780. rect.width,
  5781. rect.height,
  5782. ];
  5783. }
  5784. }
  5785. }, 100);
  5786. }
  5787. }
  5788. jSuites.notification = (function(options) {
  5789. var obj = {};
  5790. obj.options = {};
  5791. // Default configuration
  5792. var defaults = {
  5793. icon: null,
  5794. name: 'Notification',
  5795. date: null,
  5796. title: null,
  5797. message: null,
  5798. timeout: 4000,
  5799. autoHide: true,
  5800. closeable: true,
  5801. };
  5802. // Loop through our object
  5803. for (var property in defaults) {
  5804. if (options && options.hasOwnProperty(property)) {
  5805. obj.options[property] = options[property];
  5806. } else {
  5807. obj.options[property] = defaults[property];
  5808. }
  5809. }
  5810. var notification = document.createElement('div');
  5811. notification.className = 'jnotification';
  5812. var notificationContainer = document.createElement('div');
  5813. notificationContainer.className = 'jnotification-container';
  5814. notification.appendChild(notificationContainer);
  5815. var notificationHeader = document.createElement('div');
  5816. notificationHeader.className = 'jnotification-header';
  5817. notificationContainer.appendChild(notificationHeader);
  5818. var notificationImage = document.createElement('div');
  5819. notificationImage.className = 'jnotification-image';
  5820. notificationHeader.appendChild(notificationImage);
  5821. if (obj.options.icon) {
  5822. var notificationIcon = document.createElement('img');
  5823. notificationIcon.src = obj.options.icon;
  5824. notificationImage.appendChild(notificationIcon);
  5825. }
  5826. var notificationName = document.createElement('div');
  5827. notificationName.className = 'jnotification-name';
  5828. notificationName.innerHTML = obj.options.name;
  5829. notificationHeader.appendChild(notificationName);
  5830. if (obj.options.closeable == true) {
  5831. var notificationClose = document.createElement('div');
  5832. notificationClose.className = 'jnotification-close';
  5833. notificationClose.onclick = function() {
  5834. obj.hide();
  5835. }
  5836. notificationHeader.appendChild(notificationClose);
  5837. }
  5838. var notificationDate = document.createElement('div');
  5839. notificationDate.className = 'jnotification-date';
  5840. notificationHeader.appendChild(notificationDate);
  5841. var notificationContent = document.createElement('div');
  5842. notificationContent.className = 'jnotification-content';
  5843. notificationContainer.appendChild(notificationContent);
  5844. if (obj.options.title) {
  5845. var notificationTitle = document.createElement('div');
  5846. notificationTitle.className = 'jnotification-title';
  5847. notificationTitle.innerHTML = obj.options.title;
  5848. notificationContent.appendChild(notificationTitle);
  5849. }
  5850. var notificationMessage = document.createElement('div');
  5851. notificationMessage.className = 'jnotification-message';
  5852. notificationMessage.innerHTML = obj.options.message;
  5853. notificationContent.appendChild(notificationMessage);
  5854. obj.show = function() {
  5855. document.body.appendChild(notification);
  5856. if (jSuites.getWindowWidth() > 800) {
  5857. jSuites.fadeIn(notification);
  5858. } else {
  5859. jSuites.slideTop(notification, 1);
  5860. }
  5861. }
  5862. obj.hide = function() {
  5863. if (jSuites.getWindowWidth() > 800) {
  5864. jSuites.fadeOut(notification, function() {
  5865. notification.parentNode.removeChild(notification);
  5866. });
  5867. } else {
  5868. jSuites.slideTop(notification, 0, function() {
  5869. notification.parentNode.removeChild(notification);
  5870. });
  5871. }
  5872. };
  5873. obj.show();
  5874. if (obj.options.autoHide == true) {
  5875. setTimeout(function() {
  5876. obj.hide();
  5877. }, obj.options.timeout);
  5878. }
  5879. if (jSuites.getWindowWidth() < 800) {
  5880. notification.addEventListener("swipeup", function(e) {
  5881. obj.hide();
  5882. e.preventDefault();
  5883. e.stopPropagation();
  5884. });
  5885. }
  5886. return obj;
  5887. });
  5888. jSuites.rating = (function(el, options) {
  5889. var obj = {};
  5890. obj.options = {};
  5891. // Default configuration
  5892. var defaults = {
  5893. number: 5,
  5894. value: 0,
  5895. tooltip: [ 'Very bad', 'Bad', 'Average', 'Good', 'Very good' ],
  5896. onchange: null,
  5897. };
  5898. // Loop through the initial configuration
  5899. for (var property in defaults) {
  5900. if (options && options.hasOwnProperty(property)) {
  5901. obj.options[property] = options[property];
  5902. } else {
  5903. obj.options[property] = defaults[property];
  5904. }
  5905. }
  5906. // Class
  5907. el.classList.add('jrating');
  5908. // Add elements
  5909. for (var i = 0; i < obj.options.number; i++) {
  5910. var div = document.createElement('div');
  5911. div.setAttribute('data-index', (i + 1))
  5912. div.setAttribute('title', obj.options.tooltip[i])
  5913. el.appendChild(div);
  5914. }
  5915. // Set value
  5916. obj.setValue = function(index) {
  5917. for (var i = 0; i < obj.options.number; i++) {
  5918. if (i < index) {
  5919. el.children[i].classList.add('jrating-selected');
  5920. } else {
  5921. el.children[i].classList.remove('jrating-over');
  5922. el.children[i].classList.remove('jrating-selected');
  5923. }
  5924. }
  5925. obj.options.value = index;
  5926. if (typeof(obj.options.onchange) == 'function') {
  5927. obj.options.onchange(el, index);
  5928. }
  5929. }
  5930. obj.getValue = function() {
  5931. return obj.options.value;
  5932. }
  5933. if (obj.options.value) {
  5934. for (var i = 0; i < obj.options.number; i++) {
  5935. if (i < obj.options.value) {
  5936. el.children[i].classList.add('jrating-selected');
  5937. }
  5938. }
  5939. }
  5940. // Events
  5941. el.addEventListener("click", function(e) {
  5942. var index = e.target.getAttribute('data-index');
  5943. if (index != undefined) {
  5944. if (index == obj.options.value) {
  5945. obj.setValue(0);
  5946. } else {
  5947. obj.setValue(index);
  5948. }
  5949. }
  5950. });
  5951. el.addEventListener("mouseover", function(e) {
  5952. var index = e.target.getAttribute('data-index');
  5953. for (var i = 0; i < obj.options.number; i++) {
  5954. if (i < index) {
  5955. el.children[i].classList.add('jrating-over');
  5956. } else {
  5957. el.children[i].classList.remove('jrating-over');
  5958. }
  5959. }
  5960. });
  5961. el.addEventListener("mouseout", function(e) {
  5962. for (var i = 0; i < obj.options.number; i++) {
  5963. el.children[i].classList.remove('jrating-over');
  5964. }
  5965. });
  5966. el.rating = obj;
  5967. return obj;
  5968. });
  5969. /**
  5970. * (c) Image slider
  5971. * https://github.com/paulhodel/jtools
  5972. *
  5973. * @author: Paul Hodel <paul.hodel@gmail.com>
  5974. * @description: Image Slider
  5975. */
  5976. jSuites.slider = (function(el, options) {
  5977. var obj = {};
  5978. obj.options = {};
  5979. obj.currentImage = null;
  5980. if (options) {
  5981. obj.options = options;
  5982. }
  5983. // Items
  5984. obj.options.items = [];
  5985. if (! el.classList.contains('jslider')) {
  5986. el.classList.add('jslider');
  5987. // Create container
  5988. var container = document.createElement('div');
  5989. container.className = 'jslider-container';
  5990. // Move children inside
  5991. if (el.children.length > 0) {
  5992. // Keep children items
  5993. for (var i = 0; i < el.children.length; i++) {
  5994. obj.options.items.push(el.children[i]);
  5995. }
  5996. }
  5997. if (obj.options.items.length > 0) {
  5998. for (var i = 0; i < obj.options.items.length; i++) {
  5999. obj.options.items[i].classList.add('jfile');
  6000. var index = obj.options.items[i].src.lastIndexOf('/');
  6001. if (index < 0) {
  6002. obj.options.items[i].setAttribute('data-name', obj.options.items[i].src);
  6003. } else {
  6004. obj.options.items[i].setAttribute('data-name', obj.options.items[i].src.substr(index + 1));
  6005. }
  6006. var index = obj.options.items[i].src.lastIndexOf('/');
  6007. container.appendChild(obj.options.items[i]);
  6008. }
  6009. }
  6010. el.appendChild(container);
  6011. // Add close buttom
  6012. var close = document.createElement('div');
  6013. close.className = 'jslider-close';
  6014. close.innerHTML = '';
  6015. close.onclick = function() {
  6016. obj.close();
  6017. }
  6018. el.appendChild(close);
  6019. } else {
  6020. var container = el.querySelector('slider-container');
  6021. }
  6022. obj.show = function(target) {
  6023. if (! target) {
  6024. var target = container.children[0];
  6025. }
  6026. if (! container.classList.contains('jslider-preview')) {
  6027. container.classList.add('jslider-preview');
  6028. close.style.display = 'block';
  6029. }
  6030. // Hide all images
  6031. for (var i = 0; i < container.children.length; i++) {
  6032. container.children[i].style.display = 'none';
  6033. }
  6034. // Show clicked only
  6035. target.style.display = 'block';
  6036. // Is there any previous
  6037. if (target.previousSibling) {
  6038. container.classList.add('jslider-left');
  6039. } else {
  6040. container.classList.remove('jslider-left');
  6041. }
  6042. // Is there any next
  6043. if (target.nextSibling) {
  6044. container.classList.add('jslider-right');
  6045. } else {
  6046. container.classList.remove('jslider-right');
  6047. }
  6048. obj.currentImage = target;
  6049. }
  6050. obj.open = function() {
  6051. obj.show();
  6052. // Event
  6053. if (typeof(obj.options.onopen) == 'function') {
  6054. obj.options.onopen(el);
  6055. }
  6056. }
  6057. obj.close = function() {
  6058. container.classList.remove('jslider-preview');
  6059. container.classList.remove('jslider-left');
  6060. container.classList.remove('jslider-right');
  6061. for (var i = 0; i < container.children.length; i++) {
  6062. container.children[i].style.display = '';
  6063. }
  6064. close.style.display = '';
  6065. obj.currentImage = null;
  6066. // Event
  6067. if (typeof(obj.options.onclose) == 'function') {
  6068. obj.options.onclose(el);
  6069. }
  6070. }
  6071. obj.reset = function() {
  6072. container.innerHTML = '';
  6073. }
  6074. obj.addFile = function(v, ignoreEvents) {
  6075. var img = document.createElement('img');
  6076. img.setAttribute('data-lastmodified', v.lastmodified);
  6077. img.setAttribute('data-name', v.name);
  6078. img.setAttribute('data-size', v.size);
  6079. img.setAttribute('data-extension', v.extension);
  6080. img.setAttribute('data-cover', v.cover);
  6081. img.setAttribute('src', v.file);
  6082. img.className = 'jfile';
  6083. container.appendChild(img);
  6084. obj.options.items.push(img);
  6085. // Onchange
  6086. if (! ignoreEvents) {
  6087. if (typeof(obj.options.onchange) == 'function') {
  6088. obj.options.onchange(el, v);
  6089. }
  6090. }
  6091. }
  6092. obj.addFiles = function(files) {
  6093. for (var i = 0; i < files.length; i++) {
  6094. obj.addFile(files[i]);
  6095. }
  6096. }
  6097. obj.next = function() {
  6098. if (obj.currentImage.nextSibling) {
  6099. obj.show(obj.currentImage.nextSibling);
  6100. }
  6101. }
  6102. obj.prev = function() {
  6103. if (obj.currentImage.previousSibling) {
  6104. obj.show(obj.currentImage.previousSibling);
  6105. }
  6106. }
  6107. obj.getData = function() {
  6108. return jSuites.getFiles(container);
  6109. }
  6110. // Append data
  6111. if (obj.options.data && obj.options.data.length) {
  6112. for (var i = 0; i < obj.options.data.length; i++) {
  6113. if (obj.options.data[i]) {
  6114. obj.addFile(obj.options.data[i]);
  6115. }
  6116. }
  6117. }
  6118. // Allow insert
  6119. if (obj.options.allowAttachment) {
  6120. var attachmentInput = document.createElement('input');
  6121. attachmentInput.type = 'file';
  6122. attachmentInput.className = 'slider-attachment';
  6123. attachmentInput.setAttribute('accept', 'image/*');
  6124. attachmentInput.style.display = 'none';
  6125. attachmentInput.onchange = function() {
  6126. var reader = [];
  6127. for (var i = 0; i < this.files.length; i++) {
  6128. var type = this.files[i].type.split('/');
  6129. if (type[0] == 'image') {
  6130. var extension = this.files[i].name;
  6131. extension = extension.split('.');
  6132. extension = extension[extension.length-1];
  6133. var file = {
  6134. size: this.files[i].size,
  6135. name: this.files[i].name,
  6136. extension: extension,
  6137. cover: 0,
  6138. lastmodified: this.files[i].lastModified,
  6139. }
  6140. reader[i] = new FileReader();
  6141. reader[i].addEventListener("load", function (e) {
  6142. file.file = e.target.result;
  6143. obj.addFile(file);
  6144. }, false);
  6145. reader[i].readAsDataURL(this.files[i]);
  6146. } else {
  6147. alert('The extension is not allowed');
  6148. }
  6149. };
  6150. }
  6151. var attachmentIcon = document.createElement('i');
  6152. attachmentIcon.innerHTML = 'attachment';
  6153. attachmentIcon.className = 'jslider-attach material-icons';
  6154. attachmentIcon.onclick = function() {
  6155. jSuites.click(attachmentInput);
  6156. }
  6157. el.appendChild(attachmentInput);
  6158. el.appendChild(attachmentIcon);
  6159. }
  6160. // Push to refresh
  6161. var longTouchTimer = null;
  6162. var mouseDown = function(e) {
  6163. if (e.target.tagName == 'IMG') {
  6164. // Remove
  6165. var targetImage = e.target;
  6166. longTouchTimer = setTimeout(function() {
  6167. if (e.target.src.substr(0,4) == 'data') {
  6168. e.target.remove();
  6169. } else {
  6170. if (e.target.classList.contains('jremove')) {
  6171. e.target.classList.remove('jremove');
  6172. } else {
  6173. e.target.classList.add('jremove');
  6174. }
  6175. }
  6176. // Onchange
  6177. if (typeof(obj.options.onchange) == 'function') {
  6178. obj.options.onchange(el, e.target);
  6179. }
  6180. }, 1000);
  6181. }
  6182. }
  6183. var mouseUp = function(e) {
  6184. if (longTouchTimer) {
  6185. clearTimeout(longTouchTimer);
  6186. }
  6187. // Open slider
  6188. if (e.target.tagName == 'IMG') {
  6189. if (! e.target.classList.contains('jremove')) {
  6190. obj.show(e.target);
  6191. }
  6192. } else {
  6193. // Arrow controls
  6194. if (e.target.clientWidth - e.offsetX < 40) {
  6195. // Show next image
  6196. obj.next();
  6197. } else if (e.offsetX < 40) {
  6198. // Show previous image
  6199. obj.prev();
  6200. }
  6201. }
  6202. }
  6203. container.addEventListener('mousedown', mouseDown);
  6204. container.addEventListener('touchstart', mouseDown);
  6205. container.addEventListener('mouseup', mouseUp);
  6206. container.addEventListener('touchend', mouseUp);
  6207. // Add global events
  6208. el.addEventListener("swipeleft", function(e) {
  6209. obj.next();
  6210. e.preventDefault();
  6211. e.stopPropagation();
  6212. });
  6213. el.addEventListener("swiperight", function(e) {
  6214. obj.prev();
  6215. e.preventDefault();
  6216. e.stopPropagation();
  6217. });
  6218. el.slider = obj;
  6219. return obj;
  6220. });
  6221. /**
  6222. * (c) jTools v1.0.1 - Element sorting
  6223. * https://github.com/paulhodel/jtools
  6224. *
  6225. * @author: Paul Hodel <paul.hodel@gmail.com>
  6226. * @description: Element drag and drop sorting
  6227. */
  6228. jSuites.sorting = (function(el, options) {
  6229. el.classList.add('jsorting');
  6230. el.addEventListener('dragstart', function(e) {
  6231. e.target.classList.add('dragging');
  6232. });
  6233. el.addEventListener('dragover', function(e) {
  6234. e.preventDefault();
  6235. if (e.target.clientHeight / 2 > e.offsetY) {
  6236. e.path[0].style.borderTop = '1px dotted #ccc';
  6237. e.path[0].style.borderBottom = '';
  6238. } else {
  6239. e.path[0].style.borderTop = '';
  6240. e.path[0].style.borderBottom = '1px dotted #ccc';
  6241. }
  6242. });
  6243. el.addEventListener('dragleave', function(e) {
  6244. e.path[0].style.borderTop = '';
  6245. e.path[0].style.borderBottom = '';
  6246. });
  6247. el.addEventListener('dragend', function(e) {
  6248. e.path[1].querySelector('.dragging').classList.remove('dragging');
  6249. });
  6250. el.addEventListener('drop', function(e) {
  6251. var element = e.path[1].querySelector('.dragging');
  6252. if (e.target.clientHeight / 2 > e.offsetY) {
  6253. e.path[1].insertBefore(element, e.path[0]);
  6254. } else {
  6255. e.path[1].insertBefore(element, e.path[0].nextSibling);
  6256. }
  6257. e.path[0].style.borderTop = '';
  6258. e.path[0].style.borderBottom = '';
  6259. });
  6260. for (var i = 0; i < el.children.length; i++) {
  6261. el.children[i].setAttribute('draggable', 'true');
  6262. };
  6263. return el;
  6264. });
  6265. jSuites.tabs = (function(el, options) {
  6266. var obj = {};
  6267. obj.options = {};
  6268. // Default configuration
  6269. var defaults = {
  6270. data: null,
  6271. onchange: null,
  6272. onload: null,
  6273. };
  6274. // Loop through the initial configuration
  6275. for (var property in defaults) {
  6276. if (options && options.hasOwnProperty(property)) {
  6277. obj.options[property] = options[property];
  6278. } else {
  6279. obj.options[property] = defaults[property];
  6280. }
  6281. }
  6282. // Class
  6283. el.classList.add('jtabs');
  6284. // Create from data
  6285. if (obj.options.data) {
  6286. // Make sure the component is blank
  6287. el.innerHTML = '';
  6288. var headers = document.createElement('div');
  6289. var content = document.createElement('div');
  6290. headers.classList.add('jtabs-headers');
  6291. content.classList.add('jtabs-content');
  6292. el.appendChild(headers);
  6293. el.appendChild(content);
  6294. for (var i = 0; i < obj.options.data.length; i++) {
  6295. var headersItem = document.createElement('div');
  6296. headers.appendChild(headersItem);
  6297. var contentItem = document.createElement('div');
  6298. content.appendChild(contentItem);
  6299. headersItem.innerHTML = obj.options.data[i].title;
  6300. if (obj.options.data[i].content) {
  6301. contentItem.innerHTML = obj.options.data[i].content;
  6302. } else if (obj.options.data[i].url) {
  6303. jSuites.ajax({
  6304. url: obj.options.data[i].url,
  6305. type: 'GET',
  6306. success: function(result) {
  6307. contentItem.innerHTML = result;
  6308. },
  6309. complete: function() {
  6310. if (typeof(obj.options.onload) == 'function') {
  6311. obj.options.onload(el);
  6312. }
  6313. }
  6314. });
  6315. }
  6316. }
  6317. } else if (el.children[0] && el.children[1]) {
  6318. // Create from existing elements
  6319. var headers = el.children[0];
  6320. var content = el.children[1];
  6321. headers.classList.add('jtabs-headers');
  6322. content.classList.add('jtabs-content');
  6323. }
  6324. // Border
  6325. var border = document.createElement('div');
  6326. border.className = 'jtabs-border';
  6327. el.appendChild(border);
  6328. var setBorder = function(index) {
  6329. var rect = headers.children[index].getBoundingClientRect();
  6330. border.style.width = rect.width + 'px';
  6331. border.style.top = rect.top + rect.height - 2 + 'px';
  6332. border.style.left = rect.left + 'px';
  6333. }
  6334. // Set value
  6335. obj.open = function(index) {
  6336. for (var i = 0; i < headers.children.length; i++) {
  6337. headers.children[i].classList.remove('jtabs-selected');
  6338. if (content.children[i]) {
  6339. content.children[i].classList.remove('jtabs-selected');
  6340. }
  6341. }
  6342. headers.children[index].classList.add('jtabs-selected');
  6343. if (content.children[index]) {
  6344. content.children[index].classList.add('jtabs-selected');
  6345. }
  6346. // Set border
  6347. setTimeout(function() {
  6348. setBorder(index);
  6349. }, 10);
  6350. }
  6351. // Events
  6352. headers.addEventListener("click", function(e) {
  6353. var index = Array.prototype.indexOf.call(headers.children, e.target);
  6354. if (index >= 0) {
  6355. obj.open(index);
  6356. }
  6357. });
  6358. obj.open(0);
  6359. el.tabs = obj;
  6360. return obj;
  6361. });
  6362. jSuites.tags = (function(el, options) {
  6363. var obj = {};
  6364. obj.options = {};
  6365. /**
  6366. * @typedef {Object} defaults
  6367. * @property {(string|Array)} value - Initial value of the compontent
  6368. * @property {number} limit - Max number of tags inside the element
  6369. * @property {string} search - The URL for suggestions
  6370. * @property {string} placeholder - The default instruction text on the element
  6371. * @property {validation} validation - Method to validate the tags
  6372. * @property {requestCallback} onbeforechange - Method to be execute before any changes on the element
  6373. * @property {requestCallback} onchange - Method to be execute after any changes on the element
  6374. * @property {requestCallback} onfocus - Method to be execute when on focus
  6375. * @property {requestCallback} onblur - Method to be execute when on blur
  6376. * @property {requestCallback} onload - Method to be execute when the element is loaded
  6377. */
  6378. var defaults = {
  6379. value: null,
  6380. limit: null,
  6381. search: null,
  6382. placeholder: null,
  6383. validation: null,
  6384. onbeforechange: null,
  6385. onchange: null,
  6386. onfocus: null,
  6387. onblur: null,
  6388. onload: null,
  6389. colors: null,
  6390. };
  6391. // Loop through though the default configuration
  6392. for (var property in defaults) {
  6393. if (options && options.hasOwnProperty(property)) {
  6394. obj.options[property] = options[property];
  6395. } else {
  6396. obj.options[property] = defaults[property];
  6397. }
  6398. }
  6399. // Search helpers
  6400. var searchContainer = null;
  6401. var searchTerms = null;
  6402. var searchIndex = 0;
  6403. var searchTimer = 0;
  6404. /**
  6405. * Add a new tag to the element
  6406. * @param {(?string|Array)} value - The value of the new element
  6407. */
  6408. obj.add = function(value) {
  6409. if (typeof(obj.options.onbeforechange) == 'function') {
  6410. var v = obj.options.onbeforechange(el, obj, value);
  6411. if (v != null) {
  6412. value = v;
  6413. }
  6414. }
  6415. // Close search
  6416. if (searchContainer) {
  6417. searchContainer.style.display = '';
  6418. }
  6419. // Get node
  6420. var node = getSelectionStart();
  6421. // Mix argument string or array
  6422. if (! value || typeof(value) == 'string') {
  6423. var div = document.createElement('div');
  6424. div.innerHTML = value ? value : '<br>';
  6425. if (node && node.parentNode.classList.contains('jtags')) {
  6426. el.insertBefore(div, node.nextSibling);
  6427. } else {
  6428. el.appendChild(div);
  6429. }
  6430. } else {
  6431. if (node && node.parentNode.classList.contains('jtags')) {
  6432. if (! node.innerText.replace("\n", "")) {
  6433. el.removeChild(node);
  6434. }
  6435. }
  6436. for (var i = 0; i < value.length; i++) {
  6437. var div = document.createElement('div');
  6438. div.innerHTML = value[i] ? value[i] : '<br>';
  6439. el.appendChild(div);
  6440. };
  6441. var div = document.createElement('div');
  6442. div.innerHTML = '<br>';
  6443. el.appendChild(div);
  6444. }
  6445. // Place caret
  6446. setTimeout(function() {
  6447. caret(div);
  6448. }, 0);
  6449. // Filter
  6450. filter();
  6451. if (typeof(obj.options.onchange) == 'function') {
  6452. obj.options.onchange(el, obj, value ? value : '');
  6453. }
  6454. }
  6455. /**
  6456. * Get all tags in the element
  6457. * @return {Array} data - All tags as an array
  6458. */
  6459. obj.getData = function() {
  6460. var data = [];
  6461. for (var i = 0; i < el.children.length; i++) {
  6462. var value = obj.getValue(i);
  6463. if (value) {
  6464. var id = el.children[i].getAttribute('data-id');
  6465. if (! id) {
  6466. id = value;
  6467. }
  6468. data.push({ id: id, value: value });
  6469. }
  6470. }
  6471. return data;
  6472. }
  6473. /**
  6474. * Get the value of one tag. Null for all tags
  6475. * @param {?number} index - Tag index number. Null for all tags.
  6476. * @return {string} value - All tags separated by comma
  6477. */
  6478. obj.getValue = function(index) {
  6479. var value = null;
  6480. if (index != null) {
  6481. // Get one individual value
  6482. value = el.children[index].innerText.replace("\n", "");
  6483. } else {
  6484. // Get all
  6485. var data = [];
  6486. for (var i = 0; i < el.children.length; i++) {
  6487. value = el.children[i].innerText.replace("\n", "");
  6488. if (value) {
  6489. data.push(obj.getValue(i));
  6490. }
  6491. }
  6492. value = data.join(',');
  6493. }
  6494. return value;
  6495. }
  6496. /**
  6497. * Set the value of the element based on a string separeted by (,|;|\r\n)
  6498. * @param {string} value - A string with the tags
  6499. */
  6500. obj.setValue = function(text) {
  6501. // Remove whitespaces
  6502. text = text.trim();
  6503. if (text) {
  6504. // Tags
  6505. var data = extractTags(text);
  6506. console.log(data);
  6507. // Add tags to the element
  6508. obj.add(data);
  6509. }
  6510. }
  6511. obj.reset = function() {
  6512. el.innerHTML = '<div><br></div>';
  6513. }
  6514. /**
  6515. * Verify if all tags in the element are valid
  6516. * @return {boolean}
  6517. */
  6518. obj.isValid = function() {
  6519. var test = 0;
  6520. for (var i = 0; i < el.children.length; i++) {
  6521. if (el.children[i].classList.contains('jtags_error')) {
  6522. test++;
  6523. }
  6524. }
  6525. return test == 0 ? true : false;
  6526. }
  6527. /**
  6528. * Add one element from the suggestions to the element
  6529. * @param {object} item - Node element in the suggestions container
  6530. */
  6531. obj.selectIndex = function(item) {
  6532. // Reset terms
  6533. searchTerms = '';
  6534. var node = getSelectionStart();
  6535. // Append text to the caret
  6536. node.innerText = item.children[1].innerText;
  6537. // Set node id
  6538. if (item.children[1].getAttribute('data-id')) {
  6539. node.setAttribute('data-id', item.children[1].getAttribute('data-id'));
  6540. }
  6541. // Close container
  6542. if (searchContainer) {
  6543. searchContainer.style.display = '';
  6544. searchContainer.innerHTML = '';
  6545. }
  6546. // Remove any error
  6547. node.classList.remove('jtags_error');
  6548. // Add new item
  6549. obj.add();
  6550. }
  6551. /**
  6552. * Search for suggestions
  6553. * @param {object} node - Target node for any suggestions
  6554. */
  6555. obj.search = function(node) {
  6556. // Create and append search container to the DOM
  6557. if (! searchContainer) {
  6558. var div = document.createElement('div');
  6559. div.style.position = 'relative';
  6560. el.parentNode.insertBefore(div, el.nextSibling);
  6561. // Create container
  6562. searchContainer = document.createElement('div');
  6563. searchContainer.classList.add('jtags_search');
  6564. div.appendChild(searchContainer);
  6565. }
  6566. // Search for
  6567. var terms = node.anchorNode.nodeValue;
  6568. // Search
  6569. if (node.anchorNode.nodeValue && terms != searchTerms) {
  6570. // Terms
  6571. searchTerms = node.anchorNode.nodeValue;
  6572. // Reset index
  6573. searchIndex = 0;
  6574. // Get remove results
  6575. jSuites.ajax({
  6576. url: obj.options.search + searchTerms,
  6577. method: 'GET',
  6578. dataType: 'json',
  6579. success: function(data) {
  6580. // Reset container
  6581. searchContainer.innerHTML = '';
  6582. // Print results
  6583. if (! data.length) {
  6584. // Show container
  6585. searchContainer.style.display = '';
  6586. } else {
  6587. // Show container
  6588. searchContainer.style.display = 'block';
  6589. // Show items
  6590. var len = data.length < 11 ? data.length : 10;
  6591. for (var i = 0; i < len; i++) {
  6592. var div = document.createElement('div');
  6593. if (i == 0) {
  6594. div.classList.add('selected');
  6595. }
  6596. var img = document.createElement('img');
  6597. if (data[i].image) {
  6598. img.src = data[i].image;
  6599. } else {
  6600. img.style.display = 'none';
  6601. }
  6602. div.appendChild(img);
  6603. var item = document.createElement('div');
  6604. item.setAttribute('data-id', data[i].id);
  6605. item.innerHTML = data[i].name;
  6606. div.onclick = function() {
  6607. // Add item
  6608. obj.selectIndex(this);
  6609. }
  6610. div.appendChild(item);
  6611. // Append item to the container
  6612. searchContainer.appendChild(div);
  6613. }
  6614. }
  6615. }
  6616. });
  6617. }
  6618. }
  6619. // Destroy tags element
  6620. obj.destroy = function() {
  6621. // Bind events
  6622. el.removeEventListener('mouseup', tagsMouseUp);
  6623. el.removeEventListener('keydown', tagsKeyDown);
  6624. el.removeEventListener('keyup', tagsKeyUp);
  6625. el.removeEventListener('paste', tagsPaste);
  6626. el.removeEventListener('focus', tagsFocus);
  6627. el.removeEventListener('blur', tagsBlur);
  6628. // Remove element
  6629. el.parentNode.removeChild(el);
  6630. }
  6631. var getRandomColor = function(index) {
  6632. var rand = function(min, max) {
  6633. return min + Math.random() * (max - min);
  6634. }
  6635. return 'hsl(' + rand(1, 360) + ',' + rand(40, 70) + '%,' + rand(65, 72) + '%)';
  6636. }
  6637. /**
  6638. * Filter tags
  6639. */
  6640. var filter = function() {
  6641. for (var i = 0; i < el.children.length; i++) {
  6642. // Create label design
  6643. if (! obj.getValue(i)) {
  6644. el.children[i].classList.remove('jtags_label');
  6645. } else {
  6646. el.children[i].classList.add('jtags_label');
  6647. // Validation in place
  6648. if (typeof(obj.options.validation) == 'function') {
  6649. if (obj.getValue(i)) {
  6650. if (! obj.options.validation(el.children[i], el.children[i].innerText, el.children[i].getAttribute('data-id'))) {
  6651. el.children[i].classList.add('jtags_error');
  6652. } else {
  6653. el.children[i].classList.remove('jtags_error');
  6654. }
  6655. } else {
  6656. el.children[i].classList.remove('jtags_error');
  6657. }
  6658. }
  6659. }
  6660. }
  6661. }
  6662. /**
  6663. * Place caret in the element node
  6664. */
  6665. var caret = function(e) {
  6666. var range = document.createRange();
  6667. var sel = window.getSelection();
  6668. range.setStart(e, e.innerText.length);
  6669. range.collapse(true);
  6670. sel.removeAllRanges();
  6671. sel.addRange(range);
  6672. }
  6673. /**
  6674. * Selection
  6675. */
  6676. var getSelectionStart = function() {
  6677. var node = document.getSelection().anchorNode;
  6678. if (node) {
  6679. return (node.nodeType == 3 ? node.parentNode : node);
  6680. } else {
  6681. return null;
  6682. }
  6683. }
  6684. /**
  6685. * Extract tags from a string
  6686. * @param {string} text - Raw string
  6687. * @return {Array} data - Array with extracted tags
  6688. */
  6689. var extractTags = function(text) {
  6690. /** @type {Array} */
  6691. var data = [];
  6692. /** @type {string} */
  6693. var word = '';
  6694. // Remove whitespaces
  6695. text = text.trim();
  6696. if (text) {
  6697. for (var i = 0; i < text.length; i++) {
  6698. if (text[i] == ',' || text[i] == ';' || text[i] == '\r\n') {
  6699. if (word) {
  6700. data.push(word);
  6701. }
  6702. } else {
  6703. word += text[i];
  6704. }
  6705. }
  6706. if (word) {
  6707. data.push(word);
  6708. }
  6709. }
  6710. return data;
  6711. }
  6712. /** @type {number} */
  6713. var anchorOffset = 0;
  6714. /**
  6715. * Processing event keydown on the element
  6716. * @param e {object}
  6717. */
  6718. var tagsKeyDown = function(e) {
  6719. // Anchoroffset
  6720. anchorOffset = window.getSelection().anchorOffset;
  6721. // Verify content
  6722. if (! el.children.length) {
  6723. var div = document.createElement('div');
  6724. div.innerHTML = '<br>';
  6725. el.appendChild(div);
  6726. }
  6727. // Comma
  6728. if (e.which == 9 || e.which == 186 || e.which == 188) {
  6729. var n = window.getSelection().anchorOffset;
  6730. if (n > 1) {
  6731. obj.add();
  6732. }
  6733. e.preventDefault();
  6734. } else if (e.which == 13) {
  6735. // Enter
  6736. if (searchContainer && searchContainer.style.display != '') {
  6737. obj.selectIndex(searchContainer.children[searchIndex]);
  6738. } else {
  6739. var n = window.getSelection().anchorOffset;
  6740. if (n > 1) {
  6741. obj.add();
  6742. }
  6743. }
  6744. e.preventDefault();
  6745. } else if (e.which == 38) {
  6746. // Up
  6747. if (searchContainer && searchContainer.style.display != '') {
  6748. searchContainer.children[searchIndex].classList.remove('selected');
  6749. if (searchIndex > 0) {
  6750. searchIndex--;
  6751. }
  6752. searchContainer.children[searchIndex].classList.add('selected');
  6753. e.preventDefault();
  6754. }
  6755. } else if (e.which == 40) {
  6756. // Down
  6757. if (searchContainer && searchContainer.style.display != '') {
  6758. searchContainer.children[searchIndex].classList.remove('selected');
  6759. if (searchIndex < 9) {
  6760. searchIndex++;
  6761. }
  6762. searchContainer.children[searchIndex].classList.add('selected');
  6763. e.preventDefault();
  6764. }
  6765. }
  6766. }
  6767. /**
  6768. * Processing event keyup on the element
  6769. * @param e {object}
  6770. */
  6771. var tagsKeyUp = function(e) {
  6772. if (e.which == 39) {
  6773. var n = window.getSelection().anchorOffset;
  6774. if (n > 1 && n == anchorOffset) {
  6775. obj.add();
  6776. }
  6777. } else if (e.which == 13 || e.which == 38 || e.which == 40) {
  6778. e.preventDefault();
  6779. } else {
  6780. if (searchTimer) {
  6781. clearTimeout(searchTimer);
  6782. }
  6783. searchTimer = setTimeout(function() {
  6784. // Current node
  6785. var node = window.getSelection();
  6786. // Search
  6787. if (obj.options.search) {
  6788. obj.search(node);
  6789. }
  6790. searchTimer = null;
  6791. }, 300);
  6792. }
  6793. filter();
  6794. }
  6795. /**
  6796. * Processing event paste on the element
  6797. * @param e {object}
  6798. */
  6799. var tagsPaste = function(e) {
  6800. if (e.clipboardData || e.originalEvent.clipboardData) {
  6801. var html = (e.originalEvent || e).clipboardData.getData('text/html');
  6802. var text = (e.originalEvent || e).clipboardData.getData('text/plain');
  6803. } else if (window.clipboardData) {
  6804. var html = window.clipboardData.getData('Html');
  6805. var text = window.clipboardData.getData('Text');
  6806. }
  6807. obj.setValue(text);
  6808. e.preventDefault();
  6809. }
  6810. /**
  6811. * Processing event mouseup on the element
  6812. * @param e {object}
  6813. */
  6814. var tagsMouseUp = function(e) {
  6815. if (e.target.parentNode && e.target.parentNode.classList.contains('jtags')) {
  6816. if (e.target.classList.contains('jtags_label') || e.target.classList.contains('jtags_error')) {
  6817. const rect = e.target.getBoundingClientRect();
  6818. if (rect.width - (e.clientX - rect.left) < 16) {
  6819. el.removeChild(e.target);
  6820. el.focus();
  6821. }
  6822. }
  6823. }
  6824. if (searchContainer) {
  6825. searchContainer.style.display = '';
  6826. }
  6827. }
  6828. /**
  6829. * Processing event focus on the element
  6830. * @param e {object}
  6831. */
  6832. var tagsFocus = function(e) {
  6833. if (! el.children.length || obj.getValue(el.children.length - 1)) {
  6834. var div = document.createElement('div');
  6835. div.innerHTML = '<br>';
  6836. el.appendChild(div);
  6837. }
  6838. if (typeof(obj.options.onfocus) == 'function') {
  6839. obj.options.onfocus(el, obj, obj.getValue());
  6840. }
  6841. }
  6842. /**
  6843. * Processing event blur on the element
  6844. * @param e {object}
  6845. */
  6846. var tagsBlur = function(e) {
  6847. if (searchContainer) {
  6848. setTimeout(function() {
  6849. searchContainer.style.display = '';
  6850. }, 200);
  6851. }
  6852. for (var i = 0; i < el.children.length - 1; i++) {
  6853. // Create label design
  6854. if (! obj.getValue(i)) {
  6855. el.removeChild(el.children[i]);
  6856. }
  6857. }
  6858. if (typeof(obj.options.onblur) == 'function') {
  6859. obj.options.onblur(el, obj, obj.getValue());
  6860. }
  6861. }
  6862. // Bind events
  6863. el.addEventListener('mouseup', tagsMouseUp);
  6864. el.addEventListener('keydown', tagsKeyDown);
  6865. el.addEventListener('keyup', tagsKeyUp);
  6866. el.addEventListener('paste', tagsPaste);
  6867. el.addEventListener('focus', tagsFocus);
  6868. el.addEventListener('blur', tagsBlur);
  6869. // Prepare container
  6870. el.classList.add('jtags');
  6871. el.setAttribute('contenteditable', true);
  6872. el.setAttribute('spellcheck', false);
  6873. if (obj.options.placeholder) {
  6874. el.placeholder = obj.options.placeholder;
  6875. }
  6876. // Make sure element is empty
  6877. if (obj.options.value) {
  6878. obj.setValue(obj.options.value);
  6879. } else {
  6880. el.innerHTML = '<div><br></div>';
  6881. }
  6882. if (typeof(obj.options.onload) == 'function') {
  6883. obj.options.onload(el, obj);
  6884. }
  6885. el.tags = obj;
  6886. return obj;
  6887. });
  6888. jSuites.tracker = (function(el, options) {
  6889. var obj = {};
  6890. obj.options = {};
  6891. // Default configuration
  6892. var defaults = {
  6893. url: null,
  6894. message: 'Are you sure? There are unsaved information in your form',
  6895. ignore: false,
  6896. currentHash: null,
  6897. submitButton:null,
  6898. onload: null,
  6899. onbeforesave: null,
  6900. onsave: null,
  6901. };
  6902. // Loop through our object
  6903. for (var property in defaults) {
  6904. if (options && options.hasOwnProperty(property)) {
  6905. obj.options[property] = options[property];
  6906. } else {
  6907. obj.options[property] = defaults[property];
  6908. }
  6909. }
  6910. obj.setUrl = function(url) {
  6911. obj.options.url = url;
  6912. }
  6913. obj.load = function() {
  6914. jSuites.ajax({
  6915. url: obj.options.url,
  6916. method: 'GET',
  6917. dataType: 'json',
  6918. success: function(data) {
  6919. var elements = el.querySelectorAll("input, select, textarea");
  6920. for (var i = 0; i < elements.length; i++) {
  6921. var name = elements[i].getAttribute('name');
  6922. if (data[name]) {
  6923. elements[i].value = data[name];
  6924. }
  6925. }
  6926. if (typeof(obj.options.onload) == 'function') {
  6927. obj.options.onload(el, data);
  6928. }
  6929. }
  6930. });
  6931. }
  6932. obj.save = function() {
  6933. var test = obj.validate();
  6934. if (test) {
  6935. jSuites.alert(test);
  6936. } else {
  6937. var data = obj.getElements(true);
  6938. if (typeof(obj.options.onbeforesave) == 'function') {
  6939. var data = obj.options.onbeforesave(el, data);
  6940. if (data === false) {
  6941. console.log('Onbeforesave returned false');
  6942. return;
  6943. }
  6944. }
  6945. jSuites.ajax({
  6946. url: obj.options.url,
  6947. method: 'POST',
  6948. dataType: 'json',
  6949. data: data,
  6950. success: function(result) {
  6951. jSuites.alert(result.message);
  6952. if (typeof(obj.options.onsave) == 'function') {
  6953. var data = obj.options.onsave(el, result);
  6954. }
  6955. obj.reset();
  6956. }
  6957. });
  6958. }
  6959. }
  6960. obj.validateElement = function(element) {
  6961. var emailChecker = function(data) {
  6962. var pattern = new RegExp(/^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/);
  6963. return pattern.test(data) ? true : false;
  6964. }
  6965. var passwordChecker = function(data) {
  6966. return (data.length > 5) ? true : false;
  6967. }
  6968. var addError = function(element) {
  6969. // Add error in the element
  6970. element.classList.add('error');
  6971. // Submit button
  6972. if (obj.options.submitButton) {
  6973. obj.options.submitButton.setAttribute('disabled', true);
  6974. }
  6975. // Return error message
  6976. return element.getAttribute('data-error') || 'There is an error in the form';
  6977. }
  6978. var delError = function(element) {
  6979. var error = false;
  6980. // Remove class from this element
  6981. element.classList.remove('error');
  6982. // Get elements in the form
  6983. var elements = el.querySelectorAll("input, select, textarea");
  6984. // Run all elements
  6985. for (var i = 0; i < elements.length; i++) {
  6986. if (elements[i].getAttribute('data-validation')) {
  6987. if (elements[i].classList.contains('error')) {
  6988. error = true;
  6989. }
  6990. }
  6991. }
  6992. if (obj.options.submitButton) {
  6993. if (error) {
  6994. obj.options.submitButton.setAttribute('disabled', true);
  6995. } else {
  6996. obj.options.submitButton.removeAttribute('disabled');
  6997. }
  6998. }
  6999. }
  7000. // Blank
  7001. var test = '';
  7002. if (! element.value) {
  7003. test = addError(element);
  7004. } else if (element.getAttribute('data-email') && ! emailChecker(element.value)) {
  7005. test = addError(element);
  7006. } else if (element.getAttribute('data-password') && ! emailChecker(element.value)) {
  7007. test = addError(element);
  7008. } else {
  7009. if (element.classList.contains('error')) {
  7010. delError(element);
  7011. }
  7012. }
  7013. return test;
  7014. }
  7015. // Run form validation
  7016. obj.validate = function() {
  7017. var test = '';
  7018. // Get elements in the form
  7019. var elements = el.querySelectorAll("input, select, textarea");
  7020. // Run all elements
  7021. for (var i = 0; i < elements.length; i++) {
  7022. if (elements[i].getAttribute('data-validation')) {
  7023. if (test) {
  7024. test += "<br>\r\n";
  7025. }
  7026. test += obj.validateElement(elements[i]);
  7027. }
  7028. }
  7029. return test;
  7030. }
  7031. // Check the form
  7032. obj.getError = function() {
  7033. // Validation
  7034. return obj.validation() ? true : false;
  7035. }
  7036. // Return the form hash
  7037. obj.setHash = function() {
  7038. return obj.getHash(obj.getElements());
  7039. }
  7040. // Get the form hash
  7041. obj.getHash = function(str) {
  7042. var hash = 0, i, chr;
  7043. if (str.length === 0) {
  7044. return hash;
  7045. } else {
  7046. for (i = 0; i < str.length; i++) {
  7047. chr = str.charCodeAt(i);
  7048. hash = ((hash << 5) - hash) + chr;
  7049. hash |= 0;
  7050. }
  7051. }
  7052. return hash;
  7053. }
  7054. // Is there any change in the form since start tracking?
  7055. obj.isChanged = function() {
  7056. var hash = obj.setHash();
  7057. return (obj.options.currentHash != hash);
  7058. }
  7059. // Restart tracking
  7060. obj.resetTracker = function() {
  7061. obj.options.currentHash = obj.setHash();
  7062. obj.options.ignore = false;
  7063. }
  7064. obj.reset = function() {
  7065. obj.options.currentHash = obj.setHash();
  7066. obj.options.ignore = false;
  7067. }
  7068. // Ignore flag
  7069. obj.setIgnore = function(ignoreFlag) {
  7070. obj.options.ignore = ignoreFlag ? true : false;
  7071. }
  7072. // Get form elements
  7073. obj.getElements = function(asArray) {
  7074. var data = {};
  7075. var elements = el.querySelectorAll("input, select, textarea");
  7076. for (var i = 0; i < elements.length; i++) {
  7077. var element = elements[i];
  7078. var name = element.name;
  7079. var value = element.value;
  7080. if (name) {
  7081. data[name] = value;
  7082. }
  7083. }
  7084. return asArray == true ? data : JSON.stringify(data);
  7085. }
  7086. // Start tracking in one second
  7087. setTimeout(function() {
  7088. obj.options.currentHash = obj.setHash();
  7089. }, 1000);
  7090. // Alert
  7091. window.addEventListener("beforeunload", function (e) {
  7092. if (obj.isChanged() && obj.options.ignore == false) {
  7093. var confirmationMessage = obj.options.message? obj.options.message : "\o/";
  7094. if (confirmationMessage) {
  7095. if (typeof e == 'undefined') {
  7096. e = window.event;
  7097. }
  7098. if (e) {
  7099. e.returnValue = confirmationMessage;
  7100. }
  7101. return confirmationMessage;
  7102. } else {
  7103. return void(0);
  7104. }
  7105. }
  7106. });
  7107. // Validations
  7108. el.addEventListener("keyup", function(e) {
  7109. if (e.target.getAttribute('data-validation')) {
  7110. obj.validateElement(e.target);
  7111. }
  7112. });
  7113. el.tracker = obj;
  7114. return obj;
  7115. });
  7116. return jSuites;
  7117. })));