Skip to content

Commit

Permalink
IBX-1674: Empty select option for dropdown (#109)
Browse files Browse the repository at this point in the history
  • Loading branch information
GrabowskiM authored Dec 16, 2021
1 parent 0a54e3f commit 48d9117
Show file tree
Hide file tree
Showing 12 changed files with 149 additions and 145 deletions.
64 changes: 9 additions & 55 deletions src/bundle/Resources/public/js/scripts/core/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,11 @@
this.itemsListContainer = this.itemsContainer.querySelector('.ibexa-dropdown__items-list');
this.itemsFilterInput = this.itemsContainer.querySelector('.ibexa-dropdown__items-filter');

this.noItems = this.container.classList.contains('ibexa-dropdown--no-items');
this.canSelectOnlyOne = !this.sourceInput?.multiple;
this.hasDefaultSelection = config.hasDefaultSelection ?? this.canSelectOnlyOne;
this.selectedItemTemplate = this.selectedItemsContainer.dataset.template;

this.createSelectedItem = this.createSelectedItem.bind(this);
this.selectFirstItem = this.selectFirstItem.bind(this);
this.hideOptions = this.hideOptions.bind(this);
this.fitItems = this.fitItems.bind(this);
this.clearCurrentSelection = this.clearCurrentSelection.bind(this);
Expand All @@ -58,48 +57,18 @@
this.itemsPopoverContent = this.itemsPopoverContent.bind(this);
}

getSelectedItems() {
return this.selectedItemsContainer.querySelectorAll(
'.ibexa-dropdown__selected-item:not(.ibexa-dropdown__selected-item--predefined)'
);
}

createSelectedItem(value, label) {
return this.selectedItemTemplate.replace('{{ value }}', value).replace('{{ label }}', label);
}

selectFirstItem() {
const items = this.itemsListContainer.querySelectorAll('.ibexa-dropdown__item:not(.ibexa-dropdown__item--preferred-choice)');
const [firstItem] = items;

if (!firstItem) {
return;
}

const label = firstItem.querySelector('.ibexa-dropdown__item-label').innerHTML;

items.forEach((item) => item.classList.remove('ibexa-dropdown__item--selected'));
firstItem.classList.add('ibexa-dropdown__item--selected');

if (!this.canSelectOnlyOne) {
firstItem.querySelector('.ibexa-input').checked = true;
}

this.selectedItemsContainer
.querySelector('.ibexa-dropdown__selected-placeholder')
.insertAdjacentHTML('beforebegin', this.createSelectedItem(firstItem.dataset.value, label));
}

clearCurrentSelection() {
const placeholder = this.selectedItemsContainer.querySelector('.ibexa-dropdown__selected-placeholder').cloneNode();
const overflowNumber = this.selectedItemsContainer.querySelector('.ibexa-dropdown__selected-overflow-number').cloneNode();

this.sourceInput.querySelectorAll('option').forEach((option) => (option.selected = false));
this.itemsListContainer
.querySelectorAll('.ibexa-dropdown__item--selected')
.forEach((option) => option.classList.remove('ibexa-dropdown__item--selected'));
this.selectedItemsContainer.innerHTML = '';
this.selectedItemsContainer.append(placeholder);
this.selectedItemsContainer.append(overflowNumber);
}

Expand Down Expand Up @@ -139,7 +108,7 @@
const label = element.querySelector('.ibexa-dropdown__item-label').innerHTML;

selectedItemsList
.querySelector('.ibexa-dropdown__selected-placeholder')
.querySelector('.ibexa-dropdown__selected-item--predefined')
.insertAdjacentHTML('beforebegin', this.createSelectedItem(value, label));
} else {
const valueNode = selectedItemsList.querySelector(`[data-value="${value}"]`);
Expand All @@ -149,14 +118,6 @@
}
}

if (
!selected &&
this.hasDefaultSelection &&
(this.canSelectOnlyOne || !selectedItemsList.querySelectorAll('.ibexa-dropdown__selected-item').length)
) {
this.selectFirstItem();
}

this.fitItems();
this.fireValueChangedEvent();
}
Expand Down Expand Up @@ -202,7 +163,6 @@
const value = option.dataset.value;
const optionSelect = this.sourceInput.querySelector(`[value="${value}"]`);
const itemSelected = this.itemsListContainer.querySelector(`[data-value="${value}"]`);
const selectedItems = this.getSelectedItems();

