fix: 🐛 Dropdown z-index problem
Z-index of dropdown does not work because it's parent has a transform property. To avoid this, we float the dropdown using fixed co-ordinates and then update the x, y positions.
This commit is contained in:
parent
d494590b70
commit
3fc8ac9e72
@ -63,51 +63,72 @@ export default class ColumnManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bindDropdown() {
|
bindDropdown() {
|
||||||
let $activeDropdown;
|
|
||||||
let activeClass = 'dt-dropdown--active';
|
|
||||||
let toggleClass = '.dt-dropdown__toggle';
|
let toggleClass = '.dt-dropdown__toggle';
|
||||||
|
let dropdownClass = '.dt-dropdown__list';
|
||||||
|
|
||||||
$.on(this.header, 'click', toggleClass, (e, $button) => {
|
// attach the dropdown list to container
|
||||||
const $dropdown = $.closest('.dt-dropdown', $button);
|
this.instance.dropdownContainer.innerHTML = this.getDropdownListHTML();
|
||||||
|
this.$dropdownList = this.instance.dropdownContainer.firstElementChild;
|
||||||
|
|
||||||
if (!$dropdown.classList.contains(activeClass)) {
|
$.on(this.header, 'click', toggleClass, e => {
|
||||||
deactivateDropdown();
|
this.openDropdown(e);
|
||||||
$dropdown.classList.add(activeClass);
|
|
||||||
$activeDropdown = $dropdown;
|
|
||||||
} else {
|
|
||||||
deactivateDropdown();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const deactivateDropdownOnBodyClick = (e) => {
|
const deactivateDropdownOnBodyClick = (e) => {
|
||||||
const selector = [toggleClass, toggleClass + ' *'].join(',');
|
const selector = [
|
||||||
|
toggleClass, toggleClass + ' *',
|
||||||
|
dropdownClass, dropdownClass + ' *'
|
||||||
|
].join(',');
|
||||||
if (e.target.matches(selector)) return;
|
if (e.target.matches(selector)) return;
|
||||||
deactivateDropdown();
|
deactivateDropdown();
|
||||||
};
|
};
|
||||||
$.on(document.body, 'click', deactivateDropdownOnBodyClick);
|
$.on(document.body, 'click', deactivateDropdownOnBodyClick);
|
||||||
|
document.addEventListener('scroll', deactivateDropdown, true);
|
||||||
|
|
||||||
this.instance.on('onDestroy', () => {
|
this.instance.on('onDestroy', () => {
|
||||||
$.off(document.body, 'click', deactivateDropdownOnBodyClick);
|
$.off(document.body, 'click', deactivateDropdownOnBodyClick);
|
||||||
|
$.off(document, 'scroll', deactivateDropdown);
|
||||||
});
|
});
|
||||||
|
|
||||||
const dropdownItems = this.options.headerDropdown;
|
$.on(this.$dropdownList, 'click', '.dt-dropdown__list-item', (e, $item) => {
|
||||||
|
if (!this._dropdownActiveColIndex) return;
|
||||||
$.on(this.header, 'click', '.dt-dropdown__list-item', (e, $item) => {
|
const dropdownItems = this.options.headerDropdown;
|
||||||
const $col = $.closest('.dt-cell', $item);
|
const { index } = $.data($item);
|
||||||
const {
|
const colIndex = this._dropdownActiveColIndex;
|
||||||
index
|
|
||||||
} = $.data($item);
|
|
||||||
const {
|
|
||||||
colIndex
|
|
||||||
} = $.data($col);
|
|
||||||
let callback = dropdownItems[index].action;
|
let callback = dropdownItems[index].action;
|
||||||
|
|
||||||
callback && callback.call(this.instance, this.getColumn(colIndex));
|
callback && callback.call(this.instance, this.getColumn(colIndex));
|
||||||
|
this.hideDropdown();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const _this = this;
|
||||||
function deactivateDropdown(e) {
|
function deactivateDropdown(e) {
|
||||||
$activeDropdown && $activeDropdown.classList.remove(activeClass);
|
_this.hideDropdown();
|
||||||
$activeDropdown = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.hideDropdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
openDropdown(e) {
|
||||||
|
if (!this._dropdownWidth) {
|
||||||
|
$.style(this.$dropdownList, { display: '' });
|
||||||
|
this._dropdownWidth = $.style(this.$dropdownList, 'width');
|
||||||
|
}
|
||||||
|
$.style(this.$dropdownList, {
|
||||||
|
display: '',
|
||||||
|
left: (e.clientX - this._dropdownWidth + 4) + 'px',
|
||||||
|
top: (e.clientY + 4) + 'px'
|
||||||
|
});
|
||||||
|
const $cell = $.closest('.dt-cell', e.target);
|
||||||
|
const { colIndex } = $.data($cell);
|
||||||
|
this._dropdownActiveColIndex = colIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
hideDropdown() {
|
||||||
|
$.style(this.$dropdownList, {
|
||||||
|
display: 'none'
|
||||||
|
});
|
||||||
|
this._dropdownActiveColIndex = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bindResizeColumn() {
|
bindResizeColumn() {
|
||||||
@ -370,17 +391,24 @@ export default class ColumnManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getDropdownHTML() {
|
getDropdownHTML() {
|
||||||
const { dropdownButton, headerDropdown: dropdownItems } = this.options;
|
const { dropdownButton } = this.options;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="dt-dropdown">
|
<div class="dt-dropdown">
|
||||||
<div class="dt-dropdown__toggle">${dropdownButton}</div>
|
<div class="dt-dropdown__toggle">${dropdownButton}</div>
|
||||||
<div class="dt-dropdown__list">
|
|
||||||
${dropdownItems.map((d, i) => `
|
|
||||||
<div class="dt-dropdown__list-item" data-index="${i}">${d.label}</div>
|
|
||||||
`).join('')}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDropdownListHTML() {
|
||||||
|
const { headerDropdown: dropdownItems } = this.options;
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class="dt-dropdown__list">
|
||||||
|
${dropdownItems.map((d, i) => `
|
||||||
|
<div class="dt-dropdown__list-item" data-index="${i}">${d.label}</div>
|
||||||
|
`).join('')}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,6 +78,7 @@ class DataTable {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="dt-toast"></div>
|
<div class="dt-toast"></div>
|
||||||
|
<div class="dt-dropdown-container"></div>
|
||||||
<textarea class="dt-paste-target"></textarea>
|
<textarea class="dt-paste-target"></textarea>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@ -89,6 +90,7 @@ class DataTable {
|
|||||||
this.freezeContainer = $('.dt-freeze', this.wrapper);
|
this.freezeContainer = $('.dt-freeze', this.wrapper);
|
||||||
this.toastMessage = $('.dt-toast', this.wrapper);
|
this.toastMessage = $('.dt-toast', this.wrapper);
|
||||||
this.pasteTarget = $('.dt-paste-target', this.wrapper);
|
this.pasteTarget = $('.dt-paste-target', this.wrapper);
|
||||||
|
this.dropdownContainer = $('.dt-dropdown-container', this.wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh(data, columns) {
|
refresh(data, columns) {
|
||||||
|
|||||||
@ -191,13 +191,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__list {
|
&__list {
|
||||||
display: none;
|
position: fixed;
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
min-width: 8rem;
|
min-width: 8rem;
|
||||||
top: 100%;
|
|
||||||
right: 0;
|
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
cursor: pointer;
|
||||||
background-color: var(--dt-cell-bg);
|
background-color: var(--dt-cell-bg);
|
||||||
border-radius: var(--dt-border-radius);
|
border-radius: var(--dt-border-radius);
|
||||||
padding: var(--dt-spacer-2) 0;
|
padding: var(--dt-spacer-2) 0;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user