-
-
Save mjpieters/0bfa189b62fee0425b0ea02f45a4fe69 to your computer and use it in GitHub Desktop.
Fork from samliew/SO-mod-userscripts/blob/master/lib/common.js to test work-arounds
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
/* | |
Common helper functions and variables for SOMU scripts | |
https://github.com/samliew/SO-mod-userscripts | |
Requires jQuery | |
*/ | |
/** | |
* jQuery Helper Plugins | |
*/ | |
(function() { | |
if (unsafeWindow !== undefined && window !== unsafeWindow) { | |
window.jQuery = unsafeWindow.jQuery; | |
window.$ = unsafeWindow.jQuery; | |
} | |
jQuery.getCachedScript = function(url, callback) { | |
return $.ajax({ | |
url: url, | |
dataType: 'script', | |
cache: true | |
}).done(callback); | |
}; | |
jQuery.fn.getUid = function() { | |
const url = $(this).attr('href') || ''; | |
if(!url.contains('/users/')) return null; | |
const res = Number((url.match(/\/\d+\/?/) || [''])[0].replace(/[^\d]/g, '')); | |
return isNaN(res) || res == 0 ? null : res; | |
}; | |
})(); | |
/** | |
* Checks if current user is a moderator. Works on all sites (main, meta, and chat) pages | |
* @return {boolean} Whether the user is a moderator | |
*/ | |
function isModerator() { | |
return location.hostname.includes('chat.') ? | |
$('.topbar-menu-links').text().includes('♦') || (typeof CHAT !== "undefined" && CHAT.RoomUsers && typeof CHAT.RoomUsers.current === "function" && CHAT.RoomUsers.current().is_moderator) : | |
typeof StackExchange !== "undefined" && StackExchange.options && StackExchange.options.user && StackExchange.options.user.isModerator; | |
} | |
/** | |
* Simple wrapper for (a cross-domain) GM_xmlhttpRequest() that returns a Promise | |
* See http://tampermonkey.net/documentation.php#GM_xmlhttpRequest for options | |
* Requires @grant GM_xmlhttpRequest | |
* @param {string} options - The URL for the AJAX request, via the 'GET' method, OR | |
* @param {object} options - A key-value pair of params for the AJAX request | |
* @return {Promise} A promise containing the response of the AJAX request | |
*/ | |
function ajaxPromise(options, type = 'text') { | |
if(typeof options === 'string') { | |
options = { url: options }; | |
} | |
return new Promise(function(resolve, reject) { | |
if(typeof options.url === 'undefined' || options.url == null) reject(); | |
options.responseType = type; | |
options.method = options.method || 'GET'; | |
options.onload = function(response) { | |
let parser = new DOMParser(); | |
resolve(parser.parseFromString(response.responseText, 'text/html')); | |
}; | |
options.onerror = function() { | |
reject(); | |
}; | |
GM_xmlhttpRequest(options); | |
}); | |
} | |
/** | |
* Override jQuery's setRequestHeader to ignore setting the "X-Requested-With" header | |
* Solution from https://stackoverflow.com/a/24719409 | |
* @return {jQuery.ajaxSettings.xhr} An overidden jQuery.ajaxSettings.xhr function to be passed to the options param of a jQuery AJAX function | |
* | |
* Example: | |
* ajaxPromise({ | |
* url: url, | |
* xhr: jQueryXhrOverride | |
* }) | |
*/ | |
function jQueryXhrOverride() { | |
var xhr = jQuery.ajaxSettings.xhr(); | |
var setRequestHeader = xhr.setRequestHeader; | |
xhr.setRequestHeader = function(name, value) { | |
if (name == 'X-Requested-With') return; | |
setRequestHeader.call(this, name, value); | |
}; | |
return xhr; | |
} | |
/** | |
* hasBackoff() - Check if there's a backoff on the current page | |
* addBackoff(num) - Sets a temporary backoff timeout from now until num seconds later | |
* If already set, replaces the timeout | |
*/ | |
const _w = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window; | |
const hasBackoff = () => typeof _w.backoff === 'number'; | |
function addBackoff(secs) { | |
if(isNaN(secs)) return; | |
if(hasBackoff()) clearTimeout(_w.backoff); | |
_w.backoff = setTimeout(() => { clearTimeout(_w.backoff); _w.backoff = null }, secs * 1000); | |
} | |
/** | |
* Decodes a string containing HTML entities to a text string | |
* https://stackoverflow.com/a/34064434 | |
*/ | |
function htmlDecode(input) { | |
var doc = new DOMParser().parseFromString(input, "text/html"); | |
return doc.documentElement.textContent; | |
} | |
/** | |
* Checks if any parameters contain invalid ids (non-numerical strings or non-integers, or <= 0) | |
* Usage: let anyInvalidParams = hasInvalidIds(1, 2, 3.1) // true - 3.1 is not valid | |
*/ | |
function hasInvalidIds() { | |
return [...arguments].some((v) => typeof v === 'undefined' || v === null || isNaN(v) || v <= 0 || v != Math.round(v)); | |
} | |
/** | |
* Parse URL for a post id | |
*/ | |
function getPostId(url) { | |
if(typeof url === 'undefined' || url == null) return null; | |
const a = url.match(/#\d+$/g); | |
if(a && a.length) return a[0].replace(/\D/g, ''); | |
const b = url.match(/\/\d+\/?/g); | |
if(b && b.length) return b[b.length - 1].replace(/\D/g, ''); | |
return null; | |
} | |
// EOF |
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
(function(jQuery) { | |
// Plugin options | |
let maxTimeout = 30000; | |
// Plugin CSS | |
jQuery('body').append(` | |
<style> | |
.ajax-progressbar { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 3px; | |
z-index: 999999; | |
background-color: white; | |
-webkit-appearance: none; | |
appearance: none; | |
} | |
.ajax-progressbar::-webkit-progress-bar, | |
.ajax-progressbar::-moz-progress-bar { | |
background-color: white; | |
} | |
.ajax-progressbar::-webkit-progress-value { | |
background-color: #F48024; | |
} | |
</style>`); | |
jQuery.fn.showAjaxProgress = function(num, styles = {}) { | |
const progressbar = jQuery(`<progress class="ajax-progressbar" value="0" max="${num}"></progress>`).css(styles).prependTo(this); | |
let count = 0, max = num, activeTimeout = 0; | |
maxTimeout = 1000 * num; | |
jQuery(document).ajaxComplete(function() { | |
progressbar.val(++count).attr('title', count + '/' + max); | |
if(count == max) { | |
progressbar.remove(); | |
jQuery(document).unbind('ajaxComplete'); | |
} | |
// Also remove progressbar only if there are no further ajax completions after X seconds | |
if(activeTimeout) clearTimeout(activeTimeout); | |
activeTimeout = setTimeout(() => { progressbar.remove(); }, 10000); | |
}); | |
// Maximum time to wait for completion | |
setTimeout(function() { | |
progressbar.remove(); | |
}, maxTimeout, progressbar); | |
} | |
})(jQuery || unsafeWindow.jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment