fn

Contains common function utility methods.

Members


<static, readonly> CONTAINS_SUPER :RegExp

The regular expression to test if a function uses the this._super method applied by the FooGallery.utils.fn.add method.

Description

When the script is first loaded into the page this performs a quick check to see if the browser supports function decompilation. If it does the regular expression is set to match the expected _super, however if function decompilation is not supported, the regular expression is set to match anything effectively making the test always return true.

Examples

// alias the FooGallery.utils.fn namespace
var _fn = FooGallery.utils.fn;

// create some functions to test
function testFn1(){}
function testFn2(){
	this._super();
}

console.log( _fn.CONTAINS_SUPER.test( testFn1 ) ); // => false
console.log( _fn.CONTAINS_SUPER.test( testFn2 ) ); // => true

// NOTE: in browsers that don't support functional decompilation both tests will return `true`

Details
RegExp

/\b_super\b/


<static> resolved :Promise

A resolved promise object.

Details
Promise

<static> resolved :Promise

A rejected promise object.

Details
Promise

Methods


<static> addOrOverride( proto, name, fn )

Adds or overrides the given method name on the proto using the supplied fn.

Description

If the new method overrides a pre-existing one, this function will expose the overridden method as this._super within the new methods scope.

This replaces having to write out the following to override a method and call its original:

var original = MyClass.prototype.someMethod;
			MyClass.prototype.someMethod = function(arg1, arg2){
			    // execute the original
			    original.call(this, arg1, arg2);
			};

With the following:

FooGallery.utils.fn.addOrOverride( MyClass.prototype, "someMethod", function(arg1, arg2){
			    // execute the original
			    this._super(arg1, arg2);
			});

This method is used by the FooGallery.utils.Class to implement the inheritance of individual methods.

Parameters
Name Type Description
proto Object

The prototype to add the method to.

name string

The name of the method to add, if this already exists the original will be exposed within the scope of the supplied fn as this._super.

fn function

The function to add to the prototype, if this is overriding an existing method you can use this._super to access the original within its' scope.

Examples

// alias the FooGallery.utils.fn namespace
var _fn = FooGallery.utils.fn;

var proto = {
	write: function( message ){
		console.log( "Original#write: " + message );
	}
};

proto.write( "My message" ); // => "Original#write: My message"

_fn.addOrOverride( proto, "write", function( message ){
	message = "Override#write: " + message;
	this._super( message );
} );

proto.write( "My message" ); // => "Original#write: Override#write: My message"


<static> apply( klass [, args ] ) → {function}

Use the Function.prototype.apply method on a class constructor using the new keyword.

Description

When using the default Function.prototype.apply you can't use it on class constructors requiring the new keyword, this method allows us to do that.

Parameters
Name Type Attributes Default Description
klass Object

The class to create.

args Array <optional>
[]

The arguments to pass to the constructor.

Returns

The new instance of the klass created with the supplied args.

Examples

// alias the FooGallery.utils.fn namespace
var _fn = FooGallery.utils.fn;

// create a class to test with
function Test( name, value ){
	if ( !( this instanceof Test )){
		console.log( "Test instantiated without the `new` keyword." );
		return;
	}
	console.log( "Test: name = " + name + ", value = " + value );
}

Test.apply( Test, ["My name", "My value"] ); // => "Test instantiated without the `new` keyword."
_fn.apply( Test, ["My name", "My value"] ); // => "Test: name = My name, value = My value"


<static> arg2arr( args ) → {Array}

Converts the default arguments object into a proper array.

Description

This method is simply a replacement for calling Array.prototype.slice.call() to create an array from an arguments object.

Parameters
Name Type Description
args Arguments

The arguments object to create an array from.

Returns
Examples

// alias the FooGallery.utils.fn namespace
var _fn = FooGallery.utils.fn;

function callMe(){
	var args = _fn.arg2arr(arguments);
	console.log( arguments instanceof Array ); // => false
	console.log( args instanceof Array ); // => true
	console.log( args ); // => [ "arg1", "arg2" ]
}

callMe("arg1", "arg2");


<static> check( thisArg, value [, def [, ctx ] ] ) → {function}

Checks the given value and ensures a function is returned.

Description

This function is primarily used to check the value of a callback option that could be supplied as either a function or a string.

When just the function name is supplied this method uses the FooGallery.utils.fn.fetch method to resolve and wrap it to ensure when it's called the correct context is applied.