itemSelected.classList.remove('ibexa-dropdown__item--selected');

Expand All @@ -216,12 +176,6 @@

option.remove();

if (!selectedItems.length && this.hasDefaultSelection) {
this.hideOptions();
this.clearCurrentSelection();
this.selectFirstItem();
}

this.fitItems();
this.fireValueChangedEvent();
}
Expand Down Expand Up @@ -317,11 +271,8 @@

this.container.dataset.initialized = true;

const selectedItems = this.getSelectedItems();
const isEmpty = !selectedItems.length;

if (isEmpty && this.hasDefaultSelection) {
this.selectFirstItem();
if (this.noItems) {
return;
}

this.itemsPopover = new DropdownPopover(
Expand All @@ -346,8 +297,11 @@
this.itemsListContainer
.querySelectorAll('.ibexa-dropdown__item:not([disabled])')
.forEach((option) => option.addEventListener('click', this.onOptionClick, false));
this.itemsFilterInput.addEventListener('keyup', this.filterItems, false);
this.itemsFilterInput.addEventListener('input', this.filterItems, false);

if (this.itemsFilterInput) {
this.itemsFilterInput.addEventListener('keyup', this.filterItems, false);
this.itemsFilterInput.addEventListener('input', this.filterItems, false);
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/bundle/Resources/public/scss/_dropdown.scss
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@
right: calculateRem(16px);
}
}

&--search-hidden {
.ibexa-input-text-wrapper {
display: none;
}
}
}

