@amcharts/amcharts5
Version:
amCharts 5
298 lines • 11.2 kB
JavaScript
import { __awaiter } from "tslib";
import { Dropdown } from "./Dropdown";
//import type { IDisposer } from "../../../core/util/Disposer";
import * as $array from "../../../core/util/Array";
import * as $utils from "../../../core/util/Utils";
/**
* A dropdown control for [[StockToolbar]].
*
* @see {@link https://www.amcharts.com/docs/v5/charts/stock/toolbar/dropdown-list-control/} for more info
*/
export class DropdownList extends Dropdown {
// private _itemDisposers: Array<IDisposer> = [];
_afterNew() {
super._afterNew();
this._setupKeyboardNav();
this._root.addDisposer(this);
}
_initElements() {
super._initElements();
// Create container
const container = this.getPrivate("container");
// Init search
if (this.get("searchable")) {
this._initSearch();
}
// Create list
const list = document.createElement("ul");
list.className = "am5stock-control-list";
container.appendChild(list);
this.setPrivate("list", list);
this._initItems();
}
_sizeItems() {
const list = this.getPrivate("list");
if (list) {
list.style.maxHeight = (this.root.container.height() - 100) + "px";
list.style.overflow = "auto";
}
}
/**
* Rebuilds the list.
*
* Useful when changing item data within item list.
*
* @since 5.7.0
*/
rebuildList() {
this._initItems();
}
_initItems(items) {
const list = this.getPrivate("list");
list.innerHTML = "";
if (!items) {
items = this.get("items", []);
}
const exclude = this.get("exclude", []);
$array.each(items, (item) => {
if (exclude.indexOf(item.id) == -1) {
this.addItem(item);
}
});
if (this.get("scrollable")) {
this._sizeItems();
}
this._maybeMakeAccessible();
}
_initSearch() {
let searchBox = this.getPrivate("search");
if (this.get("searchable")) {
if (!searchBox) {
const container = this.getPrivate("container");
searchBox = document.createElement("div");
searchBox.className = "am5stock-list-search";
container.appendChild(searchBox);
this.setPrivate("search", searchBox);
const input = document.createElement("input");
input.type = "text";
input.placeholder = this._root.language.translateAny("Search");
searchBox.appendChild(input);
this._disposers.push($utils.addEventListener(input, "input", (_ev) => {
this._filterItems(input.value);
}));
this._disposers.push($utils.addEventListener(input, "focus", (_ev) => {
this._currentSelectedIndex = undefined;
}));
}
}
else if (searchBox) {
searchBox.style.display = "none";
}
}
_beforeChanged() {
super._beforeChanged();
if (this.isDirty("items")) {
this._initItems();
}
if (this.isDirty("searchable")) {
this._initSearch();
}
if (this.isPrivateDirty("currentId")) {
// @todo
}
if (this.isDirty("control")) {
this._maybeMakeAccessible();
}
}
_dispose() {
super._dispose();
// $array.each(this._itemDisposers, (x) => {
// x.dispose();
// });
}
_filterItems(search) {
return __awaiter(this, void 0, void 0, function* () {
const searchCallback = this.get("searchCallback");
if (search == "") {
this._initItems(this.get("items"));
}
else if (searchCallback && search) {
const maxItems = this.get("maxSearchItems", 1000);
let items = yield searchCallback.call(this, search);
if (maxItems && (items.length > maxItems)) {
items = items.slice(0, maxItems - 1);
items.push({
id: "",
className: "am5stock-list-info",
label: this._root.language.translateAny("Search results are limited to %1.", undefined, "" + maxItems)
});
}
this._initItems(items);
}
else {
const list = this.getPrivate("list");
if (list) {
const items = list.getElementsByTagName("li");
$array.each(items, (item) => {
const regex = new RegExp(search || "", "i");
if (!search || item.innerText.match(regex)) {
item.style.display = "";
}
else {
item.style.display = "none";
}
});
}
}
});
}
addItem(info) {
const list = this.getPrivate("list");
const item = document.createElement("li");
item.className = "am5stock-list-item";
item.setAttribute("title", info.subLabel || info.label);
if (info.className) {
item.className += " " + info.className;
}
if (info.icon) {
item.appendChild(info.icon);
}
let inputId;
if (info.form) {
const input = document.createElement("input");
inputId = "am5stock-list-" + info.id;
input.type = info.form;
input.setAttribute("tabindex", "-1");
if (info.value) {
input.value = info.value;
}
if (info.form == "radio") {
input.name = info.id;
inputId += "-" + info.value;
}
if (info.checked) {
input.checked = true;
}
input.id = inputId;
this._disposers.push($utils.addEventListener(item, "click", (ev) => {
//ev.preventDefault();
if (ev.target !== input) {
input.checked = !input.checked;
}
this.events.dispatch("changed", {
type: "changed",
item: info,
value: input.checked,
checked: input.checked,
target: this
});
}));
item.appendChild(input);
}
const label = document.createElement("label");
label.innerHTML = info.label;
if (info.label == "") {
label.style.display = "none";
}
item.appendChild(label);
if (info.subLabel) {
const subLabel = document.createElement("label");
subLabel.className = "am5stock-list-sub";
subLabel.innerHTML = info.subLabel;
item.appendChild(subLabel);
}
if (info.id == "separator") {
item.innerHTML = "<hr>";
}
list.appendChild(item);
// Add click event
if (info.disabled) {
item.className += " am5stock-disabled";
}
else {
this._disposers.push($utils.addEventListener(item, "click", (_ev) => {
this.hide();
this.events.dispatch("invoked", {
type: "invoked",
item: info,
target: this
});
}));
}
}
hide() {
super.hide();
this._filterItems();
let searchBox = this.getPrivate("search");
if (searchBox) {
const inputs = searchBox.getElementsByTagName("input");
let isCustomSearch = false;
$array.each(inputs, (input) => {
if (input.value !== "") {
isCustomSearch = true;
input.value = "";
}
});
if (this.get("searchCallback") && isCustomSearch) {
this._initItems();
}
}
this._currentSelectedIndex = undefined;
}
_setupKeyboardNav() {
if ($utils.supports("keyboardevents")) {
const button = this.get("control").getPrivate("button");
this._disposers.push($utils.addEventListener(document, "keydown", (ev) => {
if (this.isAccessible()) {
if (document.activeElement && (document.activeElement === button || $utils.contains(button, document.activeElement))) {
if (ev.keyCode == 13) {
// ENTER
if (document.activeElement !== button) {
document.activeElement.click();
}
}
else if (ev.keyCode == 38 || ev.keyCode == 40) {
const dir = ev.keyCode == 38 ? -1 : 1;
let index = this._currentSelectedIndex;
if (index === undefined) {
index = 0;
}
else {
index += dir;
}
const items = this._getActiveItems();
if (index < 0) {
index = items.length - 1;
}
else if (index >= items.length) {
index = 0;
}
this.setTimeout(() => {
$utils.focus(items.item(index));
this._currentSelectedIndex = index;
}, 15);
}
}
}
}));
}
}
_maybeMakeAccessible() {
super._maybeMakeAccessible();
if (this.isAccessible()) {
//const tabindex = this._root.tabindex.toString();
//const list = this.getPrivate("list")!;
const items = this._getActiveItems();
items.forEach((item) => {
item.setAttribute("tabindex", "-1");
item.setAttribute("aria-label", item.getAttribute("title") || "");
});
}
}
_getActiveItems() {
return this.getPrivate("list").querySelectorAll(".am5stock-list-item:not(.am5stock-list-info, .am5stock-list-heading, .am5stock-disabled)");
}
}
DropdownList.className = "DropdownList";
DropdownList.classNames = Dropdown.classNames.concat([DropdownList.className]);
//# sourceMappingURL=DropdownList.js.map