Being able to resolve a function from a name allows callbacks to be easily set even through data attributes as you can just supply the full function name as a string and then use this method to retrieve the actual function.

Parameters
Name Type Attributes Default Description
thisArg Object <nullable>
window

The this keyword within the returned function, if the supplied value is not an object this defaults to the window.

value *

The value to check, if not a function or the name of one then the def value is automatically returned.

def function <optional>
jQuery.noop

A default function to use if the value is not resolved to a function.

ctx Object <optional>
window

If the value is a string this is supplied to the FooGallery.utils.fn.fetch method as the content to retrieve the function from.

Returns

A function that ensures the correct context is applied when executed.

Examples

// alias the FooGallery.utils.fn namespace
var _fn = FooGallery.utils.fn;

// a simple `api` with a `sendMessage` function
window.api = {
	sendMessage: function(){
		this.write( "window.api.sendMessage" );
	},
	child: {
		api: {
			sendMessage: function(){
				this.write( "window.api.child.api.sendMessage" );
			}
		}
	}
};

// a default function to use in case the check fails
var def = function(){
	this.write( "default" );
};

// an object to use as the `this` object within the scope of the checked functions
var thisArg = {
	write: function( message ){
		console.log( message );
	}
};

// check the value and return a wrapped function ensuring the correct context.
var fn = _fn.check( thisArg, null, def );
fn(); // => "default"

fn = _fn.check( thisArg, "api.doesNotExist", def );
fn(); // => "default"

fn = _fn.check( thisArg, api.sendMessage, def );
fn(); // => "window.api.sendMessage"

fn = _fn.check( thisArg, "api.sendMessage", def );
fn(); // => "window.api.sendMessage"

fn = _fn.check( thisArg, "api.sendMessage", def, window.api.child );
fn(); // => "window.api.child.api.sendMessage"


<static> fetch( name [, ctx ] ) → {function}

Fetches a function given its name.

Parameters
Name Type Attributes Default Description
name string

The name of the function to fetch. This can be a . notated name.

ctx Object <optional>
window

The context to retrieve the function from, defaults to the window object.

Returns

null if a function with the given name is not found within the context.

Examples

// alias the FooGallery.utils.fn namespace
var _fn = FooGallery.utils.fn;

// create a dummy `api` with a `sendMessage` function to test
window.api = {
	sendMessage: function( message ){
		console.log( "api.sendMessage: " + message );
	}
};

// the below shows 3 different ways to fetch the `sendMessage` function
var send1 = _fn.fetch( "api.sendMessage" );
var send2 = _fn.fetch( "api.sendMessage", window );
var send3 = _fn.fetch( "sendMessage", window.api );

// all the retrieved methods should be the same
console.log( send1 === send2 && send2 === send3 ); // => true

// check if the function was found
if ( send1 != null ){
	send1( "My message" ); // => "api.sendMessage: My message"
}


<static> enqueue( objects, name [, arg1 [, ...argN ] ] ) → {Promise}

Enqueues methods using the given name from all supplied objects and executes each in order with the given arguments.

Description

This method allows an array of objects that implement a common set of methods to be executed in a supplied order. Each method in the queue is only executed after the successful completion of the previous. Success is evaluated as the method did not throw an error and if it returned a promise it was resolved.

An example of this being used within the plugin is the loading and execution of methods on the various components. Using this method ensures components are loaded and have their methods executed in a static order regardless of when they were registered with the plugin or if the method is async. This way if ComponentB's preinit relies on properties set in ComponentA's preinit method you can register ComponentB with a lower priority than ComponentA and you can be assured ComponentA's preinit completed successfully before ComponentB's preinit is called event if it performs an async operation.

Parameters
Name Type Attributes Description
objects Array.<Object>

The objects to call the method on.

name string

The name of the method to execute.

arg1 * <optional>

The first argument to call the method with.

argN * <optional>
<repeatable>

Any additional arguments for the method.

Returns

If resolved the first argument supplied to any success callbacks is an array of all returned value(s). These values are encapsulated within their own array as if the method returned a promise it could be resolved with more than one argument.

If rejected any fail callbacks are supplied the arguments the promise was rejected with plus an additional one appended by this method, an array of all objects that have already had their methods run. This allows you to perform rollback operations if required after a failure. The last object in this array would contain the method that raised the error.

