1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00
Files
netbox-community-netbox/netbox/project-static/src/search.ts

138 lines
4.9 KiB
TypeScript
Raw Normal View History

import debounce from 'just-debounce-it';
import { getElements, getRowValues, findFirstAdjacent } from './util';
2021-03-13 02:31:57 -07:00
interface SearchFilterButton extends EventTarget {
dataset: { searchValue: string };
}
function isSearchButton(el: any): el is SearchFilterButton {
return el?.dataset?.searchValue ?? null !== null;
}
2021-04-20 09:34:12 -07:00
function initSearchBar() {
2021-03-13 02:31:57 -07:00
const dropdown = document.getElementById('object-type-selector');
const selectedValue = document.getElementById('selected-value') as HTMLSpanElement;
const selectedType = document.getElementById('search-obj-type') as HTMLInputElement;
let selected = '';
if (dropdown !== null) {
const buttons = dropdown.querySelectorAll('li > button.dropdown-item');
for (const button of buttons) {
if (button !== null) {
function handleClick(event: Event) {
if (isSearchButton(event.target)) {
const objectType = event.target.dataset.searchValue;
if (objectType !== '' && selected !== objectType) {
selected = objectType;
selectedValue.innerHTML = button.textContent ?? 'Error';
selectedType.value = objectType;
} else {
selected = '';
selectedType.innerHTML = 'All Objects';
selectedType.value = '';
}
}
}
button.addEventListener('click', handleClick);
}
}
}
}
/**
* Initialize Interface Table Filter Elements.
*/
2021-04-20 09:34:12 -07:00
function initInterfaceFilter() {
for (const input of getElements<HTMLInputElement>('input.interface-filter')) {
const table = findFirstAdjacent<HTMLTableElement>(input, 'table');
const rows = Array.from(
table?.querySelectorAll<HTMLTableRowElement>('tbody > tr') ?? [],
).filter(r => r !== null);
/**
* Filter on-page table by input text.
*/
function handleInput(event: Event) {
const target = event.target as HTMLInputElement;
// Create a regex pattern from the input search text to match against.
const filter = new RegExp(target.value.toLowerCase().trim());
// Each row represents an interface and its attributes.
for (const row of rows) {
// Find the row's checkbox and deselect it, so that it is not accidentally included in form
// submissions.
const checkBox = row.querySelector<HTMLInputElement>('input[type="checkbox"][name="pk"]');
if (checkBox !== null) {
checkBox.checked = false;
}
// The data-name attribute's value contains the interface name.
const name = row.getAttribute('data-name');
if (typeof name === 'string') {
if (filter.test(name.toLowerCase().trim())) {
// If this row matches the search pattern, but is already hidden, unhide it.
if (row.classList.contains('d-none')) {
row.classList.remove('d-none');
}
} else {
// If this row doesn't match the search pattern, hide it.
row.classList.add('d-none');
}
}
}
}
input.addEventListener('keyup', debounce(handleInput, 300));
}
}
function initTableFilter() {
for (const input of getElements<HTMLInputElement>('input.object-filter')) {
// Find the first adjacent table element.
const table = findFirstAdjacent<HTMLTableElement>(input, 'table');
// Build a valid array of <tr/> elements that are children of the adjacent table.
const rows = Array.from(
table?.querySelectorAll<HTMLTableRowElement>('tbody > tr') ?? [],
).filter(r => r !== null);
/**
* Filter table rows by matched input text.
* @param event
*/
function handleInput(event: Event) {
const target = event.target as HTMLInputElement;
// Create a regex pattern from the input search text to match against.
const filter = new RegExp(target.value.toLowerCase().trim());
for (const row of rows) {
// Find the row's checkbox and deselect it, so that it is not accidentally included in form
// submissions.
const checkBox = row.querySelector<HTMLInputElement>('input[type="checkbox"][name="pk"]');
if (checkBox !== null) {
checkBox.checked = false;
}
// Iterate through each row's cell values
for (const value of getRowValues(row)) {
if (filter.test(value.toLowerCase())) {
// If this row matches the search pattern, but is already hidden, unhide it and stop
// iterating through the rest of the cells.
row.classList.remove('d-none');
break;
} else {
// If none of the cells in this row match the search pattern, hide the row.
row.classList.add('d-none');
}
}
}
}
input.addEventListener('keyup', debounce(handleInput, 300));
}
}
2021-04-20 09:34:12 -07:00
export function initSearch() {
for (const func of [initSearchBar, initTableFilter, initInterfaceFilter]) {
2021-04-20 09:34:12 -07:00
func();
}
}