Skip to content

Instantly share code, notes, and snippets.

@jr-codes
Last active May 2, 2024 02:45
Show Gist options
  • Select an option

  • Save jr-codes/4088609 to your computer and use it in GitHub Desktop.

Select an option

Save jr-codes/4088609 to your computer and use it in GitHub Desktop.
u.js userscript
// ==UserScript==
// @name u.js (embedded)
// @namespace http://zarjay.net/
// @description Utility functions for browser console ninjas
// @include *
// @version 0.9
// ==/UserScript==
function exec(fn) {
var script = document.createElement('script');
script.textContent = '(' + fn + ')();';
document.head.appendChild(script);
}
exec(function() {
// Key used for localStorage
var KEY = '_u.js' + location.pathname;
var USER_KEY = KEY + ':user:';
// Libraries for easy including with u.lib();
var LIBS = {
datejs: {
css: [],
js: ['//cdnjs.cloudflare.com/ajax/libs/datejs/1.0/date.min.js']
},
design: {
css: [],
js: ['http://www.sprymedia.co.uk/design/design/media/js/design-loader.js']
},
'dom-monster': {
css: [],
js: ['//mir.aculo.us/dom-monster/dommonster.js']
},
jquery: {
css: [],
js: ['//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js']
},
'jquery-ui': {
css: ['//ajax.googleapis.com/ajax/libs/jqueryui/1/themes/base/jquery-ui.css'],
js: ['//ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js']
},
kickass: {
css: [],
js: ['//hi.kickassapp.com/kickass.js']
},
raphael: {
css: [],
js: ['//cdnjs.cloudflare.com/ajax/libs/raphael/2.0.1/raphael-min.js']
},
underscore: {
css: [],
js: ['//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.2/underscore-min.js']
}
};
var u = {};
u._namespace = 'zarjay.net';
function loadu(u, names) {
var loaded = false;
for (var i = 0; !loaded && i < names.length; ++i) {
var name = names[i];
if (window[name] && window[name]._namespace !== u._namespace) {
console.warn('u: "' + name + '" is taken.');
} else {
window[name] = u;
console.log('u.js is loaded: ' + name);
loaded = true;
}
}
if (!loaded) console.warn('u: u.js not loaded due to naming collisions.');
}
loadu(u, ['u', 'ujs', 'ujslib', 'zarjay_u']);
// u.uload(fn) - Sets a function to run when u.js loads
// u.uload() - Runs the function previously set
// u.uload(null) - Clears the function previously set
u.uload = function(fn) {
if (typeof fn === 'function') {
localStorage[KEY] = JSON.stringify(fn.toString());
}
if (typeof fn === 'undefined') {
fn = localStorage[KEY];
if (fn) fn = JSON.parse(fn);
this.exec(fn);
}
if (fn === null) {
localStorage.removeItem(KEY);
}
};
// Sets an item in localStorage
u.set = function(key, value) {
if (typeof value === 'function') value = value.toString();
localStorage[USER_KEY + key] = JSON.stringify(value);
};
// Gets an item in localStorage
u.get = function(key) {
var value = localStorage[USER_KEY + key];
// Return immediately if undefined
if (typeof value === 'undefined' || value === 'undefined') return value;
value = JSON.parse(value);
// Check for function string and convert to function
if (value.indexOf && value.indexOf('function') === 0) value = eval('(' + value + ')');
return value;
};
// Code utilities
// Executes a function
u.exec = function(fn) {
if (!fn) return;
var script = document.createElement('script');
script.textContent = '(' + fn + ')();';
document.head.appendChild(script);
};
// Includes a JS or CSS file onto the page
u.include = function(url, type) {
if (!url) return;
// If type is empty, determine type via file extension
type = (type || url.split('.').pop()).toLowerCase();
if (type === 'css') {
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = url;
// Add <link> to <head>
document.head.appendChild(link);
console.log('Loaded ' + url);
} else if (type === 'js') {
var script = document.createElement('script');
script.src = url;
// Make sure scripts run in the order in which they're included.
script.async = false;
// Add <script> to <head>
document.head.appendChild(script);
console.log('Loaded ' + url);
} else {
throw new Error('u: Failed to include ' + url + ' due to unknown file type.');
}
};
// Includes one or more libraries onto the page
u.lib = function(/* libs */) {
var numArgs = arguments.length;
// If no params, return list of available libraries
if (numArgs === 0) return Object.keys(LIBS);
// Import CSS/JS files from each lib parameter
for (var i = 0; i < numArgs; ++i) {
var lib = LIBS[arguments[i]];
if (lib) {
for (var j = 0; j < lib.css.length; ++j) this.include(lib.css[j], 'css');
for (var k = 0; k < lib.js.length; ++k) this.include(lib.js[k], 'js');
}
}
},
// DOM queries
// Shortcut for document.querySelector()
u.query = function(selector) {
return document.querySelector(selector);
},
// Shortcut for document.querySelectorAll() + converts result to an array
u.queryAll = function(selector) {
return Array.prototype.slice.call(document.querySelectorAll(selector));
},
// Calculations
u.accumulate = function(selector, filter, map, reduce) {
return this.queryAll(selector).filter(filter).map(map).reduce(reduce);
},
// Adds together numbers from given selector.
// Optionally massage the data by passing in filter and map functions.
u.sum = function(selector, filter, map) {
filter = filter || function() { return true; };
map = map || function(elem) { return +elem.textContent.replace(/[$,%]/g, ''); };
var sum = function(a, b) { return a + b; };
return this.accumulate(selector, filter, map, sum);
},
u.start = function(name) {
console.time(name || 'u');
};
u.stop = function(name) {
console.timeEnd(name || 'u');
};
// Modifications
// Makes everything editable.
u.edit = function() {
document.body.contentEditable = 'true';
document.designMode = 'on';
},
// string.replace() on selector (or body if no selector is given)
u.replace = function(/* [selector], regex, newStr */) {
var numArgs = arguments.length,
selector = 'body',
regex,
newStr;
switch(numArgs) {
case 3:
selector = arguments[0];
regex = arguments[1];
newStr = arguments[2];
break;
case 2:
regex = arguments[0];
newStr = arguments[1];
break;
default:
console.log('u: Use 2 parameters (regex, newStr) or 3 (selector, regex, newStr)');
return;
}
if (!(regex instanceof RegExp)) regex = new RegExp(regex,'g');
var elems = this.queryAll(selector);
elems.forEach(function(elem) {
elem.innerHTML = elem.innerHTML.replace(regex, newStr);
});
};
// TODO: Consider converting numArg stuff into an extends() method.
// TODO: Let append() and replace() share the same queryAll/forEach code.
// TODO: Consider adding prepend(); look at insertAdjacentHTML's options
u.append = function(/* [selector], html */) {
var numArgs = arguments.length,
selector = 'body',
html;
switch(numArgs) {
case 2:
selector = arguments[0];
html = arguments[1];
break;
case 1:
html = arguments[0];
break;
default:
console.log('u: Use 2 parameters (selector, html) or 1 (html)');
return;
}
var elems = this.queryAll(selector);
elems.forEach(function(elem) {
elem.insertAdjacentHTML('beforeend', html);
});
};
u.uload();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment