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