Instantly share code, notes, and snippets.
Last active
October 11, 2015 04:57
-
Star
(1)
1
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save hippietrail/3806276 to your computer and use it in GitHub Desktop.
Add a "Related Tags" module to the sidebar for Search results
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Hippietrail's Related Tags for Search | |
// @description Add a "Related Tags" module to the sidebar for Search results | |
// @version 0.15 | |
// @namespace hippietrail | |
// @include http://stackoverflow.com/search* | |
// @include http://meta.stackoverflow.com/search* | |
// @include http://serverfault.com/search* | |
// @include http://meta.serverfault.com/search* | |
// @include http://superuser.com/search* | |
// @include http://meta.superuser.com/search* | |
// @include http://stackapps.com/search* | |
// @include http://*.stackexchange.com/search* | |
// @include http://meta.*.stackexchange.com/search* | |
// ==/UserScript== | |
function main() { | |
'use strict'; | |
var key = '4XJuRcz29Fulfh*9DL4Pug((', | |
searchedTags, | |
$postTags, | |
hash = {}, | |
$relatedModule, | |
$interestingModule, | |
PAGE_SIZE = 20, // we can only send 20 tags to the tag API at a time | |
arrayOfSets = [], | |
tagArray, | |
def; | |
if ($('.search-page').length) { | |
searchedTags = $.makeArray($('.tagged .post-tag').map(function (i, e) { | |
return e.textContent; | |
})); | |
$postTags = $('.tags .post-tag').filter(function () { | |
return searchedTags.indexOf(this.textContent) === -1; | |
}); | |
if ($postTags.length && !$('#search-examples').length) { | |
$postTags.map(function (i, e) { | |
return { tagName: e.textContent, c: e.className }; | |
}).each(function (i, e) { | |
if (hash[e.tagName] !== undefined) { | |
hash[e.tagName].n += 1; | |
} else { | |
hash[e.tagName] = { n: 1, c: e.c }; | |
} | |
}); | |
$relatedModule = $('<div>', { | |
'class': 'module', | |
html: $('<h4>', { | |
id: 'h-related-tags' | |
}).text('Related Tags') | |
}); | |
$interestingModule = $('#interesting-tags'); | |
if ($interestingModule.length) { | |
$relatedModule.insertBefore($interestingModule); | |
} else { | |
$relatedModule.appendTo($('#sidebar')); | |
} | |
Object.keys(hash).sort(function (a, b) { | |
return hash[b].n - hash[a].n; | |
}).forEach(function (tagName) { | |
var queryObject = {}, | |
newHref = window.location.pathname + '?'; | |
// parse current URL's query string into an object | |
window.location.search.substring(1).split('&').forEach(function (e) { | |
var spl = e.split('='); | |
queryObject[decodeURIComponent(spl[0])] = spl[1].split(/\++/).map(function (e) { | |
return decodeURIComponent(e); | |
}); | |
}); | |
// add the tag to a new search query | |
queryObject.q.push('[' + tagName + ']'); | |
// turn query object back into a string | |
newHref += Object.keys(queryObject).map(function (e) { | |
return e + '=' + queryObject[e].map(function (e) { | |
return encodeURIComponent(e); | |
}).join('+'); | |
}).join('&'); | |
$('#h-related-tags').parent().append( | |
$('<a>', { | |
href: newHref, | |
'class': hash[tagName].c, | |
title: 'show questions tagged \'' + tagName + '\'', | |
rel: 'tag' | |
}).text(tagName), | |
( hash[tagName].n > 1 ? $('<span>', { | |
'class': 'item-multiplier', | |
html: $('<span>', { | |
'class': 'item-multiplier-x' | |
}).text('×') | |
}).append( | |
' ', | |
$('<span>', { | |
'class': 'item-multiplier-count' | |
}).text(hash[tagName].n) | |
) : '' ), | |
$('<br>') | |
); | |
}); | |
// now look up how many times each tag is used in the whole site | |
tagArray = Object.keys(hash); | |
def = $.Deferred(); | |
while (tagArray.length) { | |
arrayOfSets.push(tagArray.splice(0, PAGE_SIZE)); | |
} | |
// loop | |
(function () { | |
function getWikis(tagSetNumber) { | |
var ourTags = arrayOfSets[tagSetNumber], | |
tagsParams = { | |
key: key, | |
filter: '!nEU0TvB5f5', // just the 'count' and 'name' fields | |
site: window.location.hostname | |
}, | |
url = 'https://api.stackexchange.com/2.1/tags/' + ourTags.map(function (e) { | |
return encodeURIComponent(e); | |
}).join(';') + '/info', | |
tagsPromise = $.ajax({ | |
url: url, | |
data: $.param(tagsParams), | |
dataType: $.support.cors ? 'json' : 'jsonp' | |
}); | |
tagsPromise.pipe(function (data) { | |
$.each(data.items, function (di, de) { | |
$relatedModule.find('.post-tag:contains("' + de.name + '")').each(function (ri, re) { | |
var $im; | |
if (de.name === re.textContent) { | |
$im = ( de.count > 1 ? $('<span>', { | |
'css': { 'opacity': 7 / 12 }, | |
'class': 'item-multiplier', | |
html: $('<span>', { | |
'class': 'item-multiplier-x' | |
}).text('×') | |
}).append( | |
' ', | |
$('<span>', { | |
'class': 'item-multiplier-count' | |
}).text(de.count) | |
) : '' ); | |
$(re).nextAll('br:first').before($im); | |
} | |
}); | |
}); | |
if (++tagSetNumber < arrayOfSets.length) { | |
getWikis(tagSetNumber); | |
} else { | |
def.resolve(); | |
} | |
}); | |
} | |
getWikis(0); | |
})(); | |
def.then(function () { | |
var questionsParams = { | |
filter: '!mdIpJ69CRB', // just the 'total' field | |
key: key, | |
page: 1, | |
pagesize: 1, | |
site: window.location.hostname | |
}, | |
url = 'https://api.stackexchange.com/2.1/questions', | |
questionsPromise = $.ajax({ | |
url: url, | |
data: $.param(questionsParams), | |
dataType: $.support.cors ? 'json' : 'jsonp' | |
}); | |
questionsPromise.pipe(function (data) { | |
var totalQuestions = data.total, | |
$c = $('#h-related-tags').parent().contents(), | |
s = null, | |
arr = []; | |
$c.each(function (i, e) { | |
var $sl, counts, tf_idf; | |
if (e.tagName === 'A') { | |
s = i; | |
} else if (e.tagName === 'BR') { | |
$sl = $c.slice(s, i + 1); | |
counts = $.makeArray( | |
$sl.find('.item-multiplier-count').map(function () { | |
return parseInt(this.textContent, 10); | |
}) | |
); | |
counts = [1, 1].concat(counts).splice(counts.length, 2); | |
tf_idf = counts[0] * Math.log(totalQuestions / counts[1]); | |
arr.push([$sl].concat(tf_idf, counts[0])); | |
} | |
}); | |
arr.sort(function (a, b) { | |
return b[1] - a[1] || b[2] - a[2]; | |
}).forEach(function (e) { | |
$('#h-related-tags').parent().append(e[0]); | |
}); | |
}); | |
}); | |
} | |
} | |
} | |
function addJsNode(func) { | |
'use strict'; | |
var targ = document.getElementsByTagName('head')[0] || document.body || document.documentElement, | |
scriptNode = document.createElement('script'); | |
scriptNode.type = 'text/javascript'; | |
scriptNode.textContent = '(' + func.toString() + ')()'; | |
targ.appendChild(scriptNode); | |
} | |
addJsNode(main); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment