list.js is a lightweight JavaScript library that provides powerful client-side filtering and sorting capabilities for lists of data displayed in HTML tables or unordered lists. It allows you to easily add search, pagination, and advanced filtering functionalities to your web applications without needing a backend solution for these features. list.js operates directly on the DOM, making it efficient and fast, even with large datasets.
list.js can be easily integrated into your project using several methods:
list.min.js
file in your HTML using a <script>
tag.<script src="path/to/list.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/list.js@2/dist/list.min.js"></script>
npm install list.js
Then import it into your JavaScript file:
import List from 'list.js';
This example demonstrates creating a simple list with basic filtering:
<!DOCTYPE html>
<html>
<head>
<title>list.js Example</title>
<script src="https://cdn.jsdelivr.net/npm/list.js@2/dist/list.min.js"></script>
</head>
<body>
<input type="text" id="search" placeholder="Search...">
<ul id="myList"></ul>
<script>
var values = [
name: "Item 1"},
{name: "Item 2"},
{name: "Item 3"}
{;
]
var options = {
valueNames: ['name'] //Specifies which elements to search within
;
}
var list = new List('myList', options, values);
</script>
</body>
</html>
This code creates a searchable list. Typing into the search input will filter the ul
element with the id “myList”, based on the ‘name’ property of the data objects. Remember to replace "https://cdn.jsdelivr.net/npm/list.js@2/dist/list.min.js"
with the correct path if you downloaded the library locally.
The core of list.js is the List
object. It’s created by instantiating the List
class, passing it the ID of the list container (typically a <ul>
or <table>
), options, and optionally, an initial data array. The List
object manages all aspects of the list, including rendering, searching, sorting, and pagination. It exposes methods for manipulating and interacting with the list’s items and data. A typical instantiation looks like this:
const list = new List('myList', {
valueNames: ['name', 'age'], //fields to search
page: 5, //number of items per page
pagination: true // enable pagination
, data); // optional initial data array }
The List
object then provides methods to interact with and manipulate the list data, such as add
, remove
, update
, search
, sort
, etc.
Value Objects: These represent the individual data items in your list. They are plain JavaScript objects, each containing key-value pairs corresponding to the fields in your list. For example, if your list displays names and ages, a value object might look like { name: 'Alice', age: 30 }
.
Item Objects: These are internal objects created by list.js to represent each item in the list’s DOM. They wrap a Value object and provide additional information, such as the associated DOM element and its index within the list. You generally don’t directly interact with Item objects; the List object handles their creation and management. However, methods like list.getItems()
provide access to these.
list.js provides methods to add, remove, and update items within the list:
add(values)
: Adds one or more new items to the list. values
should be an array of Value objects.
remove(values)
: Removes items from the list. values
can be an array of Value objects, or a function that returns true
if an item should be removed.
update(values)
: Updates existing items in the list. values
should be an array of Value objects where each object has a unique identifier (often an ID) that corresponds to existing items. list.js matches these to existing items and updates their values.
get(index)
: Retrieves a single item from the list at the specified index.
list.js allows for powerful searching and filtering using the search()
method. The valueNames
option specified during list initialization determines which fields are searchable. Searching is case-insensitive by default.
.search('Alice'); // searches for 'Alice' in the specified fields
list.search('30'); // searches for '30' in the specified fields
list.search(''); // clears the search list
You can use more advanced search techniques such as regular expressions. See the list.js documentation for more details on advanced filtering options.
Sorting is performed using the sort()
method. You specify the field to sort by and the direction (ascending or descending).
.sort('name', { order: 'asc' }); // Sorts by name in ascending order.
list.sort('age', { order: 'desc' }); // Sorts by age in descending order. list
You can chain multiple sort criteria; list.js will sort by each criteria sequentially. For instance:
.sort('age', { order: 'desc' }, 'name', { order: 'asc' }); // Sort by age descending then by name ascending list
New items are added to the list using the add()
method. This method accepts an array of value objects as an argument. Each value object represents a single item to be added. The structure of the value objects should match the valueNames
defined during list initialization.
const newItem = { name: 'Bob', age: 25 };
.add(newItem); //Adds a single item
list
const newItems = [
name: 'Charlie', age: 30 },
{ name: 'David', age: 28 }
{ ;
].add(newItems); // Adds multiple items list
After adding items, the list is automatically re-rendered to reflect the changes.
Items can be removed using the remove()
method. This method accepts different types of arguments:
An array of value objects: Removes items that match the provided value objects. Matching is based on the entire object; all properties must match.
A filter function: A function that takes a value object as an argument and returns true
if the item should be removed. This allows for more complex removal criteria.
A single value object: Removes the single item that matches exactly the provided value object
const itemToRemove = { name: 'Bob', age: 25 };
.remove(itemToRemove); //Removes one item
list
.remove(function(item) {
listreturn item.age > 30; // Removes items where age is greater than 30
; })
Updating items modifies the values of existing items in the list. The update()
method takes an array of value objects as an argument. Each object must contain at least one unique identifier property (e.g., an id
field) that allows list.js to match it with an existing item. Only the properties present in the update object will be changed; other properties remain untouched.
const updatedItem = { id: 1, name: 'Bob Updated', age: 26 };
.update([updatedItem]); //Updates a single item list
If an id
property is not explicitly defined in valueNames
option, list.js will attempt to match by comparing the whole objects. Ensure that all properties of the object are included in the update if you are not using an id
property.
list.js doesn’t directly provide a method for reordering items in the DOM. However, you can achieve this by manipulating the underlying data array and then calling the update()
method. The update
method will re-render the list based on the new order of the items in the array. If your values have unique identifiers (e.g., an ‘id’ property), this will be the most efficient approach.
// Example assuming your data is in a variable called 'data'
// and data items have an 'id' property for identification
.sort((a, b) => a.name.localeCompare(b.name)); // Sort by name
data.update(data); // Update the list to reflect the reordering list
Pagination divides the list into multiple pages, displaying only a subset of items at a time. Pagination is enabled by setting the page
and pagination
options during list initialization. page
specifies the number of items per page.
const options = {
valueNames: ['name', 'age'],
page: 10, // 10 items per page
pagination: true
;
}
const list = new List('myList', options, data);
list.js automatically generates pagination controls (previous and next buttons). You can customize the appearance and behavior of pagination by using callbacks (see list.js documentation for details on customizing pagination).
list.js allows for highly customized rendering using custom templates. Instead of relying on the default rendering of list items, you can define your own HTML structure using a template function. This function receives an item
object as input (an internal list.js object representing a single item) and should return the HTML string for that item. This template is then used to render each item in the list.
const options = {
valueNames: ['name', 'age'],
item: function(value, index) {
return `<li>
<span class="name">${value.name}</span> -
<span class="age">${value.age}</span>
</li>`;
};
}
const list = new List('myList', options, data);
This replaces the default list item rendering with a custom structure.
list.js is not limited to working with data provided directly during initialization. You can load data from external sources (e.g., JSON APIs, CSV files) and then use the add()
or update()
methods to populate or refresh the list.
fetch('data.json')
.then(response => response.json())
.then(data => {
.add(data);
list; })
This example fetches JSON data and adds it to the list once the data is loaded. Remember to handle potential errors during the fetching process.
list.js can be easily integrated with other JavaScript libraries and frameworks. Since it operates directly on the DOM, it’s generally compatible with most other libraries. For instance, you could use it alongside a framework like React, Vue, or Angular by placing the list within your component and managing the data flow between the library and your application’s state.
list.js provides events that you can listen to in order to react to changes in the list. Common events include:
updated
: Triggered whenever the list is updated (added, removed, or sorted items).searched
: Triggered after a search operation.page
: Triggered when the page changes during pagination..on('updated', function(list) {
listconsole.log('List updated:', list.items);
;
})
.on('searched', function(list) {
listconsole.log('Search complete:', list.matchingItems);
; })
These event handlers receive the List
object as an argument.
While list.js doesn’t have a formal plugin system, its modular design allows you to extend its functionality. You can create custom functions to enhance search, sorting, or filtering capabilities. You might create a function that performs a fuzzy search, adds a custom sorting algorithm, or integrates with a specific data source. These custom functions can be integrated directly into your application code, working alongside the core list.js functionality. See the list.js documentation for examples and best practices on extending functionality.
For optimal search performance with list.js, consider these strategies:
Minimize the number of valueNames
: Only include the fields that absolutely require searching. Including too many fields significantly increases the search time.
Use efficient data structures: If you’re pre-processing your data before providing it to list.js, ensure you’re using data structures that facilitate fast lookups (like maps or sets for specific scenarios). This can improve the speed of filtering and sorting that list.js performs internally.
Pre-filter data (if possible): If you have a very large dataset and only a small portion of it might match a particular search query, consider pre-filtering the data before it’s added to list.js to reduce the load on the client.
Consider using indexes (advanced): For extremely large datasets, explore techniques to create and manage indexes on your data outside of list.js. This is an advanced optimization step requiring a deeper understanding of your data and search patterns. You’ll need to manage these indexes separately and update them whenever the data changes.
Working with large datasets requires careful consideration of performance. Here are some strategies:
Pagination: Always enable pagination (pagination: true
) for large datasets. This prevents rendering thousands of items at once, significantly improving initial load time and responsiveness.
Lazy loading: Instead of loading all data at once, consider loading data in chunks or on demand. This involves fetching data only when needed, such as when the user navigates to a new page or performs a search that requires additional data to be retrieved.
Data virtualization (advanced): For extremely large datasets, explore data virtualization techniques. This involves only rendering the visible portion of the list in the browser and only loading data for the visible items, which dramatically improves perceived performance. This is typically not a feature directly built into list.js but requires custom implementation.
Efficient updates: When updating a large list, avoid making numerous individual calls to add()
or remove()
. Instead, update the underlying data array and then use update()
with the whole updated dataset.
Excessive DOM manipulation is a common cause of performance issues. These are key areas to focus on:
Use update()
effectively: When modifying multiple items, update the entire dataset using the update()
method instead of repeatedly using add()
and remove()
. This minimizes the number of DOM manipulations.
Avoid unnecessary re-renders: If only a small portion of the list has changed, avoid re-rendering the entire list. Implement custom logic that identifies and updates only the necessary parts of the DOM to minimize unnecessary DOM changes.
Optimize your templates: Keep your custom templates (if you use them) concise and efficient. Avoid unnecessary complexity in the template HTML, as this will increase the time it takes to render each list item.
Use fragments (advanced): When creating a lot of new DOM elements, consider using DocumentFragment to perform the manipulation outside the main DOM tree and add the whole structure at once instead of element by element. This is a standard browser optimization technique, not specific to list.js.
List not rendering: Double-check that you’ve correctly included the list.js library in your HTML file and that the path to the library is accurate. Verify that the selector used to instantiate the List
object ('myList'
in many examples) correctly targets your list element in the DOM. Also, ensure that your valueNames
option correctly points to the elements within your list items that should be searched.
Search not working: Ensure that the valueNames
option correctly points to the data attributes used in your list items. Case sensitivity is by default off, but verify that the search terms match the actual data in your items. If you’re using custom templates, make sure the data is correctly accessible within the template. Try a simple search term to rule out complex filtering issues.
Items not updating: Check that your unique identifier(s) are correctly defined and used both in your original dataset and in the update()
method. If you are not using unique identifiers (such as an ‘id’ property), ensure that all properties of each object are identical between the original dataset and the one used in the update()
method for correct matching. If adding items, make sure you are using list.add()
correctly and the valueNames
match your data format.
Pagination not working: Verify that you’ve set both pagination: true
and page
(to a value greater than 0) in your List
options. Ensure that your HTML structure allows for the pagination elements to be properly added by list.js.
Performance issues: If you’re experiencing slow performance, refer to the Performance Optimization section of this manual for best practices. Consider minimizing DOM manipulations and using pagination for large datasets.
Console logging: Use console.log()
statements to inspect the data, the list object itself (console.log(list)
), and the values passed to various list.js methods. This helps track data flow and identify issues with data structures or method arguments.
Browser developer tools: Use your browser’s developer tools (usually accessed by pressing F12) to inspect the DOM, network activity, and the JavaScript console. Examine the HTML structure of your list to ensure it’s correct and that data is rendered appropriately. The console will show any JavaScript errors.
Simplify the code: Temporarily remove complex features (custom templates, advanced filtering) to isolate the problem. This can help you determine if a specific feature is causing the issue.
Check the list.js source code (advanced): In some rare cases, you may need to step through the list.js code itself using a debugger to identify the exact point of failure. This requires some familiarity with JavaScript debugging and the list.js source code.
list.js itself doesn’t throw many explicit errors. Errors usually arise from incorrect usage or from problems with your data or surrounding application code. The browser’s JavaScript console will be your primary tool for identifying errors. Pay close attention to error messages – they often provide clues about the source of the problem.
Consider adding your own error handling within your application code, particularly when dealing with asynchronous operations such as fetching data from external sources. Use try...catch
blocks to gracefully handle potential errors, such as network failures or invalid JSON data, and to prevent unexpected crashes. Provide informative error messages to users if necessary.
This section provides a concise reference for the list.js API. For detailed explanations and examples, refer to the comprehensive documentation available on the official list.js website.
The List
object exposes several methods for manipulating and interacting with the list. Here are some key methods:
add(values)
: Adds one or more new items to the list. values
is an array of value objects.
remove(values)
: Removes items from the list. values
can be an array of value objects, a filter function, or a single value object.
update(values)
: Updates existing items in the list. values
is an array of value objects, each needing a unique identifier for matching.
search(searchString)
: Performs a search on the list based on the provided search string.
sort(sortField, options)
: Sorts the list items based on specified field(s) and order(s).
filter(filterFunction)
: Filters the list items based on a provided filter function.
get(index)
: Returns a specific item at the given index.
getItems()
: Returns all items in the list as an array of Item objects.
matchingItems()
: Returns only the items that match the current search query as an array of Item objects.
on(eventName, callback)
: Attaches an event listener.
off(eventName, callback)
: Detaches an event listener.
clear()
: Removes all items from the list.
The Item
object, returned by list.getItems()
or list.matchingItems()
, provides access to individual list items. Key methods include:
values()
: Returns the value object associated with the item.
el
: Provides direct access to the DOM element representing this item.
list.js triggers several events that you can listen for using the on()
method. Some key events are:
updated
: Fired after items are added, removed, updated, or sorted.
searched
: Fired after a search is performed.
page
: Fired when the page changes during pagination.
The List
object is initialized with options that define its behavior. Key options include:
valueNames
: An array of strings specifying the fields to search within.
item
: A function to generate custom HTML for each list item.
listClass
: The CSS class to be applied to the list element.
searchClass
: The CSS class to be applied to the search input.
sortClass
: The CSS class to be applied to the sort controls (if enabled).
page
: The number of items per page (for pagination).
pagination
: true
to enable pagination, false
otherwise.
insert
: Where to insert new items: 'top'
(default), 'bottom'
, or an index number.
index
: An object with parameters specifying how indexing of data should be handled. This is used for managing and searching lists with large amounts of data. (See official documentation for advanced usage of this.)
Note that many additional options and callbacks exist; consult the official list.js documentation for the complete and up-to-date list of available options and their detailed functionalities.
This section provides examples demonstrating various functionalities of list.js. These examples assume basic familiarity with the API and concepts covered in previous sections. Refer to the official documentation for more comprehensive examples and detailed code explanations.
This example demonstrates basic search and filtering on a list of products:
<input type="text" id="search" placeholder="Search products...">
<ul id="products"></ul>
<script>
const products = [
name: "Product A", category: "Electronics", price: 100 },
{ name: "Product B", category: "Clothing", price: 50 },
{ name: "Product C", category: "Electronics", price: 150 }
{ ;
]
const list = new List('products', {
valueNames: ['name', 'category', 'price']
, products);
}
document.getElementById('search').addEventListener('input', function() {
.search(this.value);
list;
})</script>
Typing into the search input filters the products
list based on name
, category
, and price
.
Advanced filtering allows combining multiple criteria. This example filters products by category and price range:
// ... (previous code) ...
const categoryFilter = 'Electronics';
const minPrice = 100;
const maxPrice = 200;
.filter(function(item) {
listreturn item.values().category === categoryFilter &&
.values().price >= minPrice &&
item.values().price <= maxPrice;
item; })
This filters the list to show only electronics products within the specified price range. You could dynamically update categoryFilter
, minPrice
, and maxPrice
based on user input.
This example demonstrates custom sorting based on price, then by name:
// ... (previous code) ...
.sort('price', {order: 'asc'}, 'name', {order: 'asc'}); list
This sorts the products first by price (ascending) and then by name (ascending) for products with the same price.
Pagination can be easily implemented:
const list = new List('products', {
valueNames: ['name', 'category', 'price'],
page: 5, // 5 items per page
pagination: true
, products); }
For infinite scrolling, you would need to add custom logic to fetch and append additional data to the list as the user scrolls near the bottom. This would involve listening to the scroll
event and making AJAX requests to load more data when appropriate. This is not directly handled by list.js but is achievable with additional code.
list.js integrates seamlessly with forms and user input. You can trigger filtering or sorting based on form submissions or changes in input fields:
// ... (Assuming you have a form with inputs for category and price) ...
document.getElementById('filterForm').addEventListener('submit', function(e) {
.preventDefault();
econst category = document.getElementById('category').value;
const minPrice = document.getElementById('minPrice').value;
const maxPrice = document.getElementById('maxPrice').value;
.filter(function(item) {
listreturn (category === '' || item.values().category === category) &&
=== '' || item.values().price >= minPrice) &&
(minPrice === '' || item.values().price <= maxPrice);
(maxPrice ;
}); })
This example filters the list dynamically based on the user’s selections in the form. Empty input fields are treated as “no filter” conditions. Remember to replace the IDs with those present in your actual form.