jMod

A powerful javascript library designed for User Scripts

What is jMod?

jMod is a new javascript library designed around the needs of user script authors. Lightweight and versatile, it comes packaged with tools that will cut your coding time in half!

Designed for user scripts

jMod was constructed with the sandbox’s security in mind. It will handle permission and scope errors for you without any additional headaches.

Time saver

Settings Modal, Notification Popups, and Loading Events are just a few of the features built into jMod that will boost your productivity and cut your time coding.

B

Bootstrap

jMod uses a custom Bootstrap stylesheet fully namespaced with the class .jmod-na. Trimmed to its bare bones, loading is lightning fast and won’t cause any unintentional changes to the page.

Font Awesome

jMod loads a namespaced version of Font Awesome.

Easy to use

Loading jMod is as simple as requiring it in your script. That’s it! Once loaded, jMod takes care of everything else.

Open Source

jMod is 100% open source and freely accepts edits and feature updates.

Features

Get Started

Meta Block

To add jMod to any project, use the following example as a guide:

// ==UserScript==
// @name             jMod Example Script
// @description      Example script
// @author           jgjake2
// @include          http://test.com/change/me
// @require          http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// @require          http://code.jmod.info/0.0.19/jMod.min.js
// @version          0.1
// @grant            unsafeWindow
// @grant            GM_info
// @grant            GM_log
// @grant            GM_addStyle
// @grant            GM_getMetadata
// @grant            GM_xmlhttpRequest
// @grant            GM_registerMenuCommand
// @grant            GM_getValue
// @grant            GM_setValue
// @grant            GM_listValues
// @grant            GM_deleteValue
// @grant            GM_getResourceText
// @grant            GM_getResourceURL
// @unwrap
// @noframes
// @run-at document-start
// @jMod             {"debug": true, "API": {"log": {"debug": true}}}
// ==/UserScript==

Only the @require line is necessary. However, the @jMod allows you to configure jMod as it initializes (rather than configuring it when your script begins) with a JSON string.

Additionally, it is recommended you include the following grants:

// @grant            unsafeWindow
// @grant            GM_info
// @grant            GM_getMetadata
// @grant            GM_xmlhttpRequest
// @grant            GM_getValue
// @grant            GM_setValue
// @grant            GM_listValues
// @grant            GM_deleteValue

Without GM_info and GM_getMetadata, jMod wont be able to access your meta block and cant properly initialize.

Events

jMod handles loading events for you. This is key when writing a script that executes at document-start since your script will execute before the DOM exists.

// Start DOM interactions
function onDOMReadyCB(){
    console.log('onDOMReadyCB');
}
jMod.onDOMReady = onDOMReadyCB;

// jMod fully initialized
function onReadyCB(){
    console.log('onReadyCB');
}
jMod.onReady = onReadyCB;

// Page is ready
function onPageReadyCB(){
    console.log('onPageReadyCB');
}
jMod.onPageReady = onPageReadyCB;

// Page is loaded
function loadCB(){
    console.log('loadCB');
}
jMod.load = loadCB;


/**
 * The following four methods are all functionally equivalent:
 */
// Execute function when jMod is fully loaded and CSS is added
jMod.onReady = function(){
    console.log('onReady');
}

jMod(function(){
    console.log('onReady');
});

jMod('onReady', function(){
    console.log('onReady');
});

jMod.Events.addListener('onReady', function(){
    console.log('onReady');
}, true);

CSS

Adding CSS is simpler than ever with jMod. You dont have to worry about if the DOM exists or not; jMod takes care of that for you. Just use the following example:

// Import a style sheet
jMod.CSS = "@import url(//example.com/custom.css);"
// add custom css
jMod.CSS = ".class-name {color: #000000;}";
// add custom stylesheet link (does not wait for DOM to exist)
jMod.API.addStylesheet("http://example.com/custom2.css");
// add custom css (does not wait for DOM to exist)
jMod.API.addStyle(".class-name {color: #000000;}");

jMod.CSS will add your style to the current document immediately if the DOM exists. Otherwise it is added to the jMod CSS stack, which is added one the DOM is available.

Settings Dialog

jMod can generate a settings dialog for you! No need to write your own settings engine.

