Examples
Here is a list of examples you will find below,
- Hybrid dropdown with multiple nested groups
- Hybrid dropdown with treeview selection
- Hybrid Dropdown with multiple limited selections
- Visual styling change to reflect field update
- Filtering list of options to display
- Pre-filled/pre-selected hybrid dropdown
- Customise the selected text label and default option
- Using keyboard navigation between form fields
- Dropdown list with with custom labels with images
- Image grid field, no dropdown
Hybrid dropdown with multiple nested groups.
Unlike <select/>
dropdown fields, Hybrid Dropdowns can be constructed with multiple nested groups, this is especially useful to display hierarchical list such as WordPress taxonomies with multiple branches, however this is only possible using the JSON dataset construct,
<div id="json-field">
<script type="application/json">
{
"":"Select a dish",
"Japan":{
"sushi":{
"label":"Sushi",
"ps":"Pumpkin sushi",
"as":"Avocado sushi",
"tc":"Tomato sushi",
"cs":"Carrot sushi",
}
},
"India":{
"dosa":{
"label":"Dosa",
"pd":"Plain dosa",
"md":"Masala dosa",
"myd":"Mysore dosa",
"pr":"Paper roast",
}
}
}
</script>
</div>
Note the inclusion of the keyword "label"
in the JSON 2nd level branch, which results in,
and enables selection of the parent option. Excluding the "label"
keyword would simply group the child branch with the parent as title.
Hybrid dropdown with treeview selection
Using the same example as above, but adding a "label"
keywords for the top most parent, we enable the treeView option
<div id="json-field" data-tree-view="true">
<script type="application/json">
{
"":"Select a dish",
"japan":{
"label":"Japan",
"sushi":{
"label":"Sushi",
"ps":"Pumpkin sushi",
...
}
}
}
</script>
</div>
which results in,
Note
new HybridDropdown(el,{treeView:true})
enables selection of whole branches when the parent option is selected.- treeView also indicates a parent is partially selected when not all options in the branch are selected.
- partially selected parent options are not submitted.
- treeView automatically activates multiple selection, and if limitSelection is not set then it is automatically set to
-1
, unlimited. - treeView options’ values are constructed by concatenating them with their parent value, this allows submitted treeView fields to preserve their branch selection, so in the above example, the first branch option ‘Pumkin Suchi’ which has a value of ‘ps’ will be submitted as
japan/sushi/ps
to reflect that it is a child of ‘Sushi’ which itself is a child of ‘Japan’.
Hybrid Dropdown with multiple limited selections
The Hybrid dropdown can be enabled to allow multiple number of option selection but limited to the limitSelection
option value,
<div id="json-field" data-limit-selection="3">
<script type="application/json">
{
"":"Select a dish",
"Japan":{
"sushi":{
"label":"Sushi",
...
}
}
}
</script>
</div>
which results in,
Visual styling change to reflect field update.
You can use the negative
option setting along with the refresh()
method to flip the colour style of the dropdown field when the change
event is fired.
<select id="flip-style">
<option value="">Select a dish</option>
<option value="ps">Pumpkin sushi</option>
<option value="as">Avocado sushi</option>
<option value="ts">Tomato sushi</option>
<option value="cs">Carrot sushi</option>
</select>
<script type="text/javascript">
(function(){
let sel, hyd;
document.addEventListener('DOMContentLoaded', (e) => { //instantiate on document ready.
sel= document.querySelector('#flip-style');
new HybridDropdown(sel,
{
'negative':false
});
sel.addEventListener('change', (ce) => {
let hdd = ce.target._hybriddd; //hybrid object is stored on the element on which it was instantiated
if(!hdd) return; //no hybrid here.
if(Object.keys(hdd.value).length>0 && !hdd.value['']){ //hybrid value is always an object of value=>label.
if(!hdd.opt.negative){ //if previously negative, let's refresh.
hdd.refresh({'negative':true});
}
}else if(hdd.opt.negative) hdd.refresh({'negative':false}); //flip back.
})
})
})
</script>
which results in a hybrid dropdown which inverts its style if a value is selected,
Filtering list of options to display.
One of the powerful features this plugin offers, is the ability to filter the visible list of options. This allows dynamic dropdown lists based on the other fields’ values. Here is an example, select the radio field below to change the dropdown list,
the for the list, you can either convert a <select/>
field or use a JSON dataset,
<div id="radio-filter">
<label> <input type="radio" checked="true" name="radio-filter" value="vegetarian"/> Vegetarian </label>
<label><input type="radio" name="radio-filter" value="non-vegetarian" /> Non-vegetarian </label>
</div>
<select id="filter-list">
<option class="vegetarian" value="">Select a vegetarian dish</option>
<option class="vegetarian" value="ps">Pumpkin sushi</option>
...
<option class="non-vegetarian" value="">Select a non-vegetarian dish</option>
<option class="non-vegetarian" value="ss">Salmon sushi</option>
...
</select>
Note
- the use of 2 options with identical values (the default options)
- the addition of classes in the option list that reflect the values of the radio fields.
the script used to enable this,
let fe = document.querySelector('#filter-list'), //select field.
re = document.querySelector('#radio-filter'); //radio fields container
let hdd =new HybridDropdown(fe,
{
'listOption':function(o,i){
if(o.classList.contains('vegetarian')) return true;
return false;
}
}
);
re.addEventListener('change', (ce) => { //listen for bubbling change events
hdd.refresh(
{
'listOption':function(o,i){ //filter the options based on the new value selected.
if(o.classList.contains(ce.target.value)) return true;
return false;
}
})
})
Pre-filled/pre-selected hybrid dropdown
You can use the selectedValues
option to pre-fill/pre-select values in a dropdown field,
<div id="pre-fill">
<script type="application/json">
{
"":"Select any dish",
"Japan":{
"sushi":{
"ps":"Pumpkin sushi",
...
}
}
}
</script>
</div>
and use the following construction,
let fe = document.querySelector('#pre-fill');
new HybridDropdown(fe,
{
'multiple': true,
'selectedValues':'["ps","as","pd"]',
'fieldName':'dishes[]'
}
);
resulting in,
Customise the selected text label and default option
In the above example, you will note that the mulitple selection in the list results in a selected text being truncated in order to limit the size of the field. This can be customised using the selectedLabel
option setting, while the default option can be set using the placeholder
option setting,
<div id="defaults" style="max-width:200px">
<script type="application/json">
{
"Japan":{
"sushi":{
"ps":"Pumpkin sushi",
...
}
}
}
</script>
</div>
let’s maintain the maximum width at 200px, and use the following construction,
let de = document.querySelector('#defaults');
new HybridDropdown(de,
{
'limitSelection': -1, //no limits
'fieldName':'dishes-img',
'placeholder': '---dishes---',
'selectedLabel':function(v){ //is a value=>label object.
let k = Object.keys(v),
s='';
k.forEach(i=>{
s+=`<span>${v[i]}</span>`;
});
return s;
}
}
);
resulting in, select multiple choices to see the result.
Using keyboard navigation between form fields
<form/>
fields can use tabindex
attributes to determine the order in which the fields are tab
‘ed into when using the keyboard to navigate.
<input tabindex=1 type="text"/>
The hybrid dropdown can be navigated to and interacted with using the keyboard keys.
Use,
tab
to move from one field to anotherup/down arrow
keys allow you to choose options in the hybrid list without opening the list.enter/space
to open the hybrid dropdownup/down arrow
to scroll the list.enter
to select an option.
Dropdown list with with custom labels with images.
The plugin is built to provide flexible customisation of the dropdown list. Constructing the list from a JSON dataset allows you to add additional attributes or HTML constructs to your dropdown list. Using the following JSON dataset to add images to my dropdown list,
<div id="with-images" data-limit-selection="1" >
<script type="application/json">
{
"Sushi":{
"ps":["Pumpkin sushi", "/images/ps.jpg"],
"as":["Avocado sushi", "/images/as.jpg"],
"tc":["Tomato sushi", "/images/tc.jpg"],
"cs":["Carrot sushi", "/images/cs.jpg"]
}
}
</script>
</div>
and make use of the optionLabel
option setting to customise the option label HTML construct,
let wi = document.querySelector('#with-images');
new HybridDropdown(wi,
{
'fieldName':'dishes-img',
'placeholder': '---Sushis---',
'checkboxes': false,
'dropdown':'landscape',
'optionLabel':function(lbl){ //is a value=>label object.
return `<div><img src="${lbl[1]}" alt="${lbl[0]}" /><p>${lbl[0]}</p></div>`;
}
}
);
NOTE:
- switch off the checkboxes, as the images will act as checkboxes.
- the ‘landscape’ mode which forces the list in a horizontal (inline) display.
You'll need some custom CSS Styling
#with-images .hybridddl img {
width: auto;
height: auto;
}
#with-images .hybridddl img + p,
#with-images .hybriddd-selected img + p{
position: absolute;
top: 0;
width: 140px;
height: ;
text-align: center;
background: #2e2e2ead;
margin: 57px 5px;
padding: 12px 0;
line-height: 1;
border: solid 1px white;
border-radius: 4px;
display: none;
color: #fff;
}
#with-images .hybriddd-option:hover > label img+p,
#with-images .hybriddd-selected img + p{ display:block}
#with-images .hybriddd-group > ul {
display: inline-block;
margin-left: 31px;
}
#with-images .hybriddd-group{line-height: 1;}
#with-images .hybriddd-group > span {
transform: rotate(-90deg);
position: absolute;
top: 61px;
left: -56px;
border: solid 1px;
height: auto;
padding: 5px 47px;
}
resulting in,
Image grid, no dropdown.
the plugin can be initialised with the dropdown
option set to none
. In this mode the field has no dropdown and the fields are visible on the onset. In addition, setting the gridColumns
option to specific the number of columns will force the option list to be displayed as a grid.
<div id="grid-layout" data-dropdown="none" data-grid-columns="4">
<script type="application/json">
{...}
</script>
</div>
let ig = document.querySelector('#grid-layout');
new HybridDropdown(ig,{
fieldName:'painting',
optionLabel: function(lbl){
return `<img src="${lbl[4]}" alt="${lbl[0]}-${lbl[1]}" /><p><span class="painter">${lbl[0]}</span> - ${lbl[1]} </p>`;
}
})
You'll need some custom CSS Styling
#grid-layout .hybriddd-wrapper.hybriddd-grid {
--hybriddd-gap: 2px;
width: calc( calc(var(--hybriddd-item) + var(--hybriddd-gap)) * var(--hybriddd-col));
}
#grid-layout.hybriddd-none .hybriddd-option > label > input {
position: absolute;
}
#grid-layout .hybriddd-option p {
position: absolute;
width: 150px;
padding: 2px 5px;
bottom: 0;
line-height: normal;
background: #0000008c;
color: white;
text-align: center;
margin: auto;
font-size: 13px;
}
#grid-layout .hybriddd-option p span {
font-size: 15px;
font-weight: bold;
}
#grid-layout input:checked + .hybridddcb {
width: 20px;
height: 20px;
vertical-align: middle;
visibility: visible;
border-radius: 50%;
z-index: 7;
background: #000000a6;
}
#grid-layout .hybridddcb {
display: inline-block;
position: absolute;
top: 0;
right: 0;
margin: 4px;
}
#grid-layout input:checked + .hybridddcb::before {
width: 10px;
height: 10px;
margin: 4px auto;
background: white;
border-radius: 50%;
}
#grid-layout .hybridddcb::before {
content: '';
display: block;
width: 0;
height: 0;
margin: 0;
}
#grid-layout .hybridddl div{
position: relative;
width: 150px;
height: 150px;
}
#grid-layout .hybriddd-grid .hybriddd-option > label:hover {
transform: scale(96%);
}
resulting in,
images courtesy of the National Gallery of Art, Washington, USA.