aboutsummaryrefslogblamecommitdiffstats
path: root/searcher/script.js
blob: e452b5ff1e0ee700feabe833606dda925cc0b2db (plain) (tree)
1
2
3
4
5
6
7

                                                  




                                                                                                                                                      




                               
                                                          
                          





                               

                              































                                                                     
                                                                        
 


                                                                 
                                                                                               






                                                                               
                                                                                                                                            
                                                            
                                          








                                                                                                 
                                                                                                                        

























                                                                                                                    
                                                                                                           









































                                                                                                                                                                                                                                    





                                                                                    


                                             
                                                                                                                              





                                                                                 

                                                                                                                                   








                                                                                                           
                                                                                                                                                   







                                                                             

                                                                       
 
                                                                
















































































                                                                                         
const isNested = Boolean(window.parent != window);

const deprecationStrings = {
	"Active": {Text: "", Class: "hide"},
	"": {Text: "Warning! This chip is being deprecated. It will be broken in the near future, and should not be used.", Class: "depwarn"},
	"Deprecated": {Text: "Warning! This chip is currently deprecated. It is no longer in the palette, and likely does not work.", Class: "depbad"}
};
const fusenameopts = {
	isCaseSensitive: false,
	minMatchCharLength: 1,
	ignoreLocation: true,
	threshold: 0,
	keys: ["ReadonlyPaletteName", "ReadonlyChipName"],
	includeScore: true
};
const fusedescopts = {
	isCaseSensitive: false,
	minMatchCharLength: 1,
	ignoreLocation: true,
	threshold: 0,
	keys: ["Description"],
	includeScore: true
};

function genExplanation(name) {
	return name;
}

function genSearchPath(path, name) {
	const ret = document.createElement("li");
	ret.classList.add("searchpath");
	ret.innerText = path.join("/") + "/" + name;
	return ret;
}

function getChipAddListener(GUID) {
	return function(e) {
		window.parent.postMessage(
			{
				type: 'newChip',
				GUID: GUID
			}
		);
	}
}

var searchresults = [];
var page = 0

