Userscripts.org Better Search

By Cletus Last update Jul 14, 2011 — Installed 4,273 times.

There are 13 previous versions of this script.

// ==UserScript==
// @name			Userscripts.org Better Search
// @namespace		#Cletus
// @description		Allows advanced searching on Userscripts.org without any fussing.
// @copyright		2011+, Ryan Chatham (http://userscripts.org/users/cletus)
// @license			(CC); http://creativecommons.org/licenses/by-nc-sa/3.0/
// @icon			http://www.gravatar.com/avatar.php?gravatar_id=6875e83aa6c563790cb2da914aaba8b3&r=PG&s=48&default=identicon
//
// @require			http://usocheckup.redirectme.net/98575.js
// @require			http://userscripts.org/scripts/source/87345.user.js
// @require			http://userscripts.org/scripts/source/98574.user.js
//
// @include			http://userscripts.org/*
//
// @version			1.1.4
// ==/UserScript==

// Create preferences.
devtools.config.init({
	title: 'Better Search Preferences',
	html: 'Choose the options that you want to filter your search results by. <br/><br/><strong>Note:</strong> Certain options (marked below) will only use one search engine.',
	settings: {
		'titleOnly': {
			type: 'checkbox',
			label: 'Search in title of page only <em>(Google CSE only)</em>',
			defaultValue: false
		},
		'searchLocation': {
			type: 'radio',
			label: 'Search location',
			options: {
				'Everywhere <em>(Google CSE only)</em>': 'all',
				'Scripts': 'scripthome',
				'Source Codes <em>(Google CSE only)</em>': 'scriptsource',
				'Users <em>(UserScripts.org only)</em>': 'user',
				'Blogs <em>(Google CSE only)</em>': 'blog',
				'Groups <em>(Google CSE only)</em>': 'group',
				'Guides <em>(Google CSE only)</em>': 'guide',
				'Reviews <em>(Google CSE only)</em>': 'review',
				'Forums / Discussions': 'topic',
				'Tags': 'tag'
			},
			defaultValue: 'all'
		},
		'searchEngine': {
			type: 'radio',
			label: 'Search engine',
			options: {
				'UserScripts.org': 'uso',
				'Google CSE': 'cse',
			},
			defaultValue: 'cse'
		}
	},
	callback: hookSearch
});

// Create container if it doesn't exists.
var sectionDiv = document.getElementById('section');
if (!sectionDiv) {
	sectionDiv = document.createElement('div');
	sectionDiv.id = 'section';
	var sectionData = grabSectionData();
	sectionDiv.innerHTML =
		'<div class="container">'+
			'<h2>' + sectionData.title + '</h2>'+
			'<p class="subtitle">' + sectionData.subtitle + '</p>'+
		'</div>';
	document.getElementById('root').insertBefore(sectionDiv, document.getElementById('header').nextSibling);
	sectionDiv = document.getElementById('section');
}

// Create form if it doesn't exist.
var searchDiv = document.getElementById('section_search');
if (!searchDiv) {
	searchDiv = document.createElement('div');
	searchDiv.id = 'section_search';
	
	sectionDiv.firstElementChild.insertBefore(searchDiv, sectionDiv.firstElementChild.firstChild);
	searchDiv = document.getElementById('section_search');
}
searchDiv.innerHTML =
	'<form action="/posts/search" method="get">'+
		'<input type="hidden" value="http://userscripts.org/cse.xml" name="cref">'+
		'<input type="hidden" value="FORID:9" name="cof">'+
		'<input type="hidden" value="UTF-8" name="ie">'+
		'<input class="input" name="q" placeholder="Search userscripts.org" title="Search" type="text">'+
		'<input class="go" name="submit" value="" type="submit">'+
	'</form>';

// Settings icon used in the search form.
var gearIcon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALEAAACxABrSO9dQAAAAd0SU1FB9sDCgMvNzTX/8MAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn4iUAAADySURBVChTXZExakJBFEVFTKWNAXt3YBBby6SxzCryC1t70cbSJaiVIU3ICrIAuzSBiIVFAkKKdBrUc/Qpox8Oc/+97zL/z+Ry8WRZVlSyVmAaVMI7ZOeHsApdeIQnWARqPbNqWqhhfMAPrOA/UOuZ1Q4FRB7uwlyzfsJroNaz4EzeQhte4A9m0ISbQK1n5kzbwhK2sIMeFJKDKIRn5szSQgPeo9C5OI3jJ3cic6ahUYZRmBPfkx3M9NxhDLcWHuArzF/WIbQCtZ6FubMW6jCAZ/AYDVP0zJypp3dRwpjCBr4DtV7p+t9Od9InfIP7QN1Ph/evpNRQk7mZ5gAAAABJRU5ErkJggg==';

// Create preferences button.
var prefsButton = document.createElement('div');
prefsButton.className = 'go';
prefsButton.id = 'userscripts_better_search';
prefsButton.setAttribute('style', 'background-image: url(' + gearIcon + '); background-position: center 2px; cursor: pointer; right: 25px;');
searchDiv.firstElementChild.insertBefore(prefsButton, searchDiv.firstElementChild.lastElementChild);

// Add listener to preferences button.
prefsButton.addEventListener('click', function () {
	devtools.config.open();
}, false);

// Add listener to search form.
searchDiv.querySelector('form').addEventListener('submit', function (e) {
	var element = this.querySelector('input[type="text"]');
	if (element.value == '') {
		e.preventDefault();
	}
	else {
		var result = hookSearchSubmit(element.value);
		element.value = result;
	}
}, false);

// Make sure search form is hooked on the initial load.
hookSearch();

