1"use strict"; 2 3// Component Definition 4var KTApp = function() { 5 /** @type {object} colors State colors **/ 6 var settings = {}; 7 8 var initTooltip = function(el) { 9 var theme = el.data('theme') ? 'tooltip-' + el.data('theme') : ''; 10 var width = el.data('width') == 'auto' ? 'tooltop-auto-width' : ''; 11 var trigger = el.data('trigger') ? el.data('trigger') : 'hover'; 12 13 $(el).tooltip({ 14 trigger: trigger, 15 template: '<div class="tooltip ' + theme + ' ' + width + '" role="tooltip">\ 16 <div class="arrow"></div>\ 17 <div class="tooltip-inner"></div>\ 18 </div>' 19 }); 20 } 21 22 var initTooltips = function() { 23 // init bootstrap tooltips 24 $('[data-toggle="tooltip"]').each(function() { 25 initTooltip($(this)); 26 }); 27 } 28 29 var initPopover = function(el) { 30 var skin = el.data('skin') ? 'popover-' + el.data('skin') : ''; 31 var triggerValue = el.data('trigger') ? el.data('trigger') : 'hover'; 32 33 el.popover({ 34 trigger: triggerValue, 35 template: '\ 36 <div class="popover ' + skin + '" role="tooltip">\ 37 <div class="arrow"></div>\ 38 <h3 class="popover-header"></h3>\ 39 <div class="popover-body"></div>\ 40 </div>' 41 }); 42 } 43 44 var initPopovers = function() { 45 // init bootstrap popover 46 $('[data-toggle="popover"]').each(function() { 47 initPopover($(this)); 48 }); 49 } 50 51 var initFileInput = function() { 52 // init bootstrap popover 53 $('.custom-file-input').on('change', function() { 54 var fileName = $(this).val(); 55 $(this).next('.custom-file-label').addClass("selected").html(fileName); 56 }); 57 } 58 59 var initScroll = function() { 60 $('[data-scroll="true"]').each(function() { 61 var el = $(this); 62 63 KTUtil.scrollInit(this, { 64 mobileNativeScroll: true, 65 handleWindowResize: true, 66 rememberPosition: (el.data('remember-position') == 'true' ? true : false) 67 }); 68 }); 69 } 70 71 var initAlerts = function() { 72 // init bootstrap popover 73 $('body').on('click', '[data-close=alert]', function() { 74 $(this).closest('.alert').hide(); 75 }); 76 } 77 78 var initCard = function(el, options) { 79 // init card tools 80 var el = $(el); 81 var card = new KTCard(el[0], options); 82 } 83 84 var initCards = function() { 85 // init card tools 86 $('[data-card="true"]').each(function() { 87 var el = $(this); 88 var options = {}; 89 90 if (el.data('data-card-initialized') !== true) { 91 initCard(el, options); 92 el.data('data-card-initialized', true); 93 } 94 }); 95 } 96 97 var initStickyCard = function() { 98 if (typeof Sticky === 'undefined') { 99 return; 100 } 101 102 var sticky = new Sticky('[data-sticky="true"]'); 103 } 104 105 var initAbsoluteDropdown = function(context) { 106 var dropdownMenu; 107 108 if (!context) { 109 return; 110 } 111 112 $('body').on('show.bs.dropdown', context, function(e) { 113 dropdownMenu = $(e.target).find('.dropdown-menu'); 114 $('body').append(dropdownMenu.detach()); 115 dropdownMenu.css('display', 'block'); 116 dropdownMenu.position({ 117 'my': 'right top', 118 'at': 'right bottom', 119 'of': $(e.relatedTarget), 120 }); 121 }).on('hide.bs.dropdown', context, function(e) { 122 $(e.target).append(dropdownMenu.detach()); 123 dropdownMenu.hide(); 124 }); 125 } 126 127 var initAbsoluteDropdowns = function() { 128 $('body').on('show.bs.dropdown', function(e) { 129 // e.target is always parent (contains toggler and menu) 130 var $toggler = $(e.target).find("[data-attach='body']"); 131 if ($toggler.length === 0) { 132 return; 133 } 134 var $dropdownMenu = $(e.target).find('.dropdown-menu'); 135 // save detached menu 136 var $detachedDropdownMenu = $dropdownMenu.detach(); 137 // save reference to detached menu inside data of toggler 138 $toggler.data('dropdown-menu', $detachedDropdownMenu); 139 140 $('body').append($detachedDropdownMenu); 141 $detachedDropdownMenu.css('display', 'block'); 142 $detachedDropdownMenu.position({ 143 my: 'right top', 144 at: 'right bottom', 145 of: $(e.relatedTarget), 146 }); 147 }); 148 149 $('body').on('hide.bs.dropdown', function(e) { 150 var $toggler = $(e.target).find("[data-attach='body']"); 151 if ($toggler.length === 0) { 152 return; 153 } 154 // access to reference of detached menu from data of toggler 155 var $detachedDropdownMenu = $toggler.data('dropdown-menu'); 156 // re-append detached menu inside parent 157 $(e.target).append($detachedDropdownMenu.detach()); 158 // hide dropdown 159 $detachedDropdownMenu.hide(); 160 }); 161 }; 162 163 return { 164 init: function(settingsArray) { 165 if (settingsArray) { 166 settings = settingsArray; 167 } 168 169 KTApp.initComponents(); 170 }, 171 172 initComponents: function() { 173 initScroll(); 174 initTooltips(); 175 initPopovers(); 176 initAlerts(); 177 initFileInput(); 178 initCards(); 179 initStickyCard(); 180 initAbsoluteDropdowns(); 181 }, 182 183 initTooltips: function() { 184 initTooltips(); 185 }, 186 187 initTooltip: function(el) { 188 initTooltip(el); 189 }, 190 191 initPopovers: function() { 192 initPopovers(); 193 }, 194 195 initPopover: function(el) { 196 initPopover(el); 197 }, 198 199 initCard: function(el, options) { 200 initCard(el, options); 201 }, 202 203 initCards: function() { 204 initCards(); 205 }, 206 207 initSticky: function() { 208 initSticky(); 209 }, 210 211 initAbsoluteDropdown: function(context) { 212 initAbsoluteDropdown(context); 213 }, 214 215 block: function(target, options) { 216 var el = $(target); 217 218 options = $.extend(true, { 219 opacity: 0.05, 220 overlayColor: '#000000', 221 type: '', 222 size: '', 223 state: 'primary', 224 centerX: true, 225 centerY: true, 226 message: '', 227 shadow: true, 228 width: 'auto' 229 }, options); 230 231 var html; 232 var version = options.type ? 'spinner-' + options.type : ''; 233 var state = options.state ? 'spinner-' + options.state : ''; 234 var size = options.size ? 'spinner-' + options.size : ''; 235 var spinner = '<span class="spinner ' + version + ' ' + state
235+ ' ' + size + '"></span'; 236 237 if (options.message && options.message.length > 0) { 238 var classes = 'blockui ' + (options.shadow === false ? 'blockui' : ''); 239 240 html = '<div class="' + classes + '"><span>' + options.message + '</span>' + spinner + '</div>'; 241 242 var el = document.createElement('div'); 243 244 $('body').prepend(el); 245 KTUtil.addClass(el, classes); 246 el.innerHTML = html; 247 options.width = KTUtil.actualWidth(el) + 10; 248 KTUtil.remove(el); 249 250 if (target == 'body') { 251 html = '<div class="' + classes + '" style="margin-left:-' + (options.width / 2) + 'px;"><span>' + options.message + '</span><span>' + spinner + '</span></div>'; 252 } 253 } else { 254 html = spinner; 255 } 256 257 var params = { 258 message: html, 259 centerY: options.centerY, 260 centerX: options.centerX, 261 css: { 262 top: '30%', 263 left: '50%', 264 border: '0', 265 padding: '0', 266 backgroundColor: 'none', 267 width: options.width 268 }, 269 overlayCSS: { 270 backgroundColor: options.overlayColor, 271 opacity: options.opacity, 272 cursor: 'wait', 273 zIndex: (target == 'body' ? 1100 : 10) 274 }, 275 onUnblock: function() { 276 if (el && el[0]) { 277 KTUtil.css(el[0], 'position', ''); 278 KTUtil.css(el[0], 'zoom', ''); 279 } 280 } 281 }; 282 283 if (target == 'body') { 284 params.css.top = '50%'; 285 $.blockUI(params); 286 } else { 287 var el = $(target); 288 el.block(params); 289 } 290 }, 291 292 unblock: function(target) { 293 if (target && target != 'body') { 294 $(target).unblock(); 295 } else { 296 $.unblockUI(); 297 } 298 }, 299 300 blockPage: function(options) { 301 return KTApp.block('body', options); 302 }, 303 304 unblockPage: function() { 305 return KTApp.unblock('body'); 306 }, 307 308 getSettings: function() { 309 return settings; 310 } 311 }; 312}(); 313 314// webpack support 315if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 316 module.exports = KTApp; 317} 318 319// Initialize KTApp class on document ready 320$(document).ready(function() { 321 KTApp.init(KTAppSettings); 322}); 323 324// CSS3 Transitions only after page load(.page-loading class added to body tag and remove with JS on page load) 325window.onload = function() { 326 var result = KTUtil.getByTagName('body'); 327 if (result && result[0]) { 328 KTUtil.removeClass(result[0], 'page-loading'); 329 } 330} 331"use strict"; 332 333// Component Definition 334var KTCard = function(elementId, options) { 335 // Main object 336 var the = this; 337 var init = false; 338 339 // Get element object 340 var element = KTUtil.getById(elementId); 341 var body = KTUtil.getBody(); 342 343 if (!element) { 344 return; 345 } 346 347 // Default options 348 var defaultOptions = { 349 toggleSpeed: 400, 350 sticky: { 351 releseOnReverse: false, 352 offset: 300, 353 zIndex: 101 354 } 355 }; 356 357 //////////////////////////// 358 // ** Private Methods ** // 359 //////////////////////////// 360 361 var Plugin = { 362 /** 363 * Construct 364 */ 365 366 construct: function(options) { 367 if (KTUtil.data(element).has('card')) { 368 the = KTUtil.data(element).get('card'); 369 } else { 370 // reset menu 371 Plugin.init(options); 372 373 // build menu 374 Plugin.build(); 375 376 KTUtil.data(element).set('card', the); 377 } 378 379 return the; 380 }, 381 382 /** 383 * Init card 384 */ 385 init: function(options) { 386 the.element = element; 387 the.events = []; 388 389 // merge default and user defined options 390 the.options = KTUtil.deepExtend({}, defaultOptions, options); 391 the.header = KTUtil.child(element, '.card-header'); 392 the.footer = KTUtil.child(element, '.card-footer'); 393 394 if (KTUtil.child(element, '.card-body')) { 395 the.body = KTUtil.child(element, '.card-body'); 396 } else if (KTUtil.child(element, '.form')) { 397 the.body = KTUtil.child(element, '.form'); 398 } 399 }, 400 401 /** 402 * Build Form Wizard 403 */ 404 build: function() { 405 // Remove 406 var remove = KTUtil.find(the.header, '[data-card-tool=remove]'); 407 if (remove) { 408 KTUtil.addEvent(remove, 'click', function(e) { 409 e.preventDefault(); 410 Plugin.remove(); 411 }); 412 } 413 414 // Reload 415 var reload = KTUtil.find(the.header, '[data-card-tool=reload]');
416 if (reload) { 417 KTUtil.addEvent(reload, 'click', function(e) { 418 e.preventDefault(); 419 Plugin.reload(); 420 }); 421 } 422 423 // Toggle 424 var toggle = KTUtil.find(the.header, '[data-card-tool=toggle]'); 425 if (toggle) { 426 KTUtil.addEvent(toggle, 'click', function(e) { 427 e.preventDefault(); 428 Plugin.toggle(); 429 }); 430 } 431 }, 432 433 /** 434 * Enable stickt mode 435 */ 436 initSticky: function() { 437 var lastScrollTop = 0; 438 var offset = the.options.sticky.offset; 439 440 if (!the.header) { 441 return; 442 } 443 444 window.addEventListener('scroll', Plugin.onScrollSticky); 445 }, 446 447 /** 448 * Window scroll handle event for sticky card 449 */ 450 onScrollSticky: function(e) { 451 var offset = the.options.sticky.offset; 452 453 if(isNaN(offset)) return; 454 455 var st = KTUtil.getScrollTop(); 456 457 if (st >= offset && KTUtil.hasClass(body, 'card-sticky-on') === false) { 458 Plugin.eventTrigger('stickyOn'); 459 460 KTUtil.addClass(body, 'card-sticky-on'); 461 462 Plugin.updateSticky(); 463 464 } else if ((st*1.5) <= offset && KTUtil.hasClass(body, 'card-sticky-on')) { 465 // Back scroll mode 466 Plugin.eventTrigger('stickyOff'); 467 468 KTUtil.removeClass(body, 'card-sticky-on'); 469 470 Plugin.resetSticky(); 471 } 472 }, 473 474 updateSticky: function() { 475 if (!the.header) { 476 return; 477 } 478 479 var top; 480 481 if (KTUtil.hasClass(body, 'card-sticky-on')) { 482 if (the.options.sticky.position.top instanceof Function) { 483 top = parseInt(the.options.sticky.position.top.call(this, the)); 484 } else { 485 top = parseInt(the.options.sticky.position.top); 486 } 487 488 var left; 489 if (the.options.sticky.position.left instanceof Function) { 490 left = parseInt(the.options.sticky.position.left.call(this, the)); 491 } else { 492 left = parseInt(the.options.sticky.position.left); 493 } 494 495 var right; 496 if (the.options.sticky.position.right instanceof Function) { 497 right = parseInt(the.options.sticky.position.right.call(this, the)); 498 } else { 499 right = parseInt(the.options.sticky.position.right); 500 } 501 502 KTUtil.css(the.header, 'z-index', the.options.sticky.zIndex); 503 KTUtil.css(the.header, 'top', top + 'px'); 504 KTUtil.css(the.header, 'left', left + 'px'); 505 KTUtil.css(the.header, 'right', right + 'px'); 506 } 507 }, 508 509 resetSticky: function() { 510 if (!the.header) { 511 return; 512 } 513 514 if (KTUtil.hasClass(body, 'card-sticky-on') === false) { 515 KTUtil.css(the.header, 'z-index', ''); 516 KTUtil.css(the.header, 'top', ''); 517 KTUtil.css(the.header, 'left', ''); 518 KTUtil.css(the.header, 'right', ''); 519 } 520 }, 521 522 /** 523 * Remove card 524 */ 525 remove: function() { 526 if (Plugin.eventTrigger('beforeRemove') === false) { 527 return; 528 } 529 530 // Remove tooltips 531 var tooltips; 532 if ( tooltips = document.querySelectorAll('.tooltip.show') ) { 533 $(tooltips).tooltip('dispose'); 534 } 535 536 KTUtil.remove(element); 537 538 Plugin.eventTrigger('afterRemove'); 539 }, 540 541 /** 542 * Set content 543 */ 544 setContent: function(html) { 545 if (html) { 546 the.body.innerHTML = html; 547 } 548 }, 549 550 /** 551 * Get body 552 */ 553 getBody: function() { 554 return the.body; 555 }, 556 557 /** 558 * Get self 559 */ 560 getSelf: function() { 561 return element; 562 }, 563 564 /** 565 * Reload 566 */ 567 reload: function() { 568 Plugin.eventTrigger('reload'); 569 }, 570 571 /** 572 * Toggle 573 */ 574 toggle: function() { 575 if (KTUtil.hasClass(element, 'card-collapse') || KTUtil.hasClass(element, 'card-collapsed')) { 576 Plugin.expand(); 577 } else { 578 Plugin.collapse(); 579 } 580 }, 581 582 /** 583 * Collapse 584 */ 585 collapse: function() { 586 if (Plugin.eventTrigger('beforeCollapse') === false) { 587 return; 588 } 589 590 KTUtil.slideUp(the.body, the.options.toggleSpeed, function() { 591 Plugin.eventTrigger('afterCollapse'); 592 }); 593 594 KTUtil.addClass(element, 'card-collapse'); 595 }, 596 597 /** 598 * Expand 599 */ 600 expand: function() {
601 if (Plugin.eventTrigger('beforeExpand') === false) { 602 return; 603 } 604 605 KTUtil.slideDown(the.body, the.options.toggleSpeed, function() { 606 Plugin.eventTrigger('afterExpand'); 607 }); 608 609 KTUtil.removeClass(element, 'card-collapse'); 610 KTUtil.removeClass(element, 'card-collapsed'); 611 }, 612 613 /** 614 * Trigger events 615 */ 616 eventTrigger: function(name) { 617 //KTUtil.triggerCustomEvent(name); 618 for (var i = 0; i < the.events.length; i++) { 619 var event = the.events[i]; 620 if (event.name == name) { 621 if (event.one == true) { 622 if (event.fired == false) { 623 the.events[i].fired = true; 624 return event.handler.call(this, the); 625 } 626 } else { 627 return event.handler.call(this, the); 628 } 629 } 630 } 631 }, 632 633 addEvent: function(name, handler, one) { 634 the.events.push({ 635 name: name, 636 handler: handler, 637 one: one, 638 fired: false 639 }); 640 641 return the; 642 } 643 }; 644 645 ////////////////////////// 646 // ** Public Methods ** // 647 ////////////////////////// 648 649 /** 650 * Set default options 651 */ 652 653 the.setDefaults = function(options) { 654 defaultOptions = options; 655 }; 656 657 /** 658 * Remove card 659 */ 660 the.remove = function() { 661 return Plugin.remove(html); 662 }; 663 664 /** 665 * Init sticky card 666 */ 667 the.initSticky = function() { 668 return Plugin.initSticky(); 669 }; 670 671 /** 672 * Rerender sticky layout 673 */ 674 the.updateSticky = function() { 675 return Plugin.updateSticky(); 676 }; 677 678 /** 679 * Reset the sticky 680 */ 681 the.resetSticky = function() { 682 return Plugin.resetSticky(); 683 }; 684 685 /** 686 * Destroy sticky card 687 */ 688 the.destroySticky = function() { 689 Plugin.resetSticky(); 690 window.removeEventListener('scroll', Plugin.onScrollSticky); 691 }; 692 693 /** 694 * Reload card 695 */ 696 the.reload = function() { 697 return Plugin.reload(); 698 }; 699 700 /** 701 * Set card content 702 */ 703 the.setContent = function(html) { 704 return Plugin.setContent(html); 705 }; 706 707 /** 708 * Toggle card 709 */ 710 the.toggle = function() { 711 return Plugin.toggle(); 712 }; 713 714 /** 715 * Collapse card 716 */ 717 the.collapse = function() { 718 return Plugin.collapse(); 719 }; 720 721 /** 722 * Expand card 723 */ 724 the.expand = function() { 725 return Plugin.expand(); 726 }; 727 728 /** 729 * Get cardbody 730 * @returns {jQuery} 731 */ 732 the.getBody = function() { 733 return Plugin.getBody(); 734 }; 735 736 /** 737 * Get cardbody 738 * @returns {jQuery} 739 */ 740 the.getSelf = function() { 741 return Plugin.getSelf(); 742 }; 743 744 /** 745 * Attach event 746 */ 747 the.on = function(name, handler) { 748 return Plugin.addEvent(name, handler); 749 }; 750 751 /** 752 * Attach event that will be fired once 753 */ 754 the.one = function(name, handler) { 755 return Plugin.addEvent(name, handler, true); 756 }; 757 758 // Construct plugin 759 Plugin.construct.apply(the, [options]); 760 761 return the; 762}; 763 764// webpack support 765if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 766 module.exports = KTCard; 767} 768 769"use strict";
770// DOCS: https://javascript.info/cookie 771 772// Component Definition 773var KTCookie = function() { 774 return { 775 // returns the cookie with the given name, 776 // or undefined if not found 777 getCookie: function(name) { 778 var matches = document.cookie.match(new RegExp( 779 "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" 780 )); 781 return matches ? decodeURIComponent(matches[1]) : undefined; 782 }, 783 // Please note that a cookie value is encoded, 784 // so getCookie uses a built-in decodeURIComponent function to decode it. 785 setCookie: function(name, value, options) { 786 if (!options) { 787 options = {}; 788 } 789 790 options = Object.assign({}, {path: '/'}, options); 791 792 if (options.expires instanceof Date) { 793 options.expires = options.expires.toUTCString(); 794 } 795 796 var updatedCookie = encodeURIComponent(name) + "=" + encodeURIComponent(value); 797 798 for (var optionKey in options) { 799 if (!options.hasOwnProperty(optionKey)) { 800 continue; 801 } 802 updatedCookie += "; " + optionKey; 803 var optionValue = options[optionKey]; 804 if (optionValue !== true) { 805 updatedCookie += "=" + optionValue; 806 } 807 } 808 809 document.cookie = updatedCookie; 810 }, 811 // To delete a cookie, we can call it with a negative expiration date: 812 deleteCookie: function(name) { 813 setCookie(name, "", { 814 'max-age': -1 815 }) 816 } 817 } 818}(); 819 820// webpack support 821if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 822 module.exports = KTCookie; 823} 824 825"use strict"; 826 827// Component Definition 828var KTDialog = function(options) { 829 // Main object 830 var the = this; 831 832 // Get element object 833 var element; 834 var body = KTUtil.getBody(); 835 836 // Default options 837 var defaultOptions = { 838 'placement' : 'top center', 839 'type' : 'loader', 840 'width' : 100, 841 'state' : 'default', 842 'message' : 'Loading...' 843 }; 844 845 //////////////////////////// 846 // ** Private Methods ** // 847 //////////////////////////// 848 849 var Plugin = { 850 /** 851 * Construct 852 */ 853 854 construct: function(options) { 855 Plugin.init(options); 856 857 return the; 858 }, 859 860 /** 861 * Handles subtoggle click toggle 862 */ 863 init: function(options) { 864 the.events = []; 865 866 // merge default and user defined options 867 the.options = KTUtil.deepExtend({}, defaultOptions, options); 868 869 the.state = false; 870 }, 871 872 /** 873 * Show dialog 874 */ 875 show: function() { 876 Plugin.eventTrigger('show'); 877 878 element = document.createElement("DIV"); 879 KTUtil.setHTML(element, the.options.message); 880 881 KTUtil.addClass(element, 'dialog dialog-shown'); 882 KTUtil.addClass(element, 'dialog-' + the.options.state); 883 KTUtil.addClass(element, 'dialog-' + the.options.type); 884 885 if (the.options.placement == 'top center') { 886 KTUtil.addClass(element, 'dialog-top-center'); 887 } 888 889 body.appendChild(element); 890 891 the.state = 'shown'; 892 893 Plugin.eventTrigger('shown'); 894 895 return the; 896 }, 897 898 /** 899 * Hide dialog 900 */ 901 hide: function() { 902 if (element) { 903 Plugin.eventTrigger('hide'); 904 905 element.remove(); 906 the.state = 'hidden'; 907 908 Plugin.eventTrigger('hidden'); 909 } 910 911 return the; 912 }, 913 914 /** 915 * Trigger events 916 */ 917 eventTrigger: function(name) { 918 for (var i = 0; i < the.events.length; i++) { 919 var event = the.events[i]; 920 921 if (event.name == name) { 922 if (event.one == true) { 923 if (event.fired == false) { 924 the.events[i].fired = true; 925 return event.handler.call(this, the); 926 } 927 } else { 928 return event.handler.call(this, the); 929 } 930 } 931 } 932 }, 933 934 addEvent: function(name, handler, one) { 935 the.events.push({ 936 name: name, 937 handler: handler, 938 one: one, 939 fired: false 940 }); 941 942 return the; 943 } 944 }; 945
946 ////////////////////////// 947 // ** Public Methods ** // 948 ////////////////////////// 949 950 /** 951 * Set default options 952 */ 953 954 the.setDefaults = function(options) { 955 defaultOptions = options; 956 }; 957 958 /** 959 * Check shown state 960 */ 961 the.shown = function() { 962 return the.state == 'shown'; 963 }; 964 965 /** 966 * Check hidden state 967 */ 968 the.hidden = function() { 969 return the.state == 'hidden'; 970 }; 971 972 /** 973 * Show dialog 974 */ 975 the.show = function() { 976 return Plugin.show(); 977 }; 978 979 /** 980 * Hide dialog 981 */ 982 the.hide = function() { 983 return Plugin.hide(); 984 }; 985 986 /** 987 * Attach event 988 * @returns {KTToggle} 989 */ 990 the.on = function(name, handler) { 991 return Plugin.addEvent(name, handler); 992 }; 993 994 /** 995 * Attach event that will be fired once 996 * @returns {KTToggle} 997 */ 998 the.one = function(name, handler) { 999 return Plugin.addEvent(name, handler, true); 1000 }; 1001 1002 // Construct plugin 1003 Plugin.construct.apply(the, [options]); 1004 1005 return the; 1006}; 1007 1008// webpack support 1009if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 1010 module.exports = KTDialog; 1011} 1012 1013"use strict"; 1014 1015// Component Definition 1016var KTHeader = function(elementId, options) { 1017 // Main object 1018 var the = this; 1019 var init = false; 1020 1021 // Get element object 1022 var element = KTUtil.getById(elementId); 1023 var body = KTUtil.getBody(); 1024 1025 if (element === undefined) { 1026 return; 1027 } 1028 1029 // Default options 1030 var defaultOptions = { 1031 offset: { 1032 desktop: true, 1033 tabletAndMobile: true 1034 }, 1035 releseOnReverse: { 1036 desktop: false, 1037 tabletAndMobile: false 1038 } 1039 }; 1040 1041 //////////////////////////// 1042 // ** Private Methods ** // 1043 //////////////////////////// 1044 1045 var Plugin = { 1046 /** 1047 * Run plugin 1048 * @returns {KTHeader} 1049 */ 1050 construct: function(options) { 1051 if (KTUtil.data(element).has('header')) { 1052 the = KTUtil.data(element).get('header'); 1053 } else { 1054 // reset header 1055 Plugin.init(options); 1056 1057 // build header 1058 Plugin.build(); 1059 1060 KTUtil.data(element).set('header', the); 1061 } 1062 1063 return the; 1064 }, 1065 1066 /** 1067 * Handles subheader click toggle 1068 * @returns {KTHeader} 1069 */ 1070 init: function(options) { 1071 the.events = []; 1072 1073 // merge default and user defined options 1074 the.options = KTUtil.deepExtend({}, defaultOptions, options); 1075 }, 1076 1077 /** 1078 * Reset header 1079 * @returns {KTHeader} 1080 */ 1081 build: function() { 1082 var eventTriggerState = true; 1083 var lastScrollTop = 0; 1084 1085 window.addEventListener('scroll', function() { 1086 var offset = 0, st, attrName; 1087 1088 if (KTUtil.isBreakpointDown('lg') && the.options.offset.tabletAndMobile === false) { 1089 return; 1090 } 1091 1092 if (KTUtil.isBreakpointUp('lg') && the.options.offset.desktop === false) { 1093 return; 1094 } 1095 1096 if (KTUtil.isBreakpointUp('lg')) { 1097 offset = the.options.offset.desktop; 1098 } else if (KTUtil.isBreakpointDown('lg')) { 1099 offset = the.options.offset.tabletAndMobile; 1100 } 1101 1102 st = KTUtil.getScrollTop(); 1103 1104 if ( 1105 (KTUtil.isBreakpointDown('lg') && the.options.releseOnReverse.tabletAndMobile) || 1106 (KTUtil.isBreakpointUp('lg') && the.options.releseOnReverse.desktop) 1107 ) { 1108 if (st > offset && lastScrollTop < st) { // down scroll mode 1109 if (body.hasAttribute('data-header-scroll') === false) { 1110 body.setAttribute('data-header-scroll', 'on'); 1111 } 1112 1113 if (eventTriggerState) { 1114 Plugin.eventTrigger('scrollOn', the); 1115 eventTriggerState = false;
1116 } 1117 } else { // back scroll mode 1118 if (body.hasAttribute('data-header-scroll') === true) { 1119 body.removeAttribute('data-header-scroll'); 1120 } 1121 1122 if (eventTriggerState == false) { 1123 Plugin.eventTrigger('scrollOff', the); 1124 eventTriggerState = true; 1125 } 1126 } 1127 1128 lastScrollTop = st; 1129 } else { 1130 if (st > offset) { // down scroll mode 1131 if (body.hasAttribute('data-header-scroll') === false) { 1132 body.setAttribute('data-header-scroll', 'on'); 1133 } 1134 1135 if (eventTriggerState) { 1136 Plugin.eventTrigger('scrollOn', the); 1137 eventTriggerState = false; 1138 } 1139 } else { // back scroll mode 1140 if (body.hasAttribute('data-header-scroll') === true) { 1141 body.removeAttribute('data-header-scroll'); 1142 } 1143 1144 if (eventTriggerState == false) { 1145 Plugin.eventTrigger('scrollOff', the); 1146 eventTriggerState = true; 1147 } 1148 } 1149 } 1150 }); 1151 }, 1152 1153 /** 1154 * Trigger events 1155 */ 1156 eventTrigger: function(name, args) { 1157 for (var i = 0; i < the.events.length; i++) { 1158 var event = the.events[i]; 1159 if (event.name == name) { 1160 if (event.one == true) { 1161 if (event.fired == false) { 1162 the.events[i].fired = true; 1163 return event.handler.call(this, the, args); 1164 } 1165 } else { 1166 return event.handler.call(this, the, args); 1167 } 1168 } 1169 } 1170 }, 1171 1172 addEvent: function(name, handler, one) { 1173 the.events.push({ 1174 name: name, 1175 handler: handler, 1176 one: one, 1177 fired: false 1178 }); 1179 } 1180 }; 1181 1182 ////////////////////////// 1183 // ** Public Methods ** // 1184 ////////////////////////// 1185 1186 /** 1187 * Set default options 1188 */ 1189 1190 the.setDefaults = function(options) { 1191 defaultOptions = options; 1192 }; 1193 1194 /** 1195 * Register event 1196 */ 1197 the.on = function(name, handler) { 1198 return Plugin.addEvent(name, handler); 1199 }; 1200 1201 /////////////////////////////// 1202 // ** Plugin Construction ** // 1203 /////////////////////////////// 1204 1205 // Run plugin 1206 Plugin.construct.apply(the, [options]); 1207 1208 // Init done 1209 init = true; 1210 1211 // Return plugin instance 1212 return the; 1213}; 1214 1215// webpack support 1216if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 1217 module.exports = KTHeader; 1218} 1219 1220"use strict"; 1221 1222// Component Definition 1223var KTImageInput = function(elementId, options) { 1224 // Main object 1225 var the = this; 1226 var init = false; 1227 1228 // Get element object 1229 var element = KTUtil.getById(elementId); 1230 var body = KTUtil.getBody(); 1231 1232 if (!element) { 1233 return; 1234 } 1235 1236 // Default options 1237 var defaultOptions = { 1238 editMode: false 1239 }; 1240 1241 //////////////////////////// 1242 // ** Private Methods ** // 1243 //////////////////////////// 1244 1245 var Plugin = { 1246 /** 1247 * Construct 1248 */ 1249 1250 construct: function(options) { 1251 if (KTUtil.data(element).has('imageinput')) { 1252 the = KTUtil.data(element).get('imageinput'); 1253 } else { 1254 // reset menu 1255 Plugin.init(options); 1256 1257 // build menu 1258 Plugin.build(); 1259 1260 KTUtil.data(element).set('imageinput', the); 1261 } 1262 1263 return the; 1264 }, 1265 1266 /** 1267 * Init avatar
1268 */ 1269 init: function(options) { 1270 the.element = element; 1271 the.events = []; 1272 1273 the.input = KTUtil.find(element, 'input[type="file"]'); 1274 the.wrapper = KTUtil.find(element, '.image-input-wrapper'); 1275 the.cancel = KTUtil.find(element, '[data-action="cancel"]'); 1276 the.remove = KTUtil.find(element, '[data-action="remove"]'); 1277 the.src = KTUtil.css(the.wrapper, 'backgroundImage'); 1278 the.hidden = KTUtil.find(element, 'input[type="hidden"]'); 1279 1280 // merge default and user defined options 1281 the.options = KTUtil.deepExtend({}, defaultOptions, options); 1282 }, 1283 1284 /** 1285 * Build 1286 */ 1287 build: function() { 1288 // Handle change 1289 KTUtil.addEvent(the.input, 'change', function(e) { 1290 e.preventDefault(); 1291 1292 if (the.input && the.input.files && the.input.files[0]) { 1293 var reader = new FileReader(); 1294 reader.onload = function(e) { 1295 KTUtil.css(the.wrapper, 'background-image', 'url('+e.target.result +')'); 1296 } 1297 reader.readAsDataURL(the.input.files[0]); 1298 1299 KTUtil.addClass(the.element, 'image-input-changed'); 1300 KTUtil.removeClass(the.element, 'image-input-empty'); 1301 1302 // Fire change event 1303 Plugin.eventTrigger('change'); 1304 } 1305 }); 1306 1307 // Handle cancel 1308 KTUtil.addEvent(the.cancel, 'click', function(e) { 1309 e.preventDefault(); 1310 1311 // Fire cancel event 1312 Plugin.eventTrigger('cancel'); 1313 1314 KTUtil.removeClass(the.element, 'image-input-changed'); 1315 KTUtil.removeClass(the.element, 'image-input-empty'); 1316 KTUtil.css(the.wrapper, 'background-image', the.src); 1317 the.input.value = ""; 1318 1319 if (the.hidden) { 1320 the.hidden.value = "0"; 1321 } 1322 }); 1323 1324 // Handle remove 1325 KTUtil.addEvent(the.remove, 'click', function(e) { 1326 e.preventDefault(); 1327 1328 // Fire cancel event 1329 Plugin.eventTrigger('remove'); 1330 1331 KTUtil.removeClass(the.element, 'image-input-changed'); 1332 KTUtil.addClass(the.element, 'image-input-empty'); 1333 KTUtil.css(the.wrapper, 'background-image', "none"); 1334 the.input.value = ""; 1335 1336 if (the.hidden) { 1337 the.hidden.value = "1"; 1338 } 1339 }); 1340 }, 1341 1342 /** 1343 * Trigger events 1344 */ 1345 eventTrigger: function(name) { 1346 //KTUtil.triggerCustomEvent(name); 1347 for (var i = 0; i < the.events.length; i++) { 1348 var event = the.events[i]; 1349 if (event.name == name) { 1350 if (event.one == true) { 1351 if (event.fired == false) { 1352 the.events[i].fired = true; 1353 return event.handler.call(this, the); 1354 } 1355 } else { 1356 return event.handler.call(this, the); 1357 } 1358 } 1359 } 1360 }, 1361 1362 addEvent: function(name, handler, one) { 1363 the.events.push({ 1364 name: name, 1365 handler: handler, 1366 one: one, 1367 fired: false 1368 }); 1369 1370 return the; 1371 } 1372 }; 1373 1374 ////////////////////////// 1375 // ** Public Methods ** // 1376 ////////////////////////// 1377 1378 /** 1379 * Set default options 1380 */ 1381 1382 the.setDefaults = function(options) { 1383 defaultOptions = options; 1384 }; 1385 1386 /** 1387 * Attach event 1388 */ 1389 the.on = function(name, handler) { 1390 return Plugin.addEvent(name, handler); 1391 }; 1392 1393 /** 1394 * Attach event that will be fired once 1395 */ 1396 the.one = function(name, handler) { 1397 return Plugin.addEvent(name, handler, true); 1398 }; 1399 1400 // Construct plugin 1401 Plugin.construct.apply(the, [options]); 1402 1403 return the; 1404}; 1405 1406// webpack support 1407if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 1408 module.exports = KTImageInput; 1409} 1410 1411"use strict"; 1412 1413// Component Definition 1414var KTMenu = function(elementId, options) { 1415 // Main object 1416 var the = this; 1417 var init = false;
1418 1419 // Get element object 1420 var element = KTUtil.getById(elementId); 1421 var body = KTUtil.getBody(); 1422 1423 if (!element) { 1424 return; 1425 } 1426 1427 // Default options 1428 var defaultOptions = { 1429 // scrollable area with Perfect Scroll 1430 scroll: { 1431 rememberPosition: false 1432 }, 1433 1434 // accordion submenu mode 1435 accordion: { 1436 slideSpeed: 200, // accordion toggle slide speed in milliseconds 1437 autoScroll: false, // enable auto scrolling(focus) to the clicked menu item 1438 autoScrollSpeed: 1200, 1439 expandAll: true // allow having multiple expanded accordions in the menu 1440 }, 1441 1442 // dropdown submenu mode 1443 dropdown: { 1444 timeout: 500 // timeout in milliseconds to show and hide the hoverable submenu dropdown 1445 } 1446 }; 1447 1448 //////////////////////////// 1449 // ** Private Methods ** // 1450 //////////////////////////// 1451 1452 var Plugin = { 1453 /** 1454 * Run plugin 1455 * @returns {KTMenu} 1456 */ 1457 construct: function(options) { 1458 if (KTUtil.data(element).has('menu')) { 1459 the = KTUtil.data(element).get('menu'); 1460 } else { 1461 // reset menu 1462 Plugin.init(options); 1463 1464 // reset menu 1465 Plugin.reset(); 1466 1467 // build menu 1468 Plugin.build(); 1469 1470 KTUtil.data(element).set('menu', the); 1471 } 1472 1473 return the; 1474 }, 1475 1476 /** 1477 * Handles submenu click toggle 1478 * @returns {KTMenu} 1479 */ 1480 init: function(options) { 1481 the.events = []; 1482 1483 the.eventHandlers = {}; 1484 1485 // merge default and user defined options 1486 the.options = KTUtil.deepExtend({}, defaultOptions, options); 1487 1488 // pause menu 1489 the.pauseDropdownHoverTime = 0; 1490 1491 the.uid = KTUtil.getUniqueID(); 1492 }, 1493 1494 update: function(options) { 1495 // merge default and user defined options 1496 the.options = KTUtil.deepExtend({}, defaultOptions, options); 1497 1498 // pause menu 1499 the.pauseDropdownHoverTime = 0; 1500 1501 // reset menu 1502 Plugin.reset(); 1503 1504 the.eventHandlers = {}; 1505 1506 // build menu 1507 Plugin.build(); 1508 1509 KTUtil.data(element).set('menu', the); 1510 }, 1511 1512 reload: function() { 1513 // reset menu 1514 Plugin.reset(); 1515 1516 // build menu 1517 Plugin.build(); 1518 1519 // reset submenu props 1520 Plugin.resetSubmenuProps(); 1521 }, 1522 1523 /** 1524 * Reset menu 1525 * @returns {KTMenu} 1526 */ 1527 build: function() { 1528 // General accordion submenu toggle 1529 the.eventHandlers['event_1'] = KTUtil.on( element, '.menu-toggle', 'click', Plugin.handleSubmenuAccordion); 1530 1531 // Dropdown mode(hoverable) 1532 if (Plugin.getSubmenuMode() === 'dropdown' || Plugin.isConditionalSubmenuDropdown()) { 1533 // dropdown submenu - hover toggle 1534 the.eventHandlers['event_2'] = KTUtil.on( element, '[data-menu-toggle="hover"]', 'mouseover', Plugin.handleSubmenuDrodownHoverEnter); 1535 the.eventHandlers['event_3'] = KTUtil.on( element, '[data-menu-toggle="hover"]', 'mouseout', Plugin.handleSubmenuDrodownHoverExit); 1536 1537 // dropdown submenu - click toggle 1538 the.eventHandlers['event_4'] = KTUtil.on( element, '[data-menu-toggle="click"] > .menu-toggle, [data-menu-toggle="click"] > .menu-link .menu-toggle', 'click', Plugin.handleSubmenuDropdownClick); 1539 the.eventHandlers['event_5'] = KTUtil.on( element, '[data-menu-toggle="tab"] > .menu-toggle, [data-menu-toggle="tab"] > .menu-link .menu-toggle', 'click', Plugin.handleSubmenuDropdownTabClick); 1540 } 1541 1542 // Handle general link click 1543 the.eventHandlers['event_6'] = KTUtil.on(element, '.menu-item > .menu-link:not(.menu-toggle):not(.menu-link-toggle-skip)', 'click', Plugin.handleLinkClick); 1544 1545 // Init scrollable menu 1546 if (the.options.scroll && the.options.scroll.height) { 1547 Plugin.scrollInit(); 1548 } 1549 }, 1550 1551 /** 1552 * Reset menu 1553 * @returns {KTMenu} 1554 */ 1555 reset: function() { 1556 KTUtil.off( element, 'click', the.eventHandlers['event_1']); 1557 1558 // dropdown submenu - hover toggle 1559 KTUtil.off( element, 'mouseover', the.eventHandlers['event_2']); 1560 KTUtil.off( element, 'mouseout', the.eventHandlers['event_3']); 1561 1562 // dropdown submenu - click toggle 1563 KTUtil.off( element, 'click', the.eventHandlers['event_4']); 1564 KTUtil.off( element, 'click', the.eventHandlers['event_5']); 1565 1566 // handle link click 1567 KTUtil.off(element, 'click', the.eventHandlers['event_6']); 1568 }, 1569 1570 /** 1571 * Init scroll menu 1572 * 1573 */ 1574 scrollInit: function() { 1575 if ( the.options.scroll && the.options.scroll.height ) { 1576 KTUtil.scrollDestroy(element, true); 1577 KTUtil.scrollInit(element, {mobileNativeScroll: true, windowScroll: false, resetHeightOnDestroy: true, handleWindowResize: true, height: the.options.scroll.height, rememberPosition: the.options.scroll.rememberPosition}); 1578 } else { 1579 KTUtil.scrollDestroy(element, true); 1580 } 1581 }, 1582 1583 /** 1584 * Update scroll menu 1585 */ 1586 scrollUpdate: function() { 1587 if ( the.options.scroll && the.options.scroll.height ) { 1588 KTUtil.scrollUpdate(element); 1589 } 1590 }, 1591 1592 /** 1593 * Scroll top 1594 */ 1595 scrollTop: function() { 1596 if ( the.options.scroll && the.options.scroll.height ) { 1597 KTUtil.scrollTop(element); 1598 } 1599 }, 1600 1601 /** 1602 * Get submenu mode for current breakpoint and menu state 1603 * @returns {KTMenu} 1604 */ 1605 getSubmenuMode: function(el) {
1606 if ( KTUtil.isBreakpointUp('lg') ) { 1607 if (el && KTUtil.hasAttr(el, 'data-menu-toggle') && KTUtil.attr(el, 'data-menu-toggle') == 'hover') { 1608 return 'dropdown'; 1609 } 1610 1611 if ( KTUtil.isset(the.options.submenu, 'desktop.state.body') ) { 1612 if ( KTUtil.hasClasses(body, the.options.submenu.desktop.state.body) ) { 1613 return the.options.submenu.desktop.state.mode; 1614 } else { 1615 return the.options.submenu.desktop.default; 1616 } 1617 } else if ( KTUtil.isset(the.options.submenu, 'desktop') ) { 1618 return the.options.submenu.desktop; 1619 } 1620 } else if ( KTUtil.isBreakpointUp('md') && KTUtil.isBreakpointDown('lg') && KTUtil.isset(the.options.submenu, 'tablet') ) { 1621 return the.options.submenu.tablet; 1622 } else if ( KTUtil.isBreakpointDown('md') && KTUtil.isset(the.options.submenu, 'mobile') ) { 1623 return the.options.submenu.mobile; 1624 } else { 1625 return false; 1626 } 1627 }, 1628 1629 /** 1630 * Get submenu mode for current breakpoint and menu state 1631 * @returns {KTMenu} 1632 */ 1633 isConditionalSubmenuDropdown: function() { 1634 if ( KTUtil.isBreakpointUp('lg') && KTUtil.isset(the.options.submenu, 'desktop.state.body') ) { 1635 return true; 1636 } else { 1637 return false; 1638 } 1639 }, 1640 1641 1642 /** 1643 * Reset submenu attributes 1644 * @returns {KTMenu} 1645 */ 1646 resetSubmenuProps: function(e) { 1647 var submenus = KTUtil.findAll(element, '.menu-submenu'); 1648 if ( submenus ) { 1649 for (var i = 0, len = submenus.length; i < len; i++) { 1650 var submenu = submenus[0]; 1651 1652 KTUtil.css(submenu, 'display', ''); 1653 KTUtil.css(submenu, 'overflow', ''); 1654 1655 if (submenu.hasAttribute('data-hor-direction')) { 1656 KTUtil.removeClass(submenu, 'menu-submenu-left'); 1657 KTUtil.removeClass(submenu, 'menu-submenu-right'); 1658 KTUtil.addClass(submenu, submenu.getAttribute('data-hor-direction')); 1659 } 1660 } 1661 } 1662 }, 1663 1664 /** 1665 * Handles submenu hover toggle 1666 * @returns {KTMenu} 1667 */ 1668 handleSubmenuDrodownHoverEnter: function(e) { 1669 if ( Plugin.getSubmenuMode(this) === 'accordion' ) { 1670 return; 1671 } 1672 1673 if ( the.resumeDropdownHover() === false ) { 1674 return; 1675 } 1676 1677 var item = this; 1678 1679 if ( item.getAttribute('data-hover') == '1' ) { 1680 item.removeAttribute('data-hover'); 1681 clearTimeout( item.getAttribute('data-timeout') ); 1682 item.removeAttribute('data-timeout'); 1683 } 1684 1685 Plugin.showSubmenuDropdown(item); 1686 }, 1687 1688 /** 1689 * Handles submenu hover toggle 1690 * @returns {KTMenu} 1691 */ 1692 handleSubmenuDrodownHoverExit: function(e) { 1693 if ( the.resumeDropdownHover() === false ) { 1694 return; 1695 } 1696 1697 if ( Plugin.getSubmenuMode(this) === 'accordion' ) { 1698 return; 1699 } 1700 1701 var item = this; 1702 var time = the.options.dropdown.timeout; 1703 1704 var timeout = setTimeout(function() { 1705 if ( item.getAttribute('data-hover') == '1' ) { 1706 Plugin.hideSubmenuDropdown(item, true); 1707 } 1708 }, time); 1709 1710 item.setAttribute('data-hover', '1'); 1711 item.setAttribute('data-timeout', timeout); 1712 }, 1713 1714 /** 1715 * Handles submenu click toggle 1716 * @returns {KTMenu} 1717 */ 1718 handleSubmenuDropdownClick: function(e) { 1719 if ( Plugin.getSubmenuMode(this) === 'accordion' ) { 1720 return; 1721 } 1722 1723 var item = this.closest('.menu-item'); 1724 1725 // Trigger click event handlers 1726 var result = Plugin.eventTrigger('submenuToggle', this, e); 1727 if (result === false) { 1728 return; 1729 } 1730 1731 if ( item.getAttribute('data-menu-submenu-mode') == 'accordion' ) { 1732 return; 1733 } 1734
1735 if ( KTUtil.hasClass(item, 'menu-item-hover') === false ) { 1736 KTUtil.addClass(item, 'menu-item-open-dropdown'); 1737 Plugin.showSubmenuDropdown(item); 1738 } else { 1739 KTUtil.removeClass(item, 'menu-item-open-dropdown' ); 1740 Plugin.hideSubmenuDropdown(item, true); 1741 } 1742 1743 e.preventDefault(); 1744 }, 1745 1746 /** 1747 * Handles tab click toggle 1748 * @returns {KTMenu} 1749 */ 1750 handleSubmenuDropdownTabClick: function(e) { 1751 if (Plugin.getSubmenuMode(this) === 'accordion') { 1752 return; 1753 } 1754 var item = this.closest('.menu-item'); 1755 1756 // Trigger click event handlers 1757 var result = Plugin.eventTrigger('submenuToggle', this, e); 1758 if (result === false) { 1759 return; 1760 } 1761 1762 if (item.getAttribute('data-menu-submenu-mode') == 'accordion') { 1763 return; 1764 } 1765 1766 if (KTUtil.hasClass(item, 'menu-item-hover') == false) { 1767 KTUtil.addClass(item, 'menu-item-open-dropdown'); 1768 Plugin.showSubmenuDropdown(item); 1769 } 1770 1771 e.preventDefault(); 1772 }, 1773 1774 /** 1775 * Handles link click 1776 * @returns {KTMenu} 1777 */ 1778 handleLinkClick: function(e) { 1779 var submenu = this.closest('.menu-item.menu-item-submenu'); 1780 1781 // Trigger click event handlers 1782 var result = Plugin.eventTrigger('linkClick', this, e); 1783 if (result === false) { 1784 return; 1785 } 1786 1787 if ( submenu && Plugin.getSubmenuMode(submenu) === 'dropdown' ) { 1788 Plugin.hideSubmenuDropdowns(); 1789 } 1790 }, 1791 1792 /** 1793 * Handles submenu dropdown close on link click 1794 * @returns {KTMenu} 1795 */ 1796 handleSubmenuDropdownClose: function(e, el) { 1797 // exit if its not submenu dropdown mode 1798 if (Plugin.getSubmenuMode(el) === 'accordion') { 1799 return; 1800 } 1801 1802 var shown = element.querySelectorAll('.menu-item.menu-item-submenu.menu-item-hover:not(.menu-item-tabs)'); 1803 1804 // check if currently clicked link's parent item ha 1805 if (shown.length > 0 && KTUtil.hasClass(el, 'menu-toggle') === false && el.querySelectorAll('.menu-toggle').length === 0) { 1806 // close opened dropdown menus 1807 for (var i = 0, len = shown.length; i < len; i++) { 1808 Plugin.hideSubmenuDropdown(shown[0], true); 1809 } 1810 } 1811 }, 1812 1813 /** 1814 * helper functions 1815 * @returns {KTMenu} 1816 */ 1817 handleSubmenuAccordion: function(e, el) { 1818 var query; 1819 var item = el ? el : this; 1820 1821 // Trigger click event handlers 1822 var result = Plugin.eventTrigger('submenuToggle', this, e); 1823 if (result === false) { 1824 return; 1825 } 1826 1827 if ( Plugin.getSubmenuMode(el) === 'dropdown' && (query = item.closest('.menu-item') ) ) { 1828 if (query.getAttribute('data-menu-submenu-mode') != 'accordion' ) { 1829 e.preventDefault(); 1830 return; 1831 } 1832 } 1833 1834 var li = item.closest('.menu-item'); 1835 var submenu = KTUtil.child(li, '.menu-submenu, .menu-inner'); 1836 1837 if (KTUtil.hasClass(item.closest('.menu-item'), 'menu-item-open-always')) { 1838 return; 1839 } 1840 1841 if ( li && submenu ) { 1842 e.preventDefault(); 1843 var speed = the.options.accordion.slideSpeed; 1844 var hasClosables = false; 1845 1846 if ( KTUtil.hasClass(li, 'menu-item-open') === false ) { 1847 // hide other accordions 1848 if ( the.options.accordion.expandAll === false ) { 1849 var subnav = item.closest('.menu-nav, .menu-subnav'); 1850 var closables = KTUtil.children(subnav, '.menu-item.menu-item-open.menu-item-submenu:not(.menu-item-here):not(.menu-item-open-always)'); 1851 1852 if ( subnav && closables ) { 1853 for (var i = 0, len = closables.length; i < len; i++) { 1854 var el_ = closables[0]; 1855 var submenu_ = KTUtil.child(el_, '.menu-submenu'); 1856 if ( submenu_ ) { 1857 KTUtil.slideUp(submenu_, speed, function() { 1858 Plugin.scrollUpdate(); 1859 KTUtil.removeClass(el_, 'menu-item-open'); 1860 }); 1861 } 1862 } 1863 } 1864 } 1865 1866 KTUtil.slideDown(submenu, speed, function() { 1867 Plugin.scrollToItem(item); 1868 Plugin.scrollUpdate(); 1869 1870 Plugin.eventTrigger('submenuToggle', submenu, e); 1871 }); 1872 1873 KTUtil.addClass(li, 'menu-item-open'); 1874 1875 } else { 1876 KTUtil.slideUp(submenu, speed, function() { 1877 Plugin.scrollToItem(item); 1878 Plugin.scrollUpdate(); 1879 Plugin.eventTrigger('submenuToggle', submenu, e); 1880 }); 1881 1882 KTUtil.removeClass(li, 'menu-item-open'); 1883 } 1884 } 1885 }, 1886 1887 /** 1888 * scroll to item function 1889 * @returns {KTMenu} 1890 */ 1891 scrollToItem: function(item) { 1892 // handle auto scroll for accordion submenus
1893 if ( KTUtil.isBreakpointUp('lg') && the.options.accordion.autoScroll && element.getAttribute('data-menu-scroll') !== '1' ) { 1894 KTUtil.scrollTo(item, the.options.accordion.autoScrollSpeed); 1895 } 1896 }, 1897 1898 /** 1899 * Hide submenu dropdown 1900 * @returns {KTMenu} 1901 */ 1902 hideSubmenuDropdown: function(item, classAlso) { 1903 // remove submenu activation class 1904 if ( classAlso ) { 1905 KTUtil.removeClass(item, 'menu-item-hover'); 1906 KTUtil.removeClass(item, 'menu-item-active-tab'); 1907 } 1908 1909 // clear timeout 1910 item.removeAttribute('data-hover'); 1911 1912 if ( item.getAttribute('data-menu-toggle-class') ) { 1913 KTUtil.removeClass(body, item.getAttribute('data-menu-toggle-class')); 1914 } 1915 1916 var timeout = item.getAttribute('data-timeout'); 1917 item.removeAttribute('data-timeout'); 1918 clearTimeout(timeout); 1919 }, 1920 1921 /** 1922 * Hide submenu dropdowns 1923 * @returns {KTMenu} 1924 */ 1925 hideSubmenuDropdowns: function() { 1926 var items; 1927 if ( items = element.querySelectorAll('.menu-item-submenu.menu-item-hover:not(.menu-item-tabs):not([data-menu-toggle="tab"])') ) { 1928 for (var j = 0, cnt = items.length; j < cnt; j++) { 1929 Plugin.hideSubmenuDropdown(items[j], true); 1930 } 1931 } 1932 }, 1933 1934 /** 1935 * helper functions 1936 * @returns {KTMenu} 1937 */ 1938 showSubmenuDropdown: function(item) { 1939 // close active submenus 1940 var list = element.querySelectorAll('.menu-item-submenu.menu-item-hover, .menu-item-submenu.menu-item-active-tab'); 1941 1942 if ( list ) { 1943 for (var i = 0, len = list.length; i < len; i++) { 1944 var el = list[i]; 1945 if ( item !== el && el.contains(item) === false && item.contains(el) === false ) { 1946 Plugin.hideSubmenuDropdown(el, true); 1947 } 1948 } 1949 } 1950 1951 // add submenu activation class 1952 KTUtil.addClass(item, 'menu-item-hover'); 1953 1954 // Change the alignment of submenu is offscreen. 1955 var submenu = KTUtil.find(item, '.menu-submenu'); 1956 1957 if (submenu && submenu.hasAttribute('data-hor-direction') === false) { 1958 if (KTUtil.hasClass(submenu, 'menu-submenu-left')) { 1959 submenu.setAttribute('data-hor-direction', 'menu-submenu-left'); 1960 } else if (KTUtil.hasClass(submenu, 'menu-submenu-right')) { 1961 submenu.setAttribute('data-hor-direction', 'menu-submenu-right'); 1962 } 1963 } 1964 1965 if ( submenu && KTUtil.isOffscreen(submenu, 'left', 15) === true ) { 1966 KTUtil.removeClass(submenu, 'menu-submenu-left'); 1967 KTUtil.addClass(submenu, 'menu-submenu-right'); 1968 } else if ( submenu && KTUtil.isOffscreen(submenu, 'right', 15) === true ) { 1969 KTUtil.removeClass(submenu, 'menu-submenu-right'); 1970 KTUtil.addClass(submenu, 'menu-submenu-left'); 1971 } 1972 1973 if ( item.getAttribute('data-menu-toggle-class') ) { 1974 KTUtil.addClass(body, item.getAttribute('data-menu-toggle-class')); 1975 } 1976 }, 1977 1978 /** 1979 * Handles submenu slide toggle 1980 * @returns {KTMenu} 1981 */ 1982 createSubmenuDropdownClickDropoff: function(el) { 1983 var query; 1984 var zIndex = (query = KTUtil.child(el, '.menu-submenu') ? KTUtil.css(query, 'z-index') : 0) - 1; 1985 1986 var dropoff = document.createElement('<div class="menu-dropoff" style="background: transparent; position: fixed; top: 0; bottom: 0; left: 0; right: 0; z-index: ' + zIndex + '"></div>'); 1987 1988 body.appendChild(dropoff); 1989 1990 KTUtil.addEvent(dropoff, 'click', function(e) { 1991 e.stopPropagation(); 1992 e.preventDefault(); 1993 KTUtil.remove(this); 1994 Plugin.hideSubmenuDropdown(el, true); 1995 }); 1996 }, 1997 1998 /** 1999 * Handles submenu hover toggle 2000 * @returns {KTMenu} 2001 */ 2002 pauseDropdownHover: function(time) { 2003 var date = new Date(); 2004 2005 the.pauseDropdownHoverTime = date.getTime() + time; 2006 }, 2007 2008 /** 2009 * Handles submenu hover toggle 2010 * @returns {KTMenu} 2011 */ 2012 resumeDropdownHover: function() { 2013 var date = new Date(); 2014 2015 return (date.getTime() > the.pauseDropdownHoverTime ? true : false); 2016 }, 2017 2018 /** 2019 * Reset menu's current active item 2020 * @returns {KTMenu} 2021 */ 2022 resetActiveItem: function(item) { 2023 var list; 2024 var parents; 2025 2026 list = element.querySelectorAll('.menu-item-active'); 2027 2028 for (var i = 0, len = list.length; i < len; i++) { 2029 var el = list[0]; 2030 KTUtil.removeClass(el, 'menu-item-active'); 2031 KTUtil.hide( KTUtil.child(el, '.menu-submenu') ); 2032 parents = KTUtil.parents(el, '.menu-item-submenu') || []; 2033 2034 for (var i_ = 0, len_ = parents.length; i_ < len_; i_++) { 2035 var el_ = parents[i]; 2036 KTUtil.removeClass(el_, 'menu-item-open'); 2037 KTUtil.hide( KTUtil.child(el_, '.menu-submenu') ); 2038 } 2039 } 2040 2041 // close open submenus 2042 if ( the.options.accordion.expandAll === false ) { 2043 if ( list = element.querySelectorAll('.menu-item-open') ) { 2044 for (var i = 0, len = list.length; i < len; i++) { 2045 KTUtil.removeClass(parents[0], 'menu-item-open'); 2046 } 2047 } 2048 } 2049 }, 2050 2051 /** 2052 * Sets menu's active item 2053 * @returns {KTMenu} 2054 */
2055 setActiveItem: function(item) { 2056 // reset current active item 2057 Plugin.resetActiveItem(); 2058 2059 var parents = KTUtil.parents(item, '.menu-item-submenu') || []; 2060 for (var i = 0, len = parents.length; i < len; i++) { 2061 KTUtil.addClass(parents[i], 'menu-item-open'); 2062 } 2063 2064 KTUtil.addClass(item, 'menu-item-active'); 2065 }, 2066 2067 /** 2068 * Returns page breadcrumbs for the menu's active item 2069 * @returns {KTMenu} 2070 */ 2071 getBreadcrumbs: function(item) { 2072 var query; 2073 var breadcrumbs = []; 2074 var link = KTUtil.child(item, '.menu-link'); 2075 2076 breadcrumbs.push({ 2077 text: (query = KTUtil.child(link, '.menu-text') ? query.innerHTML : ''), 2078 title: link.getAttribute('title'), 2079 href: link.getAttribute('href') 2080 }); 2081 2082 var parents = KTUtil.parents(item, '.menu-item-submenu'); 2083 for (var i = 0, len = parents.length; i < len; i++) { 2084 var submenuLink = KTUtil.child(parents[i], '.menu-link'); 2085 2086 breadcrumbs.push({ 2087 text: (query = KTUtil.child(submenuLink, '.menu-text') ? query.innerHTML : ''), 2088 title: submenuLink.getAttribute('title'), 2089 href: submenuLink.getAttribute('href') 2090 }); 2091 } 2092 2093 return breadcrumbs.reverse(); 2094 }, 2095 2096 /** 2097 * Returns page title for the menu's active item 2098 * @returns {KTMenu} 2099 */ 2100 getPageTitle: function(item) { 2101 var query; 2102 2103 return (query = KTUtil.child(item, '.menu-text') ? query.innerHTML : ''); 2104 }, 2105 2106 /** 2107 * Trigger events 2108 */ 2109 eventTrigger: function(name, target, e) { 2110 for (var i = 0; i < the.events.length; i++ ) { 2111 var event = the.events[i]; 2112 if ( event.name == name ) { 2113 if ( event.one == true ) { 2114 if ( event.fired == false ) { 2115 the.events[i].fired = true; 2116 return event.handler.call(this, target, e); 2117 } 2118 } else { 2119 return event.handler.call(this, target, e); 2120 } 2121 } 2122 } 2123 }, 2124 2125 addEvent: function(name, handler, one) { 2126 the.events.push({ 2127 name: name, 2128 handler: handler, 2129 one: one, 2130 fired: false 2131 }); 2132 }, 2133 2134 removeEvent: function(name) { 2135 if (the.events[name]) { 2136 delete the.events[name]; 2137 } 2138 } 2139 }; 2140 2141 ////////////////////////// 2142 // ** Public Methods ** // 2143 ////////////////////////// 2144 2145 /** 2146 * Set default options 2147 */ 2148 2149 the.setDefaults = function(options) { 2150 defaultOptions = options; 2151 }; 2152 2153 /** 2154 * Update scroll 2155 */ 2156 the.scrollUpdate = function() { 2157 return Plugin.scrollUpdate(); 2158 }; 2159 2160 /** 2161 * Re-init scroll 2162 */ 2163 the.scrollReInit = function() { 2164 return Plugin.scrollInit(); 2165 }; 2166 2167 /** 2168 * Scroll top 2169 */ 2170 the.scrollTop = function() { 2171 return Plugin.scrollTop(); 2172 }; 2173 2174 /** 2175 * Set active menu item 2176 */ 2177 the.setActiveItem = function(item) { 2178 return Plugin.setActiveItem(item); 2179 }; 2180 2181 the.reload = function() { 2182 return Plugin.reload(); 2183 }; 2184 2185 the.update = function(options) { 2186 return Plugin.update(options); 2187 }; 2188 2189 /** 2190 * Set breadcrumb for menu item 2191 */ 2192 the.getBreadcrumbs = function(item) { 2193 return Plugin.getBreadcrumbs(item); 2194 }; 2195 2196 /** 2197 * Set page title for menu item 2198 */ 2199 the.getPageTitle = function(item) { 2200 return Plugin.getPageTitle(item); 2201 }; 2202 2203 /** 2204 * Get submenu mode 2205 */ 2206 the.getSubmenuMode = function(el) { 2207 return Plugin.getSubmenuMode(el); 2208 }; 2209 2210 /** 2211 * Hide dropdown 2212 * @returns {Object} 2213 */ 2214 the.hideDropdown = function(item) { 2215 Plugin.hideSubmenuDropdown(item, true); 2216 }; 2217 2218 /** 2219 * Hide dropdowns 2220 * @returns {Object} 2221 */ 2222 the.hideDropdowns = function() { 2223 Plugin.hideSubmenuDropdowns(); 2224 }; 2225 2226 /** 2227 * Disable menu for given time 2228 * @returns {Object} 2229 */ 2230 the.pauseDropdownHover = function(time) { 2231 Plugin.pauseDropdownHover(time); 2232 }; 2233 2234 /** 2235 * Disable menu for given time 2236 * @returns {Object} 2237 */ 2238 the.resumeDropdownHover = function() { 2239 return Plugin.resumeDropdownHover(); 2240 }; 2241 2242 /** 2243 * Register event 2244 */ 2245 the.on = function(name, handler) { 2246 return Plugin.addEvent(name, handler); 2247 }; 2248 2249 the.off = function(name) { 2250 return Plugin.removeEvent(name); 2251 }; 2252 2253 the.one = function(name, handler) { 2254 return Plugin.addEvent(name, handler, true); 2255 }; 2256
2257 /////////////////////////////// 2258 // ** Plugin Construction ** // 2259 /////////////////////////////// 2260 2261 // Run plugin 2262 Plugin.construct.apply(the, [options]); 2263 2264 // Handle plugin on window resize 2265 KTUtil.addResizeHandler(function() { 2266 if (init) { 2267 the.reload(); 2268 } 2269 }); 2270 2271 // Init done 2272 init = true; 2273 2274 // Return plugin instance 2275 return the; 2276}; 2277 2278// webpack support 2279if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 2280 module.exports = KTMenu; 2281} 2282 2283// Plugin global lazy initialization 2284document.addEventListener("click", function (e) { 2285 var body = KTUtil.getByTagName('body')[0]; 2286 var query; 2287 if ( query = body.querySelectorAll('.menu-nav .menu-item.menu-item-submenu.menu-item-hover:not(.menu-item-tabs)[data-menu-toggle="click"]') ) { 2288 for (var i = 0, len = query.length; i < len; i++) { 2289 var element = query[i].closest('.menu-nav').parentNode; 2290 2291 if ( element ) { 2292 var the = KTUtil.data(element).get('menu'); 2293 2294 if ( !the ) { 2295 break; 2296 } 2297 2298 if ( !the || the.getSubmenuMode() !== 'dropdown' ) { 2299 break; 2300 } 2301 2302 if ( e.target !== element && element.contains(e.target) === false ) { 2303 the.hideDropdowns(); 2304 } 2305 } 2306 } 2307 } 2308}); 2309 2310"use strict"; 2311 2312// Component Definition 2313var KTOffcanvas = function(elementId, options) { 2314 // Main object 2315 var the = this; 2316 var init = false; 2317 2318 // Get element object 2319 var element = KTUtil.getById(elementId); 2320 var body = KTUtil.getBody(); 2321 2322 if (!element) { 2323 return; 2324 } 2325 2326 // Default options 2327 var defaultOptions = { 2328 attrCustom: '' 2329 }; 2330 2331 //////////////////////////// 2332 // ** Private Methods ** // 2333 //////////////////////////// 2334 2335 var Plugin = { 2336 construct: function(options) { 2337 if (KTUtil.data(element).has('offcanvas')) { 2338 the = KTUtil.data(element).get('offcanvas'); 2339 } else { 2340 // Reset offcanvas 2341 Plugin.init(options); 2342 2343 // Build offcanvas 2344 Plugin.build(); 2345 2346 KTUtil.data(element).set('offcanvas', the); 2347 } 2348 2349 return the; 2350 }, 2351 2352 init: function(options) { 2353 the.events = []; 2354 2355 // merge default and user defined options 2356 the.options = KTUtil.deepExtend({}, defaultOptions, options); 2357 2358 the.classBase = the.options.baseClass; 2359 the.attrCustom = the.options.attrCustom; 2360 the.classShown = the.classBase + '-on'; 2361 the.classOverlay = the.classBase + '-overlay'; 2362 the.target; 2363 2364 the.state = KTUtil.hasClass(element, the.classShown) ? 'shown' : 'hidden'; 2365 }, 2366 2367 build: function() { 2368 // offcanvas toggle 2369 if (the.options.toggleBy) { 2370 if (typeof the.options.toggleBy === 'string') { 2371 KTUtil.addEvent(KTUtil.getById(the.options.toggleBy), 'click', function(e) { 2372 e.preventDefault(); 2373 the.target = this; 2374 Plugin.toggle(); 2375 }); 2376 } else if (the.options.toggleBy && the.options.toggleBy[0]) { 2377 if (the.options.toggleBy[0].target) { 2378 for (var i in the.options.toggleBy) { 2379 KTUtil.addEvent(KTUtil.getById(the.options.toggleBy[i].target), 'click', function(e) { 2380 e.preventDefault(); 2381 the.target = this; 2382 Plugin.toggle(); 2383 }); 2384 } 2385 } else { 2386 for (var i in the.options.toggleBy) { 2387 KTUtil.addEvent(KTUtil.getById(the.options.toggleBy[i]), 'click', function(e) { 2388 e.preventDefault(); 2389 the.target = this; 2390 Plugin.toggle(); 2391 }); 2392 } 2393 } 2394 2395 } else if (the.options.toggleBy && the.options.toggleBy.target) { 2396 KTUtil.addEvent( KTUtil.getById(the.options.toggleBy.target), 'click', function(e) { 2397 e.preventDefault(); 2398 the.target = this; 2399 Plugin.toggle(); 2400 }); 2401 } 2402 } 2403 2404 // offcanvas close 2405 var closeBy = KTUtil.getById(the.options.closeBy); 2406 if (closeBy) { 2407 KTUtil.addEvent(closeBy, 'click', function(e) { 2408 e.preventDefault(); 2409 the.target = this; 2410 Plugin.hide(); 2411 }); 2412 } 2413 }, 2414 2415 isShown: function() { 2416 return (the.state == 'shown' ? true : false); 2417 }, 2418 2419 toggle: function() {; 2420 Plugin.eventTrigger('toggle'); 2421 2422 if (the.state == 'shown') { 2423 Plugin.hide(); 2424 } else { 2425 Plugin.show(); 2426 } 2427 }, 2428 2429 show: function() { 2430 if (the.state == 'shown') { 2431 return; 2432 } 2433 2434 Plugin.eventTrigger('beforeShow'); 2435 2436 Plugin.toggleClass('show'); 2437 2438 // Offcanvas panel 2439 KTUtil.attr(body, 'data-offcanvas-' + the.classBase, 'on'); 2440 KTUtil.addClass(element, the.classShown); 2441 2442 if (the.attrCustom.length > 0) { 2443 KTUtil.attr(body, 'data-offcanvas-' + the.classCustom, 'on'); 2444 //KTUtil.addClass(body, the.classCustom); 2445 } 2446 2447 the.state = 'shown'; 2448 2449 if (the.options.overlay) {
2450 the.overlay = KTUtil.insertAfter(document.createElement('DIV') , element ); 2451 KTUtil.addClass(the.overlay, the.classOverlay); 2452 2453 KTUtil.addEvent(the.overlay, 'click', function(e) { 2454 //e.stopPropagation(); 2455 e.preventDefault(); 2456 Plugin.hide(the.target); 2457 }); 2458 } 2459 2460 Plugin.eventTrigger('afterShow'); 2461 }, 2462 2463 hide: function() { 2464 if (the.state == 'hidden') { 2465 return; 2466 } 2467 2468 Plugin.eventTrigger('beforeHide'); 2469 2470 Plugin.toggleClass('hide'); 2471 2472 KTUtil.removeAttr(body, 'data-offcanvas-' + the.classBase); 2473 KTUtil.removeClass(element, the.classShown); 2474 2475 if (the.attrCustom.length > 0) { 2476 KTUtil.removeAttr(body, 'data-offcanvas-' + the.attrCustom); 2477 } 2478 2479 the.state = 'hidden'; 2480 2481 if (the.options.overlay && the.overlay) { 2482 KTUtil.remove(the.overlay); 2483 } 2484 2485 Plugin.eventTrigger('afterHide'); 2486 }, 2487 2488 toggleClass: function(mode) { 2489 var id = KTUtil.attr(the.target, 'id'); 2490 var toggleBy; 2491 2492 if (the.options.toggleBy && the.options.toggleBy[0] && the.options.toggleBy[0].target) { 2493 for (var i in the.options.toggleBy) { 2494 if (the.options.toggleBy[i].target === id) { 2495 toggleBy = the.options.toggleBy[i]; 2496 } 2497 } 2498 } else if (the.options.toggleBy && the.options.toggleBy.target) { 2499 toggleBy = the.options.toggleBy; 2500 } 2501 2502 if (toggleBy) { 2503 var el = KTUtil.getById(toggleBy.target); 2504 2505 if (mode === 'show') { 2506 KTUtil.addClass(el, toggleBy.state); 2507 } 2508 2509 if (mode === 'hide') { 2510 KTUtil.removeClass(el, toggleBy.state); 2511 } 2512 } 2513 }, 2514 2515 eventTrigger: function(name, args) { 2516 for (var i = 0; i < the.events.length; i++) { 2517 var event = the.events[i]; 2518 if (event.name == name) { 2519 if (event.one == true) { 2520 if (event.fired == false) { 2521 the.events[i].fired = true; 2522 return event.handler.call(this, the, args); 2523 } 2524 } else { 2525 return event.handler.call(this, the, args); 2526 } 2527 } 2528 } 2529 }, 2530 2531 addEvent: function(name, handler, one) { 2532 the.events.push({ 2533 name: name, 2534 handler: handler, 2535 one: one, 2536 fired: false 2537 }); 2538 } 2539 }; 2540 2541 ////////////////////////// 2542 // ** Public Methods ** // 2543 ////////////////////////// 2544 2545 /** 2546 * Set default options 2547 * @param options 2548 */ 2549 the.setDefaults = function(options) { 2550 defaultOptions = options; 2551 }; 2552 2553 /** 2554 * Check if canvas is shown 2555 * @returns {boolean} 2556 */ 2557 the.isShown = function() { 2558 return Plugin.isShown(); 2559 }; 2560 2561 /** 2562 * Set to hide the canvas 2563 */ 2564 the.hide = function() { 2565 return Plugin.hide(); 2566 }; 2567 2568 /** 2569 * Set to show the canvas 2570 */ 2571 the.show = function() { 2572 return Plugin.show(); 2573 }; 2574 2575 /** 2576 * Attach event 2577 * @param name 2578 * @param handler 2579 */ 2580 the.on = function(name, handler) { 2581 return Plugin.addEvent(name, handler); 2582 }; 2583 2584 /** 2585 * Attach event that will be fired once 2586 * @param name 2587 * @param handler 2588 */ 2589 the.one = function(name, handler) { 2590 return Plugin.addEvent(name, handler, true); 2591 }; 2592 2593 /////////////////////////////// 2594 // ** Plugin Construction ** // 2595 /////////////////////////////// 2596 2597 // Run plugin 2598 Plugin.construct.apply(the, [options]); 2599 2600 // Init done 2601 init = true; 2602 2603 // Return plugin instance 2604 return the; 2605}; 2606 2607// webpack support 2608if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 2609 module.exports = KTOffcanvas; 2610} 2611 2612"use strict"; 2613 2614// Component Definition 2615var KTScrolltop = function(elementId, options) { 2616 // Main object 2617 var the = this; 2618 var init = false;
2619 2620 // Get element object 2621 var element = KTUtil.getById(elementId); 2622 var body = KTUtil.getBody(); 2623 2624 if (!element) { 2625 return; 2626 } 2627 2628 // Default options 2629 var defaultOptions = { 2630 offset: 300, 2631 speed: 6000 2632 }; 2633 2634 //////////////////////////// 2635 // ** Private Methods ** // 2636 //////////////////////////// 2637 2638 var Plugin = { 2639 /** 2640 * Run plugin 2641 * @returns {mscrolltop} 2642 */ 2643 construct: function(options) { 2644 if (KTUtil.data(element).has('scrolltop')) { 2645 the = KTUtil.data(element).get('scrolltop'); 2646 } else { 2647 // reset scrolltop 2648 Plugin.init(options); 2649 2650 // build scrolltop 2651 Plugin.build(); 2652 2653 KTUtil.data(element).set('scrolltop', the); 2654 } 2655 2656 return the; 2657 }, 2658 2659 /** 2660 * Handles subscrolltop click toggle 2661 * @returns {mscrolltop} 2662 */ 2663 init: function(options) { 2664 the.events = []; 2665 2666 // merge default and user defined options 2667 the.options = KTUtil.deepExtend({}, defaultOptions, options); 2668 }, 2669 2670 build: function() { 2671 var timer; 2672 2673 window.addEventListener('scroll', function() { 2674 KTUtil.throttle(timer, function() { 2675 Plugin.handle(); 2676 }, 200); 2677 }); 2678 2679 // handle button click 2680 KTUtil.addEvent(element, 'click', Plugin.scroll); 2681 }, 2682 2683 /** 2684 * Handles scrolltop click scrollTop 2685 */ 2686 handle: function() { 2687 var pos = KTUtil.getScrollTop(); // current vertical position 2688 2689 if (pos > the.options.offset) { 2690 if (body.hasAttribute('data-scrolltop') === false) { 2691 body.setAttribute('data-scrolltop', 'on'); 2692 } 2693 } else { 2694 if (body.hasAttribute('data-scrolltop') === true) { 2695 body.removeAttribute('data-scrolltop'); 2696 } 2697 } 2698 }, 2699 2700 /** 2701 * Handles scrolltop click scrollTop 2702 */ 2703 scroll: function(e) { 2704 e.preventDefault(); 2705 2706 KTUtil.scrollTop(0, the.options.speed); 2707 }, 2708 2709 2710 /** 2711 * Trigger events 2712 */ 2713 eventTrigger: function(name, args) { 2714 for (var i = 0; i < the.events.length; i++) { 2715 var event = the.events[i]; 2716 if (event.name == name) { 2717 if (event.one == true) { 2718 if (event.fired == false) { 2719 the.events[i].fired = true; 2720 return event.handler.call(this, the, args); 2721 } 2722 } else { 2723 return event.handler.call(this, the, args); 2724 } 2725 } 2726 } 2727 }, 2728 2729 addEvent: function(name, handler, one) { 2730 the.events.push({ 2731 name: name, 2732 handler: handler, 2733 one: one, 2734 fired: false 2735 }); 2736 } 2737 }; 2738 2739 ////////////////////////// 2740 // ** Public Methods ** // 2741 ////////////////////////// 2742 2743 /** 2744 * Set default options 2745 */ 2746 2747 the.setDefaults = function(options) { 2748 defaultOptions = options; 2749 }; 2750 2751 /** 2752 * Get subscrolltop mode 2753 */ 2754 the.on = function(name, handler) { 2755 return Plugin.addEvent(name, handler); 2756 }; 2757 2758 /** 2759 * Set scrolltop content 2760 * @returns {mscrolltop} 2761 */ 2762 the.one = function(name, handler) { 2763 return Plugin.addEvent(name, handler, true); 2764 }; 2765 2766 /////////////////////////////// 2767 // ** Plugin Construction ** // 2768 /////////////////////////////// 2769 2770 // Run plugin 2771 Plugin.construct.apply(the, [options]); 2772 2773 // Init done 2774 init = true; 2775 2776 // Return plugin instance 2777 return the; 2778}; 2779 2780// webpack support 2781if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 2782 module.exports = KTScrolltop; 2783} 2784 2785"use strict"; 2786 2787// Component Definition 2788var KTToggle = function(toggleElement, targetElement, options) { 2789 // Main object 2790 var the = this; 2791 var init = false;
2792 2793 // Get element object 2794 var element = toggleElement; 2795 var target = targetElement; 2796 2797 if (!element) { 2798 return; 2799 } 2800 2801 // Default options 2802 var defaultOptions = { 2803 targetToggleMode: 'class' // class|attribute 2804 }; 2805 2806 //////////////////////////// 2807 // ** Private Methods ** // 2808 //////////////////////////// 2809 2810 var Plugin = { 2811 /** 2812 * Construct 2813 */ 2814 2815 construct: function(options) { 2816 if (KTUtil.data(element).has('toggle')) { 2817 the = KTUtil.data(element).get('toggle'); 2818 } else { 2819 // reset menu 2820 Plugin.init(options); 2821 2822 // build menu 2823 Plugin.build(); 2824 2825 KTUtil.data(element).set('toggle', the); 2826 } 2827 2828 return the; 2829 }, 2830 2831 /** 2832 * Handles subtoggle click toggle 2833 */ 2834 init: function(options) { 2835 the.element = element; 2836 the.events = []; 2837 2838 // Merge default and user defined options 2839 the.options = KTUtil.deepExtend({}, defaultOptions, options); 2840 2841 //alert(the.options.target.tagName); 2842 the.target = target; 2843 2844 the.targetState = the.options.targetState; 2845 the.toggleState = the.options.toggleState; 2846 2847 if (the.options.targetToggleMode == 'class') { 2848 the.state = KTUtil.hasClasses(the.target, the.targetState) ? 'on' : 'off'; 2849 } else { 2850 the.state = KTUtil.hasAttr(the.target, 'data-' + the.targetState) ? KTUtil.attr(the.target, 'data-' + the.targetState) : 'off'; 2851 } 2852 }, 2853 2854 /** 2855 * Setup toggle 2856 */ 2857 build: function() { 2858 KTUtil.addEvent(element, 'mouseup', Plugin.toggle); 2859 }, 2860 2861 /** 2862 * Handles offcanvas click toggle 2863 */ 2864 toggle: function(e) { 2865 Plugin.eventTrigger('beforeToggle'); 2866 2867 if (the.state == 'off') { 2868 Plugin.toggleOn(); 2869 } else { 2870 Plugin.toggleOff(); 2871 } 2872 2873 Plugin.eventTrigger('afterToggle'); 2874 2875 e.preventDefault(); 2876 2877 return the; 2878 }, 2879 2880 /** 2881 * Handles toggle click toggle 2882 */ 2883 toggleOn: function() { 2884 Plugin.eventTrigger('beforeOn'); 2885 2886 if (the.options.targetToggleMode == 'class') { 2887 KTUtil.addClass(the.target, the.targetState); 2888 } else { 2889 KTUtil.attr(the.target, 'data-' + the.targetState, 'on'); 2890 } 2891 2892 if (the.toggleState) { 2893 KTUtil.addClass(element, the.toggleState); 2894 } 2895 2896 the.state = 'on'; 2897 2898 Plugin.eventTrigger('afterOn'); 2899 2900 Plugin.eventTrigger('toggle'); 2901 2902 return the; 2903 }, 2904 2905 /** 2906 * Handles toggle click toggle 2907 */ 2908 toggleOff: function() { 2909 Plugin.eventTrigger('beforeOff'); 2910 2911 if (the.options.targetToggleMode == 'class') { 2912 KTUtil.removeClass(the.target, the.targetState); 2913 } else { 2914 KTUtil.removeAttr(the.target, 'data-' + the.targetState); 2915 } 2916 2917 if (the.toggleState) { 2918 KTUtil.removeClass(element, the.toggleState); 2919 } 2920 2921 the.state = 'off'; 2922 2923 Plugin.eventTrigger('afterOff'); 2924 2925 Plugin.eventTrigger('toggle'); 2926 2927 return the; 2928 }, 2929 2930 /** 2931 * Trigger events 2932 */ 2933 eventTrigger: function(name) { 2934 for (var i = 0; i < the.events.length; i++) { 2935 var event = the.events[i]; 2936 2937 if (event.name == name) { 2938 if (event.one == true) { 2939 if (event.fired == false) { 2940 the.events[i].fired = true; 2941 return event.handler.call(this, the); 2942 } 2943 } else { 2944 return event.handler.call(this, the); 2945 } 2946 } 2947 } 2948 }, 2949 2950 addEvent: function(name, handler, one) { 2951 the.events.push({ 2952 name: name, 2953 handler: handler, 2954 one: one, 2955 fired: false 2956 }); 2957 2958 return the; 2959 } 2960 }; 2961
2962 ////////////////////////// 2963 // ** Public Methods ** // 2964 ////////////////////////// 2965 2966 /** 2967 * Set default options 2968 */ 2969 2970 the.setDefaults = function(options) { 2971 defaultOptions = options; 2972 }; 2973 2974 /** 2975 * Get toggle state 2976 */ 2977 the.getState = function() { 2978 return the.state; 2979 }; 2980 2981 /** 2982 * Toggle 2983 */ 2984 the.toggle = function() { 2985 return Plugin.toggle(); 2986 }; 2987 2988 /** 2989 * Toggle on 2990 */ 2991 the.toggleOn = function() { 2992 return Plugin.toggleOn(); 2993 }; 2994 2995 /** 2996 * Toggle off 2997 */ 2998 the.toggleOff = function() { 2999 return Plugin.toggleOff(); 3000 }; 3001 3002 /** 3003 * Attach event 3004 * @returns {KTToggle} 3005 */ 3006 the.on = function(name, handler) { 3007 return Plugin.addEvent(name, handler); 3008 }; 3009 3010 /** 3011 * Attach event that will be fired once 3012 * @returns {KTToggle} 3013 */ 3014 the.one = function(name, handler) { 3015 return Plugin.addEvent(name, handler, true); 3016 }; 3017 3018 // Construct plugin 3019 Plugin.construct.apply(the, [options]); 3020 3021 return the; 3022}; 3023 3024// webpack support 3025if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 3026 module.exports = KTToggle; 3027} 3028 3029"use strict"; 3030 3031/** 3032 * @class KTUtil base utilize class that privides helper functions 3033 */ 3034 3035// Polyfills 3036/** 3037 * Element.matches() polyfill (simple version) 3038 * https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill 3039 */ 3040if (!Element.prototype.matches) { 3041 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; 3042} 3043 3044/** 3045 * Element.closest() polyfill 3046 * https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill 3047 */ 3048if (!Element.prototype.closest) { 3049 if (!Element.prototype.matches) { 3050 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; 3051 } 3052 Element.prototype.closest = function (s) { 3053 var el = this; 3054 var ancestor = this; 3055 if (!document.documentElement.contains(el)) return null; 3056 do { 3057 if (ancestor.matches(s)) return ancestor; 3058 ancestor = ancestor.parentElement; 3059 } while (ancestor !== null); 3060 return null; 3061 }; 3062} 3063 3064/** 3065 * ChildNode.remove() polyfill 3066 * https://gomakethings.com/removing-an-element-from-the-dom-the-es6-way/ 3067 * @author Chris Ferdinandi 3068 * @license MIT 3069 */ 3070(function (elem) { 3071 for (var i = 0; i < elem.length; i++) { 3072 if (!window[elem[i]] || 'remove' in window[elem[i]].prototype) continue; 3073 window[elem[i]].prototype.remove = function () { 3074 this.parentNode.removeChild(this); 3075 }; 3076 } 3077})(['Element', 'CharacterData', 'DocumentType']); 3078 3079 3080// 3081// requestAnimationFrame polyfill by Erik Möller. 3082// With fixes from Paul Irish and Tino Zijdel 3083// 3084// http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 3085// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 3086// 3087// MIT license 3088// 3089(function() { 3090 var lastTime = 0; 3091 var vendors = ['webkit', 'moz']; 3092 for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 3093 window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; 3094 window.cancelAnimationFrame = 3095 window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame']; 3096 } 3097 3098 if (!window.requestAnimationFrame) 3099 window.requestAnimationFrame = function(callback) { 3100 var currTime = new Date().getTime(); 3101 var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 3102 var id = window.setTimeout(function() { 3103 callback(currTime + timeToCall); 3104 }, timeToCall); 3105 lastTime = currTime + timeToCall; 3106 return id; 3107 }; 3108 3109 if (!window.cancelAnimationFrame) 3110 window.cancelAnimationFrame = function(id) { 3111 clearTimeout(id); 3112 }; 3113}()); 3114 3115// Source: https://github.com/jserz/js_piece/blob/master/DOM/ParentNode/prepend()/prepend().md 3116(function(arr) { 3117 arr.forEach(function(item) { 3118 if (item.hasOwnProperty('prepend')) { 3119 return; 3120 } 3121 Object.defineProperty(item, 'prepend', { 3122 configurable: true, 3123 enumerable: true, 3124 writable: true, 3125 value: function prepend() { 3126 var argArr = Array.prototype.slice.call(arguments), 3127 docFrag = document.createDocumentFragment(); 3128 3129 argArr.forEach(function(argItem) { 3130 var isNode = argItem instanceof Node; 3131 docFrag.appendChild(isNode ? argItem : document.createTextNode(String(argItem))); 3132 }); 3133 3134 this.insertBefore(docFrag, this.firstChild); 3135 } 3136 }); 3137 }); 3138})([Element.prototype, Document.prototype, DocumentFragment.prototype]); 3139 3140// getAttributeNames 3141if (Element.prototype.getAttributeNames == undefined) { 3142 Element.prototype.getAttributeNames = function () { 3143 var attributes = this.attributes; 3144 var length = attributes.length; 3145 var result = new Array(length); 3146 for (var i = 0; i < length; i++) { 3147 result[i] = attributes[i].name; 3148 } 3149 return result; 3150 }; 3151} 3152 3153// Global variables 3154window.KTUtilElementDataStore = {}; 3155window.KTUtilElementDataStoreID = 0; 3156window.KTUtilDelegatedEventHandlers = {}; 3157 3158var KTUtil = function() { 3159 var resizeHandlers = []; 3160 3161 /** @type {object} breakpoints The device width breakpoints **/ 3162 var breakpoints = { 3163 sm: 544, // Small screen / phone 3164 md: 768, // Medium screen / tablet 3165 lg: 992, // Large screen / desktop 3166 xl: 1200 // Extra large screen / wide desktop 3167 }; 3168 3169 /** 3170 * Handle window resize event with some 3171 * delay to attach event handlers upon resize complete 3172 */ 3173 var _windowResizeHandler = function() { 3174 var _runResizeHandlers = function() { 3175 // reinitialize other subscribed elements 3176 for (var i = 0; i < resizeHandlers.length; i++) { 3177 var each = resizeHandlers[i]; 3178 each.call(); 3179 } 3180 }; 3181 3182 var timer; 3183 3184 window.addEventListener('resize', function() { 3185 KTUtil.throttle(timer, function() { 3186 _runResizeHandlers(); 3187 }, 200); 3188 }); 3189 }; 3190 3191 return { 3192 /** 3193 * Class main initializer. 3194 * @param {object} settings. 3195 * @returns null 3196 */ 3197 //main function to initiate the theme 3198 init: function(settings) { 3199 if (settings && settings.breakpoints) { 3200 breakpoints = settings.breakpoints; 3201 } 3202 3203 _windowResizeHandler(); 3204 }, 3205 3206 /** 3207 * Adds window resize event handler. 3208 * @param {function} callback function. 3209 */ 3210 addResizeHandler: function(callback) { 3211 resizeHandlers.push(callback); 3212 }, 3213 3214 /** 3215 * Removes window resize event handler. 3216 * @param {function} callback function. 3217 */ 3218 removeResizeHandler: function(callback) { 3219 for (var i = 0; i < resizeHandlers.length; i++) { 3220 if (callback === resizeHandlers[i]) { 3221 delete resizeHandlers[i]; 3222 } 3223 } 3224 }, 3225 3226 /** 3227 * Trigger window resize handlers. 3228 */ 3229 runResizeHandlers: function() { 3230 _runResizeHandlers(); 3231 }, 3232 3233 resize: function() { 3234 if (typeof(Event) === 'function') { 3235 // modern browsers 3236 window.dispatchEvent(new Event('resize')); 3237 } else { 3238 // for IE and other old browsers 3239 // causes deprecation warning on modern browsers 3240 var evt = window.document.createEvent('UIEvents'); 3241 evt.initUIEvent('resize', true, false, window, 0); 3242 window.dispatchEvent(evt); 3243 } 3244 }, 3245 3246 /** 3247 * Get GET parameter value from URL. 3248 * @param {string} paramName Parameter name. 3249 * @returns {string} 3250 */ 3251 getURLParam: function(paramName) { 3252 var searchString = window.location.search.substring(1), 3253 i, val, params = searchString.split("&"); 3254 3255 for (i = 0; i < params.length; i++) { 3256 val = params[i].split("="); 3257 if (val[0] == paramName) { 3258 return unescape(val[1]); 3259 } 3260 } 3261 3262 return null; 3263 }, 3264 3265 /** 3266 * Checks whether current device is mobile touch. 3267 * @returns {boolean} 3268 */ 3269 isMobileDevice: function() { 3270 var test = (this.getViewPort().width < this.getBreakp
3270oint('lg') ? true : false); 3271 3272 if (test === false) { 3273 // For use within normal web clients 3274 test = navigator.userAgent.match(/iPad/i) != null; 3275 } 3276 3277 return test; 3278 }, 3279 3280 /** 3281 * Checks whether current device is desktop. 3282 * @returns {boolean} 3283 */ 3284 isDesktopDevice: function() { 3285 return KTUtil.isMobileDevice() ? false : true; 3286 }, 3287 3288 /** 3289 * Gets browser window viewport size. Ref: 3290 * http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/ 3291 * @returns {object} 3292 */ 3293 getViewPort: function() { 3294 var e = window, 3295 a = 'inner'; 3296 if (!('innerWidth' in window)) { 3297 a = 'client'; 3298 e = document.documentElement || document.body; 3299 } 3300 3301 return { 3302 width: e[a + 'Width'], 3303 height: e[a + 'Height'] 3304 }; 3305 }, 3306 3307 /** 3308 * Checks whether given device mode is currently activated. 3309 * @param {string} mode Responsive mode name(e.g: desktop, 3310 * desktop-and-tablet, tablet, tablet-and-mobile, mobile) 3311 * @returns {boolean} 3312 */ 3313 isInResponsiveRange: function(mode) { 3314 var breakpoint = this.getViewPort().width; 3315 3316 if (mode == 'general') { 3317 return true; 3318 } else if (mode == 'desktop' && breakpoint >= (this.getBreakpoint('lg') + 1)) { 3319 return true; 3320 } else if (mode == 'tablet' && (breakpoint >= (this.getBreakpoint('md') + 1) && breakpoint < this.getBreakpoint('lg'))) { 3321 return true; 3322 } else if (mode == 'mobile' && breakpoint <= this.getBreakpoint('md')) { 3323 return true; 3324 } else if (mode == 'desktop-and-tablet' && breakpoint >= (this.getBreakpoint('md') + 1)) { 3325 return true; 3326 } else if (mode == 'tablet-and-mobile' && breakpoint <= this.getBreakpoint('lg')) { 3327 return true; 3328 } else if (mode == 'minimal-desktop-and-below' && breakpoint <= this.getBreakpoint('xl')) { 3329 return true; 3330 } 3331 3332 return false; 3333 }, 3334 3335 /** 3336 * Checks whether given device mode is currently activated. 3337 * @param {string} mode Responsive mode name(e.g: desktop, 3338 * desktop-and-tablet, tablet, tablet-and-mobile, mobile) 3339 * @returns {boolean} 3340 */ 3341 isBreakpointUp: function(mode) { 3342 var width = this.getViewPort().width; 3343 var breakpoint = this.getBreakpoint(mode); 3344 3345 return (width >= breakpoint); 3346 }, 3347 3348 isBreakpointDown: function(mode) { 3349 var width = this.getViewPort().width; 3350 var breakpoint = this.getBreakpoint(mode); 3351 3352 return (width < breakpoint); 3353 }, 3354 3355 /** 3356 * Generates unique ID for give prefix. 3357 * @param {string} prefix Prefix for generated ID 3358 * @returns {boolean} 3359 */ 3360 getUniqueID: function(prefix) { 3361 return prefix + Math.floor(Math.random() * (new Date()).getTime()); 3362 }, 3363 3364 /** 3365 * Gets window width for give breakpoint mode. 3366 * @param {string} mode Responsive mode name(e.g: xl, lg, md, sm) 3367 * @returns {number} 3368 */ 3369 getBreakpoint: function(mode) { 3370 return breakpoints[mode]; 3371 }, 3372 3373 /** 3374 * Checks whether object has property matchs given key path. 3375 * @param {object} obj Object contains values paired with given key path 3376 * @param {string} keys Keys path seperated with dots 3377 * @returns {object} 3378 */ 3379 isset: function(obj, keys) { 3380 var stone; 3381 3382 keys = keys || ''; 3383 3384 if (keys.indexOf('[') !== -1) { 3385 throw new Error('Unsupported object path notation.'); 3386 } 3387 3388 keys = keys.split('.'); 3389 3390 do { 3391 if (obj === undefined) { 3392 return false; 3393 } 3394 3395 stone = keys.shift(); 3396 3397 if (!obj.hasOwnProperty(stone)) { 3398 return false;
3399 } 3400 3401 obj = obj[stone]; 3402 3403 } while (keys.length); 3404 3405 return true; 3406 }, 3407 3408 /** 3409 * Gets highest z-index of the given element parents 3410 * @param {object} el jQuery element object 3411 * @returns {number} 3412 */ 3413 getHighestZindex: function(el) { 3414 var position, value; 3415 3416 while (el && el !== document) { 3417 // Ignore z-index if position is set to a value where z-index is ignored by the browser 3418 // This makes behavior of this function consistent across browsers 3419 // WebKit always returns auto if the element is positioned 3420 position = KTUtil.css(el, 'position'); 3421 3422 if (position === "absolute" || position === "relative" || position === "fixed") { 3423 // IE returns 0 when zIndex is not specified 3424 // other browsers return a string 3425 // we ignore the case of nested elements with an explicit value of 0 3426 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 3427 value = parseInt(KTUtil.css(el, 'z-index')); 3428 3429 if (!isNaN(value) && value !== 0) { 3430 return value; 3431 } 3432 } 3433 3434 el = el.parentNode; 3435 } 3436 3437 return null; 3438 }, 3439 3440 /** 3441 * Checks whether the element has any parent with fixed positionfreg 3442 * @param {object} el jQuery element object 3443 * @returns {boolean} 3444 */ 3445 hasFixedPositionedParent: function(el) { 3446 var position; 3447 3448 while (el && el !== document) { 3449 position = KTUtil.css(el, 'position'); 3450 3451 if (position === "fixed") { 3452 return true; 3453 } 3454 3455 el = el.parentNode; 3456 } 3457 3458 return false; 3459 }, 3460 3461 /** 3462 * Simulates delay 3463 */ 3464 sleep: function(milliseconds) { 3465 var start = new Date().getTime(); 3466 for (var i = 0; i < 1e7; i++) { 3467 if ((new Date().getTime() - start) > milliseconds) { 3468 break; 3469 } 3470 } 3471 }, 3472 3473 /** 3474 * Gets randomly generated integer value within given min and max range 3475 * @param {number} min Range start value 3476 * @param {number} max Range end value 3477 * @returns {number} 3478 */ 3479 getRandomInt: function(min, max) { 3480 return Math.floor(Math.random() * (max - min + 1)) + min; 3481 }, 3482 3483 /** 3484 * Checks whether Angular library is included 3485 * @returns {boolean} 3486 */ 3487 isAngularVersion: function() { 3488 return window.Zone !== undefined ? true : false; 3489 }, 3490 3491 // Deep extend: $.extend(true, {}, objA, objB); 3492 deepExtend: function(out) { 3493 out = out || {}; 3494 3495 for (var i = 1; i < arguments.length; i++) { 3496 var obj = arguments[i]; 3497 if (!obj) continue; 3498 3499 for (var key in obj) { 3500 if (!obj.hasOwnProperty(key)) { 3501 continue; 3502 } 3503 3504 // based on https://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/ 3505 if ( Object.prototype.toString.call(obj[key]) === '[object Object]' ) { 3506 out[key] = KTUtil.deepExtend(out[key], obj[key]); 3507 continue; 3508 } 3509 3510 out[key] = obj[key]; 3511 } 3512 } 3513 3514 return out; 3515 }, 3516 3517 // extend: $.extend({}, objA, objB); 3518 extend: function(out) { 3519 out = out || {}; 3520 3521 for (var i = 1; i < arguments.length; i++) { 3522 if (!arguments[i]) 3523 continue; 3524 3525 for (var key in arguments[i]) { 3526 if (arguments[i].hasOwnProperty(key)) 3527 out[key] = arguments[i][key]; 3528 } 3529 } 3530 3531 return out; 3532 }, 3533 3534 getById: function(el) { 3535 if (typeof el === 'string') { 3536 return document.getElementById(el); 3537 } else { 3538 return el; 3539 } 3540 }, 3541 3542 getByTag: function(query) { 3543 return document.getElementsByTagName(query); 3544 }, 3545 3546 getByTagName: function(query) { 3547 return document.getElementsByTagName(query); 3548 }, 3549 3550 getByClass: function(query) { 3551 return document.getElementsByClassName(query); 3552 }, 3553 3554 getBody: function() { 3555 return document.getElementsByTagName('body')[0]; 3556 }, 3557 3558 /** 3559 * Checks whether the element has given classes 3560 * @param {object} el jQuery element object 3561 * @param {string} Classes string 3562 * @returns {boolean} 3563 */ 3564 hasClasses: function(el, classes) { 3565 if (!el) { 3566 return; 3567 } 3568 3569 var classesArr = classes.split(" "); 3570 3571 for (var i = 0; i < classesArr.length; i++) { 3572 if (KTUtil.hasClass(el, KTUtil.trim(classesArr[i])) == false) { 3573 return false;
3574 } 3575 } 3576 3577 return true; 3578 }, 3579 3580 hasClass: function(el, className) { 3581 if (!el) { 3582 return; 3583 } 3584 3585 return el.classList ? el.classList.contains(className) : new RegExp('\\b' + className + '\\b').test(el.className); 3586 }, 3587 3588 addClass: function(el, className) { 3589 if (!el || typeof className === 'undefined') { 3590 return; 3591 } 3592 3593 var classNames = className.split(' '); 3594 3595 if (el.classList) { 3596 for (var i = 0; i < classNames.length; i++) { 3597 if (classNames[i] && classNames[i].length > 0) { 3598 el.classList.add(KTUtil.trim(classNames[i])); 3599 } 3600 } 3601 } else if (!KTUtil.hasClass(el, className)) { 3602 for (var x = 0; x < classNames.length; x++) { 3603 el.className += ' ' + KTUtil.trim(classNames[x]); 3604 } 3605 } 3606 }, 3607 3608 removeClass: function(el, className) { 3609 if (!el || typeof className === 'undefined') { 3610 return; 3611 } 3612 3613 var classNames = className.split(' '); 3614 3615 if (el.classList) { 3616 for (var i = 0; i < classNames.length; i++) { 3617 el.classList.remove(KTUtil.trim(classNames[i])); 3618 } 3619 } else if (KTUtil.hasClass(el, className)) { 3620 for (var x = 0; x < classNames.length; x++) { 3621 el.className = el.className.replace(new RegExp('\\b' + KTUtil.trim(classNames[x]) + '\\b', 'g'), ''); 3622 } 3623 } 3624 }, 3625 3626 triggerCustomEvent: function(el, eventName, data) { 3627 var event; 3628 if (window.CustomEvent) { 3629 event = new CustomEvent(eventName, { 3630 detail: data 3631 }); 3632 } else { 3633 event = document.createEvent('CustomEvent'); 3634 event.initCustomEvent(eventName, true, true, data); 3635 } 3636 3637 el.dispatchEvent(event); 3638 }, 3639 3640 triggerEvent: function(node, eventName) { 3641 // Make sure we use the ownerDocument from the provided node to avoid cross-window problems 3642 var doc; 3643 if (node.ownerDocument) { 3644 doc = node.ownerDocument; 3645 } else if (node.nodeType == 9) { 3646 // the node may be the document itself, nodeType 9 = DOCUMENT_NODE 3647 doc = node; 3648 } else { 3649 throw new Error("Invalid node passed to fireEvent: " + node.id); 3650 } 3651 3652 if (node.dispatchEvent) { 3653 // Gecko-style approach (now the standard) takes more work 3654 var eventClass = ""; 3655 3656 // Different events have different event classes. 3657 // If this switch statement can't map an eventName to an eventClass, 3658 // the event firing is going to fail. 3659 switch (eventName) { 3660 case "click": // Dispatching of 'click' appears to not work correctly in Safari. Use 'mousedown' or 'mouseup' instead. 3661 case "mouseenter": 3662 case "mouseleave": 3663 case "mousedown": 3664 case "mouseup": 3665 eventClass = "MouseEvents"; 3666 break; 3667 3668 case "focus": 3669 case "change": 3670 case "blur": 3671 case "select": 3672 eventClass = "HTMLEvents"; 3673 break; 3674 3675 default: 3676 throw "fireEvent: Couldn't find an event class for event '" + eventName + "'."; 3677 break; 3678 } 3679 var event = doc.createEvent(eventClass); 3680 3681 var bubbles = eventName == "change" ? false : true; 3682 event.initEvent(eventName, bubbles, true); // All events created as bubbling and cancelable. 3683 3684 event.synthetic = true; // allow detection of synthetic events 3685 // The second parameter says go ahead with the default action 3686 node.dispatchEvent(event, true); 3687 } else if (node.fireEvent) { 3688 // IE-old school style 3689 var event = doc.createEventObject(); 3690 event.synthetic = true; // allow detection of synthetic events 3691 node.fireEvent("on" + eventName, event); 3692 } 3693 }, 3694 3695 index: function( el ){ 3696 var c = el.parentNode.children, i = 0; 3697 for(; i < c.length; i++ ) 3698 if( c[i] == el ) return i; 3699 }, 3700 3701 trim: function(string) { 3702 return string.trim(); 3703 }, 3704 3705 eventTriggered: function(e) { 3706 if (e.currentTarget.dataset.triggered) { 3707 return true; 3708 } else { 3709 e.currentTarget.dataset.triggered = true; 3710 3711 return false;
3712 } 3713 }, 3714 3715 remove: function(el) { 3716 if (el && el.parentNode) { 3717 el.parentNode.removeChild(el); 3718 } 3719 }, 3720 3721 find: function(parent, query) { 3722 parent = KTUtil.getById(parent); 3723 if (parent) { 3724 return parent.querySelector(query); 3725 } 3726 }, 3727 3728 findAll: function(parent, query) { 3729 parent = KTUtil.getById(parent); 3730 if (parent) { 3731 return parent.querySelectorAll(query); 3732 } 3733 }, 3734 3735 insertAfter: function(el, referenceNode) { 3736 return referenceNode.parentNode.insertBefore(el, referenceNode.nextSibling); 3737 }, 3738 3739 parents: function(elem, selector) { 3740 // Element.matches() polyfill 3741 if (!Element.prototype.matches) { 3742 Element.prototype.matches = 3743 Element.prototype.matchesSelector || 3744 Element.prototype.mozMatchesSelector || 3745 Element.prototype.msMatchesSelector || 3746 Element.prototype.oMatchesSelector || 3747 Element.prototype.webkitMatchesSelector || 3748 function(s) { 3749 var matches = (this.document || this.ownerDocument).querySelectorAll(s), 3750 i = matches.length; 3751 while (--i >= 0 && matches.item(i) !== this) {} 3752 return i > -1; 3753 }; 3754 } 3755 3756 // Set up a parent array 3757 var parents = []; 3758 3759 // Push each parent element to the array 3760 for ( ; elem && elem !== document; elem = elem.parentNode ) { 3761 if (selector) { 3762 if (elem.matches(selector)) { 3763 parents.push(elem); 3764 } 3765 continue; 3766 } 3767 parents.push(elem); 3768 } 3769 3770 // Return our parent array 3771 return parents; 3772 }, 3773 3774 children: function(el, selector, log) { 3775 if (!el || !el.childNodes) { 3776 return; 3777 } 3778 3779 var result = [], 3780 i = 0, 3781 l = el.childNodes.length; 3782 3783 for (var i; i < l; ++i) { 3784 if (el.childNodes[i].nodeType == 1 && KTUtil.matches(el.childNodes[i], selector, log)) { 3785 result.push(el.childNodes[i]); 3786 } 3787 } 3788 3789 return result; 3790 }, 3791 3792 child: function(el, selector, log) { 3793 var children = KTUtil.children(el, selector, log); 3794 3795 return children ? children[0] : null; 3796 }, 3797 3798 matches: function(el, selector, log) { 3799 var p = Element.prototype; 3800 var f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function(s) { 3801 return [].indexOf.call(document.querySelectorAll(s), this) !== -1; 3802 }; 3803 3804 if (el && el.tagName) { 3805 return f.call(el, selector); 3806 } else { 3807 return false; 3808 } 3809 }, 3810 3811 data: function(el) { 3812 return { 3813 set: function(name, data) { 3814 if (!el) { 3815 return; 3816 } 3817 3818 if (el.customDataTag === undefined) { 3819 window.KTUtilElementDataStoreID++; 3820 el.customDataTag = window.KTUtilElementDataStoreID; 3821 } 3822 3823 if (window.KTUtilElementDataStore[el.customDataTag] === undefined) { 3824 window.KTUtilElementDataStore[el.customDataTag] = {}; 3825 } 3826 3827 window.KTUtilElementDataStore[el.customDataTag][name] = data; 3828 }, 3829 3830 get: function(name) { 3831 if (!el) { 3832 return; 3833 } 3834 3835 if (el.customDataTag === undefined) { 3836 return null; 3837 } 3838 3839 return this.has(name) ? window.KTUtilElementDataStore[el.customDataTag][name] : null; 3840 }, 3841 3842 has: function(name) { 3843 if (!el) { 3844 return false;
3845 } 3846 3847 if (el.customDataTag === undefined) { 3848 return false; 3849 } 3850 3851 return (window.KTUtilElementDataStore[el.customDataTag] && window.KTUtilElementDataStore[el.customDataTag][name]) ? true : false; 3852 }, 3853 3854 remove: function(name) { 3855 if (el && this.has(name)) { 3856 delete window.KTUtilElementDataStore[el.customDataTag][name]; 3857 } 3858 } 3859 }; 3860 }, 3861 3862 outerWidth: function(el, margin) { 3863 var width; 3864 3865 if (margin === true) { 3866 width = parseFloat(el.offsetWidth); 3867 width += parseFloat(KTUtil.css(el, 'margin-left')) + parseFloat(KTUtil.css(el, 'margin-right')); 3868 3869 return parseFloat(width); 3870 } else { 3871 width = parseFloat(el.offsetWidth); 3872 3873 return width; 3874 } 3875 }, 3876 3877 offset: function(el) { 3878 var rect, win; 3879 3880 if ( !el ) { 3881 return; 3882 } 3883 3884 // Return zeros for disconnected and hidden (display: none) elements (gh-2310) 3885 // Support: IE <=11 only 3886 // Running getBoundingClientRect on a 3887 // disconnected node in IE throws an error 3888 3889 if ( !el.getClientRects().length ) { 3890 return { top: 0, left: 0 }; 3891 } 3892 3893 // Get document-relative position by adding viewport scroll to viewport-relative gBCR 3894 rect = el.getBoundingClientRect(); 3895 win = el.ownerDocument.defaultView; 3896 3897 return { 3898 top: rect.top + win.pageYOffset, 3899 left: rect.left + win.pageXOffset 3900 }; 3901 }, 3902 3903 height: function(el) { 3904 return KTUtil.css(el, 'height'); 3905 }, 3906 3907 outerHeight: function(el, withMargin) { 3908 var height = el.offsetHeight; 3909 var style; 3910 3911 if (typeof withMargin !== 'undefined' && withMargin === true) { 3912 style = getComputedStyle(el); 3913 height += parseInt(style.marginTop) + parseInt(style.marginBottom); 3914 3915 return height; 3916 } else { 3917 return height; 3918 } 3919 }, 3920 3921 visible: function(el) { 3922 return !(el.offsetWidth === 0 && el.offsetHeight === 0); 3923 }, 3924 3925 attr: function(el, name, value) { 3926 if (el == undefined) { 3927 return; 3928 } 3929 3930 if (value !== undefined) { 3931 el.setAttribute(name, value); 3932 } else { 3933 return el.getAttribute(name); 3934 } 3935 }, 3936 3937 hasAttr: function(el, name) { 3938 if (el == undefined) { 3939 return; 3940 } 3941 3942 return el.getAttribute(name) ? true : false; 3943 }, 3944 3945 removeAttr: function(el, name) { 3946 if (el == undefined) { 3947 return; 3948 } 3949 3950 el.removeAttribute(name); 3951 }, 3952 3953 animate: function(from, to, duration, update, easing, done) { 3954 /** 3955 * TinyAnimate.easings 3956 * Adapted from jQuery Easing 3957 */ 3958 var easings = {}; 3959 var easing; 3960 3961 easings.linear = function(t, b, c, d) { 3962 return c * t / d + b; 3963 }; 3964 3965 easing = easings.linear; 3966 3967 // Early bail out if called incorrectly 3968 if (typeof from !== 'number' || 3969 typeof to !== 'number' || 3970 typeof duration !== 'number' || 3971 typeof update !== 'function') { 3972 return; 3973 } 3974 3975 // Create mock done() function if necessary 3976 if (typeof done !== 'function') { 3977 done = function() {}; 3978 } 3979 3980 // Pick implementation (requestAnimationFrame | setTimeout) 3981 var rAF = window.requestAnimationFrame || function(callback) { 3982 window.setTimeout(callback, 1000 / 50); 3983 }; 3984 3985 // Animation loop 3986 var canceled = false;
3987 var change = to - from; 3988 3989 function loop(timestamp) { 3990 var time = (timestamp || +new Date()) - start; 3991 3992 if (time >= 0) { 3993 update(easing(time, from, change, duration)); 3994 } 3995 if (time >= 0 && time >= duration) { 3996 update(to); 3997 done(); 3998 } else { 3999 rAF(loop); 4000 } 4001 } 4002 4003 update(from); 4004 4005 // Start animation loop 4006 var start = window.performance && window.performance.now ? window.performance.now() : +new Date(); 4007 4008 rAF(loop); 4009 }, 4010 4011 actualCss: function(el, prop, cache) { 4012 var css = ''; 4013 4014 if (el instanceof HTMLElement === false) { 4015 return; 4016 } 4017 4018 if (!el.getAttribute('kt-hidden-' + prop) || cache === false) { 4019 var value; 4020 4021 // the element is hidden so: 4022 // making the el block so we can meassure its height but still be hidden 4023 css = el.style.cssText; 4024 el.style.cssText = 'position: absolute; visibility: hidden; display: block;'; 4025 4026 if (prop == 'width') { 4027 value = el.offsetWidth; 4028 } else if (prop == 'height') { 4029 value = el.offsetHeight; 4030 } 4031 4032 el.style.cssText = css; 4033 4034 // store it in cache 4035 el.setAttribute('kt-hidden-' + prop, value); 4036 4037 return parseFloat(value); 4038 } else { 4039 // store it in cache 4040 return parseFloat(el.getAttribute('kt-hidden-' + prop)); 4041 } 4042 }, 4043 4044 actualHeight: function(el, cache) { 4045 return KTUtil.actualCss(el, 'height', cache); 4046 }, 4047 4048 actualWidth: function(el, cache) { 4049 return KTUtil.actualCss(el, 'width', cache); 4050 }, 4051 4052 getScroll: function(element, method) { 4053 // The passed in `method` value should be 'Top' or 'Left' 4054 method = 'scroll' + method; 4055 return (element == window || element == document) ? ( 4056 self[(method == 'scrollTop') ? 'pageYOffset' : 'pageXOffset'] || 4057 (browserSupportsBoxModel && document.documentElement[method]) || 4058 document.body[method] 4059 ) : element[method]; 4060 }, 4061 4062 css: function(el, styleProp, value) { 4063 if (!el) { 4064 return; 4065 } 4066 4067 if (value !== undefined) { 4068 el.style[styleProp] = value; 4069 } else { 4070 var defaultView = (el.ownerDocument || document).defaultView; 4071 // W3C standard way: 4072 if (defaultView && defaultView.getComputedStyle) { 4073 // sanitize property name to css notation 4074 // (hyphen separated words eg. font-Size) 4075 styleProp = styleProp.replace(/([A-Z])/g, "-$1").toLowerCase(); 4076 return defaultView.getComputedStyle(el, null).getPropertyValue(styleProp); 4077 } else if (el.currentStyle) { // IE 4078 // sanitize property name to camelCase 4079 styleProp = styleProp.replace(/\-(\w)/g, function(str, letter) { 4080 return letter.toUpperCase(); 4081 }); 4082 value = el.currentStyle[styleProp]; 4083 // convert other units to pixels on IE 4084 if (/^\d+(em|pt|%|ex)?$/i.test(value)) { 4085 return (function(value) { 4086 var oldLeft = el.style.left, 4087 oldRsLeft = el.runtimeStyle.left; 4088 el.runtimeStyle.left = el.currentStyle.left; 4089 el.style.left = value || 0; 4090 value = el.style.pixelLeft + "px"; 4091 el.style.left = oldLeft; 4092 el.runtimeStyle.left = oldRsLeft; 4093 return value; 4094 })(value); 4095 } 4096 return value; 4097 } 4098 } 4099 }, 4100 4101 slide: function(el, dir, speed, callback, recalcMaxHeight) { 4102 if (!el || (dir == 'up' && KTUtil.visible(el) === false) || (dir == 'down' && KTUtil.visible(el) === true)) { 4103 return; 4104 } 4105 4106 speed = (speed ? speed : 600); 4107 var calcHeight = KTUtil.actualHeight(el); 4108 var calcPaddingTop = false;
4109 var calcPaddingBottom = false; 4110 4111 if (KTUtil.css(el, 'padding-top') && KTUtil.data(el).has('slide-padding-top') !== true) { 4112 KTUtil.data(el).set('slide-padding-top', KTUtil.css(el, 'padding-top')); 4113 } 4114 4115 if (KTUtil.css(el, 'padding-bottom') && KTUtil.data(el).has('slide-padding-bottom') !== true) { 4116 KTUtil.data(el).set('slide-padding-bottom', KTUtil.css(el, 'padding-bottom')); 4117 } 4118 4119 if (KTUtil.data(el).has('slide-padding-top')) { 4120 calcPaddingTop = parseInt(KTUtil.data(el).get('slide-padding-top')); 4121 } 4122 4123 if (KTUtil.data(el).has('slide-padding-bottom')) { 4124 calcPaddingBottom = parseInt(KTUtil.data(el).get('slide-padding-bottom')); 4125 } 4126 4127 if (dir == 'up') { // up 4128 el.style.cssText = 'display: block; overflow: hidden;'; 4129 4130 if (calcPaddingTop) { 4131 KTUtil.animate(0, calcPaddingTop, speed, function(value) { 4132 el.style.paddingTop = (calcPaddingTop - value) + 'px'; 4133 }, 'linear'); 4134 } 4135 4136 if (calcPaddingBottom) { 4137 KTUtil.animate(0, calcPaddingBottom, speed, function(value) { 4138 el.style.paddingBottom = (calcPaddingBottom - value) + 'px'; 4139 }, 'linear'); 4140 } 4141 4142 KTUtil.animate(0, calcHeight, speed, function(value) { 4143 el.style.height = (calcHeight - value) + 'px'; 4144 }, 'linear', function() { 4145 el.style.height = ''; 4146 el.style.display = 'none'; 4147 4148 if (typeof callback === 'function') { 4149 callback(); 4150 } 4151 }); 4152 4153 4154 } else if (dir == 'down') { // down 4155 el.style.cssText = 'display: block; overflow: hidden;'; 4156 4157 if (calcPaddingTop) { 4158 KTUtil.animate(0, calcPaddingTop, speed, function(value) {// 4159 el.style.paddingTop = value + 'px'; 4160 }, 'linear', function() { 4161 el.style.paddingTop = ''; 4162 }); 4163 } 4164 4165 if (calcPaddingBottom) { 4166 KTUtil.animate(0, calcPaddingBottom, speed, function(value) { 4167 el.style.paddingBottom = value + 'px'; 4168 }, 'linear', function() { 4169 el.style.paddingBottom = ''; 4170 }); 4171 } 4172 4173 KTUtil.animate(0, calcHeight, speed, function(value) { 4174 el.style.height = value + 'px'; 4175 }, 'linear', function() { 4176 el.style.height = ''; 4177 el.style.display = ''; 4178 el.style.overflow = ''; 4179 4180 if (typeof callback === 'function') { 4181 callback(); 4182 } 4183 }); 4184 } 4185 }, 4186 4187 slideUp: function(el, speed, callback) { 4188 KTUtil.slide(el, 'up', speed, callback); 4189 }, 4190 4191 slideDown: function(el, speed, callback) { 4192 KTUtil.slide(el, 'down', speed, callback); 4193 }, 4194 4195 show: function(el, display) { 4196 if (typeof el !== 'undefined') { 4197 el.style.display = (display ? display : 'block'); 4198 } 4199 }, 4200 4201 hide: function(el) { 4202 if (typeof el !== 'undefined') { 4203 el.style.display = 'none'; 4204 } 4205 }, 4206 4207 addEvent: function(el, type, handler, one) { 4208 if (typeof el !== 'undefined' && el !== null) { 4209 el.addEventListener(type, handler); 4210 } 4211 }, 4212 4213 removeEvent: function(el, type, handler) { 4214 if (el !== null) { 4215 el.removeEventListener(type, handler); 4216 } 4217 }, 4218 4219 on: function(element, selector, event, handler) { 4220 if (!selector) { 4221 return; 4222 } 4223 4224 var eventId = KTUtil.getUniqueID('event'); 4225 4226 window.KTUtilDelegatedEventHandlers[eventId] = function(e) { 4227 var targets = element.querySelectorAll(selector); 4228 var target = e.target; 4229 4230 while (target && target !== element) { 4231 for (var i = 0, j = targets.length; i < j; i++) { 4232 if (target === targets[i]) { 4233 handler.call(target, e); 4234 } 4235 } 4236 4237 target = target.parentNode; 4238 } 4239 } 4240 4241 KTUtil.addEvent(element, event, window.KTUtilDelegatedEventHandlers[eventId]); 4242 4243 return eventId; 4244 }, 4245 4246 off: function(element, event, eventId) { 4247 if (!element || !window.KTUtilDelegatedEventHandlers[eventId]) { 4248 return; 4249 } 4250 4251 KTUtil.removeEvent(element, event, window.KTUtilDelegatedEventHandlers[eventId]); 4252 4253 delete window.KTUtilDelegatedEventHandlers[eventId]; 4254 }, 4255 4256 one: function onetime(el, type, callback) { 4257 el.addEventListener(type, function callee(e) { 4258 // remove event 4259 if (e.target && e.target.removeEventListener) { 4260 e.target.removeEventListener(e.type, callee); 4261 } 4262
4263 // need to verify from https://themeforest.net/author_dashboard#comment_23615588 4264 if (el && el.removeEventListener) { 4265 e.currentTarget.removeEventListener(e.type, callee); 4266 } 4267 4268 // call handler 4269 return callback(e); 4270 }); 4271 }, 4272 4273 hash: function(str) { 4274 var hash = 0, 4275 i, chr; 4276 4277 if (str.length === 0) return hash; 4278 for (i = 0; i < str.length; i++) { 4279 chr = str.charCodeAt(i); 4280 hash = ((hash << 5) - hash) + chr; 4281 hash |= 0; // Convert to 32bit integer 4282 } 4283 4284 return hash; 4285 }, 4286 4287 animateClass: function(el, animationName, callback) { 4288 var animation; 4289 var animations = { 4290 animation: 'animationend', 4291 OAnimation: 'oAnimationEnd', 4292 MozAnimation: 'mozAnimationEnd', 4293 WebkitAnimation: 'webkitAnimationEnd', 4294 msAnimation: 'msAnimationEnd', 4295 }; 4296 4297 for (var t in animations) { 4298 if (el.style[t] !== undefined) { 4299 animation = animations[t]; 4300 } 4301 } 4302 4303 KTUtil.addClass(el, 'animated ' + animationName); 4304 4305 KTUtil.one(el, animation, function() { 4306 KTUtil.removeClass(el, 'animated ' + animationName); 4307 }); 4308 4309 if (callback) { 4310 KTUtil.one(el, animation, callback); 4311 } 4312 }, 4313 4314 transitionEnd: function(el, callback) { 4315 var transition; 4316 var transitions = { 4317 transition: 'transitionend', 4318 OTransition: 'oTransitionEnd', 4319 MozTransition: 'mozTransitionEnd', 4320 WebkitTransition: 'webkitTransitionEnd', 4321 msTransition: 'msTransitionEnd' 4322 }; 4323 4324 for (var t in transitions) { 4325 if (el.style[t] !== undefined) { 4326 transition = transitions[t]; 4327 } 4328 } 4329 4330 KTUtil.one(el, transition, callback); 4331 }, 4332 4333 animationEnd: function(el, callback) { 4334 var animation; 4335 var animations = { 4336 animation: 'animationend', 4337 OAnimation: 'oAnimationEnd', 4338 MozAnimation: 'mozAnimationEnd', 4339 WebkitAnimation: 'webkitAnimationEnd', 4340 msAnimation: 'msAnimationEnd' 4341 }; 4342 4343 for (var t in animations) { 4344 if (el.style[t] !== undefined) { 4345 animation = animations[t]; 4346 } 4347 } 4348 4349 KTUtil.one(el, animation, callback); 4350 }, 4351 4352 animateDelay: function(el, value) { 4353 var vendors = ['webkit-', 'moz-', 'ms-', 'o-', '']; 4354 for (var i = 0; i < vendors.length; i++) { 4355 KTUtil.css(el, vendors[i] + 'animation-delay', value); 4356 } 4357 }, 4358 4359 animateDuration: function(el, value) { 4360 var vendors = ['webkit-', 'moz-', 'ms-', 'o-', '']; 4361 for (var i = 0; i < vendors.length; i++) { 4362 KTUtil.css(el, vendors[i] + 'animation-duration', value); 4363 } 4364 }, 4365 4366 scrollTo: function(target, offset, duration) { 4367 var duration = duration ? duration : 500; 4368 var targetPos = target ? KTUtil.offset(target).top : 0; 4369 var scrollPos = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; 4370 var from, to; 4371 4372 if (offset) { 4373 scrollPos += offset; 4374 } 4375 4376 from = scrollPos; 4377 to = targetPos; 4378 4379 KTUtil.animate(from, to, duration, function(value) { 4380 document.documentElement.scrollTop = value; 4381 document.body.parentNode.scrollTop = value; 4382 document.body.scrollTop = value; 4383 }); //, easing, done 4384 }, 4385 4386 scrollTop: function(offset, duration) { 4387 KTUtil.scrollTo(null, offset, duration); 4388 }, 4389 4390 isArray: function(obj) { 4391 return obj && Array.isArray(obj); 4392 }, 4393 4394 ready: function(callback) { 4395 if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") { 4396 callback(); 4397 } else { 4398 document.addEventListener('DOMContentLoaded', callback); 4399 } 4400 }, 4401 4402 isEmpty: function(obj) { 4403 for (var prop in obj) { 4404 if (obj.hasOwnProperty(prop)) { 4405 return false;
4406 } 4407 } 4408 4409 return true; 4410 }, 4411 4412 numberString: function(nStr) { 4413 nStr += ''; 4414 var x = nStr.split('.'); 4415 var x1 = x[0]; 4416 var x2 = x.length > 1 ? '.' + x[1] : ''; 4417 var rgx = /(\d+)(\d{3})/; 4418 while (rgx.test(x1)) { 4419 x1 = x1.replace(rgx, '$1' + ',' + '$2'); 4420 } 4421 return x1 + x2; 4422 }, 4423 4424 detectIE: function() { 4425 var ua = window.navigator.userAgent; 4426 4427 // Test values; Uncomment to check result … 4428 4429 // IE 10 4430 // ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)'; 4431 4432 // IE 11 4433 // ua = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko'; 4434 4435 // Edge 12 (Spartan) 4436 // ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0'; 4437 4438 // Edge 13 4439 // ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586'; 4440 4441 var msie = ua.indexOf('MSIE '); 4442 if (msie > 0) { 4443 // IE 10 or older => return version number 4444 return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10); 4445 } 4446 4447 var trident = ua.indexOf('Trident/'); 4448 if (trident > 0) { 4449 // IE 11 => return version number 4450 var rv = ua.indexOf('rv:'); 4451 return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10); 4452 } 4453 4454 var edge = ua.indexOf('Edge/'); 4455 if (edge > 0) { 4456 // Edge (IE 12+) => return version number 4457 return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10); 4458 } 4459 4460 // other browser 4461 return false; 4462 }, 4463 4464 isRTL: function() { 4465 var html = KTUtil.getByTagName('html')[0]; 4466 4467 if (html) { 4468 return (KTUtil.attr(html, 'direction') == 'rtl'); 4469 } 4470 }, 4471 4472 // Scroller 4473 scrollInit: function(element, options) { 4474 if (!element) { 4475 return; 4476 } 4477 4478 // Learn more: https://github.com/mdbootstrap/perfect-scrollbar#options 4479 var pluginDefOptions = { 4480 wheelSpeed: 0.5, 4481 swipeEasing: true, 4482 wheelPropagation: false, 4483 minScrollbarLength: 40, 4484 maxScrollbarLength: 300, 4485 suppressScrollX: true 4486 }; 4487 4488 options = KTUtil.deepExtend({}, pluginDefOptions, options); 4489 4490 // Define init function 4491 function init() { 4492 var ps; 4493 var height; 4494 4495 // Get extra options via data attributes 4496 var attrs = element.getAttributeNames(); 4497 if (attrs.length > 0) { 4498 attrs.forEach(function(attrName) { 4499 // more options; https://github.com/ganlanyuan/tiny-slider#options 4500 if ((/^data-.*/g).test(attrName)) {
4501 if (['scroll', 'height', 'mobile-height'].includes(optionName) == false) { 4502 var optionName = attrName.replace('data-', '').toLowerCase().replace(/(?:[\s-])\w/g, function(match) { 4503 return match.replace('-', '').toUpperCase(); 4504 }); 4505 4506 options[optionName] = KTUtil.filterBoolean(element.getAttribute(attrName)); 4507 } 4508 } 4509 }); 4510 } 4511 4512 if (options.height instanceof Function) { 4513 height = options.height.call(); 4514 } else { 4515 if (KTUtil.isMobileDevice() === true && options.mobileHeight) { 4516 height = parseInt(options.mobileHeight); 4517 } else if (options.height) { 4518 height = parseInt(options.height); 4519 } else { 4520 height = parseInt(KTUtil.css(element, 'height')); 4521 } 4522 } 4523 4524 if (height === false) { 4525 KTUtil.scrollDestroy(element, true); 4526 4527 return; 4528 } 4529 4530 height = parseInt(height); 4531 4532 // Destroy scroll on table and mobile modes 4533 if ((options.mobileNativeScroll || options.disableForMobile) && KTUtil.isMobileDevice() === true) { 4534 ps = KTUtil.data(element).get('ps'); 4535 if (ps) { 4536 if (options.resetHeightOnDestroy) { 4537 KTUtil.css(element, 'height', 'auto'); 4538 } else { 4539 KTUtil.css(element, 'overflow', 'auto'); 4540 if (height > 0) { 4541 KTUtil.css(element, 'height', height + 'px'); 4542 } 4543 } 4544 4545 ps.destroy(); 4546 ps = KTUtil.data(element).remove('ps'); 4547 } else if (height > 0){ 4548 KTUtil.css(element, 'overflow', 'auto'); 4549 KTUtil.css(element, 'height', height + 'px'); 4550 } 4551 4552 return; 4553 } 4554 4555 if (height > 0) { 4556 KTUtil.css(element, 'height', height + 'px'); 4557 } 4558 4559 if (options.desktopNativeScroll) { 4560 KTUtil.css(element, 'overflow', 'auto'); 4561 return; 4562 } 4563 4564 // Pass options via HTML Attributes 4565 if (KTUtil.attr(element, 'data-window-scroll') == 'true') { 4566 options.windowScroll = true; 4567 } 4568 4569 // Init scroll 4570 ps = KTUtil.data(element).get('ps'); 4571 4572 if (ps) { 4573 ps.update(); 4574 } else { 4575 KTUtil.css(element, 'overflow', 'hidden'); 4576 KTUtil.addClass(element, 'scroll'); 4577 4578 ps = new PerfectScrollbar(element, options); 4579 4580 KTUtil.data(element).set('ps', ps); 4581 } 4582 4583 // Remember scroll position in cookie 4584 var uid = KTUtil.attr(element, 'id'); 4585 4586 // Todo:Consider using Localstorage 4587 if (options.rememberPosition === true && KTCookie && uid) { 4588 if (KTCookie.getCookie(uid)) { 4589 var pos = parseInt(KTCookie.getCookie(uid)); 4590 4591 if (pos > 0) { 4592 element.scrollTop = pos; 4593 } 4594 } 4595 4596 element.addEventListener('ps-scroll-y', function() { 4597 KTCookie.setCookie(uid, element.scrollTop); 4598 }); 4599 } 4600 } 4601 4602 // Init 4603 init(); 4604 4605 // Handle window resize 4606 if (options.handleWindowResize) { 4607 KTUtil.addResizeHandler(function() { 4608 init(); 4609 }); 4610 } 4611 }, 4612 4613 scrollUpdate: function(element) { 4614 var ps = KTUtil.data(element).get('ps'); 4615 if (ps) { 4616 ps.update(); 4617 } 4618 }, 4619 4620 scrollUpdateAll: function(parent) { 4621 var scrollers = KTUtil.findAll(parent, '.ps'); 4622 for (var i = 0, len = scrollers.length; i < len; i++) { 4623 KTUtil.scrollUpdate(scrollers[i]); 4624 } 4625 }, 4626 4627 scrollDestroy: function(element, resetAll) { 4628 var ps = KTUtil.data(element).get('ps'); 4629 4630 if (ps) { 4631 ps.destroy(); 4632 ps = KTUtil.data(element).remove('ps'); 4633 } 4634 4635 if (element && resetAll) { 4636 element.style.setProperty('overflow', ''); 4637 element.style.setProperty('height', ''); 4638 } 4639 }, 4640 4641 filterBoolean: function(val) { 4642 // Convert string boolean 4643 if (val === true || val === 'true') { 4644 return true; 4645 } 4646 4647 if (val === false || val === 'false') { 4648 return false;
4649 } 4650 4651 return val; 4652 }, 4653 4654 setHTML: function(el, html) { 4655 el.innerHTML = html; 4656 }, 4657 4658 getHTML: function(el) { 4659 if (el) { 4660 return el.innerHTML; 4661 } 4662 }, 4663 4664 getDocumentHeight: function() { 4665 var body = document.body; 4666 var html = document.documentElement; 4667 4668 return Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight ); 4669 }, 4670 4671 getScrollTop: function() { 4672 return (document.scrollingElement || document.documentElement).scrollTop; 4673 }, 4674 4675 changeColor: function(col, amt) { 4676 4677 var usePound = false; 4678 4679 if (col[0] == "#") { 4680 col = col.slice(1); 4681 usePound = true; 4682 } 4683 4684 var num = parseInt(col,16); 4685 4686 var r = (num >> 16) + amt; 4687 4688 if (r > 255) r = 255; 4689 else if (r < 0) r = 0; 4690 4691 var b = ((num >> 8) & 0x00FF) + amt; 4692 4693 if (b > 255) b = 255; 4694 else if (b < 0) b = 0; 4695 4696 var g = (num & 0x0000FF) + amt; 4697 4698 if (g > 255) g = 255; 4699 else if (g < 0) g = 0; 4700 4701 return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16); 4702 4703 }, 4704 4705 // Throttle function: Input as function which needs to be throttled and delay is the time interval in milliseconds 4706 throttle: function (timer, func, delay) { 4707 // If setTimeout is already scheduled, no need to do anything 4708 if (timer) { 4709 return; 4710 } 4711 4712 // Schedule a setTimeout after delay seconds 4713 timer = setTimeout(function () { 4714 func(); 4715 4716 // Once setTimeout function execution is finished, timerId = undefined so that in <br> 4717 // the next scroll event function execution can be scheduled by the setTimeout 4718 timer = undefined; 4719 }, delay); 4720 }, 4721 4722 // Debounce function: Input as function which needs to be debounced and delay is the debounced time in milliseconds 4723 debounce: function (timer, func, delay) { 4724 // Cancels the setTimeout method execution 4725 clearTimeout(timer) 4726 4727 // Executes the func after delay time. 4728 timer = setTimeout(func, delay); 4729 }, 4730 4731 btnWait: function(el, cls, message, disable) { 4732 if (!el) { 4733 return; 4734 } 4735 4736 if (typeof disable !== 'undefined' && disable === true) { 4737 KTUtil.attr(el, "disabled", true); 4738 } 4739 4740 if (cls) { 4741 KTUtil.addClass(el, cls); 4742 KTUtil.attr(el, "wait-class", cls); 4743 } 4744 4745 if (message) { 4746 var caption = KTUtil.find(el, '.btn-caption'); 4747 4748 if (caption) { 4749 KTUtil.data(caption).set('caption', KTUtil.getHTML(caption)); 4750 KTUtil.setHTML(caption, message); 4751 } else { 4752 KTUtil.data(el).set('caption', KTUtil.getHTML(el)); 4753 KTUtil.setHTML(el, message); 4754 } 4755 } 4756 }, 4757 4758 btnRelease: function(el) { 4759 if (!el) { 4760 return; 4761 } 4762 4763 /// Show loading state on button 4764 KTUtil.removeAttr(el, "disabled"); 4765 4766 if (KTUtil.hasAttr(el, "wait-class")) { 4767 KTUtil.removeClass(el, KTUtil.attr(el, "wait-class")); 4768 } 4769 4770 var caption = KTUtil.find(el, '.btn-caption'); 4771 4772 if (caption && KTUtil.data(caption).has('caption')) { 4773 KTUtil.setHTML(caption, KTUtil.data(caption).get('caption')); 4774 } else if (KTUtil.data(el).has('caption')) { 4775 KTUtil.setHTML(el, KTUtil.data(el).get('caption')); 4776 } 4777 }, 4778 4779 isOffscreen: function(el, direction, offset) { 4780 offset = offset || 0; 4781 4782 var windowWidth = KTUtil.getViewPort().width; 4783 var windowHeight = KTUtil.getViewPort().height; 4784 4785 var top = KTUtil.offset(el).top; 4786 var height = KTUtil.outerHeight(el) + offset; 4787 var left = KTUtil.offset(el).left; 4788 var width = KTUtil.outerWidth(el) + offset; 4789 4790 if (direction == 'bottom') { 4791 if (windowHeight < top + height) { 4792 return true; 4793 } else if (windowHeight > top + height * 1.5) { 4794 return true; 4795 } 4796 } 4797 4798 if (direction == 'top') { 4799 if (top < 0) { 4800 return true; 4801 } else if (top > height) { 4802 return true; 4803 } 4804 } 4805 4806 if (direction == 'left') { 4807 if (left < 0) { 4808 return true; 4809 } else if (left * 2 > width) { 4810 //console.log('left 2'); 4811 //return true; 4812 } 4813 } 4814 4815 if (direction == 'right') { 4816 if (windowWidth < left + width) { 4817 return true; 4818 } else { 4819 //console.log('right 2'); 4820 //return true; 4821 } 4822 } 4823 4824 return false;
4825 } 4826 } 4827}(); 4828 4829// webpack support 4830if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 4831 module.exports = KTUtil; 4832} 4833 4834// Initialize KTUtil class on document ready 4835KTUtil.ready(function() { 4836 if (typeof KTAppSettings !== 'undefined') { 4837 KTUtil.init(KTAppSettings); 4838 } else { 4839 KTUtil.init(); 4840 } 4841}); 4842 4843"use strict"; 4844 4845// Component Definition 4846var KTWizard = function(elementId, options) { 4847 // Main object 4848 var the = this; 4849 var init = false; 4850 4851 // Get element object 4852 var element = KTUtil.getById(elementId); 4853 var body = KTUtil.getBody(); 4854 4855 if (!element) { 4856 return; 4857 } 4858 4859 // Default options 4860 var defaultOptions = { 4861 startStep: 1, 4862 clickableSteps: false // to make steps clickable this set value true and add data-wizard-clickable="true" in HTML for class="wizard" element 4863 }; 4864 4865 //////////////////////////// 4866 // ** Private Methods ** // 4867 //////////////////////////// 4868 4869 var Plugin = { 4870 /** 4871 * Construct 4872 */ 4873 4874 construct: function(options) { 4875 if (KTUtil.data(element).has('wizard')) { 4876 the = KTUtil.data(element).get('wizard'); 4877 } else { 4878 // reset menu 4879 Plugin.init(options); 4880 4881 // build menu 4882 Plugin.build(); 4883 4884 KTUtil.data(element).set('wizard', the); 4885 } 4886 4887 return the; 4888 }, 4889 4890 /** 4891 * Init wizard 4892 */ 4893 init: function(options) { 4894 the.element = element; 4895 the.events = []; 4896 4897 // merge default and user defined options 4898 the.options = KTUtil.deepExtend({}, defaultOptions, options); 4899 4900 // Elements 4901 the.steps = KTUtil.findAll(element, '[data-wizard-type="step"]'); 4902 4903 the.btnNext = KTUtil.find(element, '[data-wizard-type="action-next"]'); 4904 the.btnPrev = KTUtil.find(element, '[data-wizard-type="action-prev"]'); 4905 the.btnSubmit = KTUtil.find(element, '[data-wizard-type="action-submit"]'); 4906 4907 // Variables 4908 the.events = []; 4909 the.lastStep = 0; 4910 the.currentStep = 1; 4911 the.newStep = 0; 4912 the.stopped = false; 4913 the.totalSteps = the.steps.length; 4914 4915 // Init current step 4916 if (the.options.startStep > 1) { 4917 Plugin.goTo(the.options.startStep); 4918 } 4919 4920 // Init UI 4921 Plugin.updateUI(); 4922 }, 4923 4924 /** 4925 * Build Form Wizard 4926 */ 4927 build: function() { 4928 // Next button event handler 4929 KTUtil.addEvent(the.btnNext, 'click', function(e) { 4930 e.preventDefault(); 4931 4932 // Set new step number 4933 Plugin.setNewStep(Plugin.getNextStep()); 4934 4935 // Trigger change event 4936 if (Plugin.eventTrigger('change') !== false) { 4937 Plugin.goTo(Plugin.getNextStep()); 4938 } 4939 }); 4940 4941 // Prev button event handler 4942 KTUtil.addEvent(the.btnPrev, 'click', function(e) { 4943 e.preventDefault(); 4944 4945 // Set new step number 4946 Plugin.setNewStep(Plugin.getPrevStep()); 4947 4948 // Trigger change event 4949 if (Plugin.eventTrigger('change') !== false) { 4950 Plugin.goTo(Plugin.getPrevStep()); 4951 } 4952 }); 4953 4954 if (the.options.clickableSteps === true) { 4955 KTUtil.on(element, '[data-wizard-type="step"]', 'click', function() { 4956 var index = KTUtil.index(this) + 1; 4957 4958 if (index !== the.currentStep) { 4959 Plugin.setNewStep(index); 4960 4961 // Trigger change event 4962 if (Plugin.eventTrigger('change') !== false) { 4963 Plugin.goTo(index); 4964 } 4965 } 4966 }); 4967 } 4968 4969 // Submit button event handler 4970 KTUtil.addEvent(the.btnSubmit, 'click', function(e) { 4971 e.preventDefault(); 4972 4973 Plugin.eventTrigger('submit'); 4974 }); 4975 }, 4976 4977 /** 4978 * Handles wizard click wizard 4979 */ 4980 goTo: function(number) { 4981 // Skip if stopped 4982 if (the.stopped === true) { 4983 the.stopped = false;
4984 return; 4985 } 4986 4987 // Skip if this step is already shown 4988 if (number === the.currentStep || number > the.totalSteps || number < 0) { 4989 return; 4990 } 4991 4992 // Validate step number 4993 number = parseInt(number); 4994 4995 // Set current step 4996 the.lastStep = the.currentStep; 4997 the.currentStep = number; 4998 the.newStep = 0; 4999 5000 Plugin.updateUI(); 5001 5002 Plugin.eventTrigger('changed'); 5003 5004 return the; 5005 }, 5006 5007 /** 5008 * Stop wizard 5009 */ 5010 stop: function() { 5011 the.stopped = true; 5012 }, 5013 5014 /** 5015 * Resume wizard 5016 */ 5017 resume: function() { 5018 the.stopped = false; 5019 }, 5020 5021 /** 5022 * Check last step 5023 */ 5024 isLastStep: function() { 5025 return the.currentStep === the.totalSteps; 5026 }, 5027 5028 /** 5029 * Check first step 5030 */ 5031 isFirstStep: function() { 5032 return the.currentStep === 1; 5033 }, 5034 5035 /** 5036 * Check between step 5037 */ 5038 isBetweenStep: function() { 5039 return Plugin.isLastStep() === false && Plugin.isFirstStep() === false; 5040 }, 5041 5042 /** 5043 * Update wizard UI after step change 5044 */ 5045 updateUI: function() { 5046 var stepType = ''; 5047 var index = the.currentStep - 1; 5048 5049 if (Plugin.isLastStep()) { 5050 stepType = 'last'; 5051 } else if (Plugin.isFirstStep()) { 5052 stepType = 'first'; 5053 } else { 5054 stepType = 'between'; 5055 } 5056 5057 KTUtil.attr(the.element, 'data-wizard-state', stepType); 5058 5059 // Steps 5060 var steps = KTUtil.findAll(the.element, '[data-wizard-type="step"]'); 5061 5062 if (steps && steps.length > 0) { 5063 for (var i = 0, len = steps.length; i < len; i++) { 5064 if (i == index) { 5065 KTUtil.attr(steps[i], 'data-wizard-state', 'current'); 5066 } else { 5067 if (i < index) { 5068 KTUtil.attr(steps[i], 'data-wizard-state', 'done'); 5069 } else { 5070 KTUtil.attr(steps[i], 'data-wizard-state', 'pending'); 5071 } 5072 } 5073 } 5074 } 5075 5076 // Steps Info 5077 var stepsInfo = KTUtil.findAll(the.element, '[data-wizard-type="step-info"]'); 5078 if (stepsInfo &&stepsInfo.length > 0) { 5079 for (var i = 0, len = stepsInfo.length; i < len; i++) { 5080 if (i == index) { 5081 KTUtil.attr(stepsInfo[i], 'data-wizard-state', 'current'); 5082 } else { 5083 KTUtil.removeAttr(stepsInfo[i], 'data-wizard-state'); 5084 } 5085 } 5086 } 5087 5088 // Steps Content 5089 var stepsContent = KTUtil.findAll(the.element, '[data-wizard-type="step-content"]'); 5090 if (stepsContent&& stepsContent.length > 0) { 5091 for (var i = 0, len = stepsContent.length; i < len; i++) { 5092 if (i == index) { 5093 KTUtil.attr(stepsContent[i], 'data-wizard-state', 'current'); 5094 } else { 5095 KTUtil.removeAttr(stepsContent[i], 'data-wizard-state'); 5096 } 5097 } 5098 } 5099 }, 5100 5101 /** 5102 * Get next step number 5103 */ 5104 getNextStep: function() { 5105 if (the.totalSteps >= (the.currentStep + 1)) { 5106 return the.currentStep + 1; 5107 } else { 5108 return the.totalSteps; 5109 } 5110 }, 5111 5112 /** 5113 * Get prev step number 5114 */ 5115 getPrevStep: function() { 5116 if ((the.currentStep - 1) >= 1) { 5117 return the.currentStep - 1; 5118 } else { 5119 return 1; 5120 } 5121 }, 5122 5123 /** 5124 * Get new step number 5125 */ 5126 getNewStep: function() { 5127 return the.newStep; 5128 }, 5129 5130 /** 5131 * Set new step 5132 */ 5133 setNewStep: function(step) { 5134 the.newStep = step; 5135 }, 5136 5137 /** 5138 * Trigger events 5139 */ 5140 eventTrigger: function(name, nested) { 5141 //KTUtil.triggerCustomEvent(name); 5142 for (var i = 0; i < the.events.length; i++) { 5143 var event = the.events[i]; 5144 if (event.name == name) { 5145 if (event.one == true) { 5146 if (event.fired == false) { 5147 the.events[i].fired = true; 5148 return event.handler.call(this, the); 5149 } 5150 } else { 5151 return event.handler.call(this, the); 5152 } 5153 } 5154 } 5155 }, 5156 5157 addEvent: function(name, handler, one) { 5158 the.events.push({ 5159 name: name, 5160 handler: handler, 5161 one: one, 5162 fired: false 5163 }); 5164 5165 return the; 5166 } 5167 }; 5168
5169 ////////////////////////// 5170 // ** Public Methods ** // 5171 ////////////////////////// 5172 5173 /** 5174 * Set default options 5175 */ 5176 5177 the.setDefaults = function(options) { 5178 defaultOptions = options; 5179 }; 5180 5181 /** 5182 * Go to the next step 5183 */ 5184 the.goNext = function() { 5185 return Plugin.goTo(Plugin.getNextStep()); 5186 }; 5187 5188 /** 5189 * Go to the prev step 5190 */ 5191 the.goPrev = function() { 5192 return Plugin.goTo(Plugin.getPrevStep()); 5193 }; 5194 5195 /** 5196 * Go to the last step 5197 */ 5198 the.goLast = function() { 5199 return Plugin.goTo(Plugin.getLastStep()); 5200 }; 5201 5202 /** 5203 * Go to the first step 5204 */ 5205 the.goFirst = function() { 5206 return Plugin.goTo(Plugin.getFirstStep()); 5207 }; 5208 5209 /** 5210 * Go to a step 5211 */ 5212 the.goTo = function(number) { 5213 return Plugin.goTo(number); 5214 }; 5215 5216 /** 5217 * Stop wizard 5218 */ 5219 the.stop = function() { 5220 return Plugin.stop(); 5221 }; 5222 5223 /** 5224 * Resume wizard 5225 */ 5226 the.resume = function() { 5227 return Plugin.resume(); 5228 }; 5229 5230 /** 5231 * Get current step number 5232 */ 5233 the.getStep = function() { 5234 return the.currentStep; 5235 }; 5236 5237 /** 5238 * Get new step number 5239 */ 5240 the.getNewStep = function() { 5241 return Plugin.getNewStep(); 5242 }; 5243 5244 /** 5245 * Set new step number 5246 */ 5247 the.setNewStep = function(number) { 5248 Plugin.setNewStep(number); 5249 }; 5250 5251 /** 5252 * Check last step 5253 */ 5254 the.isLastStep = function() { 5255 return Plugin.isLastStep(); 5256 }; 5257 5258 /** 5259 * Check first step 5260 */ 5261 the.isFirstStep = function() { 5262 return Plugin.isFirstStep(); 5263 }; 5264 5265 /** 5266 * Attach event("change", "changed", "submit") 5267 */ 5268 the.on = function(name, handler) { 5269 return Plugin.addEvent(name, handler); 5270 }; 5271 5272 /** 5273 * Attach event that will be fired once 5274 */ 5275 the.one = function(name, handler) { 5276 return Plugin.addEvent(name, handler, true); 5277 }; 5278 5279 // Construct plugin 5280 Plugin.construct.apply(the, [options]); 5281 5282 return the; 5283}; 5284 5285// webpack support 5286if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 5287 module.exports = KTWizard; 5288} 5289 5290'use strict'; 5291(function($) { 5292 5293 var pluginName = 'KTDatatable'; 5294 var pfx = ''; 5295 var util = KTUtil; 5296 var app = KTApp; 5297 5298 if (typeof util === 'undefined') throw new Error('Util class is required and must be included before ' + pluginName); 5299 5300 // plugin setup 5301 $.fn[pluginName] = function(options) { 5302 if ($(this).length === 0) { 5303 console.warn('No ' + pluginName + ' element exist.'); 5304 return; 5305 } 5306 5307 // global variables 5308 var datatable = this; 5309 5310 // debug enabled? 5311 // 1) state will be cleared on each refresh 5312 // 2) enable some logs 5313 // 3) etc. 5314 datatable.debug = false; 5315 5316 datatable.API = { 5317 record: null, 5318 value: null, 5319 params: null, 5320 }; 5321 5322 var Plugin = { 5323 /******************** 5324 ** PRIVATE METHODS 5325 ********************/ 5326 isInit: false, 5327 cellOffset: 110, 5328 iconOffset: 15, 5329 stateId: 'meta', 5330 ajaxParams: {}, 5331 pagingObject: {}, 5332 5333 init: function(options) { 5334 var isHtmlTable = false; 5335 // data source option empty is normal table 5336 if (options.data.source === null) { 5337 Plugin.extractTable(); 5338 isHtmlTable = true; 5339 } 5340 5341 Plugin.setupBaseDOM.call(); 5342 Plugin.setupDOM(datatable.table); 5343 5344 // on event after layout had done setup, show datatable 5345 $(datatable).on(pfx + 'datatable-on-layout-updated', Plugin.afterRender); 5346 5347 if (datatable.debug) { 5348 Plugin.stateRemove(Plugin.stateId); 5349 } 5350 5351 /*var es = Plugin.stateGet(Plugin.stateId); 5352 var eq = {}; 5353 if (es && es.hasOwnProperty('query')) { 5354 eq = es.query; 5355 } 5356 Plugin.setDataSourceQuery(Object.assign({}, eq, Plugin.getOption('data.source.read.params.query')));*/ 5357 5358 // set custom query from options 5359 Plugin.setDataSourceQuery(Plugin.getOption('data.source.read.params.query')); 5360 5361 // initialize extensions 5362 $.each(Plugin.getOption('extensions'), function(extName, extOptions) { 5363 if (typeof $.fn[pluginName][extName] === 'function') { 5364 if (typeof extOptions !== 'object') { 5365 extOptions = $.extend({}, extOptions); 5366 } 5367 new $.fn[pluginName][extName](datatable, extOptions); 5368 } 5369 }); 5370 5371 Plugin.spinnerCallback(true); 5372 // get data 5373 if (options.data.type === 'remote' || options.data.type === 'local') { 5374 if (options.data.saveState === false) { 5375 Plugin.stateRemove(Plugin.stateId); 5376 } 5377 // get data for local datatable and local table 5378 if (options.data.type === 'local' && typeof options.data.source === 'object') { 5379 datatable.dataSet = datatable.originalDataSet = Plugin.dataMapCallback(options.data.source); 5380 } 5381 Plugin.dataRender(); 5382 } 5383 5384 // if html table, remove and setup a new header 5385 if (isHtmlTable) { 5386 $(datatable.tableHead).find('tr').remove(); 5387 $(datatable.tableFoot).find('tr').remove(); 5388 } 5389 5390 Plugin.setHeadTitle(); 5391 if (Plugin.getOption('layout.footer')) { 5392 Plugin.setHeadTitle(datatable.tableFoot); 5393 } 5394 5395 // hide header 5396 if (typeof options.layout.header !== 'undefined' && 5397 options.layout.header === false) { 5398 $(datatable.table).find('thead').remove(); 5399 } 5400 5401 // hide footer 5402 if (typeof options.layout.footer !== 'undefined' && 5403 options.layout.footer === false) { 5404 $(datatable.table).find('tfoot').remove(); 5405 } 5406 5407 // for normal and local data type, run layoutUpdate 5408 if (options.data.type === null || 5409 options.data.type === 'local') { 5410 Plugin.setupCellField.call(); 5411 Plugin.setupTemplateCell.call(); 5412 5413 // setup nested datatable, if option enabled 5414 Plugin.setupSubDatatable.call(); 5415 5416 // setup extra system column properties 5417 Plugin.setupSystemColumn.call(); 5418 Plugin.redraw(); 5419 } 5420 5421 var width; 5422 var initialWidth = false;
5423 $(window).resize(function() { 5424 // issue: URL Bar Resizing on mobile, https://developers.google.com/web/updates/2016/12/url-bar-resizing 5425 // trigger datatable resize on width change only 5426 if ($(this).width() !== width) { 5427 width = $(this).width(); 5428 Plugin.fullRender(); 5429 } 5430 // get initial width 5431 if (!initialWidth) { 5432 width = $(this).width(); 5433 initialWidth = true; 5434 } 5435 }); 5436 5437 $(datatable).height(''); 5438 5439 var prevKeyword = ''; 5440 $(Plugin.getOption('search.input')).on('keyup', function(e) { 5441 if (Plugin.getOption('search.onEnter') && e.which !== 13) return; 5442 var keyword = $(this).val(); 5443 // prevent multiple search request on every button keyup 5444 if (prevKeyword !== keyword) { 5445 Plugin.search(keyword); 5446 prevKeyword = keyword; 5447 } 5448 }); 5449 5450 return datatable; 5451 }, 5452 5453 /** 5454 * Extract static HTML table content into datasource 5455 */ 5456 extractTable: function() { 5457 var columns = []; 5458 var headers = $(datatable).find('tr:first-child th').get().map(function(cell, i) { 5459 var field = $(cell).data('field'); 5460 var title = $(cell).data('title'); 5461 if (typeof field === 'undefined') { 5462 field = $(cell).text().trim(); 5463 } 5464 if (typeof title === 'undefined') { 5465 title = $(cell).text().trim(); 5466 } 5467 var column = {field: field, title: title}; 5468 for (var ii in options.columns) { 5469 if (options.columns[ii].field === field) { 5470 column = $.extend(true, {}, options.columns[ii], column); 5471 } 5472 } 5473 columns.push(column); 5474 return field; 5475 }); 5476 // auto create columns config 5477 options.columns = columns; 5478 5479 var rowProp = []; 5480 var source = []; 5481 5482 $(datatable).find('tr').each(function() { 5483 if ($(this).find('td').length) { 5484 rowProp.push($(this).prop('attributes')); 5485 } 5486 var td = {}; 5487 $(this).find('td').each(function(i, cell) { 5488 td[headers[i]] = cell.innerHTML.trim(); 5489 }); 5490 if (!util.isEmpty(td)) { 5491 source.push(td); 5492 } 5493 }); 5494 5495 options.data.attr.rowProps = rowProp; 5496 options.data.source = source; 5497 }, 5498 5499 /** 5500 * One time layout update on init 5501 */ 5502 layoutUpdate: function() { 5503 // setup nested datatable, if option enabled 5504 Plugin.setupSubDatatable.call(); 5505 5506 // setup extra system column properties 5507 Plugin.setupSystemColumn.call(); 5508 5509 // setup cell hover event 5510 Plugin.setupHover.call(); 5511 5512 if (typeof options.detail === 'undefined' 5513 // temporary disable lock column in subtable 5514 && Plugin.getDepth() === 1) { 5515 // lock columns handler 5516 Plugin.lockTable.call(); 5517 } 5518 5519 Plugin.resetScroll(); 5520 5521 // check if not is a locked column 5522 if (!Plugin.isLocked()) { 5523 Plugin.redraw.call(); 5524 // check if its not a subtable and has autoHide option enabled 5525 if (!Plugin.isSubtable() && Plugin.getOption('rows.autoHide') === true) { 5526 Plugin.autoHide(); 5527 } 5528 // reset row 5529 $(datatable.table).find('.' + pfx + 'datatable-row').css('height', ''); 5530 } 5531 5532 Plugin.columnHide.call(); 5533 5534 Plugin.rowEvenOdd.call(); 5535 5536 Plugin.sorting.call(); 5537 5538 Plugin.scrollbar.call(); 5539 5540 if (!Plugin.isInit) { 5541 // run once dropdown inside datatable 5542 Plugin.dropdownFix(); 5543 $(datatable).trigger(pfx + 'datatable-on-init', {table: $(datatable.wrap).attr('id'), options: options}); 5544 Plugin.isInit = true; 5545 } 5546 5547 $(datatable).trigger(pfx + 'datatable-on-layout-updated', {table: $(datatable.wrap).attr('id')}); 5548 }, 5549 5550 dropdownFix: function() { 5551 var dropdownMenu; 5552 $('body').on('show.bs.dropdown', '.' + pfx + 'datatable .' + pfx + 'datatable-body', function(e) { 5553 dropdownMenu = $(e.target).find('.dropdown-menu'); 5554 $('body').append(dropdownMenu.detach()); 5555 // dropdownMenu.css('display', 'block'); 5556 dropdownMenu.position({ 5557 'my': 'right top', 5558 'at': 'right bottom', 5559 'of': $(e.relatedTarget), 5560 }); 5561 // if datatable is inside modal 5562 if (datatable.closest('.modal').length) { 5563 // increase dropdown z-index 5564 dropdownMenu.css('z-index', '2000'); 5565 } 5566 }).on('hide.bs.dropdown', '.' + pfx + 'datatable .' + pfx + 'datatable-body', function(e) { 5567 $(e.target).append(dropdownMenu.detach()); 5568 dropdownMenu.hide(); 5569 }); 5570 5571 // remove dropdown if window resize 5572 $(window).on('resize', function(e) { 5573 if (typeof dropdownMenu !== 'undefined') { 5574 dropdownMenu.hide(); 5575 } 5576 }); 5577 }, 5578 5579 lockTable: function() { 5580 var lock = { 5581 lockEnabled: false, 5582 init: function() { 5583 // check if table should be locked columns 5584 lock.lockEnabled = Plugin.lockEnabledColumns(); 5585 if (lock.lockEnabled.left.length === 0 && 5586 lock.lockEnabled.right.length === 0) { 5587 return; 5588 } 5589 lock.enable(); 5590 }, 5591 enable: function() { 5592 var enableLock = function(tablePart) { 5593 // check if already has lock column 5594 if ($(tablePart).find('.' + pfx + 'datatable-lock').length > 0) { 5595 Plugin.log('Locked container already exist in: ', tablePart); 5596 return; 5597 } 5598 // check if no rows exists 5599 if ($(tablePart).find('.' + pfx + 'datatable-row').length === 0) { 5600 Plugin.log('No row exist in: ', tablePart); 5601 return; 5602 } 5603 5604 // locked div container
5605 var lockLeft = $('<div/>').addClass(pfx + 'datatable-lock ' + pfx + 'datatable-lock-left'); 5606 var lockScroll = $('<div/>').addClass(pfx + 'datatable-lock ' + pfx + 'datatable-lock-scroll'); 5607 var lockRight = $('<div/>').addClass(pfx + 'datatable-lock ' + pfx + 'datatable-lock-right'); 5608 5609 $(tablePart).find('.' + pfx + 'datatable-row').each(function() { 5610 // create new row for lock columns and pass the data 5611 var rowLeft = $('<tr/>').addClass(pfx + 'datatable-row').data('obj', $(this).data('obj')).appendTo(lockLeft); 5612 var rowScroll = $('<tr/>').addClass(pfx + 'datatable-row').data('obj', $(this).data('obj')).appendTo(lockScroll); 5613 var rowRight = $('<tr/>').addClass(pfx + 'datatable-row').data('obj', $(this).data('obj')).appendTo(lockRight); 5614 $(this).find('.' + pfx + 'datatable-cell').each(function() { 5615 var locked = $(this).data('locked'); 5616 if (typeof locked !== 'undefined') { 5617 if (typeof locked.left !== 'undefined' || locked === true) { 5618 // default locked to left 5619 $(this).appendTo(rowLeft); 5620 } 5621 if (typeof locked.right !== 'undefined') { 5622 $(this).appendTo(rowRight); 5623 } 5624 } else { 5625 $(this).appendTo(rowScroll); 5626 } 5627 }); 5628 // remove old row 5629 $(this).remove(); 5630 }); 5631 5632 if (lock.lockEnabled.left.length > 0) { 5633 $(datatable.wrap).addClass(pfx + 'datatable-lock'); 5634 $(lockLeft).appendTo(tablePart); 5635 } 5636 if (lock.lockEnabled.left.length > 0 || lock.lockEnabled.right.length > 0) { 5637 $(lockScroll).appendTo(tablePart); 5638 } 5639 if (lock.lockEnabled.right.length > 0) { 5640 $(datatable.wrap).addClass(pfx + 'datatable-lock'); 5641 $(lockRight).appendTo(tablePart); 5642 } 5643 }; 5644 5645 $(datatable.table).find('thead,tbody,tfoot').each(function() { 5646 var tablePart = this; 5647 if ($(this).find('.' + pfx + 'datatable-lock').length === 0) { 5648 $(this).ready(function() { 5649 enableLock(tablePart); 5650 }); 5651 } 5652 }); 5653 }, 5654 }; 5655 lock.init(); 5656 return lock; 5657 }, 5658 5659 /** 5660 * Render everything for resize 5661 */ 5662 fullRender: function() { 5663 $(datatable.tableHead).empty(); 5664 Plugin.setHeadTitle(); 5665 if (Plugin.getOption('layout.footer')) { 5666 $(datatable.tableFoot).empty(); 5667 Plugin.setHeadTitle(datatable.tableFoot); 5668 } 5669 5670 Plugin.spinnerCallback(true); 5671 $(datatable.wrap).removeClass(pfx + 'datatable-loaded'); 5672 5673 Plugin.insertData(); 5674 }, 5675 5676 lockEnabledColumns: function() { 5677 var screen = $(window).width(); 5678 var columns = options.columns; 5679 var enabled = {left: [], right: []}; 5680 $.each(columns, function(i, column) { 5681 if (typeof column.locked !== 'undefined') { 5682 if (typeof column.locked.left !== 'undefined') { 5683 if (util.getBreakpoint(column.locked.left) <= screen) { 5684 enabled['left'].push(column.locked.left); 5685 } 5686 } 5687 if (typeof column.locked.right !== 'undefined') { 5688 if (util.getBreakpoint(column.locked.right) <= screen) { 5689 enabled['right'].push(column.locked.right); 5690 } 5691 } 5692 } 5693 }); 5694 return enabled; 5695 }, 5696 5697 /** 5698 * After render event, called by "datatable-on-layout-updated" 5699 * @param e 5700 * @param args 5701 */ 5702 afterRender: function(e, args) { 5703 $(datatable).ready(function() { 5704 // redraw locked columns table 5705 if (Plugin.isLocked()) { 5706 Plugin.redraw(); 5707 } 5708 5709 $(datatable.tableBody).css('visibility', ''); 5710 $(datatable.wrap).addClass(pfx + 'datatable-loaded'); 5711 5712 Plugin.spinnerCallback(false); 5713 }); 5714 }, 5715 5716 hoverTimer: 0, 5717 isScrolling: false, 5718 setupHover: function() { 5719 $(window).scroll(function(e) { 5720 // stop hover when scrolling 5721 clearTimeout(Plugin.hoverTimer); 5722 Plugin.isScrolling = true; 5723 }); 5724 5725 $(datatable.tableBody).find('.' + pfx + 'datatable-cell').off('mouseenter', 'mouseleave').on('mouseenter', function() { 5726 // reset scroll timer to hover class 5727 Plugin.hoverTimer = setTimeout(function() { 5728 Plugin.isScrolling = false;
5729 }, 200); 5730 if (Plugin.isScrolling) return; 5731 5732 // normal table 5733 var row = $(this).closest('.' + pfx + 'datatable-row').addClass(pfx + 'datatable-row-hover'); 5734 var index = $(row).index() + 1; 5735 5736 // lock table 5737 $(row).closest('.' + pfx + 'datatable-lock').parent().find('.' + pfx + 'datatable-row:nth-child(' + index + ')').addClass(pfx + 'datatable-row-hover'); 5738 }).on('mouseleave', function() { 5739 // normal table 5740 var row = $(this).closest('.' + pfx + 'datatable-row').removeClass(pfx + 'datatable-row-hover'); 5741 var index = $(row).index() + 1; 5742 5743 // look table 5744 $(row).closest('.' + pfx + 'datatable-lock').parent().find('.' + pfx + 'datatable-row:nth-child(' + index + ')').removeClass(pfx + 'datatable-row-hover'); 5745 }); 5746 }, 5747 5748 /** 5749 * Adjust width of locked table containers by resize handler 5750 * @returns {number} 5751 */ 5752 adjustLockContainer: function() { 5753 if (!Plugin.isLocked()) return 0; 5754 5755 // refer to head dimension 5756 var containerWidth = $(datatable.tableHead).width(); 5757 var lockLeft = $(datatable.tableHead).find('.' + pfx + 'datatable-lock-left').width(); 5758 var lockRight = $(datatable.tableHead).find('.' + pfx + 'datatable-lock-right').width(); 5759 5760 if (typeof lockLeft === 'undefined') lockLeft = 0; 5761 if (typeof lockRight === 'undefined') lockRight = 0; 5762 5763 var lockScroll = Math.floor(containerWidth - lockLeft - lockRight); 5764 $(datatable.table).find('.' + pfx + 'datatable-lock-scroll').css('width', lockScroll); 5765 5766 return lockScroll; 5767 }, 5768 5769 /** 5770 * todo; not in use 5771 */ 5772 dragResize: function() { 5773 var pressed = false; 5774 var start = undefined; 5775 var startX, startWidth; 5776 $(datatable.tableHead).find('.' + pfx + 'datatable-cell').mousedown(function(e) { 5777 start = $(this); 5778 pressed = true; 5779 startX = e.pageX; 5780 startWidth = $(this).width(); 5781 $(start).addClass(pfx + 'datatable-cell-resizing'); 5782 5783 }).mousemove(function(e) { 5784 if (pressed) { 5785 var i = $(start).index(); 5786 var tableBody = $(datatable.tableBody); 5787 var ifLocked = $(start).closest('.' + pfx + 'datatable-lock'); 5788 5789 if (ifLocked) { 5790 var lockedIndex = $(ifLocked).index(); 5791 tableBody = $(datatable.tableBody).find('.' + pfx + 'datatable-lock').eq(lockedIndex); 5792 } 5793 5794 $(tableBody).find('.' + pfx + 'datatable-row').each(function(tri, tr) { 5795 $(tr).find('.' + pfx + 'datatable-cell').eq(i).width(startWidth + (e.pageX - startX)).children().width(startWidth + (e.pageX - startX)); 5796 }); 5797 5798 $(start).children().css('width', startWidth + (e.pageX - startX)); 5799 } 5800 5801 }).mouseup(function() { 5802 $(start).removeClass(pfx + 'datatable-cell-resizing'); 5803 pressed = false; 5804 }); 5805 5806 $(document).mouseup(function() { 5807 $(start).removeClass(pfx + 'datatable-cell-resizing'); 5808 pressed = false; 5809 }); 5810 }, 5811 5812 /** 5813 * To prepare placeholder for table before content is loading 5814 */ 5815 initHeight: function() { 5816 if (options.layout.height && options.layout.scroll) { 5817 var theadHeight = $(datatable.tableHead).find('.' + pfx + 'datatable-row').outerHeight(); 5818 var tfootHeight = $(datatable.tableFoot).find('.' + pfx + 'datatable-row').outerHeight(); 5819 var bodyHeight = options.layout.height; 5820 if (theadHeight > 0) { 5821 bodyHeight -= theadHeight; 5822 } 5823 if (tfootHeight > 0) { 5824 bodyHeight -= tfootHeight; 5825 } 5826 5827 // scrollbar offset 5828 bodyHeight -= 2; 5829 5830 $(datatable.tableBody).css('max-height', Math.floor(parseFloat(bodyHeight))); 5831 5832 // set scrollable area fixed height 5833 // $(datatable.tableBody).find('.' + pfx + 'datatable-lock-scroll').css('height', Math.floor(parseFloat(bodyHeight))); 5834 } 5835 }, 5836 5837 /** 5838 * Setup base DOM (table, thead, tbody, tfoot) and create if not 5839 * exist. 5840 */ 5841 setupBaseDOM: function() { 5842 // keep original state before datatable initialize 5843 datatable.initialDatatable = $(datatable).clone(); 5844 5845 // main element 5846 if ($(datatable).prop('tagName') === 'TABLE') { 5847 // if main init element is <table>, wrap with div 5848 datatable.table = $(datatable).removeClass(pfx + 'datatable').addClass(pfx + 'datatable-table'); 5849 if ($(datatable.table).parents('.' + pfx + 'datatable').length === 0) {
5850 datatable.table.wrap($('<div/>').addClass(pfx + 'datatable').addClass(pfx + 'datatable-' + options.layout.theme)); 5851 datatable.wrap = $(datatable.table).parent(); 5852 } 5853 } else { 5854 // create table 5855 datatable.wrap = $(datatable).addClass(pfx + 'datatable').addClass(pfx + 'datatable-' + options.layout.theme); 5856 datatable.table = $('<table/>').addClass(pfx + 'datatable-table').appendTo(datatable); 5857 } 5858 5859 if (typeof options.layout.class !== 'undefined') { 5860 $(datatable.wrap).addClass(options.layout.class); 5861 } 5862 5863 $(datatable.table).removeClass(pfx + 'datatable-destroyed').css('display', 'block'); 5864 5865 // force disable save state 5866 if (typeof $(datatable).attr('id') === 'undefined') { 5867 Plugin.setOption('data.saveState', false); 5868 $(datatable.table).attr('id', util.getUniqueID(pfx + 'datatable-')); 5869 } 5870 5871 // predefine table height 5872 if (Plugin.getOption('layout.minHeight')) 5873 $(datatable.table).css('min-height', Plugin.getOption('layout.minHeight')); 5874 5875 if (Plugin.getOption('layout.height')) 5876 $(datatable.table).css('max-height', Plugin.getOption('layout.height')); 5877 5878 // for normal table load 5879 if (options.data.type === null) { 5880 $(datatable.table).css('width', '').css('display', ''); 5881 } 5882 5883 // create table head element 5884 datatable.tableHead = $(datatable.table).find('thead'); 5885 if ($(datatable.tableHead).length === 0) { 5886 datatable.tableHead = $('<thead/>').prependTo(datatable.table); 5887 } 5888 5889 // create table head element 5890 datatable.tableBody = $(datatable.table).find('tbody'); 5891 if ($(datatable.tableBody).length === 0) { 5892 datatable.tableBody = $('<tbody/>').appendTo(datatable.table); 5893 } 5894 5895 if (typeof options.layout.footer !== 'undefined' && 5896 options.layout.footer) { 5897 // create table foot element 5898 datatable.tableFoot = $(datatable.table).find('tfoot'); 5899 if ($(datatable.tableFoot).length === 0) { 5900 datatable.tableFoot = $('<tfoot/>').appendTo(datatable.table); 5901 } 5902 } 5903 }, 5904 5905 /** 5906 * Set column data before table manipulation. 5907 */ 5908 setupCellField: function(tableParts) { 5909 if (typeof tableParts === 'undefined') tableParts = $(datatable.table).children(); 5910 var columns = options.columns; 5911 $.each(tableParts, function(part, tablePart) { 5912 $(tablePart).find('.' + pfx + 'datatable-row').each(function(tri, tr) { 5913 // prepare data 5914 $(tr).find('.' + pfx + 'datatable-cell').each(function(tdi, td) { 5915 if (typeof columns[tdi] !== 'undefined') { 5916 $(td).data(columns[tdi]); 5917 } 5918 }); 5919 }); 5920 }); 5921 }, 5922 5923 /** 5924 * Set column template callback 5925 * @param tablePart 5926 */ 5927 setupTemplateCell: function(tablePart) { 5928 if (typeof tablePart === 'undefined') tablePart = datatable.tableBody; 5929 var columns = options.columns; 5930 $(tablePart).find('.' + pfx + 'datatable-row').each(function(tri, tr) { 5931 // row data object, if any 5932 var obj = $(tr).data('obj'); 5933 if (typeof obj === 'undefined') { 5934 return; 5935 } 5936 5937 // @deprecated in v5.0.6 5938 // obj['getIndex'] = function() { 5939 // return tri; 5940 // }; 5941 // @deprecated in v5.0.6 5942 // obj['getDatatable'] = function() { 5943 // return datatable; 5944 // }; 5945 5946 // @deprecated in v5.0.6 5947 var rowCallback = Plugin.getOption('rows.callback'); 5948 if (typeof rowCallback === 'function') { 5949 rowCallback($(tr), obj, tri); 5950 } 5951 // before template row callback 5952 var beforeTemplate = Plugin.getOption('rows.beforeTemplate'); 5953 if (typeof beforeTemplate === 'function') { 5954 beforeTemplate($(tr), obj, tri); 5955 } 5956 // if data object is undefined, collect from table 5957 if (typeof obj === 'undefined') { 5958 obj = {}; 5959 $(tr).find('.' + pfx + 'datatable-cell').each(function(tdi, td) { 5960 // get column settings by field 5961 var column = $.grep(columns, function(n, i) { 5962 return $(td).data('field') === n.field; 5963 })[0]; 5964 if (typeof column !== 'undefined') { 5965 obj[column['field']] = $(td).text(); 5966 } 5967 }); 5968 } 5969 5970 $(tr).find('.' + pfx + 'datatable-cell').each(function(tdi, td) { 5971 // get column settings by field 5972 var column = $.grep(columns, function(n, i) { 5973 return $(td).data('field') === n.field; 5974 })[0]; 5975 if (typeof column !== 'undefined') { 5976 // column template 5977 if (typeof column.template !== 'undefined') { 5978 var finalValue = ''; 5979 // template string 5980 if (typeof column.template === 'string') { 5981 finalValue = Plugin.dataPlaceholder(column.template, obj); 5982 } 5983 // template callback function 5984 if (typeof column.template === 'function') { 5985 finalValue = column.template(obj, tri, datatable); 5986 } 5987 5988 // sanitize using DOMPurify if installed 5989 if (typeof DOMPurify !== 'undefined') { 5990 finalValue = DOMPurify.sanitize(finalValue); 5991 } 5992 5993 var span = document.createElement('span'); 5994 span.innerHTML = finalValue; 5995 5996 // insert to cell, wrap with span 5997 $(td).html(span); 5998 5999 // set span overflow 6000 if (typeof column.overflow !== 'undefined') { 6001 $(span).css('overflow', column.overflow); 6002 $(span).css('position', 'relative'); 6003 } 6004 } 6005 } 6006 }); 6007 6008 // after template row callback 6009 var afterTemplate = Plugin.getOption('rows.afterTemplate'); 6010 if (typeof afterTemplate === 'function') { 6011 afterTemplate($(tr), obj, tri); 6012 } 6013 }); 6014 }, 6015 6016 /** 6017 * Setup extra system column properties 6018 * Note: selector checkbox, subtable toggle 6019 */ 6020 setupSystemColumn: function() { 6021 datatable.dataSet = datatable.dataSet || []; 6022 // no records available 6023 if (datatable.dataSet.length === 0) return; 6024 6025 var columns = options.columns; 6026 $(datatable.tableBody).find('.' + pfx + 'datatable-row').each(function(tri, tr) { 6027 $(tr).find('.' + pfx + 'datatable-cell').each(function(tdi, td) { 6028 // get column settings by field 6029 var column = $.grep(columns, function(n, i) { 6030 return $(td).data('field') === n.field; 6031 })[0]; 6032 if (typeof column !== 'undefined') { 6033 var value = $(td).text(); 6034 6035 // enable column selector 6036 if (typeof column.selector !== 'undefined' && column.selector !== false) { 6037 // check if checkbox exist 6038 if ($(td).find('.' + pfx + 'checkbox [type="checkbox"]').length > 0) return; 6039 6040 $(td).addClass(pfx + 'datatable-cell-check'); 6041 6042 // append checkbox 6043 var chk = $('<label/>'). 6044 addClass(pfx + 'checkbox ' + pfx + 'checkbox-single'). 6045 append($('<input/>').attr('type', 'checkbox').attr('value', value).on('click', function() { 6046 if ($(this).is(':checked')) { 6047 // add checkbox active row class 6048 Plugin.setActive(this); 6049 } else { 6050 // add checkbox active row class 6051 Plugin.setInactive(this); 6052 } 6053 })). 6054 append(' <span></span>'); 6055 6056 // checkbox selector has outline style 6057 if (typeof column.selector.class !== 'undefined') { 6058 $(chk).addClass(column.selector.class); 6059 } 6060 6061 $(td).children().html(chk); 6062 } 6063 6064 // enable column subtable toggle 6065 if (typeof column.subtable !== 'undefined' && column.subtable) { 6066 // check if subtable toggle exist 6067 if ($(td).find('.' + pfx + 'datatable-toggle-subtable').length > 0) return; 6068 // append subtable toggle 6069 $(td). 6070 children(). 6071 html($('<a/>'). 6072 addClass(pfx + 'datatable-toggle-subtable'). 6073 attr('href', '#'). 6074 attr('data-value', value). 6075 append($('<i/>').addClass(Plugin.getOption('layout.icons.rowDetail.collapse')))); 6076 } 6077 } 6078 }); 6079 }); 6080 6081 // init checkbox for header/footer 6082 var initCheckbox = function(tr) { 6083 // get column settings by field 6084 var column = $.grep(columns, function(n, i) { 6085 return typeof n.selector !== 'undefined' && n.selector !== false; 6086 })[0]; 6087 6088 if (typeof column !== 'undefined') { 6089 // enable column selector 6090 if (typeof column.selector !== 'undefined' && column.selector !== false) { 6091 var td = $(tr).find('[data-field="' + column.field + '"]'); 6092 // check if checkbox exist 6093 if ($(td).find('.' + pfx + 'checkbox [type="checkbox"]').length > 0) return; 6094 6095 $(td).addClass(pfx + 'datatable-cell-check'); 6096 6097 // append checkbox 6098 var chk = $('<label/>'). 6099 addClass(pfx + 'checkbox ' + pfx + 'checkbox-single ' + pfx + 'checkbox-all'). 6100 append($('<input/>').attr('type', 'checkbox').on('click', function() { 6101 if ($(this).is(':checked')) { 6102 Plugin.setActiveAll(true); 6103 } else { 6104 Plugin.setActiveAll(false); 6105 } 6106 })). 6107 append(' <span></span>'); 6108 6109 // checkbox selector has outline style 6110 if (typeof column.selector.class !== 'undefined') { 6111 $(chk).addClass(column.selector.class); 6112 } 6113 6114 $(td).children().html(chk); 6115 } 6116 } 6117 }; 6118 6119 if (options.layout.header) {
6120 initCheckbox($(datatable.tableHead).find('.' + pfx + 'datatable-row').first()); 6121 } 6122 if (options.layout.footer) { 6123 initCheckbox($(datatable.tableFoot).find('.' + pfx + 'datatable-row').first()); 6124 } 6125 }, 6126 6127 maxWidthList: {}, 6128 6129 /** 6130 * Adjust width to match container size 6131 */ 6132 adjustCellsWidth: function() { 6133 // get table width 6134 var containerWidth = $(datatable.tableBody).innerWidth() - Plugin.iconOffset; 6135 6136 // get total number of columns 6137 var columns = $(datatable.tableHead). 6138 find('.' + pfx + 'datatable-row:first-child'). 6139 find('.' + pfx + 'datatable-cell'). 6140 // exclude expand icon 6141 not('.' + pfx + 'datatable-toggle-detail'). 6142 not(':hidden').length; 6143 6144 if (columns > 0) { 6145 // remove reserved sort icon width 6146 containerWidth = containerWidth - (Plugin.iconOffset * columns); 6147 var minWidth = Math.floor(containerWidth / columns); 6148 6149 // minimum width 6150 if (minWidth <= Plugin.cellOffset) { 6151 minWidth = Plugin.cellOffset; 6152 } 6153 6154 $(datatable.table).find('.' + pfx + 'datatable-row'). 6155 find('.' + pfx + 'datatable-cell').
6156 // exclude expand icon 6157 not('.' + pfx + 'datatable-toggle-detail'). 6158 not(':hidden').each(function(tdi, td) { 6159 6160 var width = minWidth; 6161 var dataWidth = $(td).data('width'); 6162 6163 if (typeof dataWidth !== 'undefined') { 6164 if (dataWidth === 'auto') { 6165 var field = $(td).data('field'); 6166 if (Plugin.maxWidthList[field]) { 6167 width = Plugin.maxWidthList[field]; 6168 } 6169 else { 6170 var cells = $(datatable.table).find('.' + pfx + 'datatable-cell[data-field="' + field + '"]'); 6171 width = Plugin.maxWidthList[field] = Math.max.apply(null, 6172 $(cells).map(function() { 6173 return $(this).outerWidth(); 6174 }).get()); 6175 } 6176 } 6177 else { 6178 width = dataWidth; 6179 } 6180 } 6181 $(td).children().css('width', Math.ceil(width)); 6182 }); 6183 } 6184 6185 return datatable; 6186 }, 6187 6188 /** 6189 * Adjust height to match container size 6190 */ 6191 adjustCellsHeight: function() { 6192 $.each($(datatable.table).children(), function(part, tablePart) { 6193 var totalRows = $(tablePart).find('.' + pfx + 'datatable-row').first().parent().find('.' + pfx + 'datatable-row').length; 6194 for (var i = 1; i <= totalRows; i++) { 6195 var rows = $(tablePart).find('.' + pfx + 'datatable-row:nth-child(' + i + ')'); 6196 if ($(rows).length > 0) { 6197 var maxHeight = Math.max.apply(null, $(rows).map(function() { 6198 return $(this).outerHeight(); 6199 }).get()); 6200 $(rows).css('height', Math.ceil(maxHeight)); 6201 } 6202 } 6203 }); 6204 }, 6205 6206 /** 6207 * Setup table DOM and classes 6208 */ 6209 setupDOM: function(table) { 6210 // set table classes 6211 $(table).find('> thead').addClass(pfx + 'datatable-head'); 6212 $(table).find('> tbody').addClass(pfx + 'datatable-body'); 6213 $(table).find('> tfoot').addClass(pfx + 'datatable-foot'); 6214 $(table).find('tr').addClass(pfx + 'datatable-row'); 6215 $(table).find('tr > th, tr > td').addClass(pfx + 'datatable-cell'); 6216 $(table).find('tr > th, tr > td').each(function(i, td) { 6217 if ($(td).find('span').length === 0) { 6218 $(td).wrapInner($('<span/>').css('width', Plugin.cellOffset)); 6219 } 6220 }); 6221 }, 6222 6223 /** 6224 * Default scrollbar 6225 * @returns {{tableLocked: null, init: init, onScrolling: 6226 * onScrolling}} 6227 */ 6228 scrollbar: function() { 6229 var scroll = { 6230 scrollable: null, 6231 tableLocked: null, 6232 initPosition: null, 6233 init: function() { 6234 var screen = util.getViewPort().width; 6235 // setup scrollable datatable 6236 if (options.layout.scroll) { 6237 // add scrollable datatable class 6238 $(datatable.wrap).addClass(pfx + 'datatable-scroll'); 6239 6240 var scrollable = $(datatable.tableBody).find('.' + pfx + 'datatable-lock-scroll'); 6241 6242 // check if scrollable area have rows 6243 if ($(scrollable).find('.' + pfx + 'datatable-row').length > 0 && $(scrollable).length > 0) { 6244 scroll.scrollHead = $(datatable.tableHead).find('> .' + pfx + 'datatable-lock-scroll > .' + pfx + 'datatable-row'); 6245 scroll.scrollFoot = $(datatable.tableFoot).find('> .' + pfx + 'datatable-lock-scroll > .' + pfx + 'datatable-row'); 6246 scroll.tableLocked = $(datatable.tableBody).find('.' + pfx + 'datatable-lock:not(.' + pfx + 'datatable-lock-scroll)'); 6247 if (Plugin.getOption('layout.customScrollbar') && util.detectIE() != 10 && screen > util.getBreakpoint('lg')) { 6248 scroll.initCustomScrollbar(scrollable[0]); 6249 } else { 6250 scroll.initDefaultScrollbar(scrollable); 6251 } 6252 } else if ($(datatable.tableBody).find('.' + pfx + 'datatable-row').length > 0) { 6253 scroll.scrollHead = $(datatable.tableHead).find('> .' + pfx + 'datatable-row'); 6254 scroll.scrollFoot = $(datatable.tableFoot).find('> .' + pfx + 'datatable-row'); 6255 if (Plugin.getOption('layout.customScrollbar') && util.detectIE() != 10 && screen > util.getBreakpoint('lg')) { 6256 scroll.initCustomScrollbar(datatable.tableBody); 6257 } else { 6258 scroll.initDefaultScrollbar(datatable.tableBody); 6259 } 6260 } 6261 } 6262 }, 6263 initDefaultScrollbar: function(scrollable) { 6264 // get initial scroll position 6265 scroll.initPosition = $(scrollable).scrollLeft(); 6266 $(scrollable).css('overflow-y', 'auto').off().on('scroll', scroll.onScrolling); 6267 $(scrollable).css('overflow-x', 'auto'); 6268 }, 6269 onScrolling: function(e) { 6270 var left = $(this).scrollLeft(); 6271 var top = $(this).scrollTop(); 6272 if (util.isRTL()) {
6273 // deduct initial position for RTL 6274 left = left - scroll.initPosition; 6275 } 6276 $(scroll.scrollHead).css('left', -left); 6277 $(scroll.scrollFoot).css('left', -left); 6278 $(scroll.tableLocked).each(function(i, table) { 6279 if (Plugin.isLocked()) { 6280 // scrollbar offset 6281 top -= 1; 6282 } 6283 $(table).css('top', -top); 6284 }); 6285 }, 6286 initCustomScrollbar: function(scrollable) { 6287 scroll.scrollable = scrollable; 6288 // create a new instance for table body with scrollbar 6289 Plugin.initScrollbar(scrollable); 6290 // get initial scroll position 6291 scroll.initPosition = $(scrollable).scrollLeft(); 6292 $(scrollable).off().on('scroll', scroll.onScrolling); 6293 }, 6294 }; 6295 scroll.init(); 6296 return scroll; 6297 }, 6298 6299 /** 6300 * Init custom scrollbar and reset position 6301 * @param element 6302 * @param options 6303 */ 6304 initScrollbar: function(element, options) { 6305 if (!element || !element.nodeName) { 6306 return; 6307 } 6308 $(datatable.tableBody).css('overflow', ''); 6309 var ps = $(element).data('ps'); 6310 if (util.hasClass(element, 'ps') && typeof ps !== 'undefined') { 6311 ps.update(); 6312 } else { 6313 ps = new PerfectScrollbar(element, Object.assign({}, { 6314 wheelSpeed: 0.5, 6315 swipeEasing: true, 6316 // wheelPropagation: false, 6317 minScrollbarLength: 40, 6318 maxScrollbarLength: 300, 6319 suppressScrollX: Plugin.getOption('rows.autoHide') && !Plugin.isLocked() 6320 }, options)); 6321 $(element).data('ps', ps); 6322 } 6323 6324 // reset perfect scrollbar on resize 6325 $(window).resize(function() { 6326 ps.update(); 6327 }); 6328 }, 6329 6330 /** 6331 * Set column title from options.columns settings 6332 */ 6333 setHeadTitle: function(tablePart) { 6334 if (typeof tablePart === 'undefined') tablePart = datatable.tableHead; 6335 tablePart = $(tablePart)[0]; 6336 var columns = options.columns; 6337 var row = tablePart.getElementsByTagName('tr')[0]; 6338 var ths = tablePart.getElementsByTagName('td'); 6339 6340 if (typeof row === 'undefined') { 6341 row = document.createElement('tr'); 6342 tablePart.appendChild(row); 6343 } 6344 6345 $.each(columns, function(i, column) { 6346 var th = ths[i]; 6347 if (typeof th === 'undefined') { 6348 th = document.createElement('th'); 6349 row.appendChild(th); 6350 } 6351 6352 // set column title 6353 if (typeof column['title'] !== 'undefined') { 6354 th.innerHTML = column.title; 6355 th.setAttribute('data-field', column.field); 6356 util.addClass(th, column.class); 6357 // set disable autoHide or force enable 6358 if (typeof column.autoHide !== 'undefined') { 6359 if (column.autoHide !== true) { 6360 th.setAttribute('data-autohide-disabled', column.autoHide); 6361 } else { 6362 th.setAttribute('data-autohide-enabled', column.autoHide); 6363 } 6364 } 6365 $(th).data(column); 6366 } 6367 6368 // set header attr option 6369 if (typeof column.attr !== 'undefined') { 6370 $.each(column.attr, function(key, val) { 6371 th.setAttribute(key, val); 6372 }); 6373 } 6374 6375 // apply text align to thead/tfoot 6376 if (typeof column.textAlign !== 'undefined') { 6377 var align = typeof datatable.textAlign[column.textAlign] !== 'undefined' ? datatable.textAlign[column.textAlign] : ''; 6378 util.addClass(th, align); 6379 } 6380 }); 6381 Plugin.setupDOM(tablePart); 6382 }, 6383 6384 /** 6385 * Initiate to get remote or local data via ajax 6386 */ 6387 dataRender: function(action) { 6388 $(datatable.table).siblings('.' + pfx + 'datatable-pager').removeClass(pfx + 'datatable-paging-loaded'); 6389 6390 var buildMeta = function() { 6391 datatable.dataSet = datatable.dataSet || []; 6392 Plugin.localDataUpdate(); 6393 // local pagination meta 6394 var meta = Plugin.getDataSourceParam('pagination'); 6395 if (meta.perpage === 0) { 6396 meta.perpage = options.data.pageSize || 10; 6397 } 6398 meta.total = datatable.dataSet.length; 6399 var start = Math.max(meta.perpage * (meta.page - 1), 0); 6400 var end = Math.min(start + meta.perpage, meta.total); 6401 datatable.dataSet = $(datatable.dataSet).slice(start, end); 6402 return meta; 6403 }; 6404 6405 var afterGetData = function(result) { 6406 var localPagingCallback = function(ctx, meta) { 6407 if (!$(ctx.pager).hasClass(pfx + 'datatable-paging-loaded')) { 6408 $(ctx.pager).remove(); 6409 ctx.init(meta); 6410 } 6411 $(ctx.pager).off().on(pfx + 'datatable-on-goto-page', function(e) { 6412 $(ctx.pager).remove(); 6413 ctx.init(meta); 6414 }); 6415 6416 var start = Math.max(meta.perpage * (meta.page - 1), 0); 6417 var end = Math.min(start + meta.perpage, meta.total); 6418 6419 Plugin.localDataUpdate(); 6420 datatable.dataSet = $(datatable.dataSet).slice(start, end); 6421 6422 // insert data into table content 6423 Plugin.insertData(); 6424 }; 6425 6426 $(datatable.wrap).removeClass(pfx + 'datatable-error'); 6427 // pagination enabled 6428 if (options.pagination) { 6429 if (options.data.serverPaging && options.data.type !== 'local') { 6430 // server pagination 6431 var serverMeta = Plugin.getObject('meta', result || null); 6432 if (serverMeta !== null) { 6433 Plugin.pagingObject = Plugin.paging(serverMeta); 6434 } else { 6435 // no meta object from server response, fallback to local pagination 6436 Plugin.pagingObject = Plugin.paging(buildMeta(), localPagingCallback); 6437 } 6438 } else { 6439 // local pagination can be used by remote data also 6440 Plugin.pagingObject = Plugin.paging(buildMeta(), localPagingCallback); 6441 } 6442 } else { 6443 // pagination is disabled 6444 Plugin.localDataUpdate(); 6445 } 6446 // insert data into table content 6447 Plugin.insertData(); 6448 }; 6449 6450 // get local datasource 6451 if (options.data.type === 'local' 6452 // for remote json datasource 6453 // || typeof options.data.source.read === 'undefined' && datatable.dataSet !== null 6454 // for remote datasource, server sorting is disabled and data already received from remote 6455 || options.data.serverSorting === false && action === 'sort' 6456 || options.data.serverFiltering === false && action === 'search' 6457 ) { 6458 setTimeout(function() { 6459 Plugin.setAutoColumns(); 6460 afterGetData(); 6461 }); 6462 return; 6463 } 6464 6465 // getting data from remote only 6466 Plugin.getData().done(afterGetData); 6467 }, 6468 6469 /** 6470 * Process ajax data 6471 */ 6472 insertData: function() { 6473 datatable.dataSet = datatable.dataSet || []; 6474 var params = Plugin.getDataSourceParam(); 6475 6476 // get row attributes 6477 var pagination = params.pagination; 6478 var start = (Math.max(pagination.page, 1) - 1) * pagination.perpage; 6479 var end = Math.min(pagination.page, pagination.pages) * pagination.perpage; 6480 var rowProps = {}; 6481 if (typeof options.data.attr.rowProps !== 'undefined' && options.data.attr.rowProps.length) { 6482 rowProps = options.data.attr.rowProps.slice(start, end); 6483 } 6484 6485 var tableBody = document.createElement('tbody'); 6486 tableBody.style.visibility = 'hidden'; 6487 var colLength = options.columns.length; 6488 6489 $.each(datatable.dataSet, function(rowIndex, row) { 6490 var tr = document.createElement('tr'); 6491 tr.setAttribute('data-row', rowIndex); 6492 // keep data object to row 6493 $(tr).data('obj', row); 6494 6495 if (typeof rowProps[rowIndex] !== 'undefined') { 6496 $.each(rowProps[rowIndex], function() { 6497 tr.setAttribute(this.name, this.value); 6498 }); 6499 } 6500 6501 var cellIndex = 0; 6502 var tds = []; 6503 for (var a = 0; a < colLength; a += 1) { 6504 var column = options.columns[a]; 6505 var classes = []; 6506 // add sorted class to cells 6507 if (Plugin.getObject('sort.field', params) === column.field) { 6508 classes.push(pfx + 'datatable-cell-sorted'); 6509 } 6510 6511 // apply text align 6512 if (typeof column.textAlign !== 'undefined') { 6513 var align = typeof datatable.textAlign[column.textAlign] !== 'undefined' ? datatable.textAlign[column.textAlign] : ''; 6514 classes.push(align); 6515 } 6516 6517 // var classAttr = ''; 6518 if (typeof column.class !== 'undefined') { 6519 classes.push(column.class); 6520 } 6521 6522 var td = document.createElement('td'); 6523 util.addClass(td, classes.join(' ')); 6524 td.setAttribute('data-field', column.field); 6525 // set disable autoHide or force enable 6526 if (typeof column.autoHide !== 'undefined') { 6527 if (column.autoHide !== true) { 6528 td.setAttribute('data-autohide-disabled', column.autoHide); 6529 } else { 6530 td.setAttribute('data-autohide-enabled', column.autoHide); 6531 } 6532 } 6533 td.innerHTML = Plugin.getObject(column.field, row); 6534 td.setAttribute('aria-label', Plugin.getObject(column.field, row)); 6535 tr.appendChild(td); 6536 } 6537 6538 tableBody.appendChild(tr); 6539 }); 6540 6541 // display no records message 6542 if (datatable.dataSet.length === 0) { 6543 var errorSpan = document.createElement('span'); 6544 util.addClass(errorSpan, pfx + 'datatable-error'); 6545 errorSpan.innerHTML = Plugin.getOption('translate.records.noRecords'); 6546 tableBody.appendChild(errorSpan); 6547 $(datatable.wrap).addClass(pfx + 'datatable-error ' + pfx + 'datatable-loaded'); 6548 Plugin.spinnerCallback(false); 6549 } 6550 6551 // replace existing table body 6552 $(datatable.tableBody).replaceWith(tableBody); 6553 datatable.tableBody = tableBody; 6554 6555 // layout update 6556 Plugin.setupDOM(datatable.table); 6557 Plugin.setupCellField([datatable.tableBody]); 6558 Plugin.setupTemplateCell(datatable.tableBody); 6559 Plugin.layoutUpdate(); 6560 }, 6561 6562 updateTableComponents: function() { 6563 datatable.tableHead = $(datatable.table).children('thead').get(0); 6564 datatable.tableBody = $(datatable.table).children('tbody').get(0); 6565 datatable.tableFoot = $(datatable.table).children('tfoot').get(0); 6566 }, 6567 6568 /** 6569 * Call ajax for raw JSON data 6570 */ 6571 getData: function() { 6572 // Plugin.spinnerCallback(true); 6573 6574 var ajaxParams = { 6575 dataType: 'json', 6576 method: 'POST', 6577 data: {}, 6578 timeout: Plugin.getOption('data.source.read.timeout') || 30000, 6579 }; 6580 6581 if (options.data.type === 'local') { 6582 ajaxParams.url = options.data.source; 6583 } 6584 6585 if (options.data.type === 'remote') { 6586 var data = Plugin.getDataSourceParam(); 6587 // remove if server params is not enabled 6588 if (!Plugin.getOption('data.serverPaging')) { 6589 delete data['pagination']; 6590 } 6591 if (!Plugin.getOption('data.serverSorting')) { 6592 delete data['sort']; 6593 } 6594 ajaxParams.data = $.extend({}, ajaxParams.data, Plugin.getOption('data.source.read.params'), data); 6595 ajaxParams = $.extend({}, ajaxParams, Plugin.getOption('data.source.read')); 6596 6597 if (typeof ajaxParams.url !== 'string') ajaxParams.url = Plugin.getOption('data.source.read'); 6598 if (typeof ajaxParams.url !== 'string') ajaxParams.url = Plugin.getOption('data.source'); 6599 // ajaxParams.data = $.extend(ajaxParams.data, data.pagination); 6600 } 6601 6602 return $.ajax(ajaxParams).done(function(response, textStatus, jqXHR) { 6603 datatable.lastResponse = response; 6604 // extendible data map callback for custom datasource 6605 datatable.dataSet = datatable.originalDataSet = Plugin.dataMapCallback(response); 6606 Plugin.setAutoColumns(); 6607 $(datatable).trigger(pfx + 'datatable-on-ajax-done', [datatable.dataSet]); 6608 }).fail(function(jqXHR, textStatus, errorThrown) { 6609 $(datatable).trigger(pfx + 'datatable-on-ajax-fail', [jqXHR]); 6610 $(datatable.tableBody).html($('<span/>').addClass(pfx + 'datatable-error').html(Plugin.getOption('translate.records.noRecords'))); 6611 $(datatable.wrap).addClass(pfx + 'datatable-error ' + pfx + 'datatable-loaded'); 6612 Plugin.spinnerCallback(false); 6613 }).always(function() { 6614 }); 6615 }, 6616 6617 /** 6618 * Pagination object 6619 * @param meta if null, local pagination, otherwise remote 6620 * pagination 6621 * @param callback for update data when navigating page 6622 */ 6623 paging: function(meta, callback) { 6624 var pg = { 6625 meta: null, 6626 pager: null, 6627 paginateEvent: null, 6628 pagerLayout: {pagination: null, info: null}, 6629 callback: null, 6630 init: function(meta) { 6631 pg.meta = meta; 6632 6633 // parse pagination meta to integer 6634 pg.meta.page = parseInt(pg.meta.page); 6635 pg.meta.pages = parseInt(pg.meta.pages); 6636 pg.meta.perpage = parseInt(pg.meta.perpage); 6637 pg.meta.total = parseInt(pg.meta.total); 6638
6639 // always recount total pages 6640 pg.meta.pages = Math.max(Math.ceil(pg.meta.total / pg.meta.perpage), 1); 6641 6642 // current page must be not over than total pages 6643 if (pg.meta.page > pg.meta.pages) pg.meta.page = pg.meta.pages; 6644 6645 // set unique event name between tables 6646 pg.paginateEvent = Plugin.getTablePrefix('paging'); 6647 6648 pg.pager = $(datatable.table).siblings('.' + pfx + 'datatable-pager'); 6649 if ($(pg.pager).hasClass(pfx + 'datatable-paging-loaded')) return; 6650 6651 // if class .'+pfx+'datatable-paging-loaded not exist, recreate pagination 6652 $(pg.pager).remove(); 6653 6654 // if no pages available 6655 if (pg.meta.pages === 0) return; 6656 6657 // update datasource params 6658 Plugin.setDataSourceParam('pagination', { 6659 page: pg.meta.page, 6660 pages: pg.meta.pages, 6661 perpage: pg.meta.perpage, 6662 total: pg.meta.total, 6663 }); 6664 6665 // default callback function, contains remote pagination handler 6666 pg.callback = pg.serverCallback; 6667 // custom callback function 6668 if (typeof callback === 'function') pg.callback = callback; 6669 6670 pg.addPaginateEvent(); 6671 pg.populate(); 6672 6673 pg.meta.page = Math.max(pg.meta.page || 1, pg.meta.page); 6674 6675 $(datatable).trigger(pg.paginateEvent, pg.meta); 6676 6677 pg.pagingBreakpoint.call(); 6678 $(window).resize(pg.pagingBreakpoint); 6679 }, 6680 serverCallback: function(ctx, meta) { 6681 Plugin.dataRender(); 6682 }, 6683 populate: function() { 6684 datatable.dataSet = datatable.dataSet || []; 6685 // no records available 6686 if (datatable.dataSet.length === 0) return; 6687 6688 var icons = Plugin.getOption('layout.icons.pagination'); 6689 var title = Plugin.getOption('translate.toolbar.pagination.items.default'); 6690 // pager root element 6691 pg.pager = $('<div/>').addClass(pfx + 'datatable-pager ' + pfx + 'datatable-paging-loaded'); 6692 // numbering links 6693 var pagerNumber = $('<ul/>').addClass(pfx + 'datatable-pager-nav my-2 mb-sm-0'); 6694 pg.pagerLayout['pagination'] = pagerNumber; 6695 6696 // pager first/previous button 6697 $('<li/>'). 6698 append($('<a/>'). 6699 attr('title', title.first). 6700 addClass(pfx + 'datatable-pager-link ' + pfx + 'datatable-pager-link-first'). 6701 append($('<i/>').addClass(icons.first)). 6702 on('click', pg.gotoMorePage). 6703 attr('data-page', 1)). 6704 appendTo(pagerNumber); 6705 $('<li/>'). 6706 append($('<a/>'). 6707 attr('title', title.prev). 6708 addClass(pfx + 'datatable-pager-link ' + pfx + 'datatable-pager-link-prev'). 6709 append($('<i/>').addClass(icons.prev)). 6710 on('click', pg.gotoMorePage)). 6711 appendTo(pagerNumber); 6712 6713 $('<li/>').append($('<input/>').attr('type', 'text').addClass(pfx + 'datatable-pager-input form-control').attr('title', title.input).on('keyup', function() { 6714 // on keyup update [data-page] 6715 $(this).attr('data-page', Math.abs($(this).val())); 6716 }).on('keypress', function(e) { 6717 // on keypressed enter button 6718 if (e.which === 13) pg.gotoMorePage(e); 6719 })).appendTo(pagerNumber); 6720 6721 var pagesNumber = Plugin.getOption('toolbar.items.pagination.pages.desktop.pagesNumber'); 6722 var end = Math.ceil(pg.meta.page / pagesNumber) * pagesNumber; 6723 var start = end - pagesNumber; 6724 if (end > pg.meta.pages) { 6725 end = pg.meta.pages; 6726 } 6727 6728 // keep pagination 1 if there is no records 6729 if (start < 0) { 6730 start = 0; 6731 } 6732 6733 for (var x = start; x < (end || 1); x++) { 6734 var pageNumber = x + 1; 6735 $('<li/>'). 6736 append($('<a/>'). 6737 addClass(pfx + 'datatable-pager-link ' + pfx + 'datatable-pager-link-number'). 6738 text(pageNumber). 6739 attr('data-page', pageNumber). 6740 attr('title', pageNumber). 6741 on('click', pg.gotoPage)). 6742 appendTo(pagerNumber); 6743 } 6744 6745 // pager next/last button 6746 $('<li/>'). 6747 append($('<a/>'). 6748 attr('title', title.next). 6749 addClass(pfx + 'datatable-pager-link ' + pfx + 'datatable-pager-link-next'). 6750 append($('<i/>').addClass(icons.next)). 6751 on('click', pg.gotoMorePage)). 6752 appendTo(pagerNumber); 6753 $('<li/>'). 6754 append($('<a/>'). 6755 attr('title', title.last). 6756 addClass(pfx + 'datatable-pager-link ' + pfx + 'datatable-pager-link-last'). 6757 append($('<i/>').addClass(icons.last)). 6758 on('click', pg.gotoMorePage). 6759 attr('data-page', pg.meta.pages)). 6760 appendTo(pagerNumber); 6761 6762 // page info 6763 if (Plugin.getOption('toolbar.items.info')) { 6764 pg.pagerLayout['info'] = $('<div/>').addClass(pfx + 'datatable-pager-info my-2 mb-sm-0').append($('<span/>').addClass(pfx + 'datatable-pager-detail')); 6765 } 6766 6767 $.each(Plugin.getOption('toolbar.layout'), function(i, layout) { 6768 $(pg.pagerLayout[layout]).appendTo(pg.pager); 6769 }); 6770 6771 // page size select 6772 var pageSizeSelect = $('<select/>'). 6773 addClass('selectpicker ' + pfx + 'datatable-pager-size'). 6774 attr('title', Plugin.getOption('translate.toolbar.pagination.items.default.select')). 6775 attr('data-width', '60px'). 6776 attr('data-container', 'body'). 6777 val(pg.meta.perpage). 6778 on('change', pg.updatePerpage). 6779 prependTo(pg.pagerLayout['info']); 6780 6781 var pageSizes = Plugin.getOption('toolbar.items.pagination.pageSizeSelect'); 6782 // default value here, to fix override option by user 6783 if (pageSizes.length == 0) pageSizes = [5, 10, 20, 30, 50, 100]; 6784 $.each(pageSizes, function(i, size) { 6785 var display = size; 6786 if (size === -1) display = Plugin.getOption('translate.toolbar.pagination.items.default.all'); 6787 $('<option/>').attr('value', size).html(display).appendTo(pageSizeSelect); 6788 }); 6789 6790 // init selectpicker to dropdown 6791 $(datatable).ready(function() { 6792 $('.selectpicker'). 6793 selectpicker(). 6794 on('hide.bs.select', function() { 6795 // fix dropup arrow icon on hide 6796 $(this).closest('.bootstrap-select').removeClass('dropup'); 6797 }). 6798 siblings('.dropdown-toggle'). 6799 attr('title', Plugin.getOption('translate.toolbar.pagination.items.default.select')); 6800 }); 6801 6802 pg.paste(); 6803 }, 6804 paste: function() { 6805 // insert pagination based on placement position, top|bottom 6806 $.each($.unique(Plugin.getOption('toolbar.placement')), 6807 function(i, position) { 6808 if (position === 'bottom') { 6809 $(pg.pager).clone(true).insertAfter(datatable.table); 6810 } 6811 if (position === 'top') { 6812 // pager top need some extra space 6813 $(pg.pager).clone(true).addClass(pfx + 'datatable-pager-top').insertBefore(datatable.table); 6814 } 6815 }); 6816 }, 6817 gotoMorePage: function(e) { 6818 e.preventDefault(); 6819 // $(this) is a link of .'+pfx+'datatable-pager-link 6820 6821 if ($(this).attr('disabled') === 'disabled') return false;
6822 6823 var page = $(this).attr('data-page'); 6824 6825 // event from text input 6826 if (typeof page === 'undefined') { 6827 page = $(e.target).attr('data-page'); 6828 } 6829 6830 pg.openPage(parseInt(page)); 6831 return false; 6832 }, 6833 gotoPage: function(e) { 6834 e.preventDefault(); 6835 // prevent from click same page number 6836 if ($(this).hasClass(pfx + 'datatable-pager-link-active')) return; 6837 6838 pg.openPage(parseInt($(this).data('page'))); 6839 }, 6840 openPage: function(page) { 6841 // currentPage is 1-based index 6842 pg.meta.page = parseInt(page); 6843 6844 $(datatable).trigger(pg.paginateEvent, pg.meta); 6845 pg.callback(pg, pg.meta); 6846 6847 // update page callback function 6848 $(pg.pager).trigger(pfx + 'datatable-on-goto-page', pg.meta); 6849 }, 6850 updatePerpage: function(e) { 6851 e.preventDefault(); 6852 // if (Plugin.getOption('layout.height') === null) { 6853 // fix white space, when perpage is set from many records to less records 6854 // $('html, body').animate({scrollTop: $(datatable).position().top}); 6855 // } 6856 6857 // hide dropdown after select 6858 $(this).selectpicker('toggle'); 6859 6860 pg.pager = $(datatable.table).siblings('.' + pfx + 'datatable-pager').removeClass(pfx + 'datatable-paging-loaded'); 6861 6862 // on change select page size 6863 if (e.originalEvent) { 6864 pg.meta.perpage = parseInt($(this).val()); 6865 } 6866 6867 $(pg.pager).find('select.' + pfx + 'datatable-pager-size').val(pg.meta.perpage).attr('data-selected', pg.meta.perpage); 6868 6869 // update datasource params 6870 Plugin.setDataSourceParam('pagination', { 6871 page: pg.meta.page, 6872 pages: pg.meta.pages, 6873 perpage: pg.meta.perpage, 6874 total: pg.meta.total, 6875 }); 6876 6877 // update page callback function 6878 $(pg.pager).trigger(pfx + 'datatable-on-update-perpage', pg.meta); 6879 $(datatable).trigger(pg.paginateEvent, pg.meta); 6880 pg.callback(pg, pg.meta); 6881 6882 // update pagination info 6883 pg.updateInfo.call(); 6884 }, 6885 addPaginateEvent: function(e) { 6886 // pagination event 6887 $(datatable).off(pg.paginateEvent).on(pg.paginateEvent, function(e, meta) { 6888 Plugin.spinnerCallback(true); 6889 6890 pg.pager = $(datatable.table).siblings('.' + pfx + 'datatable-pager'); 6891 var pagerNumber = $(pg.pager).find('.' + pfx + 'datatable-pager-nav'); 6892 6893 // set sync active page class 6894 $(pagerNumber).find('.' + pfx + 'datatable-pager-link-active').removeClass(pfx + 'datatable-pager-link-active'); 6895 $(pagerNumber).find('.' + pfx + 'datatable-pager-link-number[data-page="' + meta.page + '"]').addClass(pfx + 'datatable-pager-link-active'); 6896 6897 // set next and previous link page number 6898 $(pagerNumber).find('.' + pfx + 'datatable-pager-link-prev').attr('data-page', Math.max(meta.page - 1, 1)); 6899 $(pagerNumber).find('.' + pfx + 'datatable-pager-link-next').attr('data-page', Math.min(meta.page + 1, meta.pages)); 6900 6901 // current page input value sync 6902 $(pg.pager).each(function() { 6903 $(this).find('.' + pfx + 'datatable-pager-input[type="text"]').prop('value', meta.page); 6904 }); 6905 6906 // if only 1 page, should hide page? 6907 // $(pg.pager).find('.' + pfx + 'datatable-pager-nav').show(); 6908 // if (meta.pages <= 1) { 6909 // // hide pager if has 1 page 6910 // $(pg.pager).find('.' + pfx + 'datatable-pager-nav').hide(); 6911 // } 6912 6913 // update datasource params 6914 Plugin.setDataSourceParam('pagination', { 6915 page: pg.meta.page, 6916 pages: pg.meta.pages, 6917 perpage: pg.meta.perpage, 6918 total: pg.meta.total, 6919 }); 6920 6921 $(pg.pager).find('select.' + pfx + 'datatable-pager-size').val(meta.perpage).attr('data-selected', meta.perpage); 6922 6923 // clear active rows 6924 $(datatable.table).find('.' + pfx + 'checkbox > [type="checkbox"]').prop('checked', false); 6925 $(datatable.table).find('.' + pfx + 'datatable-row-active').removeClass(pfx + 'datatable-row-active'); 6926 6927 pg.updateInfo.call(); 6928 pg.pagingBreakpoint.call(); 6929 // Plugin.resetScroll(); 6930 }); 6931 }, 6932 updateInfo: function() { 6933 var start = Math.max(pg.meta.perpage * (pg.meta.page - 1) + 1, 1); 6934 var end = Math.min(start + pg.meta.perpage - 1, pg.meta.total); 6935 // page info update 6936 $(pg.pager).find('.' + pfx + 'datatable-pager-info').find('.' + pfx + 'datatable-pager-detail').html(Plugin.dataPlaceholder( 6937 Plugin.getOption('translate.toolbar.pagination.items.info'), { 6938 // set start page 0 if the is no records. eg. Showing 0 - 0 of 0 6939 start: pg.meta.total === 0 ? 0 : start, 6940 end: pg.meta.perpage === -1 ? pg.meta.total : end, 6941 pageSize: pg.meta.perpage === -1 || 6942 pg.meta.perpage >= pg.meta.total 6943 ? pg.meta.total 6944 : pg.meta.perpage, 6945 total: pg.meta.total, 6946 })); 6947 }, 6948 6949 /** 6950 * Update pagination layout breakpoint 6951 */ 6952 pagingBreakpoint: function() { 6953 // keep page links reference 6954 var pagerNumber = $(datatable.table).siblings('.' + pfx + 'datatable-pager').find('.' + pfx + 'datatable-pager-nav'); 6955 if ($(pagerNumber).length === 0) return; 6956 6957 var currentPage = Plugin.getCurrentPage(); 6958 var pagerInput = $(pagerNumber).find('.' + pfx + 'datatable-pager-input').closest('li'); 6959 6960 // reset 6961 $(pagerNumber).find('li').show(); 6962 6963 // pagination update 6964 $.each(Plugin.getOption('toolbar.items.pagination.pages'), 6965 function(mode, option) { 6966 if (util.isInResponsiveRange(mode)) { 6967 switch (mode) { 6968 case 'desktop': 6969 case 'tablet': 6970 var end = Math.ceil(currentPage / option.pagesNumber) * option.pagesNumber; 6971 var start = end - option.pagesNumber; 6972 $(pagerInput).hide(); 6973 pg.meta = Plugin.getDataSourceParam('pagination'); 6974 pg.paginationUpdate(); 6975 break; 6976 6977 case 'mobile': 6978 $(pagerInput).show(); 6979 $(pagerNumber).find('.' + pfx + 'datatable-pager-link-more-prev').closest('li').hide(); 6980 $(pagerNumber).find('.' + pfx + 'datatable-pager-link-more-next').closest('li').hide(); 6981 $(pagerNumber).find('.' + pfx + 'datatable-pager-link-number').closest('li').hide(); 6982 break; 6983 } 6984 6985 return false;
6986 } 6987 }); 6988 }, 6989 6990 /** 6991 * Update pagination number and button display 6992 */ 6993 paginationUpdate: function() { 6994 var pager = $(datatable.table).siblings('.' + pfx + 'datatable-pager').find('.' + pfx + 'datatable-pager-nav'), 6995 pagerMorePrev = $(pager).find('.' + pfx + 'datatable-pager-link-more-prev'), 6996 pagerMoreNext = $(pager).find('.' + pfx + 'datatable-pager-link-more-next'), 6997 pagerFirst = $(pager).find('.' + pfx + 'datatable-pager-link-first'), 6998 pagerPrev = $(pager).find('.' + pfx + 'datatable-pager-link-prev'), 6999 pagerNext = $(pager).find('.' + pfx + 'datatable-pager-link-next'), 7000 pagerLast = $(pager).find('.' + pfx + 'datatable-pager-link-last'); 7001 7002 // get visible page 7003 var pagerNumber = $(pager).find('.' + pfx + 'datatable-pager-link-number'); 7004 // get page before of first visible 7005 var morePrevPage = Math.max($(pagerNumber).first().data('page') - 1, 1); 7006 $(pagerMorePrev).each(function(i, prev) { 7007 $(prev).attr('data-page', morePrevPage); 7008 }); 7009 // show/hide <li> 7010 if (morePrevPage === 1) { 7011 $(pagerMorePrev).parent().hide(); 7012 } else { 7013 $(pagerMorePrev).parent().show(); 7014 } 7015 7016 // get page after of last visible 7017 var moreNextPage = Math.min($(pagerNumber).last().data('page') + 1, 7018 pg.meta.pages); 7019 $(pagerMoreNext).each(function(i, prev) { 7020 $(pagerMoreNext).attr('data-page', moreNextPage).show(); 7021 }); 7022 7023 // show/hide <li> 7024 if (moreNextPage === pg.meta.pages 7025 // missing dot fix when last hidden page is one left 7026 && moreNextPage === $(pagerNumber).last().data('page')) { 7027 $(pagerMoreNext).parent().hide(); 7028 } else { 7029 $(pagerMoreNext).parent().show(); 7030 } 7031 7032 // begin/end of pages 7033 if (pg.meta.page === 1) { 7034 $(pagerFirst).attr('disabled', true).addClass(pfx + 'datatable-pager-link-disabled'); 7035 $(pagerPrev).attr('disabled', true).addClass(pfx + 'datatable-pager-link-disabled'); 7036 } else { 7037 $(pagerFirst).removeAttr('disabled').removeClass(pfx + 'datatable-pager-link-disabled'); 7038 $(pagerPrev).removeAttr('disabled').removeClass(pfx + 'datatable-pager-link-disabled'); 7039 } 7040 if (pg.meta.page === pg.meta.pages) { 7041 $(pagerNext).attr('disabled', true).addClass(pfx + 'datatable-pager-link-disabled'); 7042 $(pagerLast).attr('disabled', true).addClass(pfx + 'datatable-pager-link-disabled'); 7043 } else { 7044 $(pagerNext).removeAttr('disabled').removeClass(pfx + 'datatable-pager-link-disabled'); 7045 $(pagerLast).removeAttr('disabled').removeClass(pfx + 'datatable-pager-link-disabled'); 7046 } 7047 7048 // display more buttons 7049 var nav = Plugin.getOption('toolbar.items.pagination.navigation'); 7050 if (!nav.first) $(pagerFirst).remove(); 7051 if (!nav.prev) $(pagerPrev).remove(); 7052 if (!nav.next) $(pagerNext).remove(); 7053 if (!nav.last) $(pagerLast).remove(); 7054 if (!nav.more) { 7055 $(pagerMorePrev).remove(); 7056 $(pagerMoreNext).remove(); 7057 } 7058 }, 7059 }; 7060 pg.init(meta); 7061 return pg; 7062 }, 7063 7064 /** 7065 * Hide/show table cell defined by 7066 * options[columns][i][responsive][visible/hidden] 7067 */ 7068 columnHide: function() { 7069 var screen = util.getViewPort().width; 7070 // foreach columns setting 7071 $.each(options.columns, function(i, column) { 7072 if (typeof column.responsive !== 'undefined' || typeof column.visible !== 'undefined') { 7073 var field = column.field; 7074 var tds = $.grep($(datatable.table).find('.' + pfx + 'datatable-cell'), function(n, i) { 7075 return field === $(n).data('field'); 7076 }); 7077 7078 setTimeout(function () { 7079 // hide by force 7080 if (Plugin.getObject('visible', column) === false) { 7081 $(tds).hide(); 7082 } else { 7083 // show/hide by responsive breakpoint 7084 if (util.getBreakpoint(Plugin.getObject('responsive.hidden', column)) >= screen) { 7085 $(tds).hide(); 7086 } else { 7087 $(tds).show(); 7088 } 7089 if (util.getBreakpoint(Plugin.getObject('responsive.visible', column)) <= screen) { 7090 $(tds).show(); 7091 } else { 7092 $(tds).hide(); 7093 } 7094 } 7095 }); 7096 } 7097 }); 7098 }, 7099 7100 /** 7101 * Setup sub datatable 7102 */ 7103 setupSubDatatable: function() { 7104 var subTableCallback = Plugin.getOption('detail.content'); 7105 if (typeof subTableCallback !== 'function') return; 7106 7107 // subtable already exist 7108 if ($(datatable.table).find('.' + pfx + 'datatable-subtable').length > 0) return; 7109 7110 $(datatable.wrap).addClass(pfx + 'datatable-subtable'); 7111 7112 options.columns[0]['subtable'] = true; 7113 7114 // toggle on open sub table 7115 var toggleSubTable = function(e) { 7116 e.preventDefault(); 7117 // get parent row of this subtable 7118 var parentRow = $(this).closest('.' + pfx + 'datatable-row'); 7119 7120 // get subtable row for sub table 7121 var subTableRow = $(parentRow).next('.' + pfx + 'datatable-row-subtable'); 7122 if ($(subTableRow).length === 0) { 7123 // prepare DOM for sub table, each <tr> as parent and add <tr> as child table 7124 subTableRow = $('<tr/>'). 7125 addClass(pfx + 'datatable-row-subtable ' + pfx + 'datatable-row-loading'). 7126 hide(). 7127 append($('<td/>').addClass(pfx + 'datatable-subtable').attr('colspan', Plugin.getTotalColumns())); 7128 $(parentRow).after(subTableRow); 7129 // add class to even row 7130 if ($(parentRow).hasClass(pfx + 'datatable-row-even')) { 7131 $(subTableRow).addClass(pfx + 'datatable-row-subtable-even'); 7132 } 7133 } 7134 7135 $(subTableRow).toggle(); 7136 7137 var subTable = $(subTableRow).find('.' + pfx + 'datatable-subtable'); 7138 7139 // get id from first column of parent row 7140 var primaryKey = $(this).closest('[data-field]:first-child').find('.' + pfx + 'datatable-toggle-subtable').data('value'); 7141 7142 var icon = $(this).find('i').removeAttr('class'); 7143 7144 // prevent duplicate datatable init 7145 if ($(parentRow).hasClass(pfx + 'datatable-row-subtable-expanded')) { 7146 $(icon).addClass(Plugin.getOption('layout.icons.rowDetail.collapse')); 7147 // remove expand class from parent row 7148 $(parentRow).removeClass(pfx + 'datatable-row-subtable-expanded'); 7149 // trigger event on collapse 7150 $(datatable).trigger(pfx + 'datatable-on-collapse-subtable', [parentRow]); 7151 } else { 7152 // expand and run callback function 7153 $(icon).addClass(Plugin.getOption('layout.icons.rowDetail.expand')); 7154 // add expand class to parent row 7155 $(parentRow).addClass(pfx + 'datatable-row-subtable-expanded'); 7156 // trigger event on expand 7157 $(datatable).trigger(pfx + 'datatable-on-expand-subtable', [parentRow]); 7158 } 7159 7160 // prevent duplicate datatable init 7161 if ($(subTable).find('.' + pfx + 'datatable').length === 0) { 7162 // get data by primary id 7163 $.map(datatable.dataSet, function(n, i) { 7164 // primary id must be at the first column, otherwise e.data will be undefined 7165 if (primaryKey === n[options.columns[0].field]) { 7166 e.data = n; 7167 return true; 7168 } 7169 return false;
7170 }); 7171 7172 // deprecated in v5.0.6 7173 e.detailCell = subTable; 7174 7175 e.parentRow = parentRow; 7176 e.subTable = subTable; 7177 7178 // run callback with event 7179 subTableCallback(e); 7180 7181 $(subTable).children('.' + pfx + 'datatable').on(pfx + 'datatable-on-init', function(e) { 7182 $(subTableRow).removeClass(pfx + 'datatable-row-loading'); 7183 }); 7184 if (Plugin.getOption('data.type') === 'local') { 7185 $(subTableRow).removeClass(pfx + 'datatable-row-loading'); 7186 } 7187 } 7188 }; 7189 7190 var columns = options.columns; 7191 $(datatable.tableBody).find('.' + pfx + 'datatable-row').each(function(tri, tr) { 7192 $(tr).find('.' + pfx + 'datatable-cell').each(function(tdi, td) { 7193 // get column settings by field 7194 var column = $.grep(columns, function(n, i) { 7195 return $(td).data('field') === n.field; 7196 })[0]; 7197 if (typeof column !== 'undefined') { 7198 var value = $(td).text(); 7199 // enable column subtable toggle 7200 if (typeof column.subtable !== 'undefined' && column.subtable) { 7201 // check if subtable toggle exist 7202 if ($(td).find('.' + pfx + 'datatable-toggle-subtable').length > 0) return; 7203 // append subtable toggle 7204 $(td). 7205 html($('<a/>'). 7206 addClass(pfx + 'datatable-toggle-subtable'). 7207 attr('href', '#'). 7208 attr('data-value', value). 7209 attr('title', Plugin.getOption('detail.title')). 7210 on('click', toggleSubTable). 7211 append($('<i/>').css('width', $(td).data('width')).addClass(Plugin.getOption('layout.icons.rowDetail.collapse')))); 7212 } 7213 } 7214 }); 7215 }); 7216 7217 // $(datatable.tableHead).find('.'+pfx+'-datatable-row').first() 7218 }, 7219 7220 /** 7221 * Datasource mapping callback 7222 */ 7223 dataMapCallback: function(raw) { 7224 // static dataset array 7225 var dataSet = raw; 7226 // dataset mapping callback 7227 if (typeof Plugin.getOption('data.source.read.map') === 'function') { 7228 return Plugin.getOption('data.source.read.map')(raw); 7229 } else { 7230 // default data mapping fallback 7231 if (typeof raw !== 'undefined' && typeof raw.data !== 'undefined') { 7232 dataSet = raw.data; 7233 } 7234 } 7235 return dataSet; 7236 }, 7237 7238 isSpinning: false, 7239 /** 7240 * BlockUI spinner callback 7241 * @param block 7242 * @param target 7243 */ 7244 spinnerCallback: function(block, target) { 7245 if (typeof target === 'undefined') target = datatable; 7246 // get spinner options 7247 var spinnerOptions = Plugin.getOption('layout.spinner'); 7248 // spinner is disabled 7249 if (typeof spinnerOptions === 'undefined' || !spinnerOptions) { 7250 return; 7251 } 7252 if (block) { 7253 if (!Plugin.isSpinning) { 7254 if (typeof spinnerOptions.message !== 'undefined' && spinnerOptions.message === true) { 7255 // use default spinner message from translation 7256 spinnerOptions.message = Plugin.getOption('translate.records.processing'); 7257 } 7258 Plugin.isSpinning = true; 7259 if (typeof app !== 'undefined') { 7260 app.block(target, spinnerOptions); 7261 } 7262 } 7263 } else { 7264 Plugin.isSpinning = false; 7265 if (typeof app !== 'undefined') { 7266 app.unblock(target); 7267 } 7268 } 7269 }, 7270 7271 /** 7272 * Default sort callback function 7273 * @param data 7274 * @param sort 7275 * @param column 7276 * @returns {*|Array.<T>|{sort, field}|{asc, desc}} 7277 */ 7278 sortCallback: function(data, sort, column) { 7279 var type = column['type'] || 'string'; 7280 var format = column['format'] || ''; 7281 var field = column['field']; 7282 7283 return $(data).sort(function(a, b) { 7284 var aField = a[field]; 7285 var bField = b[field]; 7286 7287 switch (type) { 7288 case 'date': 7289 if (typeof moment === 'undefined') { 7290 throw new Error('Moment.js is required.'); 7291 } 7292 var diff = moment(aField, format).diff(moment(bField, format)); 7293 if (sort === 'asc') { 7294 return diff > 0 ? 1 : diff < 0 ? -1 : 0; 7295 } else { 7296 return diff < 0 ? 1 : diff > 0 ? -1 : 0; 7297 } 7298 break; 7299 7300 case 'number': 7301 if (isNaN(parseFloat(aField)) && aField != null) { 7302 aField = Number(aField.replace(/[^0-9\.-]+/g, '')); 7303 } 7304 if (isNaN(parseFloat(bField)) && bField != null) { 7305 bField = Number(bField.replace(/[^0-9\.-]+/g, '')); 7306 } 7307 aField = parseFloat(aField); 7308 bField = parseFloat(bField); 7309 if (sort === 'asc') { 7310 return aField > bField ? 1 : aField < bField ? -1 : 0; 7311 } else { 7312 return aField < bField ? 1 : aField > bField ? -1 : 0; 7313 } 7314 break; 7315 7316 case 'html': 7317 return $(data).sort(function(a, b) { 7318 // get the text only from html 7319 aField = $(a[field]).text(); 7320 bField = $(b[field]).text(); 7321 // sort 7322 if (sort === 'asc') { 7323 return aField > bField ? 1 : aField < bField ? -1 : 0; 7324 } else { 7325 return aField < bField ? 1 : aField > bField ? -1 : 0; 7326 } 7327 }); 7328 break; 7329 7330 case 'string': 7331 default: 7332 if (sort === 'asc') { 7333 return aField > bField ? 1 : aField < bField ? -1 : 0; 7334 } else { 7335 return aField < bField ? 1 : aField > bField ? -1 : 0; 7336 } 7337 break; 7338 } 7339 }); 7340 }, 7341 7342 /** 7343 * Custom debug log 7344 * @param text 7345 * @param obj 7346 */ 7347 log: function(text, obj) { 7348 if (typeof obj === 'undefined') obj = ''; 7349 if (datatable.debug) { 7350 console.log(text, obj); 7351 } 7352 }, 7353 7354 /** 7355 * Auto hide columnds overflow in row 7356 */ 7357 autoHide: function() { 7358 var hiddenExist = false;
7359 // force hide enabled 7360 var hidDefault = $(datatable.table).find('[data-autohide-enabled]'); 7361 if (hidDefault.length) { 7362 hiddenExist = true; 7363 hidDefault.hide(); 7364 } 7365 7366 var toggleHiddenColumns = function(e) { 7367 e.preventDefault(); 7368 7369 var row = $(this).closest('.' + pfx + 'datatable-row'); 7370 var detailRow = $(row).next(); 7371 7372 if (!$(detailRow).hasClass(pfx + 'datatable-row-detail')) { 7373 $(this).find('i').removeClass(Plugin.getOption('layout.icons.rowDetail.collapse')).addClass(Plugin.getOption('layout.icons.rowDetail.expand')); 7374 7375 var hiddenCells = $(row).find('.' + pfx + 'datatable-cell:hidden'); 7376 var clonedCells = hiddenCells.clone().show(); 7377 7378 detailRow = $('<tr/>').addClass(pfx + 'datatable-row-detail').insertAfter(row); 7379 var detailRowTd = $('<td/>').addClass(pfx + 'datatable-detail').attr('colspan', Plugin.getTotalColumns()).appendTo(detailRow); 7380 7381 var detailSubTable = $('<table/>'); 7382 $(clonedCells).each(function() { 7383 var field = $(this).data('field'); 7384 var column = $.grep(options.columns, function(n, i) { 7385 return field === n.field; 7386 })[0]; 7387 if (typeof column === 'undefined' || column.visible !== false) { 7388 $(detailSubTable). 7389 append($('<tr class="' + pfx + 'datatable-row"></tr>'). 7390 append($('<td class="' + pfx + 'datatable-cell"></td>').append($('<span/>').append(column.title))). 7391 append(this)); 7392 } 7393 }); 7394 $(detailRowTd).append(detailSubTable); 7395 7396 } else { 7397 $(this).find('i').removeClass(Plugin.getOption('layout.icons.rowDetail.expand')).addClass(Plugin.getOption('layout.icons.rowDetail.collapse')); 7398 $(detailRow).remove(); 7399 } 7400 }; 7401 7402 setTimeout(function () { 7403 $(datatable.table).find('.' + pfx + 'datatable-cell').show(); 7404 $(datatable.tableBody).each(function() { 7405 var recursive = 0; 7406 var offsetWidth = $(this)[0].offsetWidth; 7407 var scrollWidth = $(this)[0].scrollWidth; 7408 7409 while (offsetWidth < scrollWidth && (scrollWidth - offsetWidth) > Plugin.cellOffset && recursive < options.columns.length) { 7410 7411 $(datatable.table).find('.' + pfx + 'datatable-row').each(function(i) { 7412 var cell = $(this).find('.' + pfx + 'datatable-cell:not(:hidden):not([data-autohide-disabled])').last(); 7413 if (cell.length) { 7414 $(cell).hide(); 7415 hiddenExist = true; 7416 } 7417 }); 7418 recursive++; 7419 7420 offsetWidth = $(this)[0].offsetWidth; 7421 scrollWidth = $(this)[0].scrollWidth; 7422 } 7423 }); 7424 7425 if (hiddenExist) { 7426 // toggle show hidden columns 7427 $(datatable.tableBody).find('.' + pfx + 'datatable-row').each(function() { 7428 // if no toggle yet 7429 if($(this).find('.' + pfx + 'datatable-toggle-detail').length === 0) { 7430 // add toggle 7431 $(this).prepend($('<td/>'). 7432 addClass(pfx + 'datatable-cell ' + pfx + 'datatable-toggle-detail'). 7433 append($('<a/>'). 7434 addClass(pfx + 'datatable-toggle-detail'). 7435 attr('href', ''). 7436 on('click', toggleHiddenColumns). 7437 append('<i class="' + Plugin.getOption('layout.icons.rowDetail.collapse') + '"></i>'))); 7438 } 7439 7440 // check if subtable toggle exist 7441 if ($(datatable.tableHead).find('.' + pfx + 'datatable-toggle-detail').length === 0) { 7442 // add empty column to the header and footer 7443 $(datatable.tableHead). 7444 find('.' + pfx + 'datatable-row'). 7445 first(). 7446 prepend('<th class="' + pfx + 'datatable-cell ' + pfx + 'datatable-toggle-detail"><span></span></th>'); 7447 $(datatable.tableFoot). 7448 find('.' + pfx + 'datatable-row'). 7449 first(). 7450 prepend('<th class="' + pfx + 'datatable-cell ' + pfx + 'datatable-toggle-detail"><span></span></th>'); 7451 } else { 7452 $(datatable.tableHead).find('.' + pfx + 'datatable-toggle-detail').find('span'); 7453 } 7454 }); 7455 } 7456 }); 7457 7458 Plugin.adjustCellsWidth.call(); 7459 }, 7460 7461 /** 7462 * To enable auto columns features for remote data source 7463 */ 7464 setAutoColumns: function() { 7465 if (Plugin.getOption('data.autoColumns')) { 7466 $.each(datatable.dataSet[0], function(k, v) { 7467 var found = $.grep(options.columns, function(n, i) { 7468 return k === n.field; 7469 }); 7470 if (found.length === 0) {
7471 options.columns.push({field: k, title: k}); 7472 } 7473 }); 7474 $(datatable.tableHead).find('.' + pfx + 'datatable-row').remove(); 7475 Plugin.setHeadTitle(); 7476 if (Plugin.getOption('layout.footer')) { 7477 $(datatable.tableFoot).find('.' + pfx + 'datatable-row').remove(); 7478 Plugin.setHeadTitle(datatable.tableFoot); 7479 } 7480 } 7481 }, 7482 7483 /******************** 7484 ** HELPERS 7485 ********************/ 7486 7487 /** 7488 * Check if table is a locked colums table 7489 */ 7490 isLocked: function() { 7491 var isLocked = Plugin.lockEnabledColumns(); 7492 return isLocked.left.length > 0 || isLocked.right.length > 0; 7493 }, 7494 7495 isSubtable: function() { 7496 return util.hasClass(datatable.wrap[0], pfx + 'datatable-subtable') || false; 7497 }, 7498 7499 /** 7500 * Get total extra space of an element for width calculation, 7501 * including padding, margin, border 7502 * @param element 7503 * @returns {number} 7504 */ 7505 getExtraSpace: function(element) { 7506 var padding = parseInt($(element).css('paddingRight')) + 7507 parseInt($(element).css('paddingLeft')); 7508 var margin = parseInt($(element).css('marginRight')) + 7509 parseInt($(element).css('marginLeft')); 7510 var border = Math.ceil( 7511 $(element).css('border-right-width').replace('px', '')); 7512 return padding + margin + border; 7513 }, 7514 7515 /** 7516 * Insert data of array into {{ }} template placeholder 7517 * @param template 7518 * @param data 7519 * @returns {*} 7520 */ 7521 dataPlaceholder: function(template, data) { 7522 var result = template; 7523 $.each(data, function(key, val) { 7524 result = result.replace('{{' + key + '}}', val); 7525 }); 7526 return result; 7527 }, 7528 7529 /** 7530 * Get table unique ID 7531 * Note: table unique change each time refreshed 7532 * @param suffix 7533 * @returns {*} 7534 */ 7535 getTableId: function(suffix) { 7536 if (typeof suffix === 'undefined') suffix = ''; 7537 var id = $(datatable).attr('id'); 7538 if (typeof id === 'undefined') { 7539 id = $(datatable).attr('class').split(' ')[0]; 7540 } 7541 return id + suffix; 7542 }, 7543 7544 /** 7545 * Get table prefix with depth number 7546 */ 7547 getTablePrefix: function(suffix) { 7548 if (typeof suffix !== 'undefined') suffix = '-' + suffix; 7549 return Plugin.getTableId() + '-' + Plugin.getDepth() + suffix; 7550 }, 7551 7552 /** 7553 * Get current table depth of sub table 7554 * @returns {number} 7555 */ 7556 getDepth: function() { 7557 var depth = 0; 7558 var table = datatable.table; 7559 do { 7560 table = $(table).parents('.' + pfx + 'datatable-table'); 7561 depth++; 7562 } while ($(table).length > 0); 7563 return depth; 7564 }, 7565 7566 /** 7567 * Keep state item 7568 * @param key 7569 * @param value 7570 */ 7571 stateKeep: function(key, value) { 7572 key = Plugin.getTablePrefix(key); 7573 if (Plugin.getOption('data.saveState') === false) return; 7574 if (localStorage) { 7575 localStorage.setItem(key, JSON.stringify(value)); 7576 } 7577 }, 7578 7579 /** 7580 * Get state item 7581 * @param key 7582 * @param defValue 7583 */ 7584 stateGet: function(key, defValue) { 7585 key = Plugin.getTablePrefix(key); 7586 if (Plugin.getOption('data.saveState') === false) return; 7587 var value = null; 7588 if (localStorage) { 7589 value = localStorage.getItem(key); 7590 } 7591 if (typeof value !== 'undefined' && value !== null) { 7592 return JSON.parse(value); 7593 } 7594 }, 7595 7596 /** 7597 * Update data in state without clear existing 7598 * @param key 7599 * @param value 7600 */ 7601 stateUpdate: function(key, value) { 7602 var ori = Plugin.stateGet(key); 7603 if (typeof ori === 'undefined' || ori === null) ori = {}; 7604 Plugin.stateKeep(key, $.extend({}, ori, value)); 7605 }, 7606 7607 /** 7608 * Remove state item 7609 * @param key 7610 */ 7611 stateRemove: function(key) { 7612 key = Plugin.getTablePrefix(key); 7613 if (localStorage) { 7614 localStorage.removeItem(key); 7615 } 7616 }, 7617 7618 /** 7619 * Get total columns. 7620 */ 7621 getTotalColumns: function(tablePart) { 7622 if (typeof tablePart === 'undefined') tablePart = datatable.tableBody; 7623 return $(tablePart).find('.' + pfx + 'datatable-row').first().find('.' + pfx + 'datatable-cell').length; 7624 }, 7625 7626 /** 7627 * Get table row. Useful to get row when current table is in lock 7628 * mode. Can be used for both lock and normal table mode. By 7629 * default, returning result will be in a list of <td>. 7630 * @param tablePart 7631 * @param row 1-based index 7632 * @param tdOnly Optional. Default true 7633 * @returns {*} 7634 */ 7635 getOneRow: function(tablePart, row, tdOnly) { 7636 if (typeof tdOnly === 'undefined') tdOnly = true; 7637 // get list of <tr> 7638 var result = $(tablePart).find('.' + pfx + 'datatable-row:not(.' + pfx + 'datatable-row-detail):nth-child(' + row + ')'); 7639 if (tdOnly) { 7640 // get list of <td> or <th> 7641 result = result.find('.' + pfx + 'datatable-cell'); 7642 } 7643 return result; 7644 }, 7645 7646 /** 7647 * Sort table row at HTML level by column index. 7648 * todo; Not in use. 7649 * @param header Header sort clicked 7650 * @param sort asc|desc. Optional. Default asc 7651 * @param int Boolean. Optional. Comparison value parse to integer. 7652 * Default false 7653 */ 7654 sortColumn: function(header, sort, int) { 7655 if (typeof sort === 'undefined') sort = 'asc'; // desc 7656 if (typeof int === 'undefined') int = false;
7657 7658 var column = $(header).index(); 7659 var rows = $(datatable.tableBody).find('.' + pfx + 'datatable-row'); 7660 var hIndex = $(header).closest('.' + pfx + 'datatable-lock').index(); 7661 if (hIndex !== -1) { 7662 rows = $(datatable.tableBody).find('.' + pfx + 'datatable-lock:nth-child(' + (hIndex + 1) + ')').find('.' + pfx + 'datatable-row'); 7663 } 7664 7665 var container = $(rows).parent(); 7666 $(rows).sort(function(a, b) { 7667 var tda = $(a).find('td:nth-child(' + column + ')').text(); 7668 var tdb = $(b).find('td:nth-child(' + column + ')').text(); 7669 7670 if (int) { 7671 // useful for integer type sorting 7672 tda = parseInt(tda); 7673 tdb = parseInt(tdb); 7674 } 7675 7676 if (sort === 'asc') { 7677 return tda > tdb ? 1 : tda < tdb ? -1 : 0; 7678 } else { 7679 return tda < tdb ? 1 : tda > tdb ? -1 : 0; 7680 } 7681 }).appendTo(container); 7682 }, 7683 7684 /** 7685 * Perform sort remote and local 7686 */ 7687 sorting: function() { 7688 var sortObj = { 7689 init: function() { 7690 if (options.sortable) { 7691 $(datatable.tableHead). 7692 find('.' + pfx + 'datatable-cell:not(.' + pfx + 'datatable-cell-check)'). 7693 addClass(pfx + 'datatable-cell-sort'). 7694 off('click'). 7695 on('click', sortObj.sortClick); 7696 // first init 7697 sortObj.setIcon(); 7698 } 7699 }, 7700 setIcon: function() { 7701 var meta = Plugin.getDataSourceParam('sort'); 7702 if ($.isEmptyObject(meta)) return; 7703 7704 var column = Plugin.getColumnByField(meta.field); 7705 // sort is disabled for this column 7706 if (typeof column === 'undefined') return; 7707 if (typeof column.sortable !== 'undefined' && column.sortable === false) return; 7708 if (typeof column.selector !== 'undefined' && column.selector === true) return; 7709 7710 // sort icon beside column header 7711 var td = $(datatable.tableHead).find('.' + pfx + 'datatable-cell[data-field="' + meta.field + '"]').attr('data-sort', meta.sort); 7712 var sorting = $(td).find('span'); 7713 var icon = $(sorting).find('i'); 7714 7715 var icons = Plugin.getOption('layout.icons.sort'); 7716 // update sort icon; desc & asc 7717 if ($(icon).length > 0) { 7718 $(icon).removeAttr('class').addClass(icons[meta.sort]); 7719 } else { 7720 $(sorting).append($('<i/>').addClass(icons[meta.sort])); 7721 } 7722 7723 // set sorted class to header on init 7724 $(td).addClass(pfx + 'datatable-cell-sorted'); 7725 }, 7726 sortClick: function(e) { 7727 var meta = Plugin.getDataSourceParam('sort'); 7728 var field = $(this).data('field'); 7729 var column = Plugin.getColumnByField(field); 7730 // sort is disabled for this column 7731 if (typeof column === 'undefined') return; 7732 if (typeof column.sortable !== 'undefined' && column.sortable === false) return; 7733 if (typeof column.selector !== 'undefined' && column.selector === true) return; 7734 7735 // set sorted class to header 7736 $(datatable.tableHead).find('th').removeClass(pfx + 'datatable-cell-sorted'); 7737 util.addClass(this, pfx + 'datatable-cell-sorted'); 7738 7739 $(datatable.tableHead).find('.' + pfx + 'datatable-cell > span > i').remove(); 7740 7741 if (options.sortable) { 7742 Plugin.spinnerCallback(true); 7743 7744 var sort = 'desc'; 7745 if (Plugin.getObject('field', meta) === field) { 7746 sort = Plugin.getObject('sort', meta); 7747 } 7748 7749 // toggle sort 7750 sort = typeof sort === 'undefined' || sort === 'desc' 7751 ? 'asc' 7752 : 'desc'; 7753 7754 // update field and sort params 7755 meta = {field: field, sort: sort}; 7756 Plugin.setDataSourceParam('sort', meta); 7757 7758 sortObj.setIcon(); 7759 7760 setTimeout(function() { 7761 Plugin.dataRender('sort'); 7762 $(datatable).trigger(pfx + 'datatable-on-sort', meta); 7763 }, 300); 7764 } 7765 }, 7766 }; 7767 sortObj.init(); 7768 }, 7769 7770 /** 7771 * Update JSON data list linked with sort, filter and pagination. 7772 * Call this method, before using dataSet variable. 7773 * @returns {*|null} 7774 */ 7775 localDataUpdate: function() { 7776 var params = Plugin.getDataSourceParam(); 7777 if (typeof datatable.originalDataSet === 'undefined') { 7778 datatable.originalDataSet = datatable.dataSet; 7779 } 7780 7781 var field = Plugin.getObject('sort.field', params); 7782 var sort = Plugin.getObject('sort.sort', params); 7783 var column = Plugin.getColumnByField(field); 7784 if (typeof column !== 'undefined' && Plugin.getOption('data.serverSorting') !== true) { 7785 if (typeof column.sortCallback === 'function') { 7786 datatable.dataSet = column.sortCallback(datatable.originalDataSet, sort, column); 7787 } else { 7788 datatable.dataSet = Plugin.sortCallback(datatable.originalDataSet, sort, column); 7789 } 7790 } else { 7791 datatable.dataSet = datatable.originalDataSet; 7792 } 7793 7794 // if server filter enable, don't pass local filter 7795 if (typeof params.query === 'object' && !Plugin.getOption('data.serverFiltering')) { 7796 params.query = params.query || {}; 7797 7798 var nestedSearch = function(obj) { 7799 for (var field in obj) { 7800 if (!obj.hasOwnProperty(field)) continue; 7801 if (typeof obj[field] === 'string') { 7802 if (obj[field].toLowerCase() == search || obj[field].toLowerCase().indexOf(search) !== -1) { 7803 return true; 7804 } 7805 } else if (typeof obj[field] === 'number') { 7806 if (obj[field] === search) { 7807 return true; 7808 } 7809 } else if (typeof obj[field] === 'object') { 7810 if (nestedSearch(obj[field])) { 7811 return true; 7812 } 7813 } 7814 } 7815 return false;
7816 }; 7817 7818 var search = $(Plugin.getOption('search.input')).val(); 7819 if (typeof search !== 'undefined' && search !== '') { 7820 search = search.toLowerCase(); 7821 datatable.dataSet = $.grep(datatable.dataSet, nestedSearch); 7822 // remove generalSearch as we don't need this for next columns filter 7823 delete params.query[Plugin.getGeneralSearchKey()]; 7824 } 7825 7826 // remove empty element from array 7827 $.each(params.query, function(k, v) { 7828 if (v === '') { 7829 delete params.query[k]; 7830 } 7831 }); 7832 7833 // filter array by query 7834 datatable.dataSet = Plugin.filterArray(datatable.dataSet, params.query); 7835 7836 // reset array index 7837 datatable.dataSet = datatable.dataSet.filter(function() { 7838 return true; 7839 }); 7840 } 7841 7842 return datatable.dataSet; 7843 }, 7844 7845 /** 7846 * Utility helper to filter array by object pair of {key:value} 7847 * @param list 7848 * @param args 7849 * @param operator 7850 * @returns {*} 7851 */ 7852 filterArray: function(list, args, operator) { 7853 if (typeof list !== 'object') { 7854 return []; 7855 } 7856 7857 if (typeof operator === 'undefined') operator = 'AND'; 7858 7859 if (typeof args !== 'object') { 7860 return list; 7861 } 7862 7863 operator = operator.toUpperCase(); 7864 7865 if ($.inArray(operator, ['AND', 'OR', 'NOT']) === -1) { 7866 return []; 7867 } 7868 7869 var count = Object.keys(args).length; 7870 var filtered = []; 7871 7872 $.each(list, function(key, obj) { 7873 var to_match = obj; 7874 7875 var matched = 0; 7876 $.each(args, function(m_key, m_value) { 7877 m_value = m_value instanceof Array ? m_value : [m_value]; 7878 var match_property = Plugin.getObject(m_key, to_match); 7879 if (typeof match_property !== 'undefined' && match_property) { 7880 var lhs = match_property.toString().toLowerCase(); 7881 m_value.forEach(function(item, index) { 7882 if (item.toString().toLowerCase() == lhs || lhs.indexOf(item.toString().toLowerCase()) !== -1) { 7883 matched++; 7884 } 7885 }); 7886 } 7887 }); 7888 7889 if (('AND' == operator && matched == count) || 7890 ('OR' == operator && matched > 0) || 7891 ('NOT' == operator && 0 == matched)) { 7892 filtered[key] = obj; 7893 } 7894 }); 7895 7896 list = filtered; 7897 7898 return list; 7899 }, 7900 7901 /** 7902 * Reset lock column scroll to 0 when resize 7903 */ 7904 resetScroll: function() { 7905 if (typeof options.detail === 'undefined' && Plugin.getDepth() === 1) { 7906 $(datatable.table).find('.' + pfx + 'datatable-row').css('left', 0); 7907 $(datatable.table).find('.' + pfx + 'datatable-lock').css('top', 0); 7908 $(datatable.tableBody).scrollTop(0); 7909 } 7910 }, 7911 7912 /** 7913 * Get column options by field 7914 * @param field 7915 * @returns {boolean} 7916 */ 7917 getColumnByField: function(field) { 7918 if (typeof field === 'undefined') return; 7919 var result; 7920 $.each(options.columns, function(i, column) { 7921 if (field === column.field) { 7922 result = column; 7923 return false; 7924 } 7925 }); 7926 return result; 7927 }, 7928 7929 /** 7930 * Get default sort column 7931 */ 7932 getDefaultSortColumn: function() { 7933 var result; 7934 $.each(options.columns, function(i, column) { 7935 if (typeof column.sortable !== 'undefined' 7936 && $.inArray(column.sortable, ['asc', 'desc']) !== -1) { 7937 result = {sort: column.sortable, field: column.field}; 7938 return false; 7939 } 7940 }); 7941 return result; 7942 }, 7943 7944 /** 7945 * Helper to get element dimensions, when the element is hidden 7946 * @param element 7947 * @param includeMargin 7948 * @returns {{width: number, height: number, innerWidth: number, 7949 * innerHeight: number, outerWidth: number, outerHeight: 7950 * number}} 7951 */ 7952 getHiddenDimensions: function(element, includeMargin) { 7953 var props = { 7954 position: 'absolute', 7955 visibility: 'hidden', 7956 display: 'block', 7957 }, 7958 dim = { 7959 width: 0, 7960 height: 0, 7961 innerWidth: 0, 7962 innerHeight: 0, 7963 outerWidth: 0, 7964 outerHeight: 0, 7965 }, 7966 hiddenParents = $(element).parents().addBack().not(':visible'); 7967 includeMargin = (typeof includeMargin === 'boolean') 7968 ? includeMargin 7969 : false; 7970 7971 var oldProps = []; 7972 hiddenParents.each(function() { 7973 var old = {}; 7974 7975 for (var name in props) { 7976 old[name] = this.style[name]; 7977 this.style[name] = props[name]; 7978 } 7979 7980 oldProps.push(old); 7981 }); 7982 7983 dim.width = $(element).width(); 7984 dim.outerWidth = $(element).outerWidth(includeMargin); 7985 dim.innerWidth = $(element).innerWidth(); 7986 dim.height = $(element).height();
7987 dim.innerHeight = $(element).innerHeight(); 7988 dim.outerHeight = $(element).outerHeight(includeMargin); 7989 7990 hiddenParents.each(function(i) { 7991 var old = oldProps[i]; 7992 for (var name in props) { 7993 this.style[name] = old[name]; 7994 } 7995 }); 7996 7997 return dim; 7998 }, 7999 8000 getGeneralSearchKey: function() { 8001 var searchInput = $(Plugin.getOption('search.input')); 8002 return Plugin.getOption('search.key') || $(searchInput).prop('name'); 8003 }, 8004 8005 /** 8006 * Get value by dot notation path string and to prevent undefined 8007 * errors 8008 * @param path String Dot notation path in string 8009 * @param object Object to iterate 8010 * @returns {*} 8011 */ 8012 getObject: function(path, object) { 8013 return path.split('.').reduce(function(obj, i) { 8014 return obj !== null && typeof obj[i] !== 'undefined' ? obj[i] : null; 8015 }, object); 8016 }, 8017 8018 /** 8019 * Extend object 8020 * @param obj 8021 * @param path 8022 * @param value 8023 * @returns {*} 8024 */ 8025 extendObj: function(obj, path, value) { 8026 var levels = path.split('.'), 8027 i = 0; 8028 8029 function createLevel(child) { 8030 var name = levels[i++]; 8031 if (typeof child[name] !== 'undefined' && child[name] !== null) { 8032 if (typeof child[name] !== 'object' && 8033 typeof child[name] !== 'function') { 8034 child[name] = {}; 8035 } 8036 } else { 8037 child[name] = {}; 8038 } 8039 if (i === levels.length) { 8040 child[name] = value; 8041 } else { 8042 createLevel(child[name]); 8043 } 8044 } 8045 8046 createLevel(obj); 8047 return obj; 8048 }, 8049 8050 rowEvenOdd: function() { 8051 // row even class 8052 $(datatable.tableBody).find('.' + pfx + 'datatable-row').removeClass(pfx + 'datatable-row-even'); 8053 if ($(datatable.wrap).hasClass(pfx + 'datatable-subtable')) { 8054 $(datatable.tableBody).find('.' + pfx + 'datatable-row:not(.' + pfx + 'datatable-row-detail):even').addClass(pfx + 'datatable-row-even'); 8055 } else { 8056 $(datatable.tableBody).find('.' + pfx + 'datatable-row:nth-child(even)').addClass(pfx + 'datatable-row-even'); 8057 } 8058 }, 8059 8060 /******************** 8061 ** PUBLIC API METHODS 8062 ********************/ 8063 8064 // delay timer 8065 timer: 0, 8066 8067 /** 8068 * Redraw datatable by recalculating its DOM elements, etc. 8069 * @returns {jQuery} 8070 */ 8071 redraw: function() { 8072 Plugin.adjustCellsWidth.call(); 8073 if (Plugin.isLocked()) { 8074 // fix hiding cell width issue 8075 Plugin.scrollbar(); 8076 Plugin.resetScroll(); 8077 Plugin.adjustCellsHeight.call(); 8078 } 8079 Plugin.adjustLockContainer.call(); 8080 Plugin.initHeight.call(); 8081 return datatable; 8082 }, 8083 8084 /** 8085 * Shortcode to reload 8086 * @returns {jQuery} 8087 */ 8088 load: function() { 8089 Plugin.reload(); 8090 return datatable; 8091 }, 8092 8093 /** 8094 * Datasource reload 8095 * @returns {jQuery} 8096 */ 8097 reload: function() { 8098 var delay = (function() { 8099 return function(callback, ms) { 8100 clearTimeout(Plugin.timer); 8101 Plugin.timer = setTimeout(callback, ms); 8102 }; 8103 })(); 8104 delay(function() { 8105 // local only. remote pagination will skip this block 8106 if (!options.data.serverFiltering) { 8107 Plugin.localDataUpdate(); 8108 } 8109 Plugin.dataRender(); 8110 $(datatable).trigger(pfx + 'datatable-on-reloaded'); 8111 }, Plugin.getOption('search.delay')); 8112 return datatable; 8113 }, 8114 8115 /** 8116 * Get record by record ID 8117 * @param id 8118 * @returns {jQuery} 8119 */ 8120 getRecord: function(id) { 8121 if (typeof datatable.tableBody === 'undefined') datatable.tableBody = $(datatable.table).children('tbody'); 8122 $(datatable.tableBody).find('.' + pfx + 'datatable-cell:first-child').each(function(i, cell) { 8123 if (id == $(cell).text()) { 8124 var rowNumber = $(cell).closest('.' + pfx + 'datatable-row').index() + 1; 8125 datatable.API.record = datatable.API.value = Plugin.getOneRow(datatable.tableBody, rowNumber); 8126 return datatable; 8127 } 8128 }); 8129 return datatable; 8130 }, 8131 8132 /** 8133 * @deprecated in v5.0.6 8134 * Get column of current record ID 8135 * @param columnName 8136 * @returns {jQuery} 8137 */ 8138 getColumn: function(columnName) { 8139 Plugin.setSelectedRecords(); 8140 datatable.API.value = $(datatable.API.record).find('[data-field="' + columnName + '"]'); 8141 return datatable; 8142 }, 8143 8144 /** 8145 * Destroy datatable to original DOM state before datatable was 8146 * initialized 8147 * @returns {jQuery} 8148 */ 8149 destroy: function() { 8150 $(datatable).parent().find('.' + pfx + 'datatable-pager').remove(); 8151 var initialDatatable = $(datatable.initialDatatable).addClass(pfx + 'datatable-destroyed').show(); 8152 $(datatable).replaceWith(initialDatatable); 8153 datatable = initialDatatable; 8154 $(datatable).trigger(pfx + 'datatable-on-destroy'); 8155 Plugin.isInit = false;
8156 8157 // clean up variables 8158 initialDatatable = null; 8159 datatable.dataSet = null; 8160 datatable.originalDataSet = null; 8161 datatable.tableHead = null; 8162 datatable.tableBody = null; 8163 datatable.table = null; 8164 datatable.wrap = null; 8165 datatable.API = { 8166 record: null, 8167 value: null, 8168 params: null, 8169 }; 8170 8171 Plugin.ajaxParams = {}; 8172 Plugin.pagingObject = {}; 8173 Plugin.nodeTr = []; 8174 Plugin.nodeTd = []; 8175 Plugin.nodeCols = []; 8176 Plugin.recentNode = []; 8177 8178 return initialDatatable; 8179 }, 8180 8181 /** 8182 * Sort by column field 8183 * @param field 8184 * @param sort 8185 */ 8186 sort: function(field, sort) { 8187 // toggle sort 8188 sort = typeof sort === 'undefined' ? 'asc' : sort; 8189 8190 Plugin.spinnerCallback(true); 8191 8192 // update field and sort params 8193 var meta = {field: field, sort: sort}; 8194 Plugin.setDataSourceParam('sort', meta); 8195 8196 setTimeout(function() { 8197 Plugin.dataRender('sort'); 8198 $(datatable).trigger(pfx + 'datatable-on-sort', meta); 8199 $(datatable.tableHead).find('.' + pfx + 'datatable-cell > span > i').remove(); 8200 }, 300); 8201 8202 return datatable; 8203 }, 8204 8205 /** 8206 * @deprecated in v5.0.6 8207 * Get current selected column value 8208 * @returns {jQuery} 8209 */ 8210 getValue: function() { 8211 return $(datatable.API.value).text(); 8212 }, 8213 8214 /** 8215 * Set checkbox active 8216 * @param cell JQuery selector or checkbox ID 8217 */ 8218 setActive: function(cell) { 8219 if (typeof cell === 'string') { 8220 // set by checkbox id 8221 cell = $(datatable.tableBody).find('.' + pfx + 'checkbox-single > [type="checkbox"][value="' + cell + '"]'); 8222 } 8223 8224 $(cell).prop('checked', true); 8225 8226 var ids = []; 8227 $(cell).each(function(i, td) { 8228 // normal table 8229 var row = $(td).closest('tr').addClass(pfx + 'datatable-row-active'); 8230 8231 var id = $(td).attr('value'); 8232 if (typeof id !== 'undefined') { 8233 ids.push(id); 8234 } 8235 }); 8236 8237 $(datatable).trigger(pfx + 'datatable-on-check', [ids]); 8238 }, 8239 8240 /** 8241 * Set checkbox inactive 8242 * @param cell JQuery selector or checkbox ID 8243 */ 8244 setInactive: function(cell) { 8245 if (typeof cell === 'string') { 8246 // set by checkbox id 8247 cell = $(datatable.tableBody).find('.' + pfx + 'checkbox-single > [type="checkbox"][value="' + cell + '"]'); 8248 } 8249 8250 $(cell).prop('checked', false); 8251 8252 var ids = []; 8253 $(cell).each(function(i, td) { 8254 // normal table 8255 var row = $(td).closest('tr').removeClass(pfx + 'datatable-row-active'); 8256 8257 var id = $(td).attr('value'); 8258 if (typeof id !== 'undefined') { 8259 ids.push(id); 8260 } 8261 }); 8262 8263 $(datatable).trigger(pfx + 'datatable-on-uncheck', [ids]); 8264 }, 8265 8266 /** 8267 * Set all checkboxes active or inactive 8268 * @param active 8269 */ 8270 setActiveAll: function(active) { 8271 var checkboxes = $(datatable.table). 8272 find('> tbody, > thead'). 8273 find('tr').not('.' + pfx + 'datatable-row-subtable'). 8274 find('.' + pfx + 'datatable-cell-check [type="checkbox"]'); 8275 if (active) { 8276 Plugin.setActive(checkboxes); 8277 } else { 8278 Plugin.setInactive(checkboxes); 8279 } 8280 }, 8281 8282 /** 8283 * @deprecated in v5.0.6 8284 * Get selected rows which are active 8285 * @returns {jQuery} 8286 */ 8287 setSelectedRecords: function() { 8288 datatable.API.record = $(datatable.tableBody).find('.' + pfx + 'datatable-row-active'); 8289 return datatable; 8290 }, 8291 8292 /** 8293 * Get selected records 8294 * @returns {null} 8295 */ 8296 getSelectedRecords: function() { 8297 // support old method 8298 Plugin.setSelectedRecords(); 8299 datatable.API.record = datatable.rows('.' + pfx + 'datatable-row-active').nodes(); 8300 return datatable.API.record; 8301 }, 8302 8303 /** 8304 * Get options by dots notation path 8305 * @param path String Dot notation path in string 8306 * @returns {*} 8307 */ 8308 getOption: function(path) { 8309 return Plugin.getObject(path, options); 8310 }, 8311 8312 /** 8313 * Set global options nodes by dots notation path 8314 * @param path 8315 * @param object 8316 */ 8317 setOption: function(path, object) { 8318 options = Plugin.extendObj(options, path, object); 8319 }, 8320 8321 /** 8322 * Search filter for local & remote 8323 * @param value 8324 * @param columns. Optional list of columns to be filtered. 8325 */ 8326 search: function(value, columns) { 8327 if (typeof columns !== 'undefined') columns = $.makeArray(columns);
8328 var delay = (function() { 8329 return function(callback, ms) { 8330 clearTimeout(Plugin.timer); 8331 Plugin.timer = setTimeout(callback, ms); 8332 }; 8333 })(); 8334 8335 delay(function() { 8336 // get query parameters 8337 var query = Plugin.getDataSourceQuery(); 8338 8339 // search not by columns 8340 if (typeof columns === 'undefined' && typeof value !== 'undefined') { 8341 var key = Plugin.getGeneralSearchKey(); 8342 query[key] = value; 8343 } 8344 8345 // search by columns, support multiple columns 8346 if (typeof columns === 'object') { 8347 $.each(columns, function(k, column) { 8348 query[column] = value; 8349 }); 8350 // remove empty element from arrays 8351 $.each(query, function(k, v) { 8352 if (v === '' || $.isEmptyObject(v)) { 8353 delete query[k]; 8354 } 8355 }); 8356 } 8357 8358 Plugin.setDataSourceQuery(query); 8359 8360 // reset pagination to 1 when doing seearching 8361 datatable.setDataSourceParam('pagination', Object.assign({}, datatable.getDataSourceParam('pagination'), {page: 1})); 8362 8363 // local filter only. remote pagination will skip this block 8364 if (!options.data.serverFiltering) { 8365 Plugin.localDataUpdate(); 8366 } 8367 Plugin.dataRender('search'); 8368 }, Plugin.getOption('search.delay')); 8369 }, 8370 8371 /** 8372 * Set datasource params extract 8373 * @param param 8374 * @param value 8375 */ 8376 setDataSourceParam: function(param, value) { 8377 datatable.API.params = $.extend({}, { 8378 pagination: {page: 1, perpage: Plugin.getOption('data.pageSize')}, 8379 sort: Plugin.getDefaultSortColumn(), 8380 query: {}, 8381 }, datatable.API.params, Plugin.stateGet(Plugin.stateId)); 8382 8383 datatable.API.params = Plugin.extendObj(datatable.API.params, param, value); 8384 8385 Plugin.stateKeep(Plugin.stateId, datatable.API.params); 8386 }, 8387 8388 /** 8389 * Get datasource params 8390 * @param param 8391 */ 8392 getDataSourceParam: function(param) { 8393 datatable.API.params = $.extend({}, { 8394 pagination: {page: 1, perpage: Plugin.getOption('data.pageSize')}, 8395 sort: Plugin.getDefaultSortColumn(), 8396 query: {}, 8397 }, datatable.API.params, Plugin.stateGet(Plugin.stateId)); 8398 8399 if (typeof param === 'string') { 8400 return Plugin.getObject(param, datatable.API.params); 8401 } 8402 8403 return datatable.API.params; 8404 }, 8405 8406 /** 8407 * Shortcode to datatable.getDataSourceParam('query'); 8408 * @returns {*} 8409 */ 8410 getDataSourceQuery: function() { 8411 return Plugin.getDataSourceParam('query') || {}; 8412 }, 8413 8414 /** 8415 * Shortcode to datatable.setDataSourceParam('query', query); 8416 * @param query 8417 */ 8418 setDataSourceQuery: function(query) { 8419 Plugin.setDataSourceParam('query', query); 8420 }, 8421 8422 /** 8423 * Get current page number 8424 * @returns {number} 8425 */ 8426 getCurrentPage: function() { 8427 return $(datatable.table). 8428 siblings('.' + pfx + 'datatable-pager'). 8429 last(). 8430 find('.' + pfx + 'datatable-pager-nav'). 8431 find('.' + pfx + 'datatable-pager-link.' + pfx + 'datatable-pager-link-active'). 8432 data('page') || 1; 8433 }, 8434 8435 /** 8436 * Get selected dropdown page size 8437 * @returns {*|number} 8438 */ 8439 getPageSize: function() { 8440 return $(datatable.table).siblings('.' + pfx + 'datatable-pager').last().find('select.' + pfx + 'datatable-pager-size').val() || 10; 8441 }, 8442 8443 /** 8444 * Get total rows 8445 */ 8446 getTotalRows: function() { 8447 return datatable.API.params.pagination.total; 8448 }, 8449 8450 /** 8451 * Get full dataset in grid 8452 * @returns {*|null|Array} 8453 */ 8454 getDataSet: function() { 8455 return datatable.originalDataSet; 8456 }, 8457 8458 nodeTr: [], 8459 nodeTd: [], 8460 nodeCols: [], 8461 recentNode: [], 8462 8463 table: function() { 8464 if (typeof datatable.table !== 'undefined') { 8465 return datatable.table; 8466 } 8467 }, 8468 8469 /** 8470 * Select a single row from the table 8471 * @param selector 8472 * @returns {jQuery} 8473 */ 8474 row: function(selector) { 8475 Plugin.rows(selector); 8476 Plugin.nodeTr = Plugin.recentNode = $(Plugin.nodeTr).first(); 8477 return datatable; 8478 }, 8479 8480 /** 8481 * Select multiple rows from the table 8482 * @param selector 8483 * @returns {jQuery} 8484 */ 8485 rows: function(selector) { 8486 if (Plugin.isLocked()) { 8487 Plugin.nodeTr = Plugin.recentNode = $(datatable.tableBody).find(selector).filter('.' + pfx + 'datatable-lock-scroll > .' + pfx + 'datatable-row'); 8488 } else { 8489 Plugin.nodeTr = Plugin.recentNode = $(datatable.tableBody).find(selector).filter('.' + pfx + 'datatable-row'); 8490 } 8491 return datatable; 8492 }, 8493 8494 /** 8495 * Select a single column from the table 8496 * @param index zero-based index 8497 * @returns {jQuery} 8498 */ 8499 column: function(index) { 8500 Plugin.nodeCols = Plugin.recentNode = $(datatable.tableBody).find('.' + pfx + 'datatable-cell:nth-child(' + (index + 1) + ')'); 8501 return datatable; 8502 }, 8503 8504 /** 8505 * Select multiple columns from the table 8506 * @param selector 8507 * @returns {jQuery} 8508 */ 8509 columns: function(selector) { 8510 var context = datatable.table; 8511 if (Plugin.nodeTr === Plugin.recentNode) { 8512 context = Plugin.nodeTr; 8513 } 8514 var columns = $(context).find('.' + pfx + 'datatable-cell[data-field="' + selector + '"]'); 8515 if (columns.length > 0) { 8516 Plugin.nodeCols = Plugin.recentNode = columns; 8517 } else { 8518 Plugin.nodeCols = Plugin.recentNode = $(context).find(selector).filter('.' + pfx + 'datatable-cell'); 8519 } 8520 return datatable; 8521 }, 8522 8523 cell: function(selector) { 8524 Plugin.cells(selector); 8525 Plugin.nodeTd = Plugin.recentNode = $(Plugin.nodeTd).first(); 8526 return datatable; 8527 }, 8528 8529 cells: function(selector) { 8530 var cells = $(datatable.tableBody).find('.' + pfx + 'datatable-cell'); 8531 if (typeof selector !== 'undefined') { 8532 cells = $(cells).filter(selector); 8533 } 8534 Plugin.nodeTd = Plugin.recentNode = cells; 8535 return datatable; 8536 }, 8537 8538 /** 8539 * Delete the selected row from the table 8540 * @returns {jQuery} 8541 */ 8542 remove: function() { 8543 if ($(Plugin.nodeTr.length) && Plugin.nodeTr === Plugin.recentNode) { 8544 $(Plugin.nodeTr).remove(); 8545 } 8546 Plugin.layoutUpdate(); 8547 return datatable; 8548 }, 8549 8550 /** 8551 * Show or hide the columns or rows 8552 */ 8553 visible: function(bool) { 8554 if ($(Plugin.recentNode.length)) { 8555 var locked = Plugin.lockEnabledColumns(); 8556 if (Plugin.recentNode === Plugin.nodeCols) { 8557 var index = Plugin.recentNode.index(); 8558 8559 if (Plugin.isLocked()) { 8560 var scrollColumns = $(Plugin.recentNode).closest('.' + pfx + 'datatable-lock-scroll').length; 8561 if (scrollColumns) { 8562 // is at center of scrollable area 8563 index += locked.left.length + 1; 8564 } else if ($(Plugin.recentNode).closest('.' + pfx + 'datatable-lock-right').length) { 8565 // is at the right locked table
8566 index += locked.left.length + scrollColumns + 1; 8567 } 8568 } 8569 } 8570 8571 if (bool) { 8572 if (Plugin.recentNode === Plugin.nodeCols) { 8573 delete options.columns[index].visible; 8574 } 8575 $(Plugin.recentNode).show(); 8576 } else { 8577 if (Plugin.recentNode === Plugin.nodeCols) { 8578 Plugin.setOption('columns.' + (index) + '.visible', false); 8579 } 8580 $(Plugin.recentNode).hide(); 8581 } 8582 Plugin.columnHide(); 8583 Plugin.redraw(); 8584 } 8585 }, 8586 8587 /** 8588 * Get the the DOM element for the selected rows or columns 8589 * @returns {Array} 8590 */ 8591 nodes: function() { 8592 return Plugin.recentNode; 8593 }, 8594 8595 /** 8596 * will be implemented soon 8597 * @returns {jQuery} 8598 */ 8599 dataset: function() { 8600 return datatable; 8601 }, 8602 8603 /** 8604 * Open page by number 8605 * @param page number 8606 */ 8607 gotoPage: function (page) { 8608 if (typeof Plugin.pagingObject !== 'undefined') { 8609 Plugin.isInit = true; 8610 Plugin.pagingObject.openPage(page); 8611 } 8612 }, 8613 8614 }; 8615 8616 /** 8617 * Public API methods can be used directly by datatable 8618 */ 8619 $.each(Plugin, function(funcName, func) { 8620 datatable[funcName] = func; 8621 }); 8622 8623 // initialize main datatable plugin 8624 if (typeof options !== 'undefined') { 8625 if (typeof options === 'string') { 8626 var method = options; 8627 datatable = $(this).data(pluginName); 8628 if (typeof datatable !== 'undefined') { 8629 options = datatable.options; 8630 Plugin[method].apply(this, Array.prototype.slice.call(arguments, 1)); 8631 } 8632 } else { 8633 if (!datatable.data(pluginName) && !$(this).hasClass(pfx + 'datatable-loaded')) { 8634 datatable.dataSet = null; 8635 datatable.textAlign = { 8636 left: pfx + 'datatable-cell-left', 8637 center: pfx + 'datatable-cell-center', 8638 right: pfx + 'datatable-cell-right', 8639 }; 8640 8641 // merge default and user defined options 8642 options = $.extend(true, {}, $.fn[pluginName].defaults, options); 8643 8644 datatable.options = options; 8645 8646 // init plugin process 8647 Plugin.init.apply(this, [options]); 8648 8649 $(datatable.wrap).data(pluginName, datatable); 8650 } 8651 } 8652 } else { 8653 // get existing instance datatable 8654 datatable = $(this).data(pluginName); 8655 if (typeof datatable === 'undefined') { 8656 $.error(pluginName + ' not initialized'); 8657 } 8658 options = datatable.options; 8659 } 8660 8661 return datatable; 8662 }; 8663 8664 // default options 8665 $.fn[pluginName].defaults = { 8666 // datasource definition 8667 data: { 8668 type: 'local', 8669 source: null, 8670 pageSize: 10, // display records per page 8671 saveState: true, 8672 8673 serverPaging: false, 8674 serverFiltering: false, 8675 serverSorting: false, 8676 8677 autoColumns: false, 8678 attr: { 8679 rowProps: [], 8680 }, 8681 }, 8682 8683 // layout definition 8684 layout: { 8685 theme: 'default', // datatable will support multiple themes and designs 8686 class: pfx + 'datatable-primary', // custom wrapper class 8687 scroll: false, // enable/disable datatable scroll both horizontal and vertical when needed. 8688 height: null, // datatable's body's fixed height 8689 minHeight: null, 8690 footer: false, // display/hide footer 8691 header: true, // display/hide header 8692 customScrollbar: true, // set false to disable custom scrollbar 8693 8694 // datatable spinner 8695 spinner: { 8696 overlayColor: '#000000', 8697 opacity: 0, 8698 type: 'loader', 8699 state: 'primary', 8700 message: true, 8701 }, 8702 8703 // datatable UI icons 8704 icons: { 8705 sort: {asc: 'flaticon2-arrow-up', desc: 'flaticon2-arrow-down'}, 8706 pagination: { 8707 next: 'flaticon2-next', 8708 prev: 'flaticon2-back', 8709 first: 'flaticon2-fast-back', 8710 last: 'flaticon2-fast-next', 8711 more: 'flaticon-more-1', 8712 }, 8713 rowDetail: {expand: 'fa fa-caret-down', collapse: 'fa fa-caret-right'}, 8714 }, 8715 }, 8716 8717 // column sorting 8718 sortable: true, 8719 8720 // resize column size with mouse drag coming soon) 8721 resizable: false, 8722 8723 // column based filtering (coming soon) 8724 filterable: false, 8725 8726 pagination: true, 8727 8728 // inline and bactch editing (cooming soon) 8729 editable: false, 8730 8731 // columns definition 8732 columns: [], 8733 8734 search: { 8735 // enable trigger search by keyup enter 8736 onEnter: false, 8737 // input text for search 8738 input: null, 8739 // search delay in milliseconds 8740 delay: 400, 8741 // remote server search key value 8742 key: null 8743 }, 8744 8745 rows: { 8746 // deprecated 8747 callback: function() { 8748 }, 8749 // call before row template 8750 beforeTemplate: function() { 8751 }, 8752 // call after row template 8753 afterTemplate: function() { 8754 }, 8755 autoHide: true, 8756 }, 8757 8758 // toolbar 8759 toolbar: { 8760 // place pagination and displayInfo blocks according to the array order 8761 layout: ['pagination', 'info'], 8762 8763 // toolbar placement can be at top or bottom or both top and bottom repeated 8764 placement: ['bottom'], //'top', 'bottom' 8765 8766 // toolbar items 8767 items: { 8768 // pagination 8769 pagination: { 8770 // pagination type(default or scroll) 8771 type: 'default', 8772 8773 // number of pages to display by breakpoints 8774 pages: { 8775 desktop: { 8776 layout: 'default', 8777 pagesNumber: 5, 8778 }, 8779 tablet: { 8780 layout: 'default', 8781 pagesNumber: 3, 8782 }, 8783 mobile: { 8784 layout: 'compact', 8785 }, 8786 }, 8787 8788 // navigation buttons 8789 navigation: { 8790 prev: true, // display prev button 8791 next: true, // display next button 8792 first: true, // display first button 8793 last: true, // display last button 8794 more: false // display more button 8795 }, 8796 8797 // page size select 8798 pageSizeSelect: [], // display dropdown to select pagination size. -1 is used for "ALl" option 8799 }, 8800 8801 // records info 8802 info: true, 8803 }, 8804 }, 8805 8806 // here we will keep all strings and message used by datatable UI so developer can easiliy translate to any language. 8807 // By default the stirngs will be in the plugin source and here can override it 8808 translate: { 8809 records: { 8810 processing: 'Please wait...',
8811 noRecords: 'No records found', 8812 }, 8813 toolbar: { 8814 pagination: { 8815 items: { 8816 default: { 8817 first: 'First', 8818 prev: 'Previous', 8819 next: 'Next', 8820 last: 'Last', 8821 more: 'More pages', 8822 input: 'Page number', 8823 select: 'Select page size', 8824 all: 'all', 8825 }, 8826 info: 'Showing {{start}} - {{end}} of {{total}}', 8827 }, 8828 }, 8829 }, 8830 }, 8831 8832 extensions: {}, 8833 }; 8834 8835}(jQuery)); 8836 8837"use strict"; 8838(function($) { 8839 8840 var pluginName = 'KTDatatable'; 8841 var pfx = ''; 8842 8843 $.fn[pluginName] = $.fn[pluginName] || {}; 8844 8845 /** 8846 * @param datatable Main datatable plugin instance 8847 * @param options Extension options 8848 * @returns {*} 8849 */ 8850 $.fn[pluginName].checkbox = function(datatable, options) { 8851 var Extension = { 8852 selectedAllRows: false, 8853 selectedRows: [], 8854 unselectedRows: [], 8855 8856 init: function() { 8857 if (Extension.selectorEnabled()) { 8858 // reset 8859 datatable.setDataSourceParam(options.vars.selectedAllRows, false); 8860 datatable.stateRemove('checkbox'); 8861 8862 // requestIds is not null 8863 if (options.vars.requestIds) { 8864 // request ids in response 8865 datatable.setDataSourceParam(options.vars.requestIds, true); 8866 } 8867 8868 // remove selected checkbox on datatable reload 8869 $(datatable).on(pfx + 'datatable-on-reloaded', function() { 8870 datatable.stateRemove('checkbox'); 8871 datatable.setDataSourceParam(options.vars.selectedAllRows, false); 8872 Extension.selectedAllRows = false; 8873 Extension.selectedRows = []; 8874 Extension.unselectedRows = []; 8875 }); 8876 8877 // select all on extension init 8878 Extension.selectedAllRows = datatable.getDataSourceParam(options.vars.selectedAllRows); 8879 8880 $(datatable).on(pfx + 'datatable-on-layout-updated', function(e, args) { 8881 if (args.table != $(datatable.wrap).attr('id')) { 8882 return; 8883 } 8884 datatable.ready(function() { 8885 Extension.initVars(); 8886 Extension.initEvent(); 8887 Extension.initSelect(); 8888 }); 8889 }); 8890 8891 $(datatable).on(pfx + 'datatable-on-check', function(e, ids) { 8892 ids.forEach(function(id) { 8893 Extension.selectedRows.push(id); 8894 // // remove from unselected rows 8895 Extension.unselectedRows = Extension.remove(Extension.unselectedRows, id); 8896 }); 8897 var storage = {}; 8898 storage['selectedRows'] = Extension.selectedRows.filter(Extension.unique); 8899 storage['unselectedRows'] = Extension.unselectedRows.filter(Extension.unique); 8900 datatable.stateKeep('checkbox', storage); 8901 }); 8902 $(datatable).on(pfx + 'datatable-on-uncheck', function(e, ids) { 8903 ids.forEach(function(id) { 8904 Extension.unselectedRows.push(id); 8905 // // remove from selected rows 8906 Extension.selectedRows = Extension.remove(Extension.selectedRows, id); 8907 }); 8908 var storage = {}; 8909 storage['selectedRows'] = Extension.selectedRows.filter(Extension.unique); 8910 storage['unselectedRows'] = Extension.unselectedRows.filter(Extension.unique); 8911 storage['unselectedRows'] = Extension.unselectedRows.filter(Extension.unique); 8912 datatable.stateKeep('checkbox', storage); 8913 }); 8914 } 8915 }, 8916 8917 /** 8918 * Init checkbox clicks event 8919 */ 8920 initEvent: function() { 8921 // select all checkbox click 8922 $(datatable.tableHead).find('.' + pfx + 'checkbox-all > [type="checkbox"]').click(function(e) { 8923 // clear selected and unselected rows 8924 Extension.selectedRows = Extension.unselectedRows = []; 8925 datatable.stateRemove('checkbox'); 8926 8927 // select all rows 8928 Extension.selectedAllRows = !!$(this).is(':checked'); 8929 8930 // local select all current page rows 8931 if (!options.vars.requestIds) { 8932 if ($(this).is(':checked')) { 8933 Extension.selectedRows = $.makeArray($(datatable.tableBody).find('.' + pfx + 'checkbox-single > [type="checkbox"]').map(function(i, chk) { 8934 return $(chk).val(); 8935 })); 8936 } 8937 var storage = {}; 8938 storage['selectedRows'] = Extension.selectedRows.filter(Extension.unique); 8939 datatable.stateKeep('checkbox', storage); 8940 } 8941 8942 // keep selectedAllRows in datasource params 8943 datatable.setDataSourceParam(options.vars.selectedAllRows, Extension.selectedAllRows); 8944 8945 $(datatable).trigger(pfx + 'datatable-on-click-checkbox', [$(this)]); 8946 }); 8947 8948 // single row checkbox click 8949 $(datatable.tableBody).find('.' + pfx + 'checkbox-single > [type="checkbox"]').click(function(e) { 8950 var id = $(this).val(); 8951 if ($(this).is(':checked')) { 8952 Extension.selectedRows.push(id); 8953 // remove from unselected rows 8954 Extension.unselectedRows = Extension.remove(Extension.unselectedRows, id); 8955 } 8956 else { 8957 Extension.unselectedRows.push(id); 8958 // remove from selected rows 8959 Extension.selectedRows = Extension.remove(Extension.selectedRows, id); 8960 } 8961 8962 // local checkbox header check 8963 if (!options.vars.requestIds && Extension.selectedRows.length < 1) { 8964 // remove select all checkbox, if there is no checked checkbox left 8965 $(datatable.tableHead).find('.' + pfx + 'checkbox-all > [type="checkbox"]').prop('checked', false); 8966 } 8967 8968 var storage = {}; 8969 storage['selectedRows'] = Extension.selectedRows.filter(Extension.unique); 8970 storage['unselectedRows'] = Extension.unselectedRows.filter(Extension.unique); 8971 datatable.stateKeep('checkbox', storage); 8972 8973 $(datatable).trigger(pfx + 'datatable-on-click-checkbox', [$(this)]); 8974 }); 8975 }, 8976 8977 unique: function(value, index, self) { 8978 return self.indexOf(value) === index; 8979 }, 8980 8981 initSelect: function() { 8982 // selected all rows from server 8983 if (Extension.selectedAllRows && options.vars.requestIds) { 8984 if (!datatable.hasClass(pfx + 'datatable-error')) { 8985 // set header select all checkbox checked 8986 $(datatable.tableHead).find('.' + pfx + 'checkbox-all > [type="checkbox"]').prop('checked', true); 8987 } 8988 8989 // set all checkbox in table body 8990 datatable.setActiveAll(true); 8991 8992 // remove unselected rows 8993 Extension.unselectedRows.forEach(function(id) { 8994 datatable.setInactive(id); 8995 }); 8996 8997 } 8998 else { 8999 // single check for server and local 9000 Extension.selectedRows.forEach(function(id) { 9001 datatable.setActive(id); 9002 }); 9003 9004 // local checkbox; check if all checkboxes of currect page are checked 9005 if (!datatable.hasClass(pfx + 'datatable-error') && $(datatable.tableBody).find('.' + pfx + 'checkbox-single > [type="checkbox"]').not(':checked').length < 1) { 9006 // set header select all checkbox checked 9007 $(datatable.tableHead).find('.' + pfx + 'checkbox-all > [type="checkbox"]').prop('checked', true); 9008 } 9009 } 9010 }, 9011 9012 /** 9013 * Check if selector is enabled from options 9014 */ 9015 selectorEnabled: function() { 9016 return $.grep(datatable.options.columns, function(n, i) { 9017 return n.selector || false; 9018 })[0]; 9019 }, 9020 9021 initVars: function() { 9022 // get single select/unselect from localstorage 9023 var storage = datatable.stateGet('checkbox'); 9024 if (typeof storage !== 'undefined') { 9025 Extension.selectedRows = storage['selectedRows'] || []; 9026 Extension.unselectedRows = storage['unselectedRows'] || []; 9027 } 9028 }, 9029 9030 getSelectedId: function(path) { 9031 Extension.initVars(); 9032 9033 // server selected all rows 9034 if (Extension.selectedAllRows && options.vars.requestIds) { 9035 if (typeof path === 'undefined') { 9036 path = options.vars.rowIds; 9037 } 9038 9039 // if selected all rows, return id from response meta 9040 var selectedAllRows = datatable.getObject(path, datatable.lastResponse) || []; 9041 9042 if (selectedAllRows.length > 0) { 9043 // remove single unselected rows from selectedAllRows ids from server response emta 9044 Extension.unselectedRows.forEach(function(id) { 9045 selectedAllRows = Extension.remove(selectedAllRows, parseInt(id)); 9046 }); 9047 } 9048 return selectedAllRows.filter(Extension.unique); 9049 } 9050 9051 // else return single checked selected rows 9052 return Extension.selectedRows.filter(Extension.unique); 9053 }, 9054 9055 remove: function(array, element) { 9056 return array.filter(function(e) { 9057 return e !== element; 9058 }); 9059 }, 9060 }; 9061 9062 // make the extension accessible from datatable init 9063 datatable.checkbox = function() { 9064 return Extension; 9065 }; 9066 9067 if (typeof options === 'object') { 9068 options = $.extend(true, {}, $.fn[pluginName].checkbox.default, options); 9069 Extension.init.apply(this, [options]); 9070 } 9071 9072 return datatable; 9073 }; 9074 9075 $.fn[pluginName].checkbox.default = { 9076 vars: { 9077 // select all rows flag to be sent to the server 9078 selectedAllRows: 'selectedAllRows', 9079 // request id parameter's name 9080 requestIds: 'requestIds', 9081 // response path to all rows id 9082 rowIds: 'meta.rowIds', 9083 }, 9084 }; 9085 9086}(jQuery)); 9087 9088var defaults = { 9089 layout: { 9090 icons: { 9091 pagination: { 9092 next: 'flaticon2-next', 9093 prev: 'flaticon2-back', 9094 first: 'flaticon2-fast-back', 9095 last: 'flaticon2-fast-next', 9096 more: 'flaticon-more-1', 9097 }, 9098 rowDetail: {expand: 'fa fa-caret-down', collapse: 'fa fa-caret-right'}, 9099 } 9100 } 9101}; 9102 9103if (KTUtil.isRTL()) { 9104 defaults = { 9105 layout: { 9106 icons: { 9107 pagination: { 9108 next: 'flaticon2-back', 9109 prev: 'flaticon2-next', 9110 first: 'flaticon2-fast-next', 9111 last: 'flaticon2-fast-back', 9112 }, 9113 rowDetail: {collapse: 'fa fa-caret-down', expand: 'fa fa-caret-right'}, 9114 } 9115 } 9116 } 9117} 9118 9119$.extend(true, $.fn.KTDatatable.defaults, defaults); 9120 9121"use strict"; 9122 9123// Initialization 9124KTUtil.ready(function() {
9125 //////////////////////////////////////////////////// 9126 // Layout Base Partials(mandatory for core layout)// 9127 //////////////////////////////////////////////////// 9128 9129 // Init Desktop & Mobile Headers 9130 if (typeof KTLayoutHeader !== 'undefined') { 9131 KTLayoutHeader.init('kt_header', 'kt_header_mobile'); 9132 } 9133 9134 // Init Header Menu 9135 if (typeof KTLayoutHeaderMenu !== 'undefined') { 9136 KTLayoutHeaderMenu.init('kt_header_menu', 'kt_header_menu_wrapper'); 9137 } 9138 9139 // Init Header Topbar For Mobile Mode 9140 if (typeof KTLayoutHeaderTopbar !== 'undefined') { 9141 KTLayoutHeaderTopbar.init('kt_header_mobile_topbar_toggle'); 9142 } 9143 9144 // Init Brand Panel For Logo 9145 if (typeof KTLayoutBrand !== 'undefined') { 9146 KTLayoutBrand.init('kt_brand'); 9147 } 9148 9149 // Init Aside 9150 if (typeof KTLayoutAside !== 'undefined') { 9151 KTLayoutAside.init('kt_aside'); 9152 } 9153 9154 // Init Aside Menu Toggle 9155 if (typeof KTLayoutAsideToggle !== 'undefined') { 9156 KTLayoutAsideToggle.init('kt_aside_toggle'); 9157 } 9158 9159 // Init Aside Menu 9160 if (typeof KTLayoutAsideMenu !== 'undefined') { 9161 KTLayoutAsideMenu.init('kt_aside_menu'); 9162 } 9163 9164 // Init Subheader 9165 if (typeof KTLayoutSubheader !== 'undefined') { 9166 KTLayoutSubheader.init('kt_subheader'); 9167 } 9168 9169 // Init Content 9170 if (typeof KTLayoutContent !== 'undefined') { 9171 KTLayoutContent.init('kt_content'); 9172 } 9173 9174 // Init Footer 9175 if (typeof KTLayoutFooter !== 'undefined') { 9176 KTLayoutFooter.init('kt_footer'); 9177 } 9178 9179 9180 ////////////////////////////////////////////// 9181 // Layout Extended Partials(optional to use)// 9182 ////////////////////////////////////////////// 9183 9184 // Init Scrolltop 9185 if (typeof KTLayoutScrolltop !== 'undefined') { 9186 KTLayoutScrolltop.init('kt_scrolltop'); 9187 } 9188 9189 // Init Sticky Card 9190 if (typeof KTLayoutStickyCard !== 'undefined') { 9191 KTLayoutStickyCard.init('kt_page_sticky_card'); 9192 } 9193 9194 // Init Stretched Card 9195 if (typeof KTLayoutStretchedCard !== 'undefined') { 9196 KTLayoutStretchedCard.init('kt_page_stretched_card'); 9197 } 9198 9199 // Init Code Highlighter & Preview Blocks(used to demonstrate the theme features) 9200 if (typeof KTLayoutExamples !== 'undefined') { 9201 KTLayoutExamples.init(); 9202 } 9203 9204 // Init Demo Selection Panel 9205 if (typeof KTLayoutDemoPanel !== 'undefined') { 9206 KTLayoutDemoPanel.init('kt_demo_panel'); 9207 } 9208 9209 // Init Chat App(quick modal chat) 9210 if (typeof KTLayoutChat !== 'undefined') { 9211 KTLayoutChat.init('kt_chat_modal'); 9212 } 9213 9214 // Init Quick Actions Offcanvas Panel 9215 if (typeof KTLayoutQuickActions !== 'undefined') { 9216 KTLayoutQuickActions.init('kt_quick_actions'); 9217 } 9218 9219 // Init Quick Notifications Offcanvas Panel 9220 if (typeof KTLayoutQuickNotifications !== 'undefined') { 9221 KTLayoutQuickNotifications.init('kt_quick_notifications'); 9222 } 9223 9224 // Init Quick Offcanvas Panel 9225 if (typeof KTLayoutQuickPanel!== 'undefined') { 9226 KTLayoutQuickPanel.init('kt_quick_panel'); 9227 } 9228 9229 // Init Quick User Panel 9230 if (typeof KTLayoutQuickUser !== 'undefined') { 9231 KTLayoutQuickUser.init('kt_quick_user'); 9232 } 9233 9234 // Init Quick Search Panel 9235 if (typeof KTLayoutQuickSearch !== 'undefined') { 9236 KTLayoutQuickSearch.init('kt_quick_search'); 9237 } 9238 9239 // Init Quick Cart Panel 9240 if (typeof KTLayoutQuickCartPanel !== 'undefined') { 9241 KTLayoutQuickCartPanel.init('kt_quick_cart'); 9242 } 9243 9244 // Init Search For Quick Search Dropdown 9245 if (typeof KTLayoutSearch !== 'undefined') { 9246 KTLayoutSearch().init('kt_quick_search_dropdown'); 9247 } 9248 9249 // Init Search For Quick Search Offcanvas Panel 9250 if (typeof KTLayoutSearchOffcanvas !== 'undefined') { 9251 KTLayoutSearchOffcanvas().init('kt_quick_search_offcanvas'); 9252 } 9253}); 9254 9255"use strict"; 9256 9257var KTLayoutAsideMenu = function() { 9258 // Private properties 9259 var _body; 9260 var _element; 9261 var _menuObject; 9262 9263 // Initialize 9264 var _init = function() { 9265 var menuDesktopMode = (KTUtil.attr(_element, 'data-menu-dropdown') === '1' ? 'dropdown' : 'accordion'); 9266 var scroll; 9267 9268 if (KTUtil.attr(_element, 'data-menu-scroll') === '1') { 9269 scroll = { 9270 rememberPosition: true, // remember position on page reload 9271 height: function() { // calculate available scrollable area height 9272 var height = parseInt(KTUtil.getViewPort().height); 9273 9274 if (KTUtil.isBreakpointUp('lg')) { 9275 height = height - KTLayoutBrand.getHeight(); 9276 } 9277 9278 height = height - (parseInt(KTUtil.css(_element, 'marginBottom')) + parseInt(KTUtil.css(_element, 'marginTop'))); 9279 9280 return height; 9281 } 9282 }; 9283 } 9284 9285 _menuObject = new KTMenu(_element, { 9286 // Vertical scroll 9287 scroll: scroll, 9288 9289 // Submenu setup 9290 submenu: { 9291 desktop: menuDesktopMode, 9292 tablet: 'accordion', // menu set to accordion in tablet mode 9293 mobile: 'accordion' // menu set to accordion in mobile mode 9294 }, 9295 9296 // Accordion setup 9297 accordion: { 9298 expandAll: false // allow having multiple expanded accordions in the menu 9299 } 9300 }); 9301 } 9302 9303 var _initHover = function() { 9304 // Handle Minimized Aside Hover 9305 if (KTUtil.hasClass(_body, 'aside-fixed') && KTUtil.hasClass(_body, 'aside-minimize-hoverable')) { 9306 var insideTm; 9307 var outsideTm; 9308 9309 // Handle Aside Hover Mode 9310 KTUtil.addEvent(_element, 'mouseenter', function(e) { 9311 e.preventDefault(); 9312 9313 if (KTUtil.isBreakpointUp('lg') === false) { 9314 return; 9315 } 9316 9317 if (outsideTm) { 9318 clearTimeout(outsideTm); 9319 outsideTm = null; 9320 } 9321 9322 if (insideTm) { 9323 clearTimeout(insideTm); 9324 insideTm = null; 9325 } 9326 9327 insideTm = setTimeout(function() { 9328 if (KTUtil.hasClass(_body, 'aside-minimize') && KTUtil.isBreakpointUp('lg')) { 9329 // Hover class 9330 KTUtil.addClass(_body, 'aside-minimize-hover'); 9331
9332 KTLayoutAsideMenu.getMenu().scrollUpdate(); 9333 KTLayoutAsideMenu.getMenu().scrollTop(); 9334 } 9335 }, 50); 9336 }); 9337 9338 KTUtil.addEvent(KTLayoutAside.getElement(), 'mouseleave', function(e) { 9339 e.preventDefault(); 9340 9341 if (KTUtil.isBreakpointUp('lg') === false) { 9342 return; 9343 } 9344 9345 if (insideTm) { 9346 clearTimeout(insideTm); 9347 insideTm = null; 9348 } 9349 9350 if (outsideTm) { 9351 clearTimeout(outsideTm); 9352 outsideTm = null; 9353 } 9354 9355 outsideTm = setTimeout(function() { 9356 if (KTUtil.hasClass(_body, 'aside-minimize-hover') && KTUtil.isBreakpointUp('lg')) { 9357 KTUtil.removeClass(_body, 'aside-minimize-hover'); 9358 9359 // Hover class 9360 KTLayoutAsideMenu.getMenu().scrollUpdate(); 9361 KTLayoutAsideMenu.getMenu().scrollTop(); 9362 } 9363 }, 100); 9364 }); 9365 } 9366 } 9367 9368 // Public methods 9369 return { 9370 init: function(id) { 9371 _body = KTUtil.getBody(); 9372 _element = KTUtil.getById(id); 9373 9374 if (!_element) { 9375 return; 9376 } 9377 9378 // Initialize menu 9379 _init(); 9380 _initHover(); 9381 }, 9382 9383 getElement: function() { 9384 return _element; 9385 }, 9386 9387 getMenu: function() { 9388 return _menuObject; 9389 }, 9390 9391 pauseDropdownHover: function(time) { 9392 if (_menuObject) { 9393 _menuObject.pauseDropdownHover(time); 9394 } 9395 }, 9396 9397 closeMobileOffcanvas: function() { 9398 if (_menuObject && KTUtil.isMobileDevice()) { 9399 _menuObject.hide(); 9400 } 9401 } 9402 }; 9403}(); 9404 9405// Webpack support 9406if (typeof module !== 'undefined') { 9407 module.exports = KTLayoutAsideMenu; 9408} 9409 9410"use strict"; 9411 9412var KTLayoutAsideToggle = function() { 9413 // Private properties 9414 var _body; 9415 var _element; 9416 var _toggleObject; 9417 9418 // Initialize 9419 var _init = function() { 9420 _toggleObject = new KTToggle(_element, _body, { 9421 targetState: 'aside-minimize', 9422 toggleState: 'active' 9423 }); 9424 9425 _toggleObject.on('toggle', function(toggle) { 9426 // Update sticky card 9427 if (typeof KTLayoutStickyCard !== 'undefined') { 9428 KTLayoutStickyCard.update(); 9429 } 9430 9431 // Pause header menu dropdowns 9432 if (typeof KTLayoutHeaderMenu !== 'undefined') { 9433 KTLayoutHeaderMenu.pauseDropdownHover(800); 9434 } 9435 9436 // Pause aside menu dropdowns 9437 if (typeof KTLayoutAsideMenu !== 'undefined') { 9438 KTLayoutAsideMenu.pauseDropdownHover(800); 9439 } 9440 9441 // Remember state in cookie 9442 KTCookie.setCookie('kt_aside_toggle_state', toggle.getState()); 9443 // to set default minimized left aside use this cookie value in y
9443our 9444 // server side code and add "kt-primary--minimize aside-minimize" classes to 9445 // the body tag in order to initialize the minimized left aside mode during page loading. 9446 }); 9447 9448 _toggleObject.on('beforeToggle', function(toggle) { 9449 if (KTUtil.hasClass(_body, 'aside-minimize') === false && KTUtil.hasClass(_body, 'aside-minimize-hover')) { 9450 KTUtil.removeClass(_body, 'aside-minimize-hover'); 9451 } 9452 }); 9453 } 9454 9455 // Public methods 9456 return { 9457 init: function(id) { 9458 _element = KTUtil.getById(id); 9459 _body = KTUtil.getBody(); 9460 9461 if (!_element) { 9462 return; 9463 } 9464 9465 // Initialize 9466 _init(); 9467 }, 9468 9469 getElement: function() { 9470 return _element; 9471 }, 9472 9473 getToggle: function() { 9474 return _toggleObject; 9475 }, 9476 9477 onToggle: function(handler) { 9478 if (typeof _toggleObject.element !== 'undefined') { 9479 _toggleObject.on('toggle', handler); 9480 } 9481 } 9482 }; 9483}(); 9484 9485// Webpack support 9486if (typeof module !== 'undefined') { 9487 module.exports = KTLayoutAsideToggle; 9488} 9489 9490"use strict"; 9491 9492var KTLayoutAside = function() { 9493 // Private properties 9494 var _body; 9495 var _element; 9496 var _offcanvasObject; 9497 9498 // Private functions 9499 // Initialize 9500 var _init = function() { 9501 var offcanvasClass = KTUtil.hasClass(_element, 'aside-offcanvas-default') ? 'aside-offcanvas-default' : 'aside'; 9502 9503 // Initialize mobile aside offcanvas 9504 _offcanvasObject = new KTOffcanvas(_element, { 9505 baseClass: offcanvasClass, 9506 overlay: true, 9507 closeBy: 'kt_aside_close_btn', 9508 toggleBy: { 9509 target: 'kt_aside_mobile_toggle', 9510 state: 'mobile-toggle-active' 9511 } 9512 }); 9513 } 9514 9515 // Public methods 9516 return { 9517 init: function(id) { 9518 _element = KTUtil.getById(id); 9519 _body = KTUtil.getBody(); 9520 9521 if (!_element) { 9522 return; 9523 } 9524 9525 // Initialize 9526 _init(); 9527 }, 9528 9529 getElement: function() { 9530 return _element; 9531 }, 9532 9533 getOffcanvas: function() { 9534 return _offcanvasObject; 9535 }, 9536 9537 isFixed: function() { 9538 return KTUtil.hasClass(_body, 'aside-fixed'); 9539 }, 9540 9541 isMinimized: function() { 9542 return (KTUtil.hasClass(_body, 'aside-fixed') && KTUtil.hasClass(_body, 'aside-minimize')); 9543 }, 9544 9545 isHoverable: function() { 9546 return (KTUtil.hasClass(_body, 'aside-fixed') && KTUtil.hasClass(_body, 'aside-minimize-hoverable')); 9547 } 9548 }; 9549}(); 9550 9551// Webpack support 9552if (typeof module !== 'undefined') { 9553 module.exports = KTLayoutAside; 9554} 9555 9556"use strict"; 9557 9558var KTLayoutBrand = function() { 9559 // Private properties 9560 var _element; 9561 9562 // Private functions 9563 var _getHeight = function() { 9564 var height = 0; 9565 9566 if (_element) { 9567 height = KTUtil.actualHeight(_element); 9568 } 9569 9570 return height; 9571 } 9572 9573 // Public methods 9574 return { 9575 init: function(id) { 9576 _element = KTUtil.getById(id); 9577 9578 if (!_element) { 9579 return; 9580 } 9581 }, 9582 9583 getElement: function() { 9584 return _element; 9585 }, 9586 9587 getHeight: function() { 9588 return _getHeight(); 9589 } 9590 }; 9591}(); 9592 9593// Webpack support 9594if (typeof module !== 'undefined') { 9595 module.exports = KTLayoutBrand; 9596} 9597 9598"use strict"; 9599 9600var KTLayoutContent = function() { 9601 // Private properties 9602 var _element; 9603 9604 // Private functions 9605 var _getHeight = function() { 9606 var height; 9607 9608 height = KTUtil.getViewPort().height; 9609 9610 if (_element) { 9611 height = height - parseInt(KTUtil.css(_element, 'paddingTop')) - parseInt(KTUtil.css(_element, 'paddingBottom')); 9612 } 9613 9614 height = height - KTLayoutHeader.getHeight(); 9615 height = height - KTLayoutSubheader.getHeight(); 9616 height = height - KTLayoutFooter.getHeight(); 9617 9618 return height; 9619 } 9620 9621 // Public methods 9622 return { 9623 init: function(id) { 9624 _element = KTUtil.getById(id); 9625 }, 9626 9627 getHeight: function() { 9628 return _getHeight(); 9629 }, 9630 9631 getElement: function() { 9632 return _element; 9633 } 9634 }; 9635}(); 9636 9637// Webpack support 9638if (typeof module !== 'undefined') { 9639 module.exports = KTLayoutContent; 9640} 9641 9642"use strict"; 9643 9644var KTLayoutFooter = function() { 9645 // Private properties 9646 var _element; 9647 9648 // Private functions 9649 var _getHeight = function() { 9650 var height = 0; 9651 9652 if (_element) { 9653 height = KTUtil.actualHeight(_element); 9654 } 9655 9656 return height; 9657 } 9658 9659 // Public methods 9660 return { 9661 init: function(id) { 9662 _element = KTUtil.getById(id); 9663 }, 9664 9665 getHeight: function() { 9666 return _getHeight(); 9667 }, 9668 9669 getElement: function() { 9670 return _element; 9671 } 9672 }; 9673}(); 9674 9675// Webpack support 9676if (typeof module !== 'undefined') { 9677 module.exports = KTLayoutFooter; 9678} 9679 9680"use strict"; 9681 9682var KTLayoutHeaderMenu = function() { 9683 // Private properties 9684 var _menuElement; 9685 var _menuObject; 9686 var _offcanvasElement; 9687 var _offcanvasObject; 9688 9689 // Private functions 9690 var _init = function() { 9691 _offcanvasObject = new KTOffcanvas(_offcanvasElement, { 9692 overlay: true, 9693 baseClass: 'header-menu-wrapper', 9694 closeBy: 'kt_header_menu_mobile_close_btn', 9695 toggleBy: { 9696 target: 'kt_header_mobile_toggle', 9697 state: 'mobile-toggle-active' 9698 } 9699 }); 9700 9701 _menuObject = new KTMenu(_menuElement, { 9702 submenu: { 9703 desktop: 'dropdown', 9704 tablet: 'accordion', 9705 mobile: 'accordion' 9706 }, 9707 accordion: { 9708 slideSpeed: 200, // accordion toggle slide speed in milliseconds 9709 expandAll: false // allow having multiple expanded accordions in the menu 9710 } 9711 }); 9712 9713 // Close aside offcanvas panel before page reload On tablet and mobile 9714 _menuObject.on('linkClick', function(menu) { 9715 if (KTUtil.isBreakpointDown('lg')) { // Tablet and mobile mode 9716 _offcanvasObject.hide(); // Hide offcanvas after general link click 9717 } 9718 }); 9719 } 9720 9721 // Public methods 9722 return { 9723 init: function(menuId, offcanvasId) { 9724 _menuElement = KTUtil.getById(menuId); 9725 _offcanvasElement = KTUtil.getById(offcanvasId); 9726 9727 if (!_menuElement) { 9728 return; 9729 } 9730 9731 // Initialize menu 9732 _init(); 9733 }, 9734 9735 getMenuElement: function() { 9736 return _menuElement; 9737 }, 9738 9739 getOffcanvasElement: function() { 9740 return _offcanvasElement; 9741 }, 9742 9743 getMenu: function() { 9744 return _menuObject; 9745 }, 9746 9747 pauseDropdownHover: function(time) { 9748 if (_menuObject) { 9749 _menuObject.pauseDropdownHover(time); 9750 } 9751 }, 9752 9753 getOffcanvas: function() { 9754 return _offcanvasObject; 9755 }, 9756 9757 closeMobileOffcanvas: function() {
9758 if (_menuObject && KTUtil.isMobileDevice()) { 9759 _offcanvasObject.hide(); 9760 } 9761 } 9762 }; 9763}(); 9764 9765// Webpack support 9766if (typeof module !== 'undefined') { 9767 module.exports = KTLayoutHeaderMenu; 9768} 9769 9770"use strict"; 9771 9772var KTLayoutHeaderTopbar = function() { 9773 // Private properties 9774 var _toggleElement; 9775 var _toggleObject; 9776 9777 // Private functions 9778 var _init = function() { 9779 _toggleObject = new KTToggle(_toggleElement, KTUtil.getBody(), { 9780 targetState: 'topbar-mobile-on', 9781 toggleState: 'active', 9782 }); 9783 } 9784 9785 // Public methods 9786 return { 9787 init: function(id) { 9788 _toggleElement = KTUtil.getById(id); 9789 9790 if (!_toggleElement) { 9791 return; 9792 } 9793 9794 // Initialize 9795 _init(); 9796 }, 9797 9798 getToggleElement: function() { 9799 return _toggleElement; 9800 } 9801 }; 9802}(); 9803 9804// Webpack support 9805if (typeof module !== 'undefined') { 9806 module.exports = KTLayoutHeaderTopbar; 9807} 9808 9809"use strict"; 9810 9811var KTLayoutHeader = function() { 9812 // Private properties 9813 var _element; 9814 var _elementForMobile; 9815 var _object; 9816 9817 // Private functions 9818 // Get Height 9819 var _getHeight = function() { 9820 var height = 0; 9821 9822 if (_element) { 9823 height = KTUtil.actualHeight(_element) + 1; 9824 } 9825 9826 return height; 9827 } 9828 9829 // Get Height 9830 var _getHeightForMobile = function() { 9831 var height; 9832 9833 height = KTUtil.actualHeight(_elementForMobile); 9834 9835 return height; 9836 } 9837 9838 // Public Methods 9839 return { 9840 init: function(id, idForMobile) { 9841 _element = KTUtil.getById(id); 9842 _elementForMobile = KTUtil.getById(idForMobile); 9843 9844 if (!_element) { 9845 return; 9846 } 9847 }, 9848 9849 isFixed: function() { 9850 return KTUtil.hasClass(KTUtil.getBody(), 'header-fixed') 9851 }, 9852 9853 isFixedForMobile: function() { 9854 return KTUtil.hasClass(KTUtil.getBody(), 'header-mobile-fixed') 9855 }, 9856 9857 getElement: function() { 9858 return _element; 9859 }, 9860 9861 getElementForMobile: function() { 9862 return _elementForMobile; 9863 }, 9864 9865 getHeader: function() { 9866 return _object; 9867 }, 9868 9869 getHeight: function() { 9870 return _getHeight(); 9871 }, 9872 9873 getHeightForMobile: function() { 9874 return _getHeightForMobile(); 9875 } 9876 }; 9877}(); 9878 9879// Webpack support 9880if (typeof module !== 'undefined') { 9881 module.exports = KTLayoutHeader; 9882} 9883 9884"use strict"; 9885 9886var KTLayoutStickyCard = function() { 9887 // Private properties 9888 var _element; 9889 var _object; 9890 9891 // Private functions 9892 var _init = function() { 9893 var offset = 300; 9894 9895 if (typeof KTLayoutHeader !== 'undefined') { 9896 offset = KTLayoutHeader.getHeight(); 9897 } 9898 9899 _object = new KTCard(_element, { 9900 sticky: { 9901 offset: offset, 9902 zIndex: 90, 9903 position: { 9904 top: function() { 9905 var pos = 0; 9906 var body = KTUtil.getBody(); 9907 9908 if (KTUtil.isBreakpointUp('lg')) { 9909 if (typeof KTLayoutHeader !== 'undefined' && KTLayoutHeader.isFixed()) { 9910 pos = pos + KTLayoutHeader.getHeight(); 9911 } 9912 9913 if (typeof KTLayoutSubheader !== 'undefined' && KTLayoutSubheader.isFixed()) { 9914 pos = pos + KTLayoutSubheader.getHeight(); 9915 } 9916 } else { 9917 if (typeof KTLayoutHeader !== 'undefined' && KTLayoutHeader.isFixedForMobile()) { 9918 pos = pos + KTLayoutHeader.getHeightForMobile(); 9919 } 9920 } 9921 9922 pos = pos - 1; // remove header border width 9923 9924 return pos; 9925 }, 9926 left: function(card) { 9927 return KTUtil.offset(_element).left; 9928 }, 9929 right: function(card) { 9930 var body = KTUtil.getBody(); 9931 9932 var cardWidth = parseInt(KTUtil.css(_element, 'width')); 9933 var bodyWidth = parseInt(KTUtil.css(body, 'width')); 9934 var cardOffsetLeft = KTUtil.offset(_element).left; 9935 9936 return bodyWidth - cardWidth - cardOffsetLeft; 9937 } 9938 } 9939 } 9940 }); 9941 9942 _object.initSticky(); 9943 9944 KTUtil.addResizeHandler(function() { 9945 _object.updateSticky(); 9946 }); 9947 } 9948 9949 // Public methods 9950 return { 9951 init: function(id) { 9952 _element = KTUtil.getById(id); 9953 9954 if (!_element) { 9955 return; 9956 } 9957 9958 // Initialize 9959 _init(); 9960 }, 9961 9962 update: function() { 9963 if (_object) { 9964 _object.updateSticky(); 9965 } 9966 } 9967 }; 9968}(); 9969 9970// Webpack support 9971if (typeof module !== 'undefined') { 9972 module.exports = KTLayoutStickyCard; 9973} 9974 9975"use strict"; 9976 9977var KTLayoutStretchedCard = function() { 9978 // Private properties 9979 var _element; 9980 9981 // Private functions 9982 var _init = function() { 9983 var scroll = KTUtil.find(_element, '.card-scroll'); 9984 var cardBody = KTUtil.find(_element, '.card-body'); 9985 var cardHeader = KTUtil.find(_element, '.card-header'); 9986 9987 var height = KTLayoutContent.getHeight(); 9988 9989 height = height - parseInt(KTUtil.actualHeight(cardHeader)); 9990 9991 height = height - parseInt(KTUtil.css(_element, 'marginTop')) - parseInt(KTUtil.css(_element, 'marginBottom')); 9992 height = height - parseInt(KTUtil.css(_element, 'paddingTop')) - parseInt(KTUtil.css(_element, 'paddingBottom')); 9993 9994 height = height - parseInt(KTUtil.css(cardBody, 'paddingTop')) - parseInt(KTUtil.css(cardBody, 'paddingBottom')); 9995 height = height - parseInt(KTUtil.css(cardBody, 'marginTop')) - parseInt(KTUtil.css(cardBody, 'marginBottom')); 9996 9997 height = height - 3; 9998 9999 KTUtil.css(scroll, 'height', height + 'px'); 10000 } 10001 10002 // Public methods 10003 return { 10004 init: function(id) { 10005 _element = KTUtil.getById(id); 10006 10007 if (!_element) { 10008 return; 10009 } 10010 10011 // Initialize 10012 _init(); 10013 10014 // Re-calculate on window resize 10015 KTUtil.addResizeHandler(function() { 10016 _init(); 10017 }); 10018 }, 10019 10020 update: function() { 10021 _init(); 10022 } 10023 }; 10024}(); 10025 10026// Webpack support 10027if (typeof module !== 'undefined') { 10028 module.exports = KTLayoutStretchedCard; 10029} 10030 10031"use strict"; 10032 10033var KTLayoutSubheader = function() { 10034 // Private properties 10035 var _element; 10036 10037 // Private functions 10038 var _getHeight = function() { 10039 var height = 0; 10040 10041 if (_element) { 10042 height = KTUtil.actualHeight(_element); 10043 } 10044 10045 return height; 10046 } 10047 10048 // Public methods 10049 return { 10050 init: function(id) { 10051 _element = KTUtil.getById(id); 10052 10053 if (!_element) { 10054 return; 10055 } 10056 }, 10057 10058 isFixed: function() { 10059 return KTUtil.hasClass(KTUtil.getBody(), 'subheader-fixed'); 10060 }, 10061 10062 getElement: function() { 10063 return _element; 10064 }, 10065 10066 getHeight: function() { 10067 return _getHeight(); 10068 } 10069 }; 10070}(); 10071 10072// Webpack support 10073if (typeof module !== 'undefined') { 10074 module.exports = KTLayoutSubheader; 10075} 10076 10077"use strict"; 10078 10079// Class definition 10080var KTLayoutChat = function () { 10081 // Private functions 10082 var _init = function (element) { 10083 var scrollEl = KTUtil.find(element, '.scroll'); 10084 var cardBodyEl = KTUtil.find(element, '.card-body'); 10085 var cardHeaderEl = KTUtil.find(element, '.card-header'); 10086 var cardFooterEl = KTUtil.find(element, '.card-footer'); 10087 10088 if (!scrollEl) { 10089 return; 10090 } 10091 10092 // initialize perfect scrollbar(see: https://github.com/utatti/perfect-scrollbar) 10093 KTUtil.scrollInit(scrollEl, { 10094 windowScroll: false, // allow browser scroll when the scroll reaches the end of the side 10095 mobileNativeScroll: true, // enable native scroll for mobile 10096 desktopNativeScroll: false, // disable native scroll and use custom scroll for desktop 10097 resetHeightOnDestroy: true, // reset css height on scroll feature destroyed 10098 handleWindowResize: true, // recalculate hight on window resize 10099 rememberPosition: true, // remember scroll position in cookie 10100 height: function() { // calculate height 10101 var height; 10102 10103 if (KTUtil.isBreakpointDown('lg')) { // Mobile mode 10104 return KTUtil.hasAttr(scrollEl, 'data-mobile-height') ? parseInt(KTUtil.attr(scrollEl, 'data-mobile-height')) : 400; 10105 } else if (KTUtil.isBreakpointUp('lg') && KTUtil.hasAttr(scrollEl, 'data-height')) { // Desktop Mode 10106 return parseInt(KTUtil.attr(scrollEl, 'data-height')); 10107 } else { 10108 height = KTLayoutContent.getHeight(); 10109 10110 if (scrollEl) { 10111 height = height - parseInt(KTUtil.css(scrollEl, 'margin-top')) - parseInt(KTUtil.css(scrollEl, 'margin-bottom')); 10112 } 10113 10114 if (cardHeaderEl) { 10115 height = height - parseInt(KTUtil.css(cardHeaderEl, 'height')); 10116 height = height - parseInt(KTUtil.css(cardHeaderEl, 'margin-top')) - parseInt(KTUtil.css(cardHeaderEl, 'margin-bottom')); 10117 } 10118 10119 if (cardBodyEl) { 10120 height = height - parseInt(KTUtil.css(cardBodyEl, 'padding-top')) - parseInt(KTUtil.css(cardBodyEl, 'padding-bottom')); 10121 } 10122 10123 if (cardFooterEl) { 10124 height = height - parseInt(KTUtil.css(cardFooterEl, 'height')); 10125 height = height - parseInt(KTUtil.css(cardFooterEl, 'margin-top')) - parseInt(KTUtil.css(cardFooterEl, 'margin-bottom')); 10126 } 10127 } 10128 10129 // Remove additional space 10130 height = height - 2; 10131 10132 return height; 10133 } 10134 }); 10135 10136 // attach events 10137 KTUtil.on(element, '.card-footer textarea', 'keydown', function(e) { 10138 if (e.keyCode == 13) { 10139 _handeMessaging(element); 10140 e.preventDefault(); 10141 10142 return false;
10143 } 10144 }); 10145 10146 KTUtil.on(element, '.card-footer .chat-send', 'click', function(e) { 10147 _handeMessaging(element); 10148 }); 10149 } 10150 10151 var _handeMessaging = function(element) { 10152 var messagesEl = KTUtil.find(element, '.messages'); 10153 var scrollEl = KTUtil.find(element, '.scroll'); 10154 var textarea = KTUtil.find(element, 'textarea'); 10155 10156 if (textarea.value.length === 0 ) { 10157 return; 10158 } 10159 10160 var node = document.createElement("DIV"); 10161 KTUtil.addClass(node, 'd-flex flex-column mb-5 align-items-end'); 10162 10163 var html = ''; 10164 html += '<div class="d-flex align-items-center">'; 10165 html += ' <div>'; 10166 html += ' <span class="text-muted font-size-sm">2 Hours</span>'; 10167 html += ' <a href="#" class="text-dark-75 text-hover-primary font-weight-bold font-size-h6">You</a>'; 10168 html += ' </div>'; 10169 html += ' <div class="symbol symbol-circle symbol-40 ml-3">'; 10170 html += ' <img alt="Pic" src="assets/media/users/300_12.jpg"/>'; 10171 html += ' </div>'; 10172 html += '</div>'; 10173 html += '<div class="mt-2 rounded p-5 bg-light-primary text-dark-50 font-weight-bold font-size-lg text-right max-w-400px">' + textarea.value + '</div>'; 10174 10175 KTUtil.setHTML(node, html); 10176 messagesEl.appendChild(node); 10177 textarea.value = ''; 10178 scrollEl.scrollTop = parseInt(KTUtil.css(messagesEl, 'height')); 10179 10180 var ps; 10181 if (ps = KTUtil.data(scrollEl).get('ps')) { 10182 ps.update(); 10183 } 10184 10185 setTimeout(function() { 10186 var node = document.createElement("DIV"); 10187 KTUtil.addClass(node, 'd-flex flex-column mb-5 align-items-start'); 10188 10189 var html = ''; 10190 html += '<div class="d-flex align-items-center">'; 10191 html += ' <div class="symbol symbol-circle symbol-40 mr-3">'; 10192 html += ' <img alt="Pic" src="assets/media/users/300_12.jpg"/>'; 10193 html += ' </div>'; 10194 html += ' <div>'; 10195 html += ' <a href="#" class="text-dark-75 text-hover-primary font-weight-bold font-size-h6">Matt Pears</a>'; 10196 html += ' <span class="text-muted font-size-sm">Just now</span>'; 10197 html += ' </div>'; 10198 html += '</div>'; 10199 html += '<div class="mt-2 rounded p-5 bg-light-success text-dark-50 font-weight-bold font-size-lg text-left max-w-400px">'; 10200 html += 'Right before vacation season we have the next Big Deal for you.'; 10201 html += '</div>'; 10202 10203 KTUtil.setHTML(node, html); 10204 messagesEl.appendChild(node); 10205 textarea.value = ''; 10206 scrollEl.scrollTop = parseInt(KTUtil.css(messagesEl, 'height')); 10207 10208 var ps; 10209 if (ps = KTUtil.data(scrollEl).get('ps')) { 10210 ps.update(); 10211 } 10212 }, 2000); 10213 } 10214 10215 // Public methods 10216 return { 10217 init: function(id) { 10218 // Init modal chat example 10219 _init(KTUtil.getById(id)); 10220 10221 // Trigger click to show popup modal chat on page load 10222 if (encodeURI(window.location.hostname) == 'keenthemes.com' || encodeURI(window.location.hostname) == 'www.keenthemes.com') { 10223 setTimeout(function() { 10224 if (!KTCookie.getCookie('kt_app_chat_shown')) { 10225 var expires = new Date(new Date().getTime() + 60 * 60 * 1000); // expire in 60 minutes from now 10226 10227 KTCookie.setCookie('kt_app_chat_shown', 1, { expires: expires }); 10228 10229 if (KTUtil.getById('kt_app_chat_launch_btn')) { 10230 KTUtil.getById('kt_app_chat_launch_btn').click(); 10231 } 10232 } 10233 }, 2000); 10234 } 10235 }, 10236 10237 setup: function(element) { 10238 _init(element); 10239 } 10240 }; 10241}(); 10242 10243// Webpack support 10244if (typeof module !== 'undefined') { 10245 module.exports = KTLayoutChat; 10246} 10247 10248"use strict"; 10249 10250var KTLayoutDemoPanel = function() { 10251 // Private properties 10252 var _element; 10253 var _offcanvasObject; 10254 10255 // Private functions 10256 var _init = function() { 10257 _offcanvasObject = new KTOffcanvas(_element, { 10258 overlay: true, 10259 baseClass: 'offcanvas', 10260 placement: 'right', 10261 closeBy: 'kt_demo_panel_close', 10262 toggleBy: 'kt_demo_panel_toggle' 10263 }); 10264 10265 var header = KTUtil.find(_element, '.offcanvas-header'); 10266 var content = KTUtil.find(_element, '.offcanvas-content'); 10267 var wrapper = KTUtil.find(_element, '.offcanvas-wrapper'); 10268 var footer = KTUtil.find(_element, '.offcanvas-footer'); 10269 10270 KTUtil.scrollInit(wrapper, { 10271 disableForMobile: true, 10272 resetHeightOnDestroy: true, 10273 handleWindowResize: true, 10274 height: function() { 10275 var height = parseInt(KTUtil.getViewPort().height); 10276 10277 if (header) { 10278 height = height - parseInt(KTUtil.actualHeight(header)); 10279 height = height - parseInt(KTUtil.css(header, 'marginTop')); 10280 height = height - parseInt(KTUtil.css(header, 'marginBottom')); 10281 } 10282 10283 if (content) { 10284 height = height - parseInt(KTUtil.css(content, 'marginTop')); 10285 height = height - parseInt(KTUtil.css(content, 'marginBottom')); 10286 } 10287 10288 if (wrapper) { 10289 height = height - parseInt(KTUtil.css(wrapper, 'marginTop')); 10290 height = height - parseInt(KTUtil.css(wrapper, 'marginBottom')); 10291 } 10292 10293 if (footer) { 10294 height = height - parseInt(KTUtil.actualHeight(footer)); 10295 height = height - parseInt(KTUtil.css(footer, 'marginTop')); 10296 height = height - parseInt(KTUtil.css(footer, 'marginBottom')); 10297 } 10298 10299 height = height - parseInt(KTUtil.css(_element, 'paddingTop')); 10300 height = height - parseInt(KTUtil.css(_element, 'paddingBottom')); 10301 10302 height = height - 2; 10303 10304 return height; 10305 } 10306 }); 10307 10308 if (typeof offcanvas !== 'undefined' && offcanvas.length === 0) { 10309 offcanvas.on('hide', function() { 10310 var expires = new Date(new Date().getTime() + 60 * 60 * 1000); // expire in 60 minutes from now 10311 KTCookie.setCookie('kt_demo_panel_shown', 1, {expires: expires}); 10312 }); 10313 } 10314 } 10315 10316 var _remind = function() { 10317 if (!(encodeURI(window.location.hostname) == 'keenthemes.com' || encodeURI(window.location.hostname) == 'www.keenthemes.com')) { 10318 return; 10319 } 10320 10321 setTimeout(function() { 10322 if (!KTCookie.getCookie('kt_demo_panel_shown')) { 10323 var expires = new Date(new Date().getTime() + 15 * 60 * 1000); // expire in 15 minutes from now 10324 KTCookie.setCookie('kt_demo_panel_shown', 1, { expires: expires }); 10325 if (typeof _offcanvasObject !== 'undefined') {
10326 _offcanvasObject.show(); 10327 } 10328 } 10329 }, 4000); 10330 } 10331 10332 // Public methods 10333 return { 10334 init: function(id) { 10335 _element = KTUtil.getById(id); 10336 10337 if (!_element) { 10338 return; 10339 } 10340 10341 // Initialize 10342 _init(); 10343 10344 // Remind 10345 _remind(); 10346 } 10347 }; 10348}(); 10349 10350// Webpack support 10351if (typeof module !== 'undefined') { 10352 module.exports = KTLayoutDemoPanel; 10353} 10354 10355"use strict"; 10356 10357var KTLayoutExamples = function() { 10358 10359 var initDefaultMode = function(element) { 10360 var elements = element; 10361 if (typeof elements === 'undefined') { 10362 elements = document.querySelectorAll('.example:not(.example-compact):not(.example-hover):not(.example-basic)'); 10363 } 10364 10365 if (elements && elements.length > 0 ) { 10366 for (var i = 0; i < elements.length; ++i) { 10367 var example = elements[i]; 10368 var copy = KTUtil.find(example, '.example-copy'); 10369 10370 if (copy) { 10371 var clipboard = new ClipboardJS(copy, { 10372 target: function(trigger) { 10373 var example = trigger.closest('.example'); 10374 var el = KTUtil.find(example, '.example-code .tab-pane.active'); 10375 10376 if (!el) { 10377 el = KTUtil.find(example, '.example-code'); 10378 } 10379 10380 return el; 10381 } 10382 }); 10383 10384 clipboard.on('success', function(e) { 10385 KTUtil.addClass(e.trigger, 'example-copied'); 10386 e.clearSelection(); 10387 10388 setTimeout(function() { 10389 KTUtil.removeClass(e.trigger, 'example-copied'); 10390 }, 2000); 10391 }); 10392 } 10393 } 10394 } 10395 } 10396 10397 var initCompactMode = function(element) { 10398 var example,code,toggle,copy, clipboard; 10399 10400 var elements = element; 10401 if (typeof elements === 'undefined') { 10402 var elements = document.querySelectorAll('.example.example-compact'); 10403 } 10404 10405 if (elements && elements.length > 0 ) { 10406 for (var i = 0; i < elements.length; ++i) { 10407 var example = elements[i]; 10408 var toggle = KTUtil.find(example, '.example-toggle'); 10409 var copy = KTUtil.find(example, '.example-copy'); 10410 10411 // Handle toggle 10412 KTUtil.addEvent(toggle, 'click', function() { 10413 var example = this.closest('.example'); 10414 var code = KTUtil.find(example, '.example-code'); 10415 var the = this; 10416 10417 if (KTUtil.hasClass(this, 'example-toggled')) { 10418 KTUtil.slideUp(code, 300, function() { 10419 KTUtil.removeClass(the, 'example-toggled'); 10420 KTUtil.removeClass(code, 'example-code-on'); 10421 KTUtil.hide(code); 10422 }); 10423 } else { 10424 KTUtil.addClass(code, 'example-code-on'); 10425 KTUtil.addClass(this, 'example-toggled'); 10426 KTUtil.slideDown(code, 300, function() { 10427 KTUtil.show(code); 10428 }); 10429 } 10430 }); 10431 10432 // Handle copy 10433 if (copy) { 10434 var clipboard = new ClipboardJS(copy, { 10435 target: function(trigger) { 10436 var example = trigger.closest('.example'); 10437 var el = KTUtil.find(example, '.example-code .tab-pane.active'); 10438 10439 if (!el) { 10440 el = KTUtil.find(example, '.example-code'); 10441 } 10442 10443 return el; 10444 } 10445 }); 10446 10447 clipboard.on('success', function(e) { 10448 KTUtil.addClass(e.trigger, 'example-copied'); 10449 e.clearSelection(); 10450 10451 setTimeout(function() { 10452 KTUtil.removeClass(e.trigger, 'example-copied'); 10453 }, 2000); 10454 }); 10455 } 10456 } 10457 } 10458 } 10459 10460 return { 10461 init: function(element, options) { 10462 initDefaultMode(element); 10463 initCompactMode(element); 10464 } 10465 }; 10466}(); 10467 10468// webpack support 10469if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 10470 module.exports = KTLayoutExamples; 10471} 10472 10473"use strict"; 10474 10475var KTLayoutQuickActions = function() { 10476 // Private properties 10477 var _element; 10478 var _offcanvasObject; 10479 10480 // Private functions 10481 var _init = function() { 10482 var header = KTUtil.find(_element, '.offcanvas-header'); 10483 var content = KTUtil.find(_element, '.offcanvas-content'); 10484 10485 _offcanvasObject = new KTOffcanvas(_element, { 10486 overlay: true, 10487 baseClass: 'offcanvas', 10488 placement: 'right', 10489 closeBy: 'kt_quick_actions_close', 10490 toggleBy: 'kt_quick_actions_toggle' 10491 }); 10492 10493 KTUtil.scrollInit(content, { 10494 disableForMobile: true, 10495 resetHeightOnDestroy: true, 10496 handleWindowResize: true, 10497 height: function() { 10498 var height = parseInt(KTUtil.getViewPort().height); 10499 10500 if (header) { 10501 height = height - parseInt(KTUtil.actualHeight(header)); 10502 height = height - parseInt(KTUtil.css(header, 'marginTop')); 10503 height = height - parseInt(KTUtil.css(header, 'marginBottom')); 10504 } 10505 10506 if (content) { 10507 height = height - parseInt(KTUtil.css(content, 'marginTop')); 10508 height = height - parseInt(KTUtil.css(content, 'marginBottom')); 10509 } 10510 10511 height = height - parseInt(KTUtil.css(_element, 'paddingTop')); 10512 height = height - parseInt(KTUtil.css(_element, 'paddingBottom')); 10513 10514 height = height - 2; 10515 10516 return height; 10517 } 10518 }); 10519 } 10520 10521 // Public methods 10522 return { 10523 init: function(id) { 10524 _element = KTUtil.getById(id); 10525 10526 if (!_element) { 10527 return; 10528 } 10529 10530 // Initialize 10531 _init(); 10532 }, 10533 10534 getElement: function() { 10535 return _element; 10536 } 10537 }; 10538}(); 10539 10540// Webpack support 10541if (typeof module !== 'undefined') { 10542 module.exports = KTLayoutQuickActions; 10543} 10544 10545"use strict"; 10546 10547var KTLayoutQuickCartPanel = function() { 10548 // Private properties 10549 var _element; 10550 var _offcanvasObject; 10551 10552 // Private functions 10553 var _init = function() { 10554 _offcanvasObject = new KTOffcanvas(_element, { 10555 overlay: true, 10556 baseClass: 'offcanvas', 10557 placement: 'right', 10558 closeBy: 'kt_quick_cart_close', 10559 toggleBy: 'kt_quick_cart_toggle' 10560 }); 10561 10562 var header = KTUtil.find(_element, '.offcanvas-header'); 10563 var content = KTUtil.find(_element, '.offcanvas-content'); 10564 var wrapper = KTUtil.find(_element, '.offcanvas-wrapper'); 10565 var footer = KTUtil.find(_element, '.offcanvas-footer'); 10566 10567 KTUtil.scrollInit(wrapper, { 10568 disableForMobile: true, 10569 resetHeightOnDestroy: true, 10570 handleWindowResize: true, 10571 height: function() { 10572 var height = parseInt(KTUtil.getViewPort().height); 10573 10574 if (header) { 10575 height = height - parseInt(KTUtil.actualHeight(header)); 10576 height = height - parseInt(KTUtil.css(header, 'marginTop')); 10577 height = height - parseInt(KTUtil.css(header, 'marginBottom')); 10578 } 10579 10580 if (content) { 10581 height = height - parseInt(KTUtil.css(content, 'marginTop')); 10582 height = height - parseInt(KTUtil.css(content, 'marginBottom')); 10583 } 10584 10585 if (wrapper) { 10586 height = height - parseInt(KTUtil.css(wrapper, 'marginTop')); 10587 height = height - parseInt(KTUtil.css(wrapper, 'marginBottom')); 10588 } 10589 10590 if (footer) { 10591 height = height - parseInt(KTUtil.actualHeight(footer)); 10592 height = height - parseInt(KTUtil.css(footer, 'marginTop')); 10593 height = height - parseInt(KTUtil.css(footer, 'marginBottom')); 10594 } 10595 10596 height = height - parseInt(KTUtil.css(_element, 'paddingTop')); 10597 height = height - parseInt(KTUtil.css(_element, 'paddingBottom')); 10598 10599 height = height - 2; 10600 10601 return height; 10602 } 10603 }); 10604 } 10605 10606 // Public methods 10607 return { 10608 init: function(id) { 10609 _element = KTUtil.getById(id); 10610 10611 if (!_element) { 10612 return; 10613 } 10614 10615 // Initialize 10616 _init(); 10617 } 10618 }; 10619}(); 10620 10621// Webpack support 10622if (typeof module !== 'undefined') { 10623 module.exports = KTLayoutQuickCartPanel; 10624} 10625 10626"use strict"; 10627 10628var KTLayoutQuickNotifications = function() { 10629 // Private properties 10630 var _element; 10631 var _offcanvasObject; 10632 10633 // Private functions 10634 var _init = function() { 10635 var header = KTUtil.find(_element, '.offcanvas-header'); 10636 var content = KTUtil.find(_element, '.offcanvas-content'); 10637 10638 _offcanvasObject = new KTOffcanvas(_element, { 10639 overlay: true, 10640 baseClass: 'offcanvas', 10641 placement: 'right', 10642 closeBy: 'kt_quick_notifications_close', 10643 toggleBy: 'kt_quick_notifications_toggle' 10644 }); 10645 10646 KTUtil.scrollInit(content, { 10647 disableForMobile: true, 10648 resetHeightOnDestroy: true, 10649 handleWindowResize: true, 10650 height: function() { 10651 var height = parseInt(KTUtil.getViewPort().height); 10652 10653 if (header) { 10654 height = height - parseInt(KTUtil.actualHeight(header)); 10655 height = height - parseInt(KTUtil.css(header, 'marginTop')); 10656 height = height - parseInt(KTUtil.css(header, 'marginBottom')); 10657 } 10658 10659 if (content) { 10660 height = height - parseInt(KTUtil.css(content, 'marginTop')); 10661 height = height - parseInt(KTUtil.css(content, 'marginBottom')); 10662 } 10663 10664 height = height - parseInt(KTUtil.css(_element, 'paddingTop')); 10665 height = height - parseInt(KTUtil.css(_element, 'paddingBottom')); 10666 10667 height = height - 2; 10668 10669 return height; 10670 } 10671 }); 10672 } 10673 10674 // Public methods 10675 return { 10676 init: function(id) { 10677 _element = KTUtil.getById(id); 10678 10679 if (!_element) { 10680 return; 10681 } 10682 10683 // Initialize 10684 _init(); 10685 }, 10686 10687 getElement: function() { 10688 return _element; 10689 } 10690 }; 10691}(); 10692 10693// Webpack support 10694if (typeof module !== 'undefined') { 10695 module.exports = KTLayoutQuickNotifications; 10696} 10697 10698"use strict"; 10699 10700var KTLayoutQuickPanel = function() { 10701 // Private properties 10702 var _element; 10703 var _offcanvasObject; 10704 var _notificationsElement; 10705 var _logsElement; 10706 var _settingsElement; 10707 10708 // Private functions 10709 var _getContentHeight = function() { 10710 var height; 10711 10712 var header = KTUtil.find(_element, '.offcanvas-header'); 10713 var content = KTUtil.find(_element, '.offcanvas-content'); 10714 10715 var height = parseInt(KTUtil.getViewPort().height); 10716 10717 if (header) { 10718 height = height - parseInt(KTUtil.actualHeight(header)); 10719 height = height - parseInt(KTUtil.css(header, 'marginTop')); 10720 height = height - parseInt(KTUtil.css(header, 'marginBottom')); 10721 } 10722 10723 if (content) { 10724 height = height - parseInt(KTUtil.css(content, 'marginTop')); 10725 height = height - parseInt(KTUtil.css(content, 'marginBottom')); 10726 } 10727 10728 height = height - parseInt(KTUtil.css(_element, 'paddingTop')); 10729 height = height - parseInt(KTUtil.css(_element, 'paddingBottom')); 10730 10731 height = height - 2; 10732 10733 return height; 10734 } 10735 10736 var _init = function() { 10737 _offcanvasObject = new KTOffcanvas(_element, { 10738 overlay: true, 10739 baseClass: 'offcanvas', 10740 placement: 'right', 10741 closeBy: 'kt_quick_panel_close', 10742 toggleBy: 'kt_quick_panel_toggle' 10743 }); 10744 } 10745 10746 var _initNotifications = function() { 10747 KTUtil.scrollInit(_notificationsElement, { 10748 mobileNativeScroll: true, 10749 resetHeightOnDestroy: true, 10750 handleWindowResize: true, 10751 height: function() { 10752 return _getContentHeight(); 10753 } 10754 }); 10755 } 10756 10757 var _initLogs = function() { 10758 KTUtil.scrollInit(_logsElement, { 10759 mobileNativeScroll: true, 10760 resetHeightOnDestroy: true, 10761 handleWindowResize: true, 10762 height: function() { 10763 return _getContentHeight(); 10764 } 10765 }); 10766 } 10767 10768 var _initSettings = function() { 10769 KTUtil.scrollInit(_settingsElement, { 10770 mobileNativeScroll: true, 10771 resetHeightOnDestroy: true, 10772 handleWindowResize: true, 10773 height: function() { 10774 return _getContentHeight(); 10775 } 10776 }); 10777 } 10778 10779 var _updateScrollbars = function() { 10780 $(_element).find('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { 10781 KTUtil.scrollUpdate(_notificationsElement); 10782 KTUtil.scrollUpdate(_logsElement); 10783 KTUtil.scrollUpdate(_settingsElement); 10784 }); 10785 } 10786 10787 // Public methods 10788 return { 10789 init: function(id) { 10790 _element = KTUtil.getById(id); 10791 _notificationsElement = KTUtil.getById('kt_quick_panel_notifications'); 10792 _logsElement = KTUtil.getById('kt_quick_panel_logs'); 10793 _settingsElement = KTUtil.getById('kt_quick_panel_settings'); 10794 10795 _init(); 10796 _initNotifications(); 10797 _initLogs(); 10798 _initSettings(); 10799 10800 _updateScrollbars(); 10801 } 10802 }; 10803}(); 10804 10805// Webpack support 10806if (typeof module !== 'undefined') { 10807 module.exports = KTLayoutQuickPanel; 10808} 10809 10810"use strict"; 10811 10812var KTLayoutQuickSearch = function() { 10813 // Private properties 10814 var _element; 10815 var _offcanvasObject; 10816 10817 // Private functions 10818 var _init = function() { 10819 var header = KTUtil.find(_element, '.offcanvas-header'); 10820 var content = KTUtil.find(_element, '.offcanvas-content'); 10821 var form = KTUtil.find(_element, '.quick-search-form'); 10822 var results = KTUtil.find(_element, '.quick-search-wrapper'); 10823 10824 _offcanvasObject = new KTOffcanvas(_element, { 10825 overlay: true, 10826 baseClass: 'offcanvas', 10827 placement: 'right', 10828 closeBy: 'kt_quick_search_close', 10829 toggleBy: 'kt_quick_search_toggle' 10830 }); 10831 10832 KTUtil.scrollInit(results, { 10833 disableForMobile: true, 10834 resetHeightOnDestroy: true, 10835 handleWindowResize: true, 10836 height: function() { 10837 var height = parseInt(KTUtil.getViewPort().height); 10838 10839 if (header) { 10840 height = height - parseInt(KTUtil.actualHeight(header)); 10841 height = height - parseInt(KTUtil.css(header, 'marginTop')); 10842 height = height - parseInt(KTUtil.css(header, 'marginBottom')); 10843 } 10844 10845 if (content) { 10846 height = height - parseInt(KTUtil.css(content, 'marginTop')); 10847 height = height - parseInt(KTUtil.css(content, 'marginBottom')); 10848 } 10849 10850 if (results) { 10851 height = height - parseInt(KTUtil.actualHeight(form)); 10852 height = height - parseInt(KTUtil.css(form, 'marginTop')); 10853 height = height - parseInt(KTUtil.css(form, 'marginBottom')); 10854 10855 height = heig
10855ht - parseInt(KTUtil.css(results, 'marginTop')); 10856 height = height - parseInt(KTUtil.css(results, 'marginBottom')); 10857 } 10858 10859 height = height - parseInt(KTUtil.css(_element, 'paddingTop')); 10860 height = height - parseInt(KTUtil.css(_element, 'paddingBottom')); 10861 10862 height = height - 2; 10863 10864 return height; 10865 } 10866 }); 10867 } 10868 10869 // Public methods 10870 return { 10871 init: function(id) { 10872 _element = KTUtil.getById(id); 10873 10874 if (!_element) { 10875 return; 10876 } 10877 10878 // Initialize 10879 _init(); 10880 }, 10881 10882 getElement: function() { 10883 return _element; 10884 } 10885 }; 10886}(); 10887 10888// Webpack support 10889if (typeof module !== 'undefined') { 10890 module.exports = KTLayoutQuickSearch; 10891} 10892 10893"use strict"; 10894 10895var KTLayoutQuickUser = function() { 10896 // Private properties 10897 var _element; 10898 var _offcanvasObject; 10899 10900 // Private functions 10901 var _init = function() { 10902 var header = KTUtil.find(_element, '.offcanvas-header'); 10903 var content = KTUtil.find(_element, '.offcanvas-content'); 10904 10905 _offcanvasObject = new KTOffcanvas(_element, { 10906 overlay: true, 10907 baseClass: 'offcanvas', 10908 placement: 'right', 10909 closeBy: 'kt_quick_user_close', 10910 toggleBy: 'kt_quick_user_toggle' 10911 }); 10912 10913 KTUtil.scrollInit(content, { 10914 disableForMobile: true, 10915 resetHeightOnDestroy: true, 10916 handleWindowResize: true, 10917 height: function() { 10918 var height = parseInt(KTUtil.getViewPort().height); 10919 10920 if (header) { 10921 height = height - parseInt(KTUtil.actualHeight(header)); 10922 height = height - parseInt(KTUtil.css(header, 'marginTop')); 10923 height = height - parseInt(KTUtil.css(header, 'marginBottom')); 10924 } 10925 10926 if (content) { 10927 height = height - parseInt(KTUtil.css(content, 'marginTop')); 10928 height = height - parseInt(KTUtil.css(content, 'marginBottom')); 10929 } 10930 10931 height = height - parseInt(KTUtil.css(_element, 'paddingTop')); 10932 height = height - parseInt(KTUtil.css(_element, 'paddingBottom')); 10933 10934 height = height - 2; 10935 10936 return height; 10937 } 10938 }); 10939 } 10940 10941 // Public methods 10942 return { 10943 init: function(id) { 10944 _element = KTUtil.getById(id); 10945 10946 if (!_element) { 10947 return; 10948 } 10949 10950 // Initialize 10951 _init(); 10952 }, 10953 10954 getElement: function() { 10955 return _element; 10956 } 10957 }; 10958}(); 10959 10960// Webpack support 10961if (typeof module !== 'undefined') { 10962 module.exports = KTLayoutQuickUser; 10963} 10964 10965"use strict"; 10966 10967var KTLayoutScrolltop = function() { 10968 // Private properties 10969 var _element; 10970 var _object; 10971 10972 // Private functions 10973 var _init = function() { 10974 _object = new KTScrolltop(_element, { 10975 offset: 300, 10976 speed: 600, 10977 }); 10978 } 10979 10980 // Public methods 10981 return { 10982 init: function(id) { 10983 _element = KTUtil.getById(id); 10984 10985 if (!_element) { 10986 return; 10987 } 10988 10989 // Initialize 10990 _init(); 10991 }, 10992 10993 getElement: function() { 10994 return _element; 10995 } 10996 }; 10997}(); 10998 10999// Webpack support 11000if (typeof module !== 'undefined') { 11001 module.exports = KTLayoutScrolltop; 11002} 11003 11004"use strict";
11005// 11006// Handle User Quick Search For Dropdown, Inline and Offcanvas Search Panels 11007// 11008 11009var KTLayoutSearch = function() { 11010 // Private properties 11011 var _target; 11012 var _form; 11013 var _input; 11014 var _closeIcon; 11015 var _resultWrapper; 11016 var _resultDropdown; 11017 var _resultDropdownToggle; 11018 var _closeIconContainer; 11019 var _inputGroup; 11020 var _query = ''; 11021 11022 var _hasResult = false; 11023 var _timeout = false; 11024 var _isProcessing = false; 11025 var _requestTimeout = 200; // ajax request fire timeout in milliseconds 11026 var _spinnerClass = 'spinner spinner-sm spinner-primary'; 11027 var _resultClass = 'quick-search-has-result'; 11028 var _minLength = 2; 11029 11030 // Private functions 11031 var _showProgress = function() { 11032 _isProcessing = true; 11033 KTUtil.addClass(_closeIconContainer, _spinnerClass); 11034 11035 if (_closeIcon) { 11036 KTUtil.hide(_closeIcon); 11037 } 11038 } 11039 11040 var _hideProgress = function() { 11041 _isProcessing = false; 11042 KTUtil.removeClass(_closeIconContainer, _spinnerClass); 11043 11044 if (_closeIcon) { 11045 if (_input.value.length < _minLength) { 11046 KTUtil.hide(_closeIcon); 11047 } else { 11048 KTUtil.show(_closeIcon, 'flex'); 11049 } 11050 } 11051 } 11052 11053 var _showDropdown = function() { 11054 if (_resultDropdownToggle && !KTUtil.hasClass(_resultDropdown, 'show')) { 11055 $(_resultDropdownToggle).dropdown('toggle'); 11056 $(_resultDropdownToggle).dropdown('update'); 11057 } 11058 } 11059 11060 var _hideDropdown = function() { 11061 if (_resultDropdownToggle && KTUtil.hasClass(_resultDropdown, 'show')) { 11062 $(_resultDropdownToggle).dropdown('toggle'); 11063 } 11064 } 11065 11066 var _processSearch = function() { 11067 if (_hasResult && _query === _input.value) { 11068 _hideProgress(); 11069 KTUtil.addClass(_target, _resultClass); 11070 _showDropdown(); 11071 KTUtil.scrollUpdate(_resultWrapper); 11072 11073 return; 11074 } 11075 11076 _query = _input.value; 11077 11078 KTUtil.removeClass(_target, _resultClass); 11079 _showProgress(); 11080 _hideDropdown(); 11081 11082 setTimeout(function() { 11083 $.ajax({ 11084 url: HOST_URL + '/api/quick_search.php', 11085 data: { 11086 query: _query 11087 }, 11088 dataType: 'html', 11089 success: function(res) { 11090 _hasResult = true; 11091 _hideProgress(); 11092 KTUtil.addClass(_target, _resultClass); 11093 KTUtil.setHTML(_resultWrapper, res); 11094 _showDropdown(); 11095 KTUtil.scrollUpdate(_resultWrapper); 11096 }, 11097 error: function(res) { 11098 _hasResult = false;
11099 _hideProgress(); 11100 KTUtil.addClass(_target, _resultClass); 11101 KTUtil.setHTML(_resultWrapper, '<span class="font-weight-bold text-muted">Connection error. Please try again later..</div>'); 11102 _showDropdown(); 11103 KTUtil.scrollUpdate(_resultWrapper); 11104 } 11105 }); 11106 }, 1000); 11107 } 11108 11109 var _handleCancel = function(e) { 11110 _input.value = ''; 11111 _query = ''; 11112 _hasResult = false; 11113 KTUtil.hide(_closeIcon); 11114 KTUtil.removeClass(_target, _resultClass); 11115 _hideDropdown(); 11116 } 11117 11118 var _handleSearch = function() { 11119 if (_input.value.length < _minLength) { 11120 _hideProgress(); 11121 _hideDropdown(); 11122 11123 return; 11124 } 11125 11126 if (_isProcessing == true) { 11127 return; 11128 } 11129 11130 if (_timeout) { 11131 clearTimeout(_timeout); 11132 } 11133 11134 _timeout = setTimeout(function() { 11135 _processSearch(); 11136 }, _requestTimeout); 11137 } 11138 11139 // Public methods 11140 return { 11141 init: function(id) { 11142 _target = KTUtil.getById(id); 11143 11144 if (!_target) { 11145 return; 11146 } 11147 11148 _form = KTUtil.find(_target, '.quick-search-form'); 11149 _input = KTUtil.find(_target, '.form-control'); 11150 _closeIcon = KTUtil.find(_target, '.quick-search-close'); 11151 _resultWrapper = KTUtil.find(_target, '.quick-search-wrapper'); 11152 _resultDropdown = KTUtil.find(_target, '.dropdown-menu'); 11153 _resultDropdownToggle = KTUtil.find(_target, '[data-toggle="dropdown"]'); 11154 _inputGroup = KTUtil.find(_target, '.input-group'); 11155 _closeIconContainer = KTUtil.find(_target, '.input-group .input-group-append'); 11156 11157 // Attach input keyup handler 11158 KTUtil.addEvent(_input, 'keyup', _handleSearch); 11159 KTUtil.addEvent(_input, 'focus', _handleSearch); 11160 11161 // Prevent enter click 11162 _form.onkeypress = function(e) { 11163 var key = e.charCode || e.keyCode || 0; 11164 if (key == 13) { 11165 e.preventDefault(); 11166 } 11167 } 11168 11169 KTUtil.addEvent(_closeIcon, 'click', _handleCancel); 11170 } 11171 }; 11172}; 11173 11174// Webpack support 11175if (typeof module !== 'undefined') { 11176 module.exports = KTLayoutSearch; 11177} 11178 11179var KTLayoutSearchInline = KTLayoutSearch; 11180var KTLayoutSearchOffcanvas = KTLayoutSearch;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.