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:
Faris Ansari 2018-12-28 19:16:26 +05:30
parent d494590b70
commit 3fc8ac9e72
3 changed files with 62 additions and 35 deletions

View File

@ -63,51 +63,72 @@ export default class ColumnManager {
}
bindDropdown() {
let $activeDropdown;
let activeClass = 'dt-dropdown--active';
let toggleClass = '.dt-dropdown__toggle';
let dropdownClass = '.dt-dropdown__list';
$.on(this.header, 'click', toggleClass, (e, $button) => {
const $dropdown = $.closest('.dt-dropdown', $button);
// attach the dropdown list to container
this.instance.dropdownContainer.innerHTML = this.getDropdownListHTML();
this.$dropdownList = this.instance.dropdownContainer.firstElementChild;
if (!$dropdown.classList.contains(activeClass)) {
deactivateDropdown();
$dropdown.classList.add(activeClass);
$activeDropdown = $dropdown;
} else {
deactivateDropdown();
}
$.on(this.header, 'click', toggleClass, e => {
this.openDropdown(e);
});
const deactivateDropdownOnBodyClick = (e) => {
const selector = [toggleClass, toggleClass + ' *'].join(',');
const selector = [
toggleClass, toggleClass + ' *',
dropdownClass, dropdownClass + ' *'
].join(',');
if (e.target.matches(selector)) return;
deactivateDropdown();
};
$.on(document.body, 'click', deactivateDropdownOnBodyClick);
document.addEventListener('scroll', deactivateDropdown, true);
this.instance.on('onDestroy', () => {
$.off(document.body, 'click', deactivateDropdownOnBodyClick);
$.off(document, 'scroll', deactivateDropdown);
});
const dropdownItems = this.options.headerDropdown;
$.on(this.header, 'click', '.dt-dropdown__list-item', (e, $item) => {
const $col = $.closest('.dt-cell', $item);
const {
index
} = $.data($item);
const {
colIndex
} = $.data($col);
$.on(this.$dropdownList, 'click', '.dt-dropdown__list-item', (e, $item) => {
if (!this._dropdownActiveColIndex) return;
const dropdownItems = this.options.headerDropdown;
const { index } = $.data($item);
const colIndex = this._dropdownActiveColIndex;
let callback = dropdownItems[index].action;
callback && callback.call(this.instance, this.getColumn(colIndex));
this.hideDropdown();
});
const _this = this;
function deactivateDropdown(e) {
$activeDropdown && $activeDropdown.classList.remove(activeClass);
$activeDropdown = null;
_this.hideDropdown();
}
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() {
@ -370,17 +391,24 @@ export default class ColumnManager {
}
getDropdownHTML() {
const { dropdownButton, headerDropdown: dropdownItems } = this.options;
const { dropdownButton } = this.options;
return `
<div class="dt-dropdown">
<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>
`;
}
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>
`;
}
}

View File

@ -78,6 +78,7 @@ class DataTable {
</span>
</div>
<div class="dt-toast"></div>
<div class="dt-dropdown-container"></div>
<textarea class="dt-paste-target"></textarea>
</div>
`;
@ -89,6 +90,7 @@ class DataTable {
this.freezeContainer = $('.dt-freeze', this.wrapper);
this.toastMessage = $('.dt-toast', this.wrapper);
this.pasteTarget = $('.dt-paste-target', this.wrapper);
this.dropdownContainer = $('.dt-dropdown-container', this.wrapper);
}
refresh(data, columns) {

View File

@ -191,13 +191,10 @@
}
&__list {
display: none;
position: absolute;
position: fixed;
min-width: 8rem;
top: 100%;
right: 0;
z-index: 1;
cursor: pointer;
background-color: var(--dt-cell-bg);
border-radius: var(--dt-border-radius);
padding: var(--dt-spacer-2) 0;