& &__items {
Expand Down
5 changes: 5 additions & 0 deletions src/bundle/Resources/translations/forms.en.xliff
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,11 @@
<target state="new">Select Content item</target>
<note>key: swap_location_form.swap</note>
</trans-unit>
<trans-unit id="f41c864f5e47e9829cac16492d544b9c7bce9f01" resname="translation.base_language.choose">
<source>Choose a Language</source>
<target state="new">Choose a Language</target>
<note>key: translation.base_language.choose</note>
</trans-unit>
<trans-unit id="30b0c3c3e5e096a078005be2cc34bca6227ae381" resname="trash_empty_form.empty">
<source>Delete permanently</source>
<target state="new">Delete permanently</target>
Expand Down
5 changes: 5 additions & 0 deletions src/bundle/Resources/translations/messages.en.xliff
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,11 @@
<target state="new">Choose an option</target>
<note>key: dropdown.placeholder</note>
</trans-unit>
<trans-unit id="49f6d75aca8da375a2a79c0778934bc45a8ffe8c" resname="dropdown.placeholder.empty">
<source>No options available</source>
<target state="new">No options available</target>
<note>key: dropdown.placeholder.empty</note>
</trans-unit>
<trans-unit id="272e650f8667b4f4fcb7032b85b98ef4a9974f0f" resname="dropdown.search">
<source>Search...</source>
<target state="new">Search...</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
</select>
{% endset %}

{% include '@ibexadesign/ui/component/dropdown.html.twig' with {
{% include '@ibexadesign/ui/component/dropdown/dropdown.html.twig' with {
source: source,
choices: choices,
value: value,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@

{% set choices_flat = choices
| map(choice => choice.choices is defined ? choice.choices : [choice])
| reduce((carry, choices) => carry|merge(choices), [])
%}
{% set preferred_choices = preferred_choices|default([]) %}
{% set min_search_items = min_search_items|default(5) %}
{% set custom_form = custom_form is defined ? custom_form : true %}
{% set translation_domain = translation_domain|default(false) %}
{% set value = value is defined ? value : null %}
{% set multiple = multiple|default(false) %}
{% set no_items = choices_flat|length == 0 %}

{% macro get_translated_label(label, translation_domain) %}
{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}
{% endmacro %}

<div
class="ibexa-dropdown
{{ multiple ? "ibexa-dropdown--multi" : "ibexa-dropdown--single" }}
{{ custom_init|default(false) ? "ibexa-dropdown--custom-init" }}
{{ no_items ? "ibexa-dropdown--no-items" }}
{{ class|default('') }}
"
>
<div class="ibexa-dropdown__source">
{{ source|default(null)|raw }}
</div>
<div class="ibexa-dropdown__wrapper">
<ul
class="ibexa-dropdown__selection-info"
data-template="{{ include('@ibexadesign/ui/component/dropdown/dropdown_selected_item.html.twig', {
value: '{{ value }}',
label: '{{ label }}',
})|e('html_attr') }}"
>
{% if no_items %}
<li class="ibexa-dropdown__selected-item ibexa-dropdown__selected-item--predefined ibexa-dropdown__selected-placeholder">
{{ 'dropdown.placeholder.empty'|trans|desc("No options available") }}
</li>
{% else %}
{% for choice in choices_flat %}
{% if custom_form ? choice.value == value : choice is selectedchoice(value) %}
{% include '@ibexadesign/ui/component/dropdown/dropdown_selected_item.html.twig' with {
value: choice.value,
label: _self.get_translated_label(choice.label, translation_domain),
} %}
{% endif %}
{% endfor %}

{% if value is empty %}
{% if multiple %}
<li class="ibexa-dropdown__selected-item ibexa-dropdown__selected-item--predefined ibexa-dropdown__selected-placeholder">
{% if placeholder is defined %}
{{ _self.get_translated_label(placeholder, translation_domain )}}
{% else %}
{{ 'dropdown.placeholder'|trans|desc("Choose an option") }}
{% endif %}
</li>
{% else %}
{% if placeholder is not none %}
{% include '@ibexadesign/ui/component/dropdown/dropdown_selected_item.html.twig' with {
value: '',
label: _self.get_translated_label(placeholder, translation_domain),
} %}
{% else %}
{% set first_choice = choices_flat|first %}

{% include '@ibexadesign/ui/component/dropdown/dropdown_selected_item.html.twig' with {
value: first_choice.value,
label: _self.get_translated_label(first_choice.label),
} %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}

<li class="ibexa-dropdown__selected-item ibexa-dropdown__selected-item--predefined ibexa-dropdown__selected-overflow-number" hidden></li>
</ul>
<div class="ibexa-dropdown__items {{ choices_flat|length < min_search_items ? 'ibexa-dropdown__items--search-hidden' }}">
{%- embed '@ibexadesign/ui/component/input_text.html.twig' with { has_search: true } -%}
{% block content %}
<input
type="text"
placeholder="{{ 'dropdown.search'|trans|desc('Search...') }}"
class="ibexa-dropdown__items-filter ibexa-input ibexa-input--text ibexa-input--small form-control"
/>
{% endblock %}
{%- endembed -%}
<ul
class="ibexa-dropdown__items-list"
data-template="{{ include('@ibexadesign/ui/component/dropdown/dropdown_item.html.twig', {
custom_form: true,
choice: {
value: '{{ value }}',
label: '{{ label }}',
},
})|e('html_attr') }}"
>
{% if not multiple and placeholder is defined %}
{% set placeholder_choice = {
value: '',
label: _self.get_translated_label(placeholder, translation_domain),
} %}
{% include '@ibexadesign/ui/component/dropdown/dropdown_item.html.twig' with { choice: placeholder_choice, custom_form: true } %}
{% endif %}
{% for choice in preferred_choices %}
{% include '@ibexadesign/ui/component/dropdown/dropdown_item.html.twig' with { choice, preferred_choice: true, custom_form } %}
{% endfor %}
{% if preferred_choices|length > 0 %}
<hr class="ibexa-dropdown__separator" />
{% endif %}
{% for choice in choices %}
{% include '@ibexadesign/ui/component/dropdown/dropdown_item.html.twig' with { choice, custom_form } %}
{% endfor %}
</ul>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<label class="ibexa-dropdown__item-group-label">{{ item_label }}</label>
<ul class="ibexa-dropdown__item-group-list">
{% for child in choice.choices %}
{% include '@ibexadesign/ui/component/dropdown_item.html.twig' with { choice: child, preferred_choice, custom_form } %}
{% include '@ibexadesign/ui/component/dropdown/dropdown_item.html.twig' with { choice: child, preferred_choice, custom_form } %}
{% endfor %}
</ul>
</li>
Expand Down
Loading

0 comments on commit 48d9117

Please sign in to comment.