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
// @namespace http://zarjay.net/
// @description Utility functions for browser console ninjas
// @include *
// @version 0.17
// ==/UserScript==
// Execute function in global scope (instead of userscript scope)
function exec(fn) {
var script = document.createElement('script');
script.textContent = '(' + fn + ')();';
document.head.appendChild(script);
}
exec(function() {
// Current version of u.js
var VERSION = '0.17',
// Predefined resources to be included via u.include(name)
RESOURCES = {
design: {
css: [],
js: ['http://www.sprymedia.co.uk/design/design/media/js/design-loader.js'],
script: []
},
'dom-monster': {
css: [],
js: ['//mir.aculo.us/dom-monster/dommonster.js'],
script: []
},
jquery: {
css: [],
js: ['//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js'],
script: []
},
'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'],
script: []
},
// Katamari Hack Bookmarklet - http://kathack.com/
// Turn a webpage into a game of Katamari Damacy. Use your katamari ball to pick up DOM elements.
katamari: {
css: [],
js: ['//ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js', 'http://kathack.com/js/kh.js'],
script: []
},
// Kickass Bookmarklet - https://kickassapp.com/
// Turn a webpage into a game of Asteroids. Use your ship to destroy DOM elements.
kickass: {
css: [],
js: ['//hi.kickassapp.com/kickass.js'],
script: []
},
lodash: {
css: [],
js: ['//cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.0-rc.3/lodash.min.js'],
script: []
},
markup: {
css: [],
js: [],
script: ["(function(){window.add_js=function(s){var k=(document.getElementsByTagName('head')[0]||document.body).appendChild(document.createElement('script'));k.src=s;k.type='text/javascript';k.markup='ea33cdc7-73dd-11e2-9673-fac11f1adc9e'};window.MarkUp=window.MarkUp||{};add_js('http://api.markup.io/bootstrap.js?v=1&'+(+(new Date)))})();"]
},
moment: {
css: [],
js: ['//cdnjs.cloudflare.com/ajax/libs/datejs/1.0/date.min.js'],
script: []
},
raphael: {
css: [],
js: ['//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js'],
script: []
},
stats: {
css: [],
js: ['https://github.com/mrdoob/stats.js/raw/master/build/stats.min.js'],
script: ['var interval=setInterval(function(){if(typeof Stats==\'function\'){clearInterval(interval);var stats=new Stats();stats.domElement.style.position=\'fixed\';stats.domElement.style.left=\'0px\';stats.domElement.style.top=\'0px\';stats.domElement.style.zIndex=\'10000\';document.body.appendChild(stats.domElement);setInterval(function(){stats.update();},1000/60);}},100);']
},
// Statsy Bookmarklet - http://www.phpied.com/statsy-more-data-points-for-markup-quality/
// Displays some DOM statistics
statsy: {
css: [],
js: ['http://phpied.com/files/bookmarklets/somestats.js'],
script: []
},
underscore: {
css: [],
js: ['//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js'],
script: []
},
// What Font Bookmarklet - http://chengyinliu.com/whatfont.html
// Identifies fonts
whatfont: {
css: [],
js: ['http://chengyinliu.com/wf.js'],
script: []
}
},
animationCounter = 0,
// Converts array-like objects to arrays
slice = Function.prototype.call.bind(Array.prototype.slice),
// Creates a partial function (passing default argument to existing function)
partial = function(fn) {
var args = slice(arguments, 1);
return function() {
return fn.apply(this, args.concat(slice(arguments)));
};
},
// Adds a <style> to the page
addStyle = function(css) {
style = document.createElement('style');
style.textContent = css;
document.head.appendChild(style);
},
// Adds a <link> for the specified URL
addCSS = function(url) {
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = url;
document.head.appendChild(link);
console.log('Loaded ' + url);
},
// Adds a <script> for the specified URL
addJS = function(url) {
var script = document.createElement('script');
script.src = url;
script.async = false;
document.head.appendChild(script);
console.log('Loaded ' + url);
},
// Adds a <script> for the specified JavaScript
addScript = function(fn) {
var script = document.createElement('script');
script.innerHTML = fn;
document.head.appendChild(script);
},
// Adds a <link> or <script> for the specified URL
addURL = function(url, type) {
type = (type || url.split('.').pop()).toLowerCase();
if (type === 'css') {
addCSS(url);
} else if (type === 'js') {
addJS(url);
} else {
throw new Error('Could not load ' + url);
}
},
// Includes one or more resources onto the page
addResource = function(key) {
var resource = RESOURCES[key];
if (resource.css) for (var j = 0; j < resource.css.length; ++j) addCSS(resource.css[j]);
if (resource.js) for (var k = 0; k < resource.js.length; ++k) addJS(resource.js[k]);
if (resource.script) for (var l = 0; l < resource.script.length; ++l) addScript(resource.script[l]);
},
// Lists items in localStorage
listStorageItems = function() {
return Object.keys(localStorage);
},
// Gets an item in localStorage
getStorageItem = function(key) {
var value = localStorage[key];
// Return immediately if undefined
if (typeof value === 'undefined' || value === 'undefined') return value;
// Parse value and convert to function if necessary
value = JSON.parse(value);
if (value.indexOf && value.indexOf('function') === 0) value = eval('(' + value + ')');
return value;
},
// Sets an item in localStorage
setStorageItem = function(key, value) {
if (typeof value === 'function') value = value.toString();
localStorage[key] = JSON.stringify(value);
},
// Inserts HTML at the specified position
insertHTML = function(element, position, html) {
var positions = {
append: 'beforeend',
prepend: 'afterbegin',
before: 'beforebegin',
after: 'afterend'
};
element.insertAdjacentHTML(positions[position] || position, html);
},
// Replaces HTML based on the given regex
// If a string is used instead of a regex, it's converted to a global regex
replaceHTML = function(element, regex, html) {
if (!(regex instanceof RegExp)) regex = new RegExp(regex, 'g');
element.innerHTML = element.innerHTML.replace(regex, html);
},
// Sets an element as contentEditable
setEditable = function(element, isEditable) {
if (isEditable === undefined) isEditable = true;
element.contentEditable = isEditable;
},
// Gets a CSS property for element
getStyle = function(element, property) {
return getComputedStyle(element)[property];
},
// Sets a CSS property for element
setStyle = function(element, property, value) {
element.style[property] = value;
},
// Gets/sets CSS
css = function(element, property, value) {
if (value === undefined) {
return getStyle(element, property);
} else {
setStyle(element, property, value);
}
},
// Adds a CSS animation style
addAnimation = function(property, value) {
++animationCounter;
var animationName = 'u-animation-' + animationCounter;
var style = '@-webkit-keyframes ' + animationName + ' { 50% { ' + property + ': ' + value + '; ' + '} }';
addStyle(style);
return animationName;
},
// Sets an animation on an element (to loop infinitely)
setAnimation = function(element, animation, speed) {
speed = speed || 3;
var animationValue = animation + ' ' + speed + 's infinite';
setStyle(element, '-webkit-animation', animationValue);
},
// Sets a transition on an element
setTransition = function(element, property, value, speed) {
speed = speed || 3;
setStyle(element, '-webkit-transition', speed + 's');
setStyle(element, property, value);
},
listEffects = function() {
console.log('Not ready yet.');
},
effect = function(element, effect, speed, loop) {
console.log('Not ready yet.');
},
// Applies a CSS animation or transition
animate = function(element, property, value, speed, loop) {
if (property === undefined) {
listEffects();
} else if (property in EFFECTS) {
effect(element, property, value, speed, loop);
} else if (loop) {
var animation = addAnimation(property, value);
setAnimation(element, animation, speed);
} else {
setTransition(element, property, value, speed);
}
},
// Stop event propagation
stopEvents = function(event) {
event.stopPropagation();
},
// Intercept events by executing first (during the capture phase) and stopping propagation
// Useful for sites that prevent/manipulate text selection, right-click, etc.
interceptUserInput = function(element) {
var events = ['keyup', 'keydown', 'mouseup', 'mousedown', 'selectstart', 'contextmenu', 'copy'];
for (var i = 0; i < events.length; ++i) element.addEventListener(events[i], stopEvents, true);
},
// Extra functions for the u.query()'s array
wrappedFunctions = {
// Applies a CSS animation or transition
animate: function(property, value, speed, loop) {
if (loop && this.length) {
var animation = addAnimation(property, value);
this.forEach(function(element) {
setAnimation(element, animation, speed);
});
} else {
this.forEach(function(element) {
setTransition(element, property, value, speed);
});
}
},
// Sets CSS property for elements
// Or gets the CSS property value of first element
css: function(property, value) {
if (value === undefined && this.length) {
return getStyle(this[0], property);
} else {
this.forEach(function(element) {
setStyle(element, property, value);
});
}
},
// Make elements editable
edit: function(isEditable) {
this.forEach(function(element) {
setEditable(element, isEditable);
});
},
// Add HTML at the specified position
insert: function(position, html) {
this.forEach(function(element) {
insertHTML(element, position, html);
});
},
// Intercept user input events for elements
intercept: function() {
this.forEach(function(element) {
interceptUserInput(element);
});
},
// Replaces HTML using the specified regex
replace: function(regex, html) {
this.forEach(function(element) {
replaceText(element, regex, html);
});
},
// Combine element values
// Optionally specify functions to filter out selections,
// remap values, or change how the values are summed up
sum: function(filter, map, reduce) {
filter = filter || function() { return true; };
map = map || function(elem) { return +elem.textContent.replace(/[$,%]/g, ''); };
reduce = reduce || function(a, b) { return a + b; };
return this.filter(filter).map(map).reduce(reduce);
}
},
// Wrap array with extra functions
wrap = function(wrapped) {
for (var func in wrappedFunctions) {
if (wrappedFunctions.hasOwnProperty(func)) {
wrapped[func] = wrappedFunctions[func];
}
}
return wrapped;
},
// Shortcut for document.querySelectorAll() with extra array functions
querySelectorAll = function(selector) {
return wrap(slice(document.querySelectorAll(selector)));
};
// u.js
var u = {
// Current version of u.js
_VERSION: VERSION,
// u.animate(property, value, speed, loop)
// u.animate(effect, speed, loop)
animate: partial(animate, document.body),
// Get/set a CSS property on <body>
// u.css(property)
// u.css(property, value)
css: partial(css, document.body),
// Makes everything editable.
// u.edit() or u.edit(true) - Turns on editing
// u.edit(false) - Turns off editing
edit: partial(setEditable, document.body),
// Include a CSS file, JS file, or predefined resource
// u.include(url) - Adds CSS or JS file onto the page
// u.include(url, type) - Adds CSS or JS file onto the page (specifying type in second param)
// u.include(resource) - Adds resource onto the page
// u.include() - Lists available resources to include
include: function(resource, type) {
if (resource === undefined) {
return Object.keys(RESOURCES);
} else if (resource in RESOURCES) {
addResource(resource);
} else {
addURL(resource, type);
}
},
// Insert HTML in <body> at the specified position
// u.insert(position, html)
insert: partial(insertHTML, document.body),
// Stop events from manipulating/preventing user input
// u.intercept()
intercept: partial(interceptUserInput, document.body),
// Replace HTML in <body> usng a string or regex
// u.replace(regex, html)
replace: partial(replaceHTML, document.body),
// Store and retrieve data in localStorage (including functions)
// store(key, value) - Stores value in localStorage under key
// store(key) - Gets value of key in localStorage
// store() - List keys stored in localStorage
store: function(key, value) {
if (key === undefined) {
return listStorageItems();
} else if (value === undefined) {
return getStorageItem(key);
} else {
setStorageItem(key, value);
}
},
// Returns u.js-powered array of elements
// Shortcut for document.querySelectorAll()
// u.query(selector)
query: querySelectorAll
};
/* Init */
var loadu = function(u, names) {
for (var i = 0; i < names.length; ++i) {
var name = names[i];
if (name in window) continue;
window[name] = u;
console.log('Loaded u.js as global variable ' + name);
return;
}
console.warn('Could not load u.js due to variable conflicts.');
};
loadu(u, ['u', 'u.js', 'zarjay.net/u.js']);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment