Sixtest Wiki:API4/SearchSuggest

(function {	"use strict";	// TODO: make reusable	// extension	var extension = $API.create.extension('SearchSuggest'),		// api references		$ui,		$root,		// variables		elements = {},		focus = 0,		// variables		searchResults,		// functions		init,		// event functions		e_onkeyup,		e_onkeydown,		e_onmouseover;	$API.user.edittools = ($API.user.edittools === undefined ? true : $API.user.edittools);	$ui = $API.ui || $API.create.ui;	$root = $ui.query(function (d) { return d.level === 0 && d.ele.className === 'APIRoot'; }, 1);	init = function {		// initialize the extension ... add elements / apply css classes / js properties etc.		if (!extension.initiated) {			// search - main container			elements.main = $root.data[0].child('div');			elements.main.ele.className = 'SearchSuggest';			// search - left container (item view box)			elements.left = elements.main.child('div');			elements.left.ele.className = 'SearchSuggestLeft';			// search - right container (search results box)			elements.right = elements.main.child('div');			elements.right.ele.className = 'SearchSuggestRight';			// search - left - input box			elements.input = elements.left.child('input');			elements.input.ele.className = 'SearchSuggest_Input';			// search - left - search suggestions			elements.output = elements.left.child('div'); elements.output.ele.className = 'SearchSuggest_Output'; // search - right - display elements.display = elements.right.child('div'); elements.display.ele.className = 'SearchSuggest_Display'; // events for search suggestion / browsing elements.input.ele.onkeyup = e_onkeyup(elements.input, elements.output, "all"); elements.input.ele.onkeydown = e_onkeydown(elements.input, elements.output, "all"); elements.output.ele.onmouseover = e_onmouseover(elements.input, elements.output, "all"); // css $API.create.stylesheet('/Item/css'); }		// set initiated = true so this won't be rerun return true; };	/* Search suggestion function */ extension.searchSuggest = function (element, target, dataType, amount) { var re, i, len, dataobj; // if element/target is undefined, use the defaults element = element || elements.input; target = target || elements.output; dataType = dataType || 'all'; amount = amount || 10; function addSuggestion(name) { // name - item to suggest var e = target.child('div'); e.ele.appendChild(document.createTextNode(name)); }		// regex to search re = (element.value === undefined ? element.ele.value : element.value).toLowerCase; // clear search suggestion box from last time while (target.ele.hasChildNodes) { target.ele.removeChild(target.ele.lastChild); }		// reset the focus or it may bug upon search focus = 0; if (dataType === 'all' && $API.data.all === undefined) { // merge all data... $API.data.merge; }		// the data we are searching: default to "all" dataobj = $API.data[dataType] || $API.data.all; searchResults = dataobj.query(function (d) {			// get results from regex			var name = d.name.toLowerCase;			return name.match(re);		}, amount).data; for (i = 0, len = searchResults.length; i < len; i += 1) { addSuggestion(searchResults[i].name, target); }	};	extension.displayItem = function (id) { var item, property, strOut = '', tools, toggleTools, edit; toggleTools = function { var banned = $API.user.banned, active = $API.user.edittools; if (!elements.display.ele.children.length || !elements.edittools.ele.children.length) { // does this cause memory leak? shouldn't ... elements.edittools = elements.display.child('div'); elements.edittoolsActive = elements.edittools.child('img'); elements.edittoolsMain = elements.edittools.child('div'); elements.edittoolsPublish = elements.edittoolsMain.child('div'); elements.edittoolsPublishLink = elements.edittoolsPublish.child('a'); elements.edittoolsPublishLink.ele.appendChild(document.createTextNode('Publish')); } else { $API.user.edittools = active = !active; }			$(elements.display.ele).removeClass('edittools-' + (!(active && !banned) ? 'enabled' : 'disabled')); $(elements.display.ele).addClass('edittools-' + (active && !banned ? 'enabled' : 'disabled')); elements.edittools.ele.className = 'toolbox'; elements.edittoolsMain.ele.className = 'edittools'; elements.edittoolsPublish.ele.className = 'edittoolspublish'; elements.edittoolsActive.ele.title = "Edit tools are " + (active && !banned ? 'enabled' : 'disabled') + "." + (banned ? "" : " Click to toggle."); elements.edittoolsActive.ele.src = (banned ? 'http://images.wikia.com/sixtest/images/f/f0/Tools-Banned.png' : (active ? 'http://images.wikia.com/sixtest/images/d/d3/Tools-Active.png' : 'http://images.wikia.com/sixtest/images/6/69/Tools-Inactive.png')); elements.edittoolsPublishLink.ele.onclick = (active && !banned ? $API.ext.Edit.submit : null); elements.edittoolsPublishLink.ele.title = (active && !banned ? "Submit all the data you have changed this session." : ''); };		if (typeof id === 'string') { item = $API.data.item.query(function (data) {				return data.name === id;			}).data[0]; } else if (typeof id === 'number') { item = searchResults[id]; }		if (item !== undefined) { // first remove existing items if any have been requested if (elements.display === undefined) { elements.display = elements.main.child('div'); //elements.display.ele.className = 'SearchSuggest_Display'; }			// clear the DOM of child elements // to prevent memory leak, destroy their associated objects by clearing all references ($API.data.ui, [parent].children) elements.display.destroy; // search - right - edittools toggleTools; elements.edittoolsActive.ele.onclick = toggleTools; if (item && item.dataType && $API.ext[item.dataType] && $API.ext[item.dataType].layout) { $API.ext[item.dataType].layout(item, elements.display); }		}	};	extension.listFocus = function (target, offset) { var children = (target || elements.output).ele.children, focusElement = children[focus]; focusElement.className = ''; if (typeof offset === 'number') { focus = (focus + offset + children.length) % children.length; }		focusElement = children[focus]; focusElement.className = 'SSactive'; extension.displayItem(focus); };	e_onkeydown = function (element, target, type, amount) { element = element || elements.output; target = target || elements.output; return function (e) { var rtn; if (e.keyCode === 40) { rtn = extension.listFocus(target, +1); } else if (e.keyCode === 38) { rtn = extension.listFocus(target, -1); } else { rtn = extension.searchSuggest(element, target, type, amount); }			return rtn; };	};	e_onmouseover = function (element, target, type, amount, display) { element = element || elements.input.ele; target = target || elements.output; display = display !== false; return function (e) { var hoverElement = e.srcElement || e.originalTarget, i = 0, children = target.ele.children, childrenLen = children.length; for (i; i < childrenLen; i += 1) { if (children[i] === hoverElement) { children[focus].className = ''; focus = i;					children[focus].className = 'SSactive'; if (display) { extension.displayItem(focus); } else { element.value = hoverElement.childNodes[0].data; }					return true; }			}			return false; };	};	e_onkeyup = function (element, target, type, amount) { element = element || elements.output; target = target || elements.output; return function (e) { var rtn = false; if (e.keyCode !== 40 && e.keyCode !== 38) { rtn = extension.searchSuggest(element, target, type, amount); }			return rtn; };	};	extension.employ = function (element, target, type, amount) { // attaches an instance of the search suggest function // i.e. the mouse / key events and suggestions var val = element.value || element.ele.value; type = type || 'all'; element = element.ele || element; element.onkeyup = e_onkeyup(element, target, type, amount); element.onkeydown = e_onkeydown(element, target, type, amount); target.ele.onmouseover = e_onmouseover(element, target, type, amount, false); };	extension.initialized = extension.initialized || init; });