~philipwhite/nix-package-search

2a85f84ec81aae1715c5f65302fca14eecf70379 — Philip White 2 years ago c606a03
Add space-delimited search box with dynamic updating list
2 files changed, 85 insertions(+), 14 deletions(-)

M index.html
M index.js
M index.html => index.html +19 -14
@@ 1,18 1,23 @@
<!DOCTYPE html>

<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Search NixOS packages</title>
  </head>
  <body>
    <h1>Search NixOS packages</h1>
    <p>
      This packages pulls a JSON file describing all the packages for the
      nixos-19.09 channel.
    </p>
    <input type="text" placeholder="search by name or description" />
    <script src="index.js"></script>
  </body>
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Search NixOS packages</title>
	</head>
	<body>
		<h1>Search NixOS packages</h1>
		<p>
			This packages pulls a JSON file describing all the packages for the
			nixos-19.09 channel.
		</p>
		<input
			type="text"
			id="filter-input"
			placeholder="search by name or description"
		/>
		<ul id="packages-list"></ul>
		<script src="index.js"></script>
	</body>
</html>

M index.js => index.js +66 -0
@@ 1,1 1,67 @@
const filter_input = document.getElementById("filter-input");
const packages_list = document.getElementById("packages-list");
console.log("hello world");

// The json object returned from the AJAX request - this is only loaded once per
// page load.
let channel_data = null;

// This is the list of packages that gets displayed on the screen. All major
// work should happen in the background; when it is finished it should update
// this variable and refresh the package list.
let current_packages = {};

function refresh_list() {
	if (channel_data !== null) {
		current_packages = {};
		let package_count = 0;
		for (let package_key in channel_data.packages) {
			let package = channel_data.packages[package_key];
			let filter_items = filter_input.value.split(" ");
			let passed = true;
			for (let filter_item of filter_items) {
				if (
					!(
						package.name.includes(filter_item) ||
						package_key.includes(filter_item) ||
						(package.meta.discription && package.meta.description.includes(filter_item))
					)
				) {
					passed = false;
					break;
				}
			}
			if (passed) {
				current_packages[package_key] = package;
				package_count++;
			}
			if (package_count > 200) {
				break;
			}
		}
		packages_list.innerHTML = "";
		for (let package_key in current_packages) {
			let package = current_packages[package_key];
			let package_div = document.createElement("li");
			package_div.innerHTML = `${package.name} - ${package_key} - ${package.meta.description}`;
			packages_list.appendChild(package_div);
		}
	}
}

let request = new XMLHttpRequest();
request.onreadystatechange = function() {
	if (request.readyState === 4 && request.status === 200) {
		channel_data = JSON.parse(request.responseText);
		console.log("got the data");
		refresh_list();
	}
};

filter_input.addEventListener("keyup", function() {
	console.log(filter_input.value);
	refresh_list();
});

request.open("GET", "packages.json");
request.send(null);