code added
This commit is contained in:
förälder
a826e188ed
incheckning
c2f6fbdb94
|
|
@ -0,0 +1,256 @@
|
|||
|
||||
class SearchableMulti extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ['placeholder'];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._values = [];
|
||||
this._placeholder = 'Search...';
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
if(!this._rendered) {
|
||||
this._rendered = true;
|
||||
this.attachShadow({ mode: 'open' });
|
||||
this.shadowRoot.appendChild(this._template());
|
||||
this._refresh();
|
||||
}
|
||||
|
||||
this._nonSelected.addEventListener('click', this);
|
||||
this._selected.addEventListener('click', this);
|
||||
this._search.addEventListener('keyup', this);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this._nonSelected.removeEventListener('click', this);
|
||||
this._selected.removeEventListener('click', this);
|
||||
this._search.removeEventListener('keyup', this);
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldVal, newVal) {
|
||||
if(name === 'placeholder') {
|
||||
this.placeholder = newVal;
|
||||
}
|
||||
}
|
||||
|
||||
get value() {
|
||||
return this._values;
|
||||
}
|
||||
|
||||
get placeholder() {
|
||||
return this._placeholder;
|
||||
}
|
||||
|
||||
set placeholder(val) {
|
||||
this._placeholder = val;
|
||||
if(this._rendered) {
|
||||
this.shadowRoot.querySelector('input').placeholder = val;
|
||||
}
|
||||
}
|
||||
|
||||
handleEvent(ev) {
|
||||
var el = ev.target;
|
||||
switch(ev.type) {
|
||||
case 'click':
|
||||
if(el.className === 'item') {
|
||||
if(el.parentNode.className === 'non-selected-wrapper') {
|
||||
this._nonSelectedClick(el);
|
||||
} else {
|
||||
this._selectedClick(el);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'keyup':
|
||||
if(ev.keyCode === 32 || ev.keyCode === 13) {
|
||||
if(el.className === 'item') {
|
||||
if(el.parentNode.className === 'non-selected-wrapper') {
|
||||
this._nonSelectedClick(el);
|
||||
} else {
|
||||
this._selectedClick(el);
|
||||
}
|
||||
ev.preventDefault();
|
||||
}
|
||||
} else {
|
||||
this._onSearch();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_nonSelectedClick(el) {
|
||||
// Not already selected
|
||||
if(!el._selected) {
|
||||
this._setSelected(el);
|
||||
this.dispatchEvent(new Event('change'));
|
||||
}
|
||||
}
|
||||
|
||||
_setSelected(el) {
|
||||
el._option.selected = true;
|
||||
var clone = el._selected = el.cloneNode(true);
|
||||
clone._nonSelected = el;
|
||||
this._selected.appendChild(clone);
|
||||
this._values.push(el.dataset.value);
|
||||
}
|
||||
|
||||
_selectedClick(el) {
|
||||
var nonSelected = el._nonSelected;
|
||||
var option = nonSelected._option;
|
||||
nonSelected._selected = undefined;
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
// Deselect the option
|
||||
option.selected = false;
|
||||
|
||||
// Remove from values
|
||||
var idx = this._values.indexOf(el.dataset.value);
|
||||
if(idx !== -1) {
|
||||
this._values.splice(idx, 1);
|
||||
this.dispatchEvent(new Event('change'));
|
||||
}
|
||||
}
|
||||
|
||||
_onSearch() {
|
||||
var term = this._search.value.toLowerCase();
|
||||
|
||||
function includes(str) {
|
||||
return str.toLowerCase().indexOf(term) !== -1;
|
||||
}
|
||||
|
||||
var nonSelected, d;
|
||||
for(var i = 0, len = this._nonSelected.children.length; i < len; i++) {
|
||||
nonSelected = this._nonSelected.children[i];
|
||||
|
||||
if(term && !includes(nonSelected.dataset.value) &&
|
||||
!includes(nonSelected.textContent)) {
|
||||
d = 'none';
|
||||
} else {
|
||||
d = '';
|
||||
}
|
||||
nonSelected.style.display = d;
|
||||
if(nonSelected._selected) {
|
||||
nonSelected._selected.style.display = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_template() {
|
||||
var doc = this.ownerDocument;
|
||||
var wrapper = doc.createElement('div');
|
||||
wrapper.className = 'wrapper';
|
||||
|
||||
var style = doc.createElement('style');
|
||||
style.textContent = this._styles();
|
||||
|
||||
var input = this._search = doc.createElement('input');
|
||||
input.type = 'text';
|
||||
input.className = 'search-input';
|
||||
input.placeholder = this.placeholder;
|
||||
|
||||
var nonSelected = this._nonSelected = doc.createElement('div');
|
||||
nonSelected.className = 'non-selected-wrapper';
|
||||
|
||||
var selected = this._selected = doc.createElement('div');
|
||||
selected.className = 'selected-wrapper';
|
||||
|
||||
wrapper.appendChild(style);
|
||||
wrapper.appendChild(input);
|
||||
wrapper.appendChild(nonSelected);
|
||||
wrapper.appendChild(selected);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
_styles() {
|
||||
return `
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.non-selected-wrapper,
|
||||
.selected-wrapper {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
height: 200px;
|
||||
overflow-y: scroll;;
|
||||
padding: 10px;
|
||||
vertical-align: top;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.non-selected-wrapper {
|
||||
background: #fafafa;
|
||||
border-right: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.selected-wrapper {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.item {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
background: #ececec;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
border: 0;
|
||||
border-bottom: 1px solid #ccc;
|
||||
border-radius: 0;
|
||||
display: block;
|
||||
font-size: 1em;
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
padding: 10px 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.non-selected-wrapper .item.selected {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.non-selected-wrapper .row.selected:hover {
|
||||
background: inherit;
|
||||
cursor: inherit;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
_refresh() {
|
||||
this._selected.innerHTML = this._nonSelected.innerHTML = '';
|
||||
|
||||
var term = this._search.value;
|
||||
var options = [].slice.call(this.querySelectorAll('option'));
|
||||
var doc = this.ownerDocument;
|
||||
|
||||
options.forEach(function(option){
|
||||
var row = doc.createElement('a');
|
||||
row.setAttribute('tabindex', "0");
|
||||
row.setAttribute('role', 'button');
|
||||
row.textContent = option.textContent;
|
||||
row.dataset.value = option.value;
|
||||
row.className = 'item';
|
||||
row._option = option;
|
||||
this._nonSelected.appendChild(row);
|
||||
|
||||
if(option.selected) {
|
||||
this._setSelected(row);
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('searchable-multi', SearchableMulti);
|
||||
Laddar…
Referens i nytt ärende