Examples

Shows a basic example of how you can use this method.


// alias the FooGallery.utils.fn namespace
var _fn = FooGallery.utils.fn;

// create some dummy objects that implement the same members or methods.
var obj1 = {
	"name": "obj1",
	"appendName": function(str){
		console.log( "Executing obj1.appendName..." );
		return str + this.name;
	}
};

// this objects `appendName` method returns a promise
var obj2 = {
	"name": "obj2",
	"appendName": function(str){
		console.log( "Executing obj2.appendName..." );
		var self = this;
		return $.Deferred(function(def){
			// use a setTimeout to delay execution
			setTimeout(function(){
					def.resolve(str + self.name);
			}, 300);
		});
	}
};

// this objects `appendName` method is only executed once obj2's promise is resolved
var obj3 = {
	"name": "obj3",
	"appendName": function(str){
		console.log( "Executing obj3.appendName..." );
		return str + this.name;
	}
};

_fn.enqueue( [obj1, obj2, obj3], "appendName", "modified_by:" ).then(function(results){
	console.log( results ); // => [ [ "modified_by:obj1" ], [ "modified_by:obj2" ], [ "modified_by:obj3" ] ]
});

If an error is thrown by one of the called methods or it returns a promise that is rejected, execution is halted and any fail callbacks are executed. The last argument is an array of objects that have had their methods run, the last object within this array is the one that raised the error.


// alias the FooGallery.utils.fn namespace
var _fn = FooGallery.utils.fn;

// create some dummy objects that implement the same members or methods.
var obj1 = {
	"name": "obj1",
	"last": null,
	"appendName": function(str){
		console.log( "Executing obj1.appendName..." );
		return this.last = str + this.name;
	},
	"rollback": function(){
		console.log( "Executing obj1.rollback..." );
		this.last = null;
	}
};

// this objects `appendName` method throws an error
var obj2 = {
	"name": "obj2",
	"last": null,
	"appendName": function(str){
		console.log( "Executing obj2.appendName..." );
		//throw new Error("Oops, something broke.");
		var self = this;
		return $.Deferred(function(def){
			// use a setTimeout to delay execution
			setTimeout(function(){
					self.last = str + self.name;
					def.reject(Error("Oops, something broke."));
			}, 300);
		});
	},
	"rollback": function(){
		console.log( "Executing obj2.rollback..." );
		this.last = null;
	}
};

// this objects `appendName` and `rollback` methods are never executed
var obj3 = {
	"name": "obj3",
	"last": null,
	"appendName": function(str){
		console.log( "Executing obj3.appendName..." );
		return this.last = str + this.name;
	},
	"rollback": function(){
		console.log( "Executing obj3.rollback..." );
		this.last = null;
	}
};

_fn.enqueue( [obj1, obj2, obj3], "appendName", "modified_by:" ).fail(function(err, run){
	console.log( err.message ); // => "Oops, something broke."
	console.log( run ); // => [ {"name":"obj1","last":"modified_by:obj1"}, {"name":"obj2","last":"modified_by:obj2"} ]
	var guilty = run[run.length - 1];
	console.log( "Error thrown by: " + guilty.name ); // => "obj2"
	run.reverse(); // reverse execution when rolling back to avoid dependency issues
	return _fn.enqueue( run, "rollback" ).then(function(){
		console.log( "Error handled and rollback performed." );
		console.log( run ); // => [ {"name":"obj1","last":null}, {"name":"obj2","last":null} ]
	});
});


<static> when( promises ) → {Promise}

Waits for the outcome of all promises regardless of failure and resolves supplying the results of just those that succeeded.

Parameters
Name Type Description
promises Array.<Promise>

The array of promises to wait for.

Returns

<static> rejectWith( [ arg1 [, ...argN ] ] ) → {Promise}

Return a promise rejected using the supplied args.

Parameters
Name Type Attributes Description
arg1 * <optional>

The first argument to reject the promise with.

argN * <optional>
<repeatable>

Any additional arguments to reject the promise with.

Returns

<static> resolveWith( [ arg1 [, ...argN ] ] ) → {Promise}

Return a promise resolved using the supplied args.

Parameters
Name Type Attributes Description
arg1 * <optional>

The first argument to resolve the promise with.

argN * <optional>
<repeatable>

Any additional arguments to resolve the promise with.

Returns