mirror of
https://github.com/Choices-js/Choices.git
synced 2024-05-05 07:13:11 +02:00
Ability to only render a portion of choices
This commit is contained in:
parent
04aca852c3
commit
ca3bda1f70
|
@ -35,7 +35,7 @@ export const addChoice = (value, label, id, groupId, disabled, elementId, custom
|
|||
id,
|
||||
groupId,
|
||||
disabled,
|
||||
elementId: elementId,
|
||||
elementId,
|
||||
customProperties,
|
||||
keyCode
|
||||
};
|
||||
|
|
|
@ -53,6 +53,7 @@ class Choices {
|
|||
silent: false,
|
||||
items: [],
|
||||
choices: [],
|
||||
renderChoiceLimit: -1,
|
||||
maxItemCount: -1,
|
||||
addItems: true,
|
||||
removeItems: true,
|
||||
|
@ -338,7 +339,7 @@ class Choices {
|
|||
if (groupChoices.length >= 1) {
|
||||
const dropdownGroup = this._getTemplate('choiceGroup', group);
|
||||
groupFragment.appendChild(dropdownGroup);
|
||||
this.renderChoices(groupChoices, groupFragment);
|
||||
this.renderChoices(groupChoices, groupFragment, true);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -352,37 +353,45 @@ class Choices {
|
|||
* @return {DocumentFragment} Populated choices fragment
|
||||
* @private
|
||||
*/
|
||||
renderChoices(choices, fragment) {
|
||||
renderChoices(choices, fragment, withinGroup = false) {
|
||||
// Create a fragment to store our list items (so we don't have to update the DOM for each item)
|
||||
const choicesFragment = fragment || document.createDocumentFragment();
|
||||
const { renderSelectedChoices, searchResultLimit, renderChoiceLimit } = this.config;
|
||||
const filter = this.isSearching ? sortByScore : this.config.sortFilter;
|
||||
const { renderSelectedChoices } = this.config;
|
||||
const appendChoice = (choice) => {
|
||||
const shouldRender = renderSelectedChoices === 'auto'
|
||||
? this.isSelectOneElement || !choice.selected
|
||||
: true;
|
||||
const shouldRender = renderSelectedChoices === 'auto' ?
|
||||
(this.isSelectOneElement || !choice.selected) :
|
||||
true;
|
||||
if (shouldRender) {
|
||||
const dropdownItem = this._getTemplate('choice', choice);
|
||||
choicesFragment.appendChild(dropdownItem);
|
||||
}
|
||||
};
|
||||
|
||||
// If sorting is enabled or the user is searching, filter choices
|
||||
if (this.config.shouldSort || this.isSearching) {
|
||||
choices.sort(filter);
|
||||
let rendererableChoices = choices;
|
||||
|
||||
if (renderSelectedChoices === 'auto' && !this.isSelectOneElement) {
|
||||
rendererableChoices = choices.filter(choice => !choice.selected);
|
||||
}
|
||||
|
||||
if (this.isSearching) {
|
||||
for (let i = 0; i < this.config.searchResultLimit; i++) {
|
||||
const choice = choices[i];
|
||||
if (choice) {
|
||||
appendChoice(choice);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
choices.forEach(choice => appendChoice(choice));
|
||||
// If sorting is enabled or the user is searching, filter choices
|
||||
if (this.config.shouldSort || this.isSearching) {
|
||||
rendererableChoices.sort(filter);
|
||||
}
|
||||
|
||||
let choiceLimit = rendererableChoices.length;
|
||||
|
||||
if (this.isSearching) {
|
||||
choiceLimit = Math.min(searchResultLimit, rendererableChoices.length - 1);
|
||||
} else if (renderChoiceLimit > 0 && !withinGroup) {
|
||||
choiceLimit = Math.min(renderChoiceLimit, rendererableChoices.length - 1);
|
||||
}
|
||||
|
||||
// Add each choice to dropdown within range
|
||||
for (let i = 0; i < choiceLimit; i++) {
|
||||
appendChoice(rendererableChoices[i]);
|
||||
};
|
||||
|
||||
return choicesFragment;
|
||||
}
|
||||
|
||||
|
@ -447,8 +456,11 @@ class Choices {
|
|||
// Only render if our state has actually changed
|
||||
if (this.currentState !== this.prevState) {
|
||||
// Choices
|
||||
if (this.currentState.choices !== this.prevState.choices ||
|
||||
this.currentState.groups !== this.prevState.groups) {
|
||||
if (
|
||||
this.currentState.choices !== this.prevState.choices ||
|
||||
this.currentState.groups !== this.prevState.groups ||
|
||||
this.currentState.items !== this.prevState.items
|
||||
) {
|
||||
if (this.isSelectElement) {
|
||||
// Get active groups/choices
|
||||
const activeGroups = this.store.getGroupsFilteredByActive();
|
||||
|
|
|
@ -48,6 +48,7 @@ describe('Choices', () => {
|
|||
expect(this.choices.config.silent).toEqual(jasmine.any(Boolean));
|
||||
expect(this.choices.config.items).toEqual(jasmine.any(Array));
|
||||
expect(this.choices.config.choices).toEqual(jasmine.any(Array));
|
||||
expect(this.choices.config.renderChoiceLimit).toEqual(jasmine.any(Number));
|
||||
expect(this.choices.config.maxItemCount).toEqual(jasmine.any(Number));
|
||||
expect(this.choices.config.addItems).toEqual(jasmine.any(Boolean));
|
||||
expect(this.choices.config.removeItems).toEqual(jasmine.any(Boolean));
|
||||
|
@ -293,7 +294,9 @@ describe('Choices', () => {
|
|||
});
|
||||
|
||||
it('should highlight the choices on keydown', function() {
|
||||
this.choices = new Choices(this.input);
|
||||
this.choices = new Choices(this.input, {
|
||||
renderChoiceLimit: -1
|
||||
});
|
||||
this.choices.input.focus();
|
||||
|
||||
for (let i = 0; i < 2; i++) {
|
||||
|
@ -930,7 +933,7 @@ describe('Choices', () => {
|
|||
|
||||
it('should flip the dropdown', function() {
|
||||
this.choices = new Choices(this.input, {
|
||||
position: 'top'
|
||||
position: 'top',
|
||||
});
|
||||
|
||||
const container = this.choices.containerOuter;
|
||||
|
@ -950,7 +953,8 @@ describe('Choices', () => {
|
|||
|
||||
it('should render selected choices', function() {
|
||||
this.choices = new Choices(this.input, {
|
||||
renderSelectedChoices: 'always'
|
||||
renderSelectedChoices: 'always',
|
||||
renderChoiceLimit: -1
|
||||
});
|
||||
const renderedChoices = this.choices.choiceList.querySelectorAll('.choices__item');
|
||||
expect(renderedChoices.length).toEqual(3);
|
||||
|
@ -958,11 +962,49 @@ describe('Choices', () => {
|
|||
|
||||
it('shouldn\'t render selected choices', function() {
|
||||
this.choices = new Choices(this.input, {
|
||||
renderSelectedChoices: 'auto'
|
||||
renderSelectedChoices: 'auto',
|
||||
renderChoiceLimit: -1
|
||||
});
|
||||
const renderedChoices = this.choices.choiceList.querySelectorAll('.choices__item');
|
||||
expect(renderedChoices.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('shouldn\'t render choices up to a render limit', function() {
|
||||
// Remove existing choices (to make test simpler)
|
||||
while (this.input.firstChild) {
|
||||
this.input.removeChild(this.input.firstChild);
|
||||
}
|
||||
|
||||
this.choices = new Choices(this.input, {
|
||||
choices: [
|
||||
{
|
||||
value: 'Option 1',
|
||||
selected: false,
|
||||
},
|
||||
{
|
||||
value: 'Option 2',
|
||||
selected: false,
|
||||
},
|
||||
{
|
||||
value: 'Option 3',
|
||||
selected: false,
|
||||
},
|
||||
{
|
||||
value: 'Option 4',
|
||||
selected: false,
|
||||
},
|
||||
{
|
||||
value: 'Option 5',
|
||||
selected: false,
|
||||
},
|
||||
],
|
||||
renderSelectedChoices: 'auto',
|
||||
renderChoiceLimit: 4
|
||||
});
|
||||
|
||||
const renderedChoices = this.choices.choiceList.querySelectorAll('.choices__item');
|
||||
expect(renderedChoices.length).toEqual(4);
|
||||
});
|
||||
});
|
||||
|
||||
describe('should allow custom properties provided by the user on items or choices', function() {
|
||||
|
|
Loading…
Reference in a new issue