UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

1,767 lines (1,752 loc) 213 kB
const require_kendo_licensing = require('./kendo.licensing-DQkab2ZD.js'); //#region ../src/utils/mediaquery.js let breakpoints; const EVENT = "change"; const defaultBreakpoints = { small: "(max-width: 500px)", medium: "(min-width: 500.1px) and (max-width: 768px)", large: "(min-width: 768.1px)" }; function createMediaQuery(query) { let mediaQueryList = window.matchMedia(query); let onEnterCallbacks = []; let onLeaveCallbacks = []; let onChangeHandlers = []; let kendoMediaQuery = { mediaQueryList }; const onChangeHandler = (ev) => { onChangeHandlers.forEach((cb) => cb(ev)); if (ev.matches) { onEnterCallbacks.forEach((cb) => cb(ev)); } else { onLeaveCallbacks.forEach((cb) => cb(ev)); } }; mediaQueryList.addEventListener(EVENT, onChangeHandler); const onChange = (cb) => { onChangeHandlers.push(cb); return kendoMediaQuery; }; const onEnter = (cb) => { onEnterCallbacks.push(cb); if (mediaQueryList.matches) { const media = mediaQueryList.media; const matches = true; const ev = new MediaQueryListEvent(EVENT, { media, matches }); cb(ev); } return kendoMediaQuery; }; const onLeave = (cb) => { onLeaveCallbacks.push(cb); return kendoMediaQuery; }; const destroy = () => { if (mediaQueryList) { mediaQueryList.removeEventListener(EVENT, onChangeHandler); } onEnterCallbacks = null; onLeaveCallbacks = null; onChangeHandlers = null; mediaQueryList = null; kendoMediaQuery = null; }; kendoMediaQuery.onChange = onChange; kendoMediaQuery.onEnter = onEnter; kendoMediaQuery.onLeave = onLeave; kendoMediaQuery.destroy = destroy; return kendoMediaQuery; } function mediaQuery(query) { if (!query) { return; } breakpoints = breakpoints || Object.assign({}, defaultBreakpoints, kendo.defaults.breakpoints); if (query in breakpoints) { query = breakpoints[query]; } return createMediaQuery(query); } //#endregion //#region ../src/utils/convert-class.js function fromESClass(ESClass) { class ExtendedClass extends ESClass { static extend(proto) { const subclass = class extends ExtendedClass { constructor() { super(); if (proto && proto.init) { proto.init.apply(this, arguments); } } }; Object.assign(subclass.prototype, proto); addInstanceGetter(subclass.prototype); subclass.fn = subclass.prototype; return subclass; } } addInstanceGetter(ExtendedClass.prototype); ExtendedClass.fn = ExtendedClass.prototype; return ExtendedClass; } function addInstanceGetter(proto) { Object.defineProperty(proto, "_instance", { get: function() { return this; } }); } //#endregion //#region ../src/core/models/date-utils.ts /** * Date utility type definitions */ /** * Date field mapping for format parsing */ const DATE_FIELD_MAP = { "G": "era", "y": "year", "q": "quarter", "Q": "quarter", "M": "month", "L": "month", "d": "day", "E": "weekday", "c": "weekday", "e": "weekday", "h": "hour", "H": "hour", "k": "hour", "K": "hour", "m": "minute", "s": "second", "a": "dayperiod", "t": "dayperiod", "x": "zone", "X": "zone", "z": "zone", "Z": "zone" }; /** * Name types for date formatting */ const NAME_TYPES = { month: { type: "months", minLength: 3, standAlone: "L" }, quarter: { type: "quarters", minLength: 3, standAlone: "q" }, weekday: { type: "days", minLength: { E: 0, c: 3, e: 3 }, standAlone: "c" }, dayperiod: { type: "dayPeriods", minLength: 0 }, era: { type: "eras", minLength: 0 } }; //#endregion //#region ../src/core/models/dom-utils.ts /** * Animation directions */ const DIRECTIONS = { left: { reverse: "right" }, right: { reverse: "left" }, down: { reverse: "up" }, up: { reverse: "down" }, top: { reverse: "bottom" }, bottom: { reverse: "top" }, "in": { reverse: "out" }, out: { reverse: "in" } }; //#endregion //#region ../src/core/services/support.service.ts const UNDEFINED$2 = "undefined"; /** * Test a value against a set of regex patterns */ function testRx(agent, rxs, dflt) { for (const rx in rxs) { if (rxs.hasOwnProperty(rx) && rxs[rx].test(agent)) { return rx; } } return dflt !== undefined ? dflt : agent; } /** * Support detection service for browser, OS, and feature detection */ var SupportService = class { constructor() { this._scrollbar = undefined; this.scrollbar = this.scrollbar.bind(this); this.isRtl = this.isRtl.bind(this); this.detectOS = this.detectOS.bind(this); this.detectBrowser = this.detectBrowser.bind(this); this.detectClipboardAccess = this.detectClipboardAccess.bind(this); this.zoomLevel = this.zoomLevel.bind(this); this.delayedClick = this.delayedClick.bind(this); this.initialize(); } initialize() { const win = window; const doc = document; const nav = navigator; const table = doc.createElement("table"); try { table.innerHTML = "<tr><td></td></tr>"; this.tbodyInnerHtml = true; } catch (e) { this.tbodyInnerHtml = false; } this.touch = "ontouchstart" in win; const docStyle = doc.documentElement.style; const elementProto = "HTMLElement" in win ? HTMLElement.prototype : []; this.transforms = this.transitions = { css: "", prefix: "", event: "transitionend" }; this.hasHW3D = "WebKitCSSMatrix" in win && "m11" in new win.WebKitCSSMatrix() || "MozPerspective" in docStyle || "msPerspective" in docStyle; this.cssFlexbox = "flexWrap" in docStyle || "WebkitFlexWrap" in docStyle || "msFlexWrap" in docStyle; this.devicePixelRatio = win.devicePixelRatio === undefined ? 1 : win.devicePixelRatio; try { this.screenWidth = win.outerWidth || win.screen ? win.screen.availWidth : win.innerWidth; this.screenHeight = win.outerHeight || win.screen ? win.screen.availHeight : win.innerHeight; } catch (e) { this.screenWidth = win.screen.availWidth; this.screenHeight = win.screen.availHeight; } let mobileOS = this.detectOS(nav.userAgent); this.mobileOS = mobileOS; this.wpDevicePixelRatio = mobileOS && mobileOS.wp ? screen.width / 320 : 0; this.hasNativeScrolling = false; if (mobileOS && (mobileOS.ios || mobileOS.android && parseInt(mobileOS.majorVersion) > 2 || mobileOS.wp)) { this.hasNativeScrolling = mobileOS; } this.mouseAndTouchPresent = this.touch && !(mobileOS && (mobileOS.ios || mobileOS.android)); this.browser = this.detectBrowser(nav.userAgent); if (!mobileOS && this.touch && this.browser.safari) { mobileOS = this.mobileOS = { ios: true, tablet: "tablet", device: "ipad", majorVersion: "13", minorVersion: "0", flatVersion: "1300", cordova: false, appMode: false, name: "ios", browser: "mobilesafari" }; } this.clipboard = this.detectClipboardAccess(); this.eventCapture = !!doc.documentElement.addEventListener; const input = doc.createElement("input"); this.placeholder = "placeholder" in input; this.propertyChangeEvent = "onpropertychange" in input; this.input = this.detectInputTypes(input); input.style.cssText = "float:left;"; this.cssFloat = !!input.style.cssFloat; this.stableSort = this.detectStableSort(); this.matchesSelector = elementProto.webkitMatchesSelector || elementProto.mozMatchesSelector || elementProto.msMatchesSelector || elementProto.oMatchesSelector || elementProto.matchesSelector || elementProto.matches || function(selector) { const nodeList = doc.querySelectorAll ? (this.parentNode || doc).querySelectorAll(selector) || [] : $(selector); let i = nodeList.length; while (i--) { if (nodeList[i] === this) { return true; } } return false; }; this.matchMedia = "matchMedia" in win; this.pushState = !!(win.history && win.history.pushState); this.hashChange = "onhashchange" in win; this.customElements = "registerElement" in doc; const chrome = this.browser.chrome; const mobileChrome = this.browser.crios; const mozilla = this.browser.mozilla; const safari = this.browser.safari; this.msPointers = !chrome && win.MSPointerEvent; this.pointers = !chrome && !mobileChrome && !mozilla && !safari && win.PointerEvent; this.kineticScrollNeeded = !!(mobileOS && (mobileOS.device !== "ipad" || parseInt(mobileOS.majorVersion) < 13) && (this.touch || this.msPointers || this.pointers)); if (this.touch) { if (!this.mobileOS) { this.mousedown = "mousedown touchstart"; this.mouseup = "mouseup touchend"; this.mousemove = "mousemove touchmove"; this.mousecancel = "mouseleave touchcancel"; this.click = "click"; this.resize = "resize"; } else { this.mousedown = "touchstart"; this.mouseup = "touchend"; this.mousemove = "touchmove"; this.mousecancel = "touchcancel"; this.click = "touchend"; this.resize = "orientationchange"; } } else if (this.pointers) { this.mousemove = "pointermove"; this.mousedown = "pointerdown"; this.mouseup = "pointerup"; this.mousecancel = "pointercancel"; this.click = "pointerup"; this.resize = "orientationchange resize"; } else if (this.msPointers) { this.mousemove = "MSPointerMove"; this.mousedown = "MSPointerDown"; this.mouseup = "MSPointerUp"; this.mousecancel = "MSPointerCancel"; this.click = "MSPointerUp"; this.resize = "orientationchange resize"; } else { this.mousemove = "mousemove"; this.mousedown = "mousedown"; this.mouseup = "mouseup"; this.mousecancel = "mouseleave"; this.click = "click"; this.resize = "resize"; } this.addBrowserCssClasses($); } /** * Get or calculate scrollbar width */ scrollbar(refresh) { if (!isNaN(this._scrollbar) && !refresh) { return this._scrollbar; } const div = document.createElement("div"); div.style.cssText = "overflow:scroll;overflow-x:hidden;zoom:1;clear:both;display:block"; div.innerHTML = "&nbsp;"; document.body.appendChild(div); this._scrollbar = div.offsetWidth - div.scrollWidth; document.body.removeChild(div); return this._scrollbar; } /** * Check if element is in RTL context */ isRtl(element) { return $(element).closest(".k-rtl").length > 0; } /** * Detect mobile operating system from user agent */ detectOS(ua) { let os = false; let minorVersion; let match = null; const notAndroidPhone = !/mobile safari/i.test(ua); const agentRxs = { wp: /(Windows Phone(?: OS)?)\s(\d+)\.(\d+(\.\d+)?)/, fire: /(Silk)\/(\d+)\.(\d+(\.\d+)?)/, android: /(Android|Android.*(?:Opera|Firefox).*?\/)\s*(\d+)\.?(\d+(\.\d+)?)?/, iphone: /(iPhone|iPod).*OS\s+(\d+)[\._]([\d\._]+)/, ipad: /(iPad).*OS\s+(\d+)[\._]([\d_]+)/, meego: /(MeeGo).+NokiaBrowser\/(\d+)\.([\d\._]+)/, webos: /(webOS)\/(\d+)\.(\d+(\.\d+)?)/, blackberry: /(BlackBerry|BB10).*?Version\/(\d+)\.(\d+(\.\d+)?)/, playbook: /(PlayBook).*?Tablet\s*OS\s*(\d+)\.(\d+(\.\d+)?)/, windows: /(MSIE)\s+(\d+)\.(\d+(\.\d+)?)/, tizen: /(tizen).*?Version\/(\d+)\.(\d+(\.\d+)?)/i, sailfish: /(sailfish).*rv:(\d+)\.(\d+(\.\d+)?).*firefox/i, ffos: /(Mobile).*rv:(\d+)\.(\d+(\.\d+)?).*Firefox/ }; const osRxs = { ios: /^i(phone|pad|pod)$/i, android: /^android|fire$/i, blackberry: /^blackberry|playbook/i, windows: /windows/, wp: /wp/, flat: /sailfish|ffos|tizen/i, meego: /meego/ }; const formFactorRxs = { tablet: /playbook|ipad|fire/i }; const browserRxs = { omini: /Opera\sMini/i, omobile: /Opera\sMobi/i, firefox: /Firefox|Fennec/i, mobilesafari: /version\/.*safari/i, ie: /MSIE|Windows\sPhone/i, chrome: /chrome|crios/i, webkit: /webkit/i, edge: /edge|edg|edgios|edga/i }; for (const agent in agentRxs) { if (agentRxs.hasOwnProperty(agent)) { match = ua.match(agentRxs[agent]); if (match) { if (agent === "windows" && "plugins" in navigator) { return false; } os = {}; os.device = agent; os.tablet = testRx(agent, formFactorRxs, false); os.browser = testRx(ua, browserRxs, "default"); os.name = testRx(agent, osRxs); os[os.name] = true; os.majorVersion = match[2]; os.minorVersion = (match[3] || "0").replace("_", "."); minorVersion = os.minorVersion.replace(".", "").substr(0, 2); os.flatVersion = os.majorVersion + minorVersion + new Array(3 - (minorVersion.length < 3 ? minorVersion.length : 2)).join("0"); os.cordova = typeof window.PhoneGap !== UNDEFINED$2 || typeof window.cordova !== UNDEFINED$2; os.appMode = !!navigator.standalone || /file|local|wmapp/.test(window.location.protocol) || os.cordova; if (os.android && (this.devicePixelRatio < 1.5 && parseInt(os.flatVersion) < 400 || notAndroidPhone) && (this.screenWidth > 800 || this.screenHeight > 800)) { os.tablet = agent; } break; } } } return os; } /** * Detect browser from user agent */ detectBrowser(ua) { let browser = false; let match; let chromiumEdgeMatch; const browserRxs = { edge: /(edge)[ \/]([\w.]+)/i, webkit: /(chrome|crios)[ \/]([\w.]+)/i, safari: /(webkit)[ \/]([\w.]+)/i, opera: /(opera)(?:.*version|)[ \/]([\w.]+)/i, msie: /(msie\s|trident.*? rv:)([\w.]+)/i, mozilla: /(mozilla)(?:.*? rv:([\w.]+)|)/i }; for (const agent in browserRxs) { if (browserRxs.hasOwnProperty(agent)) { match = ua.match(browserRxs[agent]); if (match) { browser = {}; browser[agent] = true; browser[match[1].toLowerCase().split(" ")[0].split("/")[0]] = true; browser.version = parseInt(document.documentMode || match[2], 10); if (browser.chrome) { chromiumEdgeMatch = ua.match(/(edg)[ \/]([\w.]+)/i); if (chromiumEdgeMatch) { browser.chromiumEdge = true; } } break; } } } return browser || { version: 0 }; } /** * Detect clipboard command support */ detectClipboardAccess() { const doc = document; const commands = { copy: doc.queryCommandSupported ? doc.queryCommandSupported("copy") : false, cut: doc.queryCommandSupported ? doc.queryCommandSupported("cut") : false, paste: doc.queryCommandSupported ? doc.queryCommandSupported("paste") : false }; if (this.browser.chrome) { commands.paste = false; if (this.browser.version >= 43) { commands.copy = true; commands.cut = true; } } return commands; } /** * Get current zoom level */ zoomLevel() { try { const browser = this.browser; let ie11WidthCorrection = 0; const docEl = document.documentElement; if (browser.msie && browser.version === 11 && docEl.scrollHeight > docEl.clientHeight && !this.touch) { ie11WidthCorrection = this.scrollbar(); } return this.touch ? docEl.clientWidth / window.innerWidth : browser.msie && browser.version >= 10 ? ((top || window).document.documentElement.offsetWidth + ie11WidthCorrection) / (top || window).innerWidth : 1; } catch (e) { return 1; } } /** * Check if device has delayed click behavior */ delayedClick() { if (this.touch) { const mobileOS = this.mobileOS; if (mobileOS && mobileOS.ios) { return true; } if (mobileOS && mobileOS.android) { if (!this.browser.chrome) { return true; } if (this.browser.version < 32) { return false; } return !($("meta[name=viewport]").attr("content") || "").match(/user-scalable=no/i); } } return false; } /** * Detect native input type support */ detectInputTypes(input) { const types = [ "number", "date", "time", "month", "week", "datetime", "datetime-local" ]; const value = "test"; const result = {}; for (const type of types) { input.setAttribute("type", type); input.value = value; result[type.replace("-", "")] = input.type !== "text" && input.value !== value; } return result; } /** * Detect if sort is stable */ detectStableSort() { const threshold = 513; const sorted = [{ index: 0, field: "b" }]; for (let i = 1; i < threshold; i++) { sorted.push({ index: i, field: "a" }); } sorted.sort((a, b) => { return a.field > b.field ? 1 : a.field < b.field ? -1 : 0; }); return sorted[0].index === 1; } /** * Add browser-specific CSS classes to document element */ addBrowserCssClasses($) { const browser = this.browser; let cssClass = ""; const docElement = $(document.documentElement); const majorVersion = parseInt(String(browser.version), 10); if (browser.msie) { cssClass = "ie"; } else if (browser.mozilla) { cssClass = "ff"; } else if (browser.safari) { cssClass = "safari"; } else if (browser.webkit) { cssClass = "webkit"; } else if (browser.opera) { cssClass = "opera"; } else if (browser.edge) { cssClass = "edge"; } if (cssClass) { cssClass = "k-" + cssClass + " k-" + cssClass + majorVersion; } if (this.mobileOS) { cssClass += " k-mobile"; } if (!this.cssFlexbox) { cssClass += " k-no-flexbox"; } docElement.addClass(cssClass); } /** * Convert Bootstrap breakpoint name to CSS media query */ bootstrapToMedia(bootstrapMedia) { const bootstrapBreakpoints = { "xs": "(max-width: 576px)", "sm": "(min-width: 576px)", "md": "(min-width: 768px)", "lg": "(min-width: 992px)", "xl": "(min-width: 1200px)" }; return bootstrapBreakpoints[bootstrapMedia]; } /** * Check if a media query matches * Supports both CSS media queries and Bootstrap breakpoint names */ matchesMedia(mediaQuery) { const media = this.bootstrapToMedia(mediaQuery) || mediaQuery; return this.matchMedia && window.matchMedia(media).matches; } }; const supportService = new SupportService(); //#endregion //#region ../src/core/services/mouse-event-normalizer.service.ts /** * Mouse Event Normalizer Service * Handles mouse event capturing and muting for touch/pointer event normalization. */ /** * Mouse event normalizer service for handling touch/mouse event conflicts. * Prevents ghost clicks and normalizes touch events to mouse events. */ var MouseEventNormalizerService = class { constructor() { this.mouseTrap = false; this.bustClick = false; this.captureMouse = false; this.MOUSE_EVENTS = [ "mousedown", "mousemove", "mouseenter", "mouseleave", "mouseover", "mouseout", "mouseup", "click" ]; this.EXCLUDE_BUST_CLICK_SELECTOR = "label, input, [data-rel=external]"; } /** * Set up mouse event capturing to prevent ghost clicks from touch events. * This sets up event listeners on document.documentElement to intercept * and optionally stop mouse events when touch events are active. */ setupMouseMute() { let idx = 0; const length = this.MOUSE_EVENTS.length; const element = document.documentElement; if (this.mouseTrap || !supportService.eventCapture) { return; } this.mouseTrap = true; this.bustClick = false; this.captureMouse = false; const self = this; const handler = function(e) { if (self.captureMouse) { if (e.type === "click") { if (self.bustClick && !$(e.target).is(self.EXCLUDE_BUST_CLICK_SELECTOR)) { e.preventDefault(); e.stopPropagation(); } } else { e.stopPropagation(); } } }; for (; idx < length; idx++) { element.addEventListener(this.MOUSE_EVENTS[idx], handler, true); } } /** * Mute mouse events. Called on touchstart to prevent ghost clicks. * @param e - The jQuery event with bustClick data */ muteMouse(e) { this.captureMouse = true; if (e.data?.bustClick) { this.bustClick = true; } clearTimeout(this.mouseTrapTimeoutID); } /** * Unmute mouse events. Called on touchend after a delay to allow * legitimate mouse events through again. */ unMuteMouse() { clearTimeout(this.mouseTrapTimeoutID); this.mouseTrapTimeoutID = setTimeout(() => { this.captureMouse = false; this.bustClick = false; }, 400); } }; const mouseEventNormalizerService = new MouseEventNormalizerService(); //#endregion //#region ../src/core/services/event-map.service.ts /** * Event Map Service * Provides cross-browser event mapping for touch, pointer, and mouse events. */ /** * Event map service for cross-browser event handling. * Maps abstract event names (down, move, up, cancel) to the appropriate * browser-specific events based on touch/pointer/mouse support. */ var EventMapService = class { constructor() { this.eventRegEx = /([^ ]+)/g; this.eventMap = this.buildEventMap(); this.setupMSPointerEvents(); } /** * Build the event map based on browser capabilities */ buildEventMap() { let map = { down: "touchstart mousedown", move: "mousemove touchmove", up: "mouseup touchend touchcancel", cancel: "mouseleave touchcancel" }; if (supportService.touch && supportService.mobileOS && (supportService.mobileOS.ios || supportService.mobileOS.android)) { map = { down: "touchstart", move: "touchmove", up: "touchend touchcancel", cancel: "touchcancel" }; } else if (supportService.pointers) { map = { down: "pointerdown", move: "pointermove", up: "pointerup", cancel: "pointercancel pointerleave" }; } else if (supportService.msPointers) { map = { down: "MSPointerDown", move: "MSPointerMove", up: "MSPointerUp", cancel: "MSPointerCancel MSPointerLeave" }; } return map; } /** * Setup MSPointerEnter/MSPointerLeave events for IE10 * Creates these events using mouseover/out and event-time checks */ setupMSPointerEvents() { if (supportService.msPointers && !("onmspointerenter" in window)) { $.each({ MSPointerEnter: "MSPointerOver", MSPointerLeave: "MSPointerOut" }, (orig, fix) => { $.event.special[orig] = { delegateType: fix, bindType: fix, handle: function(event) { let ret; const target = this; const related = event.relatedTarget; const handleObj = event.handleObj; if (!related || related !== target && !this.$.contains(target, related)) { event.type = handleObj.origType; ret = handleObj.handler.apply(this, arguments); event.type = fix; } return ret; } }; }); } } /** * Get the mapped event for an abstract event name * @param eventName - The abstract event name (down, move, up, cancel) or specific event * @returns The browser-specific event(s) or the original event if no mapping exists */ getEventMap(eventName) { return this.eventMap[eventName] || eventName; } /** * Get the full event map object */ getFullEventMap() { return { ...this.eventMap }; } /** * Apply event mapping to a space-separated list of events * @param events - Space-separated event names to map * @param ns - Optional namespace to append to each event * @returns The mapped and namespaced events */ applyEventMap(events, ns) { events = events.replace(this.eventRegEx, (e) => this.getEventMap(e)); if (ns) { events = events.replace(this.eventRegEx, "$1." + ns); } return events; } }; const eventMapService = new EventMapService(); //#endregion //#region ../src/core/services/utils.service.ts const OBJECT = "object"; const UNDEFINED$1 = "undefined"; /** * Utility service providing general helper functions. */ var UtilsService = class { constructor() { this.keys = { INSERT: 45, DELETE: 46, BACKSPACE: 8, TAB: 9, ENTER: 13, ESC: 27, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40, END: 35, HOME: 36, SPACEBAR: 32, PAGEUP: 33, PAGEDOWN: 34, F2: 113, F10: 121, F12: 123, SHIFT: 16, NUMPAD_PLUS: 107, NUMPAD_MINUS: 109, NUMPAD_DOT: 110 }; this.days = { Sunday: 0, Monday: 1, Tuesday: 2, Wednesday: 3, Thursday: 4, Friday: 5, Saturday: 6 }; } /** * Get kendo.data namespace (accessed at call time for lazy loading) */ get kendoData() { return window.kendo?.data || {}; } /** * Convert camelCase to hyphen-case */ toHyphens(str) { return str.replace(/([a-z][A-Z])/g, (g) => { return g.charAt(0) + "-" + g.charAt(1).toLowerCase(); }); } /** * Convert hyphen-case to camelCase */ toCamelCase(str) { return str.replace(/\-(\w)/g, (_strMatch, g1) => { return g1.toUpperCase(); }); } /** * Count properties in an object (excluding toJSON for IE7 compat) */ size(obj) { let result = 0; for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key) && key !== "toJSON") { result++; } } return result; } /** * Deep extend an object with one or more source objects. */ deepExtend(destination, ...sources) { for (let i = 0; i < sources.length; i++) { this.deepExtendOne(destination, sources[i]); } return destination; } /** * Deep extend destination with a single source object. * This is the core implementation that handles all the special cases. */ deepExtendOne(destination, source) { const ObservableArray = this.kendoData.ObservableArray; const LazyObservableArray = this.kendoData.LazyObservableArray; const DataSource = this.kendoData.DataSource; const HierarchicalDataSource = this.kendoData.HierarchicalDataSource; for (const property in source) { if (property === "__proto__" || property === "constructor" || property === "prototype") { continue; } const propValue = source[property]; const propType = typeof propValue; let propInit = null; if (propType === OBJECT && propValue !== null) { propInit = propValue.constructor; } let isRegExp = propInit?.name === "RegExp"; let isArrayBuffer = propInit?.name === "ArrayBuffer"; let isDate = propInit?.name === "Date"; if (propInit && !Array.isArray(propValue) && propInit !== ObservableArray && propInit !== LazyObservableArray && propInit !== DataSource && propInit !== HierarchicalDataSource && !isRegExp && (!this.isFunction(window.ArrayBuffer) || !isArrayBuffer) && !(propValue instanceof HTMLElement)) { if (isDate) { destination[property] = new Date(propValue.getTime()); } else if (this.isCloneable(propValue)) { destination[property] = propValue.clone(); } else { const destProp = destination[property]; if (typeof destProp === OBJECT) { destination[property] = destProp || {}; } else { destination[property] = {}; } this.deepExtendOne(destination[property], propValue); } } else if (propType !== UNDEFINED$1) { destination[property] = propValue; } } return destination; } /** * Check if an object has a clone method */ isCloneable(obj) { return typeof obj.clone === "function"; } /** * Create a throttled version of a function. * The throttled function will only execute at most once per delay period. * Includes a cancel() method to clear any pending execution. * * If delay is falsy (0, null, undefined), returns the original function unchanged. */ throttle(fn, delay) { if (!delay || delay <= 0) { return fn; } let timeout; let lastExecTime = 0; const throttled = function(...args) { const that = this; const elapsed = +new Date() - lastExecTime; function exec() { const result = fn.apply(that, args); lastExecTime = +new Date(); return result; } if (!lastExecTime) { return exec(); } if (timeout) { clearTimeout(timeout); } if (elapsed > delay) { return exec(); } else { timeout = setTimeout(exec, delay - elapsed); } }; throttled.cancel = function() { if (timeout) { clearTimeout(timeout); timeout = undefined; } }; return throttled; } /** * Generate a UUID. * Uses crypto.randomUUID() when available (HTTPS only), * falls back to crypto.getRandomValues(). */ guid() { const cryptoObj = window.crypto; try { return cryptoObj.randomUUID(); } catch (e) { const randomValues = cryptoObj.getRandomValues(new Uint8Array(16)); return randomValues.reduce((acc, curr, i) => { if (i === 4 || i === 6 || i === 8 || i === 10) { acc += "-"; } acc += curr.toString(16).padStart(2, "0"); return acc; }, ""); } } /** * Trim whitespace from a value. * Converts to string first, returns empty string for falsy values. */ trim(value) { if (value) { return value.toString().trim(); } return ""; } /** * Check if a value is present (not null and not undefined) */ isPresent(value) { return value !== null && value !== undefined; } /** * Check if a value is blank (null or undefined) */ isBlank(value) { return value === null || value === undefined; } /** * Check if a value is empty (has length 0) */ isEmpty(value) { return value.length === 0; } /** * Check if a value is a string */ isString(value) { return typeof value === "string"; } /** * Check if a value is an integer */ isInteger(value) { return Number.isInteger(value); } /** * Check if a value is numeric */ isNumeric(value) { return !isNaN(value - parseFloat(value)); } /** * Check if a value is a Date object */ isDate(value) { return value && value.getTime; } /** * Check if a value is a function */ isFunction(value) { return typeof value === "function"; } /** * Check if a value is an object (and not null) */ isObject(value) { return value !== null && typeof value === OBJECT; } /** * Log a message to the console. * Respects kendo.suppressLog setting. * @param message - The message to log * @param type - Console method to use ("log", "warn", "error", etc.). Defaults to "log" */ logToConsole(message, type) { const console = window.console; const kendo = window.kendo; if (!kendo.suppressLog && typeof console !== "undefined" && console.log) { console[type || "log"](message); } } /** * Wait for all promises to resolve, similar to Promise.all but for jQuery Deferreds. * Unlike $.when(), this handles failures gracefully and reports all results. * * Influenced from: https://gist.github.com/fearphage/4341799 * * @param array - Array of deferreds/promises, or multiple arguments * @returns A jQuery Promise that resolves when all inputs resolve, or rejects if any fail */ whenAll(array) { const $ = window.jQuery; const resolveValues = arguments.length === 1 && Array.isArray(array) ? array : Array.prototype.slice.call(arguments); const length = resolveValues.length; let remaining = length; const deferred = $.Deferred(); let i = 0; let failed = 0; const rejectContexts = new Array(length); const rejectValues = new Array(length); const resolveContexts = new Array(length); let value; const updateFunc = (index, contexts, values) => { return function() { if (values !== resolveValues) { failed++; } deferred.notifyWith(contexts[index] = this, values[index] = Array.prototype.slice.call(arguments)); if (!--remaining) { deferred[(!failed ? "resolve" : "reject") + "With"](contexts, values); } }; }; for (; i < length; i++) { value = resolveValues[i]; if (value && this.isFunction(value.promise)) { value.promise().done(updateFunc(i, resolveContexts, resolveValues)).fail(updateFunc(i, rejectContexts, rejectValues)); } else { deferred.notifyWith(this, value); --remaining; } } if (!remaining) { deferred.resolveWith(resolveContexts, resolveValues); } return deferred.promise(); } /** * Check if a URL is local (doesn't start with a protocol) * @param url - URL to check * @returns True if the URL is local */ isLocalUrl(url) { return url && !/^([a-z]+:)?\/\//i.test(url); } /** * Get all method names (static and instance) from a class * @param targetClass - The class to inspect * @returns Array of method names */ getAllMethods(targetClass) { const allStatic = Object.getOwnPropertyNames(targetClass).filter((prop) => typeof targetClass[prop] === "function"); const allNonStatic = Object.getOwnPropertyNames(Object.getPrototypeOf(new targetClass({}))).filter((prop) => prop !== "constructor"); return allStatic.concat(allNonStatic); } /** * Get the base class (parent class) of a given class * @param targetClass - The class to get the parent of * @returns The parent class or null if none */ getBaseClass(targetClass) { if (targetClass instanceof Function) { const baseClass = targetClass; const newBaseClass = Object.getPrototypeOf(baseClass); if (newBaseClass && newBaseClass !== Object && newBaseClass.name) { return newBaseClass; } } return null; } /** * Create a proxy member on a prototype that delegates to an instance * @param proto - The prototype object to add the member to * @param name - The name of the member to create */ createProxyMember(proto, name) { proto.fn[name] = function() { const instance = this._instance; if (instance) { return instance[name].apply(instance, arguments); } }; } /** * Convert a native Promise to a jQuery Deferred * @param promise - The native Promise to convert * @returns A jQuery Promise */ convertPromiseToDeferred(promise) { const deferred = $.Deferred(); promise.finally(deferred.always).then(deferred.resolve).catch(deferred.reject); return deferred.promise(); } }; const utilsService = new UtilsService(); //#endregion //#region ../src/core/services/kendo-jquery.service.ts /** * KendoJQuery Service * * Provides a jQuery wrapper with Kendo-specific functionality: * - Event namespacing with automatic cleanup * - Handler context binding * - Touch/mouse event normalization * - Keyboard event handling */ const STRING$5 = "string"; const UNDEFINED = "undefined"; /** * KendoJQuery Service * Creates and manages the KendoJQuery wrapper around jQuery */ var KendoJQueryService = class { constructor() { this.originalOn = $.fn.on; this.kendoJQuery = this.createKendoJQuery(); this.rootjQuery = this.kendoJQuery(document); } /** * Extend objects while avoiding jQuery deprecated properties */ noDeprecateExtend(deep, target, ...sources) { let src, copyIsArray, copy, name, options, clone; if (typeof target !== "object" && typeof target !== "function") { target = {}; } for (const source of sources) { if (source != null) { for (name in source) { if (name === "filters" || name === "concat" || name === ":" || name === "cssNumber") { continue; } src = target[name]; copy = source[name]; if (target === copy) { continue; } if (deep && copy && ($.isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) { if (copyIsArray) { copyIsArray = false; clone = src && Array.isArray(src) ? src : []; } else { clone = src && $.isPlainObject(src) ? src : {}; } target[name] = this.noDeprecateExtend(deep, clone, copy); } else if (copy !== undefined) { target[name] = copy; } } } } return target; } /** * Create the KendoJQuery constructor and prototype */ createKendoJQuery() { const self = this; const kendoJQuery = function(selector, context) { return new kendoJQuery.fn.init(selector, context); }; this.noDeprecateExtend(true, kendoJQuery, $); kendoJQuery.fn = kendoJQuery.prototype = new $(); kendoJQuery.fn.constructor = kendoJQuery; kendoJQuery.fn.init = function(selector, context) { if (context && context instanceof $ && !(context instanceof kendoJQuery)) { context = kendoJQuery(context); } return $.fn.init.call(this, selector, context, self.rootjQuery); }; kendoJQuery.fn.init.prototype = kendoJQuery.fn; $.extend(kendoJQuery.fn, { handler: function(handler) { this.data("handler", handler); return this; }, autoApplyNS: function(ns) { this.data("kendoNS", ns || utilsService.guid()); return this; }, on: function(...args) { const that = this; const ns = that.data("kendoNS"); const on = self.originalOn; if (args.length === 1) { return on.call(that, args[0]); } let context = that; const argsCopy = args.slice(); if (typeof argsCopy[argsCopy.length - 1] === UNDEFINED) { argsCopy.pop(); } const callback = argsCopy[argsCopy.length - 1]; const events = eventMapService.applyEventMap(argsCopy[0], ns); if (supportService.mouseAndTouchPresent && events.search(/mouse|click/) > -1 && this[0] !== document.documentElement) { mouseEventNormalizerService.setupMouseMute(); const selector = argsCopy.length === 2 ? null : argsCopy[1]; const bustClick = events.indexOf("click") > -1 && events.indexOf("touchend") > -1; on.call(this, { touchstart: (e) => mouseEventNormalizerService.muteMouse(e), touchend: () => mouseEventNormalizerService.unMuteMouse() }, selector, { bustClick }); } if (argsCopy[0].indexOf("keydown") !== -1 && argsCopy[1] && argsCopy[1].options) { argsCopy[0] = events; const widget = argsCopy[1]; const keyDownCallback = argsCopy[argsCopy.length - 1]; argsCopy[argsCopy.length - 1] = function(e) { if (self.keyDownHandler(e, widget)) { return keyDownCallback.apply(this, [e]); } }; on.apply(that, argsCopy); return that; } if (typeof callback === STRING$5) { context = that.data("handler"); const callbackFn = context[callback]; argsCopy[argsCopy.length - 1] = function(e) { callbackFn.call(context, e); }; } argsCopy[0] = events; on.apply(that, argsCopy); return that; }, kendoDestroy: function(ns) { ns = ns || this.data("kendoNS"); if (ns) { this.off("." + ns); } return this; } }); return kendoJQuery; } /** * Get the KendoJQuery constructor function */ getConstructor() { return this.kendoJQuery; } /** * Create a KendoJQuery wrapper */ create(selector, context) { return this.kendoJQuery(selector, context); } /** * Handle keydown events for a widget * Executes all kendoKeydown handlers and checks if event should be prevented */ keyDownHandler(e, widget) { const events = widget._events.kendoKeydown; if (!events) { return true; } const eventsCopy = events.slice(); e.sender = widget; e.preventKendoKeydown = false; for (let idx = 0, length = eventsCopy.length; idx < length; idx++) { eventsCopy[idx].call(widget, e); } return !e.preventKendoKeydown; } }; const kendoJQueryService = new KendoJQueryService(); //#endregion //#region ../src/core/base/class.ts /** * Base Class for Kendo UI. * All Kendo classes inherit from this base class. */ var Class = class { /** * Creates a subclass with the given prototype. * This is the legacy extend pattern used throughout Kendo UI. * * This method: * 1. Creates a new constructor function that extends the current class * 2. Copies all properties from proto to the new prototype * 3. For plain object members, performs deep merge with base class members using $.extend * 4. Sets up the extend method on the subclass for further inheritance * * @param proto - Object containing methods and properties for the subclass * @returns New constructor function for the subclass * * @example * var MyClass = Class.extend({ * init: function(options) { * this.options = options; * }, * myMethod: function() { * return this.options; * } * }); * * var instance = new MyClass({ foo: 'bar' }); */ static extend(proto) { const that = this; const base = function() {}; base.prototype = that.prototype; const subclass = proto && proto.init ? proto.init : function(...args) { if (that.prototype.init) { that.prototype.init.apply(this, args); } }; const fn = subclass.fn = subclass.prototype = new base(); if (proto) { for (const member in proto) { if (proto[member] != null && proto[member].constructor === Object) { fn[member] = kendoJQueryService.getConstructor().extend(true, {}, base.prototype[member], proto[member]); } else { fn[member] = proto[member]; } } } fn.constructor = subclass; subclass.extend = that.extend; return subclass; } }; Class.fn = Class.prototype; /** * Define init and _initOptions on the prototype as ENUMERABLE properties. * * ES6 class methods are non-enumerable by default, which breaks the * legacy extend() pattern because when we do: * base.prototype = that.prototype; * fn = new base(); * * The inherited methods from the ES6 class prototype don't appear in * for...in loops or when the object is logged/inspected. This causes * issues when deepExtend copies class instances - the non-enumerable * methods are not properly inherited through the prototype chain. * * By defining these methods directly on the prototype (like the original * Kendo Class did), we ensure they're enumerable and properly inherited. */ Class.prototype.init = function(..._args) {}; Class.prototype._initOptions = function(options) { this.options = kendoJQueryService.getConstructor().extend(true, {}, this.options, options); }; //#endregion //#region ../src/core/base/observable.ts /** * Kendo UI Observable Class * * Provides event binding, unbinding, and triggering functionality. * This is the foundation for all event-driven components in Kendo UI. * * Extends Class and supports both ES6 and legacy extend() patterns. * * * @example * // ES6 class inheritance * class MyComponent extends Observable { * doSomething() { * this.trigger("change", { value: 42 }); * } * } * * @example * // Legacy extend pattern * const MyComponent = Observable.extend({ * init: function() { * Observable.fn.init.call(this); * this.value = 0; * }, * setValue: function(val) { * this.value = val; * this.trigger("change", { value: val }); * } * }); * * const component = new MyComponent(); * component.bind("change", function(e) { * console.log("Value changed to:", e.value); * }); * component.setValue(42); */ const STRING$4 = "string"; const FUNCTION$2 = "function"; /** * preventDefault helper function. * Called on event object to prevent default action. * Uses regular function to preserve `this` context (the event object). */ function preventDefault() { this._defaultPrevented = true; } /** * isDefaultPrevented helper function. * Called on event object to check if default was prevented. * Uses regular function to preserve `this` context (the event object). */ function isDefaultPrevented() { return this._defaultPrevented === true; } /** * Observable class for event handling. * All Kendo UI widgets and data components inherit from this class. */ var Observable = class extends Class { /** * Constructor - initializes the Observable's _events storage. */ constructor() { super(); this._events = {}; } /** * Initialize the Observable instance. * Sets up the internal _events storage. * Accepts any arguments to allow subclasses to override with different signatures. * * Note: For direct Observable usage, this is called by the constructor. * For subclasses, they should call Observable.fn.init.call(this) in their init. */ init(..._args) { this._events = {}; } /** * Binds one or more event handlers to the observable. * * Supports multiple calling patterns: * - bind("event", handler) * - bind(["event1", "event2"], handler) * - bind({ event1: handler1, event2: handler2 }) * - bind("event", handler, true) // one-time binding * * @param eventName - Event name, array of names, or object map * @param handlers - Handler function or map of handlers * @param one - If true, handler is removed after first invocation * @returns this for chaining */ bind(eventName, handlers, one) { const that = this; let idx; let length; let original; let handler; const handlersIsFunction = typeof handlers === FUNCTION$2; let events; if (handlers === undefined) { const eventMap = eventName; for (idx in eventMap) { that.bind(idx, eventMap[idx]); } return that; } const eventNames = typeof eventName === STRING$4 ? [eventName] : eventName; for (idx = 0, length = eventNames.length; idx < length; idx++) { const currentEventName = eventNames[idx]; handler = handlersIsFunction ? handlers : handlers[currentEventName]; if (handler) { if (one) { original = handler; handler = (function(evtName, originalHandler) { const wrappedHandler = function() { that.unbind(evtName, wrappedHandler); originalHandler.apply(that, arguments); }; wrappedHandler.original = originalHandler; return wrappedHandler; })(currentEventName, original); } events = that._events[currentEventName] = that._events[currentEventName] || []; events.push(handler); } } return that; } /** * Binds an event handler that will be removed after first invocation. * * @param eventNames - Event name or array of names * @param handlers - Handler function or map of handlers * @returns this for chaining */ one(eventNames, handlers) { return this.bind(eventNames, handlers, true); } /** * Binds an event handler at the beginning of the handler list. * The handler will be invoked before other handlers. * * @param eventName - Event name or array of names * @param handlers - Handler function or map of handlers * @returns this for chaining */ first(eventName, handlers) { const that = this; let idx; const eventNames = typeof eventName === STRING$4 ? [eventName] : eventName; const length = eventNames.length; let handler; const handlersIsFunction = typeof handlers === FUNCTION$2; let events; for (idx = 0; idx < length; idx++) { const currentEventName = eventNames[idx]; handler = handlersIsFunction ? handlers : handlers[currentEventName]; if (handler) { events = that._events[currentEventName] = that._events[currentEventName] || []; events.unshift(handler); } } return that; } /** * Triggers an event, invoking all bound handlers. * * @param eventName - Name of the event to trigger * @param e - Optional event data object * @returns true if preventDefault() was called, false otherwise */ trigger(eventName, e) { const that = this; let events = that._events[eventName]; let idx; const length = events ? events.length : 0; if (events) { const eventObj = e || {}; eventObj.sender = that; eventObj._defaultPrevented = false; eventObj.preventDefault = preventDefault; eventObj.isDefaultPrevented = isDefaultPrevented; events = events.slice(); for (idx = 0; idx < length; idx++) { events[idx].call(that, eventObj); } return eventObj._defaultPrevented === true; } return false; } /** * Unbinds event handlers. * * - unbind() - removes all handlers for all events * - unbind("event") - removes all handlers for specific event * - unbind("event", handler) - removes specific handler * * @param eventName - Optional event name * @param handler - Optional specific handler to remove * @returns this for chaining */ unbind(eventName, handler) { const that = this; const events = eventName ? that._events[eventName] : undefined; let idx; if (eventName === undefined) { that._events = {}; } else if (events) { if (handler) { for (idx = events.length - 1; idx >= 0; idx--) { if (events[idx] === handler || events[idx].original === handler) { events.splice(idx, 1); } } } else { that._events[eventName] = []; } } return that; } }; /** * Make Observable methods ENUMERABLE by deleting and reassigning them. * * ES6 class methods are non-enumerable by default, which breaks legacy patterns * like `$.extend({}, observableInstance, ...)` which copies properties using * for...in loops. By deleting and reassigning, we create enumerable properties. */ const proto = Observable.prototype; const methods = [ "init", "bind", "one", "first", "trigger", "unbind" ]; methods.forEach((method) => { const fn = proto[method]; Object.defineProperty(proto, method, { value: fn, writable: true, configurable: true, enumerable: true }); }); Observable.fn = Observable.prototype; //#endregion //#region ../src/core/services/namespace.service.ts var NamespaceService = class { constructor() { this._ns = ""; } /** * Get the current namespace prefix */ get ns() { return this._ns; } /** * Set the namespace prefix * @param value - The namespace prefix (e.g., "kendo-") */ setNs(value) { this._ns = value; } }; const namespaceService = new NamespaceService(); //#endregion //#region ../src/core/services/dom-utils.service.ts const PERCENT_REGEXP = /%/; const BOX_SHADOW_REGEXP = /(\d+(?:\.?)\d*)px\s*(\d+(?:\.?)\d*)px\s*(\d+(?:\.?)\d*)px\s*(\d+)?/i; /** * Service providing DOM utility functions */ var DomUtilsService = class { constructor() { this.animationQueue = []; const win = window; this.animationFrameFn = win.requestAnimationFrame || win.webkitRequestAnimationFrame || win.mozRequestAnimationFrame || win.oRequestAnimationFrame || win.msRequestAnimationFrame || ((callback) => { setTimeout(callback, 1e3 / 60); }); } isElement(element) { return element instanceof Element || element instanceof HTMLDocument; } /** * Get outer width of element */ outerWidth(element, includeMargin, calculateFromHidden) { const $element = $(element); if (calculateFromHidden) { return this.getHiddenDimensions($element, includeMargin).width; } return $element.outerWidth(includeMargin || false) || 0; } /** * Get outer height of element */ outerHeight(element, includeMargin, calculateFromHidden) { const $element = $(element); if (calculateFromHidden) { return this.getHiddenDimensions($element, includeMargin).height; } return $element.outerHeight(includeMargin || false) || 0; } /** * Get computed styles for an element */ getComputedStyles(element, properties) { const styles = {}; let computedStyle; if (document.defaultView && document.defaultView.getComputedStyle) { computedStyle = document.defaultView.getComputedStyle(element, ""); if (properties) { $.each(properties, (_idx, value) => { styles[value] = computedStyle.getPropertyValue(value); }); } } else { computedStyle = element.currentStyle; if (properties) { $.each(properties, (_idx, value) => { styles[value] = computedStyle[utilsService.toCamelCase(valu