var SettingsTest = function(){
	console.log('jMod.Settings Example');
	var SettingOptions = {
		title: 'Example Title',
		settings: [
			{
				name: 'Setting 1',
				description: 'Setting 1 description',
				tooltip: {
					innerHTML: 'Text input Top-Right Tooltip',
					placement: 'top-right'
				},
				icon: {
					name: 'fa-microphone',
					tooltip: {
						innerHTML: 'icon tooltip',
						placement: 'right'
					}
				},
				tab: 'Tab Name 1',
				section: 'Other',
				type: 'input',
				'default': 'foo bar'
			},
			{
				name: 'element example',
				tab: 'Tab Name 1',
				section: 'Other',
				type: 'element',
				innerHTML: [
					'Element Example: ',
					{
						type: 'img',
						attributes: {
							src: "https://assets-cdn.github.com/images/modules/logos_page/GitHub-Logo.png",
							height: "10px"
						}
					}
				]
			},
			{
				name: 'Toggle',
				description: 'Toggle Test',
				options: {
					'val1': {
						label: 'Toggle 1',
						on: 'ON',
						off: 'OFF',
						tooltip: {
							innerHTML: 'Toggle Tooltip 1',
							placement: 'right'
						}
					},
					'val2': {
						label: 'Toggle 2',
						on: 'ON',
						off: 'OFF',
						tooltip: {
							innerHTML: 'Toggle Tooltip 2',
							placement: 'right'
						}
					},
					'val3': {
						label: 'Toggle 3',
						on: 'WIDE ON',
						off: 'WIDE OFF',
						className: 'wide',
						tooltip: {
							innerHTML: 'Toggle Tooltip 3',
							placement: 'right'
						}
					},
					'val4': {
						label: 'Toggle 4',
						on: 'EX WIDE ON',
						off: 'EX WIDE OFF',
						className: 'ex-wide',
						tooltip: {
							innerHTML: 'Toggle Tooltip 4',
							placement: 'right'
						}
					}
				},
				tab: 'Tab Name 1',
				section: 'Other',
				type: 'toggle',
				'default': 'val3,val4'
			},
			{
				name: 'Setting 2',
				tooltip: {
					innerHTML: 'Select Left Tooltip',
					placement: 'left'
				},
				tab: 'Tab Name 1',
				section: 'Other',
				type: 'select',
				options: {
					'val1': 'Option 1',
					'val2': 'Option 2',
					'val3': 'Option 3',
					'val4': 'Option 4',
				},
				'default': 'val3'
			},
			{
				name: 'Setting 3',
				tooltip: {
					innerHTML: 'Textarea Top Left Tooltip',
					placement: 'left-top'
				},
				icon: {
					name: 'fa-question-circle',
					tooltip: {
						innerHTML: 'Icon Tooltip for Textarea',
						placement: 'right'
					}
				},
				style: {
					minHeight: '100px'
				},
				tab: 'Tab Name 1',
				section: 'Other',
				type: 'textarea',
				'default': 'taco'
			},
			{
				name: 'Checkboxes',
				tab: 'Tab Name 1',
				tooltip: {
					innerHTML: 'Top Label Tooltip',
					placement: 'top-left',
					margin: {
						//left: '5px'
					}
				},
				section: 'Other2',
				options: {
					'val1': {
						label: 'Checkbox 1',
						tooltip: {
							innerHTML: 'Checkbox Tooltip 1',
							placement: 'top'
						}
					},
					'val2': {
						label: 'Checkbox 2',
						tooltip: {
							innerHTML: 'Checkbox Tooltip 2',
							placement: 'top'
						}
					},
					'val3': {
						label: 'Checkbox 3',
						className: 'wide',
						tooltip: {
							innerHTML: 'Checkbox Tooltip 3',
							placement: 'top'
						}
					},
					'val4': {
						label: 'Checkbox 4',
						className: 'ex-wide',
						tooltip: {
							innerHTML: 'Checkbox Tooltip 4',
							placement: 'top'
						}
					}
				},
				type: 'checkbox',
				'default': 'val1,val3'
			},
			{
				name: 'Depend Checkbox',
				description: 'Depend on Value of Checkboxes',
				tab: 'Tab Name 1',
				section: 'Other2',
				type: 'input',
				'default': 'Depend Checkbox',
				depend: {
					'Checkboxes': ['val1', 'val4']
				}
			},
			{
				name: 'Radio',
				tab: 'Tab Name 1',
				tooltip: {
					innerHTML: 'Bottom Label Tooltip',
					placement: 'bottom-left'
				},
				section: 'Other2',
				options: {
					'val1': {
						label: 'Radio 1',
						tooltip: {
							innerHTML: 'Radio Tooltip 1',
							placement: 'bottom'
						}
					},
					'val2': {
						label: 'Radio 2',
						tooltip: {
							innerHTML: 'Radio Tooltip 2',
							placement: 'bottom'
						}
					},
					'val3': {
						label: 'Radio 3',
						className: 'wide',
						tooltip: {
							innerHTML: 'Radio Tooltip 3',
							placement: 'bottom'
						}
					},
					'val4': {
						label: 'Radio 4',
						className: 'ex-wide',
						tooltip: {
							innerHTML: 'Radio Tooltip 4',
							placement: 'bottom'
						}
					}
				},
				type: 'radio',
				'default': 'val1'
			},
			{
				name: 'Depend 1',
				description: 'Depend on Value of Radio',
				tab: 'Tab Name 1',
				section: 'Other2',
				type: 'input',
				'default': 'Depend 1',
				depend: {
					'Radio': ['val2', 'val4']
				}
			},
			{
				name: 'Depend 2',
				description: 'Depend on Value of Radio',
				tab: 'Tab Name 1',
				section: 'Other2',
				type: 'input',
				'default': 'Depend 2',
				depend: {
					'Radio': function(prefEl, data, radioValue){
						if(radioValue == 'val1')
							return true;
						return false;
					}
				}
			},
			{
				name: 'Range',
				min: 20,
				max: 567,
				tooltip: {
					innerHTML: 'Slider tooltip',
					placement: 'top',
				},
				tab: 'Tab Name 1',
				section: 'Other',
				type: 'range',
				'default': '50'
			},
			{
				name: 'Setting 6',
				tab: 'Tab Name 2',
				section: 'Other',
				type: 'input'
			},
			{
				name: 'Setting 7',
				tab: 'Tab Name 2',
				section: 'Other',
				type: 'input'
			},
		],
		tabs: [
			// (optional) Additional Custom tab
			{
				name: 'About',
				innerHTML: [
					{
						type: 'h1',
						innerHTML: 'About'
					},
					{
						type: 'p',
						innerHTML: 'about example'
					}
				]
			},
			// (optional) Adding information about a tab referenced by a setting
			{
				name: 'Tab Name 1',
				displayName: 'Tab 1 displayName',
				content: {
					footer: {
						type: 'div',
						innerHTML: 'Tab 1 Footer foo bar'
					}
				}
			}
		],
		// (optional) Change the order of the tabs. Tabs left out will be added after in the order they are referenced by your settings
		tabOrder: ['About', 'Tab Name 1'],
		// (optional) Set the active tab
		activeTab: 'Tab Name 1',
		// (optional) callback that fires before the settings dialog closes
		onBeforeHide: function(e){
			console.log('Settings on before hide');
		}
	};
	
	jMod.Settings(SettingOptions);
	
	setTimeout(function(){
		// Show the settings dialog
		console.log('Show jMod Settings');
		jMod.Settings.show();
		console.log('Setting 1 Value: ', jMod.Settings.get('Setting 1'));
		console.log('Setting 1 Default: ', jMod.Settings.getDefault('Setting 1'));
	},100);
	
};

jMod.onReady = SettingsTest;

License

This User Script Library is made by jgjake2 and is 100% FREE under the GNU General Public License Version 3 (GNU GPL v3)

If you want to show your support for jMod, you can buy me a beer or coffee via the PayPal donate button below. :)

Contact

Feel free to get in touch if you have any questions or suggestions.

Want to request a feature?

I don't tweet often, but when I do it's usually about #jMod and #myUserJS related resources/content at @Eric_A_Gardner

jgjake2
jMod Creator

Get Connected