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