Skip to content

Instantly share code, notes, and snippets.

@poke
Last active March 12, 2019 20:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save poke/9058895 to your computer and use it in GitHub Desktop.
Save poke/9058895 to your computer and use it in GitHub Desktop.
[User script] StackExchange Election: Primary counter – Support on Stack Apps: http://stackapps.com/questions/4548
// ==UserScript==
// @id stackexchange-election-primary-counter@poke
// @name StackExchange Election: Primary counter
// @namespace poke
// @version 1.5.2
// @author Patrick Westerhoff
// @match *://*.stackoverflow.com/election*
// @match *://*.stackexchange.com/election*
// @match *://*.askubuntu.com/election*
// @match *://*.mathoverflow.net/election*
// @match *://*.serverfault.com/election*
// @match *://*.stackapps.com/election*
// @match *://*.superuser.com/election*
// @updateURL https://gist.githubusercontent.com/poke/9058895/raw/stackexchange-election-primary-counter.user.js
// @run-at document-end
// ==/UserScript==
(function () {
var primaryLink = document.querySelector('#tabs > a[href$="primary"]');
if (!primaryLink || !primaryLink.classList.contains('youarehere'))
return;
function addRow (table, cols, isHeader) {
var row = document.createElement('tr');
cols.forEach(function (cell) {
if (typeof cell !== 'object') {
cell = document.createTextNode(cell);
}
row.appendChild(document.createElement(isHeader ? 'th' : 'td')).appendChild(cell);
});
return table.appendChild(row);
}
// styles
var style = document.createElement('style');
style.textContent = '#_primary-counter { border: 1px solid silver; margin-bottom: 1em;}' +
'#_primary-counter th { border-bottom: 1px solid silver; }' +
'#_primary-counter td, #_primary-counter th { padding: 1px .5em; }' +
'#_primary-counter tr :nth-child(n+3) { text-align: right; }' +
'#_primary-counter tr:nth-child(11) { border-bottom: 1px solid silver; }' +
'#_primary-counter tr.withdrawn { color: #999; }';
document.head.appendChild(style);
// query candidate data
var users = Array.prototype.map.call(document.querySelectorAll('#mainbar .candidate-row'), function (post) {
var scores = post.querySelector('.candidate-score-breakdown');
return {
name: post.querySelector('.owner .user-info .user-details > a').textContent,
id: post.id.substr(5),
href: '#' + post.id,
votes: parseInt(post.querySelector('.votecell .js-vote-count').textContent, 10),
score: scores.querySelector('b').textContent.match(/(\d+\/\d+)/)[1],
rep: scores.querySelector('ul > li:nth-child(1)').textContent.trim().match(/reputation (.+)/)[1],
modBadges: scores.querySelector('ul > li:nth-child(2)').textContent.match(/moderation badges: (\d)\/\d/)[1],
editBadges: scores.querySelector('ul > li:nth-child(3)').textContent.match(/editing badges: (\d)\/\d/)[1],
participationBadges: scores.querySelector('ul > li:nth-child(4)').textContent.match(/participation badges: (\d)\/\d/)[1],
memberFor: post.querySelector('.user-details').lastChild.textContent.trim().match(/member for (.+)/)[1],
withdrawn: !!post.querySelector('.withdraw-date')
};
});
users.sort(function (a, b) { return b.votes - a.votes; });
// vote count querying
var mayQueryVoteCounts = document.body.innerHTML.includes('StackExchange.vote.election_init(true');
function queryVoteCounts (evt) {
evt.preventDefault();
var xhr = new XMLHttpRequest();
xhr.open('get', '/posts/' + this.id + '/vote-counts?_=' + (+new Date()), true);
xhr.onload = function () {
if (this.status == 200) {
var data = JSON.parse(this.response);
evt.target.parentNode.innerHTML = '+' + (+Math.abs(data.up)) + ' / ' + (-Math.abs(data.down));
}
};
xhr.send(null);
}
// display data
var table = document.createElement('table');
table.id = '_primary-counter';
addRow(table, ['#', 'User', 'Votes', 'Score', 'Reputation', 'Badges (M/E/P)', 'Member for'], true);
users.forEach(function (user, index) {
var link = document.createElement('a')
link.href = user.href;
link.appendChild(document.createTextNode(user.name));
var votes;
if (mayQueryVoteCounts) {
votes = document.createElement('a');
votes.addEventListener('click', queryVoteCounts.bind(user));
}
else {
votes = document.createElement('span');
}
votes.appendChild(document.createTextNode(user.votes));
var badges = [user.modBadges, user.editBadges, user.participationBadges].join(' / ');
var row = addRow(table, [index + 1, link, votes, user.score, user.rep, badges, user.memberFor]);
row.className = user.withdrawn ? 'withdrawn' : '';
});
document.querySelector('.question-status').appendChild(table);
})();
@samliew
Copy link

samliew commented Mar 5, 2019

'.votecell .vote-count-post' needs to be changed to '.votecell .js-vote-count' for the new post layout on L45

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment