PageSourceSearch

https://telematik5.ai/assets/js/global/components/base/util.js

js telematik5.ai collected 2026-10-05 14:44:51 UTC 51,977 bytes, 1,578 lines download raw bytes

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.