PageSourceSearch

https://redb.ru/_content/Microsoft.FluentUI.AspNetCore.Components/…/FluentDataGrid.dvdt7c1hdi.razor.js

js redb.ru collected 2026-09-30 11:08:59 UTC 17,719 bytes, 477 lines download raw bytes

1let grids = [];
2
3export function init(gridElement, autoFocus) {
4    if (gridElement === undefined || gridElement === null) {
5        return;
6    };
7
8    enableColumnResizing(gridElement);
9
10    let start = gridElement.querySelector('td:first-child');
11
12    if (autoFocus) {
13        start.focus();
14    }
15
16    const bodyClickHandler = event => {
17        const columnOptionsElement = gridElement?.querySelector('.col-options');
18        if (columnOptionsElement && event.composedPath().indexOf(columnOptionsElement) < 0) {
19            gridElement.dispatchEvent(new CustomEvent('closecolumnoptions', { bubbles: true }));
20        }
21        const columnResizeElement = gridElement?.querySelector('.col-resize');
22        if (columnResizeElement && event.composedPath().indexOf(columnResizeElement) < 0) {
23            gridElement.dispatchEvent(new CustomEvent('closecolumnresize', { bubbles: true }));
24        }
25    };
26    const keyboardNavigation = (sibling) => {
27        if (sibling !== null) {
28            start.focus();
29            sibling.focus();
30            start = sibling;
31        }
32    }
33    const keyDownHandler = event => {
34        if (document.activeElement.tagName.toLowerCase() != 'table' && document.activeElement.tagName.toLowerCase() != 'td' && document.activeElement.tagName.toLowerCase() != 'th') {
35            return;
36        }
37        const columnOptionsElement = gridElement?.querySelector('.col-options');
38        if (columnOptionsElement) {
39            if (event.key === "Escape") {
40                gridElement.dispatchEvent(new CustomEvent('closecolumnoptions', { bubbles: true }));
41                gridElement.focus();
42            }
43            columnOptionsElement.addEventListener(
44                "keydown",
45                (event) => {
46                    if (event.key === "ArrowRight" || event.key === "ArrowLeft" || event.key === "ArrowDown" || event.key === "ArrowUp") {
47                        event.stopPropagation();
48                    }
49                }
50            );
51        }
52        const columnResizeElement = gridElement?.querySelector('.col-resize');
53        if (columnResizeElement) {
54            if (event.key === "Escape") {
55                gridElement.dispatchEvent(new CustomEvent('closecolumnresize', { bubbles: true }));
56                gridElement.focus();
57            }
58            columnResizeElement.addEventListener(
59                "keydown",
60                (event) => {
61                    if (event.key === "ArrowRight" || event.key === "ArrowLeft" || event.key === "ArrowDown" || event.key === "ArrowUp") {
62                        event.stopPropagation();
63                    }
64                }
65            );
66        }
67
68        // check if start is a child of gridElement
69        if (start !== null && (gridElement.contains(start) || gridElement === start) && document.activeElement === start && document.activeElement.tagName.toLowerCase() !== 'fluent-text-field' && document.activeElement.tagName.toLowerCase() !== 'fluent-menu-item') {
70            const idx = start.cellIndex;
71
72            if (event.key === "ArrowUp") {
73                // up arrow
74                const previousRow = start.parentElement.previousElementSibling;
75                if (previousRow !== null) {
76                    event.preventDefault();
77                    const previousSibling = previousRow.cells[idx];
78                    keyboardNavigation(previousSibling);
79                }
80            } else if (event.key === "ArrowDown") {
81                // down arrow
82                const nextRow = start.parentElement.nextElementSibling;
83                if (nextRow !== null) {
84                    event.preventDefault();
85                    const nextSibling = nextRow.cells[idx];
86                    keyboardNavigation(nextSibling);
87                }
88            } else if (event.key === "ArrowLeft") {
89                // left arrow
90                event.preventDefault();
91                const previousSibling = (document.body.dir === '' || document.body.dir === 'ltr') ? start.previousElementSibling : start.nextElementSibling;
92                keyboardNavigation(previousSibling);
93                event.stopPropagation();
94            } else if (event.key === "ArrowRight") {
95                // right arrow
96                event.preventDefault();
97                const nextsibling = (document.body.dir === '' || document.body.dir === 'ltr') ? start.nextElementSibling : start.previousElementSibling;
98                keyboardNavigation(nextsibling);
99                event.stopPropagation();
100            }
101        }
102        else {
103            start = document.activeElement;
104        }
105
106    };
107
108    const cells = gridElement.querySelectorAll('[role="gridcell"]');
109    cells.forEach((cell) => {
110        cell.columnDefinition = {
111            columnDataKey: "",
112            cellInternalFocusQueue: true,
113            cellFocusTargetCallback: (cell) => {
114                return cell.children[0];
115            }
116        }
117        cell.addEventListener(
118            "keydown",
119            (event) => {
120                if (event.target.role !== "gridcell" && (event.key === "ArrowRight" || event.key === "ArrowLeft")) {
121                    event.stopPropagation();
122                }
123            }
124        );
125    });
126
127    document.body.addEventListener('click', bodyClickHandler);
128    document.body.addEventListener('mousedown', bodyClickHandler); // Otherwise it seems strange that it doesn't go away until you release the mouse button
129    gridElement.addEventListener('keydown', keyDownHandler);
130
131    return {
132        stop: () => {
133            document.body.removeEventListener('click', bodyClickHandler);
134            document.body.removeEventListener('mousedown', bodyClickHandler);
135            gridElement.removeEventListener('keydown', keyDownHandler);
136            delete grids[gridElement];
137        }
138    };
139}
140
141export function checkColumnPopupPosition(gridElement, selector) {
142    const colPopup = gridElement.querySelector(selector);
143    if (colPopup) {
144        const gridRect = gridElement.getBoundingClientRect();
145        const popupRect = colPopup.getBoundingClientRect();
146        const leftOverhang = Math.max(0, gridRect.left - popupRect.left);
147        const rightOverhang = Math.max(0, popupRect.right - gridRect.right);
148        if (leftOverhang || rightOverhang) {
149            const applyOffset = leftOverhang && rightOverhang ? (leftOverhang - rightOverhang) / 2 : (leftOverhang - rightOverhang);
150            colPopup.style.transform = `translateX(${applyOffset}px)`;
151        }
152
153        colPopup.style.visibility = 'visible';
154        colPopup.scrollIntoViewIfNeeded();
155
156        const autoFocusElem = colPopup.querySelector('[autofocus]');
157        if (autoFocusElem) {
158            autoFocusElem.focus();
159        }
160    }
161}
162
163export function enableColumnResizing(gridElement, resizeColumnOnAllRows = true) {
164    const columns = [];
165    const headers = gridElement.querySelectorAll('.column-header.resizable');
166
167    if (headers.length === 0) {
168        return;
169    }
170
171    const isRTL = getComputedStyle(gridElement).direction === 'rtl';
172    const isGrid = gridElement.classList.contains('grid')
173
174    let tableHeight = gridElement.offsetHeight;
175    // rows have not been loaded yet, so we need to calculate the height
176    if (tableHeight < 70) {
177        // by getting the aria rowcount attribute
178        const rowCount = gridElement.getAttribute('aria-rowcount');
179        if (rowCount) {
180            const rowHeight = gridElement.querySelector('thead tr th').offsetHeight;
181            // and multiply by the itemsize (== height of the header cells)
182            tableHeight = rowCount * rowHeight;
183        }
184    }
185
186    // Determine the height based on the resizeColumnOnAllRows parameter
187    let resizeHandleHeight = tableHeight;
188    if (!resizeColumnOnAllRows) {
189        // Only use the header height when resizeColumnOnAllRows is false
190        // Use the first header's height if available
191        resizeHandleHeight = headers.length > 0 ? (headers[0].offsetHeight - 14 ): 30; // fallback to 30px if no headers
192    }
193
194    headers.forEach((header) => {
195        columns.push({
196            header,
197            size: `${header.clientWidth}px`,
198        });
199
200        // remove any previously created divs
201        const resizedivs  = header.querySelectorAll(".actual-resize-handle");
202        resizedivs.forEach(div => div.remove());
203
204        // add a new resize div
205        const div = createDiv(resizeHandleHeight, isRTL);
206        header.appendChild(div);
207        setListeners(div, isRTL);
208    });
209
210    let initialWidths;
211    if (gridElement.style.gridTemplateColumns) {
212        initialWidths = gridElement.style.gridTemplateColumns;
213    } else {
214        initialWidths = columns.map(({ size }) => size).join(' ');
215
216        if (isGrid) {
217            gridElement.style.gridTemplateColumns = initialWidths;
218        }
219    }
220
221    const id = gridElement.id;
222    if (!grids.find(grid => grid.id === id)) {
223        grids.push({
224            id,
225            columns,
226            initialWidths,
227        });
228    }
229
230    function setListeners(div, isRTL) {
231        let pageX, curCol, curColWidth;
232
233        div.addEventListener('pointerdown', function (e) {
234            curCol = e.target.parentElement;
235            pageX = e.pageX;
236
237            const padding = paddingDiff(curCol);
238
239            curColWidth = curCol.offsetWidth - padding;
240        });
241
242        div.addEventListener('pointerover', function (e) {
243            e.target.style.borderInlineEnd = 'var(--fluent-data-grid-resize-handle-width) solid var(--fluent-data-grid-resize-handle-color)';
244            e.target.previousElementSibling.style.visibility = 'hidden';
245        });
246
247        div.addEventListener('pointerup', removeBorder);
248        div.addEventListener('pointercancel', removeBorder);
249        div.addEventListener('pointerleave', removeBorder);
250
251        document.addEventListener('pointermove', (e) =>
252            requestAnimationFrame(() => {
253                gridElement.style.tableLayout = 'fixed';
254
255                if (curCol) {
256                    const diffX = isRTL ? pageX - e.pageX : e.pageX - pageX;
257                    const column = columns.find(({ header }) => header === curCol);
258
259                    column.size = parseInt(Math.max(parseInt(column.header.style.minWidth), curColWidth + diffX), 10) + 'px';
260
261                    columns.forEach((col) => {
262                        if (col.size.startsWith('minmax')) {
263                            col.size = parseInt(col.header.clientWidth, 10) + 'px';
264                        }
265                    });
266
267                    if (isGrid) {
268                        gridElement.style.gridTemplateColumns = columns
269                            .map(({ size }) => size)
270                            .join(' ');
271                    }
272                    else {
273                        curCol.style.width = column.size;
274                    }
275                }
276            })
277        );
278
279        document.addEventListener('pointerup', function () {
280            curCol = undefined;
281            curColWidth = undefined;
282            pageX = undefined;
283        });
284    }
285
286    function createDiv(height, isRTL) {
287        const div = document.createElement('div');
288        div.className = "actual-resize-handle";
289        div.style.top = '5px';
290        div.style.position = 'absolute';
291        div.style.cursor = 'col-resize';
292        div.style.userSelect = 'none';
293        div.style.height = (height - 5) + 'px';
294        div.style.width = '6px';
295        div.style.opacity = 'var(--fluent-data-grid-header-opacity)'
296
297        if (isRTL) {
298            div.style.left = '0px';
299            div.style.right = 'unset';
300        } else {
301            div.style.left = 'unset';
302            div.style.right = '0px';
303        }
304        return div;
305    }
306
307    function paddingDiff(col) {
308        if (getStyleVal(col, 'box-sizing') === 'border-box') {
309            return 0;
310        }
311
312        const padLeft = getStyleVal(col, 'padding-left');
313        const padRight = getStyleVal(col, 'padding-right');
314        return parseInt(padLeft) + parseInt(padRight);
315    }
316
317    function getStyleVal(elm, css) {
318        return window.getComputedStyle(elm, null).getPropertyValue(css);
319    }
320
321    function removeBorder(e) {
322        e.target.style.borderInlineEnd = '';
323        e.target.previousElementSibling.style.visibility = 'visible';
324    }
325}
326
327
328
329export function resetColumnWidths(gridElement) {
330    const isGrid = gridElement.classList.contains('grid');
331    const grid = grids.find(({ id }) => id === gridElement.id);
332    if (!grid) {
333        return;
334    }
335
336    const columnsWidths = grid.initialWidths.split(' ');
337
338    grid.columns.forEach((column, index) => {
339        if (isGrid) {
340            column.size = columnsWidths[index];
341        } else {
342            column.header.style.width = columnsWidths[index];
343        }
344    });
345
346    if (isGrid) {
347        gridElement.style.gridTemplateColumns = grid.initialWidths;
348    }
349    gridElement.dispatchEvent(
350        new CustomEvent('closecolumnresize', { bubbles: true })
351    );
352    gridElement.focus();
353}
354
355export function resizeColumnDiscrete(gridElement, column, change) {
356    const isGrid = gridElement.classList.contains('grid');
357    const columns = [];
358    let headerBeingResized;
359
360    if (!column) {
361        const targetElement = document.activeElement.parentElement.parentElement.parentElement.parentElement;
362        if (!(targetElement.classList.contains("column-header") && targetElement.classList.contains("resizable"))) {
363            return;
364        }
365        headerBeingResized = targetElement;
366    }
367    else {
368        headerBeingResized = gridElement.querySelector('.column-header[col-index="' + column + '"]');
369    }
370
371
372    grids.find(({ id }) => id === gridElement.id).columns.forEach(column => {
373        if (column.header === headerBeingResized) {
374            const width = headerBeingResized.offsetWidth + change; //.getBoundingClientRect().width + change;
375
376            if (change < 0) {
377                column.size = Math.max(parseInt(column.header.style.minWidth), width) + 'px';
378            }
379            else {
380                column.size = width + 'px';
381            }
382            column.header.style.width = column.size;
383        }
384        if (isGrid) {
385            // for grid we need to recalculate all columns that are minmax
386            if (column.size.startsWith('minmax')) {
387                column.size = parseInt(column.header.clientWidth, 10) + 'px';
388            }
389            columns.push(column.size);
390        }
391    });
392
393    if (isGrid) {
394        gridElement.style.gridTemplateColumns = columns.join(' ');
395    }
396}
397
398export function resizeColumnExact(gridElement, column, width) {
399    const isGrid = gridElement.classList.contains('grid');
400    const columns = [];
401    let headerBeingResized = gridElement.querySelector('.column-header[col-index="' + column + '"]');
402
403    if (!headerBeingResized) {
404        return;
405    }
406
407    grids.find(({ id }) => id === gridElement.id).columns.forEach(column => {
408        if (column.header === headerBeingResized) {
409            column.size = Math.max(parseInt(column.header.style.minWidth), width) + 'px';
410            column.header.style.width = column.size;
411        }
412        if (isGrid) {
413            // for grid we need to recalculate all columns that are minmax
414            if (column.size.startsWith('minmax')) {
415                column.size = parseInt(column.header.clientWidth, 10) + 'px';
416            }
417            column.header.style.width = column.size;
418            columns.push(column.size);
419        }
420    });
421
422    if (isGrid) {
423        gridElement.style.gridTemplateColumns = columns.join(' ');
424    }
425
426    gridElement.dispatchEvent(new CustomEvent('closecolumnresize', { bubbles: true }));
427    gridElement.focus();
428}
429
430export function autoFitGridColumns(gridElement, columnCount) {
431    let gridTemplateColumns = '';
432
433    for (var i = 0; i < columnCount; i++) {
434        const columnWidths = Array
435            .from(gridElement.querySelectorAll(`[col-index="${i + 1}"]`))
436            .flatMap((x) => x.offsetWidth);
437
438        const maxColumnWidth = Math.max(...columnWidths);
439
440        gridTemplateColumns += ` ${maxColumnWidth}px`;
441    }
442
443    gridElement.style.gridTemplateColumns = gridTemplateColumns;
444    gridElement.classList.remove("auto-fit");
445
446    grids[gridElement.id] = gridTemplateColumns;
447}
448
449function calculateVisibleRows(gridElement, rowHeight) {
450    if (rowHeight <= 0) {
451        return 0;
452    }
453
454    const gridContainer = gridElement.parentElement;
455
456    if (!gridContainer) {
457        return 0;
458    }
459
460    const availableHeight = gridContainer?.clientHeight || window.visualViewport?.height || window.innerHeight;
461
462    const visibleRows = Math.max(Math.floor(availableHeight / rowHeight), 1);
463    return visibleRows;
464}
465
466export function dynamicItemsPerPage(gridElement, dotNetObject, rowSize) {
467    const observer = new ResizeObserver(() => {
468        const visibleRows = calculateVisibleRows(gridElement, rowSize)
469        dotNetObject.invokeMethodAsync('UpdateItemsPerPageAsync', visibleRows)
470            .catch(err => console.error("Error invoking Blazor method:", err));
471    });
472
473    const targetElement = gridElement.parentElement;
474    if (targetElement) {
475        observer.observe(targetElement);
476    }
477}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.