cm-angular-dual-listbox
Version:
Dual List Box for Angular
553 lines • 92 kB
JavaScript
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { AngularDualListModel } from './angular-dual-listbox.model';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/forms";
var nextId = 0;
export class CmAngularDualListboxComponent {
static { this.AVAILABLE_LIST_NAME = 'available'; }
static { this.CONFIRMED_LIST_NAME = 'confirmed'; }
static { this.LTR = 'left-to-right'; }
static { this.RTL = 'right-to-left'; }
static { this.DEFAULT_FORMAT = {
add: 'Add',
remove: 'Remove',
all: 'All',
none: 'None',
direction: CmAngularDualListboxComponent.LTR,
draggable: true,
}; }
constructor(differs) {
this.differs = differs;
this.id = `dual-list-${nextId++}`;
this.key = '_id';
this.display = '_name';
this.height = '100px';
this.filter = false;
this.format = CmAngularDualListboxComponent.DEFAULT_FORMAT;
this.sort = false;
this.disabled = false;
this.source = [];
this.destination = [];
this.destinationChange = new EventEmitter();
this.sorter = (a, b) => { return (a._name < b._name) ? -1 : ((a._name > b._name) ? 1 : 0); };
this.available = new AngularDualListModel(CmAngularDualListboxComponent.AVAILABLE_LIST_NAME);
this.confirmed = new AngularDualListModel(CmAngularDualListboxComponent.CONFIRMED_LIST_NAME);
}
ngOnChanges(changeRecord) {
if (changeRecord['filter']) {
if (changeRecord['filter'].currentValue === false) {
this.clearFilter(this.available);
this.clearFilter(this.confirmed);
}
}
if (changeRecord['sort']) {
if (changeRecord['sort'].currentValue === true && this.compare === undefined) {
this.compare = this.sorter;
}
else if (changeRecord['sort'].currentValue === false) {
this.compare = undefined;
}
}
if (changeRecord['format']) {
this.format = changeRecord['format'].currentValue;
if (typeof (this.format.direction) === 'undefined') {
this.format.direction = CmAngularDualListboxComponent.LTR;
}
if (typeof (this.format.add) === 'undefined') {
this.format.add = CmAngularDualListboxComponent.DEFAULT_FORMAT.add;
}
if (typeof (this.format.remove) === 'undefined') {
this.format.remove = CmAngularDualListboxComponent.DEFAULT_FORMAT.remove;
}
if (typeof (this.format.all) === 'undefined') {
this.format.all = CmAngularDualListboxComponent.DEFAULT_FORMAT.all;
}
if (typeof (this.format.none) === 'undefined') {
this.format.none = CmAngularDualListboxComponent.DEFAULT_FORMAT.none;
}
if (typeof (this.format.draggable) === 'undefined') {
this.format.draggable = CmAngularDualListboxComponent.DEFAULT_FORMAT.draggable;
}
}
if (changeRecord['source']) {
this.available = new AngularDualListModel(CmAngularDualListboxComponent.AVAILABLE_LIST_NAME);
this.updatedSource();
this.updatedDestination();
}
if (changeRecord['destination']) {
this.confirmed = new AngularDualListModel(CmAngularDualListboxComponent.CONFIRMED_LIST_NAME);
this.updatedDestination();
this.updatedSource();
}
}
ngDoCheck() {
if (this.source && this.buildAvailable(this.source)) {
this.onFilter(this.available);
}
if (this.destination && this.buildConfirmed(this.destination)) {
this.onFilter(this.confirmed);
}
}
buildAvailable(source) {
const sourceChanges = this.sourceDiffer.diff(source);
if (sourceChanges) {
sourceChanges.forEachRemovedItem((r) => {
const idx = this.findItemIndex(this.available.list, r.item, this.key);
if (idx !== -1) {
this.available.list.splice(idx, 1);
}
});
sourceChanges.forEachAddedItem((r) => {
// Do not add duplicates even if source has duplicates.
if (this.findItemIndex(this.available.list, r.item, this.key) === -1) {
this.available.list.push({ _id: this.makeId(r.item), _name: this.makeName(r.item) });
}
});
if (this.compare !== undefined) {
this.available.list.sort(this.compare);
}
this.available.sift = this.available.list;
return true;
}
return false;
}
buildConfirmed(destination) {
let moved = false;
const destChanges = this.destinationDiffer.diff(destination);
if (destChanges) {
destChanges.forEachRemovedItem((r) => {
const idx = this.findItemIndex(this.confirmed.list, r.item, this.key);
if (idx !== -1) {
if (!this.isItemSelected(this.confirmed.pick, this.confirmed.list[idx])) {
this.selectItem(this.confirmed.pick, this.confirmed.list[idx]);
}
this.moveItem(this.confirmed, this.available, this.confirmed.list[idx], false);
moved = true;
}
});
destChanges.forEachAddedItem((r) => {
const idx = this.findItemIndex(this.available.list, r.item, this.key);
if (idx !== -1) {
if (!this.isItemSelected(this.available.pick, this.available.list[idx])) {
this.selectItem(this.available.pick, this.available.list[idx]);
}
this.moveItem(this.available, this.confirmed, this.available.list[idx], false);
moved = true;
}
});
if (this.compare !== undefined) {
this.confirmed.list.sort(this.compare);
}
this.confirmed.sift = this.confirmed.list;
if (moved) {
this.trueUp();
}
return true;
}
return false;
}
updatedSource() {
this.available.list.length = 0;
this.available.pick.length = 0;
if (this.source !== undefined) {
this.sourceDiffer = this.differs.find(this.source).create();
}
}
updatedDestination() {
if (this.destination !== undefined) {
this.destinationDiffer = this.differs.find(this.destination).create();
}
}
direction() {
return this.format.direction === CmAngularDualListboxComponent.LTR;
}
dragEnd(list = null) {
if (list) {
list.dragStart = false;
}
else {
this.available.dragStart = false;
this.confirmed.dragStart = false;
}
return false;
}
drag(event, item, list) {
if (!this.isItemSelected(list.pick, item)) {
this.selectItem(list.pick, item);
}
list.dragStart = true;
if (event.dataTransfer)
// Set a custom type to be this dual-list's id.
event.dataTransfer.setData(this.id, item['_id']);
}
allowDrop(event, list) {
if (event.dataTransfer)
if (event.dataTransfer.types.length && (event.dataTransfer.types[0] === this.id)) {
event.preventDefault();
if (!list.dragStart) {
list.dragOver = true;
}
}
return false;
}
dragLeave() {
this.available.dragOver = false;
this.confirmed.dragOver = false;
}
drop(event, list) {
if (event.dataTransfer)
if (event.dataTransfer.types.length && (event.dataTransfer.types[0] === this.id)) {
event.preventDefault();
this.dragLeave();
this.dragEnd();
if (list === this.available) {
this.moveItem(this.available, this.confirmed);
}
else {
this.moveItem(this.confirmed, this.available);
}
}
}
trueUp() {
let changed = false;
// Clear removed items.
let pos = this.destination.length;
while ((pos -= 1) >= 0) {
const mv = this.confirmed.list.filter(conf => {
if (typeof this.destination[pos] === 'object') {
return conf._id === this.destination[pos][this.key];
}
else {
return conf._id === this.destination[pos];
}
});
if (mv.length === 0) {
// Not found so remove.
this.destination.splice(pos, 1);
changed = true;
}
}
// Push added items.
for (let i = 0, len = this.confirmed.list.length; i < len; i += 1) {
let mv = this.destination.filter((d) => {
if (typeof d === 'object') {
return (d[this.key] === this.confirmed.list[i]._id);
}
else {
return (d === this.confirmed.list[i]._id);
}
});
if (mv.length === 0) {
// Not found so add.
mv = this.source.filter((o) => {
if (typeof o === 'object') {
return (o[this.key] === this.confirmed.list[i]._id);
}
else {
return (o === this.confirmed.list[i]._id);
}
});
if (mv.length > 0) {
this.destination.push(mv[0]);
changed = true;
}
}
}
if (changed) {
this.destinationChange.emit(this.destination);
}
}
findItemIndex(list, item, key = '_id') {
let idx = -1;
function matchObject(e) {
if (e._id === item[key]) {
idx = list.indexOf(e);
return true;
}
return false;
}
function match(e) {
if (e._id === item) {
idx = list.indexOf(e);
return true;
}
return false;
}
// Assumption is that the arrays do not have duplicates.
if (typeof item === 'object') {
list.filter(matchObject);
}
else {
list.filter(match);
}
return idx;
}
makeUnavailable(source, item) {
const idx = source.list.indexOf(item);
if (idx !== -1) {
source.list.splice(idx, 1);
}
}
moveItem(source, target, item = null, trueup = true) {
let i = 0;
let len = source.pick.length;
if (item) {
i = source.list.indexOf(item);
len = i + 1;
}
for (; i < len; i += 1) {
// Is the pick still in list?
let mv = [];
if (item) {
const idx = this.findItemIndex(source.pick, item);
if (idx !== -1) {
mv[0] = source.pick[idx];
}
}
else {
mv = source.list.filter(src => {
return (src._id === source.pick[i]._id);
});
}
// Should only ever be 1
if (mv.length === 1) {
// Add if not already in target.
if (target.list.filter(trg => trg._id === mv[0]._id).length === 0) {
target.list.push(mv[0]);
}
this.makeUnavailable(source, mv[0]);
}
}
if (this.compare !== undefined) {
target.list.sort(this.compare);
}
source.pick.length = 0;
// Update destination
if (trueup) {
this.trueUp();
}
// Delay ever-so-slightly to prevent race condition.
setTimeout(() => {
this.onFilter(source);
this.onFilter(target);
}, 10);
}
isItemSelected(list, item) {
if (list.filter(e => Object.is(e, item)).length > 0) {
return true;
}
return false;
}
shiftClick(event, index, source, item) {
if (event.shiftKey && source.last && !Object.is(item, source.last)) {
const idx = source.sift.indexOf(source.last);
if (index > idx) {
for (let i = (idx + 1); i < index; i += 1) {
this.selectItem(source.pick, source.sift[i]);
}
}
else if (idx !== -1) {
for (let i = (index + 1); i < idx; i += 1) {
this.selectItem(source.pick, source.sift[i]);
}
}
}
source.last = item;
}
selectItem(list, item) {
const pk = list.filter((e) => {
return Object.is(e, item);
});
if (pk.length > 0) {
// Already in list, so deselect.
for (let i = 0, len = pk.length; i < len; i += 1) {
const idx = list.indexOf(pk[i]);
if (idx !== -1) {
list.splice(idx, 1);
}
}
}
else {
list.push(item);
}
}
selectAll(source) {
source.pick.length = 0;
source.pick = source.sift.slice(0);
}
selectNone(source) {
source.pick.length = 0;
}
isAllSelected(source) {
if (source.list.length === 0 || source.list.length === source.pick.length) {
return true;
}
return false;
}
isAnySelected(source) {
if (source.pick.length > 0) {
return true;
}
return false;
}
unpick(source) {
for (let i = source.pick.length - 1; i >= 0; i -= 1) {
if (source.sift.indexOf(source.pick[i]) === -1) {
source.pick.splice(i, 1);
}
}
}
clearFilter(source) {
if (source) {
source.picker = '';
this.onFilter(source);
}
}
onFilter(source) {
if (source.picker.length > 0) {
try {
const filtered = source.list.filter((item) => {
if (Object.prototype.toString.call(item) === '[object Object]') {
if (item._name !== undefined) {
// @ts-ignore: remove when d.ts has locale as an argument.
return item._name.toLocaleLowerCase(this.format.locale).indexOf(source.picker.toLocaleLowerCase(this.format.locale)) !== -1;
}
else {
// @ts-ignore: remove when d.ts has locale as an argument.
return JSON.stringify(item).toLocaleLowerCase(this.format.locale).indexOf(source.picker.toLocaleLowerCase(this.format.locale)) !== -1;
}
}
else {
// @ts-ignore: remove when d.ts has locale as an argument.
return item.toLocaleLowerCase(this.format.locale).indexOf(source.picker.toLocaleLowerCase(this.format.locale)) !== -1;
}
});
source.sift = filtered;
this.unpick(source);
}
catch (e) {
if (e instanceof RangeError) {
// this.format.locale = undefined;
}
source.sift = source.list;
}
}
else {
source.sift = source.list;
}
}
makeId(item) {
if (typeof item === 'object') {
return item[this.key];
}
else {
return item;
}
}
// Allow for complex names by passing an array of strings.
// Example: [display]="[ '_type.substring(0,1)', '_name' ]"
makeName(item, separator = '_') {
const display = this.display;
function fallback(itm) {
switch (Object.prototype.toString.call(itm)) {
case '[object Number]':
return itm;
case '[object String]':
return itm;
default:
if (itm !== undefined) {
return itm[display];
}
else {
return 'undefined';
}
}
}
let str = '';
if (this.display !== undefined) {
switch (Object.prototype.toString.call(this.display)) {
case '[object Function]':
str = this.display(item);
break;
case '[object Array]':
for (let i = 0, len = this.display.length; i < len; i += 1) {
if (str.length > 0) {
str = str + separator;
}
if (this.display[i].indexOf('.') === -1) {
// Simple, just add to string.
str = str + item[this.display[i]];
}
else {
// Complex, some action needs to be performed
const parts = this.display[i].split('.');
const s = item[parts[0]];
if (s) {
// Use brute force
if (parts[1].indexOf('substring') !== -1) {
const nums = (parts[1].substring(parts[1].indexOf('(') + 1, parts[1].indexOf(')'))).split(',');
switch (nums.length) {
case 1:
str = str + s.substring(parseInt(nums[0], 10));
break;
case 2:
str = str + s.substring(parseInt(nums[0], 10), parseInt(nums[1], 10));
break;
default:
str = str + s;
break;
}
}
else {
// method not approved, so just add s.
str = str + s;
}
}
}
}
break;
default:
str = fallback(item);
break;
}
}
else {
str = fallback(item);
}
return str;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CmAngularDualListboxComponent, deps: [{ token: i0.IterableDiffers }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CmAngularDualListboxComponent, isStandalone: true, selector: "dual-listbox", inputs: { id: "id", key: "key", display: "display", height: "height", filter: "filter", format: "format", sort: "sort", compare: "compare", disabled: "disabled", source: "source", destination: "destination" }, outputs: { destinationChange: "destinationChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"dual-list\">\n\t<div class=\"listbox\" [ngStyle]=\"{ 'order' : direction() ? 1 : 2, 'margin-left' : direction() ? 0 : '10px' }\">\n\t\t<button type=\"button\" name=\"addBtn\" class=\"btn btn-primary btn-block\" (click)=\"moveItem(available, confirmed)\"\n\t\t\t[ngClass]=\"direction() ? 'point-right' : 'point-left'\"\n\t\t\t[disabled]=\"available.pick.length === 0\">{{format.add}}</button>\n\n\t\t<form *ngIf=\"filter\" class=\"filter\">\n\t\t\t<input class=\"form-control\" name=\"filterSource\" [(ngModel)]=\"available.picker\"\n\t\t\t\t(ngModelChange)=\"onFilter(available)\">\n\t\t</form>\n\n\t\t<div class=\"record-picker\">\n\t\t\t<ul [ngStyle]=\"{'max-height': height, 'min-height': height}\" [ngClass]=\"{over:available.dragOver}\"\n\t\t\t\t(drop)=\"drop($event, confirmed)\" (dragover)=\"allowDrop($event, available)\" (dragleave)=\"dragLeave()\">\n\t\t\t\t<li *ngFor=\"let item of available.sift; let idx=index;\"\n\t\t\t\t\t(click)=\"disabled ? null : selectItem(available.pick, item); shiftClick($event, idx, available, item)\"\n\t\t\t\t\t[ngClass]=\"{selected: isItemSelected(available.pick, item), disabled: disabled}\"\n\t\t\t\t\t[draggable]=\"!disabled && format.draggable\" (dragstart)=\"drag($event, item, available)\"\n\t\t\t\t\t(dragend)=\"dragEnd(available)\"><label>{{item._name}}</label></li>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<div class=\"button-bar\">\n\t\t\t<button type=\"button\" class=\"btn btn-primary pull-left\" (click)=\"selectAll(available)\"\n\t\t\t\t[disabled]=\"disabled || isAllSelected(available)\">{{format.all}}</button>\n\t\t\t<button type=\"button\" class=\"btn btn-default pull-right\" (click)=\"selectNone(available)\"\n\t\t\t\t[disabled]=\"!isAnySelected(available)\">{{format.none}}</button>\n\t\t</div>\n\t</div>\n\n\t<div class=\"listbox\" [ngStyle]=\"{ 'order' : direction() ? 2 : 1, 'margin-left' : direction() ? '10px' : 0 }\">\n\t\t<button type=\"button\" name=\"removeBtn\" class=\"btn btn-primary btn-block\"\n\t\t\t(click)=\"moveItem(confirmed, available)\" [ngClass]=\"direction() ? 'point-left' : 'point-right'\"\n\t\t\t[disabled]=\"confirmed.pick.length === 0\">{{format.remove}}</button>\n\n\t\t<form *ngIf=\"filter\" class=\"filter\">\n\t\t\t<input class=\"form-control\" name=\"filterDestination\" [(ngModel)]=\"confirmed.picker\"\n\t\t\t\t(ngModelChange)=\"onFilter(confirmed)\">\n\t\t</form>\n\n\t\t<div class=\"record-picker\">\n\t\t\t<ul [ngStyle]=\"{'max-height': height, 'min-height': height}\" [ngClass]=\"{over:confirmed.dragOver}\"\n\t\t\t\t(drop)=\"drop($event, available)\" (dragover)=\"allowDrop($event, confirmed)\" (dragleave)=\"dragLeave()\">\n\t\t\t\t<li #itmConf *ngFor=\"let item of confirmed.sift; let idx=index;\"\n\t\t\t\t\t(click)=\"disabled ? null : selectItem(confirmed.pick, item); shiftClick($event, idx, confirmed, item)\"\n\t\t\t\t\t[ngClass]=\"{selected: isItemSelected(confirmed.pick, item), disabled: disabled}\"\n\t\t\t\t\t[draggable]=\"!disabled && format.draggable\" (dragstart)=\"drag($event, item, confirmed)\"\n\t\t\t\t\t(dragend)=\"dragEnd(confirmed)\"><label>{{item._name}}</label></li>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<div class=\"button-bar\">\n\t\t\t<button type=\"button\" class=\"btn btn-primary pull-left\" (click)=\"selectAll(confirmed)\"\n\t\t\t\t[disabled]=\"disabled || isAllSelected(confirmed)\">{{format.all}}</button>\n\t\t\t<button type=\"button\" class=\"btn btn-default pull-right\" (click)=\"selectNone(confirmed)\"\n\t\t\t\t[disabled]=\"!isAnySelected(confirmed)\">{{format.none}}</button>\n\t\t</div>\n\t</div>\n</div>", styles: [".record-picker{overflow-x:hidden;overflow-y:auto;border:1px solid #ddd;border-radius:8px;position:relative;cursor:pointer}.record-picker::-webkit-scrollbar{width:12px}.record-picker::-webkit-scrollbar-button{width:0px;height:0px}.record-picker{scrollbar-base-color:#337ab7;scrollbar-3dlight-color:#337ab7;scrollbar-highlight-color:#337ab7;scrollbar-track-color:#eee;scrollbar-arrow-color:gray;scrollbar-shadow-color:gray}.record-picker::-webkit-scrollbar-track{background:#eee;box-shadow:0 0 3px #dfdfdf inset;border-top-right-radius:8px;border-bottom-right-radius:8px}.record-picker::-webkit-scrollbar-thumb{background:#337ab7;border:thin solid gray;border-top-right-radius:8px;border-bottom-right-radius:8px}.record-picker::-webkit-scrollbar-thumb:hover{background:#286090}.record-picker ul{margin:0;padding:0 0 1px}.record-picker li{border-top:thin solid #ddd;border-bottom:1px solid #ddd;display:block;padding:2px 5px 5px 10px;margin-bottom:-1px;font-size:.85em;cursor:pointer;white-space:nowrap;min-height:16px}.record-picker li:hover{background-color:#f5f5f5}.record-picker li.selected{background-color:#d9edf7}.record-picker li.selected:hover{background-color:#c4e3f3}.record-picker li.disabled{opacity:.5;cursor:default;background-color:inherit}.record-picker li:first-child{border-top-left-radius:8px;border-top-right-radius:8px;border-top:none}.record-picker li:last-child{border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-bottom:none}.record-picker label{cursor:pointer;font-weight:inherit;font-size:19px;padding:4px;margin-bottom:-1px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.record-picker ul.over{background-color:#d3d3d3}.dual-list{display:-webkit-box;display:flex;flex-direction:row;align-content:flex-start}.dual-list .listbox{width:50%;margin:0}.dual-list .button-bar{margin-top:8px}.point-right:after{content:\"\\2bc8\";padding-left:.3em}.point-left:before{content:\"\\2bc7\";padding-right:.3em}.dual-list .button-bar button{width:47%;margin-right:5px;border:1px solid #322d2d}button.btn-block{display:block;width:100%;margin-bottom:8px}.filter{margin-bottom:-2.2em}.filter:after{content:\"o\";width:40px;color:transparent;font-size:2em;background-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path d=\"M0 64l192 192v192l128-32V256L512 64H0z\"/></svg>');background-repeat:no-repeat;background-position:center center;opacity:.2;top:-40px;left:calc(100% - 21px);position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CmAngularDualListboxComponent, decorators: [{
type: Component,
args: [{ selector: 'dual-listbox', standalone: true, imports: [CommonModule, FormsModule], template: "<div class=\"dual-list\">\n\t<div class=\"listbox\" [ngStyle]=\"{ 'order' : direction() ? 1 : 2, 'margin-left' : direction() ? 0 : '10px' }\">\n\t\t<button type=\"button\" name=\"addBtn\" class=\"btn btn-primary btn-block\" (click)=\"moveItem(available, confirmed)\"\n\t\t\t[ngClass]=\"direction() ? 'point-right' : 'point-left'\"\n\t\t\t[disabled]=\"available.pick.length === 0\">{{format.add}}</button>\n\n\t\t<form *ngIf=\"filter\" class=\"filter\">\n\t\t\t<input class=\"form-control\" name=\"filterSource\" [(ngModel)]=\"available.picker\"\n\t\t\t\t(ngModelChange)=\"onFilter(available)\">\n\t\t</form>\n\n\t\t<div class=\"record-picker\">\n\t\t\t<ul [ngStyle]=\"{'max-height': height, 'min-height': height}\" [ngClass]=\"{over:available.dragOver}\"\n\t\t\t\t(drop)=\"drop($event, confirmed)\" (dragover)=\"allowDrop($event, available)\" (dragleave)=\"dragLeave()\">\n\t\t\t\t<li *ngFor=\"let item of available.sift; let idx=index;\"\n\t\t\t\t\t(click)=\"disabled ? null : selectItem(available.pick, item); shiftClick($event, idx, available, item)\"\n\t\t\t\t\t[ngClass]=\"{selected: isItemSelected(available.pick, item), disabled: disabled}\"\n\t\t\t\t\t[draggable]=\"!disabled && format.draggable\" (dragstart)=\"drag($event, item, available)\"\n\t\t\t\t\t(dragend)=\"dragEnd(available)\"><label>{{item._name}}</label></li>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<div class=\"button-bar\">\n\t\t\t<button type=\"button\" class=\"btn btn-primary pull-left\" (click)=\"selectAll(available)\"\n\t\t\t\t[disabled]=\"disabled || isAllSelected(available)\">{{format.all}}</button>\n\t\t\t<button type=\"button\" class=\"btn btn-default pull-right\" (click)=\"selectNone(available)\"\n\t\t\t\t[disabled]=\"!isAnySelected(available)\">{{format.none}}</button>\n\t\t</div>\n\t</div>\n\n\t<div class=\"listbox\" [ngStyle]=\"{ 'order' : direction() ? 2 : 1, 'margin-left' : direction() ? '10px' : 0 }\">\n\t\t<button type=\"button\" name=\"removeBtn\" class=\"btn btn-primary btn-block\"\n\t\t\t(click)=\"moveItem(confirmed, available)\" [ngClass]=\"direction() ? 'point-left' : 'point-right'\"\n\t\t\t[disabled]=\"confirmed.pick.length === 0\">{{format.remove}}</button>\n\n\t\t<form *ngIf=\"filter\" class=\"filter\">\n\t\t\t<input class=\"form-control\" name=\"filterDestination\" [(ngModel)]=\"confirmed.picker\"\n\t\t\t\t(ngModelChange)=\"onFilter(confirmed)\">\n\t\t</form>\n\n\t\t<div class=\"record-picker\">\n\t\t\t<ul [ngStyle]=\"{'max-height': height, 'min-height': height}\" [ngClass]=\"{over:confirmed.dragOver}\"\n\t\t\t\t(drop)=\"drop($event, available)\" (dragover)=\"allowDrop($event, confirmed)\" (dragleave)=\"dragLeave()\">\n\t\t\t\t<li #itmConf *ngFor=\"let item of confirmed.sift; let idx=index;\"\n\t\t\t\t\t(click)=\"disabled ? null : selectItem(confirmed.pick, item); shiftClick($event, idx, confirmed, item)\"\n\t\t\t\t\t[ngClass]=\"{selected: isItemSelected(confirmed.pick, item), disabled: disabled}\"\n\t\t\t\t\t[draggable]=\"!disabled && format.draggable\" (dragstart)=\"drag($event, item, confirmed)\"\n\t\t\t\t\t(dragend)=\"dragEnd(confirmed)\"><label>{{item._name}}</label></li>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<div class=\"button-bar\">\n\t\t\t<button type=\"button\" class=\"btn btn-primary pull-left\" (click)=\"selectAll(confirmed)\"\n\t\t\t\t[disabled]=\"disabled || isAllSelected(confirmed)\">{{format.all}}</button>\n\t\t\t<button type=\"button\" class=\"btn btn-default pull-right\" (click)=\"selectNone(confirmed)\"\n\t\t\t\t[disabled]=\"!isAnySelected(confirmed)\">{{format.none}}</button>\n\t\t</div>\n\t</div>\n</div>", styles: [".record-picker{overflow-x:hidden;overflow-y:auto;border:1px solid #ddd;border-radius:8px;position:relative;cursor:pointer}.record-picker::-webkit-scrollbar{width:12px}.record-picker::-webkit-scrollbar-button{width:0px;height:0px}.record-picker{scrollbar-base-color:#337ab7;scrollbar-3dlight-color:#337ab7;scrollbar-highlight-color:#337ab7;scrollbar-track-color:#eee;scrollbar-arrow-color:gray;scrollbar-shadow-color:gray}.record-picker::-webkit-scrollbar-track{background:#eee;box-shadow:0 0 3px #dfdfdf inset;border-top-right-radius:8px;border-bottom-right-radius:8px}.record-picker::-webkit-scrollbar-thumb{background:#337ab7;border:thin solid gray;border-top-right-radius:8px;border-bottom-right-radius:8px}.record-picker::-webkit-scrollbar-thumb:hover{background:#286090}.record-picker ul{margin:0;padding:0 0 1px}.record-picker li{border-top:thin solid #ddd;border-bottom:1px solid #ddd;display:block;padding:2px 5px 5px 10px;margin-bottom:-1px;font-size:.85em;cursor:pointer;white-space:nowrap;min-height:16px}.record-picker li:hover{background-color:#f5f5f5}.record-picker li.selected{background-color:#d9edf7}.record-picker li.selected:hover{background-color:#c4e3f3}.record-picker li.disabled{opacity:.5;cursor:default;background-color:inherit}.record-picker li:first-child{border-top-left-radius:8px;border-top-right-radius:8px;border-top:none}.record-picker li:last-child{border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-bottom:none}.record-picker label{cursor:pointer;font-weight:inherit;font-size:19px;padding:4px;margin-bottom:-1px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.record-picker ul.over{background-color:#d3d3d3}.dual-list{display:-webkit-box;display:flex;flex-direction:row;align-content:flex-start}.dual-list .listbox{width:50%;margin:0}.dual-list .button-bar{margin-top:8px}.point-right:after{content:\"\\2bc8\";padding-left:.3em}.point-left:before{content:\"\\2bc7\";padding-right:.3em}.dual-list .button-bar button{width:47%;margin-right:5px;border:1px solid #322d2d}button.btn-block{display:block;width:100%;margin-bottom:8px}.filter{margin-bottom:-2.2em}.filter:after{content:\"o\";width:40px;color:transparent;font-size:2em;background-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path d=\"M0 64l192 192v192l128-32V256L512 64H0z\"/></svg>');background-repeat:no-repeat;background-position:center center;opacity:.2;top:-40px;left:calc(100% - 21px);position:relative}\n"] }]
}], ctorParameters: () => [{ type: i0.IterableDiffers }], propDecorators: { id: [{
type: Input
}], key: [{
type: Input
}], display: [{
type: Input
}], height: [{
type: Input
}], filter: [{
type: Input
}], format: [{
type: Input
}], sort: [{
type: Input
}], compare: [{
type: Input
}], disabled: [{
type: Input
}], source: [{
type: Input
}], destination: [{
type: Input
}], destinationChange: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1kdWFsLWxpc3Rib3guY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY20tYW5ndWxhci1kdWFsLWxpc3Rib3gvc3JjL2xpYi9hbmd1bGFyLWR1YWwtbGlzdGJveC9hbmd1bGFyLWR1YWwtbGlzdGJveC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jbS1hbmd1bGFyLWR1YWwtbGlzdGJveC9zcmMvbGliL2FuZ3VsYXItZHVhbC1saXN0Ym94L2FuZ3VsYXItZHVhbC1saXN0Ym94LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQVcsWUFBWSxFQUFFLEtBQUssRUFBOEIsTUFBTSxFQUFnQixNQUFNLGVBQWUsQ0FBQztBQUMxSCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUNwRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7O0FBRzdDLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztBQVNmLE1BQU0sT0FBTyw2QkFBNkI7YUFFakMsd0JBQW1CLEdBQUcsV0FBVyxBQUFkLENBQWU7YUFDbEMsd0JBQW1CLEdBQUcsV0FBVyxBQUFkLENBQWU7YUFFbEMsUUFBRyxHQUFHLGVBQWUsQUFBbEIsQ0FBbUI7YUFDdEIsUUFBRyxHQUFHLGVBQWUsQUFBbEIsQ0FBbUI7YUFFdEIsbUJBQWMsR0FBRztRQUN0QixHQUFHLEVBQUUsS0FBSztRQUNWLE1BQU0sRUFBRSxRQUFRO1FBQ2hCLEdBQUcsRUFBRSxLQUFLO1FBQ1YsSUFBSSxFQUFFLE1BQU07UUFDWixTQUFTLEVBQUUsNkJBQTZCLENBQUMsR0FBRztRQUM1QyxTQUFTLEVBQUUsSUFBSTtLQUNoQixBQVBvQixDQU9uQjtJQXVC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