testMultiSelect = {
const Data = {
"name": "multipleSelection",
"category": "2. Strings",
"type": "char",
"shape": "row",
"domain": ["a","multi","set","to","select","EvenIfAnEntryIsVeryLong","and","theTotal","length","isCrazy!"],
"value": ["a", "multi"],
"readOnly": false,
"hidden": false
};
const Data2 = {
"name": "multipleSelection2",
"category": "2. Strings",
"type": "char",
"shape": "row",
"domain": ["a","multi","set","to","select","EvenIfAnEntryIsVeryLong","and","theTotal","length","isCrazy!"],
"value": ["a", "set"],
"readOnly": false,
"hidden": false
};
class MSel {
constructor({container,data,id}={}) {
this._uniqueId = id || 'sel';
this._parent = container || DOM.element('div');
this._parent.id = "multiselect-parent";
this._shadow = this._parent.attachShadow({mode:"open"});
this._shadow.innerHTML = `<style>${innerStyle}</style>`;
this._selectionCount = 0;
this._data = data || {};
this.parse();
this.createUi();
this.bind();
this.update();
this._isListShowing = false;
}
render() {
return this._parent;
}
parse() {
if (!this.isReady) return;
var value = this._data.value;
this._optionCount = this._data.domain.length;
this._items = this._data.domain.map((name,idx) => {
if (~Array.isArray(value)) value = Array.from(value);
const isChecked = value.length ? value.some((d) => d === name ) : false;
let item = {
id: name,
index: idx,
text: humanize(name),
element: MSel.createItem("li",name,humanize(name),isChecked),
get selected() {
let input = this.element.input;
return input.checked;
},
set selected(bool) {
this.element.input.checked = bool;
}
};
return item;
});
}
createUi() {
if (!this.isReady) return;
const wrap = DOM.element("div");
wrap.classList.add("multiselect-input-div");
const input = DOM.element("input");
input.id = this.InputFieldId;
input.classList.add("multiselect-input");
input.setAttribute("autocomplete","off");
input.setAttribute("type","text");
const counter = DOM.element("label");
counter.id = this.InputBadgeId;
counter.classList.add("multiselect-count");
counter.setAttribute("for",this.InputFieldId);
counter.innerHTML = 0;
const arrow = DOM.element("label");
arrow.classList.add("multiselect-dropdown-arrow");
arrow.setAttribute("for",this.InputFieldId);
wrap.appendChild(input);
wrap.appendChild(counter);
wrap.appendChild(arrow);
this._input = {wrap:wrap,text:input,counter:counter,arrow:arrow};
const itemwrap = DOM.element("div");
itemwrap.id = this.ItemListId;
itemwrap.classList.add("multiselect-list");
var list = DOM.element("ul");
this._items.forEach( (item) => {
list.appendChild(item.element.wrap);
});
let selectall = MSel.createItem("span",-1,"Select All",false);
itemwrap.appendChild(selectall.wrap);
let hrule = DOM.element("hr");
itemwrap.appendChild(hrule);
itemwrap.appendChild(list);
this._itemList = {wrap:itemwrap,elems:list,rule:hrule,all:selectall};
}
bind() {
if (!this.isReady) return;
const self = this;
this._input.wrap.addEventListener("click", (evt) => {evt.stopPropagation});
this._input.text.addEventListener("click", (evt) => self.onInputFocus(evt));
this._input.text.addEventListener("dblclick", (evt) => self.onHideList(evt));
this._input.text.addEventListener("input", (evt) => self.onInput(evt));
this._itemList.all.input.addEventListener("change", (evt) => {
self.onSelectAllChanged(evt);
});
this._items.forEach( (item) => {
let box = item.element.input;
box.addEventListener("change", (evt) => {
self.onSelectionChanged(item,evt);
});
});
this._shadow.appendChild(this._input.wrap);
this._shadow.appendChild(this._itemList.wrap);
}
showList() {
this._itemList.wrap.classList.add('active');
this._input.arrow.classList.add('up');
this._isListShowing = true;
}
hideList() {
this._itemList.wrap.classList.remove('active');
this._input.arrow.classList.remove('up');
this.show(this._itemList.all.wrap);
this.show(this._itemList.rule);
this._itemList.elems.childNodes.forEach(this.show);
this.update();
this._isListShowing = false;
}
update() {
let Ids = this.selectedIds;
let idCount = Ids.length;
this._selectionCount = idCount;
this._input.text.value = idCount === this._optionCount ?
"All Selected" :
Ids.join(",");
this._input.counter.innerHTML = idCount;
this._data.value = Ids;
}
show(elem) {
elem.style.display = "block";
}
hide(elem) {
elem.style.display = "none";
}
onHideList(event) {
this.hideList();
if (event) event.stopPropagation();
}
onInputFocus(event) {
console.log("event:",event)
console.log("arrow:",this._input.arrow.offsetLeft)
if (!this._isListShowing) {
this.showList();
this._input.text.value = "";
} else if(event.offsetX >= this._input.arrow.offsetLeft) {
this.hideList();
}
}
onSelectionChanged(source,event) {
if (event) event.stopPropagation();
this.update();
}
onSelectAllChanged(event) {
const status = event.target.checked;
this._items.forEach( (item) => MSel.setStatus(item,status) );
if (event) event.stopPropagation();
this.update();
}
onInput(event) {
let currentText = this._input.text.value;
console.log(currentText);
}
get isReady() {
let obj = this._data;
return !(!!obj && Object.keys(obj).length === 0 && obj.constructor === Object);
}
get Id() {
return `${this._uniqueId}_multiselect`;
}
get InputFieldId() {
return `${this._uniqueId}_input`;
}
get ItemListId() {
return `${this._uniqueId}_itemList`;
}
get InputBadgeId() {
return `${this._uniqueId}_inputCount`;
}
get itemIds() {
if (!this.isReady) return [];
return this._items.map( (v) => v.id );
}
get itemNames() {
if (!this.isReady) return [];
return this._items.map( (v) => humanize(v.id) );
}
get selectedIndices() {
if (!this.isReady) return [];
return this._items.reduce( (inds,elem,loc) => {
if(elem.selected) inds.push(loc);
return inds;
}, []);
}
get selectedIds() {
if (!this.isReady) return [];
return this._items.reduce( (ids,elem) => {
if(elem.selected) ids.push(elem.id);
return ids
}, []);
}
static createItem(type,value,text,isSelected) {
let box = DOM.element("input");
box.type = "checkbox";
box.classList.add("multiselect-checkbox");
box.dataset.val = value;
box.checked = isSelected;
let textBox = DOM.element("span");
textBox.classList.add("multiselect-text");
textBox.innerHTML = text;
let wrap = DOM.element(type);
let label = DOM.element("label");
label.appendChild(box);
label.appendChild(textBox);
wrap.appendChild(label);
return {wrap:wrap,input:box};
}
static setStatus(item,status) {
item.selected = status;
}
}
const m = new MSel({data:Data});
const m2 = new MSel({data:Data2});
const tab = DOM.element('table');
tab.id = "testOuter";
const body = DOM.element('tbody');
body.innerHTML = `<tr><td class="left">left</td><td class="right">right</td></tr>`;
const row = DOM.element('tr');
row.appendChild(html`<td class="left">propname</td>`);
const cell = DOM.element('td');
cell.classList.add("right","show-overflow");
cell.appendChild(m.render());
row.appendChild(cell);
const row2 = DOM.element('tr');
row2.appendChild(html`<td class="left">propname2</td>`);
const cell2 = DOM.element('td');
cell2.classList.add("right","show-overflow");
cell2.appendChild(m2.render());
row2.appendChild(cell2);
body.appendChild(row);
body.appendChild(row2);
tab.appendChild(body);
const out = DOM.element('div');
out.id = "table-wrap";
out.style.height = "500px";
out.appendChild(tab);
return out;
}