Last active
May 2, 2024 02:45
-
-
Save jr-codes/4088609 to your computer and use it in GitHub Desktop.
u.js userscript
This file contains hidden or 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
| // ==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