window.addEventListener("load", async (e) => {
	const search = document.getElementById("search");
	const form = document.getElementById("form");
	const suggestions = document.getElementById("paletteSearch");

	//if (isNested) document.getElementById("grapherlink").remove();

	if (localStorage.length) {
		form.depr.checked = localStorage.getItem("depr");
		form.beta.checked = localStorage.getItem("beta");
		form.ReadonlyPaletteName.checked = localStorage.getItem("ReadonlyPaletteName");
		form.Description.checked = localStorage.getItem("Description");
		form.refresh.checked = localStorage.getItem("refresh");
		form.fuzziness.value = localStorage.getItem("fuzz");
		form.items.value = localStorage.getItem("items");
		form.filterSug.checked = localStorage.getItem("fsug");
	}

	let v2pr = fetch(/*"https://raw.githubusercontent.com/tyleo-rec/CircuitsV2Resources/master/misc/circuitsv2.json"/*/"/circuits.json")
				   .then(res => res.json());
	let termspr = fetch("/terms.json")
									.then(res => res.json());

	[v2json, termsjson] = await Promise.all([v2pr, termspr]);
	//console.log(v2json, termsjson);

	
	//GUID needs to be in the same object now, because we convert to an array
	const searchable = Object.entries(v2json.Nodes)
		.map(pair => {return {GUID: pair[0], ...pair[1]}})
	searchable.sort((a, b) => (a.ReadonlyPaletteName.toLowerCase() > b.ReadonlyPaletteName.toLowerCase()) ? 1 : -1);

	const fuses = [new Fuse(searchable, fusenameopts),
								 new Fuse(searchable, fusedescopts)];
	
	const filterTree = {nodes: searchable};
	searchable.forEach(chip => {
		chip.NodeFilters.forEach(filter => {
			var currentNode = filterTree;
			filter.FilterPath.forEach(path => {
				if (!currentNode[path.toUpperCase()]) currentNode[path.toUpperCase()] = {nodes: []};
				currentNode = currentNode[path.toUpperCase()]
				if (!currentNode.nodes.includes(chip))currentNode.nodes.push(chip);
				currentNode.actualname = path;
			})
		})
	})

	//console.log(filterTree);

	const redraw = targ => {
		const fuseinuse = fuses.filter(fuse => form[fuse.options.keys[0]].checked);

		start = performance.now();

		localStorage.setItem("depr", form.depr.checked ? "set" : "");
		localStorage.setItem("beta", form.beta.checked ? "set" : "");
		localStorage.setItem("ReadonlyPaletteName", form.ReadonlyPaletteName.checked ? "set" : "");
		localStorage.setItem("Description", form.Description.checked ? "set" : "");
		localStorage.setItem("refresh", form.refresh.checked ? "set" : "");
		localStorage.setItem("fsug", form.filterSug.checked ? "set" : "");
		localStorage.setItem("fuzz", form.fuzziness.value);
		localStorage.setItem("items", form.items.value);

		suggestions.id = form.filterSug.checked ? "paletteSearch" : ""
		
		var content2 = filterTree;

		const fullPath = targ.value.replace(/\\+|\/+/, "/")
													.split("/");
		const startOfPath = fullPath.slice(0, -1);
		const endOfPath = fullPath.at(-1);
		const startOfSuggestion = startOfPath.join('/');

		startOfPath.forEach(path => {
													try {
														content2 = content2[path.toUpperCase()]
													} catch (e) {}
												});
		
		if (!content2) content2 = {nodes: []};

		suggestions.innerText = '';
		suggestions.append(...Object.keys(content2)
																.filter(i => i.toUpperCase() == i)
																.sort((a, b) => (a > b) ? 1 : -1)
																.map(i => {
																	var e = document.createElement('option');
																	e.value = startOfSuggestion + (startOfSuggestion ? '/' : '') + content2[i].actualname + '/';
																	return e;
																})
											)


		fuseinuse.forEach(fuse => {
			fuse.options.minMatchCharLength = Math.floor(endOfPath.length * JSON.parse(form.fuzziness.value).nummod);
			fuse.options.threshold = JSON.parse(form.fuzziness.value).thresh;
			fuse.setCollection(content2.nodes);
		});
		
		var content = endOfPath ? (() => {
			let m = fuseinuse.map(fuse => fuse.search(endOfPath)).flat()
			m.sort((a,b) => a.score - b.score);
			m = Array.from(new Set(m.map(e => e.item)));
			return m;
		})() : content2.nodes;
		//console.log(content2.nodes)
			
		content = content.map(el => {
			if ((form.depr.checked || el.DeprecationStage == "Active") && (form.beta.checked || !el.IsBetaChip)) {
				const ret = newEl("details", "returnedchip");
				if (el.IsBetaChip) ret.classList.add("betaChip");

				const iret = newEl("div", "infocontainer");

				const name = document.createElement("summary");
				name.innerText = el.ReadonlyPaletteName +
					((el.ReadonlyPaletteName == el.ReadonlyChipName) ? "" : ` - aka "${el.ReadonlyChipName}"`);

				const deprinfo = deprecationStrings[el.DeprecationStage];
				const depr = newEl("div", deprinfo.Class);
				depr.innerText = deprinfo.Text;

				const desc = newEl("p", "chipdesc")
				desc.innerText = el.Description == "" ? "No Description!" : el.Description;

				const filters = newEl("ul", "filters")
				filters.append(...Object.values(el.NodeFilters).map(val => genSearchPath(val.FilterPath, el.ReadonlyPaletteName)));

				iret.append(desc, filters);

				const addBtn = newEl('button', 'addBtn');
				addBtn.innerText = "+";
				addBtn.setAttribute('title', 'Add to graph');
				addBtn.onclick = getChipAddListener(el.GUID);
				if (isNested) name.append(addBtn);
				
				let m = generateChipHTML(el.NodeDescs);

				ret.append(depr, name, iret, m);

				return ret;
			}
		}).filter(e => e != undefined);
		var perfstring = `returned in ${parseInt(performance.now() - start)} ms.`
		display(perfstring, content);
	};

	const redrawHandler = e => redraw(search);

	form.addEventListener("submit", e => {console.log(e); e.preventDefault()});
	search.addEventListener("change", redrawHandler);
	form.addEventListener("input", redrawHandler);

	form.refresh.addEventListener("change", e => {
		if (e.target.checked) {
			form.addEventListener("input", redrawHandler);
		} else {
			form.removeEventListener("input", redrawHandler);
		}
	});
	
	try {
		redraw(search);
	} catch (error) {
		setTimeout(() => redraw(search), 1000); 
	}
});

function display(perf, content) {
	searchresults = content;
	page = 0;
	update();
}

function first() {
	page = 0;
	update();
}
function prev() {
	page = Math.max(page - 1, 0);
	update();
}

function next() {
	const pagesize = parseInt(document.getElementById("cfgitems").value);

	page = (((page + 1) * pagesize) > searchresults.length) ? page : (page + 1);
	update();
}

function last() {
	const pagesize = parseInt(document.getElementById("cfgitems").value);

	page = Math.max(parseInt((searchresults.length - 1) / pagesize), 0);
	update();
}


function update() {
	const ndisplay = document.getElementById("pagen");
	const ofdisplay = document.getElementById("of");
	const output = document.getElementById("resultslist");
	const pagesel = document.getElementById("cfgitems");

	//pagesel.value = ;

	const pagesize = pagesel.value == "" ? 1 : Math.max(parseInt(pagesel.value), 1);

	const start = page * pagesize;
	const end   = Math.min(searchresults.length, start + pagesize);

	ndisplay.innerText = page + 1;
	ofdisplay.innerText = parseInt((searchresults.length - 1) / pagesize) + 1;

	//console.log(start, end);

	output.innerHTML = "";
	output.append(...searchresults.slice(start, end));
}