known issue: tooltip position
This commit is contained in:
		@@ -17,6 +17,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    & {
 | 
					    & {
 | 
				
			||||||
        --hover-bg-color: lightyellow;
 | 
					        --hover-bg-color: lightyellow;
 | 
				
			||||||
 | 
					        --link-fore-color: #1890ff;
 | 
				
			||||||
        --header-border-color: #adaba9;
 | 
					        --header-border-color: #adaba9;
 | 
				
			||||||
        --header-bg-color: #fafafa;
 | 
					        --header-bg-color: #fafafa;
 | 
				
			||||||
        --header-fore-color: #000;
 | 
					        --header-fore-color: #000;
 | 
				
			||||||
@@ -281,6 +282,26 @@
 | 
				
			|||||||
                            top: calc(var(--line-height) + 2px);
 | 
					                            top: calc(var(--line-height) + 2px);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    .icon {
 | 
				
			||||||
 | 
					                        display: flex;
 | 
				
			||||||
 | 
					                        cursor: pointer;
 | 
				
			||||||
 | 
					                        height: var(--line-height);
 | 
				
			||||||
 | 
					                        justify-content: center;
 | 
				
			||||||
 | 
					                        align-items: center;
 | 
				
			||||||
 | 
					                        position: relative;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        svg {
 | 
				
			||||||
 | 
					                            width: 16px;
 | 
				
			||||||
 | 
					                            height: 16px;
 | 
				
			||||||
 | 
					                            fill: var(--link-fore-color);
 | 
				
			||||||
 | 
					                            transition: opacity .12s ease;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        &:hover svg {
 | 
				
			||||||
 | 
					                            opacity: .4;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,7 @@
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.tooltip-wrapper {
 | 
					.tooltip-wrapper {
 | 
				
			||||||
    position: fixed;
 | 
					    position: absolute;
 | 
				
			||||||
    word-wrap: break-word;
 | 
					    word-wrap: break-word;
 | 
				
			||||||
    height: auto;
 | 
					    height: auto;
 | 
				
			||||||
    text-align: left;
 | 
					    text-align: left;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,7 +58,8 @@
 | 
				
			|||||||
          enabled: 'enabled'
 | 
					          enabled: 'enabled'
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        { key: 'c3', caption: 'column 3', width: 90 },
 | 
					        { key: 'c3', caption: 'column 3', width: 90 },
 | 
				
			||||||
        { key: 'c4', caption: 'Note', type: Grid.ColumnTypes.Input }
 | 
					        { key: 'c4', caption: 'Note', type: Grid.ColumnTypes.Input },
 | 
				
			||||||
 | 
					        { key: 'c5', type: Grid.ColumnTypes.Icon, text: 'times', tooltip: 'Delete' }
 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
      grid.columnChanged = (type, index, value) => console.log(`column (${index}), ${type}, ${value}`);
 | 
					      grid.columnChanged = (type, index, value) => console.log(`column (${index}), ${type}, ${value}`);
 | 
				
			||||||
      grid.cellClicked = (rId, cId) => console.log(`row (${rId}), column (${cId}) clicked.`);
 | 
					      grid.cellClicked = (rId, cId) => console.log(`row (${rId}), column (${cId}) clicked.`);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,10 @@
 | 
				
			|||||||
import { global, isPositive, isMobile, throttle, truncate } from "../utility";
 | 
					import { global, isPositive, isMobile, throttle, truncate } from "../utility";
 | 
				
			||||||
import { nullOrEmpty } from "../utility/strings";
 | 
					import { nullOrEmpty } from "../utility/strings";
 | 
				
			||||||
import { r } from "../utility/lgres";
 | 
					import { r } from "../utility/lgres";
 | 
				
			||||||
import { createIcon } from "../ui/icon";
 | 
					import { createIcon } from "./icon";
 | 
				
			||||||
import { createCheckbox } from "../ui/checkbox";
 | 
					import { createCheckbox } from "./checkbox";
 | 
				
			||||||
import Dropdown from "../ui/dropdown";
 | 
					import { setTooltip } from "./tooltip";
 | 
				
			||||||
 | 
					import Dropdown from "./dropdown";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ColumnChangedType = {
 | 
					const ColumnChangedType = {
 | 
				
			||||||
    Reorder: 'reorder',
 | 
					    Reorder: 'reorder',
 | 
				
			||||||
@@ -44,8 +45,6 @@ class GridColumn {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    static setValue(element, val) { element.innerText = val }
 | 
					    static setValue(element, val) { element.innerText = val }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static getValue(element) { return element.innerText }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static setStyle(element, style) {
 | 
					    static setStyle(element, style) {
 | 
				
			||||||
        for (let css of Object.entries(style)) {
 | 
					        for (let css of Object.entries(style)) {
 | 
				
			||||||
            element.style.setProperty(css[0], css[1]);
 | 
					            element.style.setProperty(css[0], css[1]);
 | 
				
			||||||
@@ -157,11 +156,45 @@ class GridCheckboxColumn extends GridColumn {
 | 
				
			|||||||
    static setEnabled(element, enabled) { element.querySelector('input').disabled = enabled === false }
 | 
					    static setEnabled(element, enabled) { element.querySelector('input').disabled = enabled === false }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GridIconColumn extends GridColumn {
 | 
				
			||||||
 | 
					    static create() {
 | 
				
			||||||
 | 
					        const element = document.createElement('span');
 | 
				
			||||||
 | 
					        element.className = 'icon';
 | 
				
			||||||
 | 
					        // element.appendChild(document.createElement('layer'));
 | 
				
			||||||
 | 
					        return element;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static setValue(element, val, item, col) {
 | 
				
			||||||
 | 
					        let type = col.iconType;
 | 
				
			||||||
 | 
					        if (typeof type === 'function') {
 | 
				
			||||||
 | 
					            type = type(item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        type ??= 'fa-regular';
 | 
				
			||||||
 | 
					        if (element.dataset.type !== type || element.dataset.icon !== val) {
 | 
				
			||||||
 | 
					            const icon = createIcon(type, val);
 | 
				
			||||||
 | 
					            // const layer = element.children[0];
 | 
				
			||||||
 | 
					            element.replaceChildren(icon);
 | 
				
			||||||
 | 
					            !nullOrEmpty(col.tooltip) && setTooltip(icon, col.tooltip);
 | 
				
			||||||
 | 
					            element.dataset.type = type;
 | 
				
			||||||
 | 
					            element.dataset.icon = val;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static setEnabled(element, enabled) {
 | 
				
			||||||
 | 
					        if (enabled === false) {
 | 
				
			||||||
 | 
					            element.classList.add('disabled');
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            element.classList.remove('disabled');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ColumnTypes = {
 | 
					const ColumnTypes = {
 | 
				
			||||||
    0: GridColumn,
 | 
					    0: GridColumn,
 | 
				
			||||||
    1: GridInputColumn,
 | 
					    1: GridInputColumn,
 | 
				
			||||||
    2: GridDropdownColumn,
 | 
					    2: GridDropdownColumn,
 | 
				
			||||||
    3: GridCheckboxColumn
 | 
					    3: GridCheckboxColumn,
 | 
				
			||||||
 | 
					    4: GridIconColumn
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Grid {
 | 
					class Grid {
 | 
				
			||||||
@@ -215,6 +248,7 @@ class Grid {
 | 
				
			|||||||
        Input: 1,
 | 
					        Input: 1,
 | 
				
			||||||
        Dropdown: 2,
 | 
					        Dropdown: 2,
 | 
				
			||||||
        Checkbox: 3,
 | 
					        Checkbox: 3,
 | 
				
			||||||
 | 
					        Icon: 4,
 | 
				
			||||||
        isCheckbox(type) { return type === 3 }
 | 
					        isCheckbox(type) { return type === 3 }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -533,7 +567,7 @@ class Grid {
 | 
				
			|||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                col.autoResize = true;
 | 
					                col.autoResize = true;
 | 
				
			||||||
                this.#needResize = true;
 | 
					                this.#needResize = true;
 | 
				
			||||||
                sizer.innerText = col.caption;
 | 
					                sizer.innerText = col.caption ?? '';
 | 
				
			||||||
                let width = sizer.offsetWidth + 22;
 | 
					                let width = sizer.offsetWidth + 22;
 | 
				
			||||||
                if (col.allcheck && isCheckbox) {
 | 
					                if (col.allcheck && isCheckbox) {
 | 
				
			||||||
                    width += 32;
 | 
					                    width += 32;
 | 
				
			||||||
@@ -587,7 +621,7 @@ class Grid {
 | 
				
			|||||||
                    caption.style.setProperty(css[0], css[1]);
 | 
					                    caption.style.setProperty(css[0], css[1]);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            caption.innerText = col.caption;
 | 
					            caption.innerText = col.caption ?? '';
 | 
				
			||||||
            wrapper.appendChild(caption);
 | 
					            wrapper.appendChild(caption);
 | 
				
			||||||
            // order arrow
 | 
					            // order arrow
 | 
				
			||||||
            if (col.sortable) {
 | 
					            if (col.sortable) {
 | 
				
			||||||
@@ -608,7 +642,7 @@ class Grid {
 | 
				
			|||||||
                th.appendChild(spliter);
 | 
					                th.appendChild(spliter);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            // tooltip
 | 
					            // tooltip
 | 
				
			||||||
            !nullOrEmpty(col.tooltip) && th.setAttribute('title', col.tooltip);
 | 
					            // !nullOrEmpty(col.tooltip) && setTooltip(th, col.tooltip);
 | 
				
			||||||
            header.appendChild(th);
 | 
					            header.appendChild(th);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const placeholder = document.createElement('th');
 | 
					        const placeholder = document.createElement('th');
 | 
				
			||||||
@@ -729,7 +763,7 @@ class Grid {
 | 
				
			|||||||
                                type ??= GridColumn;
 | 
					                                type ??= GridColumn;
 | 
				
			||||||
                                this.#colTypes[col.key] = type;
 | 
					                                this.#colTypes[col.key] = type;
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            cell.appendChild(type.create());
 | 
					                            cell.appendChild(type.create(col));
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@@ -796,10 +830,10 @@ class Grid {
 | 
				
			|||||||
                const isCheckbox = Grid.ColumnTypes.isCheckbox(col.type);
 | 
					                const isCheckbox = Grid.ColumnTypes.isCheckbox(col.type);
 | 
				
			||||||
                const type = isCheckbox ? GridCheckboxColumn : this.#colTypes[col.key] ?? GridColumn;
 | 
					                const type = isCheckbox ? GridCheckboxColumn : this.#colTypes[col.key] ?? GridColumn;
 | 
				
			||||||
                let element;
 | 
					                let element;
 | 
				
			||||||
                if (!isCheckbox && selectChanged) {
 | 
					                if (!isCheckbox && selectChanged && typeof type.createEdit === 'function') {
 | 
				
			||||||
                    element = selected && typeof type.createEdit === 'function' ?
 | 
					                    element = selected ?
 | 
				
			||||||
                        type.createEdit(e => this.#onRowChanged(e, startIndex + i, col, type.getValue(e))) :
 | 
					                        type.createEdit(e => this.#onRowChanged(e, startIndex + i, col, type.getValue(e))) :
 | 
				
			||||||
                        type.create();
 | 
					                        type.create(col);
 | 
				
			||||||
                    cell.replaceChildren(element);
 | 
					                    cell.replaceChildren(element);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    element = cell.children[0];
 | 
					                    element = cell.children[0];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,14 +23,20 @@ function setTooltip(container, content) {
 | 
				
			|||||||
    container.addEventListener('mouseenter', () => {
 | 
					    container.addEventListener('mouseenter', () => {
 | 
				
			||||||
        tid && clearTimeout(tid);
 | 
					        tid && clearTimeout(tid);
 | 
				
			||||||
        tid = setTimeout(() => {
 | 
					        tid = setTimeout(() => {
 | 
				
			||||||
 | 
					            while (container?.offsetWidth == null) {
 | 
				
			||||||
 | 
					                container = container.parentElement;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (container == null) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            let left = container.offsetLeft;
 | 
					            let left = container.offsetLeft;
 | 
				
			||||||
            let top = container.offsetTop;
 | 
					            let top = container.offsetTop;
 | 
				
			||||||
            let parent = container.parentElement;
 | 
					            // let parent = container.parentElement;
 | 
				
			||||||
            while (parent != null) {
 | 
					            // while (parent != null) {
 | 
				
			||||||
                left -= parent.scrollLeft;
 | 
					            //     left -= parent.scrollLeft;
 | 
				
			||||||
                top -= parent.scrollTop;
 | 
					            //     top -= parent.scrollTop;
 | 
				
			||||||
                parent = parent.parentElement;
 | 
					            //     parent = parent.parentElement;
 | 
				
			||||||
            }
 | 
					            // }
 | 
				
			||||||
            left -= wrapper.offsetWidth / 2 - container.offsetWidth / 2;
 | 
					            left -= wrapper.offsetWidth / 2 - container.offsetWidth / 2;
 | 
				
			||||||
            top -= wrapper.offsetHeight + 14;
 | 
					            top -= wrapper.offsetHeight + 14;
 | 
				
			||||||
            wrapper.style.left = `${left}px`;
 | 
					            wrapper.style.left = `${left}px`;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user