1"use strict"; 2/** 3 * @class KTUtil base utilize class that privides helper functions 4 */ 5 6// Polyfills 7/** 8 * Element.matches() polyfill (simple version) 9 * https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill 10 */ 11if (!Element.prototype.matches) { 12 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; 13} 14 15/** 16 * Element.closest() polyfill 17 * https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill 18 */ 19if (!Element.prototype.closest) { 20 if (!Element.prototype.matches) { 21 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; 22 } 23 Element.prototype.closest = function (s) { 24 var el = this; 25 var ancestor = this; 26 if (!document.documentElement.contains(el)) return null; 27 do { 28 if (ancestor.matches(s)) return ancestor; 29 ancestor = ancestor.parentElement; 30 } while (ancestor !== null); 31 return null; 32 }; 33} 34 35/** 36 * ChildNode.remove() polyfill 37 * https://gomakethings.com/removing-an-element-from-the-dom-the-es6-way/ 38 * @author Chris Ferdinandi 39 * @license MIT 40 */ 41(function (elem) { 42 for (var i = 0; i < elem.length; i++) { 43 if (!window[elem[i]] || 'remove' in window[elem[i]].prototype) continue; 44 window[elem[i]].prototype.remove = function () { 45 this.parentNode.removeChild(this); 46 }; 47 } 48})(['Element', 'CharacterData', 'DocumentType']); 49 50// 51// requestAnimationFrame polyfill by Erik Möller. 52// With fixes from Paul Irish and Tino Zijdel 53// 54// http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 55// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 56// 57// MIT license 58// 59(function() { 60 var lastTime = 0; 61 var vendors = ['webkit', 'moz']; 62 for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 63 window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; 64 window.cancelAnimationFrame = 65 window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame']; 66 } 67 68 if (!window.requestAnimationFrame) 69 window.requestAnimationFrame = function(callback) { 70 var currTime = new Date().getTime(); 71 var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 72 var id = window.setTimeout(function() { 73 callback(currTime + timeToCall); 74 }, timeToCall); 75 lastTime = currTime + timeToCall; 76 return id; 77 }; 78 79 if (!window.cancelAnimationFrame) 80 window.cancelAnimationFrame = function(id) { 81 clearTimeout(id); 82 }; 83}()); 84 85// Source: https://github.com/jserz/js_piece/blob/master/DOM/ParentNode/prepend()/prepend().md 86(function(arr) { 87 arr.forEach(function(item) { 88 if (item.hasOwnProperty('prepend')) { 89 return; 90 } 91 Object.defineProperty(item, 'prepend', { 92 configurable: true, 93 enumerable: true, 94 writable: true, 95 value: function prepend() { 96 var argArr = Array.prototype.slice.call(arguments), 97 docFrag = document.createDocumentFragment(); 98 99 argArr.forEach(function(argItem) { 100 var isNode = argItem instanceof Node; 101 docFrag.appendChild(isNode ? argItem : document.createTextNode(String(argItem))); 102 }); 103 104 this.insertBefore(docFrag, this.firstChild); 105 } 106 }); 107 }); 108})([Element.prototype, Document.prototype, DocumentFragment.prototype]); 109 110// Global variables 111window.KTUtilElementDataStore = {}; 112window.KTUtilElementDataStoreID = 0; 113window.KTUtilDelegatedEventHandlers = {}; 114 115var KTUtil = function() { 116 var resizeHandlers = []; 117 118 /** @type {object} breakpoints The device width breakpoints **/ 119 var breakpoints = { 120 sm: 544, // Small screen / phone 121 md: 768, // Medium screen / tablet 122 lg: 1024, // Large screen / desktop 123 xl: 1200 // Extra large screen / wide desktop 124 }; 125 126 /** 127 * Handle window resize event with some 128 * delay to attach event handlers upon resize complete 129 */ 130 var _windowResizeHandler = function() { 131 var _runResizeHandlers = function() { 132 // reinitialize other subscribed elements 133 for (var i = 0; i < resizeHandlers.length; i++) { 134 var each = resizeHandlers[i]; 135 each.call(); 136 } 137 }; 138 139 var timeout = false; // holder for timeout id
140 var delay = 250; // delay after event is "complete" to run callback 141 142 window.addEventListener('resize', function() { 143 clearTimeout(timeout); 144 timeout = setTimeout(function() { 145 _runResizeHandlers(); 146 }, delay); // wait 50ms until window resize finishes. 147 }); 148 }; 149 150 return { 151 /** 152 * Class main initializer. 153 * @param {object} options. 154 * @returns null 155 */ 156 //main function to initiate the theme 157 init: function(options) { 158 if (options && options.breakpoints) { 159 breakpoints = options.breakpoints; 160 } 161 162 _windowResizeHandler(); 163 }, 164 165 /** 166 * Adds window resize event handler. 167 * @param {function} callback function. 168 */ 169 addResizeHandler: function(callback) { 170 resizeHandlers.push(callback); 171 }, 172 173 /** 174 * Removes window resize event handler. 175 * @param {function} callback function. 176 */ 177 removeResizeHandler: function(callback) { 178 for (var i = 0; i < resizeHandlers.length; i++) { 179 if (callback === resizeHandlers[i]) { 180 delete resizeHandlers[i]; 181 } 182 } 183 }, 184 185 /** 186 * Trigger window resize handlers. 187 */ 188 runResizeHandlers: function() { 189 _runResizeHandlers(); 190 }, 191 192 resize: function() { 193 if (typeof(Event) === 'function') { 194 // modern browsers 195 window.dispatchEvent(new Event('resize')); 196 } else { 197 // for IE and other old browsers 198 // causes deprecation warning on modern browsers 199 var evt = window.document.createEvent('UIEvents'); 200 evt.initUIEvent('resize', true, false, window, 0); 201 window.dispatchEvent(evt); 202 } 203 }, 204 205 /** 206 * Get GET parameter value from URL. 207 * @param {string} paramName Parameter name. 208 * @returns {string} 209 */ 210 getURLParam: function(paramName) { 211 var searchString = window.location.search.substring(1), 212 i, val, params = searchString.split("&"); 213 214 for (i = 0; i < params.length; i++) { 215 val = params[i].split("="); 216 if (val[0] == paramName) { 217 return unescape(val[1]); 218 } 219 } 220 221 return null; 222 }, 223 224 /** 225 * Checks whether current device is mobile touch. 226 * @returns {boolean} 227 */ 228 isMobileDevice: function() { 229 return (this.getViewPort().width < this.getBreakpoint('lg') ? true : false); 230 }, 231 232 /** 233 * Checks whether current device is desktop. 234 * @returns {boolean} 235 */ 236 isDesktopDevice: function() { 237 return KTUtil.isMobileDevice() ? false : true; 238 }, 239 240 /** 241 * Gets browser window viewport size. Ref: 242 * http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/ 243 * @returns {object} 244 */ 245 getViewPort: function() { 246 var e = window, 247 a = 'inner'; 248 if (!('innerWidth' in window)) { 249 a = 'client'; 250 e = document.documentElement || document.body; 251 } 252 253 return { 254 width: e[a + 'Width'], 255 height: e[a + 'Height'] 256 }; 257 }, 258 259 /** 260 * Checks whether given device mode is currently activated. 261 * @param {string} mode Responsive mode name(e.g: desktop, 262 * desktop-and-tablet, tablet, tablet-and-mobile, mobile) 263 * @returns {boolean} 264 */ 265 isInResponsiveRange: function(mode) { 266 var breakpoint = this.getViewPort().width; 267 268 if (mode == 'general') { 269 return true; 270 } else if (mode == 'desktop' && breakpoint >= (this.getBreakpoint('lg') + 1)) { 271 return true; 272 } else if (mode == 'tablet' && (breakpoint >
272= (this.getBreakpoint('md') + 1) && breakpoint < this.getBreakpoint('lg'))) { 273 return true; 274 } else if (mode == 'mobile' && breakpoint <= this.getBreakpoint('md')) { 275 return true; 276 } else if (mode == 'desktop-and-tablet' && breakpoint >= (this.getBreakpoint('md') + 1)) { 277 return true; 278 } else if (mode == 'tablet-and-mobile' && breakpoint <= this.getBreakpoint('lg')) { 279 return true; 280 } else if (mode == 'minimal-desktop-and-below' && breakpoint <= this.getBreakpoint('xl')) { 281 return true; 282 } 283 284 return false; 285 }, 286 287 /** 288 * Generates unique ID for give prefix. 289 * @param {string} prefix Prefix for generated ID 290 * @returns {boolean} 291 */ 292 getUniqueID: function(prefix) { 293 return prefix + Math.floor(Math.random() * (new Date()).getTime()); 294 }, 295 296 /** 297 * Gets window width for give breakpoint mode. 298 * @param {string} mode Responsive mode name(e.g: xl, lg, md, sm) 299 * @returns {number} 300 */ 301 getBreakpoint: function(mode) { 302 return breakpoints[mode]; 303 }, 304 305 /** 306 * Checks whether object has property matchs given key path. 307 * @param {object} obj Object contains values paired with given key path 308 * @param {string} keys Keys path seperated with dots 309 * @returns {object} 310 */ 311 isset: function(obj, keys) { 312 var stone; 313 314 keys = keys || ''; 315 316 if (keys.indexOf('[') !== -1) { 317 throw new Error('Unsupported object path notation.'); 318 } 319 320 keys = keys.split('.'); 321 322 do { 323 if (obj === undefined) { 324 return false; 325 } 326 327 stone = keys.shift(); 328 329 if (!obj.hasOwnProperty(stone)) { 330 return false; 331 } 332 333 obj = obj[stone]; 334 335 } while (keys.length); 336 337 return true; 338 }, 339 340 /** 341 * Gets highest z-index of the given element parents 342 * @param {object} el jQuery element object 343 * @returns {number} 344 */ 345 getHighestZindex: function(el) { 346 var elem = KTUtil.get(el), 347 position, value; 348 349 while (elem && elem !== document) { 350 // Ignore z-index if position is set to a value where z-index is ignored by the browser 351 // This makes behavior of this function consistent across browsers 352 // WebKit always returns auto if the element is positioned 353 position = KTUtil.css(elem, 'position'); 354 355 if (position === "absolute" || position === "relative" || position === "fixed") { 356 // IE returns 0 when zIndex is not specified 357 // other browsers return a string 358 // we ignore the case of nested elements with an explicit value of 0 359 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 360 value = parseInt(KTUtil.css(elem, 'z-index')); 361 362 if (!isNaN(value) && value !== 0) { 363 return value; 364 } 365 } 366 367 elem = elem.parentNode; 368 } 369 370 return null; 371 }, 372 373 /** 374 * Checks whether the element has any parent with fixed positionfreg 375 * @param {object} el jQuery element object 376 * @returns {boolean} 377 */ 378 hasFixedPositionedParent: function(el) { 379 var position; 380 381 while (el && el !== document) { 382 position = KTUtil.css(el, 'position'); 383 384 if (position === "fixed") { 385 return true; 386 } 387 388 el = el.parentNode; 389 } 390 391 return false; 392 }, 393 394 /** 395 * Simulates delay 396 */ 397 sleep: function(milliseconds) { 398 var start = new Date().getTime(); 399 for (var i = 0; i < 1e7; i++) { 400 if ((new Date().getTime() - start) > milliseconds) { 401 break; 402 } 403 } 404 }, 405 406 /** 407 * Gets randomly generated integer value within given min and max range 408 * @param {number} min Range start value 409 * @param {number} max Range end value 410 * @returns {number} 411 */ 412 getRandomInt: function(min, max) { 413 return Math.floor(Math.random() * (max - min + 1)) + min; 414 }, 415 416 /** 417 * Checks whether Angular library is included 418 * @returns {boolean} 419 */ 420 isAngularVersion: function() { 421 return window.Zone !== undefined ? true : false;
422 }, 423 424 // jQuery Workarounds 425 426 // Deep extend: $.extend(true, {}, objA, objB); 427 deepExtend: function(out) { 428 out = out || {}; 429 430 for (var i = 1; i < arguments.length; i++) { 431 var obj = arguments[i]; 432 433 if (!obj) 434 continue; 435 436 for (var key in obj) { 437 if (obj.hasOwnProperty(key)) { 438 if (typeof obj[key] === 'object') 439 out[key] = KTUtil.deepExtend(out[key], obj[key]); 440 else 441 out[key] = obj[key]; 442 } 443 } 444 } 445 446 return out; 447 }, 448 449 // extend: $.extend({}, objA, objB); 450 extend: function(out) { 451 out = out || {}; 452 453 for (var i = 1; i < arguments.length; i++) { 454 if (!arguments[i]) 455 continue; 456 457 for (var key in arguments[i]) { 458 if (arguments[i].hasOwnProperty(key)) 459 out[key] = arguments[i][key]; 460 } 461 } 462 463 return out; 464 }, 465 466 get: function(query) { 467 var el; 468 469 if (query === document) { 470 return document; 471 } 472 473 if (!!(query && query.nodeType === 1)) { 474 return query; 475 } 476 477 if (el = document.getElementById(query)) { 478 return el; 479 } else if (el = document.getElementsByTagName(query), el.length > 0) { 480 return el[0]; 481 } else if (el = document.getElementsByClassName(query), el.length > 0) { 482 return el[0]; 483 } else { 484 return null; 485 } 486 }, 487 488 getByID: function(query) { 489 if (!!(query && query.nodeType === 1)) { 490 return query; 491 } 492 493 return document.getElementById(query); 494 }, 495 496 getByTag: function(query) { 497 var el; 498 499 if (el = document.getElementsByTagName(query)) { 500 return el[0]; 501 } else { 502 return null; 503 } 504 }, 505 506 getByClass: function(query) { 507 var el; 508 509 if (el = document.getElementsByClassName(query)) { 510 return el[0]; 511 } else { 512 return null; 513 } 514 }, 515 516 /** 517 * Checks whether the element has given classes 518 * @param {object} el jQuery element object 519 * @param {string} Classes string 520 * @returns {boolean} 521 */ 522 hasClasses: function(el, classes) { 523 if (!el) { 524 return; 525 } 526 527 var classesArr = classes.split(" "); 528 529 for (var i = 0; i < classesArr.length; i++) { 530 if (KTUtil.hasClass(el, KTUtil.trim(classesArr[i])) == false) { 531 return false; 532 } 533 } 534 535 return true; 536 }, 537 538 hasClass: function(el, className) { 539 if (!el) { 540 return; 541 } 542 543 return el.classList ? el.classList.contains(className) : new RegExp('\\b' + className + '\\b').test(el.className); 544 }, 545 546 addClass: function(el, className) { 547 if (!el || typeof className === 'undefined') { 548 return; 549 } 550 551 var classNames = className.split(' '); 552 553 if (el.classList) { 554 for (var i = 0; i < classNames.length; i++) { 555 if (classNames[i] && classNames[i].length > 0) { 556 el.classList.add(KTUtil.trim(classNames[i])); 557 } 558 } 559 } else if (!KTUtil.hasClass(el, className)) { 560 for (var x = 0; x < classNames.length; x++) { 561 el.className += ' ' + KTUtil.trim(classNames[x]); 562 } 563 } 564 }, 565 566 removeClass: function(el, className) { 567 if (!el || typeof className === 'undefined') { 568 return; 569 } 570 571 var classNames = className.split(' '); 572 573 if (el.classList) { 574 for (var i = 0; i < classNames.length; i++) { 575 el.classList.remove(KTUtil.trim(classNames[i])); 576 } 577 } else if (KTUtil.hasClass(el, className)) { 578 for (var x = 0; x < classNames.length; x++) { 579 el.className = el.className.replace(new RegExp('\\b' + KTUtil.trim(classNames[x]) + '\\b', 'g'), ''); 580 } 581 } 582 }, 583 584 triggerCustomEvent: function(el, eventName, data) { 585 var event; 586 if (window.CustomEvent) { 587 event = new CustomEvent(eventName, { 588 detail: data 589 }); 590 } else { 591 event = document.createEvent('CustomEvent'); 592 event.initCustomEvent(eventName, true, true, data); 593 } 594 595 el.dispatchEvent(event); 596 }, 597 598 triggerEvent: function(node, eventName) { 599 // Make sure we use the ownerDocument from the provided node to avoid cross-window problems 600 var doc; 601 if (node.ownerDocument) { 602 doc = node.ownerDocument; 603 } else if (node.nodeType == 9) { 604 // the node may be the document itself, nodeType 9 = DOCUMENT_NODE 605 doc = node; 606 } else { 607 throw new Error("Invalid node passed to fireEvent: " + node.id); 608 } 609
610 if (node.dispatchEvent) { 611 // Gecko-style approach (now the standard) takes more work 612 var eventClass = ""; 613 614 // Different events have different event classes. 615 // If this switch statement can't map an eventName to an eventClass, 616 // the event firing is going to fail. 617 switch (eventName) { 618 case "click": // Dispatching of 'click' appears to not work correctly in Safari. Use 'mousedown' or 'mouseup' instead. 619 case "mouseenter": 620 case "mouseleave": 621 case "mousedown": 622 case "mouseup": 623 eventClass = "MouseEvents"; 624 break; 625 626 case "focus": 627 case "change": 628 case "blur": 629 case "select": 630 eventClass = "HTMLEvents"; 631 break; 632 633 default: 634 throw "fireEvent: Couldn't find an event class for event '" + eventName + "'."; 635 break; 636 } 637 var event = doc.createEvent(eventClass); 638 639 var bubbles = eventName == "change" ? false : true; 640 event.initEvent(eventName, bubbles, true); // All events created as bubbling and cancelable. 641 642 event.synthetic = true; // allow detection of synthetic events 643 // The second parameter says go ahead with the default action 644 node.dispatchEvent(event, true); 645 } else if (node.fireEvent) { 646 // IE-old school style 647 var event = doc.createEventObject(); 648 event.synthetic = true; // allow detection of synthetic events 649 node.fireEvent("on" + eventName, event); 650 } 651 }, 652 653 index: function( elm ){ 654 elm = KTUtil.get(elm); 655 var c = elm.parentNode.children, i = 0; 656 for(; i < c.length; i++ ) 657 if( c[i] == elm ) return i; 658 }, 659 660 trim: function(string) { 661 return string.trim(); 662 }, 663 664 eventTriggered: function(e) { 665 if (e.currentTarget.dataset.triggered) { 666 return true; 667 } else { 668 e.currentTarget.dataset.triggered = true; 669 670 return false; 671 } 672 }, 673 674 remove: function(el) { 675 if (el && el.parentNode) { 676 el.parentNode.removeChild(el); 677 } 678 }, 679 680 find: function(parent, query) { 681 parent = KTUtil.get(parent); 682 if (parent) { 683 return parent.querySelector(query); 684 } 685 }, 686 687 findAll: function(parent, query) { 688 parent = KTUtil.get(parent); 689 if (parent) { 690 return parent.querySelectorAll(query); 691 } 692 }, 693 694 insertAfter: function(el, referenceNode) { 695 return referenceNode.parentNode.insertBefore(el, referenceNode.nextSibling); 696 }, 697 698 parents: function(elem, selector) { 699 // Element.matches() polyfill 700 if (!Element.prototype.matches) { 701 Element.prototype.matches = 702 Element.prototype.matchesSelector || 703 Element.prototype.mozMatchesSelector || 704 Element.prototype.msMatchesSelector || 705 Element.prototype.oMatchesSelector || 706 Element.prototype.webkitMatchesSelector || 707 function(s) { 708 var matches = (this.document || this.ownerDocument).querySelectorAll(s), 709 i = matches.length; 710 while (--i >= 0 && matches.item(i) !== this) {} 711 return i > -1; 712 }; 713 } 714 715 // Set up a parent array 716 var parents = []; 717 718 // Push each parent element to the array 719 for ( ; elem && elem !== document; elem = elem.parentNode ) { 720 if (selector) { 721 if (elem.matches(selector)) { 722 parents.push(elem); 723 } 724 continue; 725 } 726 parents.push(elem); 727 } 728 729 // Return our parent array 730 return parents; 731 }, 732 733 children: function(el, selector, log) { 734 if (!el || !el.childNodes) { 735 return; 736 } 737 738 var result = [], 739 i = 0, 740 l = el.childNodes.length; 741 742 for (var i; i < l; ++i) { 743 if (el.childNodes[i].nodeType == 1 && KTUtil.matches(el.childNodes[i], selector, log)) { 744 result.push(el.childNodes[i]); 745 } 746 } 747 748 return result; 749 }, 750 751 child: function(el, selector, log) { 752 var children = KTUtil.children(el, selector, log); 753 754 return children ? children[0] : null; 755 }, 756 757 matches: function(el, selector, log) { 758 var p = Element.prototype; 759 var f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function(s) { 760 return [].indexOf.call(document.querySelectorAll(s), this) !== -1; 761 }; 762 763 if (el && el.tagName) { 764 return f.call(el, selector); 765 } else { 766 return false;
767 } 768 }, 769 770 data: function(element) { 771 element = KTUtil.get(element); 772 773 return { 774 set: function(name, data) { 775 if (element == null || element === undefined) { 776 return; 777 } 778 779 if (element.customDataTag === undefined) { 780 window.KTUtilElementDataStoreID++; 781 element.customDataTag = window.KTUtilElementDataStoreID; 782 } 783 784 if (window.KTUtilElementDataStore[element.customDataTag] === undefined) { 785 window.KTUtilElementDataStore[element.customDataTag] = {}; 786 } 787 788 window.KTUtilElementDataStore[element.customDataTag][name] = data; 789 }, 790 791 get: function(name) { 792 if (element === undefined) { 793 return; 794 } 795 796 if (element == null || element.customDataTag === undefined) { 797 return null; 798 } 799 800 return this.has(name) ? window.KTUtilElementDataStore[element.customDataTag][name] : null; 801 }, 802 803 has: function(name) { 804 if (element === undefined) { 805 return false; 806 } 807 808 if (element == null || element.customDataTag === undefined) { 809 return false; 810 } 811 812 return (window.KTUtilElementDataStore[element.customDataTag] && window.KTUtilElementDataStore[element.customDataTag][name]) ? true : false; 813 }, 814 815 remove: function(name) { 816 if (element && this.has(name)) { 817 delete window.KTUtilElementDataStore[element.customDataTag][name]; 818 } 819 } 820 }; 821 }, 822 823 outerWidth: function(el, margin) { 824 var width; 825 826 if (margin === true) { 827 width = parseFloat(el.offsetWidth); 828 width += parseFloat(KTUtil.css(el, 'margin-left')) + parseFloat(KTUtil.css(el, 'margin-right')); 829 830 return parseFloat(width); 831 } else { 832 width = parseFloat(el.offsetWidth); 833 834 return width; 835 } 836 }, 837 838 offset: function(elem) { 839 var rect, win; 840 elem = KTUtil.get(elem); 841 842 if ( !elem ) { 843 return; 844 } 845 846 // Return zeros for disconnected and hidden (display: none) elements (gh-2310) 847 // Support: IE <=11 only 848 // Running getBoundingClientRect on a 849 // disconnected node in IE throws an error 850 851 if ( !elem.getClientRects().length ) { 852 return { top: 0, left: 0 }; 853 } 854 855 // Get document-relative position by adding viewport scroll to viewport-relative gBCR 856 rect = elem.getBoundingClientRect(); 857 win = elem.ownerDocument.defaultView; 858 859 return { 860 top: rect.top + win.pageYOffset, 861 left: rect.left + win.pageXOffset 862 }; 863 }, 864 865 height: function(el) { 866 return KTUtil.css(el, 'height'); 867 }, 868 869 visible: function(el) { 870 return !(el.offsetWidth === 0 && el.offsetHeight === 0); 871 }, 872 873 attr: function(el, name, value) { 874 el = KTUtil.get(el); 875 876 if (el == undefined) { 877 return; 878 } 879 880 if (value !== undefined) { 881 el.setAttribute(name, value); 882 } else { 883 return el.getAttribute(name); 884 } 885 }, 886 887 hasAttr: function(el, name) { 888 el = KTUtil.get(el); 889 890 if (el == undefined) { 891 return; 892 } 893 894 return el.getAttribute(name) ? true : false; 895 }, 896 897 removeAttr: function(el, name) { 898 el = KTUtil.get(el); 899 900 if (el == undefined) { 901 return; 902 } 903 904 el.removeAttribute(name); 905 }, 906 907 animate: function(from, to, duration, update, easing, done) { 908 /** 909 * TinyAnimate.easings 910 * Adapted from jQuery Easing 911 */ 912 var easings = {}; 913 var easing; 914 915 easings.linear = function(t, b, c, d) { 916 return c * t / d + b; 917 }; 918 919 easing = easings.linear; 920 921 // Early bail out if called incorrectly 922 if (typeof from !== 'number' || 923 typeof to !== 'number' || 924 typeof duration !== 'number' || 925 typeof update !== 'function') { 926 return; 927 } 928 929 // Create mock done() function if necessary 930 if (typeof done !== 'function') { 931 done = function() {}; 932 } 933 934 // Pick implementation (requestAnimationFrame | setTimeout) 935 var rAF = window.requestAnimationFrame || function(callback) { 936 window.setTimeout(callback, 1000 / 50); 937 }; 938 939 // Animation loop 940 var canceled = false;
941 var change = to - from; 942 943 function loop(timestamp) { 944 var time = (timestamp || +new Date()) - start; 945 946 if (time >= 0) { 947 update(easing(time, from, change, duration)); 948 } 949 if (time >= 0 && time >= duration) { 950 update(to); 951 done(); 952 } else { 953 rAF(loop); 954 } 955 } 956 957 update(from); 958 959 // Start animation loop 960 var start = window.performance && window.performance.now ? window.performance.now() : +new Date(); 961 962 rAF(loop); 963 }, 964 965 actualCss: function(el, prop, cache) { 966 el = KTUtil.get(el); 967 var css = ''; 968 969 if (el instanceof HTMLElement === false) { 970 return; 971 } 972 973 if (!el.getAttribute('kt-hidden-' + prop) || cache === false) { 974 var value; 975 976 // the element is hidden so: 977 // making the el block so we can meassure its height but still be hidden 978 css = el.style.cssText; 979 el.style.cssText = 'position: absolute; visibility: hidden; display: block;'; 980 981 if (prop == 'width') { 982 value = el.offsetWidth; 983 } else if (prop == 'height') { 984 value = el.offsetHeight; 985 } 986 987 el.style.cssText = css; 988 989 // store it in cache 990 el.setAttribute('kt-hidden-' + prop, value); 991 992 return parseFloat(value); 993 } else { 994 // store it in cache 995 return parseFloat(el.getAttribute('kt-hidden-' + prop)); 996 } 997 }, 998 999 actualHeight: function(el, cache) { 1000 return KTUtil.actualCss(el, 'height', cache); 1001 }, 1002 1003 actualWidth: function(el, cache) { 1004 return KTUtil.actualCss(el, 'width', cache); 1005 }, 1006 1007 getScroll: function(element, method) { 1008 // The passed in `method` value should be 'Top' or 'Left' 1009 method = 'scroll' + method; 1010 return (element == window || element == document) ? ( 1011 self[(method == 'scrollTop') ? 'pageYOffset' : 'pageXOffset'] || 1012 (browserSupportsBoxModel && document.documentElement[method]) || 1013 document.body[method] 1014 ) : element[method]; 1015 }, 1016 1017 css: function(el, styleProp, value) { 1018 el = KTUtil.get(el); 1019 1020 if (!el) { 1021 return; 1022 } 1023 1024 if (value !== undefined) { 1025 el.style[styleProp] = value; 1026 } else { 1027 var defaultView = (el.ownerDocument || document).defaultView; 1028 // W3C standard way: 1029 if (defaultView && defaultView.getComputedStyle) { 1030 // sanitize property name to css notation 1031 // (hyphen separated words eg. font-Size) 1032 styleProp = styleProp.replace(/([A-Z])/g, "-$1").toLowerCase(); 1033 return defaultView.getComputedStyle(el, null).getPropertyValue(styleProp); 1034 } else if (el.currentStyle) { // IE 1035 // sanitize property name to camelCase 1036 styleProp = styleProp.replace(/\-(\w)/g, function(str, letter) { 1037 return letter.toUpperCase(); 1038 }); 1039 value = el.currentStyle[styleProp]; 1040 // convert other units to pixels on IE 1041 if (/^\d+(em|pt|%|ex)?$/i.test(value)) { 1042 return (function(value) { 1043 var oldLeft = el.style.left, 1044 oldRsLeft = el.runtimeStyle.left; 1045 el.runtimeStyle.left = el.currentStyle.left; 1046 el.style.left = value || 0; 1047 value = el.style.pixelLeft + "px"; 1048 el.style.left = oldLeft; 1049 el.runtimeStyle.left = oldRsLeft; 1050 return value; 1051 })(value); 1052 } 1053 return value; 1054 } 1055 } 1056 }, 1057 1058 slide: function(el, dir, speed, callback, recalcMaxHeight) { 1059 if (!el || (dir == 'up' && KTUtil.visible(el) === false) || (dir == 'down' && KTUtil.visible(el) === true)) { 1060 return; 1061 } 1062 1063 speed = (speed ? speed : 600); 1064 var calcHeight = KTUtil.actualHeight(el); 1065 var calcPaddingTop = false;
1066 var calcPaddingBottom = false; 1067 1068 if (KTUtil.css(el, 'padding-top') && KTUtil.data(el).has('slide-padding-top') !== true) { 1069 KTUtil.data(el).set('slide-padding-top', KTUtil.css(el, 'padding-top')); 1070 } 1071 1072 if (KTUtil.css(el, 'padding-bottom') && KTUtil.data(el).has('slide-padding-bottom') !== true) { 1073 KTUtil.data(el).set('slide-padding-bottom', KTUtil.css(el, 'padding-bottom')); 1074 } 1075 1076 if (KTUtil.data(el).has('slide-padding-top')) { 1077 calcPaddingTop = parseInt(KTUtil.data(el).get('slide-padding-top')); 1078 } 1079 1080 if (KTUtil.data(el).has('slide-padding-bottom')) { 1081 calcPaddingBottom = parseInt(KTUtil.data(el).get('slide-padding-bottom')); 1082 } 1083 1084 if (dir == 'up') { // up 1085 el.style.cssText = 'display: block; overflow: hidden;'; 1086 1087 if (calcPaddingTop) { 1088 KTUtil.animate(0, calcPaddingTop, speed, function(value) { 1089 el.style.paddingTop = (calcPaddingTop - value) + 'px'; 1090 }, 'linear'); 1091 } 1092 1093 if (calcPaddingBottom) { 1094 KTUtil.animate(0, calcPaddingBottom, speed, function(value) { 1095 el.style.paddingBottom = (calcPaddingBottom - value) + 'px'; 1096 }, 'linear'); 1097 } 1098 1099 KTUtil.animate(0, calcHeight, speed, function(value) { 1100 el.style.height = (calcHeight - value) + 'px'; 1101 }, 'linear', function() { 1102 callback(); 1103 el.style.height = ''; 1104 el.style.display = 'none'; 1105 }); 1106 1107 1108 } else if (dir == 'down') { // down 1109 el.style.cssText = 'display: block; overflow: hidden;'; 1110 1111 if (calcPaddingTop) { 1112 KTUtil.animate(0, calcPaddingTop, speed, function(value) { 1113 el.style.paddingTop = value + 'px'; 1114 }, 'linear', function() { 1115 el.style.paddingTop = ''; 1116 }); 1117 } 1118 1119 if (calcPaddingBottom) { 1120 KTUtil.animate(0, calcPaddingBottom, speed, function(value) { 1121 el.style.paddingBottom = value + 'px'; 1122 }, 'linear', function() { 1123 el.style.paddingBottom = ''; 1124 }); 1125 } 1126 1127 KTUtil.animate(0, calcHeight, speed, function(value) { 1128 el.style.height = value + 'px'; 1129 }, 'linear', function() { 1130 callback(); 1131 el.style.height = ''; 1132 el.style.display = ''; 1133 el.style.overflow = ''; 1134 }); 1135 } 1136 }, 1137 1138 slideUp: function(el, speed, callback) { 1139 KTUtil.slide(el, 'up', speed, callback); 1140 }, 1141 1142 slideDown: function(el, speed, callback) { 1143 KTUtil.slide(el, 'down', speed, callback); 1144 }, 1145 1146 show: function(el, display) { 1147 if (typeof el !== 'undefined') { 1148 el.style.display = (display ? display : 'block'); 1149 } 1150 }, 1151 1152 hide: function(el) { 1153 if (typeof el !== 'undefined') { 1154 el.style.display = 'none'; 1155 } 1156 }, 1157 1158 addEvent: function(el, type, handler, one) { 1159 el = KTUtil.get(el); 1160 1161 if (typeof el !== 'undefined' && el !== null) { 1162 el.addEventListener(type, handler); 1163 } 1164 }, 1165 1166 removeEvent: function(el, type, handler) { 1167 el = KTUtil.get(el); 1168 1169 if (el !== null) { 1170 el.removeEventListener(type, handler); 1171 } 1172 }, 1173 1174 on: function(element, selector, event, handler) { 1175 if (!selector) { 1176 return; 1177 } 1178 1179 var eventId = KTUtil.getUniqueID('event'); 1180 1181 window.KTUtilDelegatedEventHandlers[eventId] = function(e) { 1182 var targets = element.querySelectorAll(selector); 1183 var target = e.target; 1184 1185 while (target && target !== element) { 1186 for (var i = 0, j = targets.length; i < j; i++) { 1187 if (target === targets[i]) { 1188 handler.call(target, e); 1189 } 1190 } 1191 1192 target = target.parentNode; 1193 } 1194 } 1195 1196 KTUtil.addEvent(element, event, window.KTUtilDelegatedEventHandlers[eventId]); 1197 1198 return eventId; 1199 }, 1200 1201 off: function(element, event, eventId) { 1202 if (!element || !window.KTUtilDelegatedEventHandlers[eventId]) { 1203 return; 1204 } 1205 1206 KTUtil.removeEvent(element, event, window.KTUtilDelegatedEventHandlers[eventId]); 1207 1208 delete window.KTUtilDelegatedEventHandlers[eventId]; 1209 }, 1210 1211 one: function onetime(el, type, callback) { 1212 el = KTUtil.get(el); 1213 1214 el.addEventListener(type, function callee(e) { 1215 // remove event 1216 if (e.target && e.target.removeEventListener) { 1217 e.target.removeEventListener(e.type, callee); 1218 } 1219 1220 // call handler 1221 return callback(e); 1222 }); 1223 }, 1224 1225 hash: function(str) { 1226 var hash = 0, 1227 i, chr; 1228 1229 if (str.length === 0) return hash; 1230 for (i = 0; i < str.length; i++) { 1231 chr = str.charCodeAt(i); 1232 hash = ((hash << 5) - hash) + chr; 1233 hash |= 0; // Convert to 32bit integer 1234 } 1235 1236 return hash; 1237 }, 1238 1239 animateClass: function(el, animationName, callback) { 1240 var animation; 1241 var animations = { 1242 animation: 'animationend', 1243 OAnimation: 'oAnimationEnd', 1244 MozAnimation: 'mozAnimationEnd', 1245 WebkitAnimation: 'webkitAnimationEnd', 1246 msAnimation: 'msAnimationEnd', 1247 }; 1248 1249 for (var t in animations) { 1250 if (el.style[t] !== undefined) { 1251 animation = animations[t]; 1252 } 1253 } 1254 1255 KTUtil.addClass(el, 'animated ' + animationName); 1256 1257 KTUtil.one(el, animation, function() { 1258 KTUtil.removeClass(el, 'animated ' + animationName); 1259 }); 1260 1261 if (callback) { 1262 KTUtil.one(el, animation, callback); 1263 } 1264 }, 1265 1266 transitionEnd: function(el, callback) { 1267 var transition; 1268 var transitions = { 1269 transition: 'transitionend', 1270 OTransition: 'oTransitionEnd', 1271 MozTransition: 'mozTransitionEnd', 1272 WebkitTransition: 'webkitTransitionEnd', 1273 msTransition: 'msTransitionEnd' 1274 }; 1275 1276 for (var t in transitions) { 1277 if (el.style[t] !== undefined) { 1278 transition = transitions[t]; 1279 } 1280 } 1281 1282 KTUtil.one(el, transition, callback); 1283 }, 1284 1285 animationEnd: function(el, callback) { 1286 var animation; 1287 var animations = { 1288 animation: 'animationend', 1289 OAnimation: 'oAnimationEnd', 1290 MozAnimation: 'mozAnimationEnd', 1291 WebkitAnimation: 'webkitAnimationEnd', 1292 msAnimation: 'msAnimationEnd' 1293 }; 1294 1295 for (var t in animations) { 1296 if (el.style[t] !== undefined) { 1297 animation = animations[t]; 1298 } 1299 } 1300 1301 KTUtil.one(el, animation, callback); 1302 }, 1303 1304 animateDelay: function(el, value) { 1305 var vendors = ['webkit-', 'moz-', 'ms-', 'o-', '']; 1306 for (var i = 0; i < vendors.length; i++) { 1307 KTUtil.css(el, vendors[i] + 'animation-delay', value); 1308 } 1309 }, 1310 1311 animateDuration: function(el, value) { 1312 var vendors = ['webkit-', 'moz-', 'ms-', 'o-', '']; 1313 for (var i = 0; i < vendors.length; i++) { 1314 KTUtil.css(el, vendors[i] + 'animation-duration', value); 1315 } 1316 }, 1317 1318 scrollTo: function(target, offset, duration) { 1319 duration = duration ? duration : 500; 1320 target = KTUtil.get(target); 1321 var targetPos = target ? KTUtil.offset(target).top : 0; 1322 var scrollPos = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; 1323 var from, to; 1324 1325 if (offset) { 1326 scrollPos += offset; 1327 } 1328 1329 from = scrollPos; 1330 to = targetPos; 1331 1332 KTUtil.animate(from, to, duration, function(value) { 1333 document.documentElement.scrollTop = value; 1334 document.body.parentNode.scrollTop = value; 1335 document.body.scrollTop = value; 1336 }); //, easing, done 1337 }, 1338 1339 scrollTop: function(offset, duration) { 1340 KTUtil.scrollTo(null, offset, duration); 1341 }, 1342 1343 isArray: function(obj) { 1344 return obj && Array.isArray(obj); 1345 }, 1346 1347 ready: function(callback) { 1348 if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") { 1349 callback(); 1350 } else { 1351 document.addEventListener('DOMContentLoaded', callback); 1352 } 1353 }, 1354 1355 isEmpty: function(obj) { 1356 for (var prop in obj) { 1357 if (obj.hasOwnProperty(prop)) { 1358 return false;
1359 } 1360 } 1361 1362 return true; 1363 }, 1364 1365 numberString: function(nStr) { 1366 nStr += ''; 1367 var x = nStr.split('.'); 1368 var x1 = x[0]; 1369 var x2 = x.length > 1 ? '.' + x[1] : ''; 1370 var rgx = /(\d+)(\d{3})/; 1371 while (rgx.test(x1)) { 1372 x1 = x1.replace(rgx, '$1' + ',' + '$2'); 1373 } 1374 return x1 + x2; 1375 }, 1376 1377 detectIE: function() { 1378 var ua = window.navigator.userAgent; 1379 1380 // Test values; Uncomment to check result ⦠1381 1382 // IE 10 1383 // ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)'; 1384 1385 // IE 11 1386 // ua = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko'; 1387 1388 // Edge 12 (Spartan) 1389 // 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'; 1390 1391 // Edge 13 1392 // 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'; 1393 1394 var msie = ua.indexOf('MSIE '); 1395 if (msie > 0) { 1396 // IE 10 or older => return version number 1397 return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10); 1398 } 1399 1400 var trident = ua.indexOf('Trident/'); 1401 if (trident > 0) { 1402 // IE 11 => return version number 1403 var rv = ua.indexOf('rv:'); 1404 return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10); 1405 } 1406 1407 var edge = ua.indexOf('Edge/'); 1408 if (edge > 0) { 1409 // Edge (IE 12+) => return version number 1410 return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10); 1411 } 1412 1413 // other browser 1414 return false; 1415 }, 1416 1417 isRTL: function() { 1418 return (KTUtil.attr(KTUtil.get('html'), 'direction') == 'rtl'); 1419 }, 1420 1421 // 1422 1423 // Scroller 1424 scrollInit: function(element, options) { 1425 if(!element) return; 1426 // Define init function 1427 function init() { 1428 var ps; 1429 var height; 1430 1431 if (options.height instanceof Function) { 1432 height = parseInt(options.height.call()); 1433 } else { 1434 height = parseInt(options.height); 1435 } 1436 1437 // Destroy scroll on table and mobile modes 1438 if ((options.mobileNativeScroll || options.disableForMobile) && KTUtil.isInResponsiveRange('tablet-and-mobile')) { 1439 ps = KTUtil.data(element).get('ps'); 1440 if (ps) { 1441 if (options.resetHeightOnDestroy) { 1442 KTUtil.css(element, 'height', 'auto'); 1443 } else { 1444 KTUtil.css(element, 'overflow', 'auto'); 1445 if (height > 0) { 1446 KTUtil.css(element, 'height', height + 'px'); 1447 } 1448 } 1449 1450 ps.destroy(); 1451 ps = KTUtil.data(element).remove('ps'); 1452 } else if (height > 0){ 1453 KTUtil.css(element, 'overflow', 'auto'); 1454 KTUtil.css(element, 'height', height + 'px'); 1455 } 1456 1457 return; 1458 } 1459 1460 if (height > 0) { 1461 KTUtil.css(element, 'height', height + 'px'); 1462 } 1463 1464 if (options.desktopNativeScroll) { 1465 KTUtil.css(element, 'overflow', 'auto'); 1466 return; 1467 } 1468 1469 // Init scroll 1470 KTUtil.css(element, 'overflow', 'hidden'); 1471 1472 ps = KTUtil.data(element).get('ps'); 1473 if (ps) { 1474 ps.update(); 1475 } else { 1476 KTUtil.addClass(element, 'kt-scroll'); 1477 ps = new PerfectScrollbar(element, { 1478 wheelSpeed: 0.5, 1479 swipeEasing: true, 1480 wheelPropagation: (options.windowScroll === false ? false : true), 1481 minScrollbarLength: 40, 1482 maxScrollbarLength: 300, 1483 suppressScrollX: KTUtil.attr(element, 'data-scroll-x') != 'true' ? true : false 1484 }); 1485 1486 KTUtil.data(element).set('ps', ps); 1487 } 1488 1489 // Remember scroll position in cookie
1490 var uid = KTUtil.attr(element, 'id'); 1491 1492 if (options.rememberPosition === true && Cookies && uid) { 1493 if (Cookies.get(uid)) { 1494 var pos = parseInt(Cookies.get(uid)); 1495 1496 if (pos > 0) { 1497 element.scrollTop = pos; 1498 } 1499 } 1500 1501 element.addEventListener('ps-scroll-y', function() { 1502 Cookies.set(uid, element.scrollTop); 1503 }); 1504 } 1505 } 1506 1507 // Init 1508 init(); 1509 1510 // Handle window resize 1511 if (options.handleWindowResize) { 1512 KTUtil.addResizeHandler(function() { 1513 init(); 1514 }); 1515 } 1516 }, 1517 1518 scrollUpdate: function(element) { 1519 var ps = KTUtil.data(element).get('ps'); 1520 if (ps) { 1521 ps.update(); 1522 } 1523 }, 1524 1525 scrollUpdateAll: function(parent) { 1526 var scrollers = KTUtil.findAll(parent, '.ps'); 1527 for (var i = 0, len = scrollers.length; i < len; i++) { 1528 KTUtil.scrollUpdate(scrollers[i]); 1529 } 1530 }, 1531 1532 scrollDestroy: function(element) { 1533 var ps = KTUtil.data(element).get('ps'); 1534 if (ps) { 1535 ps.destroy(); 1536 ps = KTUtil.data(element).remove('ps'); 1537 } 1538 }, 1539 1540 setHTML: function(el, html) { 1541 if (KTUtil.get(el)) { 1542 KTUtil.get(el).innerHTML = html; 1543 } 1544 }, 1545 1546 getHTML: function(el) { 1547 if (KTUtil.get(el)) { 1548 return KTUtil.get(el).innerHTML; 1549 } 1550 }, 1551 1552 getDocumentHeight: function() { 1553 var body = document.body; 1554 var html = document.documentElement; 1555 1556 return Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight ); 1557 }, 1558 1559 getScrollTop: function() { 1560 return (document.scrollingElement || document.documentElement).scrollTop; 1561 } 1562 } 1563}(); 1564 1565// webpack support 1566if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 1567 module.exports = KTUtil; 1568} 1569 1570// Initialize KTUtil class on document ready 1571KTUtil.ready(function() { 1572 KTUtil.init(); 1573}); 1574 1575// CSS3 Transitions only after page load(.kt-page-loading class added to body tag and remove with JS on page load) 1576window.onload = function() { 1577 KTUtil.removeClass(KTUtil.get('body'), 'kt-page--loading'); 1578}
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.