Cleaned up chip list further and simplified it.
This commit is contained in:
70
chip-list.js
70
chip-list.js
@@ -1,6 +1,6 @@
|
|||||||
import { IgniteHtml } from '../ignite-html/ignite-html.js';
|
import { IgniteHtml } from '../ignite-html/ignite-html.js';
|
||||||
import { IgniteElement } from "../ignite-html/ignite-element.js";
|
import { IgniteElement } from "../ignite-html/ignite-element.js";
|
||||||
import { IgniteTemplate, list, div, input, button, h4, span } from "../ignite-html/ignite-template.js";
|
import { IgniteTemplate, list, div, input, button, h4, span, i, converter, text } from "../ignite-html/ignite-template.js";
|
||||||
import { Chip } from "./chip.js";
|
import { Chip } from "./chip.js";
|
||||||
import { Popper } from "./popper.js";
|
import { Popper } from "./popper.js";
|
||||||
import { LinearProgress } from "./linear-progress.js";
|
import { LinearProgress } from "./linear-progress.js";
|
||||||
@@ -47,38 +47,35 @@ class ChipList extends IgniteElement {
|
|||||||
items: [],
|
items: [],
|
||||||
itemsMax: Number.MAX_SAFE_INTEGER,
|
itemsMax: Number.MAX_SAFE_INTEGER,
|
||||||
placeholder: null,
|
placeholder: null,
|
||||||
stopEditingOnBlur: true,
|
|
||||||
editing: false,
|
editing: false,
|
||||||
input: null,
|
input: null,
|
||||||
searchBox: null,
|
|
||||||
search: true,
|
search: true,
|
||||||
searching: false,
|
searching: false,
|
||||||
showSearchResults: true,
|
showSearchResults: true,
|
||||||
searchLoading: false,
|
searchLoading: false,
|
||||||
searchResults: null,
|
searchResults: null,
|
||||||
searchPlaceholder: "No results found.",
|
searchResultConverter: (result) => new text(result),
|
||||||
searchFooter: null,
|
|
||||||
onSearch: null,
|
onSearch: null,
|
||||||
onSearchDelay: 200,
|
onSearchDelay: 200,
|
||||||
onSearchCallback: null,
|
onSearchCallback: null,
|
||||||
blurTimeout: null,
|
|
||||||
documentListener: null,
|
documentListener: null,
|
||||||
freeForm: true,
|
freeForm: true,
|
||||||
chipBackground: null,
|
chipBackground: null,
|
||||||
chipColor: null,
|
chipColor: null,
|
||||||
changed: false,
|
changed: false,
|
||||||
border: false,
|
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
|
showClearButton: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return this.template
|
return this.template
|
||||||
.class("form-control form-control-lg position-relative d-flex flex-row flex-wrap gap-2 align-items-center")
|
.class("form-control form-control-lg position-relative d-flex flex-row gap-2 align-items-center justify-content-between")
|
||||||
.class(this.editing, value => value ? "editing" : null)
|
.class(this.editing, value => value ? "editing" : null)
|
||||||
.attribute("tabindex", "0")
|
.attribute("tabindex", "0")
|
||||||
.onFocus(e => this.onFocus())
|
.onFocus(e => this.onFocus())
|
||||||
.child(
|
.child(
|
||||||
|
new div().class("d-flex flex-row flex-wrap gap-2 align-items-center").child(
|
||||||
//Placeholder
|
//Placeholder
|
||||||
new span().class("text-muted").child(this.placeholder).hide([this.editing, this.items], (editing, items) => editing || (items != null && items.length > 0)),
|
new span().class("text-muted").child(this.placeholder).hide([this.editing, this.items], (editing, items) => editing || (items != null && items.length > 0)),
|
||||||
|
|
||||||
@@ -99,11 +96,11 @@ class ChipList extends IgniteElement {
|
|||||||
//Text input
|
//Text input
|
||||||
new div()
|
new div()
|
||||||
.class("input-container")
|
.class("input-container")
|
||||||
|
.show(this.editing)
|
||||||
.child(
|
.child(
|
||||||
new div()
|
new div()
|
||||||
.class("input")
|
.class("input")
|
||||||
.attribute("contenteditable", "true")
|
.attribute("contenteditable", "true")
|
||||||
.hide(this.editing, value => { return !value; })
|
|
||||||
.ref(this.input)
|
.ref(this.input)
|
||||||
.onEnter((e) => {
|
.onEnter((e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -122,6 +119,7 @@ class ChipList extends IgniteElement {
|
|||||||
//Add a new item to the chip list.
|
//Add a new item to the chip list.
|
||||||
this.items.push({ content: this.input.textContent.trim() });
|
this.items.push({ content: this.input.textContent.trim() });
|
||||||
this.input.innerHTML = "";
|
this.input.innerHTML = "";
|
||||||
|
this.input.focus(); //Refocus to ensure we still have it.
|
||||||
this.searching = false; //Reset searching since we just added a item.
|
this.searching = false; //Reset searching since we just added a item.
|
||||||
this.changed = true; //Make sure changed flag was set.
|
this.changed = true; //Make sure changed flag was set.
|
||||||
}
|
}
|
||||||
@@ -162,8 +160,6 @@ class ChipList extends IgniteElement {
|
|||||||
//will focus the next avaiable element.
|
//will focus the next avaiable element.
|
||||||
if (e.key == "Tab") {
|
if (e.key == "Tab") {
|
||||||
this.searching = false;
|
this.searching = false;
|
||||||
|
|
||||||
if (this.stopEditingOnBlur) {
|
|
||||||
this.editing = false;
|
this.editing = false;
|
||||||
|
|
||||||
//Fire a change event if there was a change.
|
//Fire a change event if there was a change.
|
||||||
@@ -171,7 +167,6 @@ class ChipList extends IgniteElement {
|
|||||||
this.changed = false;
|
this.changed = false;
|
||||||
this.dispatchEvent(new Event("change"));
|
this.dispatchEvent(new Event("change"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this.input.innerHTML = "";
|
this.input.innerHTML = "";
|
||||||
return;
|
return;
|
||||||
@@ -194,25 +189,49 @@ class ChipList extends IgniteElement {
|
|||||||
this.onSearchCallback = setTimeout(() => this.onSearch(this, this.input.textContent.trim()), this.onSearchDelay);
|
this.onSearchCallback = setTimeout(() => this.onSearch(this, this.input.textContent.trim()), this.onSearchDelay);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
|
//Clear button
|
||||||
|
new button()
|
||||||
|
.class("btn btn-link text-muted fs-4")
|
||||||
|
.title("Clear")
|
||||||
|
.show([this.showClearButton, this.items], (show, items) => show && items && items.length > 0)
|
||||||
|
.child(new i().class('fa fa-times'))
|
||||||
|
.onClick(() => {
|
||||||
|
this.items = null;
|
||||||
|
this.editing = false;
|
||||||
|
this.searching = false;
|
||||||
|
this.input.blur();
|
||||||
|
this.input.innerHTML = "";
|
||||||
|
}),
|
||||||
|
|
||||||
//Search results popper
|
//Search results popper
|
||||||
new Popper()
|
new Popper()
|
||||||
.property("show", this.searching)
|
.property("show", this.searching)
|
||||||
.child(
|
.child(
|
||||||
new div()
|
new div()
|
||||||
.class("d-flex flex-column justify-content-center p-2 shadow bg-white")
|
.class("d-flex flex-column justify-content-center p-2 shadow bg-white border rounded-3")
|
||||||
.style("border-radius", "0.4em")
|
|
||||||
.child(
|
.child(
|
||||||
new LinearProgress().class("my-2").property("loading", this.searchLoading),
|
//Progress bar
|
||||||
new span(this.searchPlaceholder).class("mt-2").hide([this.searchResults, this.showSearchResults, this.searchLoading], (searchResults, showSearchResults, searchLoading) => {
|
new LinearProgress()
|
||||||
//Dont show the placeholder if we have search results, or if we are not showing search results.
|
.class("my-2")
|
||||||
return (searchResults != null && searchResults.length > 0 && !searchLoading) || (!showSearchResults || searchLoading);
|
.property("loading", this.searchLoading)
|
||||||
}),
|
.property("color", "var(--bs-primary)"),
|
||||||
new list(this.searchResults, item => {
|
|
||||||
return new div(item.content).class("search-result p-2").onClick(() => this.searchResultClick(item));
|
//Showing results
|
||||||
}).hide([this.showSearchResults, this.searchLoading], (showSearchResults, searchLoading) => !showSearchResults || searchLoading),
|
new span().class("text-muted").hide(this.searchLoading).innerText(this.searchResults, results => results && results.length > 0 ? `Showing ${results.length} ${results.length == 1 ? "result" : "results"}` : "No results"),
|
||||||
this.searchFooter
|
|
||||||
|
//Results
|
||||||
|
new div().class("d-flex flex-column gap-2").hide([this.showSearchResults, this.searchLoading], (showSearchResults, searchLoading) => !showSearchResults || searchLoading).child(
|
||||||
|
new list(
|
||||||
|
this.searchResults,
|
||||||
|
result => new div()
|
||||||
|
.class("search-result")
|
||||||
|
.onClick(() => this.searchResultClick(result))
|
||||||
|
.child(new converter(result, this.searchResultConverter))
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -245,16 +264,15 @@ class ChipList extends IgniteElement {
|
|||||||
//Only blur if we are editing and the target is not ourself or any of our children.
|
//Only blur if we are editing and the target is not ourself or any of our children.
|
||||||
if (this.editing) {
|
if (this.editing) {
|
||||||
if (e.target != this && !this.contains(e.target)) {
|
if (e.target != this && !this.contains(e.target)) {
|
||||||
if (this.stopEditingOnBlur) {
|
|
||||||
this.editing = false;
|
this.editing = false;
|
||||||
|
this.searching = false;
|
||||||
|
|
||||||
//Fire a change event if there was a change.
|
//Fire a change event if there was a change.
|
||||||
if (this.changed) {
|
if (this.changed) {
|
||||||
this.changed = false;
|
this.changed = false;
|
||||||
this.dispatchEvent(new Event("change"));
|
this.dispatchEvent(new Event("change"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
this.searching = false;
|
|
||||||
this.input.blur();
|
this.input.blur();
|
||||||
this.input.innerHTML = "";
|
this.input.innerHTML = "";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user