This commit is contained in:
Sebastian Zoglowek 2026-03-10 14:27:38 +01:00 committed by GitHub
commit a537cb6390
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 963 additions and 159 deletions

View file

@ -204,6 +204,8 @@ import "choices.js/public/assets/styles/choices.css";
listItems: ['choices__list--multiple'],
listSingle: ['choices__list--single'],
listDropdown: ['choices__list--dropdown'],
dropdownMultiple: ['choices__dropdown--multiple'],
dropdownSingle: ['choices__dropdown--single'],
item: ['choices__item'],
itemSelectable: ['choices__item--selectable'],
itemDisabled: ['choices__item--disabled'],
@ -536,6 +538,14 @@ var choices = new Choices(el, {
});
```
### dropdownParent
**Type:** `string | null` **Default:** null
**Input types affected:** `select-one`, `select-multiple`
**Usage:** CSS selector for the element to append the dropdown to. Similar to select2's appendTo option
### position
**Type:** `String` **Default:** `auto`

View file

@ -409,25 +409,32 @@
Container.prototype.removeActiveDescendant = function () {
this.element.removeAttribute('aria-activedescendant');
};
Container.prototype.open = function (dropdownPos, dropdownHeight) {
Container.prototype.open = function (dropdownPos, dropdownHeight, dropdown) {
if (dropdown === void 0) { dropdown = null; }
addClassesToElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'true');
this.isOpen = true;
if (this.shouldFlip(dropdownPos, dropdownHeight)) {
addClassesToElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
addClassesToElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = true;
}
return this.isFlipped;
};
Container.prototype.close = function () {
Container.prototype.close = function (dropdown) {
if (dropdown === void 0) { dropdown = null; }
removeClassesFromElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'false');
this.removeActiveDescendant();
this.isOpen = false;
// A dropdown flips if it does not have space within the page
if (this.isFlipped) {
removeClassesFromElement(this.element, this.classNames.flippedState);
this.isFlipped = false;
removeClassesFromElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
removeClassesFromElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = false;
};
Container.prototype.addFocusState = function () {
addClassesToElement(this.element, this.classNames.focusState);
@ -937,6 +944,8 @@
listItems: ['choices__list--multiple'],
listSingle: ['choices__list--single'],
listDropdown: ['choices__list--dropdown'],
dropdownMultiple: ['choices__dropdown--multiple'],
dropdownSingle: ['choices__dropdown--single'],
item: ['choices__item'],
itemSelectable: ['choices__item--selectable'],
itemDisabled: ['choices__item--disabled'],
@ -1020,6 +1029,7 @@
callbackOnCreateTemplates: null,
classNames: DEFAULT_CLASSNAMES,
appendGroupInSearch: false,
dropdownParent: null,
};
var removeItem = function (item) {
@ -3285,11 +3295,12 @@
}
return inp;
},
dropdown: function (_a) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown;
dropdown: function (_a, isSelectOneElement) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown, dropdownSingle = _b.dropdownSingle, dropdownMultiple = _b.dropdownMultiple;
var div = document.createElement('div');
addClassesToElement(div, list);
addClassesToElement(div, listDropdown);
addClassesToElement(div, isSelectOneElement ? dropdownSingle : dropdownMultiple);
div.setAttribute('aria-expanded', 'false');
return div;
},
@ -3475,6 +3486,8 @@
this._onDeleteKey = this._onDeleteKey.bind(this);
this._onChange = this._onChange.bind(this);
this._onInvalid = this._onInvalid.bind(this);
this._onWindowResize = this._onWindowResize.bind(this);
this._onScroll = this._onScroll.bind(this);
// If element has already been initialised with Choices, fail silently
if (this.passedElement.isActive) {
if (!config.silent) {
@ -3484,6 +3497,15 @@
this.initialisedOK = false;
return;
}
// Dropdown is detached from the original wrapper
this._dropdownDetached = false;
if (config.dropdownParent) {
var parent_1 = this._docRoot.querySelector(config.dropdownParent);
if (parent_1) {
this._dropdownDetached = true;
this._dropdownParent = parent_1;
}
}
// Let's go
this.init();
// preserve the selected item list after setup for form reset
@ -3666,9 +3688,15 @@
preventInputFocus = !this._canSearch;
}
requestAnimationFrame(function () {
if (_this._dropdownDetached) {
_this.setHorizontalDropdownPosition();
}
_this.dropdown.show();
var rect = _this.dropdown.element.getBoundingClientRect();
_this.containerOuter.open(rect.bottom, rect.height);
var dropdownAbove = _this.containerOuter.open(rect.bottom, rect.height, _this.dropdown.element);
if (_this._dropdownDetached) {
_this.setVerticalDropdownPosition(dropdownAbove);
}
if (!preventInputFocus) {
_this.input.focus();
}
@ -3689,7 +3717,7 @@
this._removeHighlightedChoices();
requestAnimationFrame(function () {
_this.dropdown.hide();
_this.containerOuter.close();
_this.containerOuter.close(_this.dropdown.element);
if (!preventInputBlur && _this._canSearch) {
_this.input.removeActiveDescendant();
_this.input.blur();
@ -3698,6 +3726,22 @@
});
return this;
};
Choices.prototype.setHorizontalDropdownPosition = function () {
var containerRect = this.containerOuter.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(window.scrollY + containerRect.bottom, "px");
this.dropdown.element.style.left = "".concat(containerRect.left, "px");
this.dropdown.element.style.width = "".concat(containerRect.width, "px");
return this;
};
Choices.prototype.setVerticalDropdownPosition = function (above) {
if (above === void 0) { above = false; }
if (!above || !(this._dropdownParent instanceof HTMLElement)) {
return this;
}
var dropdownRect = this.dropdown.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(this.containerOuter.element.offsetTop + 1 - dropdownRect.height, "px");
return this;
};
Choices.prototype.getValue = function (valueOnly) {
var values = this._store.items.map(function (item) {
return (valueOnly ? item.value : getChoiceForOutput(item));
@ -4518,6 +4562,7 @@
Choices.prototype._addEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
// capture events - can cancel event processing or propagation
@ -4529,7 +4574,7 @@
documentElement.addEventListener('touchmove', this._onTouchMove, {
passive: true,
});
this.dropdown.element.addEventListener('mouseover', this._onMouseOver, {
dropdownElement.addEventListener('mouseover', this._onMouseOver, {
passive: true,
});
if (this._isSelectOneElement) {
@ -4565,11 +4610,20 @@
passive: true,
});
}
if (this._dropdownDetached) {
dropdownElement.addEventListener('keydown', this._onKeyDown, true);
dropdownElement.addEventListener('mousedown', this._onMouseDown, true);
window.addEventListener('resize', this._onWindowResize);
window.addEventListener('scroll', this._onScroll, {
passive: true,
});
}
this.input.addEventListeners();
};
Choices.prototype._removeEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
documentElement.removeEventListener('touchend', this._onTouchEnd, true);
@ -4577,7 +4631,7 @@
outerElement.removeEventListener('mousedown', this._onMouseDown, true);
documentElement.removeEventListener('click', this._onClick);
documentElement.removeEventListener('touchmove', this._onTouchMove);
this.dropdown.element.removeEventListener('mouseover', this._onMouseOver);
dropdownElement.removeEventListener('mouseover', this._onMouseOver);
if (this._isSelectOneElement) {
outerElement.removeEventListener('focus', this._onFocus);
outerElement.removeEventListener('blur', this._onBlur);
@ -4593,6 +4647,12 @@
passedElement.removeEventListener('change', this._onChange);
passedElement.removeEventListener('invalid', this._onInvalid);
}
if (this._dropdownDetached) {
dropdownElement.removeEventListener('keydown', this._onKeyDown);
dropdownElement.removeEventListener('mousedown', this._onMouseDown);
window.removeEventListener('resize', this._onWindowResize);
window.removeEventListener('scroll', this._onScroll);
}
this.input.removeEventListeners();
};
Choices.prototype._onKeyDown = function (event) {
@ -4984,6 +5044,21 @@
Choices.prototype._onInvalid = function () {
this.containerOuter.addInvalidState();
};
Choices.prototype._onWindowResize = function () {
this._moveDropdown();
};
Choices.prototype._onScroll = function () {
this._moveDropdown();
};
Choices.prototype._moveDropdown = function () {
if (!this.dropdown.isActive) {
return;
}
this.setHorizontalDropdownPosition();
var rect = this.dropdown.element.getBoundingClientRect();
var dropdownAbove = this.containerOuter.shouldFlip(rect.bottom, rect.height);
this.setVerticalDropdownPosition(dropdownAbove);
};
/**
* Removes any highlighted choice options
*/
@ -5162,7 +5237,7 @@
element: templating.itemList(config, isSelectOneElement),
});
this.dropdown = new Dropdown({
element: templating.dropdown(config),
element: templating.dropdown(config, isSelectOneElement),
classNames: classNames,
type: elementType,
});
@ -5170,14 +5245,18 @@
Choices.prototype._createStructure = function () {
var _a = this, containerInner = _a.containerInner, containerOuter = _a.containerOuter, passedElement = _a.passedElement;
var dropdownElement = this.dropdown.element;
var dropdownParent = containerOuter.element;
// Hide original element
passedElement.conceal();
// Wrap input in container preserving DOM ordering
containerInner.wrap(passedElement.element);
// Wrapper inner container with outer container
containerOuter.wrap(containerInner.element);
if (this._dropdownDetached && this._dropdownParent instanceof HTMLElement) {
dropdownParent = this._dropdownParent;
}
containerOuter.element.appendChild(containerInner.element);
containerOuter.element.appendChild(dropdownElement);
dropdownParent.appendChild(dropdownElement);
containerInner.element.appendChild(this.itemList.element);
dropdownElement.appendChild(this.choiceList.element);
if (this._isSelectOneElement) {

File diff suppressed because one or more lines are too long

View file

@ -403,25 +403,32 @@ var Container = /** @class */ (function () {
Container.prototype.removeActiveDescendant = function () {
this.element.removeAttribute('aria-activedescendant');
};
Container.prototype.open = function (dropdownPos, dropdownHeight) {
Container.prototype.open = function (dropdownPos, dropdownHeight, dropdown) {
if (dropdown === void 0) { dropdown = null; }
addClassesToElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'true');
this.isOpen = true;
if (this.shouldFlip(dropdownPos, dropdownHeight)) {
addClassesToElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
addClassesToElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = true;
}
return this.isFlipped;
};
Container.prototype.close = function () {
Container.prototype.close = function (dropdown) {
if (dropdown === void 0) { dropdown = null; }
removeClassesFromElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'false');
this.removeActiveDescendant();
this.isOpen = false;
// A dropdown flips if it does not have space within the page
if (this.isFlipped) {
removeClassesFromElement(this.element, this.classNames.flippedState);
this.isFlipped = false;
removeClassesFromElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
removeClassesFromElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = false;
};
Container.prototype.addFocusState = function () {
addClassesToElement(this.element, this.classNames.focusState);
@ -931,6 +938,8 @@ var DEFAULT_CLASSNAMES = {
listItems: ['choices__list--multiple'],
listSingle: ['choices__list--single'],
listDropdown: ['choices__list--dropdown'],
dropdownMultiple: ['choices__dropdown--multiple'],
dropdownSingle: ['choices__dropdown--single'],
item: ['choices__item'],
itemSelectable: ['choices__item--selectable'],
itemDisabled: ['choices__item--disabled'],
@ -1014,6 +1023,7 @@ var DEFAULT_CONFIG = {
callbackOnCreateTemplates: null,
classNames: DEFAULT_CLASSNAMES,
appendGroupInSearch: false,
dropdownParent: null,
};
var removeItem = function (item) {
@ -3279,11 +3289,12 @@ var templates = {
}
return inp;
},
dropdown: function (_a) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown;
dropdown: function (_a, isSelectOneElement) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown, dropdownSingle = _b.dropdownSingle, dropdownMultiple = _b.dropdownMultiple;
var div = document.createElement('div');
addClassesToElement(div, list);
addClassesToElement(div, listDropdown);
addClassesToElement(div, isSelectOneElement ? dropdownSingle : dropdownMultiple);
div.setAttribute('aria-expanded', 'false');
return div;
},
@ -3469,6 +3480,8 @@ var Choices = /** @class */ (function () {
this._onDeleteKey = this._onDeleteKey.bind(this);
this._onChange = this._onChange.bind(this);
this._onInvalid = this._onInvalid.bind(this);
this._onWindowResize = this._onWindowResize.bind(this);
this._onScroll = this._onScroll.bind(this);
// If element has already been initialised with Choices, fail silently
if (this.passedElement.isActive) {
if (!config.silent) {
@ -3478,6 +3491,15 @@ var Choices = /** @class */ (function () {
this.initialisedOK = false;
return;
}
// Dropdown is detached from the original wrapper
this._dropdownDetached = false;
if (config.dropdownParent) {
var parent_1 = this._docRoot.querySelector(config.dropdownParent);
if (parent_1) {
this._dropdownDetached = true;
this._dropdownParent = parent_1;
}
}
// Let's go
this.init();
// preserve the selected item list after setup for form reset
@ -3660,9 +3682,15 @@ var Choices = /** @class */ (function () {
preventInputFocus = !this._canSearch;
}
requestAnimationFrame(function () {
if (_this._dropdownDetached) {
_this.setHorizontalDropdownPosition();
}
_this.dropdown.show();
var rect = _this.dropdown.element.getBoundingClientRect();
_this.containerOuter.open(rect.bottom, rect.height);
var dropdownAbove = _this.containerOuter.open(rect.bottom, rect.height, _this.dropdown.element);
if (_this._dropdownDetached) {
_this.setVerticalDropdownPosition(dropdownAbove);
}
if (!preventInputFocus) {
_this.input.focus();
}
@ -3683,7 +3711,7 @@ var Choices = /** @class */ (function () {
this._removeHighlightedChoices();
requestAnimationFrame(function () {
_this.dropdown.hide();
_this.containerOuter.close();
_this.containerOuter.close(_this.dropdown.element);
if (!preventInputBlur && _this._canSearch) {
_this.input.removeActiveDescendant();
_this.input.blur();
@ -3692,6 +3720,22 @@ var Choices = /** @class */ (function () {
});
return this;
};
Choices.prototype.setHorizontalDropdownPosition = function () {
var containerRect = this.containerOuter.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(window.scrollY + containerRect.bottom, "px");
this.dropdown.element.style.left = "".concat(containerRect.left, "px");
this.dropdown.element.style.width = "".concat(containerRect.width, "px");
return this;
};
Choices.prototype.setVerticalDropdownPosition = function (above) {
if (above === void 0) { above = false; }
if (!above || !(this._dropdownParent instanceof HTMLElement)) {
return this;
}
var dropdownRect = this.dropdown.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(this.containerOuter.element.offsetTop + 1 - dropdownRect.height, "px");
return this;
};
Choices.prototype.getValue = function (valueOnly) {
var values = this._store.items.map(function (item) {
return (valueOnly ? item.value : getChoiceForOutput(item));
@ -4512,6 +4556,7 @@ var Choices = /** @class */ (function () {
Choices.prototype._addEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
// capture events - can cancel event processing or propagation
@ -4523,7 +4568,7 @@ var Choices = /** @class */ (function () {
documentElement.addEventListener('touchmove', this._onTouchMove, {
passive: true,
});
this.dropdown.element.addEventListener('mouseover', this._onMouseOver, {
dropdownElement.addEventListener('mouseover', this._onMouseOver, {
passive: true,
});
if (this._isSelectOneElement) {
@ -4559,11 +4604,20 @@ var Choices = /** @class */ (function () {
passive: true,
});
}
if (this._dropdownDetached) {
dropdownElement.addEventListener('keydown', this._onKeyDown, true);
dropdownElement.addEventListener('mousedown', this._onMouseDown, true);
window.addEventListener('resize', this._onWindowResize);
window.addEventListener('scroll', this._onScroll, {
passive: true,
});
}
this.input.addEventListeners();
};
Choices.prototype._removeEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
documentElement.removeEventListener('touchend', this._onTouchEnd, true);
@ -4571,7 +4625,7 @@ var Choices = /** @class */ (function () {
outerElement.removeEventListener('mousedown', this._onMouseDown, true);
documentElement.removeEventListener('click', this._onClick);
documentElement.removeEventListener('touchmove', this._onTouchMove);
this.dropdown.element.removeEventListener('mouseover', this._onMouseOver);
dropdownElement.removeEventListener('mouseover', this._onMouseOver);
if (this._isSelectOneElement) {
outerElement.removeEventListener('focus', this._onFocus);
outerElement.removeEventListener('blur', this._onBlur);
@ -4587,6 +4641,12 @@ var Choices = /** @class */ (function () {
passedElement.removeEventListener('change', this._onChange);
passedElement.removeEventListener('invalid', this._onInvalid);
}
if (this._dropdownDetached) {
dropdownElement.removeEventListener('keydown', this._onKeyDown);
dropdownElement.removeEventListener('mousedown', this._onMouseDown);
window.removeEventListener('resize', this._onWindowResize);
window.removeEventListener('scroll', this._onScroll);
}
this.input.removeEventListeners();
};
Choices.prototype._onKeyDown = function (event) {
@ -4978,6 +5038,21 @@ var Choices = /** @class */ (function () {
Choices.prototype._onInvalid = function () {
this.containerOuter.addInvalidState();
};
Choices.prototype._onWindowResize = function () {
this._moveDropdown();
};
Choices.prototype._onScroll = function () {
this._moveDropdown();
};
Choices.prototype._moveDropdown = function () {
if (!this.dropdown.isActive) {
return;
}
this.setHorizontalDropdownPosition();
var rect = this.dropdown.element.getBoundingClientRect();
var dropdownAbove = this.containerOuter.shouldFlip(rect.bottom, rect.height);
this.setVerticalDropdownPosition(dropdownAbove);
};
/**
* Removes any highlighted choice options
*/
@ -5156,7 +5231,7 @@ var Choices = /** @class */ (function () {
element: templating.itemList(config, isSelectOneElement),
});
this.dropdown = new Dropdown({
element: templating.dropdown(config),
element: templating.dropdown(config, isSelectOneElement),
classNames: classNames,
type: elementType,
});
@ -5164,14 +5239,18 @@ var Choices = /** @class */ (function () {
Choices.prototype._createStructure = function () {
var _a = this, containerInner = _a.containerInner, containerOuter = _a.containerOuter, passedElement = _a.passedElement;
var dropdownElement = this.dropdown.element;
var dropdownParent = containerOuter.element;
// Hide original element
passedElement.conceal();
// Wrap input in container preserving DOM ordering
containerInner.wrap(passedElement.element);
// Wrapper inner container with outer container
containerOuter.wrap(containerInner.element);
if (this._dropdownDetached && this._dropdownParent instanceof HTMLElement) {
dropdownParent = this._dropdownParent;
}
containerOuter.element.appendChild(containerInner.element);
containerOuter.element.appendChild(dropdownElement);
dropdownParent.appendChild(dropdownElement);
containerInner.element.appendChild(this.itemList.element);
dropdownElement.appendChild(this.choiceList.element);
if (this._isSelectOneElement) {

View file

@ -409,25 +409,32 @@
Container.prototype.removeActiveDescendant = function () {
this.element.removeAttribute('aria-activedescendant');
};
Container.prototype.open = function (dropdownPos, dropdownHeight) {
Container.prototype.open = function (dropdownPos, dropdownHeight, dropdown) {
if (dropdown === void 0) { dropdown = null; }
addClassesToElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'true');
this.isOpen = true;
if (this.shouldFlip(dropdownPos, dropdownHeight)) {
addClassesToElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
addClassesToElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = true;
}
return this.isFlipped;
};
Container.prototype.close = function () {
Container.prototype.close = function (dropdown) {
if (dropdown === void 0) { dropdown = null; }
removeClassesFromElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'false');
this.removeActiveDescendant();
this.isOpen = false;
// A dropdown flips if it does not have space within the page
if (this.isFlipped) {
removeClassesFromElement(this.element, this.classNames.flippedState);
this.isFlipped = false;
removeClassesFromElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
removeClassesFromElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = false;
};
Container.prototype.addFocusState = function () {
addClassesToElement(this.element, this.classNames.focusState);
@ -937,6 +944,8 @@
listItems: ['choices__list--multiple'],
listSingle: ['choices__list--single'],
listDropdown: ['choices__list--dropdown'],
dropdownMultiple: ['choices__dropdown--multiple'],
dropdownSingle: ['choices__dropdown--single'],
item: ['choices__item'],
itemSelectable: ['choices__item--selectable'],
itemDisabled: ['choices__item--disabled'],
@ -1020,6 +1029,7 @@
callbackOnCreateTemplates: null,
classNames: DEFAULT_CLASSNAMES,
appendGroupInSearch: false,
dropdownParent: null,
};
var removeItem = function (item) {
@ -2806,11 +2816,12 @@
}
return inp;
},
dropdown: function (_a) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown;
dropdown: function (_a, isSelectOneElement) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown, dropdownSingle = _b.dropdownSingle, dropdownMultiple = _b.dropdownMultiple;
var div = document.createElement('div');
addClassesToElement(div, list);
addClassesToElement(div, listDropdown);
addClassesToElement(div, isSelectOneElement ? dropdownSingle : dropdownMultiple);
div.setAttribute('aria-expanded', 'false');
return div;
},
@ -2996,6 +3007,8 @@
this._onDeleteKey = this._onDeleteKey.bind(this);
this._onChange = this._onChange.bind(this);
this._onInvalid = this._onInvalid.bind(this);
this._onWindowResize = this._onWindowResize.bind(this);
this._onScroll = this._onScroll.bind(this);
// If element has already been initialised with Choices, fail silently
if (this.passedElement.isActive) {
if (!config.silent) {
@ -3005,6 +3018,15 @@
this.initialisedOK = false;
return;
}
// Dropdown is detached from the original wrapper
this._dropdownDetached = false;
if (config.dropdownParent) {
var parent_1 = this._docRoot.querySelector(config.dropdownParent);
if (parent_1) {
this._dropdownDetached = true;
this._dropdownParent = parent_1;
}
}
// Let's go
this.init();
// preserve the selected item list after setup for form reset
@ -3187,9 +3209,15 @@
preventInputFocus = !this._canSearch;
}
requestAnimationFrame(function () {
if (_this._dropdownDetached) {
_this.setHorizontalDropdownPosition();
}
_this.dropdown.show();
var rect = _this.dropdown.element.getBoundingClientRect();
_this.containerOuter.open(rect.bottom, rect.height);
var dropdownAbove = _this.containerOuter.open(rect.bottom, rect.height, _this.dropdown.element);
if (_this._dropdownDetached) {
_this.setVerticalDropdownPosition(dropdownAbove);
}
if (!preventInputFocus) {
_this.input.focus();
}
@ -3210,7 +3238,7 @@
this._removeHighlightedChoices();
requestAnimationFrame(function () {
_this.dropdown.hide();
_this.containerOuter.close();
_this.containerOuter.close(_this.dropdown.element);
if (!preventInputBlur && _this._canSearch) {
_this.input.removeActiveDescendant();
_this.input.blur();
@ -3219,6 +3247,22 @@
});
return this;
};
Choices.prototype.setHorizontalDropdownPosition = function () {
var containerRect = this.containerOuter.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(window.scrollY + containerRect.bottom, "px");
this.dropdown.element.style.left = "".concat(containerRect.left, "px");
this.dropdown.element.style.width = "".concat(containerRect.width, "px");
return this;
};
Choices.prototype.setVerticalDropdownPosition = function (above) {
if (above === void 0) { above = false; }
if (!above || !(this._dropdownParent instanceof HTMLElement)) {
return this;
}
var dropdownRect = this.dropdown.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(this.containerOuter.element.offsetTop + 1 - dropdownRect.height, "px");
return this;
};
Choices.prototype.getValue = function (valueOnly) {
var values = this._store.items.map(function (item) {
return (valueOnly ? item.value : getChoiceForOutput(item));
@ -4039,6 +4083,7 @@
Choices.prototype._addEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
// capture events - can cancel event processing or propagation
@ -4050,7 +4095,7 @@
documentElement.addEventListener('touchmove', this._onTouchMove, {
passive: true,
});
this.dropdown.element.addEventListener('mouseover', this._onMouseOver, {
dropdownElement.addEventListener('mouseover', this._onMouseOver, {
passive: true,
});
if (this._isSelectOneElement) {
@ -4086,11 +4131,20 @@
passive: true,
});
}
if (this._dropdownDetached) {
dropdownElement.addEventListener('keydown', this._onKeyDown, true);
dropdownElement.addEventListener('mousedown', this._onMouseDown, true);
window.addEventListener('resize', this._onWindowResize);
window.addEventListener('scroll', this._onScroll, {
passive: true,
});
}
this.input.addEventListeners();
};
Choices.prototype._removeEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
documentElement.removeEventListener('touchend', this._onTouchEnd, true);
@ -4098,7 +4152,7 @@
outerElement.removeEventListener('mousedown', this._onMouseDown, true);
documentElement.removeEventListener('click', this._onClick);
documentElement.removeEventListener('touchmove', this._onTouchMove);
this.dropdown.element.removeEventListener('mouseover', this._onMouseOver);
dropdownElement.removeEventListener('mouseover', this._onMouseOver);
if (this._isSelectOneElement) {
outerElement.removeEventListener('focus', this._onFocus);
outerElement.removeEventListener('blur', this._onBlur);
@ -4114,6 +4168,12 @@
passedElement.removeEventListener('change', this._onChange);
passedElement.removeEventListener('invalid', this._onInvalid);
}
if (this._dropdownDetached) {
dropdownElement.removeEventListener('keydown', this._onKeyDown);
dropdownElement.removeEventListener('mousedown', this._onMouseDown);
window.removeEventListener('resize', this._onWindowResize);
window.removeEventListener('scroll', this._onScroll);
}
this.input.removeEventListeners();
};
Choices.prototype._onKeyDown = function (event) {
@ -4505,6 +4565,21 @@
Choices.prototype._onInvalid = function () {
this.containerOuter.addInvalidState();
};
Choices.prototype._onWindowResize = function () {
this._moveDropdown();
};
Choices.prototype._onScroll = function () {
this._moveDropdown();
};
Choices.prototype._moveDropdown = function () {
if (!this.dropdown.isActive) {
return;
}
this.setHorizontalDropdownPosition();
var rect = this.dropdown.element.getBoundingClientRect();
var dropdownAbove = this.containerOuter.shouldFlip(rect.bottom, rect.height);
this.setVerticalDropdownPosition(dropdownAbove);
};
/**
* Removes any highlighted choice options
*/
@ -4683,7 +4758,7 @@
element: templating.itemList(config, isSelectOneElement),
});
this.dropdown = new Dropdown({
element: templating.dropdown(config),
element: templating.dropdown(config, isSelectOneElement),
classNames: classNames,
type: elementType,
});
@ -4691,14 +4766,18 @@
Choices.prototype._createStructure = function () {
var _a = this, containerInner = _a.containerInner, containerOuter = _a.containerOuter, passedElement = _a.passedElement;
var dropdownElement = this.dropdown.element;
var dropdownParent = containerOuter.element;
// Hide original element
passedElement.conceal();
// Wrap input in container preserving DOM ordering
containerInner.wrap(passedElement.element);
// Wrapper inner container with outer container
containerOuter.wrap(containerInner.element);
if (this._dropdownDetached && this._dropdownParent instanceof HTMLElement) {
dropdownParent = this._dropdownParent;
}
containerOuter.element.appendChild(containerInner.element);
containerOuter.element.appendChild(dropdownElement);
dropdownParent.appendChild(dropdownElement);
containerInner.element.appendChild(this.itemList.element);
dropdownElement.appendChild(this.choiceList.element);
if (this._isSelectOneElement) {

File diff suppressed because one or more lines are too long

View file

@ -403,25 +403,32 @@ var Container = /** @class */ (function () {
Container.prototype.removeActiveDescendant = function () {
this.element.removeAttribute('aria-activedescendant');
};
Container.prototype.open = function (dropdownPos, dropdownHeight) {
Container.prototype.open = function (dropdownPos, dropdownHeight, dropdown) {
if (dropdown === void 0) { dropdown = null; }
addClassesToElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'true');
this.isOpen = true;
if (this.shouldFlip(dropdownPos, dropdownHeight)) {
addClassesToElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
addClassesToElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = true;
}
return this.isFlipped;
};
Container.prototype.close = function () {
Container.prototype.close = function (dropdown) {
if (dropdown === void 0) { dropdown = null; }
removeClassesFromElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'false');
this.removeActiveDescendant();
this.isOpen = false;
// A dropdown flips if it does not have space within the page
if (this.isFlipped) {
removeClassesFromElement(this.element, this.classNames.flippedState);
this.isFlipped = false;
removeClassesFromElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
removeClassesFromElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = false;
};
Container.prototype.addFocusState = function () {
addClassesToElement(this.element, this.classNames.focusState);
@ -931,6 +938,8 @@ var DEFAULT_CLASSNAMES = {
listItems: ['choices__list--multiple'],
listSingle: ['choices__list--single'],
listDropdown: ['choices__list--dropdown'],
dropdownMultiple: ['choices__dropdown--multiple'],
dropdownSingle: ['choices__dropdown--single'],
item: ['choices__item'],
itemSelectable: ['choices__item--selectable'],
itemDisabled: ['choices__item--disabled'],
@ -1014,6 +1023,7 @@ var DEFAULT_CONFIG = {
callbackOnCreateTemplates: null,
classNames: DEFAULT_CLASSNAMES,
appendGroupInSearch: false,
dropdownParent: null,
};
var removeItem = function (item) {
@ -2800,11 +2810,12 @@ var templates = {
}
return inp;
},
dropdown: function (_a) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown;
dropdown: function (_a, isSelectOneElement) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown, dropdownSingle = _b.dropdownSingle, dropdownMultiple = _b.dropdownMultiple;
var div = document.createElement('div');
addClassesToElement(div, list);
addClassesToElement(div, listDropdown);
addClassesToElement(div, isSelectOneElement ? dropdownSingle : dropdownMultiple);
div.setAttribute('aria-expanded', 'false');
return div;
},
@ -2990,6 +3001,8 @@ var Choices = /** @class */ (function () {
this._onDeleteKey = this._onDeleteKey.bind(this);
this._onChange = this._onChange.bind(this);
this._onInvalid = this._onInvalid.bind(this);
this._onWindowResize = this._onWindowResize.bind(this);
this._onScroll = this._onScroll.bind(this);
// If element has already been initialised with Choices, fail silently
if (this.passedElement.isActive) {
if (!config.silent) {
@ -2999,6 +3012,15 @@ var Choices = /** @class */ (function () {
this.initialisedOK = false;
return;
}
// Dropdown is detached from the original wrapper
this._dropdownDetached = false;
if (config.dropdownParent) {
var parent_1 = this._docRoot.querySelector(config.dropdownParent);
if (parent_1) {
this._dropdownDetached = true;
this._dropdownParent = parent_1;
}
}
// Let's go
this.init();
// preserve the selected item list after setup for form reset
@ -3181,9 +3203,15 @@ var Choices = /** @class */ (function () {
preventInputFocus = !this._canSearch;
}
requestAnimationFrame(function () {
if (_this._dropdownDetached) {
_this.setHorizontalDropdownPosition();
}
_this.dropdown.show();
var rect = _this.dropdown.element.getBoundingClientRect();
_this.containerOuter.open(rect.bottom, rect.height);
var dropdownAbove = _this.containerOuter.open(rect.bottom, rect.height, _this.dropdown.element);
if (_this._dropdownDetached) {
_this.setVerticalDropdownPosition(dropdownAbove);
}
if (!preventInputFocus) {
_this.input.focus();
}
@ -3204,7 +3232,7 @@ var Choices = /** @class */ (function () {
this._removeHighlightedChoices();
requestAnimationFrame(function () {
_this.dropdown.hide();
_this.containerOuter.close();
_this.containerOuter.close(_this.dropdown.element);
if (!preventInputBlur && _this._canSearch) {
_this.input.removeActiveDescendant();
_this.input.blur();
@ -3213,6 +3241,22 @@ var Choices = /** @class */ (function () {
});
return this;
};
Choices.prototype.setHorizontalDropdownPosition = function () {
var containerRect = this.containerOuter.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(window.scrollY + containerRect.bottom, "px");
this.dropdown.element.style.left = "".concat(containerRect.left, "px");
this.dropdown.element.style.width = "".concat(containerRect.width, "px");
return this;
};
Choices.prototype.setVerticalDropdownPosition = function (above) {
if (above === void 0) { above = false; }
if (!above || !(this._dropdownParent instanceof HTMLElement)) {
return this;
}
var dropdownRect = this.dropdown.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(this.containerOuter.element.offsetTop + 1 - dropdownRect.height, "px");
return this;
};
Choices.prototype.getValue = function (valueOnly) {
var values = this._store.items.map(function (item) {
return (valueOnly ? item.value : getChoiceForOutput(item));
@ -4033,6 +4077,7 @@ var Choices = /** @class */ (function () {
Choices.prototype._addEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
// capture events - can cancel event processing or propagation
@ -4044,7 +4089,7 @@ var Choices = /** @class */ (function () {
documentElement.addEventListener('touchmove', this._onTouchMove, {
passive: true,
});
this.dropdown.element.addEventListener('mouseover', this._onMouseOver, {
dropdownElement.addEventListener('mouseover', this._onMouseOver, {
passive: true,
});
if (this._isSelectOneElement) {
@ -4080,11 +4125,20 @@ var Choices = /** @class */ (function () {
passive: true,
});
}
if (this._dropdownDetached) {
dropdownElement.addEventListener('keydown', this._onKeyDown, true);
dropdownElement.addEventListener('mousedown', this._onMouseDown, true);
window.addEventListener('resize', this._onWindowResize);
window.addEventListener('scroll', this._onScroll, {
passive: true,
});
}
this.input.addEventListeners();
};
Choices.prototype._removeEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
documentElement.removeEventListener('touchend', this._onTouchEnd, true);
@ -4092,7 +4146,7 @@ var Choices = /** @class */ (function () {
outerElement.removeEventListener('mousedown', this._onMouseDown, true);
documentElement.removeEventListener('click', this._onClick);
documentElement.removeEventListener('touchmove', this._onTouchMove);
this.dropdown.element.removeEventListener('mouseover', this._onMouseOver);
dropdownElement.removeEventListener('mouseover', this._onMouseOver);
if (this._isSelectOneElement) {
outerElement.removeEventListener('focus', this._onFocus);
outerElement.removeEventListener('blur', this._onBlur);
@ -4108,6 +4162,12 @@ var Choices = /** @class */ (function () {
passedElement.removeEventListener('change', this._onChange);
passedElement.removeEventListener('invalid', this._onInvalid);
}
if (this._dropdownDetached) {
dropdownElement.removeEventListener('keydown', this._onKeyDown);
dropdownElement.removeEventListener('mousedown', this._onMouseDown);
window.removeEventListener('resize', this._onWindowResize);
window.removeEventListener('scroll', this._onScroll);
}
this.input.removeEventListeners();
};
Choices.prototype._onKeyDown = function (event) {
@ -4499,6 +4559,21 @@ var Choices = /** @class */ (function () {
Choices.prototype._onInvalid = function () {
this.containerOuter.addInvalidState();
};
Choices.prototype._onWindowResize = function () {
this._moveDropdown();
};
Choices.prototype._onScroll = function () {
this._moveDropdown();
};
Choices.prototype._moveDropdown = function () {
if (!this.dropdown.isActive) {
return;
}
this.setHorizontalDropdownPosition();
var rect = this.dropdown.element.getBoundingClientRect();
var dropdownAbove = this.containerOuter.shouldFlip(rect.bottom, rect.height);
this.setVerticalDropdownPosition(dropdownAbove);
};
/**
* Removes any highlighted choice options
*/
@ -4677,7 +4752,7 @@ var Choices = /** @class */ (function () {
element: templating.itemList(config, isSelectOneElement),
});
this.dropdown = new Dropdown({
element: templating.dropdown(config),
element: templating.dropdown(config, isSelectOneElement),
classNames: classNames,
type: elementType,
});
@ -4685,14 +4760,18 @@ var Choices = /** @class */ (function () {
Choices.prototype._createStructure = function () {
var _a = this, containerInner = _a.containerInner, containerOuter = _a.containerOuter, passedElement = _a.passedElement;
var dropdownElement = this.dropdown.element;
var dropdownParent = containerOuter.element;
// Hide original element
passedElement.conceal();
// Wrap input in container preserving DOM ordering
containerInner.wrap(passedElement.element);
// Wrapper inner container with outer container
containerOuter.wrap(containerInner.element);
if (this._dropdownDetached && this._dropdownParent instanceof HTMLElement) {
dropdownParent = this._dropdownParent;
}
containerOuter.element.appendChild(containerInner.element);
containerOuter.element.appendChild(dropdownElement);
dropdownParent.appendChild(dropdownElement);
containerInner.element.appendChild(this.itemList.element);
dropdownElement.appendChild(this.choiceList.element);
if (this._isSelectOneElement) {

View file

@ -400,25 +400,32 @@
Container.prototype.removeActiveDescendant = function () {
this.element.removeAttribute('aria-activedescendant');
};
Container.prototype.open = function (dropdownPos, dropdownHeight) {
Container.prototype.open = function (dropdownPos, dropdownHeight, dropdown) {
if (dropdown === void 0) { dropdown = null; }
addClassesToElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'true');
this.isOpen = true;
if (this.shouldFlip(dropdownPos, dropdownHeight)) {
addClassesToElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
addClassesToElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = true;
}
return this.isFlipped;
};
Container.prototype.close = function () {
Container.prototype.close = function (dropdown) {
if (dropdown === void 0) { dropdown = null; }
removeClassesFromElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'false');
this.removeActiveDescendant();
this.isOpen = false;
// A dropdown flips if it does not have space within the page
if (this.isFlipped) {
removeClassesFromElement(this.element, this.classNames.flippedState);
this.isFlipped = false;
removeClassesFromElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
removeClassesFromElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = false;
};
Container.prototype.addFocusState = function () {
addClassesToElement(this.element, this.classNames.focusState);
@ -928,6 +935,8 @@
listItems: ['choices__list--multiple'],
listSingle: ['choices__list--single'],
listDropdown: ['choices__list--dropdown'],
dropdownMultiple: ['choices__dropdown--multiple'],
dropdownSingle: ['choices__dropdown--single'],
item: ['choices__item'],
itemSelectable: ['choices__item--selectable'],
itemDisabled: ['choices__item--disabled'],
@ -1011,6 +1020,7 @@
callbackOnCreateTemplates: null,
classNames: DEFAULT_CLASSNAMES,
appendGroupInSearch: false,
dropdownParent: null,
};
var removeItem = function (item) {
@ -1693,11 +1703,12 @@
}
return inp;
},
dropdown: function (_a) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown;
dropdown: function (_a, isSelectOneElement) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown, dropdownSingle = _b.dropdownSingle, dropdownMultiple = _b.dropdownMultiple;
var div = document.createElement('div');
addClassesToElement(div, list);
addClassesToElement(div, listDropdown);
addClassesToElement(div, isSelectOneElement ? dropdownSingle : dropdownMultiple);
div.setAttribute('aria-expanded', 'false');
return div;
},
@ -1883,6 +1894,8 @@
this._onDeleteKey = this._onDeleteKey.bind(this);
this._onChange = this._onChange.bind(this);
this._onInvalid = this._onInvalid.bind(this);
this._onWindowResize = this._onWindowResize.bind(this);
this._onScroll = this._onScroll.bind(this);
// If element has already been initialised with Choices, fail silently
if (this.passedElement.isActive) {
if (!config.silent) {
@ -1892,6 +1905,15 @@
this.initialisedOK = false;
return;
}
// Dropdown is detached from the original wrapper
this._dropdownDetached = false;
if (config.dropdownParent) {
var parent_1 = this._docRoot.querySelector(config.dropdownParent);
if (parent_1) {
this._dropdownDetached = true;
this._dropdownParent = parent_1;
}
}
// Let's go
this.init();
// preserve the selected item list after setup for form reset
@ -2074,9 +2096,15 @@
preventInputFocus = !this._canSearch;
}
requestAnimationFrame(function () {
if (_this._dropdownDetached) {
_this.setHorizontalDropdownPosition();
}
_this.dropdown.show();
var rect = _this.dropdown.element.getBoundingClientRect();
_this.containerOuter.open(rect.bottom, rect.height);
var dropdownAbove = _this.containerOuter.open(rect.bottom, rect.height, _this.dropdown.element);
if (_this._dropdownDetached) {
_this.setVerticalDropdownPosition(dropdownAbove);
}
if (!preventInputFocus) {
_this.input.focus();
}
@ -2097,7 +2125,7 @@
this._removeHighlightedChoices();
requestAnimationFrame(function () {
_this.dropdown.hide();
_this.containerOuter.close();
_this.containerOuter.close(_this.dropdown.element);
if (!preventInputBlur && _this._canSearch) {
_this.input.removeActiveDescendant();
_this.input.blur();
@ -2106,6 +2134,22 @@
});
return this;
};
Choices.prototype.setHorizontalDropdownPosition = function () {
var containerRect = this.containerOuter.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(window.scrollY + containerRect.bottom, "px");
this.dropdown.element.style.left = "".concat(containerRect.left, "px");
this.dropdown.element.style.width = "".concat(containerRect.width, "px");
return this;
};
Choices.prototype.setVerticalDropdownPosition = function (above) {
if (above === void 0) { above = false; }
if (!above || !(this._dropdownParent instanceof HTMLElement)) {
return this;
}
var dropdownRect = this.dropdown.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(this.containerOuter.element.offsetTop + 1 - dropdownRect.height, "px");
return this;
};
Choices.prototype.getValue = function (valueOnly) {
var values = this._store.items.map(function (item) {
return (valueOnly ? item.value : getChoiceForOutput(item));
@ -2926,6 +2970,7 @@
Choices.prototype._addEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
// capture events - can cancel event processing or propagation
@ -2937,7 +2982,7 @@
documentElement.addEventListener('touchmove', this._onTouchMove, {
passive: true,
});
this.dropdown.element.addEventListener('mouseover', this._onMouseOver, {
dropdownElement.addEventListener('mouseover', this._onMouseOver, {
passive: true,
});
if (this._isSelectOneElement) {
@ -2973,11 +3018,20 @@
passive: true,
});
}
if (this._dropdownDetached) {
dropdownElement.addEventListener('keydown', this._onKeyDown, true);
dropdownElement.addEventListener('mousedown', this._onMouseDown, true);
window.addEventListener('resize', this._onWindowResize);
window.addEventListener('scroll', this._onScroll, {
passive: true,
});
}
this.input.addEventListeners();
};
Choices.prototype._removeEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
documentElement.removeEventListener('touchend', this._onTouchEnd, true);
@ -2985,7 +3039,7 @@
outerElement.removeEventListener('mousedown', this._onMouseDown, true);
documentElement.removeEventListener('click', this._onClick);
documentElement.removeEventListener('touchmove', this._onTouchMove);
this.dropdown.element.removeEventListener('mouseover', this._onMouseOver);
dropdownElement.removeEventListener('mouseover', this._onMouseOver);
if (this._isSelectOneElement) {
outerElement.removeEventListener('focus', this._onFocus);
outerElement.removeEventListener('blur', this._onBlur);
@ -3001,6 +3055,12 @@
passedElement.removeEventListener('change', this._onChange);
passedElement.removeEventListener('invalid', this._onInvalid);
}
if (this._dropdownDetached) {
dropdownElement.removeEventListener('keydown', this._onKeyDown);
dropdownElement.removeEventListener('mousedown', this._onMouseDown);
window.removeEventListener('resize', this._onWindowResize);
window.removeEventListener('scroll', this._onScroll);
}
this.input.removeEventListeners();
};
Choices.prototype._onKeyDown = function (event) {
@ -3392,6 +3452,21 @@
Choices.prototype._onInvalid = function () {
this.containerOuter.addInvalidState();
};
Choices.prototype._onWindowResize = function () {
this._moveDropdown();
};
Choices.prototype._onScroll = function () {
this._moveDropdown();
};
Choices.prototype._moveDropdown = function () {
if (!this.dropdown.isActive) {
return;
}
this.setHorizontalDropdownPosition();
var rect = this.dropdown.element.getBoundingClientRect();
var dropdownAbove = this.containerOuter.shouldFlip(rect.bottom, rect.height);
this.setVerticalDropdownPosition(dropdownAbove);
};
/**
* Removes any highlighted choice options
*/
@ -3570,7 +3645,7 @@
element: templating.itemList(config, isSelectOneElement),
});
this.dropdown = new Dropdown({
element: templating.dropdown(config),
element: templating.dropdown(config, isSelectOneElement),
classNames: classNames,
type: elementType,
});
@ -3578,14 +3653,18 @@
Choices.prototype._createStructure = function () {
var _a = this, containerInner = _a.containerInner, containerOuter = _a.containerOuter, passedElement = _a.passedElement;
var dropdownElement = this.dropdown.element;
var dropdownParent = containerOuter.element;
// Hide original element
passedElement.conceal();
// Wrap input in container preserving DOM ordering
containerInner.wrap(passedElement.element);
// Wrapper inner container with outer container
containerOuter.wrap(containerInner.element);
if (this._dropdownDetached && this._dropdownParent instanceof HTMLElement) {
dropdownParent = this._dropdownParent;
}
containerOuter.element.appendChild(containerInner.element);
containerOuter.element.appendChild(dropdownElement);
dropdownParent.appendChild(dropdownElement);
containerInner.element.appendChild(this.itemList.element);
dropdownElement.appendChild(this.choiceList.element);
if (this._isSelectOneElement) {

File diff suppressed because one or more lines are too long

View file

@ -394,25 +394,32 @@ var Container = /** @class */ (function () {
Container.prototype.removeActiveDescendant = function () {
this.element.removeAttribute('aria-activedescendant');
};
Container.prototype.open = function (dropdownPos, dropdownHeight) {
Container.prototype.open = function (dropdownPos, dropdownHeight, dropdown) {
if (dropdown === void 0) { dropdown = null; }
addClassesToElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'true');
this.isOpen = true;
if (this.shouldFlip(dropdownPos, dropdownHeight)) {
addClassesToElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
addClassesToElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = true;
}
return this.isFlipped;
};
Container.prototype.close = function () {
Container.prototype.close = function (dropdown) {
if (dropdown === void 0) { dropdown = null; }
removeClassesFromElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'false');
this.removeActiveDescendant();
this.isOpen = false;
// A dropdown flips if it does not have space within the page
if (this.isFlipped) {
removeClassesFromElement(this.element, this.classNames.flippedState);
this.isFlipped = false;
removeClassesFromElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
removeClassesFromElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = false;
};
Container.prototype.addFocusState = function () {
addClassesToElement(this.element, this.classNames.focusState);
@ -922,6 +929,8 @@ var DEFAULT_CLASSNAMES = {
listItems: ['choices__list--multiple'],
listSingle: ['choices__list--single'],
listDropdown: ['choices__list--dropdown'],
dropdownMultiple: ['choices__dropdown--multiple'],
dropdownSingle: ['choices__dropdown--single'],
item: ['choices__item'],
itemSelectable: ['choices__item--selectable'],
itemDisabled: ['choices__item--disabled'],
@ -1005,6 +1014,7 @@ var DEFAULT_CONFIG = {
callbackOnCreateTemplates: null,
classNames: DEFAULT_CLASSNAMES,
appendGroupInSearch: false,
dropdownParent: null,
};
var removeItem = function (item) {
@ -1687,11 +1697,12 @@ var templates = {
}
return inp;
},
dropdown: function (_a) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown;
dropdown: function (_a, isSelectOneElement) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown, dropdownSingle = _b.dropdownSingle, dropdownMultiple = _b.dropdownMultiple;
var div = document.createElement('div');
addClassesToElement(div, list);
addClassesToElement(div, listDropdown);
addClassesToElement(div, isSelectOneElement ? dropdownSingle : dropdownMultiple);
div.setAttribute('aria-expanded', 'false');
return div;
},
@ -1877,6 +1888,8 @@ var Choices = /** @class */ (function () {
this._onDeleteKey = this._onDeleteKey.bind(this);
this._onChange = this._onChange.bind(this);
this._onInvalid = this._onInvalid.bind(this);
this._onWindowResize = this._onWindowResize.bind(this);
this._onScroll = this._onScroll.bind(this);
// If element has already been initialised with Choices, fail silently
if (this.passedElement.isActive) {
if (!config.silent) {
@ -1886,6 +1899,15 @@ var Choices = /** @class */ (function () {
this.initialisedOK = false;
return;
}
// Dropdown is detached from the original wrapper
this._dropdownDetached = false;
if (config.dropdownParent) {
var parent_1 = this._docRoot.querySelector(config.dropdownParent);
if (parent_1) {
this._dropdownDetached = true;
this._dropdownParent = parent_1;
}
}
// Let's go
this.init();
// preserve the selected item list after setup for form reset
@ -2068,9 +2090,15 @@ var Choices = /** @class */ (function () {
preventInputFocus = !this._canSearch;
}
requestAnimationFrame(function () {
if (_this._dropdownDetached) {
_this.setHorizontalDropdownPosition();
}
_this.dropdown.show();
var rect = _this.dropdown.element.getBoundingClientRect();
_this.containerOuter.open(rect.bottom, rect.height);
var dropdownAbove = _this.containerOuter.open(rect.bottom, rect.height, _this.dropdown.element);
if (_this._dropdownDetached) {
_this.setVerticalDropdownPosition(dropdownAbove);
}
if (!preventInputFocus) {
_this.input.focus();
}
@ -2091,7 +2119,7 @@ var Choices = /** @class */ (function () {
this._removeHighlightedChoices();
requestAnimationFrame(function () {
_this.dropdown.hide();
_this.containerOuter.close();
_this.containerOuter.close(_this.dropdown.element);
if (!preventInputBlur && _this._canSearch) {
_this.input.removeActiveDescendant();
_this.input.blur();
@ -2100,6 +2128,22 @@ var Choices = /** @class */ (function () {
});
return this;
};
Choices.prototype.setHorizontalDropdownPosition = function () {
var containerRect = this.containerOuter.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(window.scrollY + containerRect.bottom, "px");
this.dropdown.element.style.left = "".concat(containerRect.left, "px");
this.dropdown.element.style.width = "".concat(containerRect.width, "px");
return this;
};
Choices.prototype.setVerticalDropdownPosition = function (above) {
if (above === void 0) { above = false; }
if (!above || !(this._dropdownParent instanceof HTMLElement)) {
return this;
}
var dropdownRect = this.dropdown.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(this.containerOuter.element.offsetTop + 1 - dropdownRect.height, "px");
return this;
};
Choices.prototype.getValue = function (valueOnly) {
var values = this._store.items.map(function (item) {
return (valueOnly ? item.value : getChoiceForOutput(item));
@ -2920,6 +2964,7 @@ var Choices = /** @class */ (function () {
Choices.prototype._addEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
// capture events - can cancel event processing or propagation
@ -2931,7 +2976,7 @@ var Choices = /** @class */ (function () {
documentElement.addEventListener('touchmove', this._onTouchMove, {
passive: true,
});
this.dropdown.element.addEventListener('mouseover', this._onMouseOver, {
dropdownElement.addEventListener('mouseover', this._onMouseOver, {
passive: true,
});
if (this._isSelectOneElement) {
@ -2967,11 +3012,20 @@ var Choices = /** @class */ (function () {
passive: true,
});
}
if (this._dropdownDetached) {
dropdownElement.addEventListener('keydown', this._onKeyDown, true);
dropdownElement.addEventListener('mousedown', this._onMouseDown, true);
window.addEventListener('resize', this._onWindowResize);
window.addEventListener('scroll', this._onScroll, {
passive: true,
});
}
this.input.addEventListeners();
};
Choices.prototype._removeEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
documentElement.removeEventListener('touchend', this._onTouchEnd, true);
@ -2979,7 +3033,7 @@ var Choices = /** @class */ (function () {
outerElement.removeEventListener('mousedown', this._onMouseDown, true);
documentElement.removeEventListener('click', this._onClick);
documentElement.removeEventListener('touchmove', this._onTouchMove);
this.dropdown.element.removeEventListener('mouseover', this._onMouseOver);
dropdownElement.removeEventListener('mouseover', this._onMouseOver);
if (this._isSelectOneElement) {
outerElement.removeEventListener('focus', this._onFocus);
outerElement.removeEventListener('blur', this._onBlur);
@ -2995,6 +3049,12 @@ var Choices = /** @class */ (function () {
passedElement.removeEventListener('change', this._onChange);
passedElement.removeEventListener('invalid', this._onInvalid);
}
if (this._dropdownDetached) {
dropdownElement.removeEventListener('keydown', this._onKeyDown);
dropdownElement.removeEventListener('mousedown', this._onMouseDown);
window.removeEventListener('resize', this._onWindowResize);
window.removeEventListener('scroll', this._onScroll);
}
this.input.removeEventListeners();
};
Choices.prototype._onKeyDown = function (event) {
@ -3386,6 +3446,21 @@ var Choices = /** @class */ (function () {
Choices.prototype._onInvalid = function () {
this.containerOuter.addInvalidState();
};
Choices.prototype._onWindowResize = function () {
this._moveDropdown();
};
Choices.prototype._onScroll = function () {
this._moveDropdown();
};
Choices.prototype._moveDropdown = function () {
if (!this.dropdown.isActive) {
return;
}
this.setHorizontalDropdownPosition();
var rect = this.dropdown.element.getBoundingClientRect();
var dropdownAbove = this.containerOuter.shouldFlip(rect.bottom, rect.height);
this.setVerticalDropdownPosition(dropdownAbove);
};
/**
* Removes any highlighted choice options
*/
@ -3564,7 +3639,7 @@ var Choices = /** @class */ (function () {
element: templating.itemList(config, isSelectOneElement),
});
this.dropdown = new Dropdown({
element: templating.dropdown(config),
element: templating.dropdown(config, isSelectOneElement),
classNames: classNames,
type: elementType,
});
@ -3572,14 +3647,18 @@ var Choices = /** @class */ (function () {
Choices.prototype._createStructure = function () {
var _a = this, containerInner = _a.containerInner, containerOuter = _a.containerOuter, passedElement = _a.passedElement;
var dropdownElement = this.dropdown.element;
var dropdownParent = containerOuter.element;
// Hide original element
passedElement.conceal();
// Wrap input in container preserving DOM ordering
containerInner.wrap(passedElement.element);
// Wrapper inner container with outer container
containerOuter.wrap(containerInner.element);
if (this._dropdownDetached && this._dropdownParent instanceof HTMLElement) {
dropdownParent = this._dropdownParent;
}
containerOuter.element.appendChild(containerInner.element);
containerOuter.element.appendChild(dropdownElement);
dropdownParent.appendChild(dropdownElement);
containerInner.element.appendChild(this.itemList.element);
dropdownElement.appendChild(this.choiceList.element);
if (this._isSelectOneElement) {

View file

@ -400,25 +400,32 @@
Container.prototype.removeActiveDescendant = function () {
this.element.removeAttribute('aria-activedescendant');
};
Container.prototype.open = function (dropdownPos, dropdownHeight) {
Container.prototype.open = function (dropdownPos, dropdownHeight, dropdown) {
if (dropdown === void 0) { dropdown = null; }
addClassesToElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'true');
this.isOpen = true;
if (this.shouldFlip(dropdownPos, dropdownHeight)) {
addClassesToElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
addClassesToElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = true;
}
return this.isFlipped;
};
Container.prototype.close = function () {
Container.prototype.close = function (dropdown) {
if (dropdown === void 0) { dropdown = null; }
removeClassesFromElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'false');
this.removeActiveDescendant();
this.isOpen = false;
// A dropdown flips if it does not have space within the page
if (this.isFlipped) {
removeClassesFromElement(this.element, this.classNames.flippedState);
this.isFlipped = false;
removeClassesFromElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
removeClassesFromElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = false;
};
Container.prototype.addFocusState = function () {
addClassesToElement(this.element, this.classNames.focusState);
@ -928,6 +935,8 @@
listItems: ['choices__list--multiple'],
listSingle: ['choices__list--single'],
listDropdown: ['choices__list--dropdown'],
dropdownMultiple: ['choices__dropdown--multiple'],
dropdownSingle: ['choices__dropdown--single'],
item: ['choices__item'],
itemSelectable: ['choices__item--selectable'],
itemDisabled: ['choices__item--disabled'],
@ -1011,6 +1020,7 @@
callbackOnCreateTemplates: null,
classNames: DEFAULT_CLASSNAMES,
appendGroupInSearch: false,
dropdownParent: null,
};
var removeItem = function (item) {
@ -1651,11 +1661,12 @@
}
return inp;
},
dropdown: function (_a) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown;
dropdown: function (_a, isSelectOneElement) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown, dropdownSingle = _b.dropdownSingle, dropdownMultiple = _b.dropdownMultiple;
var div = document.createElement('div');
addClassesToElement(div, list);
addClassesToElement(div, listDropdown);
addClassesToElement(div, isSelectOneElement ? dropdownSingle : dropdownMultiple);
div.setAttribute('aria-expanded', 'false');
return div;
},
@ -1841,6 +1852,8 @@
this._onDeleteKey = this._onDeleteKey.bind(this);
this._onChange = this._onChange.bind(this);
this._onInvalid = this._onInvalid.bind(this);
this._onWindowResize = this._onWindowResize.bind(this);
this._onScroll = this._onScroll.bind(this);
// If element has already been initialised with Choices, fail silently
if (this.passedElement.isActive) {
if (!config.silent) {
@ -1850,6 +1863,15 @@
this.initialisedOK = false;
return;
}
// Dropdown is detached from the original wrapper
this._dropdownDetached = false;
if (config.dropdownParent) {
var parent_1 = this._docRoot.querySelector(config.dropdownParent);
if (parent_1) {
this._dropdownDetached = true;
this._dropdownParent = parent_1;
}
}
// Let's go
this.init();
// preserve the selected item list after setup for form reset
@ -2032,9 +2054,15 @@
preventInputFocus = !this._canSearch;
}
requestAnimationFrame(function () {
if (_this._dropdownDetached) {
_this.setHorizontalDropdownPosition();
}
_this.dropdown.show();
var rect = _this.dropdown.element.getBoundingClientRect();
_this.containerOuter.open(rect.bottom, rect.height);
var dropdownAbove = _this.containerOuter.open(rect.bottom, rect.height, _this.dropdown.element);
if (_this._dropdownDetached) {
_this.setVerticalDropdownPosition(dropdownAbove);
}
if (!preventInputFocus) {
_this.input.focus();
}
@ -2055,7 +2083,7 @@
this._removeHighlightedChoices();
requestAnimationFrame(function () {
_this.dropdown.hide();
_this.containerOuter.close();
_this.containerOuter.close(_this.dropdown.element);
if (!preventInputBlur && _this._canSearch) {
_this.input.removeActiveDescendant();
_this.input.blur();
@ -2064,6 +2092,22 @@
});
return this;
};
Choices.prototype.setHorizontalDropdownPosition = function () {
var containerRect = this.containerOuter.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(window.scrollY + containerRect.bottom, "px");
this.dropdown.element.style.left = "".concat(containerRect.left, "px");
this.dropdown.element.style.width = "".concat(containerRect.width, "px");
return this;
};
Choices.prototype.setVerticalDropdownPosition = function (above) {
if (above === void 0) { above = false; }
if (!above || !(this._dropdownParent instanceof HTMLElement)) {
return this;
}
var dropdownRect = this.dropdown.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(this.containerOuter.element.offsetTop + 1 - dropdownRect.height, "px");
return this;
};
Choices.prototype.getValue = function (valueOnly) {
var values = this._store.items.map(function (item) {
return (valueOnly ? item.value : getChoiceForOutput(item));
@ -2884,6 +2928,7 @@
Choices.prototype._addEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
// capture events - can cancel event processing or propagation
@ -2895,7 +2940,7 @@
documentElement.addEventListener('touchmove', this._onTouchMove, {
passive: true,
});
this.dropdown.element.addEventListener('mouseover', this._onMouseOver, {
dropdownElement.addEventListener('mouseover', this._onMouseOver, {
passive: true,
});
if (this._isSelectOneElement) {
@ -2931,11 +2976,20 @@
passive: true,
});
}
if (this._dropdownDetached) {
dropdownElement.addEventListener('keydown', this._onKeyDown, true);
dropdownElement.addEventListener('mousedown', this._onMouseDown, true);
window.addEventListener('resize', this._onWindowResize);
window.addEventListener('scroll', this._onScroll, {
passive: true,
});
}
this.input.addEventListeners();
};
Choices.prototype._removeEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
documentElement.removeEventListener('touchend', this._onTouchEnd, true);
@ -2943,7 +2997,7 @@
outerElement.removeEventListener('mousedown', this._onMouseDown, true);
documentElement.removeEventListener('click', this._onClick);
documentElement.removeEventListener('touchmove', this._onTouchMove);
this.dropdown.element.removeEventListener('mouseover', this._onMouseOver);
dropdownElement.removeEventListener('mouseover', this._onMouseOver);
if (this._isSelectOneElement) {
outerElement.removeEventListener('focus', this._onFocus);
outerElement.removeEventListener('blur', this._onBlur);
@ -2959,6 +3013,12 @@
passedElement.removeEventListener('change', this._onChange);
passedElement.removeEventListener('invalid', this._onInvalid);
}
if (this._dropdownDetached) {
dropdownElement.removeEventListener('keydown', this._onKeyDown);
dropdownElement.removeEventListener('mousedown', this._onMouseDown);
window.removeEventListener('resize', this._onWindowResize);
window.removeEventListener('scroll', this._onScroll);
}
this.input.removeEventListeners();
};
Choices.prototype._onKeyDown = function (event) {
@ -3350,6 +3410,21 @@
Choices.prototype._onInvalid = function () {
this.containerOuter.addInvalidState();
};
Choices.prototype._onWindowResize = function () {
this._moveDropdown();
};
Choices.prototype._onScroll = function () {
this._moveDropdown();
};
Choices.prototype._moveDropdown = function () {
if (!this.dropdown.isActive) {
return;
}
this.setHorizontalDropdownPosition();
var rect = this.dropdown.element.getBoundingClientRect();
var dropdownAbove = this.containerOuter.shouldFlip(rect.bottom, rect.height);
this.setVerticalDropdownPosition(dropdownAbove);
};
/**
* Removes any highlighted choice options
*/
@ -3528,7 +3603,7 @@
element: templating.itemList(config, isSelectOneElement),
});
this.dropdown = new Dropdown({
element: templating.dropdown(config),
element: templating.dropdown(config, isSelectOneElement),
classNames: classNames,
type: elementType,
});
@ -3536,14 +3611,18 @@
Choices.prototype._createStructure = function () {
var _a = this, containerInner = _a.containerInner, containerOuter = _a.containerOuter, passedElement = _a.passedElement;
var dropdownElement = this.dropdown.element;
var dropdownParent = containerOuter.element;
// Hide original element
passedElement.conceal();
// Wrap input in container preserving DOM ordering
containerInner.wrap(passedElement.element);
// Wrapper inner container with outer container
containerOuter.wrap(containerInner.element);
if (this._dropdownDetached && this._dropdownParent instanceof HTMLElement) {
dropdownParent = this._dropdownParent;
}
containerOuter.element.appendChild(containerInner.element);
containerOuter.element.appendChild(dropdownElement);
dropdownParent.appendChild(dropdownElement);
containerInner.element.appendChild(this.itemList.element);
dropdownElement.appendChild(this.choiceList.element);
if (this._isSelectOneElement) {

File diff suppressed because one or more lines are too long

View file

@ -394,25 +394,32 @@ var Container = /** @class */ (function () {
Container.prototype.removeActiveDescendant = function () {
this.element.removeAttribute('aria-activedescendant');
};
Container.prototype.open = function (dropdownPos, dropdownHeight) {
Container.prototype.open = function (dropdownPos, dropdownHeight, dropdown) {
if (dropdown === void 0) { dropdown = null; }
addClassesToElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'true');
this.isOpen = true;
if (this.shouldFlip(dropdownPos, dropdownHeight)) {
addClassesToElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
addClassesToElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = true;
}
return this.isFlipped;
};
Container.prototype.close = function () {
Container.prototype.close = function (dropdown) {
if (dropdown === void 0) { dropdown = null; }
removeClassesFromElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'false');
this.removeActiveDescendant();
this.isOpen = false;
// A dropdown flips if it does not have space within the page
if (this.isFlipped) {
removeClassesFromElement(this.element, this.classNames.flippedState);
this.isFlipped = false;
removeClassesFromElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
removeClassesFromElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = false;
};
Container.prototype.addFocusState = function () {
addClassesToElement(this.element, this.classNames.focusState);
@ -922,6 +929,8 @@ var DEFAULT_CLASSNAMES = {
listItems: ['choices__list--multiple'],
listSingle: ['choices__list--single'],
listDropdown: ['choices__list--dropdown'],
dropdownMultiple: ['choices__dropdown--multiple'],
dropdownSingle: ['choices__dropdown--single'],
item: ['choices__item'],
itemSelectable: ['choices__item--selectable'],
itemDisabled: ['choices__item--disabled'],
@ -1005,6 +1014,7 @@ var DEFAULT_CONFIG = {
callbackOnCreateTemplates: null,
classNames: DEFAULT_CLASSNAMES,
appendGroupInSearch: false,
dropdownParent: null,
};
var removeItem = function (item) {
@ -1645,11 +1655,12 @@ var templates = {
}
return inp;
},
dropdown: function (_a) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown;
dropdown: function (_a, isSelectOneElement) {
var _b = _a.classNames, list = _b.list, listDropdown = _b.listDropdown, dropdownSingle = _b.dropdownSingle, dropdownMultiple = _b.dropdownMultiple;
var div = document.createElement('div');
addClassesToElement(div, list);
addClassesToElement(div, listDropdown);
addClassesToElement(div, isSelectOneElement ? dropdownSingle : dropdownMultiple);
div.setAttribute('aria-expanded', 'false');
return div;
},
@ -1835,6 +1846,8 @@ var Choices = /** @class */ (function () {
this._onDeleteKey = this._onDeleteKey.bind(this);
this._onChange = this._onChange.bind(this);
this._onInvalid = this._onInvalid.bind(this);
this._onWindowResize = this._onWindowResize.bind(this);
this._onScroll = this._onScroll.bind(this);
// If element has already been initialised with Choices, fail silently
if (this.passedElement.isActive) {
if (!config.silent) {
@ -1844,6 +1857,15 @@ var Choices = /** @class */ (function () {
this.initialisedOK = false;
return;
}
// Dropdown is detached from the original wrapper
this._dropdownDetached = false;
if (config.dropdownParent) {
var parent_1 = this._docRoot.querySelector(config.dropdownParent);
if (parent_1) {
this._dropdownDetached = true;
this._dropdownParent = parent_1;
}
}
// Let's go
this.init();
// preserve the selected item list after setup for form reset
@ -2026,9 +2048,15 @@ var Choices = /** @class */ (function () {
preventInputFocus = !this._canSearch;
}
requestAnimationFrame(function () {
if (_this._dropdownDetached) {
_this.setHorizontalDropdownPosition();
}
_this.dropdown.show();
var rect = _this.dropdown.element.getBoundingClientRect();
_this.containerOuter.open(rect.bottom, rect.height);
var dropdownAbove = _this.containerOuter.open(rect.bottom, rect.height, _this.dropdown.element);
if (_this._dropdownDetached) {
_this.setVerticalDropdownPosition(dropdownAbove);
}
if (!preventInputFocus) {
_this.input.focus();
}
@ -2049,7 +2077,7 @@ var Choices = /** @class */ (function () {
this._removeHighlightedChoices();
requestAnimationFrame(function () {
_this.dropdown.hide();
_this.containerOuter.close();
_this.containerOuter.close(_this.dropdown.element);
if (!preventInputBlur && _this._canSearch) {
_this.input.removeActiveDescendant();
_this.input.blur();
@ -2058,6 +2086,22 @@ var Choices = /** @class */ (function () {
});
return this;
};
Choices.prototype.setHorizontalDropdownPosition = function () {
var containerRect = this.containerOuter.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(window.scrollY + containerRect.bottom, "px");
this.dropdown.element.style.left = "".concat(containerRect.left, "px");
this.dropdown.element.style.width = "".concat(containerRect.width, "px");
return this;
};
Choices.prototype.setVerticalDropdownPosition = function (above) {
if (above === void 0) { above = false; }
if (!above || !(this._dropdownParent instanceof HTMLElement)) {
return this;
}
var dropdownRect = this.dropdown.element.getBoundingClientRect();
this.dropdown.element.style.top = "".concat(this.containerOuter.element.offsetTop + 1 - dropdownRect.height, "px");
return this;
};
Choices.prototype.getValue = function (valueOnly) {
var values = this._store.items.map(function (item) {
return (valueOnly ? item.value : getChoiceForOutput(item));
@ -2878,6 +2922,7 @@ var Choices = /** @class */ (function () {
Choices.prototype._addEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
// capture events - can cancel event processing or propagation
@ -2889,7 +2934,7 @@ var Choices = /** @class */ (function () {
documentElement.addEventListener('touchmove', this._onTouchMove, {
passive: true,
});
this.dropdown.element.addEventListener('mouseover', this._onMouseOver, {
dropdownElement.addEventListener('mouseover', this._onMouseOver, {
passive: true,
});
if (this._isSelectOneElement) {
@ -2925,11 +2970,20 @@ var Choices = /** @class */ (function () {
passive: true,
});
}
if (this._dropdownDetached) {
dropdownElement.addEventListener('keydown', this._onKeyDown, true);
dropdownElement.addEventListener('mousedown', this._onMouseDown, true);
window.addEventListener('resize', this._onWindowResize);
window.addEventListener('scroll', this._onScroll, {
passive: true,
});
}
this.input.addEventListeners();
};
Choices.prototype._removeEventListeners = function () {
var documentElement = this._docRoot;
var outerElement = this.containerOuter.element;
var dropdownElement = this.dropdown.element;
var inputElement = this.input.element;
var passedElement = this.passedElement.element;
documentElement.removeEventListener('touchend', this._onTouchEnd, true);
@ -2937,7 +2991,7 @@ var Choices = /** @class */ (function () {
outerElement.removeEventListener('mousedown', this._onMouseDown, true);
documentElement.removeEventListener('click', this._onClick);
documentElement.removeEventListener('touchmove', this._onTouchMove);
this.dropdown.element.removeEventListener('mouseover', this._onMouseOver);
dropdownElement.removeEventListener('mouseover', this._onMouseOver);
if (this._isSelectOneElement) {
outerElement.removeEventListener('focus', this._onFocus);
outerElement.removeEventListener('blur', this._onBlur);
@ -2953,6 +3007,12 @@ var Choices = /** @class */ (function () {
passedElement.removeEventListener('change', this._onChange);
passedElement.removeEventListener('invalid', this._onInvalid);
}
if (this._dropdownDetached) {
dropdownElement.removeEventListener('keydown', this._onKeyDown);
dropdownElement.removeEventListener('mousedown', this._onMouseDown);
window.removeEventListener('resize', this._onWindowResize);
window.removeEventListener('scroll', this._onScroll);
}
this.input.removeEventListeners();
};
Choices.prototype._onKeyDown = function (event) {
@ -3344,6 +3404,21 @@ var Choices = /** @class */ (function () {
Choices.prototype._onInvalid = function () {
this.containerOuter.addInvalidState();
};
Choices.prototype._onWindowResize = function () {
this._moveDropdown();
};
Choices.prototype._onScroll = function () {
this._moveDropdown();
};
Choices.prototype._moveDropdown = function () {
if (!this.dropdown.isActive) {
return;
}
this.setHorizontalDropdownPosition();
var rect = this.dropdown.element.getBoundingClientRect();
var dropdownAbove = this.containerOuter.shouldFlip(rect.bottom, rect.height);
this.setVerticalDropdownPosition(dropdownAbove);
};
/**
* Removes any highlighted choice options
*/
@ -3522,7 +3597,7 @@ var Choices = /** @class */ (function () {
element: templating.itemList(config, isSelectOneElement),
});
this.dropdown = new Dropdown({
element: templating.dropdown(config),
element: templating.dropdown(config, isSelectOneElement),
classNames: classNames,
type: elementType,
});
@ -3530,14 +3605,18 @@ var Choices = /** @class */ (function () {
Choices.prototype._createStructure = function () {
var _a = this, containerInner = _a.containerInner, containerOuter = _a.containerOuter, passedElement = _a.passedElement;
var dropdownElement = this.dropdown.element;
var dropdownParent = containerOuter.element;
// Hide original element
passedElement.conceal();
// Wrap input in container preserving DOM ordering
containerInner.wrap(passedElement.element);
// Wrapper inner container with outer container
containerOuter.wrap(containerInner.element);
if (this._dropdownDetached && this._dropdownParent instanceof HTMLElement) {
dropdownParent = this._dropdownParent;
}
containerOuter.element.appendChild(containerInner.element);
containerOuter.element.appendChild(dropdownElement);
dropdownParent.appendChild(dropdownElement);
containerInner.element.appendChild(this.itemList.element);
dropdownElement.appendChild(this.choiceList.element);
if (this._isSelectOneElement) {

View file

@ -47,7 +47,6 @@ body {
position: relative;
margin: 0;
width: 100%;
height: 100%;
}
body {
@ -169,6 +168,11 @@ label + p {
color: var(--link-color-section, var(--color-primary));
}
/** Set the section color on the dropdown list to not inherit the white color */
body > .choices__list {
color: var(--section-color, #333);
}
.logo {
display: block;
margin-bottom: 12px;

View file

@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../../../src/styles/base.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAIA;EACE;;;AAGF;EACE;AACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IAEA;;EAGF;IACE;;;AAYJ;EACE;EACA;;;AAGF;AAAA;AAAA;EAGE;;;AAGF;AAAA;EAEE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;EAGE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,eAtFiB;;;AAyFnB;AAAA;EAEE,WA1FoB;;;AA6FtB;AAAA;EAEE,WA9FoB;;;AAiGtB;AAAA;EAEE,WAlGoB;;;AAqGtB;AAAA;EAEE,WAtGoB;;;AAyGtB;AAAA;EAEE,WA1GoB;;;AA6GtB;AAAA;EAEE,WA9GoB;;;AAiHtB;EACE;;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EANF;IAOI;;;;AAIJ;EACE;EACA,SAxIiB;EAyIjB;;AAEA;AAAA;AAAA;EAGE;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE,eArKiB;;;AAwKnB;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE,eArLiB;;;AAwLnB","file":"base.css"}
{"version":3,"sourceRoot":"","sources":["../../../src/styles/base.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAIA;EACE;;;AAGF;EACE;AACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IAEA;;EAGF;IACE;;;AAYJ;EACE;EACA;;;AAGF;AAAA;AAAA;EAGE;;;AAGF;AAAA;EAEE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;EAGE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,eArFiB;;;AAwFnB;AAAA;EAEE,WAzFoB;;;AA4FtB;AAAA;EAEE,WA7FoB;;;AAgGtB;AAAA;EAEE,WAjGoB;;;AAoGtB;AAAA;EAEE,WArGoB;;;AAwGtB;AAAA;EAEE,WAzGoB;;;AA4GtB;AAAA;EAEE,WA7GoB;;;AAgHtB;EACE;;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EANF;IAOI;;;;AAIJ;EACE;EACA,SAvIiB;EAwIjB;;AAEA;AAAA;AAAA;EAGE;;;AAIJ;AAEA;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE,eA1KiB;;;AA6KnB;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE,eA1LiB;;;AA6LnB","file":"base.css"}

View file

@ -1 +1 @@
:root{--color-primary:#005F75}@media (prefers-color-scheme:dark){:root{--body-bg:#272a2b;--text-color:#cacaca;--color-primary:#38daff;--section-bg:#181a1b;--section-color:#cacaca;--hr-border:#373a3d;--choices-primary-color:#38daff;--choices-item-color:black;--choices-bg-color:#101010;--choices-bg-color-dropdown:#101010;--choices-keyline-color:#3b3e40;--choices-bg-color-disabled:#181a1b;--choices-item-disabled-color:#eee;--choices-disabled-color:#2d2d2d;--choices-highlighted-color:#16292d;--choices-icon-cross:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==");--choices-icon-cross-inverse:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==");color-scheme:dark}input,select{color:#fff}}*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,::after,::before{box-sizing:border-box}body,html{position:relative;margin:0;width:100%;height:100%}body{font-family:"Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-size:16px;line-height:1.4;color:var(--text-color, #fff);background-color:var(--body-bg, #333);overflow-x:hidden}hr,label{display:block}label,p{margin-bottom:8px}label{font-size:14px;font-weight:500;cursor:pointer}p{margin-top:0}hr{margin:30px 0;border:0;border-bottom:1px solid var(--hr-border, #eaeaea);height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:12px;font-weight:400;line-height:1.2}a,a:focus,a:visited{color:var(--link-color, #fff);text-decoration:none;font-weight:600}.form-control{display:block;width:100%;background-color:var(--form-bg, #f9f9f9);padding:12px;border:1px solid var(--form-boder, #ddd);border-radius:2.5px;font-size:14px;appearance:none;margin-bottom:24px}.h1,h1{font-size:32px}.h2,h2{font-size:24px}.h3,h3{font-size:20px}.h4,h4{font-size:18px}.h5,h5{font-size:16px}.h6,h6{font-size:14px}label+p{margin-top:-4px}.container{display:block;margin:auto;max-width:40em;padding:48px}@media (max-width:620px){.container{padding:0}}.section{background-color:var(--section-bg, #fff);padding:24px;color:var(--section-color, #333)}.section a,.section a:focus,.section a:visited{color:var(--link-color-section, var(--color-primary))}.logo{display:block;margin-bottom:12px}.logo-img{width:100%;height:auto;display:inline-block;max-width:100%;vertical-align:top;padding:6px 0}.visible-ie{display:none}.push-bottom{margin-bottom:24px}.zero-bottom{margin-bottom:0}.zero-top{margin-top:0}.text-center{text-align:center}[data-test-hook]{margin-bottom:24px}
:root{--color-primary:#005F75}@media (prefers-color-scheme:dark){:root{--body-bg:#272a2b;--text-color:#cacaca;--color-primary:#38daff;--section-bg:#181a1b;--section-color:#cacaca;--hr-border:#373a3d;--choices-primary-color:#38daff;--choices-item-color:black;--choices-bg-color:#101010;--choices-bg-color-dropdown:#101010;--choices-keyline-color:#3b3e40;--choices-bg-color-disabled:#181a1b;--choices-item-disabled-color:#eee;--choices-disabled-color:#2d2d2d;--choices-highlighted-color:#16292d;--choices-icon-cross:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==");--choices-icon-cross-inverse:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==");color-scheme:dark}input,select{color:#fff}}*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,::after,::before{box-sizing:border-box}body,html{position:relative;margin:0;width:100%}body{font-family:"Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-size:16px;line-height:1.4;color:var(--text-color, #fff);background-color:var(--body-bg, #333);overflow-x:hidden}hr,label{display:block}label,p{margin-bottom:8px}label{font-size:14px;font-weight:500;cursor:pointer}p{margin-top:0}hr{margin:30px 0;border:0;border-bottom:1px solid var(--hr-border, #eaeaea);height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:12px;font-weight:400;line-height:1.2}a,a:focus,a:visited{color:var(--link-color, #fff);text-decoration:none;font-weight:600}.form-control{display:block;width:100%;background-color:var(--form-bg, #f9f9f9);padding:12px;border:1px solid var(--form-boder, #ddd);border-radius:2.5px;font-size:14px;appearance:none;margin-bottom:24px}.h1,h1{font-size:32px}.h2,h2{font-size:24px}.h3,h3{font-size:20px}.h4,h4{font-size:18px}.h5,h5{font-size:16px}.h6,h6{font-size:14px}label+p{margin-top:-4px}.container{display:block;margin:auto;max-width:40em;padding:48px}@media (max-width:620px){.container{padding:0}}.section{background-color:var(--section-bg, #fff);padding:24px;color:var(--section-color, #333)}.section a,.section a:focus,.section a:visited{color:var(--link-color-section, var(--color-primary))}body>.choices__list{color:var(--section-color, #333)}.logo{display:block;margin-bottom:12px}.logo-img{width:100%;height:auto;display:inline-block;max-width:100%;vertical-align:top;padding:6px 0}.visible-ie{display:none}.push-bottom{margin-bottom:24px}.zero-bottom{margin-bottom:0}.zero-top{margin-top:0}.text-center{text-align:center}[data-test-hook]{margin-bottom:24px}

View file

@ -16,6 +16,10 @@
.choices.is-open {
overflow: visible;
}
.choices.is-flipped .choices__list {
top: auto;
bottom: 100%;
}
.choices.is-disabled :is(.choices__inner, .choices__input) {
background-color: var(--choices-bg-color-disabled, #eaeaea);
cursor: not-allowed !important;
@ -39,14 +43,6 @@
.choices[data-type*=select-one] .choices__inner {
padding-bottom: var(--choices-inner-one-padding, 7.5px);
}
.choices[data-type*=select-one] .choices__input {
display: block;
width: var(--choices-width, 100%);
padding: var(--choices-dropdown-item-padding, 10px);
border-bottom: var(--choices-base-border, 1px solid) var(--choices-keyline-color, #ddd);
background-color: var(--choices-bg-color-dropdown, #fff);
margin: 0;
}
.choices[data-type*=select-one] .choices__button {
background-image: var(--choices-icon-cross-inverse, url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg=="));
padding: 0;
@ -98,6 +94,15 @@
margin-right: 0;
}
.choices__dropdown--single .choices__input {
display: block;
width: var(--choices-width, 100%);
padding: var(--choices-dropdown-item-padding, 10px);
border-bottom: var(--choices-base-border, 1px solid) var(--choices-keyline-color, #ddd);
background-color: var(--choices-bg-color-dropdown, #fff);
margin: 0;
}
.choices:is([data-type*=select-multiple], [data-type*=text]) .choices__inner {
cursor: text;
}
@ -215,12 +220,10 @@
.is-open .choices__list--dropdown, .is-open .choices__list[aria-expanded] {
border-color: color-mix(in srgb, var(--choices-keyline-color, #ddd) 85%, var(--choices-darken, black));
}
.is-flipped .choices__list--dropdown, .is-flipped .choices__list[aria-expanded] {
top: auto;
bottom: 100%;
.is-flipped.choices__list--dropdown, .is-flipped.choices__list[aria-expanded] {
margin-top: 0;
margin-bottom: -1px;
border-radius: 0.25rem 0.25rem 0 0;
border-radius: var(--choices-border-radius, 2.5px) var(--choices-border-radius, 2.5px) 0 0;
}
.choices__list--dropdown .choices__list, .choices__list[aria-expanded] .choices__list {
position: relative;

View file

@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../../../src/styles/choices.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAiDA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAIA;EACE;EACA;EACA;;AAEF;EACE;EACA;;AAIJ;EACE;EACA;EACA;EACA;;;AAIJ;EACE;;AACA;EACE;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGJ;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAIA;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;;;AAMJ;EACE;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAKN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;;AAIJ;EACE;EACA;EACA;;AAOF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAEF;EACE;;;AAIJ;EACE;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;;AAKN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;;AAEA;EACE;;AAKA;EADF;IAEI;;EAEA;IACE;IACA;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;;EAEA;IACE;IACA;;;AAQN;EACE;;AAIJ;EAEE;;;AASN;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA,WArXqB;EAsXrB;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EAIE;;AAGF;EAEE;EACA;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;;;AAGF","file":"choices.css"}
{"version":3,"sourceRoot":"","sources":["../../../src/styles/choices.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAiDA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAKA;EACE;EACA;;AAKF;EACE;EACA;EACA;;AAEF;EACE;EACA;;AAIJ;EACE;EACA;EACA;EACA;;;AAIJ;EACE;;AACA;EACE;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGJ;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAIA;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;;;AAMJ;EACE;EACA;EACA;EACA;EACA;EACA;;;AAKF;EACE;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAKN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;;AAIJ;EACE;EACA;EACA;;AAOF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAEF;EACE;;;AAIJ;EACE;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;;AAKN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;;AAEA;EACE;;AAKA;EADF;IAEI;;EAEA;IACE;IACA;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;;EAEA;IACE;IACA;;;AAQN;EACE;;AAIJ;EAEE;;;AASN;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA,WA9XqB;EA+XrB;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EAIE;;AAGF;EAEE;EACA;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;;;AAGF","file":"choices.css"}

File diff suppressed because one or more lines are too long

View file

@ -62,6 +62,8 @@ declare class Choices {
text: string;
};
_docRoot: ShadowRoot | HTMLElement;
_dropdownParent: HTMLElement | null;
_dropdownDetached: boolean;
constructor(element?: string | Element | HTMLInputElement | HTMLSelectElement, userConfig?: Partial<Options>);
init(): void;
destroy(): void;
@ -76,6 +78,8 @@ declare class Choices {
removeHighlightedItems(runEvent?: boolean): this;
showDropdown(preventInputFocus?: boolean): this;
hideDropdown(preventInputBlur?: boolean): this;
setHorizontalDropdownPosition(): this;
setVerticalDropdownPosition(above?: boolean): this;
getValue<B extends boolean = false>(valueOnly?: B): EventChoiceValueType<B> | EventChoiceValueType<B>[];
setValue(items: string[] | InputChoice[]): this;
setChoiceByValue(value: string | string[]): this;
@ -200,6 +204,9 @@ declare class Choices {
target: HTMLInputElement | HTMLSelectElement;
}): void;
_onInvalid(): void;
_onWindowResize(): void;
_onScroll(): void;
_moveDropdown(): void;
/**
* Removes any highlighted choice options
*/

View file

@ -23,8 +23,8 @@ export default class Container {
shouldFlip(dropdownPos: number, dropdownHeight: number): boolean;
setActiveDescendant(activeDescendantID: string): void;
removeActiveDescendant(): void;
open(dropdownPos: number, dropdownHeight: number): void;
close(): void;
open(dropdownPos: number, dropdownHeight: number, dropdown?: HTMLElement | null): boolean;
close(dropdown?: HTMLElement | null): void;
addFocusState(): void;
removeFocusState(): void;
addInvalidState(): void;

View file

@ -16,6 +16,10 @@ export interface ClassNames {
listSingle: string | Array<string>;
/** @default ['choices__list--dropdown'] */
listDropdown: string | Array<string>;
/** @default ['choices__dropdown--multiple'] */
dropdownMultiple: string | Array<string>;
/** @default ['choices__dropdown--single'] */
dropdownSingle: string | Array<string>;
/** @default ['choices__item'] */
item: string | Array<string>;
/** @default ['choices__item--selectable'] */

View file

@ -579,4 +579,12 @@ export interface Options {
*/
callbackOnCreateTemplates: CallbackOnCreateTemplatesFn | null;
appendGroupInSearch: boolean;
/**
* CSS selector for the element to append the dropdown to. Similar to select2's appendTo option
*
* **Input types affected:** `select-one`, `select-multiple`
*
* @default null
*/
dropdownParent: string | null;
}

View file

@ -23,7 +23,7 @@ export interface Templates {
choiceGroup(options: TemplateOptions, group: GroupFull): HTMLDivElement;
choice(options: TemplateOptions, choice: ChoiceFull, selectText: string, groupText?: string): HTMLDivElement;
input(options: TemplateOptions, placeholderValue: string | null): HTMLInputElement;
dropdown(options: TemplateOptions): HTMLDivElement;
dropdown(options: TemplateOptions, isSelectOneElement: boolean): HTMLDivElement;
notice(options: TemplateOptions, innerText: string, type: NoticeType): HTMLDivElement;
option(choice: ChoiceFull): HTMLOptionElement;
}

View file

@ -158,6 +158,10 @@ class Choices {
_docRoot: ShadowRoot | HTMLElement;
_dropdownParent: HTMLElement | null;
_dropdownDetached: boolean;
constructor(
element: string | Element | HTMLInputElement | HTMLSelectElement = '[data-choice]',
userConfig: Partial<Options> = {},
@ -306,6 +310,8 @@ class Choices {
this._onDeleteKey = this._onDeleteKey.bind(this);
this._onChange = this._onChange.bind(this);
this._onInvalid = this._onInvalid.bind(this);
this._onWindowResize = this._onWindowResize.bind(this);
this._onScroll = this._onScroll.bind(this);
// If element has already been initialised with Choices, fail silently
if (this.passedElement.isActive) {
@ -319,6 +325,18 @@ class Choices {
return;
}
// Dropdown is detached from the original wrapper
this._dropdownDetached = false;
if (config.dropdownParent) {
const parent = this._docRoot.querySelector<HTMLElement>(config.dropdownParent);
if (parent) {
this._dropdownDetached = true;
this._dropdownParent = parent;
}
}
// Let's go
this.init();
// preserve the selected item list after setup for form reset
@ -512,9 +530,18 @@ class Choices {
}
requestAnimationFrame(() => {
if (this._dropdownDetached) {
this.setHorizontalDropdownPosition();
}
this.dropdown.show();
const rect = this.dropdown.element.getBoundingClientRect();
this.containerOuter.open(rect.bottom, rect.height);
const dropdownAbove = this.containerOuter.open(rect.bottom, rect.height, this.dropdown.element);
if (this._dropdownDetached) {
this.setVerticalDropdownPosition(dropdownAbove);
}
if (!preventInputFocus) {
this.input.focus();
@ -544,7 +571,7 @@ class Choices {
requestAnimationFrame(() => {
this.dropdown.hide();
this.containerOuter.close();
this.containerOuter.close(this.dropdown.element);
if (!preventInputBlur && this._canSearch) {
this.input.removeActiveDescendant();
@ -557,6 +584,28 @@ class Choices {
return this;
}
setHorizontalDropdownPosition(): this {
const containerRect = this.containerOuter.element.getBoundingClientRect();
this.dropdown.element.style.top = `${window.scrollY + containerRect.bottom}px`;
this.dropdown.element.style.left = `${containerRect.left}px`;
this.dropdown.element.style.width = `${containerRect.width}px`;
return this;
}
setVerticalDropdownPosition(above: boolean = false): this {
if (!above || !(this._dropdownParent instanceof HTMLElement)) {
return this;
}
const dropdownRect = this.dropdown.element.getBoundingClientRect();
this.dropdown.element.style.top = `${this.containerOuter.element.offsetTop + 1 - dropdownRect.height}px`;
return this;
}
getValue<B extends boolean = false>(valueOnly?: B): EventChoiceValueType<B> | EventChoiceValueType<B>[] {
const values = this._store.items.map((item) => {
return (valueOnly ? item.value : getChoiceForOutput(item)) as EventChoiceValueType<B>;
@ -1516,6 +1565,7 @@ class Choices {
_addEventListeners(): void {
const documentElement = this._docRoot;
const outerElement = this.containerOuter.element;
const dropdownElement = this.dropdown.element;
const inputElement = this.input.element;
const passedElement = this.passedElement.element;
@ -1529,7 +1579,7 @@ class Choices {
documentElement.addEventListener('touchmove', this._onTouchMove, {
passive: true,
});
this.dropdown.element.addEventListener('mouseover', this._onMouseOver, {
dropdownElement.addEventListener('mouseover', this._onMouseOver, {
passive: true,
});
@ -1572,12 +1622,22 @@ class Choices {
});
}
if (this._dropdownDetached) {
dropdownElement.addEventListener('keydown', this._onKeyDown, true);
dropdownElement.addEventListener('mousedown', this._onMouseDown, true);
window.addEventListener('resize', this._onWindowResize);
window.addEventListener('scroll', this._onScroll, {
passive: true,
});
}
this.input.addEventListeners();
}
_removeEventListeners(): void {
const documentElement = this._docRoot;
const outerElement = this.containerOuter.element;
const dropdownElement = this.dropdown.element;
const inputElement = this.input.element;
const passedElement = this.passedElement.element;
@ -1587,7 +1647,7 @@ class Choices {
documentElement.removeEventListener('click', this._onClick);
documentElement.removeEventListener('touchmove', this._onTouchMove);
this.dropdown.element.removeEventListener('mouseover', this._onMouseOver);
dropdownElement.removeEventListener('mouseover', this._onMouseOver);
if (this._isSelectOneElement) {
outerElement.removeEventListener('focus', this._onFocus);
@ -1608,6 +1668,13 @@ class Choices {
passedElement.removeEventListener('invalid', this._onInvalid);
}
if (this._dropdownDetached) {
dropdownElement.removeEventListener('keydown', this._onKeyDown);
dropdownElement.removeEventListener('mousedown', this._onMouseDown);
window.removeEventListener('resize', this._onWindowResize);
window.removeEventListener('scroll', this._onScroll);
}
this.input.removeEventListeners();
}
@ -2054,6 +2121,27 @@ class Choices {
this.containerOuter.addInvalidState();
}
_onWindowResize(): void {
this._moveDropdown();
}
_onScroll(): void {
this._moveDropdown();
}
_moveDropdown(): void {
if (!this.dropdown.isActive) {
return;
}
this.setHorizontalDropdownPosition();
const rect = this.dropdown.element.getBoundingClientRect();
const dropdownAbove = this.containerOuter.shouldFlip(rect.bottom, rect.height);
this.setVerticalDropdownPosition(dropdownAbove);
}
/**
* Removes any highlighted choice options
*/
@ -2271,7 +2359,7 @@ class Choices {
});
this.dropdown = new Dropdown({
element: templating.dropdown(config),
element: templating.dropdown(config, isSelectOneElement),
classNames,
type: elementType,
});
@ -2280,6 +2368,7 @@ class Choices {
_createStructure(): void {
const { containerInner, containerOuter, passedElement } = this;
const dropdownElement = this.dropdown.element;
let dropdownParent: HTMLElement = containerOuter.element;
// Hide original element
passedElement.conceal();
@ -2288,8 +2377,12 @@ class Choices {
// Wrapper inner container with outer container
containerOuter.wrap(containerInner.element);
if (this._dropdownDetached && this._dropdownParent instanceof HTMLElement) {
dropdownParent = this._dropdownParent;
}
containerOuter.element.appendChild(containerInner.element);
containerOuter.element.appendChild(dropdownElement);
dropdownParent.appendChild(dropdownElement);
containerInner.element.appendChild(this.itemList.element);
dropdownElement.appendChild(this.choiceList.element);

View file

@ -68,28 +68,38 @@ export default class Container {
this.element.removeAttribute('aria-activedescendant');
}
open(dropdownPos: number, dropdownHeight: number): void {
open(dropdownPos: number, dropdownHeight: number, dropdown: HTMLElement | null = null): boolean {
addClassesToElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'true');
this.isOpen = true;
if (this.shouldFlip(dropdownPos, dropdownHeight)) {
addClassesToElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
addClassesToElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = true;
}
return this.isFlipped;
}
close(): void {
close(dropdown: HTMLElement | null = null): void {
removeClassesFromElement(this.element, this.classNames.openState);
this.element.setAttribute('aria-expanded', 'false');
this.removeActiveDescendant();
this.isOpen = false;
// A dropdown flips if it does not have space within the page
if (this.isFlipped) {
removeClassesFromElement(this.element, this.classNames.flippedState);
this.isFlipped = false;
removeClassesFromElement(this.element, this.classNames.flippedState);
if (dropdown !== null) {
removeClassesFromElement(dropdown, this.classNames.flippedState);
}
this.isFlipped = false;
}
addFocusState(): void {

View file

@ -12,6 +12,8 @@ export const DEFAULT_CLASSNAMES: ClassNames = {
listItems: ['choices__list--multiple'],
listSingle: ['choices__list--single'],
listDropdown: ['choices__list--dropdown'],
dropdownMultiple: ['choices__dropdown--multiple'],
dropdownSingle: ['choices__dropdown--single'],
item: ['choices__item'],
itemSelectable: ['choices__item--selectable'],
itemDisabled: ['choices__item--disabled'],
@ -95,4 +97,5 @@ export const DEFAULT_CONFIG: Options = {
callbackOnCreateTemplates: null,
classNames: DEFAULT_CLASSNAMES,
appendGroupInSearch: false,
dropdownParent: null,
} as const;

View file

@ -16,6 +16,10 @@ export interface ClassNames {
listSingle: string | Array<string>;
/** @default ['choices__list--dropdown'] */
listDropdown: string | Array<string>;
/** @default ['choices__dropdown--multiple'] */
dropdownMultiple: string | Array<string>;
/** @default ['choices__dropdown--single'] */
dropdownSingle: string | Array<string>;
/** @default ['choices__item'] */
item: string | Array<string>;
/** @default ['choices__item--selectable'] */

View file

@ -634,4 +634,13 @@ export interface Options {
callbackOnCreateTemplates: CallbackOnCreateTemplatesFn | null;
appendGroupInSearch: boolean;
/**
* CSS selector for the element to append the dropdown to. Similar to select2's appendTo option
*
* **Input types affected:** `select-one`, `select-multiple`
*
* @default null
*/
dropdownParent: string | null;
}

View file

@ -58,7 +58,7 @@ export interface Templates {
input(options: TemplateOptions, placeholderValue: string | null): HTMLInputElement;
dropdown(options: TemplateOptions): HTMLDivElement;
dropdown(options: TemplateOptions, isSelectOneElement: boolean): HTMLDivElement;
notice(options: TemplateOptions, innerText: string, type: NoticeType): HTMLDivElement;

View file

@ -349,12 +349,15 @@ const templates: TemplatesInterface = {
return inp;
},
dropdown({ classNames: { list, listDropdown } }: TemplateOptions): HTMLDivElement {
dropdown(
{ classNames: { list, listDropdown, dropdownSingle, dropdownMultiple } }: TemplateOptions,
isSelectOneElement: boolean,
): HTMLDivElement {
const div = document.createElement('div');
addClassesToElement(div, list);
addClassesToElement(div, listDropdown);
addClassesToElement(div, isSelectOneElement ? dropdownSingle : dropdownMultiple);
div.setAttribute('aria-expanded', 'false');
return div;

View file

@ -59,7 +59,6 @@ body {
position: relative;
margin: 0;
width: 100%;
height: 100%;
}
body {
@ -181,6 +180,12 @@ label + p {
}
}
/** Set the section color on the dropdown list to not inherit the white color */
// stylelint-disable-next-line selector-class-pattern
body > .choices__list {
color: var(--section-color, #333);
}
.logo {
display: block;
margin-bottom: $global-guttering * 0.5;

View file

@ -65,6 +65,14 @@ $choices-placeholder-opacity: 0.5 !default;
overflow: visible;
}
// Only apply the normal positioning for dropdowns that are not detached from the choices-selector
&.is-flipped {
.#{$choices-selector}__list {
top: auto;
bottom: 100%;
}
}
&.is-disabled {
:is(.#{$choices-selector}__inner, .#{$choices-selector}__input) {
background-color: var(--choices-bg-color-disabled, #{$choices-bg-color-disabled});
@ -90,14 +98,6 @@ $choices-placeholder-opacity: 0.5 !default;
.#{$choices-selector}__inner {
padding-bottom: var(--choices-inner-one-padding, #{$choices-inner-one-padding});
}
.#{$choices-selector}__input {
display: block;
width: var(--choices-width, #{$choices-width});
padding: var(--choices-dropdown-item-padding, #{$choices-dropdown-item-padding});
border-bottom: var(--choices-base-border, #{$choices-base-border}) var(--choices-keyline-color, #{$choices-keyline-color});
background-color: var(--choices-bg-color-dropdown, #{$choices-bg-color-dropdown});
margin: 0;
}
.#{$choices-selector}__button {
background-image: var(--choices-icon-cross-inverse, #{$choices-icon-cross-inverse});
padding: 0;
@ -157,6 +157,17 @@ $choices-placeholder-opacity: 0.5 !default;
}
}
.#{$choices-selector}__dropdown--single {
.#{$choices-selector}__input {
display: block;
width: var(--choices-width, #{$choices-width});
padding: var(--choices-dropdown-item-padding, #{$choices-dropdown-item-padding});
border-bottom: var(--choices-base-border, #{$choices-base-border}) var(--choices-keyline-color, #{$choices-keyline-color});
background-color: var(--choices-bg-color-dropdown, #{$choices-bg-color-dropdown});
margin: 0;
}
}
.#{$choices-selector}:is([data-type*='select-multiple'], [data-type*='text']) {
.#{$choices-selector}__inner {
cursor: text;
@ -294,12 +305,10 @@ $choices-placeholder-opacity: 0.5 !default;
border-color: color-mix(in srgb, var(--choices-keyline-color, #{$choices-keyline-color}) 85%, var(--choices-darken, black));
}
.is-flipped & {
top: auto;
bottom: 100%;
&.is-flipped {
margin-top: 0;
margin-bottom: -1px;
border-radius: 0.25rem 0.25rem 0 0;
border-radius: var(--choices-border-radius, #{$choices-border-radius}) var(--choices-border-radius, #{$choices-border-radius}) 0 0;
}
.#{$choices-selector}__list {
position: relative;

View file

@ -81,7 +81,7 @@ describe('components/container', () => {
describe('open', () => {
beforeEach(() => {
instance.open();
instance.open(element);
});
it('adds open state class', () => {
@ -102,7 +102,7 @@ describe('components/container', () => {
shouldFlipStub = stub().returns(true);
instance.shouldFlip = shouldFlipStub;
instance.open();
instance.open(element);
});
afterEach(() => {
@ -121,7 +121,7 @@ describe('components/container', () => {
describe('close', () => {
beforeEach(() => {
instance.close();
instance.close(element);
});
it('adds open state class', () => {
@ -139,7 +139,7 @@ describe('components/container', () => {
describe('flipped dropdown', () => {
beforeEach(() => {
instance.isFlipped = true;
instance.close();
instance.close(element);
});
it('removes adds flipped state class', () => {