// ==UserScript== | |
// @name SE Extra, Optional Features | |
// @namespace http://stackexchange.com/users/4337810/%E1%B9%A7%D0%BD%CA%8A%C3%9F | |
// @version 0.6.1 | |
// @description Adds a bunch of optional 'features' to the StackExchange sites. | |
// @author ṧнʊß (http://stackexchange.com/users/4337810/%E1%B9%A7%D0%BD%CA%8A%C3%9F) | |
// @match *://*.stackexchange.com/* | |
// @match *://*.stackoverflow.com/* | |
// @match *://*.superuser.com/* | |
// @match *://*.serverfault.com/* | |
// @match *://*.askubuntu.com/* | |
// @match *://*.stackapps.com/* | |
// @match *://*.mathoverflow.net/* | |
// @require https://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js | |
// @require https://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js | |
// @require https://cdn.rawgit.com/timdown/rangyinputs/master/rangyinputs-jquery-src.js | |
// @require https://cdn.rawgit.com/jeresig/jquery.hotkeys/master/jquery.hotkeys.js | |
// @grant GM_setValue | |
// @grant GM_getValue | |
// @grant GM_deleteValue | |
// @updateURL https://gist.github.com/shu8/daae9127fa0fe06d5e4d/raw/67668665eeda766f03e70b02fa6ac3901ccf620a/features.user.js | |
// ==/UserScript== | |
var functionsToCall = { //ALL the functions must go in here | |
grayOutVotes: function () { // For graying out votes AND vote count: | |
//alert('gray out votes'); | |
if ($('.deleted-answer').length) { | |
$('.deleted-answer .vote-down-off, .deleted-answer .vote-up-off, .deleted-answer .vote-count-post').css('opacity', '0.5'); | |
} | |
}, | |
moveBounty: function () { // For moving bounty to the top: | |
//alert('move bounty'); | |
if ($('.bounty-notification').length) { | |
$('.bounty-notification').insertAfter('.question .fw'); | |
$('.question .bounty-notification .votecell').remove(); | |
} | |
}, | |
dragBounty: function () { // For draggable bounty window: | |
//alert('draggable'); | |
$('.bounty-notification').click(function () { | |
setTimeout(function () { | |
$('#start-bounty-popup').draggable().css('cursor', 'move'); | |
}, 50); | |
}); | |
}, | |
renameChat: function () { // For renaming Chat tabs: | |
//alert('rename chat'); | |
if (window.location.href.indexOf('chat') > -1) { | |
document.title = 'Chat - ' + document.title; | |
} | |
}, | |
exclaim: function () { // For remvoving exclamation mark: | |
//alert('exclaim'); | |
var old = $("td.comment-actions > div > div > div.message-text"); | |
var newText = old.text().replace("!", "."); | |
old.html(newText); | |
}, | |
employeeStar: function () { // For looking for employees: | |
//alert('employee'); | |
var employees = ["Jeff Atwood", "Joel Spolsky", "Jarrod Dixon", "Geoff Dalgas", "David Fullerton", "Korneel Bouman", "Robert Cartaino", "Kevin Montrose", | |
"MandyK", "Marc Gravell", "balpha", "Matt Sherman", "Danny Miller", "Jason Punyon", "NickC", "Kyle Brandt", "Jin", "Tall Jeff", "Zypher", | |
"Nick Craver", "Nick Larsen", "Shog9", "Greg", "Alex Miller", "GuyZee", "abby hairboat", "samthebrand", "Laura", "Grace Note", "Dimitar Stanimiroff", | |
"Hammer", "Peter Grace", "Charles", "Anna Lear", "stevvve", "Bethany", "Andrew17", "Kizzle", "Jay", "mjibson", "Stefan Schwarzgruber", "Will Cole", "Sean Bave", | |
"Robyn", "Bart Silverstrim", "Jaydles", "Maxwell Applebaum", "Snails", "Jordan Conner", "Bodhi", "cashenhu", "rb4", "Maurbawlz", "CMartin", "Joe Humphries", "Max", | |
"Oded", "Val Perez", "rossipedia", "Derek Still", "Tim Post", "Paul", "PDePree", "Sklivvz", "Todd Jenkins", "Jim Egan", "Kaziorex", "Ben Collins", "TomOnTime", "Dr.D", | |
"David", "Sara Rayman", "Monika P", "Prefontaine", "m0sa", "Jon Ericson", "Juice", "Tania", "Angela", "Hynes", "Kasra Rahjerdi", "Gabe", "Bret Copeland", "Arie Litovsky", | |
"Pops", "Megan Spaans", "Whitney Dwyer", "Philip Camillo", "onesysadmin", "Aurelien Gasser", "Alyssa Tomback", "Alex Cresswell", "couchand", "Brian Nickel", "Princess", | |
"Yaakov Ellis", "Ana Hevesi", "Noureddine Latrech", "Hertz", "Jill Ciaccia", "Tobias Schmidt", "Jon Chan", "Johanna Perrin", "Kristian Bright", "John LeClerc", | |
"Rob Dandorph", "Jessica Genther", "Courtny Cotten", "Stephanie", "Sean Durkin", "rla4", "Alex Warren", "Jaime Kronick", "Alexa", "Samuel Rouayrenc", "Josh Helfgott", | |
"Peter Tarr", "Shane Madden", "Nextraztus", "G-Wiz", "Dan O'Boyle", "yolovolo", "Griffin Sandberg", "ODB", "Mark Villarreal", "Lowell Gruman Jr.", "bweber", "Natalie How", | |
"Haney", "jmac", "Emmanuel Andem-Ewa", "Jess Pardue", "Dean Ward", "Steve Trout", "Nicholas Chabanovsky", "Kelli Ward", "Noah Neuman", "Lauren Roemer", "Heidi Hays", | |
"Joe Wilkie", "Mackenzie Ralston"]; | |
$('.comment, .deleted-answer-info, .employee-name, .started, .user-details').each(function () { //normal comments, deleted answers (deleted by), SE.com/about, question feed users, question/answer/edit owners | |
var $divtext = $(this); | |
$.each(employees, function (index, value) { | |
if ($divtext.find('a[href*="/users"]').html() == value) { | |
$divtext.find('a[href*="/users"]').append('<span class="mod-flair" title="possible employee">⋆</span>'); | |
} | |
}); | |
}); | |
}, | |
bulletReplace: function () { // For replacing disclosure bullets with normal ones: | |
//alert('bullets'); | |
$('.dingus').each(function () { | |
$(this).html('●'); | |
}); | |
}, | |
addEllipsis: function () { // For adding ellipsis to long names: | |
//alert('ellipsis'); | |
$('.user-info .user-details').css('text-overflow', 'ellipsis'); | |
}, | |
moveCommentsLink: function () { // For adding the 'show x more comments' link before the commnents: | |
//alert('comments link'); | |
$('.js-show-link.comments-link').each(function () { | |
var $this2 = $(this); | |
$("<tr><td></td><td>" + $this2.outerHTML() + "</td></tr>").insertBefore($(this).parent().closest('tr')).click(function () { | |
$(this).hide(); | |
}); | |
}); | |
}, | |
unHideAnswer: function () { | |
//alert('downvoted answer'); | |
$(".downvoted-answer").hover(function () { | |
$(this).removeClass("downvoted-answer"); | |
}, function () { | |
$(this).addClass("downvoted-answer"); | |
}); | |
}, | |
fixedTopbar: function () { | |
//alert('topbar'); | |
$('.topbar').css({ | |
'position': 'fixed', | |
'z-index': '1' | |
}); | |
}, | |
highlightQuestions: function() { | |
setTimeout(function() { //Need delay to make sure the CSS is applied | |
//alert('highlight alternative'); | |
if (window.location.href.indexOf('superuser') > -1) { //superuser | |
var betterCSS = { | |
backgroundColor: '#a1eaff', | |
color: 'black' | |
}; | |
} | |
else if (window.location.href.indexOf('stackoverflow') > -1) { //stackoverflow | |
var betterCSS = { | |
backgroundColor: '#ffefc6', | |
borderWidth: '0' | |
}; | |
} | |
else {//if (window.location.href.indexOf('.stackexchange.com') > -1) { | |
//if (window.location.href.indexOf('meta') === -1) { //beta sites | |
var betterCSS = { | |
backgroundColor: '#c3dafa', | |
borderWidth: '0' | |
}; | |
//} | |
} | |
var interestingTagsDiv = $("#interestingTags").text(); | |
var interesting = interestingTagsDiv.split(' '); | |
interesting.pop(); //Because there's one extra value at the end | |
$(".tagged-interesting > .summary > .tags > .post-tag").filter(function(index) { | |
return interesting.indexOf($(this).text()) > -1; | |
}).css(betterCSS); | |
$(".tagged-interesting").removeClass("tagged-interesting"); | |
}, 100); | |
}, | |
displayName: function() { | |
//alert('display name'); | |
var uname = $('.gravatar-wrapper-24').attr('title'); | |
var insertme = "<span class='reputation links-container' style='color:white;' title='"+uname+"'>"+uname+"</span>"; | |
$(insertme).insertBefore('.gravatar-wrapper-24'); | |
}, | |
colorAnswerer: function() { | |
//alert('color answerer comments'); | |
$('.answercell').each(function(i, obj) { | |
var x = $(this).find('.user-details a').text(); | |
$('.answer .comment-user').each(function() { | |
if ($(this).text() == x) { | |
$(this).css('background-color', 'orange'); | |
} | |
}); | |
}); | |
$('.js-show-link.comments-link').click(function() { //Keep CSS when 'show x more comments' is clicked | |
setTimeout(function() { | |
functionsToCall.colorAnswerer(); | |
}, 500); | |
}); | |
}, | |
addBullets: function() { | |
var list = '- ' + $('[id^="wmd-input"]').getSelection().text.split('\n').join('\n- '); | |
$('[id^="wmd-input"]').replaceSelectedText(list); | |
}, | |
addKbd: function() { | |
$('[id^="wmd-input"]').surroundSelectedText("<kbd>", "</kbd>"); | |
}, | |
kbdAndBullets: function() { | |
//alert('add kbd and list options'); | |
var kbdBtn = $('<button/>', { | |
text: '<>', | |
class: 'wmd-button', | |
click: function (e) { | |
e.preventDefault(); | |
functionsToCall.addKbd(); | |
} | |
}).css('left', '400px'); | |
var listBtn = $('<button/>', { | |
text: '-', | |
class: 'wmd-button', | |
click: function (e) { | |
e.preventDefault(); | |
functionsToCall.addBullets(); | |
} | |
}).css('left', '425px'); | |
setTimeout(function() { | |
$('[id^="wmd-redo-button"]').after(kbdBtn); | |
$('[id^="wmd-redo-button"]').after(listBtn); | |
}, 500); | |
$('[id^="wmd-input"]').bind('keydown', 'alt+l', function () { | |
functionsToCall.addBullets(); | |
}); | |
$('[id^="wmd-input"]').bind('keydown', 'alt+k', function () { | |
functionsToCall.addKbd(); | |
}); | |
}, | |
addCheckboxes: function() { | |
$('#reasons').remove(); //remove the div containing everything, we're going to add/remove stuff now: | |
if ($('[class^="inline-editor"]').length < 0) { //if there is no inline editor, do nothing | |
; | |
} else if (window.location.href.indexOf('/edit') > -1 || $('[class^="inline-editor"]').length > 0) { //everything else | |
$('.form-submit').before('<div id="reasons"></div>'); | |
$.each(JSON.parse(GM_getValue('editReasons')), function (i, obj) { | |
$('#reasons').append('<label><input type="checkbox" value="' + this[1] + '"</input>' + this[0] + '</label> '); | |
}); | |
$('#reasons input[type="checkbox"]').css('vertical-align', '-2px'); | |
$('#reasons label').hover(function () { | |
$(this).css({ //on hover | |
'background-color': 'gray', | |
'color': 'white' | |
}); | |
}, function () { | |
$(this).css({ //on un-hover | |
'background-color': 'white', | |
'color': 'inherit' | |
}); | |
}); | |
var editCommentField = $('[id^="edit-comment"]'); | |
$('#reasons input[type="checkbox"]').change(function () { | |
if (this.checked) { //Add it to the summary | |
if (editCommentField.val() == '') { | |
editCommentField.val(editCommentField.val() + $(this).val().replace(/on$/g, '')); | |
} else { | |
editCommentField.val(editCommentField.val() + '; ' + $(this).val().replace(/on$/g, '')); | |
} | |
var newEditComment = editCommentField.val(); //Remove the last space and last semicolon | |
editCommentField.val(newEditComment).focus(); | |
} else if (!this.checked) { //Remove it from the summary | |
editCommentField.val(editCommentField.val().replace($(this).val() + '; ', '')); //for middle/beginning values | |
editCommentField.val(editCommentField.val().replace($(this).val(), '')); //for last value | |
} | |
}); | |
} | |
}, | |
displayDeleteValues: function() { //Display the items from list and add buttons to delete them | |
$('#currentValues').html(' '); | |
$.each(JSON.parse(GM_getValue('editReasons')), function (i, obj) { | |
$('#currentValues').append(this[0] + ' - ' + this[1] + '<input type="button" id="' + i + '" value="Delete"><br />'); | |
}); | |
functionsToCall.addCheckboxes(); | |
}, | |
editComment: function() { | |
//alert('edit comment'); | |
var cssForDiv = { | |
'display': 'inline-block', | |
'position': 'fixed', | |
'width': '500px', | |
'top': '10px', | |
'left': '50%', | |
'z-index': '2', | |
'margin-left': '-250px', | |
'background-color': 'gray', | |
'color': 'white', | |
'-webkit-border-radius': '15px', | |
'-moz-border-radius': '15px', | |
'border-radius': '15px', | |
'text-align': 'center' | |
}; | |
var div = "<div id='dialogEditReasons'><span id='closeDialogEditReasons' style='float:right;'>Close</span><span id='resetEditReasons' style='float:left;'>Reset</span> \ | |
<h2>View/Remove Edit Reasons</h2> \ | |
<div id='currentValues'></div> \ | |
<br /> \ | |
<h3>Add a custom reason</h3> \ | |
Display Reason: <input type='text' id='displayReason'> \ | |
<br /> \ | |
Actual Reason: <input type='text' id='actualReason'> \ | |
<br /> \ | |
<input type='button' id='submitUpdate' value='Submit'> \ | |
</div>"; | |
$('body').append(div); | |
$('#dialogEditReasons').css(cssForDiv).draggable().hide(); | |
$('#closeDialogEditReasons').css('cursor', 'pointer').click(function () { | |
$(this).parent().hide(500); | |
}); | |
$('#resetEditReasons').css('cursor', 'pointer').click(function () { | |
var options = [ //Edit these to change the default settings | |
['formatting', 'Improved Formatting'], | |
['spelling', 'Corrected Spelling'], | |
['grammar', 'Fixed grammar'], | |
['greetings', 'Removed thanks/greetings'] | |
]; | |
if (confirm('Are you sure you want to reset the settings to Formatting, Spelling, Grammar and Greetings')) { | |
GM_setValue('editReasons', JSON.stringify(options)); | |
alert('Reset options to default. Refreshing...'); | |
location.reload(); | |
} | |
}); | |
if (GM_getValue('editReasons', -1) == -1) { //If settings haven't been set | |
$('#dialogEditReasons').show(); //Show the dialog | |
} else { | |
var options = JSON.parse(GM_getValue('editReasons')); //If they have, get the options | |
} | |
$('#dialogEditReasons').on('click', 'input[value="Delete"]', function () { //Click handler to delete when delete button is pressed | |
var delMe = $(this).attr('id'); | |
options.splice(delMe, 1); //actually delete it | |
GM_setValue('editReasons', JSON.stringify(options)); //save it | |
functionsToCall.displayDeleteValues(); //display the items again (update them) | |
}); | |
$('#submitUpdate').click(function () { //Click handler to update the array with custom value | |
if ($('#displayReason').val() == '' || $('#actualReason').val() == '') { | |
alert('Please enter something in both the textboxes!'); | |
} else { | |
var arrayToAdd = [$('#displayReason').val(), $('#actualReason').val()]; | |
options.push(arrayToAdd); //actually add the value to array | |
functionsToCall.displayDeleteValues(); //display the items again (update them) | |
GM_setValue('editReasons', JSON.stringify(options)); //Save the value | |
} | |
}); | |
setTimeout(function() { | |
functionsToCall.addCheckboxes(); | |
//Add the button to update and view the values in the help menu: | |
$('.topbar-dialog.help-dialog.js-help-dialog > .modal-content ul').append("<li><a href='javascript:void(0)' id='editReasonsLink'>Edit Reasons \ | |
<span class='item-summary'>Edit your personal edit reasons for SE sites</span></a></li>"); | |
$('#editReasonsLink').click(function () { | |
functionsToCall.displayDeleteValues(); | |
$('#dialogEditReasons').show(500); //Show the dialog to view and update values | |
}); | |
}, 500); | |
$('.post-menu > .edit-post').click(function () { | |
setTimeout(function () { | |
functionsToCall.addCheckboxes(); | |
}, 500); | |
}); | |
}, | |
shareLinksMarkdown: function() { | |
//alert('change share value') | |
$('.short-link').click(function() { | |
setTimeout(function() { | |
$('.share-tip input').val('[' + $('#question-header a').html() + '](' + document.URL + ')'); | |
}, 500); | |
}); | |
}, | |
commentShortcuts: function() { | |
$('.js-add-link.comments-link').click(function() { | |
setTimeout(function() { | |
$('.comments textarea').bind('keydown', 'ctrl+k', function(e) { | |
e.preventDefault(); | |
$(this).surroundSelectedText('`', '`'); | |
}); | |
$('.comments textarea').bind('keydown', 'ctrl+i', function(e) { | |
e.preventDefault(); | |
$(this).surroundSelectedText('*', '*'); | |
}); | |
$('.comments textarea').bind('keydown', 'ctrl+b', function(e) { | |
e.preventDefault(); | |
$(this).surroundSelectedText('**', '**'); | |
}); | |
}, 200); | |
}); | |
}, | |
unspoil: function() { | |
$('#answers div[id*="answer"], div[id*="question"]').each(function() { | |
$(this).find('.post-menu').append('<span class="lsep">|</span><a id="showSpoiler-' + $(this).attr("id") + '" href="javascript:void(0)">unspoil</span>'); | |
}); | |
$('a[id*="showSpoiler"]').click(function() { | |
var x = $(this).attr('id').split(/-(.+)?/)[1]; | |
$('#'+x+' .spoiler').removeClass('spoiler'); | |
}); | |
} | |
}; | |
// Format for options below: <label><input type='checkbox' id='id'>Text</label><br /> | |
var div = "<div id=featureGMOptions style='display:inline-block; position:fixed; top:10px; left:50%; width:500px; margin-left:-250px; z-index:2; background-color:gray; color:white; padding:10px; border-radius:15px; text-align:left'>\ | |
<span id='closeFeature' style='float:right;'>Close</span> <span id='resetFeature' style='float:right;'>Reset </span> <span id='featureTitle'><h2>Extra Feature Options</h2></span> \ | |
<label><input type='checkbox' id='grayOutVotes'/> Gray out deleted votes</label> <br /> \ | |
<label><input type='checkbox' id='moveBounty'/> Move 'start bounty' to top</label> <br /> \ | |
<label><input type='checkbox' id='dragBounty'/> Make bounty box draggable</label> <br /> \ | |
<label><input type='checkbox' id='renameChat'/> Prepend 'Chat - ' to chat tabs' titles</label> <br /> \ | |
<label><input type='checkbox' id='exclaim'/> Remove exclamation mark on message</label> <br /> \ | |
<label><input type='checkbox' id='employeeStar'/> Add star after employee names</label> <br /> \ | |
<label><input type='checkbox' id='bulletReplace'/> Replace triangluar bullets with normal ones</label> <br /> \ | |
<label><input type='checkbox' id='addEllipsis'/> Add ellipsis to long names</label> <br /> \ | |
<label><input type='checkbox' id='moveCommentsLink'/> Move 'show x more comments' to the top</label> <br /> \ | |
<label><input type='checkbox' id='unHideAnswer'/> Un-gray-out downvoted answers</label> <br /> \ | |
<label><input type='checkbox' id='fixedTopbar'/> Fix topbar position</label> <br /> \ | |
<label><input type='checkbox' id='highlightQuestions'/> Alternate favourite questions highlighing</label> <br /> \ | |
<label><input type='checkbox' id='displayName'/> Display name before gravatar</label> <br />\ | |
<label><input type='checkbox' id='colorAnswerer'/> Color answerer's comments</label> <br />\ | |
<label><input type='checkbox' id='kbdAndBullets'/> Add KBD and list buttons to editor toolbar</label> <br />\ | |
<label><input type='checkbox' id='editComment'/> Pre-defined edit comment options</label> <br />\ | |
<label><input type='checkbox' id='shareLinksMarkdown'/> Edit 'share' link to format of [post-name](url)</label> <br />\ | |
<label><input type='checkbox' id='commentShortcuts'/> Use Ctrl+I,B,K (to italicise, bolden and add code backticks) in comments</label> <br />\ | |
<label><input type='checkbox' id='unspoil'/> Add a link to show all spoilers in a post</label> <br />\ | |
<input type='submit' id='submitOptions' value='Submit' /><br /> \ | |
</div>"; | |
$('body').append(div); | |
$('#featureGMOptions').draggable().hide(); //Hide it at first | |
$('#featureTitle').css('cursor', 'move'); | |
if (window.location.href.indexOf('/users/') > -1) { //Add the add features link | |
$('.sub-header-links.fr').append('<span class="lsep">|</span><a href="javascript:;" id="addFeaturesLink">add features</a>'); //Old profile (pre Feb-2015) | |
$('.additional-links').append('<span class="lsep">|</span><a href="javascript:;" id="addFeaturesLink">add features</a>'); //New profile (post Feb-2015) Currently on MSE only | |
$('#addFeaturesLink').click(function () { | |
$('#featureGMOptions').show(500); | |
}); | |
} | |
$('#featureGMOptions > #closeFeature').css('cursor', 'pointer').click(function () { | |
$('#featureGMOptions').hide(500); | |
}); | |
$('#featureGMOptions > #resetFeature').css('cursor', 'pointer').click(function () { | |
GM_deleteValue('featureOptions'); //Delete the setting when clicked | |
location.reload(); | |
}); | |
$(window).bind("load", function() { | |
if (GM_getValue("featureOptions", -1) != -1) { //If the setting is already set | |
var featureOptions = JSON.parse(GM_getValue("featureOptions")); | |
for (i = 0; i < featureOptions.length; ++i) { | |
$('#featureGMOptions #'+featureOptions[i]).prop('checked', true); | |
functionsToCall[featureOptions[i]](); //Call the functions that were chosen | |
} | |
} else { //If not, set it: | |
$('#featureGMOptions input').prop('checked', true); | |
$('#featureGMOptions').show(); //Show the dialog | |
var featureOptions = []; | |
} | |
$('#submitOptions').click(function () { | |
var featureOptions = []; | |
$('input[type=checkbox]:checked').each(function () { | |
var x = $(this).attr('id'); | |
featureOptions.push(x); //Add the function's ID (also the checkbox's ID) to the array | |
}); | |
GM_setValue('featureOptions', JSON.stringify(featureOptions)); //Save the setting | |
console.log('Options saved: ' + featureOptions); | |
$('#featureGMOptions').hide(500); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment