if (!Element.prototype.matches) {
Element.prototype.matches =
Element.prototype.msMatchesSelector ||
Element.prototype.webkitMatchesSelector;
}
if (!Element.prototype.closest) {
Element.prototype.closest = function (s) {
var el = this;
do {
if (el.matches(s)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
};
}
var resolveCallbacks = [];
var rejectCallbacks = [];
var radzenRecognition;
window.Radzen = {
isRTL: function (el) {
return el && getComputedStyle(el).direction == 'rtl';
},
throttle: function (callback, delay) {
var timeout = null;
return function () {
var args = arguments;
var ctx = this;
if (!timeout) {
timeout = setTimeout(function () {
callback.apply(ctx, args);
timeout = null;
}, delay);
}
};
},
downloadFile: function (fileName, data, mimeType) {
const blob = new Blob([data], { type: mimeType });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
a.click();
URL.revokeObjectURL(url);
},
mask: function (id, mask, pattern, characterPattern) {
var el = document.getElementById(id);
if (el) {
var format = function (value, mask, pattern, characterPattern) {
var chars = !characterPattern ? value.replace(new RegExp(pattern, "g"), "").split('') : value.match(new RegExp(characterPattern, "g"));
var count = 0;
var formatted = '';
for (var i = 0; i < mask.length; i++) {
const c = mask[i];
if (chars && chars[count]) {
if (c === '*' || c == chars[count]) {
formatted += chars[count];
count++;
} else {
formatted += c;
}
}
}
return formatted;
}
if (window.safari !== undefined) {
el.onblur = function (e) {
el.dispatchEvent(new Event('change'));
};
}
var start = el.selectionStart != el.value.length ? el.selectionStart : -1;
var end = el.selectionEnd != el.value.length ? el.selectionEnd : -1;
el.value = format(el.value, mask, pattern, characterPattern);
el.selectionStart = start != -1 ? start : el.selectionStart;
el.selectionEnd = end != -1 ? end : el.selectionEnd;
}
},
addContextMenu: function (id, ref) {
var el = document.getElementById(id);
if (el) {
var handler = function (e) {
e.stopPropagation();
e.preventDefault();
try {
ref.invokeMethodAsync('RadzenComponent.RaiseContextMenu',
{
ClientX: e.clientX,
ClientY: e.clientY,
ScreenX: e.screenX,
ScreenY: e.screenY,
AltKey: e.altKey,
ShiftKey: e.shiftKey,
CtrlKey: e.ctrlKey,
MetaKey: e.metaKey,
Button: e.button,
Buttons: e.buttons,
});
} catch { }
return false;
};
Radzen[id + 'contextmenu'] = handler;
el.addEventListener('contextmenu', handler, false);
}
},
addMouseEnter: function (id, ref) {
var el = document.getElementById(id);
if (el) {
var handler = function (e) {
try { ref.invokeMethodAsync('RadzenComponent.RaiseMouseEnter'); } catch { }
};
Radzen[id + 'mouseenter'] = handler;
el.addEventListener('mouseenter', handler, false);
}
},
addMouseLeave: function (id, ref) {
var el = document.getElementById(id);
if (el) {
var handler = function (e) {
try { ref.invokeMethodAsync('RadzenComponent.RaiseMouseLeave'); } catch { }
};
Radzen[id + 'mouseleave'] = handler;
el.addEventListener('mouseleave', handler, false);
}
},
removeContextMenu: function (id) {
var el = document.getElementById(id);
if (el && Radzen[id + 'contextmenu']) {
el.removeEventListener('contextmenu', Radzen[id + 'contextmenu']);
}
},
removeMouseEnter: function (id) {
var el = document.getElementById(id);
if (el && Radzen[id + 'mouseenter']) {
el.removeEventListener('mouseenter', Radzen[id + 'mouseenter']);
}
},
removeMouseLeave: function (id) {
var el = document.getElementById(id);
if (el && Radzen[id + 'mouseleave']) {
el.removeEventListener('mouseleave', Radzen[id + 'mouseleave']);
}
},
adjustDataGridHeader: function (scrollableHeader, scrollableBody) {
if (scrollableHeader && scrollableBody) {
scrollableHeader.style.cssText =
scrollableBody.clientHeight < scrollableBody.scrollHeight
? 'margin-left:0px;padding-right: ' +
(scrollableBody.offsetWidth - scrollableBody.clientWidth) +
'px'
: 'margin-left:0px;';
}
},
ganttSyncScroll: function (ganttId) {
if (!ganttId) {
return;
}
var root = document.getElementById(ganttId);
if (!root) {
return;
}
var grid = root.querySelector('.rz-data-grid-data');
var timeline = root.querySelector('.rz-gantt-timeline-scroll');
if (!grid || !timeline) {
return;
}
var header = root.querySelector('.rz-gantt-table thead');
if (header) {
root.style.setProperty('--rz-gantt-header-height', header.getBoundingClientRect().height + 'px');
}
// Measure timeline group header and set CSS variable so the grid's
// thead::before pseudo-row matches it. Also sync overall header height.
function syncHeaderHeights() {
var gridThead = grid.querySelector('thead');
var timelineThead = timeline.querySelector('thead');
if (!gridThead || !timelineThead) return;
var groupRow = timelineThead.querySelector('.rz-gantt-header-group-row');
if (groupRow) {
root.style.setProperty('--rz-gantt-header-group-height', groupRow.offsetHeight + 'px');
} else {
root.style.setProperty('--rz-gantt-header-group-height', '0px');
}
var maxH = Math.max(gridThead.offsetHeight, timelineThead.offsetHeight);
root.style.setProperty('--rz-gantt-header-height', maxH + 'px');
}
function runSyncAfterLayout() {
requestAnimationFrame(function () {
requestAnimationFrame(syncHeaderHeights);
});
}
runSyncAfterLayout();
var key = ganttId + '_ganttScrollSync';
var state = Radzen[key];
if (state && state.grid === grid && state.timeline === timeline) {
return;
}
if (state) {
if (state.grid && state.onGrid) {
state.grid.removeEventListener('scroll', state.onGrid);
}
if (state.timeline && state.onTimeline) {
state.timeline.removeEventListener('scroll', state.onTimeline);
}
if (state.grid && state.onGridWheel) {
state.grid.removeEventListener('wheel', state.onGridWheel);
}
}
var syncing = false;
var onGrid = function () {
if (syncing) {
return;
}
syncing = true;
timeline.scrollTop = grid.scrollTop;
syncing = false;
};
var onTimeline = function () {
if (syncing) {
return;
}
syncing = true;
grid.scrollTop = timeline.scrollTop;
syncing = false;
};
// The grid has overflow-y: hidden (no native vertical scrollbar).
// Forward vertical mouse-wheel events to the timeline so the user
// can still scroll vertically while hovering over the grid.
var onGridWheel = function (e) {
if (e.deltaY) {
timeline.scrollTop += e.deltaY;
e.preventDefault();
}
};
grid.addEventListener('scroll', onGrid);
timeline.addEventListener('scroll', onTimeline);
grid.addEventListener('wheel', onGridWheel, { passive: false });
var resizeObserver = null;
if (typeof ResizeObserver !== 'undefined') {
resizeObserver = new ResizeObserver(runSyncAfterLayout);
resizeObserver.observe(root);
}
Radzen[key] = {
grid: grid,
timeline: timeline,
onGrid: onGrid,
onTimeline: onTimeline,
onGridWheel: onGridWheel,
resizeObserver: resizeObserver
};
timeline.scrollTop = grid.scrollTop;
},
ganttScrollToFirstEvent: function (ganttId) {
if (!ganttId) return false;
var root = document.getElementById(ganttId);
if (!root) return false;
var timeline = root.querySelector('.rz-gantt-timeline-scroll');
if (!timeline) return false;
var events = timeline.querySelectorAll('.rz-event');
if (!events.length) return false;
var timelineRect = timeline.getBoundingClientRect();
var thead = timeline.querySelector('thead');
var headerHeight = thead ? thead.offsetHeight : 0;
var bestTop = Infinity;
var bestLeft = Infinity;
for (var i = 0; i < events.length; i++) {
var rect = events[i].getBoundingClientRect();
if (rect.width <= 0) continue;
var contentTop = rect.top - timelineRect.top + timeline.scrollTop;
var contentLeft = rect.left - timelineRect.left + timeline.scrollLeft;
if (contentTop < bestTop || (contentTop === bestTop && contentLeft < bestLeft)) {
bestTop = contentTop;
bestLeft = contentLeft;
}
}
if (bestTop === Infinity) return false;
timeline.scrollTop = Math.max(0, bestTop - headerHeight - 4);
timeline.scrollLeft = Math.max(0, bestLeft - 40);
return true;
},
ganttSyncScrollDispose: function (ganttId) {
if (!ganttId) {
return;
}
var key = ganttId + '_ganttScrollSync';
var state = Radzen[key];
if (!state) {
return;
}
if (state.grid && state.onGrid) {
state.grid.removeEventListener('scroll', state.onGrid);
}
if (state.timeline && state.onTimeline) {
state.timeline.removeEventListener('scroll', state.onTimeline);
}
if (state.grid && state.onGridWheel) {
state.grid.removeEventListener('wheel', state.onGridWheel);
}
if (state.resizeObserver) {
state.resizeObserver.disconnect();
}
delete Radzen[key];
},
ganttInitDragResize: function (containerId, dotnetRef, timelineRangeMs, allowDrag, allowResize, rowHeightPx) {
var key = containerId + '_ganttDragResize';
if (Radzen[key]) {
Radzen[key].dotnetRef = dotnetRef;
Radzen[key].timelineRangeMs = timelineRangeMs;
Radzen[key].allowDrag = allowDrag;
Radzen[key].allowResize = allowResize;
Radzen[key].rowHeightPx = rowHeightPx || 36;
return;
}
var root = document.getElementById(containerId);
if (!root) return;
var container = root.querySelector('.rz-gantt-timeline-scroll');
if (!container) return;
var resizeThreshold = 6;
var dragThreshold = 3;
var drag = null;
var justDragged = false;
function getConfig() {
return Radzen[key];
}
function buildLinkPath(x1, x2, y1, y2, rh, linkType) {
var offset = 12;
var halfRow = rh * 0.5;
var exitRight = linkType === 0 || linkType === 2;
var enterRight = linkType === 2 || linkType === 3;
var exitDir = exitRight ? 1 : -1;
var enterDir = enterRight ? 1 : -1;
var exitX = x1 + offset * exitDir;
var enterX = x2 + offset * enterDir;
var canGoStraight = exitRight !== enterRight
? (exitRight ? x2 - x1 > offset * 2 : x1 - x2 > offset * 2)
: (exitRight ? exitX < enterX : exitX > enterX);
if (canGoStraight && y1 !== y2) {
var midX = (exitX + enterX) / 2;
return 'M' + x1 + ',' + y1 + ' L' + midX + ',' + y1 + ' L' + midX + ',' + y2 + ' L' + x2 + ',' + y2;
}
var midY = y2 > y1 ? y1 + halfRow : (y2 < y1 ? y1 - halfRow : y1 + halfRow);
return 'M' + x1 + ',' + y1 + ' L' + exitX + ',' + y1 + ' L' + exitX + ',' + midY + ' L' + enterX + ',' + midY + ' L' + enterX + ',' + y2 + ' L' + x2 + ',' + y2;
}
function updateConnectedPaths() {
if (!drag) return;
var svg = container.querySelector('.rz-gantt-links');
if (!svg) return;
var config = getConfig();
var rh = config.rowHeightPx;
var svgWidth = svg.getBoundingClientRect().width;
var idx = drag.index;
var paths = svg.querySelectorAll('path[data-from-index="' + idx + '"], path[data-to-index="' + idx + '"]');
for (var i = 0; i < paths.length; i++) {
var path = paths[i];
var fromIdx = path.dataset.fromIndex;
var toIdx = path.dataset.toIndex;
var linkType = parseInt(path.dataset.linkType, 10) || 0;
var fromBar = container.querySelector('[data-index="' + fromIdx + '"]');
var toBar = container.querySelector('[data-index="' + toIdx + '"]');
if (!fromBar || !toBar) continue;
var fromRow = parseInt(fromBar.dataset.row, 10);
var toRow = parseInt(toBar.dataset.row, 10);
var fromLeft = parseFloat(fromBar.style.getPropertyValue('inset-inline-start')) || 0;
var fromWidth = parseFloat(fromBar.style.width) || 0;
var toLeft = parseFloat(toBar.style.getPropertyValue('inset-inline-start')) || 0;
var toWidth = parseFloat(toBar.style.width) || 0;
var fromIsMilestone = fromBar.classList.contains('rz-gantt-milestone');
var toIsMilestone = toBar.classList.contains('rz-gantt-milestone');
var x1, x2;
if (linkType === 1) { x1 = fromLeft; x2 = toLeft; }
else if (linkType === 2) { x1 = fromIsMilestone ? fromLeft : fromLeft + fromWidth; x2 = toIsMilestone ? toLeft : toLeft + toWidth; }
else if (linkType === 3) { x1 = fromLeft; x2 = toIsMilestone ? toLeft : toLeft + toWidth; }
else { x1 = fromIsMilestone ? fromLeft : fromLeft + fromWidth; x2 = toLeft; }
var x1px = (x1 / 100) * svgWidth;
var x2px = (x2 / 100) * svgWidth;
var y1 = (fromRow + 0.5) * rh;
var y2 = (toRow + 0.5) * rh;
path.setAttribute('d', buildLinkPath(x1px, x2px, y1, y2, rh, linkType));
}
}
function onMouseDown(e) {
var config = getConfig();
if (!config) return;
var bar = e.target.closest('.rz-gantt-bar, .rz-gantt-milestone');
if (!bar || e.button !== 0 || !bar.dataset.index) return;
var isMilestone = bar.classList.contains('rz-gantt-milestone');
var barRect = bar.getBoundingClientRect();
var offsetX = e.clientX - barRect.left;
var mode;
if (isMilestone) {
if (!config.allowDrag) return;
mode = 'move';
} else if (config.allowResize && offsetX <= resizeThreshold) {
mode = 'resize-start';
} else if (config.allowResize && barRect.width - offsetX <= resizeThreshold) {
mode = 'resize-end';
} else if (config.allowDrag) {
mode = 'move';
} else {
return;
}
e.preventDefault();
var containerEl = bar.closest('.rz-gantt-row-container');
var containerWidth = containerEl ? containerEl.getBoundingClientRect().width : 1;
drag = {
bar: bar,
mode: mode,
startClientX: e.clientX,
containerWidth: containerWidth,
originalLeft: parseFloat(bar.style.getPropertyValue('inset-inline-start')) || 0,
originalWidth: parseFloat(bar.style.width) || 0,
offsetStart: parseFloat(bar.dataset.offsetStart) || 0,
offsetEnd: parseFloat(bar.dataset.offsetEnd) || 0,
index: parseInt(bar.dataset.index, 10),
isMilestone: isMilestone,
hasMoved: false
};
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
}
function onMouseMove(e) {
if (!drag) return;
var deltaX = e.clientX - drag.startClientX;
if (!drag.hasMoved && Math.abs(deltaX) < dragThreshold) return;
drag.hasMoved = true;
var percentDelta = (deltaX / drag.containerWidth) * 100;
if (drag.mode === 'move') {
drag.bar.style.setProperty('inset-inline-start', (drag.originalLeft + percentDelta) + '%');
} else if (drag.mode === 'resize-start') {
var newWidth = drag.originalWidth - percentDelta;
if (newWidth > 0.1) {
drag.bar.style.setProperty('inset-inline-start', (drag.originalLeft + percentDelta) + '%');
drag.bar.style.width = newWidth + '%';
}
} else if (drag.mode === 'resize-end') {
var newWidth = drag.originalWidth + percentDelta;
if (newWidth > 0.1) {
drag.bar.style.width = newWidth + '%';
}
}
drag.bar.style.zIndex = '10';
drag.bar.style.opacity = '0.85';
document.body.style.cursor = drag.mode === 'move' ? 'grabbing' : 'ew-resize';
updateConnectedPaths();
}
function onMouseUp(e) {
if (!drag) return;
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
drag.bar.style.zIndex = '';
drag.bar.style.opacity = '';
document.body.style.cursor = '';
if (drag.hasMoved) {
justDragged = true;
var deltaX = e.clientX - drag.startClientX;
var percentDelta = (deltaX / drag.containerWidth) * 100;
var config = getConfig();
var msPerPercent = config.timelineRangeMs / 100;
var deltaMs = percentDelta * msPerPercent;
var newStartMs, newEndMs;
if (drag.mode === 'move') {
newStartMs = drag.offsetStart + deltaMs;
newEndMs = drag.offsetEnd + deltaMs;
} else if (drag.mode === 'resize-start') {
newStartMs = drag.offsetStart + deltaMs;
newEndMs = drag.offsetEnd;
} else {
newStartMs = drag.offsetStart;
newEndMs = drag.offsetEnd + deltaMs;
}
var eventType = drag.mode === 'move' ? 'move' : 'resize';
config.dotnetRef.invokeMethodAsync('OnGanttBarInteractionEnd', drag.index, eventType, newStartMs, newEndMs);
}
drag = null;
}
function onMouseMoveHover(e) {
if (drag) return;
var config = getConfig();
if (!config) return;
var bar = e.target.closest('.rz-gantt-bar, .rz-gantt-milestone');
if (!bar || !bar.dataset.index) return;
if (bar.classList.contains('rz-gantt-milestone')) {
bar.style.cursor = config.allowDrag ? 'grab' : '';
return;
}
var barRect = bar.getBoundingClientRect();
var offsetX = e.clientX - barRect.left;
if (config.allowResize && (offsetX <= resizeThreshold || barRect.width - offsetX <= resizeThreshold)) {
bar.style.cursor = 'ew-resize';
} else if (config.allowDrag) {
bar.style.cursor = 'grab';
}
}
function onClickCapture(e) {
if (justDragged) {
e.stopPropagation();
e.preventDefault();
justDragged = false;
}
}
container.addEventListener('mousedown', onMouseDown);
container.addEventListener('mousemove', onMouseMoveHover);
container.addEventListener('click', onClickCapture, true);
Radzen[key] = {
container: container,
dotnetRef: dotnetRef,
timelineRangeMs: timelineRangeMs,
allowDrag: allowDrag,
allowResize: allowResize,
rowHeightPx: rowHeightPx || 36,
onMouseDown: onMouseDown,
onMouseMoveHover: onMouseMoveHover,
onClickCapture: onClickCapture
};
},
ganttDisposeDragResize: function (containerId) {
var key = containerId + '_ganttDragResize';
var config = Radzen[key];
if (!config) return;
config.container.removeEventListener('mousedown', config.onMouseDown);
config.container.removeEventListener('mousemove', config.onMouseMoveHover);
config.container.removeEventListener('click', config.onClickCapture, true);
delete Radzen[key];
},
preventDefaultAndStopPropagation: function (e) {
e.preventDefault();
e.stopPropagation();
},
preventArrows: function (el) {
var preventDefault = function (e) {
if (e.keyCode === 38 || e.keyCode === 40) {
e.preventDefault();
return false;
}
};
if (el) {
el.addEventListener('keydown', preventDefault, false);
}
},
selectTab: function (id, index) {
var el = document.getElementById(id);
if (el && el.parentNode && el.parentNode.previousElementSibling) {
var tablist = el.parentNode.previousElementSibling;
var count = el.parentNode.children.length;
for (var i = 0; i < count; i++) {
var content = el.parentNode.children[i];
if (content) {
content.style.display = i == index ? '' : 'none';
content.setAttribute('aria-hidden', i == index ? 'false' : 'true');
}
var header = tablist.children[i];
if (header) {
var btn = header.querySelector('[role="tab"]') || header;
if (i == index) {
header.classList.add('rz-tabview-selected');
header.classList.add('rz-state-focused');
btn.setAttribute('aria-selected', 'true');
}
else {
header.classList.remove('rz-tabview-selected');
header.classList.remove('rz-state-focused');
btn.setAttribute('aria-selected', 'false');
}
}
}
if (tablist.getAttribute && tablist.getAttribute('role') === 'tablist') {
var activeBtn = tablist.children[index] && (tablist.children[index].querySelector('[role="tab"]') || tablist.children[index]);
if (activeBtn && activeBtn.id) {
tablist.setAttribute('aria-activedescendant', activeBtn.id);
}
}
}
},
createAccordion: function (el, multiple) {
function getItems() {
var headers = [];
var expanders = [];
for (var i = 0; i < el.children.length; i++) {
var child = el.children[i];
if (child.classList.contains('rz-accordion-header')) {
headers.push(child);
} else if (child.classList.contains('rz-expander')) {
expanders.push(child);
}
}
return { headers: headers, expanders: expanders };
}
function toggleItem(index, expanded) {
var items = getItems();
if (index < 0 || index >= items.headers.length) return;
if (!multiple) {
for (var i = 0; i < items.headers.length; i++) {
if (i !== index) {
var btn = items.headers[i].querySelector('button');
var icon = items.headers[i].querySelector('.rz-accordion-toggle-icon');
if (btn) btn.setAttribute('aria-expanded', 'false');
if (icon) {
icon.classList.remove('rz-state-expanded');
icon.classList.add('rz-state-collapsed');
}
items.expanders[i].classList.remove('rz-state-expanded');
items.expanders[i].classList.add('rz-state-collapsed');
items.expanders[i].setAttribute('aria-hidden', 'true');
}
}
}
var button = items.headers[index].querySelector('button');
var toggleIcon = items.headers[index].querySelector('.rz-accordion-toggle-icon');
if (button) button.setAttribute('aria-expanded', expanded ? 'true' : 'false');
if (toggleIcon) {
toggleIcon.classList.remove(expanded ? 'rz-state-collapsed' : 'rz-state-expanded');
toggleIcon.classList.add(expanded ? 'rz-state-expanded' : 'rz-state-collapsed');
}
items.expanders[index].classList.remove(expanded ? 'rz-state-collapsed' : 'rz-state-expanded');
items.expanders[index].classList.add(expanded ? 'rz-state-expanded' : 'rz-state-collapsed');
items.expanders[index].setAttribute('aria-hidden', expanded ? 'false' : 'true');
}
return {
toggle: function (index, expanded) { toggleItem(index, expanded); },
setMultiple: function (value) { multiple = value; },
dispose: function () { }
};
},
loadGoogleMaps: function (defaultView, apiKey, resolve, reject, language) {
resolveCallbacks.push(resolve);
rejectCallbacks.push(reject);
if (defaultView['rz_map_init']) {
return;
}
defaultView['rz_map_init'] = function () {
for (var i = 0; i < resolveCallbacks.length; i++) {
resolveCallbacks[i](defaultView.google);
}
};
var document = defaultView.document;
var script = document.createElement('script');
script.src =
'https://maps.googleapis.com/maps/api/js?' +
(language ? 'language=' + language + '&' : '') +
(apiKey ? 'key=' + apiKey + '&' : '') +
'callback=rz_map_init&libraries=marker';
script.async = true;
script.defer = true;
script.onerror = function (err) {
for (var i = 0; i < rejectCallbacks.length; i++) {
rejectCallbacks[i](err);
}
};
document.body.appendChild(script);
},
createMap: function (wrapper, ref, id, apiKey, mapId, zoom, center, markers, options, fitBoundsToMarkersOnUpdate, language) {
var api = function () {
var defaultView = document.defaultView;
return new Promise(function (resolve, reject) {
if (defaultView.google && defaultView.google.maps) {
return resolve(defaultView.google);
}
Radzen.loadGoogleMaps(defaultView, apiKey, resolve, reject, language);
});
};
api().then(function (google) {
Radzen[id] = ref;
Radzen[id].google = google;
Radzen[id].instance = new google.maps.Map(wrapper, {
center: center,
zoom: zoom,
mapId: mapId
});
Radzen[id].instance.addListener('click', function (e) {
try { Radzen[id].invokeMethodAsync('RadzenGoogleMap.OnMapClick', {
Position: {Lat: e.latLng.lat(), Lng: e.latLng.lng()}
}); } catch { }
});
Radzen.updateMap(id, apiKey, zoom, center, markers, options, fitBoundsToMarkersOnUpdate, language);
});
},
updateMap: function (id, apiKey, zoom, center, markers, options, fitBoundsToMarkersOnUpdate, language) {
var api = function () {
var defaultView = document.defaultView;
return new Promise(function (resolve, reject) {
if (defaultView.google && defaultView.google.maps) {
return resolve(defaultView.google);
}
Radzen.loadGoogleMaps(defaultView, apiKey, resolve, reject, language);
});
};
api().then(function (google) {
let markerBounds = new google.maps.LatLngBounds();
if (Radzen[id] && Radzen[id].instance) {
if (Radzen[id].instance.markers && Radzen[id].instance.markers.length) {
for (var i = 0; i < Radzen[id].instance.markers.length; i++) {
Radzen[id].instance.markers[i].setMap(null);
}
}
if (markers) {
Radzen[id].instance.markers = [];
markers.forEach(function (m) {
var content;
if (m.label) {
content = document.createElement('span');
content.innerHTML = m.label;
}
var marker = new this.google.maps.marker.AdvancedMarkerElement({
position: m.position,
title: m.title,
content: content
});
marker.addListener('click', function (e) {
try { Radzen[id].invokeMethodAsync('RadzenGoogleMap.OnMarkerClick', {
Title: marker.title,
Label: marker.content.innerText,
Position: marker.position
}); } catch { }
});
marker.setMap(Radzen[id].instance);
Radzen[id].instance.markers.push(marker);
markerBounds.extend(marker.position);
});
}
if (zoom) {
Radzen[id].instance.setZoom(zoom);
}
if (center) {
Radzen[id].instance.setCenter(center);
}
if (options) {
Radzen[id].instance.setOptions(options);
}
if (markers && fitBoundsToMarkersOnUpdate) {
Radzen[id].instance.fitBounds(markerBounds);
}
}
});
},
destroyMap: function (id) {
if (Radzen[id].instance) {
delete Radzen[id].instance;
}
},
focusSecurityCode: function (el) {
if (!el) return;
var firstInput = el.querySelector('.rz-security-code-input');
if (firstInput) {
setTimeout(function () { firstInput.focus() }, 500);
}
},
destroySecurityCode: function (id, el) {
if (!Radzen[id]) return;
var inputs = el.getElementsByTagName('input');
if (Radzen[id].keyPress && Radzen[id].keyDown && Radzen[id].paste) {
var isAndroid = navigator.userAgent.match(/Android/i);
for (var i = 0; i < inputs.length; i++) {
inputs[i].removeEventListener(isAndroid ? 'textInput' : 'keypress', Radzen[id].keyPress);
inputs[i].removeEventListener('keydown', Radzen[id].keyDown);
inputs[i].removeEventListener('paste', Radzen[id].paste);
}
delete Radzen[id].keyPress;
delete Radzen[id].keyDown;
delete Radzen[id].paste;
}
Radzen[id] = null;
},
createSecurityCode: function (id, ref, el, isNumber) {
if (!el || !ref) return;
var hidden = el.querySelector('input[type="hidden"]');
Radzen[id] = {};
Radzen[id].inputs = [...el.querySelectorAll('.rz-security-code-input')];
var isAndroid = navigator.userAgent.match(/Android/i);
Radzen[id].paste = function (e) {
if (e.clipboardData) {
var value = e.clipboardData.getData('text');
if (value) {
for (var i = 0; i < Math.min(value.length, Radzen[id].inputs.length); i++) {
if (isNumber && isNaN(+value[i])) {
continue;
}
Radzen[id].inputs[i].value = value[i];
}
var code = Radzen[id].inputs.map(i => i.value).join('').trim();
hidden.value = code;
try { ref.invokeMethodAsync('RadzenSecurityCode.OnValueChange', code); } catch { }
Radzen[id].inputs[Radzen[id].inputs.length - 1].focus();
}
e.preventDefault();
}
}
Radzen[id].keyPress = function (e) {
var keyCode = e.data ? e.data.charCodeAt(0) : e.which;
var ch = e.data || String.fromCharCode(e.which);
if (e.metaKey ||
e.ctrlKey ||
keyCode == 9 ||
keyCode == 8 ||
keyCode == 13
) {
return;
}
if (isNumber && (keyCode < 48 || keyCode > 57)) {
e.preventDefault();
return;
}
// Android-specific: prevent default to avoid double input
if (isAndroid && e.type === 'textInput') {
e.preventDefault();
}
if (e.currentTarget.value == ch) {
return;
}
e.currentTarget.value = ch;
var value = Radzen[id].inputs.map(i => i.value).join('').trim();
hidden.value = value;
try { ref.invokeMethodAsync('RadzenSecurityCode.OnValueChange', value); } catch { }
var index = Radzen[id].inputs.indexOf(e.currentTarget);
if (index < Radzen[id].inputs.length - 1) {
Radzen[id].inputs[index + 1].focus();
}
}
Radzen[id].keyDown = function (e) {
var keyCode = e.which || e.keyCode;
if (keyCode == 8) {
e.currentTarget.value = '';
var value = Radzen[id].inputs.map(i => i.value).join('').trim();
hidden.value = value;
try { ref.invokeMethodAsync('RadzenSecurityCode.OnValueChange', value); } catch { }
var index = Radzen[id].inputs.indexOf(e.currentTarget);
if (index > 0) {
Radzen[id].inputs[index - 1].focus();
}
}
}
for (var i = 0; i < Radzen[id].inputs.length; i++) {
Radzen[id].inputs[i].addEventListener(isAndroid ? 'textInput' : 'keypress', Radzen[id].keyPress);
Radzen[id].inputs[i].addEventListener('keydown', Radzen[id].keyDown);
Radzen[id].inputs[i].addEventListener('paste', Radzen[id].paste);
}
},
createSlider: function (
id,
slider,
parent,
range,
minHandle,
maxHandle,
min,
max,
value,
step,
isVertical
) {
Radzen[id] = {};
Radzen[id].mouseMoveHandler = function (e) {
e.preventDefault();
var handle = slider.isMin ? minHandle : maxHandle;
if (!slider.canChange) return;
var offsetX =
e.targetTouches && e.targetTouches[0]
? e.targetTouches[0].pageX - e.target.getBoundingClientRect().left
: e.pageX - handle.getBoundingClientRect().left;
var offsetY =
e.targetTouches && e.targetTouches[0]
? e.targetTouches[0].pageY - e.target.getBoundingClientRect().top
: e.pageY - handle.getBoundingClientRect().top;
var percent = isVertical ? (parent.offsetHeight - handle.offsetTop - offsetY) / parent.offsetHeight
: (Radzen.isRTL(handle) ? parent.offsetWidth - handle.offsetLeft - offsetX : handle.offsetLeft + offsetX) / parent.offsetWidth;
if (percent > 1) {
percent = 1;
} else if (percent < 0) {
percent = 0;
}
var newValue = percent * (max - min) + min;
if (
slider.canChange &&
newValue >= min &&
newValue <= max
) {
try { slider.invokeMethodAsync(
'RadzenSlider.OnValueChange',
newValue,
!!slider.isMin
); } catch { }
}
};
Radzen[id].mouseDownHandler = function (e) {
if (parent.classList.contains('rz-state-disabled')) return;
document.addEventListener('mousemove', Radzen[id].mouseMoveHandler);
document.addEventListener('touchmove', Radzen[id].mouseMoveHandler, {
passive: false, capture: true
});
document.addEventListener('mouseup', Radzen[id].mouseUpHandler);
document.addEventListener('touchend', Radzen[id].mouseUpHandler, {
passive: true
});
if (minHandle == e.target || maxHandle == e.target) {
slider.canChange = true;
slider.isMin = minHandle == e.target;
} else {
var offsetX =
e.targetTouches && e.targetTouches[0]
? e.targetTouches[0].pageX - e.target.getBoundingClientRect().left
: e.offsetX;
var percent = offsetX / parent.offsetWidth;
var newValue = percent * (max - min) + min;
var oldValue = range ? value[slider.isMin ? 0 : 1] : value;
if (newValue >= min && newValue <= max && newValue != oldValue) {
try { slider.invokeMethodAsync(
'RadzenSlider.OnValueChange',
newValue,
!!slider.isMin
); } catch { }
}
}
};
Radzen[id].mouseUpHandler = function (e) {
slider.canChange = false;
document.removeEventListener('mousemove', Radzen[id].mouseMoveHandler);
document.removeEventListener('touchmove', Radzen[id].mouseMoveHandler, {
passive: false, capture: true
});
document.removeEventListener('mouseup', Radzen[id].mouseUpHandler);
document.removeEventListener('touchend', Radzen[id].mouseUpHandler, {
passive: true
});
};
parent.addEventListener('mousedown', Radzen[id].mouseDownHandler);
parent.addEventListener('touchstart', Radzen[id].mouseDownHandler, {
passive: true
});
},
destroySlider: function (id, parent) {
if (!Radzen[id]) return;
if (Radzen[id].mouseMoveHandler) {
document.removeEventListener('mousemove', Radzen[id].mouseMoveHandler);
document.removeEventListener('touchmove', Radzen[id].mouseMoveHandler);
delete Radzen[id].mouseMoveHandler;
}
if (Radzen[id].mouseUpHandler) {
document.removeEventListener('mouseup', Radzen[id].mouseUpHandler);
document.removeEventListener('touchend', Radzen[id].mouseUpHandler);
delete Radzen[id].mouseUpHandler;
}
if (Radzen[id].mouseDownHandler) {
parent.removeEventListener('mousedown', Radzen[id].mouseDownHandler);
parent.removeEventListener('touchstart', Radzen[id].mouseDownHandler);
delete Radzen[id].mouseDownHandler;
}
Radzen[id] = null;
},
prepareDrag: function (el) {
if (el) {
el.ondragover = function (e) { e.preventDefault(); };
el.ondragstart = function (e) { e.dataTransfer.setData('', e.target.id); };
}
},
focusElement: function (elementId) {
var el = document.getElementById(elementId);
if (el) {
el.focus();
}
},
focusNext: function (container, reverse) {
if (!container) return;
var selector = 'a[href]:not([disabled]):not([tabindex="-1"]), button:not([disabled]):not([tabindex="-1"]), input:not([disabled]):not([type="hidden"]):not([tabindex="-1"]), select:not([disabled]):not([tabindex="-1"]), textarea:not([disabled]):not([tabindex="-1"]), [tabindex]:not([tabindex="-1"]):not([disabled])';
var candidates = Array.from(document.querySelectorAll(selector)).filter(function (el) {
return (el.offsetWidth > 0 || el.offsetHeight > 0) && el !== container && !container.contains(el);
});
if (reverse) {
for (var i = candidates.length - 1; i >= 0; i--) {
if (container.compareDocumentPosition(candidates[i]) & Node.DOCUMENT_POSITION_PRECEDING) {
candidates[i].focus();
return;
}
}
} else {
for (var i = 0; i < candidates.length; i++) {
if (container.compareDocumentPosition(candidates[i]) & Node.DOCUMENT_POSITION_FOLLOWING) {
candidates[i].focus();
return;
}
}
}
},
scrollCarouselItem: function (el, duration) {
var container = el.parentElement;
var target = el.offsetLeft;
if (duration == null || duration < 0) {
container.scroll(target, 0);
return;
}
if (duration === 0) {
container.style.scrollBehavior = 'auto';
container.scroll(target, 0);
container.style.scrollBehavior = '';
return;
}
container.style.scrollBehavior = 'auto';
container.style.scrollSnapType = 'none';
var start = container.scrollLeft;
var distance = target - start;
var startTime = null;
function step(timestamp) {
if (!startTime) startTime = timestamp;
var elapsed = timestamp - startTime;
var progress = Math.min(elapsed / duration, 1);
var ease = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2;
container.scrollLeft = start + distance * ease;
if (elapsed < duration) {
requestAnimationFrame(step);
} else {
container.style.scrollBehavior = '';
container.style.scrollSnapType = '';
}
}
requestAnimationFrame(step);
},
createCarousel: function (container, ref) {
var scrollTimeout = null;
function handler() {
if (scrollTimeout) clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(function () {
var children = container.children;
if (!children.length) return;
var itemWidth = children[0].offsetWidth;
if (itemWidth === 0) return;
var index = Math.round(container.scrollLeft / itemWidth);
if (index < 0) index = 0;
if (index >= children.length) index = children.length - 1;
try { ref.invokeMethodAsync('RadzenCarousel.OnScroll', index); } catch { }
}, 100);
}
container.addEventListener('scroll', handler, { passive: true });
return { dispose: function () { container.removeEventListener('scroll', handler); } };
},
scrollIntoViewIfNeeded: function (ref, selector) {
var el = selector ? ref.getElementsByClassName(selector)[0] : ref;
if (el && el.scrollIntoViewIfNeeded) {
el.scrollIntoViewIfNeeded();
} else if (el && el.scrollIntoView) {
el.scrollIntoView();
}
},
updateActiveDescendant: function (ul, li, index) {
if (!ul) return;
// The popup is appended to document.body when opened, so ul.closest('[role="combobox"]')
// fails once the dropdown is open. Fall back to a reverse lookup via aria-controls.
// There can be more than one combobox referencing the same listbox (the trigger and a
// filter input inside the popup), so update them all so screen readers announce the
// active option regardless of which element currently has focus.
var comboboxes = [];
var ancestor = ul.closest('[role="combobox"]');
if (ancestor) {
comboboxes.push(ancestor);
}
if (ul.id && window.CSS && CSS.escape) {
var escapedId = CSS.escape(ul.id);
var matches = document.querySelectorAll(
'[aria-controls="' + escapedId + '"][role="combobox"]'
);
for (var i = 0; i < matches.length; i++) {
if (comboboxes.indexOf(matches[i]) === -1) {
comboboxes.push(matches[i]);
}
}
}
if (li) {
var itemId = ul.id + '-' + index;
li.id = itemId;
for (var j = 0; j < comboboxes.length; j++) {
comboboxes[j].setAttribute('aria-activedescendant', itemId);
}
} else {
for (var k = 0; k < comboboxes.length; k++) {
comboboxes[k].removeAttribute('aria-activedescendant');
}
}
},
selectListItem: function (input, ul, index) {
if (!input || !ul) return;
var childNodes = ul.getElementsByTagName('LI');
var highlighted = ul.querySelectorAll('.rz-state-highlight');
if (highlighted.length) {
for (var i = 0; i < highlighted.length; i++) {
highlighted[i].classList.remove('rz-state-highlight');
}
}
ul.nextSelectedIndex = index;
if (
ul.nextSelectedIndex >= 0 &&
ul.nextSelectedIndex <= childNodes.length - 1
) {
childNodes[ul.nextSelectedIndex].classList.add('rz-state-highlight');
childNodes[ul.nextSelectedIndex].scrollIntoView({block:'nearest'});
Radzen.updateActiveDescendant(ul, childNodes[ul.nextSelectedIndex], ul.nextSelectedIndex);
} else {
Radzen.updateActiveDescendant(ul, null, -1);
}
},
focusListItem: function (input, ul, isDown, startIndex) {
if (!input || !ul) return;
var childNodes = ul.getElementsByTagName('LI');
if (!childNodes || childNodes.length == 0) return;
if (startIndex == undefined || startIndex == null) {
startIndex = -1;
}
ul.nextSelectedIndex = startIndex;
if (isDown) {
while (ul.nextSelectedIndex < childNodes.length - 1) {
ul.nextSelectedIndex++;
if (!childNodes[ul.nextSelectedIndex].classList.contains('rz-state-disabled'))
break;
}
} else {
while (ul.nextSelectedIndex >= 0) {
ul.nextSelectedIndex--;
if (!childNodes[ul.nextSelectedIndex] || !childNodes[ul.nextSelectedIndex].classList.contains('rz-state-disabled'))
break;
}
}
var highlighted = ul.querySelectorAll('.rz-state-highlight');
if (highlighted.length) {
for (var i = 0; i < highlighted.length; i++) {
highlighted[i].classList.remove('rz-state-highlight');
}
}
if (
ul.nextSelectedIndex >= 0 &&
ul.nextSelectedIndex <= childNodes.length - 1
) {
childNodes[ul.nextSelectedIndex].classList.add('rz-state-highlight');
Radzen.scrollIntoViewIfNeeded(childNodes[ul.nextSelectedIndex]);
Radzen.updateActiveDescendant(ul, childNodes[ul.nextSelectedIndex], ul.nextSelectedIndex);
} else {
Radzen.updateActiveDescendant(ul, null, -1);
}
return ul.nextSelectedIndex;
},
focusVirtualListItem: function (ul, absoluteIndex, totalCount) {
if (!ul) return;
var childNodes = ul.getElementsByTagName('LI');
if (!childNodes || childNodes.length == 0) return;
var itemHeight = childNodes[0].offsetHeight;
if (itemHeight <= 0) return;
var wrapper = ul.parentElement;
if (!wrapper) return;
// Scroll to make the item at absoluteIndex visible
if (absoluteIndex >= 0 && absoluteIndex < totalCount) {
var targetTop = absoluteIndex * itemHeight;
var targetBottom = targetTop + itemHeight;
var viewTop = wrapper.scrollTop;
var viewBottom = viewTop + wrapper.clientHeight;
if (targetBottom > viewBottom) {
wrapper.scrollTop = targetBottom - wrapper.clientHeight;
} else if (targetTop < viewTop) {
wrapper.scrollTop = targetTop;
}
}
// Highlight the correct item after scroll
function highlightItem() {
var lis = ul.getElementsByTagName('LI');
if (!lis || lis.length == 0) return;
var highlighted = ul.querySelectorAll('.rz-state-highlight');
for (var i = 0; i < highlighted.length; i++) {
highlighted[i].classList.remove('rz-state-highlight');
}
// Determine the start index of rendered items from the top spacer
var startIndex = 0;
var spacer = ul.firstElementChild;
if (spacer && spacer.tagName !== 'LI' && spacer.style && spacer.style.height) {
startIndex = Math.round(parseFloat(spacer.style.height) / itemHeight);
}
var relativeIndex = absoluteIndex - startIndex;
if (relativeIndex >= 0 && relativeIndex < lis.length) {
lis[relativeIndex].classList.add('rz-state-highlight');
lis[relativeIndex].scrollIntoView({ block: 'nearest' });
Radzen.updateActiveDescendant(ul, lis[relativeIndex], absoluteIndex);
} else {
Radzen.updateActiveDescendant(ul, null, -1);
}
}
// Use MutationObserver to wait for Virtualize to re-render after scroll
var observer = new MutationObserver(function () {
observer.disconnect();
highlightItem();
});
observer.observe(ul, { childList: true, subtree: true });
// Also highlight immediately in case no DOM change is needed
highlightItem();
// Disconnect observer after a timeout to avoid memory leaks
setTimeout(function () { observer.disconnect(); }, 500);
},
clearFocusedHeaderCell: function (gridId) {
var grid = document.getElementById(gridId);
if (!grid) return;
var table = grid.querySelector('.rz-grid-table');
var thead = table.getElementsByTagName("thead")[0];
var highlightedCells = thead.querySelectorAll('.rz-state-focused');
if (highlightedCells.length) {
for (var i = 0; i < highlightedCells.length; i++) {
highlightedCells[i].classList.remove('rz-state-focused');
}
}
},
focusTableRow: function (gridId, key, rowIndex, cellIndex, isVirtual) {
var grid = document.getElementById(gridId);
if (!grid) return;
var table = grid.querySelector('.rz-grid-table');
var tbody = table.tBodies[0];
var thead = table.tHead;
var rows = (cellIndex != null && thead && thead.rows && thead.rows.length ? [...thead.rows] : []).concat(tbody && tbody.rows && tbody.rows.length ? [...tbody.rows] : []);
if (isVirtual && (key == 'ArrowUp' || key == 'ArrowDown' || key == 'PageUp' || key == 'PageDown' || key == 'Home' || key == 'End')) {
if (rowIndex == 0 && (key == 'End' || key == 'PageDown')) {
var highlightedCells = thead.querySelectorAll('.rz-state-focused');
if (highlightedCells.length) {
for (var i = 0; i < highlightedCells.length; i++) {
highlightedCells[i].classList.remove('rz-state-focused');
}
}
}
if (key == 'PageUp' || key == 'PageDown') {
var rowHeight = rows[rows.length - 1] ? rows[rows.length - 1].offsetHeight : 40;
var factor = 10;
table.parentNode.scrollTop = table.parentNode.scrollTop + (factor * (key == 'PageDown' ? rowHeight : -rowHeight));
}
else if (key == 'Home' || key == 'End') {
table.parentNode.scrollTop = key == 'Home' ? 0 : table.parentNode.scrollHeight;
}
}
table.nextSelectedIndex = rowIndex || 0;
table.nextSelectedCellIndex = cellIndex || 0;
if (key == 'ArrowDown') {
while (table.nextSelectedIndex < rows.length - 1) {
table.nextSelectedIndex++;
if (!rows[table.nextSelectedIndex] || !rows[table.nextSelectedIndex].classList.contains('rz-state-disabled'))
break;
}
} else if (key == 'ArrowUp') {
while (table.nextSelectedIndex > 0) {
table.nextSelectedIndex--;
if (!rows[table.nextSelectedIndex] || !rows[table.nextSelectedIndex].classList.contains('rz-state-disabled'))
break;
}
} else if (key == 'ArrowRight') {
while (table.nextSelectedCellIndex < rows[table.nextSelectedIndex].cells.length - 1) {
table.nextSelectedCellIndex++;
if (!rows[table.nextSelectedIndex] || !rows[table.nextSelectedIndex].cells[table.nextSelectedCellIndex] || !rows[table.nextSelectedIndex].cells[table.nextSelectedCellIndex].classList.contains('rz-state-disabled'))
break;
}
} else if (key == 'ArrowLeft') {
while (table.nextSelectedCellIndex > 0) {
table.nextSelectedCellIndex--;
if (!rows[table.nextSelectedIndex] || !rows[table.nextSelectedIndex].cells[table.nextSelectedCellIndex] || !rows[table.nextSelectedIndex].cells[table.nextSelectedCellIndex].classList.contains('rz-state-disabled'))
break;
}
} else if (isVirtual && (key == 'PageDown' || key == 'End')) {
table.nextSelectedIndex = rows.length - 1;
} else if (isVirtual && (key == 'PageUp' || key == 'Home')) {
table.nextSelectedIndex = 1;
}
if (isVirtual && (key == 'ArrowDown' || key == 'ArrowUp')) {
var minIndex = cellIndex != null ? 0 : 1;
if (key == 'ArrowDown' && table.nextSelectedIndex >= rows.length - 1) {
var rh = rows[rows.length - 1] ? rows[rows.length - 1].offsetHeight : 40;
table.parentNode.scrollTop += rh;
table.nextSelectedIndex = rows.length - 1;
} else if (key == 'ArrowUp' && table.nextSelectedIndex <= minIndex) {
var rh = rows[rows.length - 1] ? rows[rows.length - 1].offsetHeight : 40;
table.parentNode.scrollTop -= rh;
table.nextSelectedIndex = minIndex;
}
}
var activeId = gridId + '-active-item';
var setActiveDescendant = function (el) {
var prev = document.getElementById(activeId);
if (prev && prev !== el) { prev.removeAttribute('id'); }
if (el && el.id !== activeId) { el.id = activeId; }
if (el) { grid.setAttribute('aria-activedescendant', activeId); }
};
if (key == 'ArrowLeft' || key == 'ArrowRight' || (key == 'ArrowUp' && cellIndex != null && table.nextSelectedIndex == 0 && table.parentNode.scrollTop == 0)) {
var highlightedCells = rows[table.nextSelectedIndex].querySelectorAll('.rz-state-focused');
if (highlightedCells.length) {
for (var i = 0; i < highlightedCells.length; i++) {
highlightedCells[i].classList.remove('rz-state-focused');
}
}
if (
table.nextSelectedCellIndex >= 0 &&
table.nextSelectedCellIndex <= rows[table.nextSelectedIndex].cells.length - 1
) {
var cell = rows[table.nextSelectedIndex].cells[table.nextSelectedCellIndex];
if (!cell.classList.contains('rz-state-focused')) {
cell.classList.add('rz-state-focused');
if (!isVirtual && table.parentElement.scrollWidth > table.parentElement.clientWidth) {
Radzen.scrollIntoViewIfNeeded(cell);
}
}
setActiveDescendant(cell);
}
} else if (key == 'ArrowDown' || key == 'ArrowUp') {
var highlighted = table.querySelectorAll('.rz-state-focused');
if (highlighted.length) {
for (var i = 0; i < highlighted.length; i++) {
highlighted[i].classList.remove('rz-state-focused');
}
}
if (table.nextSelectedIndex >= 0 &&
table.nextSelectedIndex <= rows.length - 1
) {
var row = rows[table.nextSelectedIndex];
if (!row.classList.contains('rz-state-focused')) {
row.classList.add('rz-state-focused');
if (!isVirtual && table.parentElement.scrollHeight > table.parentElement.clientHeight) {
Radzen.scrollIntoViewIfNeeded(row);
}
}
setActiveDescendant(row);
}
}
return [table.nextSelectedIndex, table.nextSelectedCellIndex];
},
uploadInputChange: function (e, url, auto, multiple, clear, parameterName, method = 'POST', stream = false) {
if (auto) {
Radzen.upload(e.target, url, multiple, clear, parameterName, method, stream);
e.target.value = '';
} else {
Radzen.uploadChange(e.target);
}
},
uploads: function (uploadComponent, id) {
if (!Radzen.uploadComponents) {
Radzen.uploadComponents = {};
}
Radzen.uploadComponents[id] = uploadComponent;
},
uploadChange: function (fileInput) {
var files = [];
for (var i = 0; i < fileInput.files.length; i++) {
var file = fileInput.files[i];
files.push({
Name: file.name,
Size: file.size,
Url: URL.createObjectURL(file)
});
}
var uploadComponent =
Radzen.uploadComponents && Radzen.uploadComponents[fileInput.id];
if (uploadComponent) {
if (uploadComponent.localFiles) {
// Clear any previously created preview URL(s)
for (var i = 0; i < uploadComponent.localFiles.length; i++) {
var file = uploadComponent.localFiles[i];
if (file.Url) {
URL.revokeObjectURL(file.Url);
}
}
}
uploadComponent.files = Array.from(fileInput.files);
uploadComponent.localFiles = files;
try { uploadComponent.invokeMethodAsync('RadzenUpload.OnChange', files); } catch { }
}
for (var i = 0; i < fileInput.files.length; i++) {
var file = fileInput.files[i];
if (file.Url) {
URL.revokeObjectURL(file.Url);
}
}
},
removeFileFromUpload: function (ref, name, id) {
var uploadComponent = (Radzen.uploadComponents && Radzen.uploadComponents[ref]) ?? Radzen.uploadComponents[id];
if (!uploadComponent) return;
if (!uploadComponent.files) return;
var file = uploadComponent.files.find(function (f) { return f.name == name; })
if (!file) { return; }
var localFile = uploadComponent.localFiles.find(function (f) { return f.Name == name; });
if (localFile) {
URL.revokeObjectURL(localFile.Url);
var localIndex = uploadComponent.localFiles.indexOf(localFile);
if (localIndex != -1) {
uploadComponent.localFiles.splice(localIndex, 1);
}
}
var index = uploadComponent.files.indexOf(file)
if (index != -1) {
uploadComponent.files.splice(index, 1);
}
var fileInput = document.getElementById(id).querySelector('input[type="file"]');
if (fileInput && uploadComponent.files.length == 0) {
fileInput.value = '';
}
},
removeFileFromFileInput: function (fileInput) {
fileInput.value = '';
},
upload: function (fileInput, url, multiple, clear, parameterName, method = 'POST', stream = false) {
var uploadComponent = Radzen.uploadComponents && Radzen.uploadComponents[fileInput.id];
if (!uploadComponent) { return; }
if (!uploadComponent.files || clear) {
uploadComponent.files = Array.from(fileInput.files);
}
function asFormData() {
var data = new FormData();
var files = [];
for (var i = 0; i < uploadComponent.files.length; i++) {
var file = uploadComponent.files[i];
data.append(parameterName || (multiple ? 'files' : 'file'), file, file.name);
files.push({Name: file.name, Size: file.size});
}
return {data, files}
}
function asStream() {
if (uploadComponent.files.length > 0) {
var file = uploadComponent.files[0];
return {data: file, files: [{Name: file.name, Size: file.size}]};
}
return {data: null, files: []}
}
var cancelled = false;
var {data, files} = stream ? asStream() : asFormData();
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.upload.onprogress = function (e) {
if (e.lengthComputable) {
var uploadComponent =
Radzen.uploadComponents && Radzen.uploadComponents[fileInput.id];
if (uploadComponent) {
var progress = parseInt((e.loaded / e.total) * 100);
try { uploadComponent.invokeMethodAsync(
'RadzenUpload.OnProgress',
progress,
e.loaded,
e.total,
files,
cancelled
).then(function (cancel) {
if (cancel) {
cancelled = true;
xhr.abort();
}
}); } catch { }
}
}
};
xhr.onreadystatechange = function (e) {
if (xhr.readyState === XMLHttpRequest.DONE) {
var status = xhr.status;
var uploadComponent =
Radzen.uploadComponents && Radzen.uploadComponents[fileInput.id];
if (uploadComponent) {
if (status === 0 || (status >= 200 && status < 400)) {
try { uploadComponent.invokeMethodAsync(
'RadzenUpload.OnComplete',
xhr.responseText,
cancelled
); } catch { }
} else {
try { uploadComponent.invokeMethodAsync(
'RadzenUpload.OnError',
xhr.responseText
); } catch { }
}
}
}
};
try { uploadComponent.invokeMethodAsync('GetHeaders').then(function (headers) {
xhr.open(method, url, true);
for (var name in headers) {
xhr.setRequestHeader(name, headers[name]);
}
xhr.send(data);
}); } catch { }
},
getCookie: function (name) {
var value = '; ' + decodeURIComponent(document.cookie);
var parts = value.split('; ' + name + '=');
if (parts.length == 2) return parts.pop().split(';').shift();
},
getCulture: function () {
var cultureCookie = Radzen.getCookie('.AspNetCore.Culture');
var uiCulture = cultureCookie
? cultureCookie.split('|').pop().split('=').pop()
: null;
return uiCulture || 'en-US';
},
numericOnPaste: function (e, min, max, locale = navigator.language) {
if (!e.clipboardData) return;
let value = e.clipboardData.getData("text");
if (!value) {
e.preventDefault();
return;
}
value = String(value).trim();
const parts = new Intl.NumberFormat(locale).formatToParts(1234567.89);
let group = ",";
let decimal = ".";
for (const p of parts) {
if (p.type === "group") group = p.value;
if (p.type === "decimal") decimal = p.value;
}
value = value.replace(/[\u00A0\u202F]/g, " ");
if (group) {
const escapedGroup = group.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
value = value.replace(new RegExp(escapedGroup, "g"), "");
}
if (group === " ") {
value = value.replace(/ /g, "");
}
if (decimal !== ".") {
const escapedDecimal = decimal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
value = value.replace(new RegExp(escapedDecimal, "g"), ".");
}
if (!/^[+-]?(\d+(\.\d*)?|\.\d+)$/.test(value)) {
e.preventDefault();
return;
}
const numericValue = Number(value);
if (!Number.isFinite(numericValue)) {
e.preventDefault();
return;
}
if (min != null && numericValue < min) {
e.preventDefault();
return;
}
if (max != null && numericValue > max) {
e.preventDefault();
return;
}
},
numericOnInput: function (e, min, max, isNullable) {
var value = e.target.value;
if (!isNullable && value == '' && min != null) {
e.target.value = min;
}
if (value && !isNaN(+value)) {
var numericValue = +value;
if (min != null && !isNaN(+min) && numericValue < min) {
e.target.value = min;
}
if (max != null && !isNaN(+max) && numericValue > max) {
e.target.value = max;
}
}
},
numericKeyPress: function (e, isInteger, decimalSeparator) {
if (
e.metaKey ||
e.ctrlKey ||
e.keyCode == 9 ||
e.keyCode == 8 ||
e.keyCode == 13
) {
return;
}
if (e.code === 'NumpadDecimal' && !isInteger) {
var cursorPosition = e.target.selectionEnd;
e.target.value = [e.target.value.slice(0, e.target.selectionStart), decimalSeparator, e.target.value.slice(e.target.selectionEnd)].join('');
e.target.selectionStart = ++cursorPosition;
e.target.selectionEnd = cursorPosition;
e.preventDefault();
return;
}
var ch = e.key;
if (/\p{Nd}/u.test(ch) || ch === '-' || (!isInteger && ch === decimalSeparator)) {
return;
}
e.preventDefault();
},
openContextMenu: function (x,y,id, instance, callback) {
Radzen.closePopup(id);
Radzen.openPopup(null, id, false, null, x, y, instance, callback);
setTimeout(function () {
var popup = document.getElementById(id);
if (popup) {
var menu = popup.querySelector('.rz-menu');
if (menu) {
menu.focus();
}
}
}, 500);
},
openTooltip: function (target, id, delay, duration, position, closeTooltipOnDocumentClick, instance, callback, clientX, clientY) {
Radzen.closeTooltip(id);
if (clientX != null && clientY != null) {
position = null;
disableSmartPosition = true;
}
else {
disableSmartPosition = false;
}
if (target) {
target.setAttribute('aria-describedby', id);
Radzen[id + 'target'] = target;
}
if (delay) {
Radzen[id + 'delay'] = setTimeout(Radzen.openPopup, delay, target, id, false, position, clientX, clientY, instance, callback, closeTooltipOnDocumentClick, false, disableSmartPosition);
} else {
Radzen.openPopup(target, id, false, position, clientX, clientY, instance, callback, closeTooltipOnDocumentClick, false, disableSmartPosition);
}
if (duration) {
Radzen[id + 'duration'] = setTimeout(Radzen.closePopup, duration, id, instance, callback);
}
},
closeTooltip(id) {
Radzen.activeElement = null;
var target = Radzen[id + 'target'];
if (target) {
target.removeAttribute('aria-describedby');
Radzen[id + 'target'] = null;
}
Radzen.closePopup(id);
if (Radzen[id + 'delay']) {
clearTimeout(Radzen[id + 'delay']);
}
if (Radzen[id + 'duration']) {
clearTimeout(Radzen[id + 'duration']);
}
},
destroyDatePicker(id) {
var el = document.getElementById(id);
if (!el) return;
var button = el.querySelector('.rz-datepicker-trigger');
if (button) {
button.onclick = null;
}
var input = el.querySelector('.rz-inputtext');
if (input) {
input.onclick = null;
}
},
createDatePicker(el, popupId, instance, callback) {
if(!el) return;
var handler = function (e, condition) {
if (condition) {
Radzen.togglePopup(e.currentTarget.parentNode, popupId, false, instance, callback, true, false);
}
};
var input = el.querySelector('.rz-inputtext');
var button = el.querySelector('.rz-datepicker-trigger');
if (button) {
button.onclick = function (e) {
handler(e, !e.currentTarget.classList.contains('rz-state-disabled') && (input ? !input.classList.contains('rz-readonly') : true));
};
}
if (input) {
input.onclick = function (e) {
handler(e, e.currentTarget.classList.contains('rz-input-trigger') && !e.currentTarget.classList.contains('rz-readonly'));
};
}
},
findPopup: function (id) {
var popups = [];
for (var i = 0; i < document.body.children.length; i++) {
if (document.body.children[i].id == id) {
popups.push(document.body.children[i]);
}
}
return popups;
},
repositionPopup: function (parent, id) {
var popup = document.getElementById(id);
if (!popup) return;
var rect = popup.getBoundingClientRect();
var parentRect = parent ? parent.getBoundingClientRect() : { top: 0, bottom: 0, left: 0, right: 0, width: 0, height: 0 };
if (/Edge/.test(navigator.userAgent)) {
var scrollTop = document.body.scrollTop;
} else {
var scrollTop = document.documentElement.scrollTop;
}
var top = parentRect.bottom + scrollTop;
if (top + rect.height > window.innerHeight + scrollTop && parentRect.top > rect.height) {
top = parentRect.top - rect.height + scrollTop;
}
popup.style.top = top + 'px';
},
setPopupAriaExpanded: function (parent, id, expanded) {
if (!parent || !id) return;
var control = null;
if (parent.getAttribute && parent.getAttribute('aria-controls') === id) {
control = parent;
} else if (parent.querySelector) {
control = parent.querySelector('[aria-controls="' + id + '"]');
}
if (!control && parent.getAttribute && parent.getAttribute('role') === 'combobox') {
control = parent;
}
if (control) {
control.setAttribute('aria-expanded', expanded ? 'true' : 'false');
}
},
openPopup: function (parent, id, syncWidth, position, x, y, instance, callback, closeOnDocumentClick = true, autoFocusFirstElement = false, disableSmartPosition = false) {
var popup = document.getElementById(id);
if (!popup || popup && popup.style.display == 'block' && popup.classList.contains('rz-autocomplete-panel')) return;
Radzen.activeElement = document.activeElement;
var parentRect = parent ? parent.getBoundingClientRect() : { top: y || 0, bottom: 0, left: x || 0, right: 0, width: 0, height: 0 };
if (/Edge/.test(navigator.userAgent)) {
var scrollLeft = document.body.scrollLeft;
var scrollTop = document.body.scrollTop;
} else {
var scrollLeft = document.documentElement.scrollLeft;
var scrollTop = document.documentElement.scrollTop;
}
var top = y ? y : parentRect.bottom;
var left = x ? x : parentRect.left;
if (syncWidth) {
popup.style.width = parentRect.width + 'px';
if (!popup.style.minWidth) {
popup.minWidth = true;
popup.style.minWidth = parentRect.width + 'px';
}
}
if (window.chrome) {
var closestFrozenCell = popup.closest('.rz-frozen-cell');
if (closestFrozenCell) {
Radzen[id + 'FZL'] = { cell: closestFrozenCell, left: closestFrozenCell.style.left };
closestFrozenCell.style.left = '';
}
}
popup.style.display = 'block';
popup.style.visibility = 'hidden';
popup.onanimationend = null;
popup.classList.remove("rz-close");
Radzen.setPopupAriaExpanded(parent, id, true);
var rect = popup.getBoundingClientRect();
rect.width = x ? rect.width + 20 : rect.width;
rect.height = y ? rect.height + 20 : rect.height;
var isRTL = Radzen.isRTL(popup);
if (isRTL && parent && (!position || position == 'bottom' || position == 'top')) {
left = parentRect.right - rect.width;
}
var smartPosition = !position || position == 'bottom';
if (smartPosition && top + rect.height > window.innerHeight && parentRect.top > rect.height) {
if (disableSmartPosition !== true) {
top = parentRect.top - rect.height;
}
if (position) {
top = top - 40;
var tooltipContent = popup.children[0];
var tooltipContentClassName = 'rz-' + position + '-tooltip-content';
if (tooltipContent.classList.contains(tooltipContentClassName)) {
tooltipContent.classList.remove(tooltipContentClassName);
tooltipContent.classList.add('rz-top-tooltip-content');
position = 'top';
if (instance && callback) {
try { instance.invokeMethodAsync(callback, position); } catch { }
}
}
}
}
if (smartPosition && left + rect.width > window.innerWidth && window.innerWidth > rect.width) {
left = !position ? window.innerWidth - rect.width : rect.left;
if (position) {
top = y || parentRect.top;
var tooltipContent = popup.children[0];
var tooltipContentClassName = 'rz-' + position + '-tooltip-content';
if (tooltipContent.classList.contains(tooltipContentClassName)) {
tooltipContent.classList.remove(tooltipContentClassName);
tooltipContent.classList.add('rz-left-tooltip-content');
position = 'left';
if (instance && callback) {
try { instance.invokeMethodAsync(callback, position); } catch { }
}
}
}
}
if (smartPosition && isRTL && left < 0 && window.innerWidth > rect.width) {
left = !position ? 0 : rect.left;
if (position) {
top = y || parentRect.top;
var tooltipContent = popup.children[0];
var tooltipContentClassName = 'rz-' + position + '-tooltip-content';
if (tooltipContent.classList.contains(tooltipContentClassName)) {
tooltipContent.classList.remove(tooltipContentClassName);
tooltipContent.classList.add('rz-right-tooltip-content');
position = 'right';
if (instance && callback) {
try { instance.invokeMethodAsync(callback, position); } catch { }
}
}
}
}
if (smartPosition) {
if (position) {
top = top + 20;
}
}
if (position == 'left') {
left = parentRect.left - rect.width - 5;
top = parentRect.top;
}
if (position == 'right') {
left = parentRect.right + 10;
top = parentRect.top;
}
if (position == 'top') {
top = parentRect.top - rect.height + 5;
left = isRTL ? parentRect.right - rect.width : parentRect.left;
}
if (disableSmartPosition && x != null && y != null) {
left = x + 10;
top = y + 10;
var tooltipContent = popup.children[0];
var tooltipContentClassName = 'rz-bottom-tooltip-content';
if (tooltipContent.classList.contains(tooltipContentClassName)) {
tooltipContent.classList.remove(tooltipContentClassName);
}
if (left + rect.width > window.innerWidth && window.innerWidth > rect.width) {
top = parentRect.top - rect.height;
}
if (left + rect.width > window.innerWidth && window.innerWidth > rect.width) {
left = window.innerWidth - rect.width;
}
}
popup.style.zIndex = 2000;
popup.style.left = left + scrollLeft + 'px';
popup.style.top = top + scrollTop + 'px';
if (!popup.classList.contains('rz-overlaypanel')) {
popup.classList.add('rz-popup');
}
Radzen[id] = function (e) {
var lastPopup = Radzen.popups && Radzen.popups[Radzen.popups.length - 1];
var currentPopup = lastPopup != null && document.getElementById(lastPopup.id) || popup;
if (lastPopup) {
currentPopup.instance = lastPopup.instance;
currentPopup.callback = lastPopup.callback;
currentPopup.parent = lastPopup.parent;
}
if(e.type == 'contextmenu' || !e.target || !closeOnDocumentClick) return;
if (!/Android/i.test(navigator.userAgent) &&
!['input', 'textarea'].includes(document.activeElement ? document.activeElement.tagName.toLowerCase() : '') && e.type == 'resize') {
Radzen.closePopup(currentPopup.id, currentPopup.instance, currentPopup.callback, e);
return;
}
var closestLink = e.target.closest && (e.target.closest('.rz-link') || e.target.closest('.rz-navigation-item-link'));
if (e.type == 'resize' && !/Android/i.test(navigator.userAgent)) {
if (closestLink && closestLink.closest && closestLink.closest('a') && e.button == 0) {
closestLink.closest('a').click();
Radzen.closeAllPopups();
} else {
Radzen.closeAllPopups();
}
}
if (currentPopup.parent) {
if (e.type == 'mousedown' && !currentPopup.parent.contains(e.target) && !currentPopup.contains(e.target)) {
Radzen.closePopup(currentPopup.id, currentPopup.instance, currentPopup.callback, e);
}
} else {
if (e.target.nodeType && !currentPopup.contains(e.target)) {
Radzen.closePopup(currentPopup.id, currentPopup.instance, currentPopup.callback, e);
}
}
};
if (!Radzen.popups) {
Radzen.popups = [];
}
Radzen.popups.push({ id, instance, callback, parent });
document.body.appendChild(popup);
if (!position) {
var popupRect = popup.getBoundingClientRect();
// Clamp into the viewport. If the popup is smaller than the viewport, shift it
// so its right/bottom edge fits. If it is larger than the viewport, pin the
// top/left corner to the viewport origin so content is at least reachable
// (instead of leaving it positioned off-screen at the anchor).
if (popupRect.right > window.innerWidth) {
popup.style.left = Math.max(scrollLeft, window.innerWidth - popupRect.width + scrollLeft) + 'px';
}
if (popupRect.bottom > window.innerHeight) {
popup.style.top = Math.max(scrollTop, window.innerHeight - popupRect.height + scrollTop) + 'px';
}
}
popup.style.visibility = '';
popup.classList.add("rz-open");
document.removeEventListener('mousedown', Radzen[id]);
document.addEventListener('mousedown', Radzen[id]);
window.removeEventListener('resize', Radzen[id]);
window.addEventListener('resize', Radzen[id]);
var p = parent;
while (p && p != document.body) {
if (p.scrollWidth > p.clientWidth || p.scrollHeight > p.clientHeight) {
p.removeEventListener('scroll', Radzen.closeAllPopups);
p.addEventListener('scroll', Radzen.closeAllPopups);
}
p = p.parentElement;
}
if (!parent) {
document.removeEventListener('contextmenu', Radzen[id]);
document.addEventListener('contextmenu', Radzen[id]);
}
if (autoFocusFirstElement) {
setTimeout(function () {
popup.removeEventListener('keydown', Radzen.focusTrap);
popup.addEventListener('keydown', Radzen.focusTrap);
var focusable = Radzen.getFocusableElements(popup);
var firstFocusable = focusable[0];
if (firstFocusable) {
firstFocusable.focus();
}
}, 200);
}
if (popup.__escapeHandler) {
popup.removeEventListener('keydown', popup.__escapeHandler, true);
}
popup.__escapeHandler = function (e) {
if (e.key === 'Escape' || e.key === 'Esc') {
Radzen.closePopup(id, instance, callback, e);
}
if (e.key === 'Tab' && parent && (popup.classList.contains('rz-dropdown-panel') || popup.classList.contains('rz-multiselect-panel'))) {
e.preventDefault();
}
if (e.key === 'Tab' && !e.shiftKey) {
var timepicker = popup.querySelector('.rz-timepicker');
if (timepicker) {
var focusable = Radzen.getFocusableElements(timepicker);
var last = focusable[focusable.length - 1];
if (last && document.activeElement === last) {
Radzen.closePopup(id, instance, callback, e);
}
}
}
};
popup.addEventListener('keydown', popup.__escapeHandler, true);
},
closeAllPopups: function (e, id) {
if (!Radzen.popups) return;
var el = e && e.target || id && documentElement.getElementById(id);
var popups = Radzen.popups;
for (var i = 0; i < popups.length; i++) {
var p = popups[i];
var closestPopup = el && el.closest && (el.closest('.rz-popup') || el.closest('.rz-overlaypanel'));
if (closestPopup && closestPopup != p) {
return;
}
Radzen.closePopup(p.id, p.instance, p.callback, e);
}
Radzen.popups = [];
},
closePopup: function (id, instance, callback, e, preventFocusRestore) {
var popup = document.getElementById(id);
if (!popup) return;
var popupInfo = (Radzen.popups || []).find(function (p) { return p.id === id; });
if (popupInfo && popupInfo.parent) {
Radzen.setPopupAriaExpanded(popupInfo.parent, id, false);
var combobox = popupInfo.parent.closest('[role="combobox"]');
if (combobox) {
combobox.removeAttribute('aria-activedescendant');
}
}
if (popup.style.display == 'none') {
var popups = Radzen.findPopup(id);
if (popups.length > 1) {
for (var i = 0; i < popups.length; i++) {
if (popups[i].style.display == 'none') {
popups[i].parentNode.removeChild(popups[i]);
} else {
popup = popups[i];
}
}
} else {
return;
}
}
if (popup) {
if (popup.minWidth) {
popup.style.minWidth = '';
}
if (window.chrome && Radzen[id + 'FZL']) {
Radzen[id + 'FZL'].cell.style.left = Radzen[id + 'FZL'].left;
Radzen[id + 'FZL'] = null;
}
popup.onanimationend = function () {
popup.style.display = 'none';
popup.onanimationend = null;
}
popup.classList.add("rz-close");
popup.classList.remove("rz-open");
}
if (popup && popup.__escapeHandler) {
popup.removeEventListener('keydown', popup.__escapeHandler, true);
delete popup.__escapeHandler;
}
document.removeEventListener('mousedown', Radzen[id]);
window.removeEventListener('resize', Radzen[id]);
Radzen[id] = null;
if (instance && callback) {
if (callback.includes('RadzenTooltip')) {
try { instance.invokeMethodAsync(callback, null); } catch { }
} else {
try { instance.invokeMethodAsync(callback); } catch { }
}
}
Radzen.popups = (Radzen.popups || []).filter(function (obj) {
return obj.id !== id;
});
if (!preventFocusRestore &&
(Radzen.activeElement && Radzen.activeElement == document.activeElement ||
Radzen.activeElement && document.activeElement == document.body ||
Radzen.activeElement && popup && popup.contains(document.activeElement) ||
Radzen.activeElement && document.activeElement &&
(document.activeElement.classList.contains('rz-dropdown-filter') ||
document.activeElement.classList.contains('rz-lookup-search-input') ||
document.activeElement.classList.contains('rz-multiselect-filter-container') ||
document.activeElement.closest('.rz-multiselect-filter-container') !== null))) {
setTimeout(function () {
if (e && e.target && e.target.tabIndex != -1) {
Radzen.activeElement = e.target;
}
if (Radzen.activeElement) {
Radzen.activeElement.focus();
}
Radzen.activeElement = null;
}, 100);
}
},
popupOpened: function (id) {
var popup = document.getElementById(id);
if (popup) {
return popup.style.display != 'none';
}
return false;
},
togglePopup: function (parent, id, syncWidth, instance, callback, closeOnDocumentClick = true, autoFocusFirstElement = false) {
var popup = document.getElementById(id);
if (!popup) return;
if (popup.style.display == 'block') {
Radzen.closePopup(id, instance, callback);
} else {
Radzen.openPopup(parent, id, syncWidth, null, null, null, instance, callback, closeOnDocumentClick, autoFocusFirstElement);
}
},
destroyPopup: function (id) {
var popup = document.getElementById(id);
if (popup) {
if (popup.__escapeHandler) {
popup.removeEventListener('keydown', popup.__escapeHandler, true);
delete popup.__escapeHandler;
}
popup.parentNode.removeChild(popup);
}
document.removeEventListener('mousedown', Radzen[id]);
},
scrollDataGrid: function (e) {
var scrollLeft =
(e.target.scrollLeft ? '-' + e.target.scrollLeft : 0) + 'px';
e.target.previousElementSibling.style.marginLeft = scrollLeft;
e.target.previousElementSibling.firstElementChild.style.paddingRight =
e.target.clientHeight < e.target.scrollHeight ? (e.target.offsetWidth - e.target.clientWidth) + 'px' : '0px';
if (e.target.nextElementSibling) {
e.target.nextElementSibling.style.marginLeft = scrollLeft;
e.target.nextElementSibling.firstElementChild.style.paddingRight =
e.target.clientHeight < e.target.scrollHeight ? (e.target.offsetWidth - e.target.clientWidth) + 'px' : '0px';
}
for (var i = 0; i < document.body.children.length; i++) {
if (document.body.children[i].classList.contains('rz-overlaypanel')) {
document.body.children[i].style.display = 'none';
}
}
},
focusFirstFocusableElement: function (el) {
var focusable = Radzen.getFocusableElements(el);
if (!focusable || !focusable.length) return;
var first = focusable[0];
if (first.classList.contains('rz-html-editor-content')) {
var sel = window.getSelection();
var range = document.createRange();
range.setStart(first, 0);
range.setEnd(first, 0);
sel.removeAllRanges();
sel.addRange(range);
first.focus();
} else {
first.focus();
}
},
openSideDialog: function (options) {
setTimeout(function () {
if (options.autoFocusFirstElement) {
var dialogs = document.querySelectorAll('.rz-dialog-side-content');
if (dialogs.length == 0) return;
var lastDialog = dialogs[dialogs.length - 1];
Radzen.focusFirstFocusableElement(lastDialog);
}
}, 500);
},
createSideDialogResizer: function(handle, sideDialog, options) {
const normalizeDir = (value) => {
if (typeof value === 'string' && value.length) {
return value.toLowerCase();
}
if (typeof value === 'number') {
const positions = ['right', 'left', 'top', 'bottom'];
return positions[value] || 'right';
}
return 'right';
};
const dir = normalizeDir(options?.position);
let start = null;
const onDown = (e) => {
e.preventDefault();
start = {x: e.clientX, y: e.clientY, w: sideDialog.clientWidth, h: sideDialog.clientHeight};
document.addEventListener('pointermove', onMove);
document.addEventListener('pointerup', onUp, {once: true});
document.addEventListener('pointercancel', onUp, {once: true});
};
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
const applyWidth = (w) => {
sideDialog.style.width = Math.round(w) + 'px';
};
const applyHeight = (h) => {
sideDialog.style.height = `${Math.round(h)}px`;
};
const onMove = (e) => {
if (!start) return;
const dx = e.clientX - start.x;
const dy = e.clientY - start.y;
switch (dir) {
case 'right':
applyWidth(clamp(start.w - dx, options.minWidth, Infinity));
break;
case 'left':
applyWidth(clamp(start.w + dx, options.minWidth, Infinity));
break;
case 'bottom':
applyHeight(clamp(start.h - dy, options.minHeight, Infinity));
break;
case 'top':
applyHeight(clamp(start.h + dy, options.minHeight, Infinity));
break;
}
};
const onUp = (e) => {
start = null;
document.removeEventListener('pointermove', onMove);
};
handle.addEventListener('pointerdown', onDown);
return {
dispose() {
handle.removeEventListener('pointerdown', onDown);
document.removeEventListener('pointermove', onMove);
}
};
},
openDialog: function (options, dialogService, dialog) {
if (Radzen.closeAllPopups) {
Radzen.closeAllPopups();
}
Radzen.dialogService = dialogService;
if (
document.documentElement.scrollHeight >
document.documentElement.clientHeight
) {
document.body.classList.add('no-scroll');
}
setTimeout(function () {
var dialogs = document.querySelectorAll('.rz-dialog-content');
if (dialogs.length == 0) return;
var lastDialog = dialogs[dialogs.length - 1];
if (lastDialog) {
lastDialog.options = options;
lastDialog.removeEventListener('keydown', Radzen.focusTrap);
lastDialog.addEventListener('keydown', Radzen.focusTrap);
if (options.resizable) {
dialog.offsetWidth = lastDialog.parentElement.offsetWidth;
dialog.offsetHeight = lastDialog.parentElement.offsetHeight;
var dialogResize = function (e) {
if (!dialog) return;
if (dialog.offsetWidth != e[0].target.offsetWidth || dialog.offsetHeight != e[0].target.offsetHeight) {
dialog.offsetWidth = e[0].target.offsetWidth;
dialog.offsetHeight = e[0].target.offsetHeight;
dialog.invokeMethodAsync(
'RadzenDialog.OnResize',
e[0].target.offsetWidth,
e[0].target.offsetHeight
).catch(function () { });
}
};
var resizeObserver = new ResizeObserver(dialogResize);
resizeObserver.observe(lastDialog.parentElement);
Radzen.dialogResizer = resizeObserver;
}
if (options.draggable) {
var dialogTitle = lastDialog.parentElement.querySelector('.rz-dialog-titlebar');
if (dialogTitle) {
Radzen[dialogTitle] = function (e) {
var rect = lastDialog.parentElement.getBoundingClientRect();
var offsetX = e.clientX - rect.left;
var offsetY = e.clientY - rect.top;
var move = function (e) {
var left = e.clientX - offsetX;
var top = e.clientY - offsetY;
lastDialog.parentElement.style.left = left + 'px';
lastDialog.parentElement.style.top = top + 'px';
try { dialog.invokeMethodAsync('RadzenDialog.OnDrag', top, left); } catch { }
};
var stop = function () {
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', stop);
};
document.addEventListener('mousemove', move);
document.addEventListener('mouseup', stop);
};
dialogTitle.addEventListener('mousedown', Radzen[dialogTitle]);
}
}
if (options.autoFocusFirstElement) {
Radzen.focusFirstFocusableElement(lastDialog);
}
}
}, 500);
document.removeEventListener('keydown', Radzen.closePopupOrDialog);
if (options.closeDialogOnEsc) {
document.addEventListener('keydown', Radzen.closePopupOrDialog);
}
},
closeDialog: function () {
if (Radzen.dialogResizer && typeof Radzen.dialogResizer.disconnect === 'function') {
Radzen.dialogResizer.disconnect();
}
Radzen.dialogResizer = null;
document.body.classList.remove('no-scroll');
var dialogs = document.querySelectorAll('.rz-dialog-content');
var lastDialog = dialogs.length && dialogs[dialogs.length - 1];
if (lastDialog) {
var dialogTitle = lastDialog.parentElement.querySelector('.rz-dialog-titlebar');
if (dialogTitle) {
dialogTitle.removeEventListener('mousedown', Radzen[dialogTitle]);
Radzen[dialogTitle] = null;
delete Radzen[dialogTitle];
}
}
if (dialogs.length <= 1) {
document.removeEventListener('keydown', Radzen.closePopupOrDialog);
delete Radzen.dialogService;
}
},
disableKeydown: function (e) {
e = e || window.event;
e.preventDefault();
},
getFocusableElements: function (element) {
return [...element.querySelectorAll('a, button, input, textarea, select, details, iframe, embed, object, summary, dialog, audio[controls], video[controls], [contenteditable], [tabindex]')]
.filter(el => {
if (!el || el.hasAttribute('disabled') || el.offsetParent === null) return false;
// If this is inside a .rz-html-editor with tabindex="-1", skip it
var editorParent = el.closest('.rz-html-editor');
if (editorParent && editorParent.hasAttribute('tabindex') && editorParent.tabIndex === -1) return false;
else if (editorParent) return true;
return el.tabIndex > -1;
});
},
focusTrap: function (e) {
e = e || window.event;
var isTab = false;
if ("key" in e) {
isTab = (e.key === "Tab");
} else {
isTab = (e.keyCode === 9);
}
if (isTab) {
var focusable = Radzen.getFocusableElements(e.currentTarget);
var firstFocusable = focusable[0];
var lastFocusable = focusable[focusable.length - 1];
if (firstFocusable && lastFocusable && e.shiftKey && document.activeElement === firstFocusable) {
e.preventDefault();
lastFocusable.focus();
} else if (firstFocusable && lastFocusable && !e.shiftKey && document.activeElement === lastFocusable) {
e.preventDefault();
firstFocusable.focus();
}
}
},
closePopupOrDialog: function (e) {
e = e || window.event;
var isEscape = false;
if ("key" in e) {
isEscape = (e.key === "Escape" || e.key === "Esc");
} else {
isEscape = (e.keyCode === 27);
}
if (isEscape && Radzen.dialogService) {
var popups = document.querySelectorAll('.rz-popup,.rz-overlaypanel');
for (var i = 0; i < popups.length; i++) {
if (popups[i].style.display != 'none') {
return;
}
}
var dialogs = document.querySelectorAll('.rz-dialog-content');
if (dialogs.length == 0) return;
var lastDialog = dialogs[dialogs.length - 1];
if (lastDialog && lastDialog.options && lastDialog.options.closeDialogOnEsc) {
try {
Radzen.dialogService.invokeMethodAsync('DialogService.TryClose', null).then(function(closed) {
if (closed && dialogs.length <= 1) {
document.removeEventListener('keydown', Radzen.closePopupOrDialog);
delete Radzen.dialogService;
var layout = document.querySelector('.rz-layout');
if (layout) {
layout.removeEventListener('keydown', Radzen.disableKeydown);
}
}
});
} catch (e) { }
}
}
},
getNumericValue: function (arg) {
var el =
arg instanceof Element || arg instanceof HTMLDocument
? arg
: document.getElementById(arg);
return el ? Radzen.getInputValue(el.children[0]) : null;
},
getInputValue: function (arg) {
var input =
arg instanceof Element || arg instanceof HTMLDocument
? arg
: document.getElementById(arg);
return input && input.value != '' ? input.value : null;
},
setInputValue: function (arg, value) {
var input =
arg instanceof Element || arg instanceof HTMLDocument
? arg
: document.getElementById(arg);
if (input) {
input.value = value;
}
},
blur: function (el, e) {
if (el) {
e.preventDefault();
el.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, cancelable: true, keyCode: 9 }));
}
},
readFileAsBase64: function (fileInput, maxFileSize, maxWidth, maxHeight) {
var calculateWidthAndHeight = function (img) {
var width = img.width;
var height = img.height;
// Change the resizing logic
if (width > height) {
if (width > maxWidth) {
height = height * (maxWidth / width);
width = maxWidth;
}
} else {
if (height > maxHeight) {
width = width * (maxHeight / height);
height = maxHeight;
}
}
return { width, height };
};
var readAsDataURL = function (fileInput) {
return new Promise(function (resolve, reject) {
var reader = new FileReader();
reader.onerror = function () {
reader.abort();
reject('Error reading file.');
};
reader.addEventListener(
'load',
function () {
if (fileInput.files[0] && fileInput.files[0].type.includes('image') && maxWidth > 0 && maxHeight > 0) {
var img = document.createElement("img");
img.onload = function (event) {
// Dynamically create a canvas element
var canvas = document.createElement("canvas");
var res = calculateWidthAndHeight(img);
canvas.width = res.width;
canvas.height = res.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, res.width, res.height);
resolve(canvas.toDataURL(fileInput.type));
}
img.src = reader.result;
} else {
resolve(reader.result);
}
},
false
);
var file = fileInput.files[0];
if (!file) return;
if (file.size <= maxFileSize) {
reader.readAsDataURL(file);
} else {
reject('File too large.');
}
});
};
return readAsDataURL(fileInput);
},
toggleMenuItem: function (target, event, defaultActive, clickToOpen) {
var item = target.closest('.rz-navigation-item');
var active = defaultActive != undefined ? defaultActive : !item.classList.contains('rz-navigation-item-active');
function toggle(active) {
item.classList.toggle('rz-navigation-item-active', active);
target.classList.toggle('rz-navigation-item-wrapper-active', active);
var children = item.querySelector('.rz-navigation-menu');
if (children) {
item.setAttribute('aria-expanded', active);
if (active) {
children.onanimationend = null;
children.style.display = '';
children.classList.add('rz-open');
children.classList.remove('rz-close');
var isRtl = getComputedStyle(item).direction === 'rtl';
var el = item.parentElement;
var scrollParent = null;
while (el && el !== document.body) {
var s = getComputedStyle(el);
if (s.overflowX === 'auto' || s.overflowX === 'scroll' || s.overflowX === 'hidden') {
scrollParent = el;
break;
}
el = el.parentElement;
}
if (children.hasAttribute('data-flyout')) {
children.removeAttribute('data-flyout-flip');
var childRect = children.getBoundingClientRect();
var itemRect = item.getBoundingClientRect();
if (isRtl) {
var leftBoundary = scrollParent ? scrollParent.getBoundingClientRect().left : 0;
if (itemRect.left - childRect.width < leftBoundary) {
children.setAttribute('data-flyout-flip', '');
}
} else {
var rightBoundary = scrollParent ? scrollParent.getBoundingClientRect().right : document.documentElement.clientWidth;
if (itemRect.right + childRect.width > rightBoundary) {
children.setAttribute('data-flyout-flip', '');
}
}
}
// Shift dropdown left/right if it overflows the scroll parent or viewport
children.style.insetInlineStart = children.style.insetInlineStart || '';
var childRect = children.getBoundingClientRect();
var rightBoundary = scrollParent ? scrollParent.getBoundingClientRect().right : document.documentElement.clientWidth;
var leftBoundary = scrollParent ? scrollParent.getBoundingClientRect().left : 0;
if (!isRtl && childRect.right > rightBoundary) {
var offset = parseFloat(children.style.insetInlineStart) || 0;
children.style.insetInlineStart = (offset + rightBoundary - childRect.right) + 'px';
} else if (isRtl && childRect.left < leftBoundary) {
var offset = parseFloat(children.style.insetInlineStart) || 0;
children.style.insetInlineStart = (offset + leftBoundary - childRect.left) + 'px';
}
} else {
children.onanimationend = function () {
children.style.display = 'none';
children.style.insetInlineStart = '';
children.onanimationend = null;
}
children.classList.remove('rz-open');
children.classList.add('rz-close');
}
}
var icon = item.querySelector('.rz-navigation-item-icon-children');
if (icon) {
icon.classList.toggle('rz-state-expanded', active);
icon.classList.toggle('rz-state-collapsed', !active);
}
}
if (clickToOpen === false && item.parentElement && item.parentElement.closest('.rz-navigation-item') && !defaultActive) {
return;
};
toggle(active);
document.removeEventListener('click', target.clickHandler);
target.clickHandler = function (event) {
if (item.contains(event.target)) {
var child = event.target.closest('.rz-navigation-item');
if (child && child.querySelector('.rz-navigation-menu')) {
return;
}
}
toggle(false);
}
document.addEventListener('click', target.clickHandler);
},
destroyChart: function (ref) {
if(!ref) return;
ref.removeEventListener('mouseleave', ref.mouseLeaveHandler);
delete ref.mouseLeaveHandler;
ref.removeEventListener('mouseenter', ref.mouseEnterHandler);
delete ref.mouseEnterHandler;
ref.removeEventListener('mousemove', ref.mouseMoveHandler);
delete ref.mouseMoveHandler;
ref.removeEventListener('click', ref.clickHandler);
delete ref.clickHandler;
this.destroyResizable(ref);
},
destroyGauge: function (ref) {
if (ref._gaugeRTLObserver) {
ref._gaugeRTLObserver.disconnect();
delete ref._gaugeRTLObserver;
}
this.destroyResizable(ref);
},
destroyResizable: function (ref) {
if (ref.resizeObserver) {
ref.resizeObserver.disconnect();
delete ref.resizeObserver;
}
if (ref.resizeHandler) {
window.removeEventListener('resize', ref.resizeHandler);
delete ref.resizeHandler;
}
},
createResizable: function (ref, instance) {
ref.resizeHandler = function () {
var rect = ref.getBoundingClientRect();
try { instance.invokeMethodAsync('Resize', rect.width, rect.height); } catch { }
};
if (window.ResizeObserver) {
ref.resizeObserver = new ResizeObserver(ref.resizeHandler);
ref.resizeObserver.observe(ref);
} else {
window.addEventListener('resize', ref.resizeHandler);
}
var rect = ref.getBoundingClientRect();
return {width: rect.width, height: rect.height};
},
createChart: function (ref, instance) {
var inside = false;
ref.mouseMoveHandler = this.throttle(function (e) {
if (inside) {
var rect = ref.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
try { instance.invokeMethodAsync('MouseMove', x, y); } catch { }
}
}, 100);
ref.mouseEnterHandler = function () {
inside = true;
};
ref.mouseLeaveHandler = function (e) {
if (e.relatedTarget && (e.relatedTarget.matches('.rz-chart-tooltip') || e.relatedTarget.closest('.rz-chart-tooltip'))) {
return;
}
inside = false;
try { instance.invokeMethodAsync('MouseMove', -1, -1); } catch { }
};
ref.clickHandler = function (e) {
var rect = ref.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
if (!e.target.closest('.rz-marker') && !e.target.closest('.rz-legend-item')) {
try { instance.invokeMethodAsync('Click', x, y); } catch { }
}
};
ref.addEventListener('mouseenter', ref.mouseEnterHandler);
ref.addEventListener('mouseleave', ref.mouseLeaveHandler);
ref.addEventListener('mousemove', ref.mouseMoveHandler);
ref.addEventListener('click', ref.clickHandler);
return this.createResizable(ref, instance);
},
createGauge: function (ref, instance) {
var result = this.createResizable(ref, instance);
ref._gaugeRTLObserver = new MutationObserver(function () {
try { instance.invokeMethodAsync('SetRTL', document.documentElement.dir === 'rtl'); } catch (e) { }
});
ref._gaugeRTLObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['dir'] });
try { instance.invokeMethodAsync('SetRTL', document.documentElement.dir === 'rtl'); } catch (e) { }
return result;
},
innerHTML: function (ref, value) {
if (value != undefined) {
if (ref != null) {
ref.innerHTML = value;
}
} else {
return ref.innerHTML;
}
},
execCommand: function (ref, name, value) {
if (document.activeElement != ref && ref) {
ref.focus();
}
document.execCommand(name, false, value);
return this.queryCommands(ref);
},
queryCommands: function (ref) {
return {
html: ref != null ? ref.innerHTML : null,
fontName: document.queryCommandValue('fontName'),
fontSize: document.queryCommandValue('fontSize'),
formatBlock: document.queryCommandValue('formatBlock'),
bold: document.queryCommandState('bold'),
underline: document.queryCommandState('underline'),
justifyRight: document.queryCommandState('justifyRight'),
justifyLeft: document.queryCommandState('justifyLeft'),
justifyCenter: document.queryCommandState('justifyCenter'),
justifyFull: document.queryCommandState('justifyFull'),
italic: document.queryCommandState('italic'),
strikeThrough: document.queryCommandState('strikeThrough'),
superscript: document.queryCommandState('superscript'),
subscript: document.queryCommandState('subscript'),
unlink: document.queryCommandEnabled('unlink'),
undo: document.queryCommandEnabled('undo'),
redo: document.queryCommandEnabled('redo')
};
},
mediaQueries: {},
mediaQuery: function(query, instance) {
if (instance) {
function callback(event) {
try { instance.invokeMethodAsync('OnChange', event.matches); } catch { }
};
var query = matchMedia(query);
this.mediaQueries[instance._id] = function() {
query.removeListener(callback);
}
query.addListener(callback);
return query.matches;
} else {
instance = query;
if (this.mediaQueries[instance._id]) {
this.mediaQueries[instance._id]();
delete this.mediaQueries[instance._id];
}
}
},
createEditor: function (ref, uploadUrl, paste, instance, shortcuts) {
ref.inputListener = function () {
try { instance.invokeMethodAsync('OnChange', ref.innerHTML); } catch { }
};
ref.keydownListener = function (e) {
var key = '';
if (e.ctrlKey || e.metaKey) {
key += 'Ctrl+';
}
if (e.altKey) {
key += 'Alt+';
}
if (e.shiftKey) {
key += 'Shift+';
}
key += e.code.replace('Key', '').replace('Digit', '').replace('Numpad', '');
if (shortcuts.includes(key)) {
e.preventDefault();
try { instance.invokeMethodAsync('ExecuteShortcutAsync', key); } catch { }
}
};
ref.clickListener = function (e) {
if (e.target) {
if (e.target.matches('a,button')) {
e.preventDefault();
}
for (var img of ref.querySelectorAll('img.rz-state-selected')) {
img.classList.remove('rz-state-selected');
}
if (e.target.matches('img')) {
e.target.classList.add('rz-state-selected');
var range = document.createRange();
range.selectNode(e.target);
getSelection().removeAllRanges();
getSelection().addRange(range);
}
}
}
ref.selectionChangeListener = function () {
if (document.activeElement == ref) {
try { instance.invokeMethodAsync('OnSelectionChange'); } catch { }
}
};
ref.handleInsert = function (e, transfer, hasDelegate) {
var hasFiles = transfer.files.length > 0;
var hasHtml = transfer.types.indexOf('text/html') > -1;
var hasText = transfer.types.indexOf('text/plain') > -1;
if (hasFiles && !hasHtml && !hasText) {
for (const file of transfer.files) {
ref.handleFileInsert(e, file, hasDelegate);
}
}
else if (hasDelegate) {
ref.handleTextInsert(e, transfer);
}
};
ref.handleFileInsert = function (event, file, hasDelegate) {
event.preventDefault();
if (uploadUrl) {
var xhr = new XMLHttpRequest();
var data = new FormData();
data.append("file", file);
xhr.onreadystatechange = function (e) {
if (xhr.readyState === XMLHttpRequest.DONE) {
var status = xhr.status;
if (status === 0 || (status >= 200 && status < 400)) {
var result = JSON.parse(xhr.responseText);
var html = '
';
if (hasDelegate) {
try { instance.invokeMethodAsync('OnPaste', html)
.then(function (html) {
document.execCommand("insertHTML", false, html);
}); } catch { }
} else {
document.execCommand("insertHTML", false, '
');
}
try { instance.invokeMethodAsync('OnUploadComplete', xhr.responseText); } catch { }
} else {
try { instance.invokeMethodAsync('OnError', xhr.responseText); } catch { }
}
}
}
try { instance.invokeMethodAsync('GetHeaders').then(function (headers) {
xhr.open('POST', uploadUrl, true);
for (var name in headers) {
xhr.setRequestHeader(name, headers[name]);
}
xhr.send(data);
}); } catch { }
} else {
var reader = new FileReader();
reader.onload = function (e) {
var html = '
';
if (hasDelegate) {
try { instance.invokeMethodAsync('OnPaste', html)
.then(function (html) {
document.execCommand("insertHTML", false, html);
}); } catch { }
} else {
document.execCommand("insertHTML", false, html);
}
};
reader.readAsDataURL(file);
}
}
ref.handleTextInsert = function (e, transfer) {
e.preventDefault();
var data = transfer.getData('text/html') || transfer.getData('text/plain');
const startMarker = "";
const endMarker = "";
const startIndex = data.indexOf(startMarker);
const endIndex = data.indexOf(endMarker);
// check if the pasted data contains fragment markers
if (startIndex != -1 || endIndex != -1 || endIndex > startIndex) {
// only paste the fragment
data = data.substring(startIndex + startMarker.length, endIndex).trim();
}
try { instance.invokeMethodAsync('OnPaste', data)
.then(ref.focus())
.then(function (html) {
document.execCommand("insertHTML", false, html);
}); } catch { }
}
ref.pasteListener = function (e) {
ref.handleInsert(e, e.clipboardData, paste);
};
ref.dropListener = function (e) {
ref.handleInsert(e, e.dataTransfer, paste);
};
ref.addEventListener('input', ref.inputListener);
ref.addEventListener('paste', ref.pasteListener);
ref.addEventListener('drop', ref.dropListener);
ref.addEventListener('keydown', ref.keydownListener);
ref.addEventListener('click', ref.clickListener);
document.addEventListener('selectionchange', ref.selectionChangeListener);
document.execCommand('styleWithCSS', false, true);
},
saveSelection: function (ref) {
if (!ref) return;
var selection = getSelection();
if (selection.rangeCount > 0) {
var range = selection.getRangeAt(0);
if (ref.contains(range.commonAncestorContainer)) {
ref.range = range;
}
}
},
restoreSelection: function (ref) {
if (!ref) return;
var range = ref.range;
if (range) {
delete ref.range;
if(ref) {
ref.focus();
}
var selection = getSelection();
selection.removeAllRanges();
selection.addRange(range);
}
},
selectionAttributes: function (selector, attributes, container) {
var selection = getSelection();
var range = selection.rangeCount > 0 && selection.getRangeAt(0);
var parent = range && range.commonAncestorContainer;
var img = container.querySelector('img.rz-state-selected');
var inside = img && selector == 'img';
while (parent) {
if (parent == container) {
inside = true;
break;
}
parent = parent.parentNode;
}
if (!inside) {
return {};
}
var target = selection.focusNode;
var innerHTML;
if (img && selector == 'img') {
target = img;
} else if (target) {
if (target.nodeType == 3) {
target = target.parentElement;
} else {
if (img) {
target = target.childNodes[range.startOffset]
} else {
target = target.childNodes[selection.focusOffset];
}
if (target) {
innerHTML = target.outerHTML;
}
}
if (target && target.matches && !target.matches(selector)) {
target = target.closest(selector);
}
}
return attributes.reduce(function (result, name) {
if (target) {
result[name] = name == 'innerText' ? target[name] : target.getAttribute(name);
}
return result;
}, { innerText: selection.toString(), innerHTML: innerHTML });
},
destroyEditor: function (ref) {
if (ref) {
ref.removeEventListener('input', ref.inputListener);
ref.removeEventListener('paste', ref.pasteListener);
ref.removeEventListener('drop', ref.dropListener);
ref.removeEventListener('keydown', ref.keydownListener);
ref.removeEventListener('click', ref.clickListener);
document.removeEventListener('selectionchange', ref.selectionChangeListener);
}
},
startDrag: function (ref, instance, handler) {
if (!ref) {
return { left: 0, top: 0, width: 0, height: 0 };
}
ref.mouseMoveHandler = function (e) {
try { instance.invokeMethodAsync(handler, { clientX: e.clientX, clientY: e.clientY }); } catch { }
};
ref.touchMoveHandler = function (e) {
if (e.targetTouches[0] && ref.contains(e.targetTouches[0].target)) {
try { instance.invokeMethodAsync(handler, { clientX: e.targetTouches[0].clientX, clientY: e.targetTouches[0].clientY }); } catch { }
}
};
ref.mouseUpHandler = function (e) {
Radzen.endDrag(ref);
};
document.addEventListener('mousemove', ref.mouseMoveHandler);
document.addEventListener('mouseup', ref.mouseUpHandler);
document.addEventListener('touchmove', ref.touchMoveHandler, { passive: true, capture: true })
document.addEventListener('touchend', ref.mouseUpHandler, { passive: true });
return Radzen.clientRect(ref);
},
submit: function (form) {
form.submit();
},
clientRect: function (arg) {
var el = arg instanceof Element || arg instanceof HTMLDocument
? arg
: document.getElementById(arg);
var rect = el.getBoundingClientRect();
return { left: rect.left, top: rect.top, width: rect.width, height: rect.height };
},
outerHTML: function (arg) {
var el = arg instanceof Element || arg instanceof HTMLDocument
? arg
: document.getElementById(arg);
return el ? el.outerHTML : '';
},
endDrag: function (ref) {
document.removeEventListener('mousemove', ref.mouseMoveHandler);
document.removeEventListener('mouseup', ref.mouseUpHandler);
document.removeEventListener('touchmove', ref.touchMoveHandler)
document.removeEventListener('touchend', ref.mouseUpHandler);
},
startColumnReorder: function(id, gridId, gridRef) {
var grid = document.getElementById(gridId);
var el = document.getElementById(id + '-drag');
Radzen[id + 'cell'] = el.parentNode.parentNode;
var visual = document.createElement("th");
visual.className = Radzen[id + 'cell'].className + ' rz-column-draggable';
visual.style = Radzen[id + 'cell'].style;
visual.style.display = 'none';
visual.style.position = 'absolute';
visual.style.height = Radzen[id + 'cell'].offsetHeight + 'px';
visual.style.width = Radzen[id + 'cell'].offsetWidth + 'px';
visual.style.zIndex = 2000;
visual.style.pointerEvents = 'none';
visual.innerHTML = Radzen[id + 'cell'].firstChild.outerHTML;
visual.id = id + 'visual';
document.body.appendChild(visual);
var resizers = Radzen[id + 'cell'].parentNode.querySelectorAll('.rz-column-resizer');
for (let i = 0; i < resizers.length; i++) {
resizers[i].style.display = 'none';
}
Radzen[id + 'lastTouchX'] = null;
Radzen[id + 'lastTouchY'] = null;
Radzen[id + 'end'] = function (e) {
var triggeredByTouch = e && (e.type === 'touchend' || e.type === 'touchcancel');
var touchX = Radzen[id + 'lastTouchX'];
var touchY = Radzen[id + 'lastTouchY'];
if (triggeredByTouch && e.changedTouches && e.changedTouches[0]) {
touchX = e.changedTouches[0].clientX;
touchY = e.changedTouches[0].clientY;
}
var el = document.getElementById(id + 'visual');
if (el) {
document.body.removeChild(el);
var resizers = Radzen[id + 'cell'].parentNode.querySelectorAll('.rz-column-resizer');
for (let i = 0; i < resizers.length; i++) {
resizers[i].style.display = 'block';
}
}
grid.removeEventListener('mousemove', Radzen[id + 'move']);
grid.removeEventListener('touchmove', Radzen[id + 'touchmove']);
grid.removeEventListener('click', Radzen[id + 'end']);
document.removeEventListener('mouseup', Radzen[id + 'end']);
document.removeEventListener('touchend', Radzen[id + 'end']);
document.removeEventListener('touchcancel', Radzen[id + 'end']);
Radzen[id + 'end'] = null;
Radzen[id + 'move'] = null;
Radzen[id + 'touchmove'] = null;
Radzen[id + 'lastTouchX'] = null;
Radzen[id + 'lastTouchY'] = null;
if (triggeredByTouch && gridRef && touchX != null && touchY != null) {
var target = document.elementFromPoint(touchX, touchY);
if (target && grid.contains(target)) {
var groupHeader = target.closest('.rz-group-header');
if (groupHeader && grid.contains(groupHeader)) {
try { gridRef.invokeMethodAsync('RadzenGrid.OnColumnDropToGroup'); } catch { }
return;
}
var th = target.closest('th[data-column-index]');
if (th && grid.contains(th)) {
var columnIndex = parseInt(th.getAttribute('data-column-index'), 10);
if (!isNaN(columnIndex)) {
try { gridRef.invokeMethodAsync('RadzenGrid.OnColumnReorderEnded', columnIndex); } catch { }
}
}
}
}
}
grid.removeEventListener('click', Radzen[id + 'end']);
grid.addEventListener('click', Radzen[id + 'end']);
document.removeEventListener('mouseup', Radzen[id + 'end']);
document.addEventListener('mouseup', Radzen[id + 'end']);
document.removeEventListener('touchend', Radzen[id + 'end']);
document.addEventListener('touchend', Radzen[id + 'end'], { passive: true });
document.removeEventListener('touchcancel', Radzen[id + 'end']);
document.addEventListener('touchcancel', Radzen[id + 'end'], { passive: true });
Radzen[id + 'move'] = function (e) {
var el = document.getElementById(id + 'visual');
if (el) {
el.style.display = 'block';
if (/Edge/.test(navigator.userAgent)) {
var scrollLeft = document.body.scrollLeft;
var scrollTop = document.body.scrollTop;
} else {
var scrollLeft = document.documentElement.scrollLeft;
var scrollTop = document.documentElement.scrollTop;
}
el.style.top = e.clientY + scrollTop + 10 + 'px';
el.style.left = e.clientX + scrollLeft + 10 + 'px';
}
}
grid.removeEventListener('mousemove', Radzen[id + 'move']);
grid.addEventListener('mousemove', Radzen[id + 'move']);
Radzen[id + 'touchmove'] = function (e) {
if (e.touches && e.touches[0]) {
Radzen[id + 'lastTouchX'] = e.touches[0].clientX;
Radzen[id + 'lastTouchY'] = e.touches[0].clientY;
Radzen[id + 'move']({ clientX: e.touches[0].clientX, clientY: e.touches[0].clientY });
if (e.cancelable) {
e.preventDefault();
}
}
}
grid.removeEventListener('touchmove', Radzen[id + 'touchmove']);
grid.addEventListener('touchmove', Radzen[id + 'touchmove'], { passive: false });
},
stopColumnResize: function (id, grid, columnIndex) {
var el = document.getElementById(id + '-resizer');
if(!el) return;
var cell = el.parentNode.parentNode;
if (!cell) return;
if (Radzen[el]) {
try { grid.invokeMethodAsync(
'RadzenGrid.OnColumnResized',
columnIndex,
cell.getBoundingClientRect().width
); } catch { }
el.style.width = null;
document.removeEventListener('mousemove', Radzen[el].mouseMoveHandler);
document.removeEventListener('mouseup', Radzen[el].mouseUpHandler);
document.removeEventListener('touchmove', Radzen[el].touchMoveHandler)
document.removeEventListener('touchend', Radzen[el].mouseUpHandler);
Radzen[el] = null;
}
},
updateFrozenColumnPositions: function(gridElement) {
if (!gridElement) return;
// Get frozen cell positions from the header row first, then apply to all rows
var headerRow = gridElement.querySelector('thead tr');
if (!headerRow) return;
var leftHeaderCells = headerRow.querySelectorAll('.rz-frozen-cell-left, .rz-frozen-cell-left-end, .rz-frozen-cell-left-inner');
var rightHeaderCells = headerRow.querySelectorAll('.rz-frozen-cell-right, .rz-frozen-cell-right-end, .rz-frozen-cell-right-inner');
// Calculate offsets from header widths
var leftOffsets = [];
var offset = 0;
for (var i = 0; i < leftHeaderCells.length; i++) {
leftOffsets.push(offset);
offset += leftHeaderCells[i].getBoundingClientRect().width;
}
var rightOffsets = [];
offset = 0;
for (var i = rightHeaderCells.length - 1; i >= 0; i--) {
rightOffsets[i] = offset;
offset += rightHeaderCells[i].getBoundingClientRect().width;
}
// Apply offsets to all rows
var rows = gridElement.querySelectorAll('tr');
for (var r = 0; r < rows.length; r++) {
var row = rows[r];
var leftCells = row.querySelectorAll('.rz-frozen-cell-left, .rz-frozen-cell-left-end, .rz-frozen-cell-left-inner');
for (var i = 0; i < leftCells.length && i < leftOffsets.length; i++) {
leftCells[i].style.setProperty('inset-inline-start', leftOffsets[i] + 'px');
}
var rightCells = row.querySelectorAll('.rz-frozen-cell-right, .rz-frozen-cell-right-end, .rz-frozen-cell-right-inner');
for (var i = 0; i < rightCells.length && i < rightOffsets.length; i++) {
rightCells[i].style.setProperty('inset-inline-end', rightOffsets[i] + 'px');
}
}
},
startColumnResize: function(id, grid, columnIndex, clientX) {
var el = document.getElementById(id + '-resizer');
var cell = el.parentNode.parentNode;
var col = document.getElementById(id + '-col');
var dataCol = document.getElementById(id + '-data-col');
var footerCol = document.getElementById(id + '-footer-col');
var isFrozen = cell.classList.contains('rz-frozen-cell');
var gridElement = isFrozen ? cell.closest('.rz-data-grid') : null;
Radzen[el] = {
clientX: clientX,
width: cell.getBoundingClientRect().width,
mouseUpHandler: function (e) {
if (Radzen[el]) {
try { grid.invokeMethodAsync(
'RadzenGrid.OnColumnResized',
columnIndex,
cell.getBoundingClientRect().width
); } catch { }
el.style.width = null;
document.removeEventListener('mousemove', Radzen[el].mouseMoveHandler);
document.removeEventListener('mouseup', Radzen[el].mouseUpHandler);
document.removeEventListener('touchmove', Radzen[el].touchMoveHandler)
document.removeEventListener('touchend', Radzen[el].mouseUpHandler);
Radzen[el] = null;
}
},
mouseMoveHandler: function (e) {
if (Radzen[el]) {
var widthFloat = (Radzen[el].width - (Radzen.isRTL(cell) ? -1 : 1) * (Radzen[el].clientX - e.clientX));
var minWidth = parseFloat(cell.style.minWidth || 0)
var maxWidth = parseFloat(cell.style.maxWidth || 0)
if (widthFloat < minWidth) {
widthFloat = minWidth;
}
if (cell.style.maxWidth && widthFloat > maxWidth) {
widthFloat = maxWidth;
}
var width = widthFloat + 'px';
if (cell) {
cell.style.width = width;
}
if (col) {
col.style.width = width;
}
if (dataCol) {
dataCol.style.width = width;
}
if (footerCol) {
footerCol.style.width = width;
}
if (gridElement) {
Radzen.updateFrozenColumnPositions(gridElement);
}
}
},
touchMoveHandler: function (e) {
if (e.targetTouches[0]) {
e.preventDefault();
Radzen[el].mouseMoveHandler(e.targetTouches[0]);
}
}
};
el.style.width = "100%";
document.addEventListener('mousemove', Radzen[el].mouseMoveHandler);
document.addEventListener('mouseup', Radzen[el].mouseUpHandler);
document.addEventListener('touchmove', Radzen[el].touchMoveHandler, { passive: false })
document.addEventListener('touchend', Radzen[el].mouseUpHandler);
},
startSplitterResize: function(id,
splitter,
paneId,
paneNextId,
orientation,
clientPos,
minValue,
maxValue,
minNextValue,
maxNextValue) {
var el = document.getElementById(id);
var pane = document.getElementById(paneId);
var paneNext = document.getElementById(paneNextId);
var paneLength;
var paneNextLength;
var panePerc;
var paneNextPerc;
var isHOrientation=orientation == 'Horizontal';
var totalLength = 0.0;
Array.from(el.children).forEach(element => {
totalLength += isHOrientation
? element.getBoundingClientRect().width
: element.getBoundingClientRect().height;
});
if (pane) {
paneLength = isHOrientation
? pane.getBoundingClientRect().width
: pane.getBoundingClientRect().height;
panePerc = (paneLength / totalLength * 100) + '%';
}
if (paneNext) {
paneNextLength = isHOrientation
? paneNext.getBoundingClientRect().width
: paneNext.getBoundingClientRect().height;
paneNextPerc = (paneNextLength / totalLength * 100) + '%';
}
function ensurevalue(value) {
if (!value)
return null;
value=value.trim().toLowerCase();
if (value.endsWith("%"))
return totalLength*parseFloat(value)/100;
if (value.endsWith("px"))
return parseFloat(value);
throw 'Invalid value';
}
minValue=ensurevalue(minValue);
maxValue=ensurevalue(maxValue);
minNextValue=ensurevalue(minNextValue);
maxNextValue=ensurevalue(maxNextValue);
Radzen[el] = {
clientPos: clientPos,
panePerc: parseFloat(panePerc),
paneNextPerc: isFinite(parseFloat(paneNextPerc)) ? parseFloat(paneNextPerc) : 0,
paneLength: paneLength,
paneNextLength: isFinite(paneNextLength) ? paneNextLength : 0,
mouseUpHandler: function(e) {
if (Radzen[el]) {
try { splitter.invokeMethodAsync(
'RadzenSplitter.OnPaneResized',
parseInt(pane.getAttribute('data-index')),
parseFloat(pane.style.flexBasis),
paneNext ? parseInt(paneNext.getAttribute('data-index')) : null,
paneNext ? parseFloat(paneNext.style.flexBasis) : null
); } catch { }
document.removeEventListener('pointerup', Radzen[el].mouseUpHandler);
document.removeEventListener('pointermove', Radzen[el].mouseMoveHandler);
el.removeEventListener('touchmove', preventDefaultAndStopPropagation);
Radzen[el] = null;
}
},
mouseMoveHandler: function(e) {
if (Radzen[el]) {
try { splitter.invokeMethodAsync(
'RadzenSplitter.OnPaneResizing'
); } catch { }
var spacePerc = Radzen[el].panePerc + Radzen[el].paneNextPerc;
var spaceLength = Radzen[el].paneLength + Radzen[el].paneNextLength;
var length = (Radzen[el].paneLength -
(isHOrientation && Radzen.isRTL(e.target) ? -1 : 1) * (Radzen[el].clientPos - (isHOrientation ? e.clientX : e.clientY)));
if (length > spaceLength)
length = spaceLength;
if (minValue && length < minValue) length = minValue;
if (maxValue && length > maxValue) length = maxValue;
if (paneNext) {
var nextSpace=spaceLength-length;
if (minNextValue && nextSpace < minNextValue) length = spaceLength-minNextValue;
if (maxNextValue && nextSpace > maxNextValue) length = spaceLength+maxNextValue;
}
var perc = length / Radzen[el].paneLength;
if (!isFinite(perc)) {
perc = 1;
Radzen[el].panePerc = 0.1;
Radzen[el].paneLength =isHOrientation
? pane.getBoundingClientRect().width
: pane.getBoundingClientRect().height;
}
var newPerc = Radzen[el].panePerc * perc;
if (newPerc < 0) newPerc = 0;
if (newPerc > 100) newPerc = 100;
pane.style.flexBasis = newPerc + '%';
if (paneNext)
paneNext.style.flexBasis = (spacePerc - newPerc) + '%';
}
},
touchMoveHandler: function(e) {
if (e.targetTouches[0]) {
Radzen[el].mouseMoveHandler(e.targetTouches[0]);
}
}
};
const preventDefaultAndStopPropagation = (ev) => {
ev.preventDefault();
ev.stopPropagation();
};
document.addEventListener('pointerup', Radzen[el].mouseUpHandler);
document.addEventListener('pointermove', Radzen[el].mouseMoveHandler);
el.addEventListener('touchmove', preventDefaultAndStopPropagation, { passive: false });
},
resizeSplitter(id, e) {
var el = document.getElementById(id);
if (el && Radzen[el]) {
Radzen[el].mouseMoveHandler(e);
Radzen[el].mouseUpHandler(e);
}
},
openWaiting: function() {
if (document.documentElement.scrollHeight > document.documentElement.clientHeight) {
document.body.classList.add('no-scroll');
}
if (Radzen.WaitingIntervalId != null) {
clearInterval(Radzen.WaitingIntervalId);
}
setTimeout(function() {
var timerObj = document.getElementsByClassName('rz-waiting-timer');
if (timerObj.length == 0) return;
var timerStart = new Date().getTime();
Radzen.WaitingIntervalId = setInterval(function() {
if (timerObj == null || timerObj[0] == null) {
clearInterval(Radzen.WaitingIntervalId);
} else {
var time = new Date(new Date().getTime() - timerStart);
timerObj[0].innerHTML = Math.floor(time / 1000) + "." + Math.floor((time % 1000) / 100);
}
},
100);
},
100);
},
closeWaiting: function() {
document.body.classList.remove('no-scroll');
if (Radzen.WaitingIntervalId != null) {
clearInterval(Radzen.WaitingIntervalId);
Radzen.WaitingIntervalId = null;
}
},
toggleDictation: function (componentRef, language) {
function start() {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SpeechRecognition) {
return;
}
radzenRecognition = new SpeechRecognition();
radzenRecognition.componentRef = componentRef;
radzenRecognition.continuous = true;
if (language) {
radzenRecognition.lang = language;
}
radzenRecognition.onresult = function (event) {
if (event.results.length < 1) {
return;
}
let current = event.results[event.results.length - 1][0]
let result = current.transcript;
try { componentRef.invokeMethodAsync("OnResult", result); } catch { }
};
radzenRecognition.onend = function (event) {
try { componentRef.invokeMethodAsync("StopRecording"); } catch { }
radzenRecognition = null;
};
radzenRecognition.start();
}
if (radzenRecognition) {
if (radzenRecognition.componentRef._id != componentRef._id) {
radzenRecognition.addEventListener('end', start);
}
radzenRecognition.stop();
} else {
start();
}
},
openChartTooltip: function (chart, x, y, id, instance, callback) {
Radzen.closeTooltip(id);
var chartRect = chart.getBoundingClientRect();
x = Math.max(2, chartRect.left + x);
y = Math.max(2, chartRect.top + y);
Radzen.openPopup(chart, id, false, null, x, y, instance, callback, true, false, false);
var popup = document.getElementById(id);
if (!popup) {
return;
}
var tooltipContent = popup.children[0];
var tooltipContentRect = tooltipContent.getBoundingClientRect();
var tooltipContentClassName = 'rz-top-chart-tooltip';
if (y - tooltipContentRect.height < 0) {
tooltipContentClassName = 'rz-bottom-chart-tooltip';
}
tooltipContent.classList.remove('rz-top-chart-tooltip');
tooltipContent.classList.remove('rz-bottom-chart-tooltip');
tooltipContent.classList.add(tooltipContentClassName);
},
createScrollListener: function (ref, selectors, selector) {
let currentSelector;
const container = selector ? document.querySelector(selector) : document.documentElement;
const elements = selectors.map(document.querySelector, document);
let rafId = null;
const scrollHandler = () => {
if (rafId !== null) {
return;
}
rafId = requestAnimationFrame(() => {
rafId = null;
const isHtml = !selector || container.tagName === 'HTML';
const threshold = isHtml ? 10 : container.getBoundingClientRect().top + 10;
const atBottom = isHtml
? window.scrollY > 0 && (window.innerHeight + window.scrollY) >= document.documentElement.scrollHeight - 2
: container.scrollTop > 0 && (container.scrollTop + container.clientHeight) >= container.scrollHeight - 2;
let match;
if (atBottom) {
for (let i = selectors.length - 1; i >= 0; i--) {
if (elements[i]) {
match = selectors[i];
break;
}
}
} else {
for (let i = elements.length - 1; i >= 0; i--) {
const element = elements[i];
if (!element) {
continue;
}
if (element.getBoundingClientRect().top <= threshold) {
match = selectors[i];
break;
}
}
}
if (match !== currentSelector) {
currentSelector = match;
try {
ref.invokeMethodAsync('ScrollIntoView', currentSelector);
} catch {
}
}
});
};
const scrollTarget = selector ? container : window;
scrollTarget.addEventListener('scroll', scrollHandler, { passive: true });
window.addEventListener('resize', scrollHandler, { passive: true });
scrollHandler();
return {
dispose() {
scrollTarget.removeEventListener('scroll', scrollHandler);
window.removeEventListener('resize', scrollHandler);
}
};
},
setTheme: function (href, wcagHref) {
const theme = document.getElementById('radzen-theme-link');
if (theme && theme.href != href) {
theme.href = href;
}
let wcagTheme = document.getElementById('radzen-wcag-theme-link');
if (!wcagTheme && wcagHref) {
wcagTheme = document.createElement('link');
wcagTheme.id = 'radzen-wcag-theme-link';
wcagTheme.rel = 'stylesheet';
wcagTheme.href = wcagHref;
theme.parentNode.insertBefore(wcagTheme, theme.nextSibling);
} else if (wcagTheme && wcagTheme.href != wcagHref) {
if (!wcagHref) {
wcagTheme.parentNode.removeChild(wcagTheme);
return;
} else {
wcagTheme.href = wcagHref;
}
}
},
createDraggable: function(element, ref, onDragStart) {
function handleDragStart(e) {
e.dataTransfer.setData('', e.target.id);
try { ref.invokeMethodAsync(onDragStart); } catch { }
}
element.draggable = true;
element.addEventListener('dragstart', handleDragStart);
return {
dispose() {
element.removeEventListener('dragstart', handleDragStart);
}
};
}
};
Radzen.registerFabMenu = function(element, dotnet){
if(!element) return;
if(element.__rzOutsideClickHandler){
document.removeEventListener('click', element.__rzOutsideClickHandler);
delete element.__rzOutsideClickHandler;
}
const handler = function(e){
if(!element.contains(e.target)){
try { dotnet.invokeMethodAsync('CloseAsync'); } catch { }
}
};
element.__rzOutsideClickHandler = handler;
document.addEventListener('click', handler);
};
Radzen.unregisterFabMenu = function(element){
if(!element) return;
const handler = element.__rzOutsideClickHandler;
if(handler){
document.removeEventListener('click', handler);
delete element.__rzOutsideClickHandler;
}
};
Radzen.chatIsNearBottom = function(container, threshold) {
if (!container) return true;
return container.scrollHeight - container.scrollTop - container.clientHeight <= (threshold || 50);
};
Radzen.chatScrollToBottom = function(container) {
if (!container) return;
container.scrollTop = container.scrollHeight;
};