// Change some of the styling.
sectionDiv.firstElementChild.style.minHeight = '80px';
searchDiv.querySelector('input[type="text"]').style.width = '255px';
searchDiv.querySelector('input[type="text"]').style.paddingRight = '45px';
window.setTimeout(function () {
	var scriptInstall = document.getElementById('install_script');
	if (scriptInstall) {
		searchDiv.style.top = '5px';
		scriptInstall.style.top = 'auto';
		scriptInstall.style.bottom = '5px';
	}
}, 100);
// Check if 'userscript.org alternate CSS' is running and adjust some styles.
window.setTimeout(function () {
	if (document.querySelector('#header .alt_topbottom')) {
		searchDiv.querySelector('input[type="text"]').style.width = '300px';
		if (scriptInstall) {scriptInstall.style.position = 'absolute';}
	}
}, 100);

// Hooks the search form based on all preferences.
var engine, inUrl;
function hookSearch() {
	// Hide duplicate search form found on /search
	var cseSearch = document.getElementById('cref_iframe_cse-search-box');
	if (cseSearch) {cseSearch.style.display = 'none';}
	var searchForm = searchDiv.querySelector('form');
	// Grab all config settings
	var config = devtools.config.getAll();
	// Start figuring out attributes for the form.
	var action, placeholder, submitName;
	inUrl = false;
	switch (config.searchLocation) {
		case 'scripthome':
			if (config.searchEngine == 'uso') {
				action = '/scripts/search';
				submitName = 'submit';
				placeholder = 'Search Scripts';
				engine = 'uso';
			}
			else {
				action = '/search';
				submitName = 'sa';
				placeholder = 'Search Scripts with Google';
				engine = 'cse';
				inUrl = 'scripts/show';
			}
		break;
		case 'scriptsource':
			action = '/search';
			submitName = 'sa';
			placeholder = 'Search Source Codes with Google';
			engine = 'cse';
			inUrl = 'scripts/review';
		break;
		case 'user':
			action = '/users';
			submitName = 'submit';
			placeholder = 'Search Users';
			engine = 'uso';
		break;
		case 'tag':
			if (config.searchEngine == 'uso') {
				action = '/scripts/search';
				submitName = 'submit';
				placeholder = 'Search Tags';
				engine = 'uso';
			}
			else {
				action = '/search';
				submitName = 'sa';
				placeholder = 'Search Tags with Google';
				engine = 'cse';
				inUrl = 'tags';
			}
		break;
		case 'blog':
			action = '/search';
			submitName = 'sa';
			placeholder = 'Search Blogs with Google';
			engine = 'cse';
			inUrl = 'articles';
		break;
		case 'group':
			action = '/search';
			submitName = 'sa';
			placeholder = 'Search Groups with Google';
			engine = 'cse';
			inUrl = 'groups';
		break;
		case 'guide':
			action = '/search';
			submitName = 'sa';
			placeholder = 'Search Guides with Google';
			engine = 'cse';
			inUrl = 'guides';
		break;
		case 'review':
			action = '/search';
			submitName = 'sa';
			placeholder = 'Search Reviews with Google';
			engine = 'cse';
			inUrl = 'reviews';
		break;
		case 'topic':
			if (config.searchEngine == 'uso') {
				action = '/posts/search';
				submitName = 'submit';
				placeholder = 'Search Forums';
				engine = 'uso';
			}
			else {
				action = '/search';
				submitName = 'sa';
				placeholder = 'Search Forums / Discussions with Google';
				engine = 'cse';
				inUrl = 'topics';
			}
		break;
		default:
			action = '/search';
			submitName = 'sa';
			placeholder = 'Search Everywhere with Google';
			engine = 'cse';
		break;
	}
	searchForm.setAttribute('action', action);
	searchForm.querySelector('input[type="text"]').setAttribute('placeholder', placeholder);
	searchForm.querySelector('input[type="text"]').title = placeholder;
	searchForm.querySelector('input[type="submit"]').setAttribute('name', submitName);
	
	// Show last search term in box.
	var lastSearch = GM_getValue('lastSearch', '');
	if (lastSearch != '') {
		searchForm.querySelector('input[type="text"]').value = lastSearch;
		searchForm.querySelector('input[type="text"]').focus();
	}
	GM_setValue('lastSearch', '');
}

// Hooks the search text when the form submits based on preferences.
function hookSearchSubmit(input) {
	var config = devtools.config.getAll();
	var text = input;
	GM_setValue('lastSearch', input);
	if (engine == 'cse') {
		if (config.titleOnly) {
			text = 'intitle:' + text;
		}
		if (config.searchLocation != 'all') {
			if (inUrl) {
				text += ' inurl:' + inUrl;
			}
		}
	}
	return text;
}

// Grabs current URL then returns an object containing the section data.
// Used when there is no section data.
function grabSectionData() {
	// Get some generic titles and subtitles.
	var genericTitle = document.querySelector('#main > h1'), genericSubtitle = document.querySelector('#main > h1 + p.subtitle');
	if (genericTitle) {genericTitle.style.display = 'none'; genericTitle = genericTitle.innerHTML;} else {genericTitle = '';}
	if (genericSubtitle) {genericSubtitle.style.display = 'none'; genericSubtitle = genericSubtitle.innerHTML;} else {genericSubtitle = '';}
	// Override certain paths' titles and subtitles.
	var paths = {
		'/home': {title: 'Dashboard', subtitle: 'Check out the tabs below'}
	};
	var path = window.location.pathname;
	if (typeof paths[path] != 'undefined') {
		return paths[path];
	}
	return {title: genericTitle, subtitle: genericSubtitle};
}