diff --git a/hybrid-select.js b/hybrid-select.js
index 6049e20..30c9447 100644
--- a/hybrid-select.js
+++ b/hybrid-select.js
@@ -45,8 +45,9 @@ GitHub: https://github.com/aurovrata/hybrid-html-select
optionLabel: function(label){
return ''+label+'';
},
- selectedLabel: function(label){
- return label;
+ selectedLabel: function(s){
+ let k = Object.keys(s);
+ return s[k[0]]+ ((k.length>1)?'[...]':'');
},
listOption: function(o){return true},
}, //default settings.
@@ -80,7 +81,7 @@ GitHub: https://github.com/aurovrata/hybrid-html-select
_.hselect.options.classList.add('hybrid-options');
_.hindex = [-1]; //initial option hover index.
_.sindex = [0]; //initial index of selected option.
- _.value = _.opt.limitSelection==1?"":[""]; //initial value.
+ _.value = {}; //initial value.
}
//set style.
_.el.parentElement.classList.value='hybrid-select-container hybrid-select-'+_.opt.dropdown;
@@ -143,12 +144,13 @@ GitHub: https://github.com/aurovrata/hybrid-html-select
//preserve select options attributes.
// for(let k in o.dataset) hso.dataset[k]=o.dataset[k];
hso.dataset.hsoValue=o.value;
- hso.innerHTML =_.opt.optionLabel(o.textContent);
+ hso.innerHTML =_.opt.optionLabel(o.text);
hso.classList = o.classList;
hso.classList.add('hybrid-option');
if(o.selected===true || (i+idx)==0){
if(i>0) opts[0].classList.remove('active');
- _.hselect.selected.innerHTML = _.opt.selectedLabel(o.textContent);
+ _.value[o.value] = o.text;
+ _.hselect.selected.innerHTML = _.opt.selectedLabel(_.value);
hso.classList.add('active');
_.sindex[0] = (i+idx); //keep track of selected value.
}
@@ -176,48 +178,40 @@ GitHub: https://github.com/aurovrata/hybrid-html-select
hasDefault = _.el.children[0].value==="";
switch(_.opt.limitSelection){
case 1: //default
- if(_.sindex[0] >=0) _.hselect.options.children[_.sindex[0]].classList.remove('active');
+ if(_.sindex[0] >=0) _.optionClass('active', _.sindex);
_.sindex[0] = idx;
_.hselect.options.children[idx].classList.add('active');
//update values.
- _.el.value = _.value = _.hselect.options.children[idx].dataset.hsoValue;
-
+ _.el.value = _.hselect.options.children[idx].dataset.hsoValue;
+ _.value[_.el.value] = _.hselect.options.children[idx].innerHTML;
//update the selected label.
- _.hselect.selected.innerHTML = _.hselect.options.children[idx].innerHTML;
+ _.hselect.selected.innerHTML = _.opt.selectedLabel(_.value);
break;
case -1: //unlimited
default: //limit number of selections.
if( hasDefault && _.sindex.length==1 && _.sindex[0]==0){
- _.hselect.options.children[0].classList.remove('active');
+ _.optionClass('active',[0]); //toggle
if(_.opt.limitSelection < 0) _.sindex = idxs;
else _.sindex = idxs.slice(0,_.opt.limitSelection);
}else{
let si =[];
- idxs.forEach(i=>{
- if( (idx = _.sindex.indexOf(i)) >=0 ){
- _.hselect.options.children[i].classList.remove('active');
- _.sindex.splice(idx,1);//remove from selection.
- }else{
- si[si.length]=i;
- }
+ _.sindex.forEach(i=>{
+ _.hselect.options.children[i].classList.remove('active');
});
- if(_.opt.limitSelection < 0) _.sindex=_.sindex.concat(si);
- else if(_.sindex.length < _.opt.limitSelection){
- _.sindex=_.sindex.concat(si.slice(0,_.opt.limitSelection-_.sindex.length));
- }
+ if(_.opt.limitSelection < 0) _.sindex=idxs;
+ else _.sindex=idxs.slice(0,_.opt.limitSelection);
}
//update values.
- _.value = [];
+ _.value = {};
_.el.selectedIndex = -1;
_.sindex.forEach(i=>{
+ let v= _.hselect.options.children[i].dataset.hsoValue;
_.hselect.options.children[i].classList.add('active');
- _.value[_.value.length] = _.hselect.options.children[i].dataset.hsoValue;
- _.el.querySelector('option[value="'+_.value[_.value.length-1]+'"]').selected=true;
+ _.value[v]=_.hselect.options.children[i].innerHTML;
+ _.el.querySelector('option[value="'+v+'"]').selected=true;
});
- // _.el.value = _.value;
-
//update the selected label.
- _.hselect.selected.innerHTML = _.hselect.options.children[_.sindex[0]].innerHTML+'[...]';
+ _.hselect.selected.innerHTML = _.opt.selectedLabel(_.value);
break;
}
if(emit) _.emit('change');
@@ -228,10 +222,10 @@ GitHub: https://github.com/aurovrata/hybrid-html-select
if(_.el.multiple){
let skipUpdate = true;
for(let i=0; i<_.el.selectedOptions.length; i++){
- if(!_.value.includes(_.el.selectedOptions.item(i).value)) skipUpdate=false;
+ if(!(_.el.selectedOptions.item(i).value in _.value) ) skipUpdate=false;
}
if(skipUpdate) return;
- }else if(_.el.value === _.value) return; //not need to update.
+ }else if(_.el.value in _.value) return; //not need to update.
let sel = _.hselect.options.querySelector(`.hybrid-option[data-hso-value="${_.el.value}"`);
sel = [..._.hselect.options.children].indexOf(sel); //index in hybrid.
_.updateSelection([sel], false);
@@ -300,9 +294,13 @@ GitHub: https://github.com/aurovrata/hybrid-html-select
switch(e.keyCode){
case 40: //down arrow.
if(_.hselect.classList.contains('active')){ //list is open, change hover option
- if(_.hindex>=0) _.hselect.options.children[_.hindex].classList.remove('hover');
- _.hindex = _.nextHybridOption(_.hindex);
- _.hselect.options.children[_.hindex].classList.add('hover');
+ if(_.hindex[0]>=0 && !_.el.multiple && !e.shiftKey) _.optionClass('hover', _.hindex); //toggle class
+ let idx = _.nextHybridOption(_.hindex);
+ _.hselect.options.children[idx].classList.add('hover');
+ if(_.el.multiple && e.shiftKey){
+ _.hindex.push(idx);
+ if(_.opt.limitSelection>0) _.hindex = _.hindex.slice(-1*_.opt.limitSelection);
+ }else _.hindex[0] = idx;
}else{ //change select value
if(1==_.opt.limitSelection){ //select the next value.
let sindex = _.nextHybridOption(_.sindex);
@@ -315,9 +313,13 @@ GitHub: https://github.com/aurovrata/hybrid-html-select
break;
case 38: //up arrow.
if(_.hselect.classList.contains('active')){ //list is open, change hover option
- if(_.hindex>=0) _.hselect.options.children[_.hindex].classList.remove('hover');
- _.hindex = _.prevHybridOption(_.hindex);
- _.hselect.options.children[_.hindex].classList.add('hover');
+ if(_.hindex[0]>=0 && !_.el.multiple && !e.shiftKey) _.optionClass('hover', _.hindex);
+ let idx = _.prevHybridOption(_.hindex);
+ _.hselect.options.children[idx].classList.add('hover');
+ if(_.el.multiple && e.shiftKey){
+ _.hindex.push(idx);
+ if(_.opt.limitSelection>0) _.hindex = _.hindex.slice(-1*_.opt.limitSelection);
+ }else _.hindex[0] = idx;
}else{ //change select value
if(1==_.opt.limitSelection){ //select the next value.
let sindex = _.prevHybridOption(_.sindex);
@@ -379,19 +381,31 @@ GitHub: https://github.com/aurovrata/hybrid-html-select
if(e && e.target){
let t = e.target;
if(t.classList.contains('hybrid-option')===false) t = t.closest('.hybrid-option');
- let idx = [..._.hselect.options.children].indexOf(t); //index in hybrid.
- _.updateSelection([idx], true);
+ _.updateSelection(_.hindex, true);
//close the dropdown
- _.closeSelect(e.type==='click');
+ if(!e.ctrlKey && !e.shiftKey) _.closeSelect(e.type==='click');
}
}
//function to flag options being hovered.
hsProtype.optionHover = function(){
let _ = this, e = arguments[0];
if(e && e.target && e.target.classList.contains('hybrid-option')) {
- if(_.hindex>=0) _.hselect.options.children[_.hindex].classList.remove('hover');
- _.hindex = [..._.hselect.options.children].indexOf(e.target);
- _.hselect.options.children[_.hindex].classList.add('hover');
+ if(_.hindex[0]>=0 && !e.shiftKey) _.optionClass('hover',_.hindex);
+ let idx = [..._.hselect.options.children].indexOf(e.target);
+ _.hselect.options.children[idx].classList.add('hover');
+ if(_.el.multiple && e.shiftKey){
+ _.hindex.push(idx);
+ if(_.opt.limitSelection>0) _.hindex = _.hindex.slice(-1*_.opt.limitSelection);
+ }else _.hindex = [idx];
+ }
+ }
+ //toggle class on option.
+ hsProtype.optionClass = function(cl, idxs=[]){
+ let _ = this;
+ if('string' == typeof cl && cl.length>0){
+ idxs.forEach(i=>{
+ _.hselect.options.children[i].classList.toggle(cl);
+ })
}
}
//open hybrid dropdown.
@@ -417,6 +431,10 @@ GitHub: https://github.com/aurovrata/hybrid-html-select
_.event(document, 'add',{
click: _.close
});
+ //listen for key navigation
+ _.event(_window,'add',{
+ keydown:_.keyNav
+ });
//close if another hselect field opens.
_.event(document,'add',{
'hybrid-select-click':_.close
@@ -424,15 +442,21 @@ GitHub: https://github.com/aurovrata/hybrid-html-select
}
//close hybrid dropdown.
hsProtype.closeSelect = function(blur){
- let _ = this, e = arguments[0],e2 = arguments[1];
-
+ let _ = this,
+ e = arguments[0],
+ e2 = arguments[1]; //click on document
+ //if click to select cancel close.
if(e && e.target && e.target.classList.contains('hselect-option')) return;
- if(e2 && e2.target.isSameNode(_.el)) return;
+
+ if(e2){
+ if(e2.target.isSameNode(_.el)) return; //in case original element is clicked
+ if(_.el.multiple && (e2.ctrlKey || e2.shiftKey)) return; //multiple select w/ ctrl|shift key
+ }
_.hselect.classList.remove('active');
//reset the option hover index.
if(_.hindex>=0) _.hselect.options.children[_.hindex].classList.remove('hover');
- _.hindex = -1;
+ _.hindex = [-1];
//stop listening to external clicks.
_.event(document, 'remove',{
click: _.close