/*!
 * jQuery JavaScript Library v2.1.1
 * http://jquery.com/
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 *
 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2014-05-01T17:11Z
 */

(function( global, factory ) {

	if ( typeof module === "object" && typeof module.exports === "object" ) {
		// For CommonJS and CommonJS-like environments where a proper window is present,
		// execute the factory and get jQuery
		// For environments that do not inherently posses a window with a document
		// (such as Node.js), expose a jQuery-making factory as module.exports
		// This accentuates the need for the creation of a real window
		// e.g. var jQuery = require("jquery")(window);
		// See ticket #14549 for more info
		module.exports = global.document ?
			factory( global, true ) :
			function( w ) {
				if ( !w.document ) {
					throw new Error( "jQuery requires a window with a document" );
				}
				return factory( w );
			};
	} else {
		factory( global );
	}

// Pass this if window is not defined yet
}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {

// Can't do this because several apps including ASP.NET trace
// the stack via arguments.caller.callee and Firefox dies if
// you try to trace through "use strict" call chains. (#13335)
// Support: Firefox 18+
//

var arr = [];

var slice = arr.slice;

var concat = arr.concat;

var push = arr.push;

var indexOf = arr.indexOf;

var class2type = {};

var toString = class2type.toString;

var hasOwn = class2type.hasOwnProperty;

var support = {};



var
	// Use the correct document accordingly with window argument (sandbox)
	document = window.document,

	version = "2.1.1",

	// Define a local copy of jQuery
	jQuery = function( selector, context ) {
		// The jQuery object is actually just the init constructor 'enhanced'
		// Need init if jQuery is called (just allow error to be thrown if not included)
		return new jQuery.fn.init( selector, context );
	},

	// Support: Android<4.1
	// Make sure we trim BOM and NBSP
	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,

	// Matches dashed string for camelizing
	rmsPrefix = /^-ms-/,
	rdashAlpha = /-([\da-z])/gi,

	// Used by jQuery.camelCase as callback to replace()
	fcamelCase = function( all, letter ) {
		return letter.toUpperCase();
	};

jQuery.fn = jQuery.prototype = {
	// The current version of jQuery being used
	jquery: version,

	constructor: jQuery,

	// Start with an empty selector
	selector: "",

	// The default length of a jQuery object is 0
	length: 0,

	toArray: function() {
		return slice.call( this );
	},

	// Get the Nth element in the matched element set OR
	// Get the whole matched element set as a clean array
	get: function( num ) {
		return num != null ?

			// Return just the one element from the set
			( num < 0 ? this[ num + this.length ] : this[ num ] ) :

			// Return all the elements in a clean array
			slice.call( this );
	},

	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems ) {

		// Build a new jQuery matched element set
		var ret = jQuery.merge( this.constructor(), elems );

		// Add the old object onto the stack (as a reference)
		ret.prevObject = this;
		ret.context = this.context;

		// Return the newly-formed element set
		return ret;
	},

	// Execute a callback for every element in the matched set.
	// (You can seed the arguments with an array of args, but this is
	// only used internally.)
	each: function( callback, args ) {
		return jQuery.each( this, callback, args );
	},

	map: function( callback ) {
		return this.pushStack( jQuery.map(this, function( elem, i ) {
			return callback.call( elem, i, elem );
		}));
	},

	slice: function() {
		return this.pushStack( slice.apply( this, arguments ) );
	},

	first: function() {
		return this.eq( 0 );
	},

	last: function() {
		return this.eq( -1 );
	},

	eq: function( i ) {
		var len = this.length,
			j = +i + ( i < 0 ? len : 0 );
		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
	},

	end: function() {
		return this.prevObject || this.constructor(null);
	},

	// For internal use only.
	// Behaves like an Array's method, not like a jQuery method.
	push: push,
	sort: arr.sort,
	splice: arr.splice
};

jQuery.extend = jQuery.fn.extend = function() {
	var options, name, src, copy, copyIsArray, clone,
		target = arguments[0] || {},
		i = 1,
		length = arguments.length,
		deep = false;

	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;

		// skip the boolean and the target
		target = arguments[ i ] || {};
		i++;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
		target = {};
	}

	// extend jQuery itself if only one argument is passed
	if ( i === length ) {
		target = this;
		i--;
	}

	for ( ; i < length; i++ ) {
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null ) {
			// Extend the base object
			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];

				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}

				// Recurse if we're merging plain objects or arrays
				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
					if ( copyIsArray ) {
						copyIsArray = false;
						clone = src && jQuery.isArray(src) ? src : [];

					} else {
						clone = src && jQuery.isPlainObject(src) ? src : {};
					}

					// Never move original objects, clone them
					target[ name ] = jQuery.extend( deep, clone, copy );

				// Don't bring in undefined values
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}

	// Return the modified object
	return target;
};

jQuery.extend({
	// Unique for each copy of jQuery on the page
	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),

	// Assume jQuery is ready without the ready module
	isReady: true,

	error: function( msg ) {
		throw new Error( msg );
	},

	noop: function() {},

	// See test/unit/core.js for details concerning isFunction.
	// Since version 1.3, DOM methods and functions like alert
	// aren't supported. They return false on IE (#2968).
	isFunction: function( obj ) {
		return jQuery.type(obj) === "function";
	},

	isArray: Array.isArray,

	isWindow: function( obj ) {
		return obj != null && obj === obj.window;
	},

	isNumeric: function( obj ) {
		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
		// subtraction forces infinities to NaN
		return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0;
	},

	isPlainObject: function( obj ) {
		// Not plain objects:
		// - Any object or value whose internal [[Class]] property is not "[object Object]"
		// - DOM nodes
		// - window
		if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
			return false;
		}

		if ( obj.constructor &&
				!hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
			return false;
		}

		// If the function hasn't returned already, we're confident that
		// |obj| is a plain object, created by {} or constructed with new Object
		return true;
	},

	isEmptyObject: function( obj ) {
		var name;
		for ( name in obj ) {
			return false;
		}
		return true;
	},

	type: function( obj ) {
		if ( obj == null ) {
			return obj + "";
		}
		// Support: Android < 4.0, iOS < 6 (functionish RegExp)
		return typeof obj === "object" || typeof obj === "function" ?
			class2type[ toString.call(obj) ] || "object" :
			typeof obj;
	},

	// Evaluates a script in a global context
	globalEval: function( code ) {
		var script,
			indirect = eval;

		code = jQuery.trim( code );

		if ( code ) {
			// If the code includes a valid, prologue position
			// strict mode pragma, execute code by injecting a
			// script tag into the document.
			if ( code.indexOf("use strict") === 1 ) {
				script = document.createElement("script");
				script.text = code;
				document.head.appendChild( script ).parentNode.removeChild( script );
			} else {
			// Otherwise, avoid the DOM node creation, insertion
			// and removal by using an indirect global eval
				indirect( code );
			}
		}
	},

	// Convert dashed to camelCase; used by the css and data modules
	// Microsoft forgot to hump their vendor prefix (#9572)
	camelCase: function( string ) {
		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
	},

	nodeName: function( elem, name ) {
		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
	},

	// args is for internal usage only
	each: function( obj, callback, args ) {
		var value,
			i = 0,
			length = obj.length,
			isArray = isArraylike( obj );

		if ( args ) {
			if ( isArray ) {
				for ( ; i < length; i++ ) {
					value = callback.apply( obj[ i ], args );

					if ( value === false ) {
						break;
					}
				}
			} else {
				for ( i in obj ) {
					value = callback.apply( obj[ i ], args );

					if ( value === false ) {
						break;
					}
				}
			}

		// A special, fast, case for the most common use of each
		} else {
			if ( isArray ) {
				for ( ; i < length; i++ ) {
					value = callback.call( obj[ i ], i, obj[ i ] );

					if ( value === false ) {
						break;
					}
				}
			} else {
				for ( i in obj ) {
					value = callback.call( obj[ i ], i, obj[ i ] );

					if ( value === false ) {
						break;
					}
				}
			}
		}

		return obj;
	},

	// Support: Android<4.1
	trim: function( text ) {
		return text == null ?
			"" :
			( text + "" ).replace( rtrim, "" );
	},

	// results is for internal usage only
	makeArray: function( arr, results ) {
		var ret = results || [];

		if ( arr != null ) {
			if ( isArraylike( Object(arr) ) ) {
				jQuery.merge( ret,
					typeof arr === "string" ?
					[ arr ] : arr
				);
			} else {
				push.call( ret, arr );
			}
		}

		return ret;
	},

	inArray: function( elem, arr, i ) {
		return arr == null ? -1 : indexOf.call( arr, elem, i );
	},

	merge: function( first, second ) {
		var len = +second.length,
			j = 0,
			i = first.length;

		for ( ; j < len; j++ ) {
			first[ i++ ] = second[ j ];
		}

		first.length = i;

		return first;
	},

	grep: function( elems, callback, invert ) {
		var callbackInverse,
			matches = [],
			i = 0,
			length = elems.length,
			callbackExpect = !invert;

		// Go through the array, only saving the items
		// that pass the validator function
		for ( ; i < length; i++ ) {
			callbackInverse = !callback( elems[ i ], i );
			if ( callbackInverse !== callbackExpect ) {
				matches.push( elems[ i ] );
			}
		}

		return matches;
	},

	// arg is for internal usage only
	map: function( elems, callback, arg ) {
		var value,
			i = 0,
			length = elems.length,
			isArray = isArraylike( elems ),
			ret = [];

		// Go through the array, translating each of the items to their new values
		if ( isArray ) {
			for ( ; i < length; i++ ) {
				value = callback( elems[ i ], i, arg );

				if ( value != null ) {
					ret.push( value );
				}
			}

		// Go through every key on the object,
		} else {
			for ( i in elems ) {
				value = callback( elems[ i ], i, arg );

				if ( value != null ) {
					ret.push( value );
				}
			}
		}

		// Flatten any nested arrays
		return concat.apply( [], ret );
	},

	// A global GUID counter for objects
	guid: 1,

	// Bind a function to a context, optionally partially applying any
	// arguments.
	proxy: function( fn, context ) {
		var tmp, args, proxy;

		if ( typeof context === "string" ) {
			tmp = fn[ context ];
			context = fn;
			fn = tmp;
		}

		// Quick check to determine if target is callable, in the spec
		// this throws a TypeError, but we will just return undefined.
		if ( !jQuery.isFunction( fn ) ) {
			return undefined;
		}

		// Simulated bind
		args = slice.call( arguments, 2 );
		proxy = function() {
			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
		};

		// Set the guid of unique handler to the same of original handler, so it can be removed
		proxy.guid = fn.guid = fn.guid || jQuery.guid++;

		return proxy;
	},

	now: Date.now,

	// jQuery.support is not used in Core but other projects attach their
	// properties to it so it needs to exist.
	support: support
});

// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
	class2type[ "[object " + name + "]" ] = name.toLowerCase();
});

function isArraylike( obj ) {
	var length = obj.length,
		type = jQuery.type( obj );

	if ( type === "function" || jQuery.isWindow( obj ) ) {
		return false;
	}

	if ( obj.nodeType === 1 && length ) {
		return true;
	}

	return type === "array" || length === 0 ||
		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}
var Sizzle =
/*!
 * Sizzle CSS Selector Engine v1.10.19
 * http://sizzlejs.com/
 *
 * Copyright 2013 jQuery Foundation, Inc. and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2014-04-18
 */
(function( window ) {

var i,
	support,
	Expr,
	getText,
	isXML,
	tokenize,
	compile,
	select,
	outermostContext,
	sortInput,
	hasDuplicate,

	// Local document vars
	setDocument,
	document,
	docElem,
	documentIsHTML,
	rbuggyQSA,
	rbuggyMatches,
	matches,
	contains,

	// Instance-specific data
	expando = "sizzle" + -(new Date()),
	preferredDoc = window.document,
	dirruns = 0,
	done = 0,
	classCache = createCache(),
	tokenCache = createCache(),
	compilerCache = createCache(),
	sortOrder = function( a, b ) {
		if ( a === b ) {
			hasDuplicate = true;
		}
		return 0;
	},

	// General-purpose constants
	strundefined = typeof undefined,
	MAX_NEGATIVE = 1 << 31,

	// Instance methods
	hasOwn = ({}).hasOwnProperty,
	arr = [],
	pop = arr.pop,
	push_native = arr.push,
	push = arr.push,
	slice = arr.slice,
	// Use a stripped-down indexOf if we can't use a native one
	indexOf = arr.indexOf || function( elem ) {
		var i = 0,
			len = this.length;
		for ( ; i < len; i++ ) {
			if ( this[i] === elem ) {
				return i;
			}
		}
		return -1;
	},

	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",

	// Regular expressions

	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
	whitespace = "[\\x20\\t\\r\\n\\f]",
	// http://www.w3.org/TR/css3-syntax/#characters
	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",

	// Loosely modeled on CSS identifier characters
	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
	identifier = characterEncoding.replace( "w", "w#" ),

	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
		// Operator (capture 2)
		"*([*^$|!~]?=)" + whitespace +
		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
		"*\\]",

	pseudos = ":(" + characterEncoding + ")(?:\\((" +
		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
		// 1. quoted (capture 3; capture 4 or capture 5)
		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
		// 2. simple (capture 6)
		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
		// 3. anything else (capture 2)
		".*" +
		")\\)|)",

	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),

	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),

	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),

	rpseudo = new RegExp( pseudos ),
	ridentifier = new RegExp( "^" + identifier + "$" ),

	matchExpr = {
		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
		"ATTR": new RegExp( "^" + attributes ),
		"PSEUDO": new RegExp( "^" + pseudos ),
		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
		// For use in libraries implementing .is()
		// We use this for POS matching in `select`
		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
	},

	rinputs = /^(?:input|select|textarea|button)$/i,
	rheader = /^h\d$/i,

	rnative = /^[^{]+\{\s*\[native \w/,

	// Easily-parseable/retrievable ID or TAG or CLASS selectors
	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,

	rsibling = /[+~]/,
	rescape = /'|\\/g,

	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
	funescape = function( _, escaped, escapedWhitespace ) {
		var high = "0x" + escaped - 0x10000;
		// NaN means non-codepoint
		// Support: Firefox<24
		// Workaround erroneous numeric interpretation of +"0x"
		return high !== high || escapedWhitespace ?
			escaped :
			high < 0 ?
				// BMP codepoint
				String.fromCharCode( high + 0x10000 ) :
				// Supplemental Plane codepoint (surrogate pair)
				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
	};

// Optimize for push.apply( _, NodeList )
try {
	push.apply(
		(arr = slice.call( preferredDoc.childNodes )),
		preferredDoc.childNodes
	);
	// Support: Android<4.0
	// Detect silently failing push.apply
	arr[ preferredDoc.childNodes.length ].nodeType;
} catch ( e ) {
	push = { apply: arr.length ?

		// Leverage slice if possible
		function( target, els ) {
			push_native.apply( target, slice.call(els) );
		} :

		// Support: IE<9
		// Otherwise append directly
		function( target, els ) {
			var j = target.length,
				i = 0;
			// Can't trust NodeList.length
			while ( (target[j++] = els[i++]) ) {}
			target.length = j - 1;
		}
	};
}

function Sizzle( selector, context, results, seed ) {
	var match, elem, m, nodeType,
		// QSA vars
		i, groups, old, nid, newContext, newSelector;

	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
		setDocument( context );
	}

	context = context || document;
	results = results || [];

	if ( !selector || typeof selector !== "string" ) {
		return results;
	}

	if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
		return [];
	}

	if ( documentIsHTML && !seed ) {

		// Shortcuts
		if ( (match = rquickExpr.exec( selector )) ) {
			// Speed-up: Sizzle("#ID")
			if ( (m = match[1]) ) {
				if ( nodeType === 9 ) {
					elem = context.getElementById( m );
					// Check parentNode to catch when Blackberry 4.6 returns
					// nodes that are no longer in the document (jQuery #6963)
					if ( elem && elem.parentNode ) {
						// Handle the case where IE, Opera, and Webkit return items
						// by name instead of ID
						if ( elem.id === m ) {
							results.push( elem );
							return results;
						}
					} else {
						return results;
					}
				} else {
					// Context is not a document
					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
						contains( context, elem ) && elem.id === m ) {
						results.push( elem );
						return results;
					}
				}

			// Speed-up: Sizzle("TAG")
			} else if ( match[2] ) {
				push.apply( results, context.getElementsByTagName( selector ) );
				return results;

			// Speed-up: Sizzle(".CLASS")
			} else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
				push.apply( results, context.getElementsByClassName( m ) );
				return results;
			}
		}

		// QSA path
		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
			nid = old = expando;
			newContext = context;
			newSelector = nodeType === 9 && selector;

			// qSA works strangely on Element-rooted queries
			// We can work around this by specifying an extra ID on the root
			// and working up from there (Thanks to Andrew Dupont for the technique)
			// IE 8 doesn't work on object elements
			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
				groups = tokenize( selector );

				if ( (old = context.getAttribute("id")) ) {
					nid = old.replace( rescape, "\\$&" );
				} else {
					context.setAttribute( "id", nid );
				}
				nid = "[id='" + nid + "'] ";

				i = groups.length;
				while ( i-- ) {
					groups[i] = nid + toSelector( groups[i] );
				}
				newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
				newSelector = groups.join(",");
			}

			if ( newSelector ) {
				try {
					push.apply( results,
						newContext.querySelectorAll( newSelector )
					);
					return results;
				} catch(qsaError) {
				} finally {
					if ( !old ) {
						context.removeAttribute("id");
					}
				}
			}
		}
	}

	// All others
	return select( selector.replace( rtrim, "$1" ), context, results, seed );
}

/**
 * Create key-value caches of limited size
 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
 *	deleting the oldest entry
 */
function createCache() {
	var keys = [];

	function cache( key, value ) {
		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
		if ( keys.push( key + " " ) > Expr.cacheLength ) {
			// Only keep the most recent entries
			delete cache[ keys.shift() ];
		}
		return (cache[ key + " " ] = value);
	}
	return cache;
}

/**
 * Mark a function for special use by Sizzle
 * @param {Function} fn The function to mark
 */
function markFunction( fn ) {
	fn[ expando ] = true;
	return fn;
}

/**
 * Support testing using an element
 * @param {Function} fn Passed the created div and expects a boolean result
 */
function assert( fn ) {
	var div = document.createElement("div");

	try {
		return !!fn( div );
	} catch (e) {
		return false;
	} finally {
		// Remove from its parent by default
		if ( div.parentNode ) {
			div.parentNode.removeChild( div );
		}
		// release memory in IE
		div = null;
	}
}

/**
 * Adds the same handler for all of the specified attrs
 * @param {String} attrs Pipe-separated list of attributes
 * @param {Function} handler The method that will be applied
 */
function addHandle( attrs, handler ) {
	var arr = attrs.split("|"),
		i = attrs.length;

	while ( i-- ) {
		Expr.attrHandle[ arr[i] ] = handler;
	}
}

/**
 * Checks document order of two siblings
 * @param {Element} a
 * @param {Element} b
 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
 */
function siblingCheck( a, b ) {
	var cur = b && a,
		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
			( ~b.sourceIndex || MAX_NEGATIVE ) -
			( ~a.sourceIndex || MAX_NEGATIVE );

	// Use IE sourceIndex if available on both nodes
	if ( diff ) {
		return diff;
	}

	// Check if b follows a
	if ( cur ) {
		while ( (cur = cur.nextSibling) ) {
			if ( cur === b ) {
				return -1;
			}
		}
	}

	return a ? 1 : -1;
}

/**
 * Returns a function to use in pseudos for input types
 * @param {String} type
 */
function createInputPseudo( type ) {
	return function( elem ) {
		var name = elem.nodeName.toLowerCase();
		return name === "input" && elem.type === type;
	};
}

/**
 * Returns a function to use in pseudos for buttons
 * @param {String} type
 */
function createButtonPseudo( type ) {
	return function( elem ) {
		var name = elem.nodeName.toLowerCase();
		return (name === "input" || name === "button") && elem.type === type;
	};
}

/**
 * Returns a function to use in pseudos for positionals
 * @param {Function} fn
 */
function createPositionalPseudo( fn ) {
	return markFunction(function( argument ) {
		argument = +argument;
		return markFunction(function( seed, matches ) {
			var j,
				matchIndexes = fn( [], seed.length, argument ),
				i = matchIndexes.length;

			// Match elements found at the specified indexes
			while ( i-- ) {
				if ( seed[ (j = matchIndexes[i]) ] ) {
					seed[j] = !(matches[j] = seed[j]);
				}
			}
		});
	});
}

/**
 * Checks a node for validity as a Sizzle context
 * @param {Element|Object=} context
 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
 */
function testContext( context ) {
	return context && typeof context.getElementsByTagName !== strundefined && context;
}

// Expose support vars for convenience
support = Sizzle.support = {};

/**
 * Detects XML nodes
 * @param {Element|Object} elem An element or a document
 * @returns {Boolean} True iff elem is a non-HTML XML node
 */
isXML = Sizzle.isXML = function( elem ) {
	// documentElement is verified for cases where it doesn't yet exist
	// (such as loading iframes in IE - #4833)
	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
	return documentElement ? documentElement.nodeName !== "HTML" : false;
};

/**
 * Sets document-related variables once based on the current document
 * @param {Element|Object} [doc] An element or document object to use to set the document
 * @returns {Object} Returns the current document
 */
setDocument = Sizzle.setDocument = function( node ) {
	var hasCompare,
		doc = node ? node.ownerDocument || node : preferredDoc,
		parent = doc.defaultView;

	// If no document and documentElement is available, return
	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
		return document;
	}

	// Set our document
	document = doc;
	docElem = doc.documentElement;

	// Support tests
	documentIsHTML = !isXML( doc );

	// Support: IE>8
	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
	// IE6-8 do not support the defaultView property so parent will be undefined
	if ( parent && parent !== parent.top ) {
		// IE11 does not have attachEvent, so all must suffer
		if ( parent.addEventListener ) {
			parent.addEventListener( "unload", function() {
				setDocument();
			}, false );
		} else if ( parent.attachEvent ) {
			parent.attachEvent( "onunload", function() {
				setDocument();
			});
		}
	}

	/* Attributes
	---------------------------------------------------------------------- */

	// Support: IE<8
	// Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
	support.attributes = assert(function( div ) {
		div.className = "i";
		return !div.getAttribute("className");
	});

	/* getElement(s)By*
	---------------------------------------------------------------------- */

	// Check if getElementsByTagName("*") returns only elements
	support.getElementsByTagName = assert(function( div ) {
		div.appendChild( doc.createComment("") );
		return !div.getElementsByTagName("*").length;
	});

	// Check if getElementsByClassName can be trusted
	support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
		div.innerHTML = "<div class='a'></div><div class='a i'></div>";

		// Support: Safari<4
		// Catch class over-caching
		div.firstChild.className = "i";
		// Support: Opera<10
		// Catch gEBCN failure to find non-leading classes
		return div.getElementsByClassName("i").length === 2;
	});

	// Support: IE<10
	// Check if getElementById returns elements by name
	// The broken getElementById methods don't pick up programatically-set names,
	// so use a roundabout getElementsByName test
	support.getById = assert(function( div ) {
		docElem.appendChild( div ).id = expando;
		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
	});

	// ID find and filter
	if ( support.getById ) {
		Expr.find["ID"] = function( id, context ) {
			if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
				var m = context.getElementById( id );
				// Check parentNode to catch when Blackberry 4.6 returns
				// nodes that are no longer in the document #6963
				return m && m.parentNode ? [ m ] : [];
			}
		};
		Expr.filter["ID"] = function( id ) {
			var attrId = id.replace( runescape, funescape );
			return function( elem ) {
				return elem.getAttribute("id") === attrId;
			};
		};
	} else {
		// Support: IE6/7
		// getElementById is not reliable as a find shortcut
		delete Expr.find["ID"];

		Expr.filter["ID"] =  function( id ) {
			var attrId = id.replace( runescape, funescape );
			return function( elem ) {
				var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
				return node && node.value === attrId;
			};
		};
	}

	// Tag
	Expr.find["TAG"] = support.getElementsByTagName ?
		function( tag, context ) {
			if ( typeof context.getElementsByTagName !== strundefined ) {
				return context.getElementsByTagName( tag );
			}
		} :
		function( tag, context ) {
			var elem,
				tmp = [],
				i = 0,
				results = context.getElementsByTagName( tag );

			// Filter out possible comments
			if ( tag === "*" ) {
				while ( (elem = results[i++]) ) {
					if ( elem.nodeType === 1 ) {
						tmp.push( elem );
					}
				}

				return tmp;
			}
			return results;
		};

	// Class
	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
		if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
			return context.getElementsByClassName( className );
		}
	};

	/* QSA/matchesSelector
	---------------------------------------------------------------------- */

	// QSA and matchesSelector support

	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
	rbuggyMatches = [];

	// qSa(:focus) reports false when true (Chrome 21)
	// We allow this because of a bug in IE8/9 that throws an error
	// whenever `document.activeElement` is accessed on an iframe
	// So, we allow :focus to pass through QSA all the time to avoid the IE error
	// See http://bugs.jquery.com/ticket/13378
	rbuggyQSA = [];

	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
		// Build QSA regex
		// Regex strategy adopted from Diego Perini
		assert(function( div ) {
			// Select is set to empty string on purpose
			// This is to test IE's treatment of not explicitly
			// setting a boolean content attribute,
			// since its presence should be enough
			// http://bugs.jquery.com/ticket/12359
			div.innerHTML = "<select msallowclip=''><option selected=''></option></select>";

			// Support: IE8, Opera 11-12.16
			// Nothing should be selected when empty strings follow ^= or $= or *=
			// The test attribute must be unknown in Opera but "safe" for WinRT
			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
			if ( div.querySelectorAll("[msallowclip^='']").length ) {
				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
			}

			// Support: IE8
			// Boolean attributes and "value" are not treated correctly
			if ( !div.querySelectorAll("[selected]").length ) {
				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
			}

			// Webkit/Opera - :checked should return selected option elements
			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
			// IE8 throws error here and will not see later tests
			if ( !div.querySelectorAll(":checked").length ) {
				rbuggyQSA.push(":checked");
			}
		});

		assert(function( div ) {
			// Support: Windows 8 Native Apps
			// The type and name attributes are restricted during .innerHTML assignment
			var input = doc.createElement("input");
			input.setAttribute( "type", "hidden" );
			div.appendChild( input ).setAttribute( "name", "D" );

			// Support: IE8
			// Enforce case-sensitivity of name attribute
			if ( div.querySelectorAll("[name=d]").length ) {
				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
			}

			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
			// IE8 throws error here and will not see later tests
			if ( !div.querySelectorAll(":enabled").length ) {
				rbuggyQSA.push( ":enabled", ":disabled" );
			}

			// Opera 10-11 does not throw on post-comma invalid pseudos
			div.querySelectorAll("*,:x");
			rbuggyQSA.push(",.*:");
		});
	}

	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
		docElem.webkitMatchesSelector ||
		docElem.mozMatchesSelector ||
		docElem.oMatchesSelector ||
		docElem.msMatchesSelector) )) ) {

		assert(function( div ) {
			// Check to see if it's possible to do matchesSelector
			// on a disconnected node (IE 9)
			support.disconnectedMatch = matches.call( div, "div" );

			// This should fail with an exception
			// Gecko does not error, returns false instead
			matches.call( div, "[s!='']:x" );
			rbuggyMatches.push( "!=", pseudos );
		});
	}

	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );

	/* Contains
	---------------------------------------------------------------------- */
	hasCompare = rnative.test( docElem.compareDocumentPosition );

	// Element contains another
	// Purposefully does not implement inclusive descendent
	// As in, an element does not contain itself
	contains = hasCompare || rnative.test( docElem.contains ) ?
		function( a, b ) {
			var adown = a.nodeType === 9 ? a.documentElement : a,
				bup = b && b.parentNode;
			return a === bup || !!( bup && bup.nodeType === 1 && (
				adown.contains ?
					adown.contains( bup ) :
					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
			));
		} :
		function( a, b ) {
			if ( b ) {
				while ( (b = b.parentNode) ) {
					if ( b === a ) {
						return true;
					}
				}
			}
			return false;
		};

	/* Sorting
	---------------------------------------------------------------------- */

	// Document order sorting
	sortOrder = hasCompare ?
	function( a, b ) {

		// Flag for duplicate removal
		if ( a === b ) {
			hasDuplicate = true;
			return 0;
		}

		// Sort on method existence if only one input has compareDocumentPosition
		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
		if ( compare ) {
			return compare;
		}

		// Calculate position if both inputs belong to the same document
		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
			a.compareDocumentPosition( b ) :

			// Otherwise we know they are disconnected
			1;

		// Disconnected nodes
		if ( compare & 1 ||
			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {

			// Choose the first element that is related to our preferred document
			if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
				return -1;
			}
			if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
				return 1;
			}

			// Maintain original order
			return sortInput ?
				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
				0;
		}

		return compare & 4 ? -1 : 1;
	} :
	function( a, b ) {
		// Exit early if the nodes are identical
		if ( a === b ) {
			hasDuplicate = true;
			return 0;
		}

		var cur,
			i = 0,
			aup = a.parentNode,
			bup = b.parentNode,
			ap = [ a ],
			bp = [ b ];

		// Parentless nodes are either documents or disconnected
		if ( !aup || !bup ) {
			return a === doc ? -1 :
				b === doc ? 1 :
				aup ? -1 :
				bup ? 1 :
				sortInput ?
				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
				0;

		// If the nodes are siblings, we can do a quick check
		} else if ( aup === bup ) {
			return siblingCheck( a, b );
		}

		// Otherwise we need full lists of their ancestors for comparison
		cur = a;
		while ( (cur = cur.parentNode) ) {
			ap.unshift( cur );
		}
		cur = b;
		while ( (cur = cur.parentNode) ) {
			bp.unshift( cur );
		}

		// Walk down the tree looking for a discrepancy
		while ( ap[i] === bp[i] ) {
			i++;
		}

		return i ?
			// Do a sibling check if the nodes have a common ancestor
			siblingCheck( ap[i], bp[i] ) :

			// Otherwise nodes in our document sort first
			ap[i] === preferredDoc ? -1 :
			bp[i] === preferredDoc ? 1 :
			0;
	};

	return doc;
};

Sizzle.matches = function( expr, elements ) {
	return Sizzle( expr, null, null, elements );
};

Sizzle.matchesSelector = function( elem, expr ) {
	// Set document vars if needed
	if ( ( elem.ownerDocument || elem ) !== document ) {
		setDocument( elem );
	}

	// Make sure that attribute selectors are quoted
	expr = expr.replace( rattributeQuotes, "='$1']" );

	if ( support.matchesSelector && documentIsHTML &&
		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {

		try {
			var ret = matches.call( elem, expr );

			// IE 9's matchesSelector returns false on disconnected nodes
			if ( ret || support.disconnectedMatch ||
					// As well, disconnected nodes are said to be in a document
					// fragment in IE 9
					elem.document && elem.document.nodeType !== 11 ) {
				return ret;
			}
		} catch(e) {}
	}

	return Sizzle( expr, document, null, [ elem ] ).length > 0;
};

Sizzle.contains = function( context, elem ) {
	// Set document vars if needed
	if ( ( context.ownerDocument || context ) !== document ) {
		setDocument( context );
	}
	return contains( context, elem );
};

Sizzle.attr = function( elem, name ) {
	// Set document vars if needed
	if ( ( elem.ownerDocument || elem ) !== document ) {
		setDocument( elem );
	}

	var fn = Expr.attrHandle[ name.toLowerCase() ],
		// Don't get fooled by Object.prototype properties (jQuery #13807)
		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
			fn( elem, name, !documentIsHTML ) :
			undefined;

	return val !== undefined ?
		val :
		support.attributes || !documentIsHTML ?
			elem.getAttribute( name ) :
			(val = elem.getAttributeNode(name)) && val.specified ?
				val.value :
				null;
};

Sizzle.error = function( msg ) {
	throw new Error( "Syntax error, unrecognized expression: " + msg );
};

/**
 * Document sorting and removing duplicates
 * @param {ArrayLike} results
 */
Sizzle.uniqueSort = function( results ) {
	var elem,
		duplicates = [],
		j = 0,
		i = 0;

	// Unless we *know* we can detect duplicates, assume their presence
	hasDuplicate = !support.detectDuplicates;
	sortInput = !support.sortStable && results.slice( 0 );
	results.sort( sortOrder );

	if ( hasDuplicate ) {
		while ( (elem = results[i++]) ) {
			if ( elem === results[ i ] ) {
				j = duplicates.push( i );
			}
		}
		while ( j-- ) {
			results.splice( duplicates[ j ], 1 );
		}
	}

	// Clear input after sorting to release objects
	// See https://github.com/jquery/sizzle/pull/225
	sortInput = null;

	return results;
};

/**
 * Utility function for retrieving the text value of an array of DOM nodes
 * @param {Array|Element} elem
 */
getText = Sizzle.getText = function( elem ) {
	var node,
		ret = "",
		i = 0,
		nodeType = elem.nodeType;

	if ( !nodeType ) {
		// If no nodeType, this is expected to be an array
		while ( (node = elem[i++]) ) {
			// Do not traverse comment nodes
			ret += getText( node );
		}
	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
		// Use textContent for elements
		// innerText usage removed for consistency of new lines (jQuery #11153)
		if ( typeof elem.textContent === "string" ) {
			return elem.textContent;
		} else {
			// Traverse its children
			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
				ret += getText( elem );
			}
		}
	} else if ( nodeType === 3 || nodeType === 4 ) {
		return elem.nodeValue;
	}
	// Do not include comment or processing instruction nodes

	return ret;
};

Expr = Sizzle.selectors = {

	// Can be adjusted by the user
	cacheLength: 50,

	createPseudo: markFunction,

	match: matchExpr,

	attrHandle: {},

	find: {},

	relative: {
		">": { dir: "parentNode", first: true },
		" ": { dir: "parentNode" },
		"+": { dir: "previousSibling", first: true },
		"~": { dir: "previousSibling" }
	},

	preFilter: {
		"ATTR": function( match ) {
			match[1] = match[1].replace( runescape, funescape );

			// Move the given value to match[3] whether quoted or unquoted
			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );

			if ( match[2] === "~=" ) {
				match[3] = " " + match[3] + " ";
			}

			return match.slice( 0, 4 );
		},

		"CHILD": function( match ) {
			/* matches from matchExpr["CHILD"]
				1 type (only|nth|...)
				2 what (child|of-type)
				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
				4 xn-component of xn+y argument ([+-]?\d*n|)
				5 sign of xn-component
				6 x of xn-component
				7 sign of y-component
				8 y of y-component
			*/
			match[1] = match[1].toLowerCase();

			if ( match[1].slice( 0, 3 ) === "nth" ) {
				// nth-* requires argument
				if ( !match[3] ) {
					Sizzle.error( match[0] );
				}

				// numeric x and y parameters for Expr.filter.CHILD
				// remember that false/true cast respectively to 0/1
				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );

			// other types prohibit arguments
			} else if ( match[3] ) {
				Sizzle.error( match[0] );
			}

			return match;
		},

		"PSEUDO": function( match ) {
			var excess,
				unquoted = !match[6] && match[2];

			if ( matchExpr["CHILD"].test( match[0] ) ) {
				return null;
			}

			// Accept quoted arguments as-is
			if ( match[3] ) {
				match[2] = match[4] || match[5] || "";

			// Strip excess characters from unquoted arguments
			} else if ( unquoted && rpseudo.test( unquoted ) &&
				// Get excess from tokenize (recursively)
				(excess = tokenize( unquoted, true )) &&
				// advance to the next closing parenthesis
				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {

				// excess is a negative index
				match[0] = match[0].slice( 0, excess );
				match[2] = unquoted.slice( 0, excess );
			}

			// Return only captures needed by the pseudo filter method (type and argument)
			return match.slice( 0, 3 );
		}
	},

	filter: {

		"TAG": function( nodeNameSelector ) {
			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
			return nodeNameSelector === "*" ?
				function() { return true; } :
				function( elem ) {
					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
				};
		},

		"CLASS": function( className ) {
			var pattern = classCache[ className + " " ];

			return pattern ||
				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
				classCache( className, function( elem ) {
					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
				});
		},

		"ATTR": function( name, operator, check ) {
			return function( elem ) {
				var result = Sizzle.attr( elem, name );

				if ( result == null ) {
					return operator === "!=";
				}
				if ( !operator ) {
					return true;
				}

				result += "";

				return operator === "=" ? result === check :
					operator === "!=" ? result !== check :
					operator === "^=" ? check && result.indexOf( check ) === 0 :
					operator === "*=" ? check && result.indexOf( check ) > -1 :
					operator === "$=" ? check && result.slice( -check.length ) === check :
					operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
					false;
			};
		},

		"CHILD": function( type, what, argument, first, last ) {
			var simple = type.slice( 0, 3 ) !== "nth",
				forward = type.slice( -4 ) !== "last",
				ofType = what === "of-type";

			return first === 1 && last === 0 ?

				// Shortcut for :nth-*(n)
				function( elem ) {
					return !!elem.parentNode;
				} :

				function( elem, context, xml ) {
					var cache, outerCache, node, diff, nodeIndex, start,
						dir = simple !== forward ? "nextSibling" : "previousSibling",
						parent = elem.parentNode,
						name = ofType && elem.nodeName.toLowerCase(),
						useCache = !xml && !ofType;

					if ( parent ) {

						// :(first|last|only)-(child|of-type)
						if ( simple ) {
							while ( dir ) {
								node = elem;
								while ( (node = node[ dir ]) ) {
									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
										return false;
									}
								}
								// Reverse direction for :only-* (if we haven't yet done so)
								start = dir = type === "only" && !start && "nextSibling";
							}
							return true;
						}

						start = [ forward ? parent.firstChild : parent.lastChild ];

						// non-xml :nth-child(...) stores cache data on `parent`
						if ( forward && useCache ) {
							// Seek `elem` from a previously-cached index
							outerCache = parent[ expando ] || (parent[ expando ] = {});
							cache = outerCache[ type ] || [];
							nodeIndex = cache[0] === dirruns && cache[1];
							diff = cache[0] === dirruns && cache[2];
							node = nodeIndex && parent.childNodes[ nodeIndex ];

							while ( (node = ++nodeIndex && node && node[ dir ] ||

								// Fallback to seeking `elem` from the start
								(diff = nodeIndex = 0) || start.pop()) ) {

								// When found, cache indexes on `parent` and break
								if ( node.nodeType === 1 && ++diff && node === elem ) {
									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
									break;
								}
							}

						// Use previously-cached element index if available
						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
							diff = cache[1];

						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
						} else {
							// Use the same loop as above to seek `elem` from the start
							while ( (node = ++nodeIndex && node && node[ dir ] ||
								(diff = nodeIndex = 0) || start.pop()) ) {

								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
									// Cache the index of each encountered element
									if ( useCache ) {
										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
									}

									if ( node === elem ) {
										break;
									}
								}
							}
						}

						// Incorporate the offset, then check against cycle size
						diff -= last;
						return diff === first || ( diff % first === 0 && diff / first >= 0 );
					}
				};
		},

		"PSEUDO": function( pseudo, argument ) {
			// pseudo-class names are case-insensitive
			// http://www.w3.org/TR/selectors/#pseudo-classes
			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
			// Remember that setFilters inherits from pseudos
			var args,
				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
					Sizzle.error( "unsupported pseudo: " + pseudo );

			// The user may use createPseudo to indicate that
			// arguments are needed to create the filter function
			// just as Sizzle does
			if ( fn[ expando ] ) {
				return fn( argument );
			}

			// But maintain support for old signatures
			if ( fn.length > 1 ) {
				args = [ pseudo, pseudo, "", argument ];
				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
					markFunction(function( seed, matches ) {
						var idx,
							matched = fn( seed, argument ),
							i = matched.length;
						while ( i-- ) {
							idx = indexOf.call( seed, matched[i] );
							seed[ idx ] = !( matches[ idx ] = matched[i] );
						}
					}) :
					function( elem ) {
						return fn( elem, 0, args );
					};
			}

			return fn;
		}
	},

	pseudos: {
		// Potentially complex pseudos
		"not": markFunction(function( selector ) {
			// Trim the selector passed to compile
			// to avoid treating leading and trailing
			// spaces as combinators
			var input = [],
				results = [],
				matcher = compile( selector.replace( rtrim, "$1" ) );

			return matcher[ expando ] ?
				markFunction(function( seed, matches, context, xml ) {
					var elem,
						unmatched = matcher( seed, null, xml, [] ),
						i = seed.length;

					// Match elements unmatched by `matcher`
					while ( i-- ) {
						if ( (elem = unmatched[i]) ) {
							seed[i] = !(matches[i] = elem);
						}
					}
				}) :
				function( elem, context, xml ) {
					input[0] = elem;
					matcher( input, null, xml, results );
					return !results.pop();
				};
		}),

		"has": markFunction(function( selector ) {
			return function( elem ) {
				return Sizzle( selector, elem ).length > 0;
			};
		}),

		"contains": markFunction(function( text ) {
			return function( elem ) {
				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
			};
		}),

		// "Whether an element is represented by a :lang() selector
		// is based solely on the element's language value
		// being equal to the identifier C,
		// or beginning with the identifier C immediately followed by "-".
		// The matching of C against the element's language value is performed case-insensitively.
		// The identifier C does not have to be a valid language name."
		// http://www.w3.org/TR/selectors/#lang-pseudo
		"lang": markFunction( function( lang ) {
			// lang value must be a valid identifier
			if ( !ridentifier.test(lang || "") ) {
				Sizzle.error( "unsupported lang: " + lang );
			}
			lang = lang.replace( runescape, funescape ).toLowerCase();
			return function( elem ) {
				var elemLang;
				do {
					if ( (elemLang = documentIsHTML ?
						elem.lang :
						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {

						elemLang = elemLang.toLowerCase();
						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
					}
				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
				return false;
			};
		}),

		// Miscellaneous
		"target": function( elem ) {
			var hash = window.location && window.location.hash;
			return hash && hash.slice( 1 ) === elem.id;
		},

		"root": function( elem ) {
			return elem === docElem;
		},

		"focus": function( elem ) {
			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
		},

		// Boolean properties
		"enabled": function( elem ) {
			return elem.disabled === false;
		},

		"disabled": function( elem ) {
			return elem.disabled === true;
		},

		"checked": function( elem ) {
			// In CSS3, :checked should return both checked and selected elements
			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
			var nodeName = elem.nodeName.toLowerCase();
			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
		},

		"selected": function( elem ) {
			// Accessing this property makes selected-by-default
			// options in Safari work properly
			if ( elem.parentNode ) {
				elem.parentNode.selectedIndex;
			}

			return elem.selected === true;
		},

		// Contents
		"empty": function( elem ) {
			// http://www.w3.org/TR/selectors/#empty-pseudo
			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
			//   but not by others (comment: 8; processing instruction: 7; etc.)
			// nodeType < 6 works because attributes (2) do not appear as children
			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
				if ( elem.nodeType < 6 ) {
					return false;
				}
			}
			return true;
		},

		"parent": function( elem ) {
			return !Expr.pseudos["empty"]( elem );
		},

		// Element/input types
		"header": function( elem ) {
			return rheader.test( elem.nodeName );
		},

		"input": function( elem ) {
			return rinputs.test( elem.nodeName );
		},

		"button": function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return name === "input" && elem.type === "button" || name === "button";
		},

		"text": function( elem ) {
			var attr;
			return elem.nodeName.toLowerCase() === "input" &&
				elem.type === "text" &&

				// Support: IE<8
				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
		},

		// Position-in-collection
		"first": createPositionalPseudo(function() {
			return [ 0 ];
		}),

		"last": createPositionalPseudo(function( matchIndexes, length ) {
			return [ length - 1 ];
		}),

		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
			return [ argument < 0 ? argument + length : argument ];
		}),

		"even": createPositionalPseudo(function( matchIndexes, length ) {
			var i = 0;
			for ( ; i < length; i += 2 ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		}),

		"odd": createPositionalPseudo(function( matchIndexes, length ) {
			var i = 1;
			for ( ; i < length; i += 2 ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		}),

		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
			var i = argument < 0 ? argument + length : argument;
			for ( ; --i >= 0; ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		}),

		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
			var i = argument < 0 ? argument + length : argument;
			for ( ; ++i < length; ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		})
	}
};

Expr.pseudos["nth"] = Expr.pseudos["eq"];

// Add button/input type pseudos
for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
	Expr.pseudos[ i ] = createInputPseudo( i );
}
for ( i in { submit: true, reset: true } ) {
	Expr.pseudos[ i ] = createButtonPseudo( i );
}

// Easy API for creating new setFilters
function setFilters() {}
setFilters.prototype = Expr.filters = Expr.pseudos;
Expr.setFilters = new setFilters();

tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
	var matched, match, tokens, type,
		soFar, groups, preFilters,
		cached = tokenCache[ selector + " " ];

	if ( cached ) {
		return parseOnly ? 0 : cached.slice( 0 );
	}

	soFar = selector;
	groups = [];
	preFilters = Expr.preFilter;

	while ( soFar ) {

		// Comma and first run
		if ( !matched || (match = rcomma.exec( soFar )) ) {
			if ( match ) {
				// Don't consume trailing commas as valid
				soFar = soFar.slice( match[0].length ) || soFar;
			}
			groups.push( (tokens = []) );
		}

		matched = false;

		// Combinators
		if ( (match = rcombinators.exec( soFar )) ) {
			matched = match.shift();
			tokens.push({
				value: matched,
				// Cast descendant combinators to space
				type: match[0].replace( rtrim, " " )
			});
			soFar = soFar.slice( matched.length );
		}

		// Filters
		for ( type in Expr.filter ) {
			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
				(match = preFilters[ type ]( match ))) ) {
				matched = match.shift();
				tokens.push({
					value: matched,
					type: type,
					matches: match
				});
				soFar = soFar.slice( matched.length );
			}
		}

		if ( !matched ) {
			break;
		}
	}

	// Return the length of the invalid excess
	// if we're just parsing
	// Otherwise, throw an error or return tokens
	return parseOnly ?
		soFar.length :
		soFar ?
			Sizzle.error( selector ) :
			// Cache the tokens
			tokenCache( selector, groups ).slice( 0 );
};

function toSelector( tokens ) {
	var i = 0,
		len = tokens.length,
		selector = "";
	for ( ; i < len; i++ ) {
		selector += tokens[i].value;
	}
	return selector;
}

function addCombinator( matcher, combinator, base ) {
	var dir = combinator.dir,
		checkNonElements = base && dir === "parentNode",
		doneName = done++;

	return combinator.first ?
		// Check against closest ancestor/preceding element
		function( elem, context, xml ) {
			while ( (elem = elem[ dir ]) ) {
				if ( elem.nodeType === 1 || checkNonElements ) {
					return matcher( elem, context, xml );
				}
			}
		} :

		// Check against all ancestor/preceding elements
		function( elem, context, xml ) {
			var oldCache, outerCache,
				newCache = [ dirruns, doneName ];

			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
			if ( xml ) {
				while ( (elem = elem[ dir ]) ) {
					if ( elem.nodeType === 1 || checkNonElements ) {
						if ( matcher( elem, context, xml ) ) {
							return true;
						}
					}
				}
			} else {
				while ( (elem = elem[ dir ]) ) {
					if ( elem.nodeType === 1 || checkNonElements ) {
						outerCache = elem[ expando ] || (elem[ expando ] = {});
						if ( (oldCache = outerCache[ dir ]) &&
							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {

							// Assign to newCache so results back-propagate to previous elements
							return (newCache[ 2 ] = oldCache[ 2 ]);
						} else {
							// Reuse newcache so results back-propagate to previous elements
							outerCache[ dir ] = newCache;

							// A match means we're done; a fail means we have to keep checking
							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
								return true;
							}
						}
					}
				}
			}
		};
}

function elementMatcher( matchers ) {
	return matchers.length > 1 ?
		function( elem, context, xml ) {
			var i = matchers.length;
			while ( i-- ) {
				if ( !matchers[i]( elem, context, xml ) ) {
					return false;
				}
			}
			return true;
		} :
		matchers[0];
}

function multipleContexts( selector, contexts, results ) {
	var i = 0,
		len = contexts.length;
	for ( ; i < len; i++ ) {
		Sizzle( selector, contexts[i], results );
	}
	return results;
}

function condense( unmatched, map, filter, context, xml ) {
	var elem,
		newUnmatched = [],
		i = 0,
		len = unmatched.length,
		mapped = map != null;

	for ( ; i < len; i++ ) {
		if ( (elem = unmatched[i]) ) {
			if ( !filter || filter( elem, context, xml ) ) {
				newUnmatched.push( elem );
				if ( mapped ) {
					map.push( i );
				}
			}
		}
	}

	return newUnmatched;
}

function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
	if ( postFilter && !postFilter[ expando ] ) {
		postFilter = setMatcher( postFilter );
	}
	if ( postFinder && !postFinder[ expando ] ) {
		postFinder = setMatcher( postFinder, postSelector );
	}
	return markFunction(function( seed, results, context, xml ) {
		var temp, i, elem,
			preMap = [],
			postMap = [],
			preexisting = results.length,

			// Get initial elements from seed or context
			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),

			// Prefilter to get matcher input, preserving a map for seed-results synchronization
			matcherIn = preFilter && ( seed || !selector ) ?
				condense( elems, preMap, preFilter, context, xml ) :
				elems,

			matcherOut = matcher ?
				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?

					// ...intermediate processing is necessary
					[] :

					// ...otherwise use results directly
					results :
				matcherIn;

		// Find primary matches
		if ( matcher ) {
			matcher( matcherIn, matcherOut, context, xml );
		}

		// Apply postFilter
		if ( postFilter ) {
			temp = condense( matcherOut, postMap );
			postFilter( temp, [], context, xml );

			// Un-match failing elements by moving them back to matcherIn
			i = temp.length;
			while ( i-- ) {
				if ( (elem = temp[i]) ) {
					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
				}
			}
		}

		if ( seed ) {
			if ( postFinder || preFilter ) {
				if ( postFinder ) {
					// Get the final matcherOut by condensing this intermediate into postFinder contexts
					temp = [];
					i = matcherOut.length;
					while ( i-- ) {
						if ( (elem = matcherOut[i]) ) {
							// Restore matcherIn since elem is not yet a final match
							temp.push( (matcherIn[i] = elem) );
						}
					}
					postFinder( null, (matcherOut = []), temp, xml );
				}

				// Move matched elements from seed to results to keep them synchronized
				i = matcherOut.length;
				while ( i-- ) {
					if ( (elem = matcherOut[i]) &&
						(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {

						seed[temp] = !(results[temp] = elem);
					}
				}
			}

		// Add elements to results, through postFinder if defined
		} else {
			matcherOut = condense(
				matcherOut === results ?
					matcherOut.splice( preexisting, matcherOut.length ) :
					matcherOut
			);
			if ( postFinder ) {
				postFinder( null, results, matcherOut, xml );
			} else {
				push.apply( results, matcherOut );
			}
		}
	});
}

function matcherFromTokens( tokens ) {
	var checkContext, matcher, j,
		len = tokens.length,
		leadingRelative = Expr.relative[ tokens[0].type ],
		implicitRelative = leadingRelative || Expr.relative[" "],
		i = leadingRelative ? 1 : 0,

		// The foundational matcher ensures that elements are reachable from top-level context(s)
		matchContext = addCombinator( function( elem ) {
			return elem === checkContext;
		}, implicitRelative, true ),
		matchAnyContext = addCombinator( function( elem ) {
			return indexOf.call( checkContext, elem ) > -1;
		}, implicitRelative, true ),
		matchers = [ function( elem, context, xml ) {
			return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
				(checkContext = context).nodeType ?
					matchContext( elem, context, xml ) :
					matchAnyContext( elem, context, xml ) );
		} ];

	for ( ; i < len; i++ ) {
		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
		} else {
			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );

			// Return special upon seeing a positional matcher
			if ( matcher[ expando ] ) {
				// Find the next relative operator (if any) for proper handling
				j = ++i;
				for ( ; j < len; j++ ) {
					if ( Expr.relative[ tokens[j].type ] ) {
						break;
					}
				}
				return setMatcher(
					i > 1 && elementMatcher( matchers ),
					i > 1 && toSelector(
						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
					).replace( rtrim, "$1" ),
					matcher,
					i < j && matcherFromTokens( tokens.slice( i, j ) ),
					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
					j < len && toSelector( tokens )
				);
			}
			matchers.push( matcher );
		}
	}

	return elementMatcher( matchers );
}

function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
	var bySet = setMatchers.length > 0,
		byElement = elementMatchers.length > 0,
		superMatcher = function( seed, context, xml, results, outermost ) {
			var elem, j, matcher,
				matchedCount = 0,
				i = "0",
				unmatched = seed && [],
				setMatched = [],
				contextBackup = outermostContext,
				// We must always have either seed elements or outermost context
				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
				// Use integer dirruns iff this is the outermost matcher
				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
				len = elems.length;

			if ( outermost ) {
				outermostContext = context !== document && context;
			}

			// Add elements passing elementMatchers directly to results
			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
			// Support: IE<9, Safari
			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
				if ( byElement && elem ) {
					j = 0;
					while ( (matcher = elementMatchers[j++]) ) {
						if ( matcher( elem, context, xml ) ) {
							results.push( elem );
							break;
						}
					}
					if ( outermost ) {
						dirruns = dirrunsUnique;
					}
				}

				// Track unmatched elements for set filters
				if ( bySet ) {
					// They will have gone through all possible matchers
					if ( (elem = !matcher && elem) ) {
						matchedCount--;
					}

					// Lengthen the array for every element, matched or not
					if ( seed ) {
						unmatched.push( elem );
					}
				}
			}

			// Apply set filters to unmatched elements
			matchedCount += i;
			if ( bySet && i !== matchedCount ) {
				j = 0;
				while ( (matcher = setMatchers[j++]) ) {
					matcher( unmatched, setMatched, context, xml );
				}

				if ( seed ) {
					// Reintegrate element matches to eliminate the need for sorting
					if ( matchedCount > 0 ) {
						while ( i-- ) {
							if ( !(unmatched[i] || setMatched[i]) ) {
								setMatched[i] = pop.call( results );
							}
						}
					}

					// Discard index placeholder values to get only actual matches
					setMatched = condense( setMatched );
				}

				// Add matches to results
				push.apply( results, setMatched );

				// Seedless set matches succeeding multiple successful matchers stipulate sorting
				if ( outermost && !seed && setMatched.length > 0 &&
					( matchedCount + setMatchers.length ) > 1 ) {

					Sizzle.uniqueSort( results );
				}
			}

			// Override manipulation of globals by nested matchers
			if ( outermost ) {
				dirruns = dirrunsUnique;
				outermostContext = contextBackup;
			}

			return unmatched;
		};

	return bySet ?
		markFunction( superMatcher ) :
		superMatcher;
}

compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
	var i,
		setMatchers = [],
		elementMatchers = [],
		cached = compilerCache[ selector + " " ];

	if ( !cached ) {
		// Generate a function of recursive functions that can be used to check each element
		if ( !match ) {
			match = tokenize( selector );
		}
		i = match.length;
		while ( i-- ) {
			cached = matcherFromTokens( match[i] );
			if ( cached[ expando ] ) {
				setMatchers.push( cached );
			} else {
				elementMatchers.push( cached );
			}
		}

		// Cache the compiled function
		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );

		// Save selector and tokenization
		cached.selector = selector;
	}
	return cached;
};

/**
 * A low-level selection function that works with Sizzle's compiled
 *  selector functions
 * @param {String|Function} selector A selector or a pre-compiled
 *  selector function built with Sizzle.compile
 * @param {Element} context
 * @param {Array} [results]
 * @param {Array} [seed] A set of elements to match against
 */
select = Sizzle.select = function( selector, context, results, seed ) {
	var i, tokens, token, type, find,
		compiled = typeof selector === "function" && selector,
		match = !seed && tokenize( (selector = compiled.selector || selector) );

	results = results || [];

	// Try to minimize operations if there is no seed and only one group
	if ( match.length === 1 ) {

		// Take a shortcut and set the context if the root selector is an ID
		tokens = match[0] = match[0].slice( 0 );
		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
				support.getById && context.nodeType === 9 && documentIsHTML &&
				Expr.relative[ tokens[1].type ] ) {

			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
			if ( !context ) {
				return results;

			// Precompiled matchers will still verify ancestry, so step up a level
			} else if ( compiled ) {
				context = context.parentNode;
			}

			selector = selector.slice( tokens.shift().value.length );
		}

		// Fetch a seed set for right-to-left matching
		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
		while ( i-- ) {
			token = tokens[i];

			// Abort if we hit a combinator
			if ( Expr.relative[ (type = token.type) ] ) {
				break;
			}
			if ( (find = Expr.find[ type ]) ) {
				// Search, expanding context for leading sibling combinators
				if ( (seed = find(
					token.matches[0].replace( runescape, funescape ),
					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
				)) ) {

					// If seed is empty or no tokens remain, we can return early
					tokens.splice( i, 1 );
					selector = seed.length && toSelector( tokens );
					if ( !selector ) {
						push.apply( results, seed );
						return results;
					}

					break;
				}
			}
		}
	}

	// Compile and execute a filtering function if one is not provided
	// Provide `match` to avoid retokenization if we modified the selector above
	( compiled || compile( selector, match ) )(
		seed,
		context,
		!documentIsHTML,
		results,
		rsibling.test( selector ) && testContext( context.parentNode ) || context
	);
	return results;
};

// One-time assignments

// Sort stability
support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;

// Support: Chrome<14
// Always assume duplicates if they aren't passed to the comparison function
support.detectDuplicates = !!hasDuplicate;

// Initialize against the default document
setDocument();

// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
// Detached nodes confoundingly follow *each other*
support.sortDetached = assert(function( div1 ) {
	// Should return 1, but returns 4 (following)
	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
});

// Support: IE<8
// Prevent attribute/property "interpolation"
// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
if ( !assert(function( div ) {
	div.innerHTML = "<a href='#'></a>";
	return div.firstChild.getAttribute("href") === "#" ;
}) ) {
	addHandle( "type|href|height|width", function( elem, name, isXML ) {
		if ( !isXML ) {
			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
		}
	});
}

// Support: IE<9
// Use defaultValue in place of getAttribute("value")
if ( !support.attributes || !assert(function( div ) {
	div.innerHTML = "<input/>";
	div.firstChild.setAttribute( "value", "" );
	return div.firstChild.getAttribute( "value" ) === "";
}) ) {
	addHandle( "value", function( elem, name, isXML ) {
		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
			return elem.defaultValue;
		}
	});
}

// Support: IE<9
// Use getAttributeNode to fetch booleans when getAttribute lies
if ( !assert(function( div ) {
	return div.getAttribute("disabled") == null;
}) ) {
	addHandle( booleans, function( elem, name, isXML ) {
		var val;
		if ( !isXML ) {
			return elem[ name ] === true ? name.toLowerCase() :
					(val = elem.getAttributeNode( name )) && val.specified ?
					val.value :
				null;
		}
	});
}

return Sizzle;

})( window );



jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.pseudos;
jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;



var rneedsContext = jQuery.expr.match.needsContext;

var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);



var risSimple = /^.[^:#\[\.,]*$/;

// Implement the identical functionality for filter and not
function winnow( elements, qualifier, not ) {
	if ( jQuery.isFunction( qualifier ) ) {
		return jQuery.grep( elements, function( elem, i ) {
			/* jshint -W018 */
			return !!qualifier.call( elem, i, elem ) !== not;
		});

	}

	if ( qualifier.nodeType ) {
		return jQuery.grep( elements, function( elem ) {
			return ( elem === qualifier ) !== not;
		});

	}

	if ( typeof qualifier === "string" ) {
		if ( risSimple.test( qualifier ) ) {
			return jQuery.filter( qualifier, elements, not );
		}

		qualifier = jQuery.filter( qualifier, elements );
	}

	return jQuery.grep( elements, function( elem ) {
		return ( indexOf.call( qualifier, elem ) >= 0 ) !== not;
	});
}

jQuery.filter = function( expr, elems, not ) {
	var elem = elems[ 0 ];

	if ( not ) {
		expr = ":not(" + expr + ")";
	}

	return elems.length === 1 && elem.nodeType === 1 ?
		jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
		jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
			return elem.nodeType === 1;
		}));
};

jQuery.fn.extend({
	find: function( selector ) {
		var i,
			len = this.length,
			ret = [],
			self = this;

		if ( typeof selector !== "string" ) {
			return this.pushStack( jQuery( selector ).filter(function() {
				for ( i = 0; i < len; i++ ) {
					if ( jQuery.contains( self[ i ], this ) ) {
						return true;
					}
				}
			}) );
		}

		for ( i = 0; i < len; i++ ) {
			jQuery.find( selector, self[ i ], ret );
		}

		// Needed because $( selector, context ) becomes $( context ).find( selector )
		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
		ret.selector = this.selector ? this.selector + " " + selector : selector;
		return ret;
	},
	filter: function( selector ) {
		return this.pushStack( winnow(this, selector || [], false) );
	},
	not: function( selector ) {
		return this.pushStack( winnow(this, selector || [], true) );
	},
	is: function( selector ) {
		return !!winnow(
			this,

			// If this is a positional/relative selector, check membership in the returned set
			// so $("p:first").is("p:last") won't return true for a doc with two "p".
			typeof selector === "string" && rneedsContext.test( selector ) ?
				jQuery( selector ) :
				selector || [],
			false
		).length;
	}
});


// Initialize a jQuery object


// A central reference to the root jQuery(document)
var rootjQuery,

	// A simple way to check for HTML strings
	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
	// Strict HTML recognition (#11290: must start with <)
	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,

	init = jQuery.fn.init = function( selector, context ) {
		var match, elem;

		// HANDLE: $(""), $(null), $(undefined), $(false)
		if ( !selector ) {
			return this;
		}

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) {
				// Assume that strings that start and end with <> are HTML and skip the regex check
				match = [ null, selector, null ];

			} else {
				match = rquickExpr.exec( selector );
			}

			// Match html or make sure no context is specified for #id
			if ( match && (match[1] || !context) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[1] ) {
					context = context instanceof jQuery ? context[0] : context;

					// scripts is true for back-compat
					// Intentionally let the error be thrown if parseHTML is not present
					jQuery.merge( this, jQuery.parseHTML(
						match[1],
						context && context.nodeType ? context.ownerDocument || context : document,
						true
					) );

					// HANDLE: $(html, props)
					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
						for ( match in context ) {
							// Properties of context are called as methods if possible
							if ( jQuery.isFunction( this[ match ] ) ) {
								this[ match ]( context[ match ] );

							// ...and otherwise set as attributes
							} else {
								this.attr( match, context[ match ] );
							}
						}
					}

					return this;

				// HANDLE: $(#id)
				} else {
					elem = document.getElementById( match[2] );

					// Check parentNode to catch when Blackberry 4.6 returns
					// nodes that are no longer in the document #6963
					if ( elem && elem.parentNode ) {
						// Inject the element directly into the jQuery object
						this.length = 1;
						this[0] = elem;
					}

					this.context = document;
					this.selector = selector;
					return this;
				}

			// HANDLE: $(expr, $(...))
			} else if ( !context || context.jquery ) {
				return ( context || rootjQuery ).find( selector );

			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)
			} else {
				return this.constructor( context ).find( selector );
			}

		// HANDLE: $(DOMElement)
		} else if ( selector.nodeType ) {
			this.context = this[0] = selector;
			this.length = 1;
			return this;

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) ) {
			return typeof rootjQuery.ready !== "undefined" ?
				rootjQuery.ready( selector ) :
				// Execute immediately if ready is not present
				selector( jQuery );
		}

		if ( selector.selector !== undefined ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return jQuery.makeArray( selector, this );
	};

// Give the init function the jQuery prototype for later instantiation
init.prototype = jQuery.fn;

// Initialize central reference
rootjQuery = jQuery( document );


var rparentsprev = /^(?:parents|prev(?:Until|All))/,
	// methods guaranteed to produce a unique set when starting from a unique set
	guaranteedUnique = {
		children: true,
		contents: true,
		next: true,
		prev: true
	};

jQuery.extend({
	dir: function( elem, dir, until ) {
		var matched = [],
			truncate = until !== undefined;

		while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {
			if ( elem.nodeType === 1 ) {
				if ( truncate && jQuery( elem ).is( until ) ) {
					break;
				}
				matched.push( elem );
			}
		}
		return matched;
	},

	sibling: function( n, elem ) {
		var matched = [];

		for ( ; n; n = n.nextSibling ) {
			if ( n.nodeType === 1 && n !== elem ) {
				matched.push( n );
			}
		}

		return matched;
	}
});

jQuery.fn.extend({
	has: function( target ) {
		var targets = jQuery( target, this ),
			l = targets.length;

		return this.filter(function() {
			var i = 0;
			for ( ; i < l; i++ ) {
				if ( jQuery.contains( this, targets[i] ) ) {
					return true;
				}
			}
		});
	},

	closest: function( selectors, context ) {
		var cur,
			i = 0,
			l = this.length,
			matched = [],
			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
				jQuery( selectors, context || this.context ) :
				0;

		for ( ; i < l; i++ ) {
			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
				// Always skip document fragments
				if ( cur.nodeType < 11 && (pos ?
					pos.index(cur) > -1 :

					// Don't pass non-elements to Sizzle
					cur.nodeType === 1 &&
						jQuery.find.matchesSelector(cur, selectors)) ) {

					matched.push( cur );
					break;
				}
			}
		}

		return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
	},

	// Determine the position of an element within
	// the matched set of elements
	index: function( elem ) {

		// No argument, return index in parent
		if ( !elem ) {
			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
		}

		// index in selector
		if ( typeof elem === "string" ) {
			return indexOf.call( jQuery( elem ), this[ 0 ] );
		}

		// Locate the position of the desired element
		return indexOf.call( this,

			// If it receives a jQuery object, the first element is used
			elem.jquery ? elem[ 0 ] : elem
		);
	},

	add: function( selector, context ) {
		return this.pushStack(
			jQuery.unique(
				jQuery.merge( this.get(), jQuery( selector, context ) )
			)
		);
	},

	addBack: function( selector ) {
		return this.add( selector == null ?
			this.prevObject : this.prevObject.filter(selector)
		);
	}
});

function sibling( cur, dir ) {
	while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}
	return cur;
}

jQuery.each({
	parent: function( elem ) {
		var parent = elem.parentNode;
		return parent && parent.nodeType !== 11 ? parent : null;
	},
	parents: function( elem ) {
		return jQuery.dir( elem, "parentNode" );
	},
	parentsUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "parentNode", until );
	},
	next: function( elem ) {
		return sibling( elem, "nextSibling" );
	},
	prev: function( elem ) {
		return sibling( elem, "previousSibling" );
	},
	nextAll: function( elem ) {
		return jQuery.dir( elem, "nextSibling" );
	},
	prevAll: function( elem ) {
		return jQuery.dir( elem, "previousSibling" );
	},
	nextUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "nextSibling", until );
	},
	prevUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "previousSibling", until );
	},
	siblings: function( elem ) {
		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
	},
	children: function( elem ) {
		return jQuery.sibling( elem.firstChild );
	},
	contents: function( elem ) {
		return elem.contentDocument || jQuery.merge( [], elem.childNodes );
	}
}, function( name, fn ) {
	jQuery.fn[ name ] = function( until, selector ) {
		var matched = jQuery.map( this, fn, until );

		if ( name.slice( -5 ) !== "Until" ) {
			selector = until;
		}

		if ( selector && typeof selector === "string" ) {
			matched = jQuery.filter( selector, matched );
		}

		if ( this.length > 1 ) {
			// Remove duplicates
			if ( !guaranteedUnique[ name ] ) {
				jQuery.unique( matched );
			}

			// Reverse order for parents* and prev-derivatives
			if ( rparentsprev.test( name ) ) {
				matched.reverse();
			}
		}

		return this.pushStack( matched );
	};
});
var rnotwhite = (/\S+/g);



// String to Object options format cache
var optionsCache = {};

// Convert String-formatted options into Object-formatted ones and store in cache
function createOptions( options ) {
	var object = optionsCache[ options ] = {};
	jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
		object[ flag ] = true;
	});
	return object;
}

/*
 * Create a callback list using the following parameters:
 *
 *	options: an optional list of space-separated options that will change how
 *			the callback list behaves or a more traditional option object
 *
 * By default a callback list will act like an event callback list and can be
 * "fired" multiple times.
 *
 * Possible options:
 *
 *	once:			will ensure the callback list can only be fired once (like a Deferred)
 *
 *	memory:			will keep track of previous values and will call any callback added
 *					after the list has been fired right away with the latest "memorized"
 *					values (like a Deferred)
 *
 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
 *
 *	stopOnFalse:	interrupt callings when a callback returns false
 *
 */
jQuery.Callbacks = function( options ) {

	// Convert options from String-formatted to Object-formatted if needed
	// (we check in cache first)
	options = typeof options === "string" ?
		( optionsCache[ options ] || createOptions( options ) ) :
		jQuery.extend( {}, options );

	var // Last fire value (for non-forgettable lists)
		memory,
		// Flag to know if list was already fired
		fired,
		// Flag to know if list is currently firing
		firing,
		// First callback to fire (used internally by add and fireWith)
		firingStart,
		// End of the loop when firing
		firingLength,
		// Index of currently firing callback (modified by remove if needed)
		firingIndex,
		// Actual callback list
		list = [],
		// Stack of fire calls for repeatable lists
		stack = !options.once && [],
		// Fire callbacks
		fire = function( data ) {
			memory = options.memory && data;
			fired = true;
			firingIndex = firingStart || 0;
			firingStart = 0;
			firingLength = list.length;
			firing = true;
			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
					memory = false; // To prevent further calls using add
					break;
				}
			}
			firing = false;
			if ( list ) {
				if ( stack ) {
					if ( stack.length ) {
						fire( stack.shift() );
					}
				} else if ( memory ) {
					list = [];
				} else {
					self.disable();
				}
			}
		},
		// Actual Callbacks object
		self = {
			// Add a callback or a collection of callbacks to the list
			add: function() {
				if ( list ) {
					// First, we save the current length
					var start = list.length;
					(function add( args ) {
						jQuery.each( args, function( _, arg ) {
							var type = jQuery.type( arg );
							if ( type === "function" ) {
								if ( !options.unique || !self.has( arg ) ) {
									list.push( arg );
								}
							} else if ( arg && arg.length && type !== "string" ) {
								// Inspect recursively
								add( arg );
							}
						});
					})( arguments );
					// Do we need to add the callbacks to the
					// current firing batch?
					if ( firing ) {
						firingLength = list.length;
					// With memory, if we're not firing then
					// we should call right away
					} else if ( memory ) {
						firingStart = start;
						fire( memory );
					}
				}
				return this;
			},
			// Remove a callback from the list
			remove: function() {
				if ( list ) {
					jQuery.each( arguments, function( _, arg ) {
						var index;
						while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
							list.splice( index, 1 );
							// Handle firing indexes
							if ( firing ) {
								if ( index <= firingLength ) {
									firingLength--;
								}
								if ( index <= firingIndex ) {
									firingIndex--;
								}
							}
						}
					});
				}
				return this;
			},
			// Check if a given callback is in the list.
			// If no argument is given, return whether or not list has callbacks attached.
			has: function( fn ) {
				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
			},
			// Remove all callbacks from the list
			empty: function() {
				list = [];
				firingLength = 0;
				return this;
			},
			// Have the list do nothing anymore
			disable: function() {
				list = stack = memory = undefined;
				return this;
			},
			// Is it disabled?
			disabled: function() {
				return !list;
			},
			// Lock the list in its current state
			lock: function() {
				stack = undefined;
				if ( !memory ) {
					self.disable();
				}
				return this;
			},
			// Is it locked?
			locked: function() {
				return !stack;
			},
			// Call all callbacks with the given context and arguments
			fireWith: function( context, args ) {
				if ( list && ( !fired || stack ) ) {
					args = args || [];
					args = [ context, args.slice ? args.slice() : args ];
					if ( firing ) {
						stack.push( args );
					} else {
						fire( args );
					}
				}
				return this;
			},
			// Call all the callbacks with the given arguments
			fire: function() {
				self.fireWith( this, arguments );
				return this;
			},
			// To know if the callbacks have already been called at least once
			fired: function() {
				return !!fired;
			}
		};

	return self;
};


jQuery.extend({

	Deferred: function( func ) {
		var tuples = [
				// action, add listener, listener list, final state
				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
				[ "notify", "progress", jQuery.Callbacks("memory") ]
			],
			state = "pending",
			promise = {
				state: function() {
					return state;
				},
				always: function() {
					deferred.done( arguments ).fail( arguments );
					return this;
				},
				then: function( /* fnDone, fnFail, fnProgress */ ) {
					var fns = arguments;
					return jQuery.Deferred(function( newDefer ) {
						jQuery.each( tuples, function( i, tuple ) {
							var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
							// deferred[ done | fail | progress ] for forwarding actions to newDefer
							deferred[ tuple[1] ](function() {
								var returned = fn && fn.apply( this, arguments );
								if ( returned && jQuery.isFunction( returned.promise ) ) {
									returned.promise()
										.done( newDefer.resolve )
										.fail( newDefer.reject )
										.progress( newDefer.notify );
								} else {
									newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
								}
							});
						});
						fns = null;
					}).promise();
				},
				// Get a promise for this deferred
				// If obj is provided, the promise aspect is added to the object
				promise: function( obj ) {
					return obj != null ? jQuery.extend( obj, promise ) : promise;
				}
			},
			deferred = {};

		// Keep pipe for back-compat
		promise.pipe = promise.then;

		// Add list-specific methods
		jQuery.each( tuples, function( i, tuple ) {
			var list = tuple[ 2 ],
				stateString = tuple[ 3 ];

			// promise[ done | fail | progress ] = list.add
			promise[ tuple[1] ] = list.add;

			// Handle state
			if ( stateString ) {
				list.add(function() {
					// state = [ resolved | rejected ]
					state = stateString;

				// [ reject_list | resolve_list ].disable; progress_list.lock
				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
			}

			// deferred[ resolve | reject | notify ]
			deferred[ tuple[0] ] = function() {
				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
				return this;
			};
			deferred[ tuple[0] + "With" ] = list.fireWith;
		});

		// Make the deferred a promise
		promise.promise( deferred );

		// Call given func if any
		if ( func ) {
			func.call( deferred, deferred );
		}

		// All done!
		return deferred;
	},

	// Deferred helper
	when: function( subordinate /* , ..., subordinateN */ ) {
		var i = 0,
			resolveValues = slice.call( arguments ),
			length = resolveValues.length,

			// the count of uncompleted subordinates
			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,

			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),

			// Update function for both resolve and progress values
			updateFunc = function( i, contexts, values ) {
				return function( value ) {
					contexts[ i ] = this;
					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
					if ( values === progressValues ) {
						deferred.notifyWith( contexts, values );
					} else if ( !( --remaining ) ) {
						deferred.resolveWith( contexts, values );
					}
				};
			},

			progressValues, progressContexts, resolveContexts;

		// add listeners to Deferred subordinates; treat others as resolved
		if ( length > 1 ) {
			progressValues = new Array( length );
			progressContexts = new Array( length );
			resolveContexts = new Array( length );
			for ( ; i < length; i++ ) {
				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
					resolveValues[ i ].promise()
						.done( updateFunc( i, resolveContexts, resolveValues ) )
						.fail( deferred.reject )
						.progress( updateFunc( i, progressContexts, progressValues ) );
				} else {
					--remaining;
				}
			}
		}

		// if we're not waiting on anything, resolve the master
		if ( !remaining ) {
			deferred.resolveWith( resolveContexts, resolveValues );
		}

		return deferred.promise();
	}
});


// The deferred used on DOM ready
var readyList;

jQuery.fn.ready = function( fn ) {
	// Add the callback
	jQuery.ready.promise().done( fn );

	return this;
};

jQuery.extend({
	// Is the DOM ready to be used? Set to true once it occurs.
	isReady: false,

	// A counter to track how many items to wait for before
	// the ready event fires. See #6781
	readyWait: 1,

	// Hold (or release) the ready event
	holdReady: function( hold ) {
		if ( hold ) {
			jQuery.readyWait++;
		} else {
			jQuery.ready( true );
		}
	},

	// Handle when the DOM is ready
	ready: function( wait ) {

		// Abort if there are pending holds or we're already ready
		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
			return;
		}

		// Remember that the DOM is ready
		jQuery.isReady = true;

		// If a normal DOM Ready event fired, decrement, and wait if need be
		if ( wait !== true && --jQuery.readyWait > 0 ) {
			return;
		}

		// If there are functions bound, to execute
		readyList.resolveWith( document, [ jQuery ] );

		// Trigger any bound ready events
		if ( jQuery.fn.triggerHandler ) {
			jQuery( document ).triggerHandler( "ready" );
			jQuery( document ).off( "ready" );
		}
	}
});

/**
 * The ready event handler and self cleanup method
 */
function completed() {
	document.removeEventListener( "DOMContentLoaded", completed, false );
	window.removeEventListener( "load", completed, false );
	jQuery.ready();
}

jQuery.ready.promise = function( obj ) {
	if ( !readyList ) {

		readyList = jQuery.Deferred();

		// Catch cases where $(document).ready() is called after the browser event has already occurred.
		// we once tried to use readyState "interactive" here, but it caused issues like the one
		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
		if ( document.readyState === "complete" ) {
			// Handle it asynchronously to allow scripts the opportunity to delay ready
			setTimeout( jQuery.ready );

		} else {

			// Use the handy event callback
			document.addEventListener( "DOMContentLoaded", completed, false );

			// A fallback to window.onload, that will always work
			window.addEventListener( "load", completed, false );
		}
	}
	return readyList.promise( obj );
};

// Kick off the DOM ready check even if the user does not
jQuery.ready.promise();




// Multifunctional method to get and set values of a collection
// The value/s can optionally be executed if it's a function
var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
	var i = 0,
		len = elems.length,
		bulk = key == null;

	// Sets many values
	if ( jQuery.type( key ) === "object" ) {
		chainable = true;
		for ( i in key ) {
			jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
		}

	// Sets one value
	} else if ( value !== undefined ) {
		chainable = true;

		if ( !jQuery.isFunction( value ) ) {
			raw = true;
		}

		if ( bulk ) {
			// Bulk operations run against the entire set
			if ( raw ) {
				fn.call( elems, value );
				fn = null;

			// ...except when executing function values
			} else {
				bulk = fn;
				fn = function( elem, key, value ) {
					return bulk.call( jQuery( elem ), value );
				};
			}
		}

		if ( fn ) {
			for ( ; i < len; i++ ) {
				fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
			}
		}
	}

	return chainable ?
		elems :

		// Gets
		bulk ?
			fn.call( elems ) :
			len ? fn( elems[0], key ) : emptyGet;
};


/**
 * Determines whether an object can have data
 */
jQuery.acceptData = function( owner ) {
	// Accepts only:
	//  - Node
	//    - Node.ELEMENT_NODE
	//    - Node.DOCUMENT_NODE
	//  - Object
	//    - Any
	/* jshint -W018 */
	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
};


function Data() {
	// Support: Android < 4,
	// Old WebKit does not have Object.preventExtensions/freeze method,
	// return new empty object instead with no [[set]] accessor
	Object.defineProperty( this.cache = {}, 0, {
		get: function() {
			return {};
		}
	});

	this.expando = jQuery.expando + Math.random();
}

Data.uid = 1;
Data.accepts = jQuery.acceptData;

Data.prototype = {
	key: function( owner ) {
		// We can accept data for non-element nodes in modern browsers,
		// but we should not, see #8335.
		// Always return the key for a frozen object.
		if ( !Data.accepts( owner ) ) {
			return 0;
		}

		var descriptor = {},
			// Check if the owner object already has a cache key
			unlock = owner[ this.expando ];

		// If not, create one
		if ( !unlock ) {
			unlock = Data.uid++;

			// Secure it in a non-enumerable, non-writable property
			try {
				descriptor[ this.expando ] = { value: unlock };
				Object.defineProperties( owner, descriptor );

			// Support: Android < 4
			// Fallback to a less secure definition
			} catch ( e ) {
				descriptor[ this.expando ] = unlock;
				jQuery.extend( owner, descriptor );
			}
		}

		// Ensure the cache object
		if ( !this.cache[ unlock ] ) {
			this.cache[ unlock ] = {};
		}

		return unlock;
	},
	set: function( owner, data, value ) {
		var prop,
			// There may be an unlock assigned to this node,
			// if there is no entry for this "owner", create one inline
			// and set the unlock as though an owner entry had always existed
			unlock = this.key( owner ),
			cache = this.cache[ unlock ];

		// Handle: [ owner, key, value ] args
		if ( typeof data === "string" ) {
			cache[ data ] = value;

		// Handle: [ owner, { properties } ] args
		} else {
			// Fresh assignments by object are shallow copied
			if ( jQuery.isEmptyObject( cache ) ) {
				jQuery.extend( this.cache[ unlock ], data );
			// Otherwise, copy the properties one-by-one to the cache object
			} else {
				for ( prop in data ) {
					cache[ prop ] = data[ prop ];
				}
			}
		}
		return cache;
	},
	get: function( owner, key ) {
		// Either a valid cache is found, or will be created.
		// New caches will be created and the unlock returned,
		// allowing direct access to the newly created
		// empty data object. A valid owner object must be provided.
		var cache = this.cache[ this.key( owner ) ];

		return key === undefined ?
			cache : cache[ key ];
	},
	access: function( owner, key, value ) {
		var stored;
		// In cases where either:
		//
		//   1. No key was specified
		//   2. A string key was specified, but no value provided
		//
		// Take the "read" path and allow the get method to determine
		// which value to return, respectively either:
		//
		//   1. The entire cache object
		//   2. The data stored at the key
		//
		if ( key === undefined ||
				((key && typeof key === "string") && value === undefined) ) {

			stored = this.get( owner, key );

			return stored !== undefined ?
				stored : this.get( owner, jQuery.camelCase(key) );
		}

		// [*]When the key is not a string, or both a key and value
		// are specified, set or extend (existing objects) with either:
		//
		//   1. An object of properties
		//   2. A key and value
		//
		this.set( owner, key, value );

		// Since the "set" path can have two possible entry points
		// return the expected data based on which path was taken[*]
		return value !== undefined ? value : key;
	},
	remove: function( owner, key ) {
		var i, name, camel,
			unlock = this.key( owner ),
			cache = this.cache[ unlock ];

		if ( key === undefined ) {
			this.cache[ unlock ] = {};

		} else {
			// Support array or space separated string of keys
			if ( jQuery.isArray( key ) ) {
				// If "name" is an array of keys...
				// When data is initially created, via ("key", "val") signature,
				// keys will be converted to camelCase.
				// Since there is no way to tell _how_ a key was added, remove
				// both plain key and camelCase key. #12786
				// This will only penalize the array argument path.
				name = key.concat( key.map( jQuery.camelCase ) );
			} else {
				camel = jQuery.camelCase( key );
				// Try the string as a key before any manipulation
				if ( key in cache ) {
					name = [ key, camel ];
				} else {
					// If a key with the spaces exists, use it.
					// Otherwise, create an array by matching non-whitespace
					name = camel;
					name = name in cache ?
						[ name ] : ( name.match( rnotwhite ) || [] );
				}
			}

			i = name.length;
			while ( i-- ) {
				delete cache[ name[ i ] ];
			}
		}
	},
	hasData: function( owner ) {
		return !jQuery.isEmptyObject(
			this.cache[ owner[ this.expando ] ] || {}
		);
	},
	discard: function( owner ) {
		if ( owner[ this.expando ] ) {
			delete this.cache[ owner[ this.expando ] ];
		}
	}
};
var data_priv = new Data();

var data_user = new Data();



/*
	Implementation Summary

	1. Enforce API surface and semantic compatibility with 1.9.x branch
	2. Improve the module's maintainability by reducing the storage
		paths to a single mechanism.
	3. Use the same single mechanism to support "private" and "user" data.
	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
	5. Avoid exposing implementation details on user objects (eg. expando properties)
	6. Provide a clear path for implementation upgrade to WeakMap in 2014
*/
var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
	rmultiDash = /([A-Z])/g;

function dataAttr( elem, key, data ) {
	var name;

	// If nothing was found internally, try to fetch any
	// data from the HTML5 data-* attribute
	if ( data === undefined && elem.nodeType === 1 ) {
		name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
		data = elem.getAttribute( name );

		if ( typeof data === "string" ) {
			try {
				data = data === "true" ? true :
					data === "false" ? false :
					data === "null" ? null :
					// Only convert to a number if it doesn't change the string
					+data + "" === data ? +data :
					rbrace.test( data ) ? jQuery.parseJSON( data ) :
					data;
			} catch( e ) {}

			// Make sure we set the data so it isn't changed later
			data_user.set( elem, key, data );
		} else {
			data = undefined;
		}
	}
	return data;
}

jQuery.extend({
	hasData: function( elem ) {
		return data_user.hasData( elem ) || data_priv.hasData( elem );
	},

	data: function( elem, name, data ) {
		return data_user.access( elem, name, data );
	},

	removeData: function( elem, name ) {
		data_user.remove( elem, name );
	},

	// TODO: Now that all calls to _data and _removeData have been replaced
	// with direct calls to data_priv methods, these can be deprecated.
	_data: function( elem, name, data ) {
		return data_priv.access( elem, name, data );
	},

	_removeData: function( elem, name ) {
		data_priv.remove( elem, name );
	}
});

jQuery.fn.extend({
	data: function( key, value ) {
		var i, name, data,
			elem = this[ 0 ],
			attrs = elem && elem.attributes;

		// Gets all values
		if ( key === undefined ) {
			if ( this.length ) {
				data = data_user.get( elem );

				if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {
					i = attrs.length;
					while ( i-- ) {

						// Support: IE11+
						// The attrs elements can be null (#14894)
						if ( attrs[ i ] ) {
							name = attrs[ i ].name;
							if ( name.indexOf( "data-" ) === 0 ) {
								name = jQuery.camelCase( name.slice(5) );
								dataAttr( elem, name, data[ name ] );
							}
						}
					}
					data_priv.set( elem, "hasDataAttrs", true );
				}
			}

			return data;
		}

		// Sets multiple values
		if ( typeof key === "object" ) {
			return this.each(function() {
				data_user.set( this, key );
			});
		}

		return access( this, function( value ) {
			var data,
				camelKey = jQuery.camelCase( key );

			// The calling jQuery object (element matches) is not empty
			// (and therefore has an element appears at this[ 0 ]) and the
			// `value` parameter was not undefined. An empty jQuery object
			// will result in `undefined` for elem = this[ 0 ] which will
			// throw an exception if an attempt to read a data cache is made.
			if ( elem && value === undefined ) {
				// Attempt to get data from the cache
				// with the key as-is
				data = data_user.get( elem, key );
				if ( data !== undefined ) {
					return data;
				}

				// Attempt to get data from the cache
				// with the key camelized
				data = data_user.get( elem, camelKey );
				if ( data !== undefined ) {
					return data;
				}

				// Attempt to "discover" the data in
				// HTML5 custom data-* attrs
				data = dataAttr( elem, camelKey, undefined );
				if ( data !== undefined ) {
					return data;
				}

				// We tried really hard, but the data doesn't exist.
				return;
			}

			// Set the data...
			this.each(function() {
				// First, attempt to store a copy or reference of any
				// data that might've been store with a camelCased key.
				var data = data_user.get( this, camelKey );

				// For HTML5 data-* attribute interop, we have to
				// store property names with dashes in a camelCase form.
				// This might not apply to all properties...*
				data_user.set( this, camelKey, value );

				// *... In the case of properties that might _actually_
				// have dashes, we need to also store a copy of that
				// unchanged property.
				if ( key.indexOf("-") !== -1 && data !== undefined ) {
					data_user.set( this, key, value );
				}
			});
		}, null, value, arguments.length > 1, null, true );
	},

	removeData: function( key ) {
		return this.each(function() {
			data_user.remove( this, key );
		});
	}
});


jQuery.extend({
	queue: function( elem, type, data ) {
		var queue;

		if ( elem ) {
			type = ( type || "fx" ) + "queue";
			queue = data_priv.get( elem, type );

			// Speed up dequeue by getting out quickly if this is just a lookup
			if ( data ) {
				if ( !queue || jQuery.isArray( data ) ) {
					queue = data_priv.access( elem, type, jQuery.makeArray(data) );
				} else {
					queue.push( data );
				}
			}
			return queue || [];
		}
	},

	dequeue: function( elem, type ) {
		type = type || "fx";

		var queue = jQuery.queue( elem, type ),
			startLength = queue.length,
			fn = queue.shift(),
			hooks = jQuery._queueHooks( elem, type ),
			next = function() {
				jQuery.dequeue( elem, type );
			};

		// If the fx queue is dequeued, always remove the progress sentinel
		if ( fn === "inprogress" ) {
			fn = queue.shift();
			startLength--;
		}

		if ( fn ) {

			// Add a progress sentinel to prevent the fx queue from being
			// automatically dequeued
			if ( type === "fx" ) {
				queue.unshift( "inprogress" );
			}

			// clear up the last queue stop function
			delete hooks.stop;
			fn.call( elem, next, hooks );
		}

		if ( !startLength && hooks ) {
			hooks.empty.fire();
		}
	},

	// not intended for public consumption - generates a queueHooks object, or returns the current one
	_queueHooks: function( elem, type ) {
		var key = type + "queueHooks";
		return data_priv.get( elem, key ) || data_priv.access( elem, key, {
			empty: jQuery.Callbacks("once memory").add(function() {
				data_priv.remove( elem, [ type + "queue", key ] );
			})
		});
	}
});

jQuery.fn.extend({
	queue: function( type, data ) {
		var setter = 2;

		if ( typeof type !== "string" ) {
			data = type;
			type = "fx";
			setter--;
		}

		if ( arguments.length < setter ) {
			return jQuery.queue( this[0], type );
		}

		return data === undefined ?
			this :
			this.each(function() {
				var queue = jQuery.queue( this, type, data );

				// ensure a hooks for this queue
				jQuery._queueHooks( this, type );

				if ( type === "fx" && queue[0] !== "inprogress" ) {
					jQuery.dequeue( this, type );
				}
			});
	},
	dequeue: function( type ) {
		return this.each(function() {
			jQuery.dequeue( this, type );
		});
	},
	clearQueue: function( type ) {
		return this.queue( type || "fx", [] );
	},
	// Get a promise resolved when queues of a certain type
	// are emptied (fx is the type by default)
	promise: function( type, obj ) {
		var tmp,
			count = 1,
			defer = jQuery.Deferred(),
			elements = this,
			i = this.length,
			resolve = function() {
				if ( !( --count ) ) {
					defer.resolveWith( elements, [ elements ] );
				}
			};

		if ( typeof type !== "string" ) {
			obj = type;
			type = undefined;
		}
		type = type || "fx";

		while ( i-- ) {
			tmp = data_priv.get( elements[ i ], type + "queueHooks" );
			if ( tmp && tmp.empty ) {
				count++;
				tmp.empty.add( resolve );
			}
		}
		resolve();
		return defer.promise( obj );
	}
});
var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;

var cssExpand = [ "Top", "Right", "Bottom", "Left" ];

var isHidden = function( elem, el ) {
		// isHidden might be called from jQuery#filter function;
		// in that case, element will be second argument
		elem = el || elem;
		return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
	};

var rcheckableType = (/^(?:checkbox|radio)$/i);



(function() {
	var fragment = document.createDocumentFragment(),
		div = fragment.appendChild( document.createElement( "div" ) ),
		input = document.createElement( "input" );

	// #11217 - WebKit loses check when the name is after the checked attribute
	// Support: Windows Web Apps (WWA)
	// `name` and `type` need .setAttribute for WWA
	input.setAttribute( "type", "radio" );
	input.setAttribute( "checked", "checked" );
	input.setAttribute( "name", "t" );

	div.appendChild( input );

	// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
	// old WebKit doesn't clone checked state correctly in fragments
	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;

	// Make sure textarea (and checkbox) defaultValue is properly cloned
	// Support: IE9-IE11+
	div.innerHTML = "<textarea>x</textarea>";
	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
})();
var strundefined = typeof undefined;



support.focusinBubbles = "onfocusin" in window;


var
	rkeyEvent = /^key/,
	rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;

function returnTrue() {
	return true;
}

function returnFalse() {
	return false;
}

function safeActiveElement() {
	try {
		return document.activeElement;
	} catch ( err ) { }
}

/*
 * Helper functions for managing events -- not part of the public interface.
 * Props to Dean Edwards' addEvent library for many of the ideas.
 */
jQuery.event = {

	global: {},

	add: function( elem, types, handler, data, selector ) {

		var handleObjIn, eventHandle, tmp,
			events, t, handleObj,
			special, handlers, type, namespaces, origType,
			elemData = data_priv.get( elem );

		// Don't attach events to noData or text/comment nodes (but allow plain objects)
		if ( !elemData ) {
			return;
		}

		// Caller can pass in an object of custom data in lieu of the handler
		if ( handler.handler ) {
			handleObjIn = handler;
			handler = handleObjIn.handler;
			selector = handleObjIn.selector;
		}

		// Make sure that the handler has a unique ID, used to find/remove it later
		if ( !handler.guid ) {
			handler.guid = jQuery.guid++;
		}

		// Init the element's event structure and main handler, if this is the first
		if ( !(events = elemData.events) ) {
			events = elemData.events = {};
		}
		if ( !(eventHandle = elemData.handle) ) {
			eventHandle = elemData.handle = function( e ) {
				// Discard the second event of a jQuery.event.trigger() and
				// when an event is called after a page has unloaded
				return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
			};
		}

		// Handle multiple events separated by a space
		types = ( types || "" ).match( rnotwhite ) || [ "" ];
		t = types.length;
		while ( t-- ) {
			tmp = rtypenamespace.exec( types[t] ) || [];
			type = origType = tmp[1];
			namespaces = ( tmp[2] || "" ).split( "." ).sort();

			// There *must* be a type, no attaching namespace-only handlers
			if ( !type ) {
				continue;
			}

			// If event changes its type, use the special event handlers for the changed type
			special = jQuery.event.special[ type ] || {};

			// If selector defined, determine special event api type, otherwise given type
			type = ( selector ? special.delegateType : special.bindType ) || type;

			// Update special based on newly reset type
			special = jQuery.event.special[ type ] || {};

			// handleObj is passed to all event handlers
			handleObj = jQuery.extend({
				type: type,
				origType: origType,
				data: data,
				handler: handler,
				guid: handler.guid,
				selector: selector,
				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
				namespace: namespaces.join(".")
			}, handleObjIn );

			// Init the event handler queue if we're the first
			if ( !(handlers = events[ type ]) ) {
				handlers = events[ type ] = [];
				handlers.delegateCount = 0;

				// Only use addEventListener if the special events handler returns false
				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
					if ( elem.addEventListener ) {
						elem.addEventListener( type, eventHandle, false );
					}
				}
			}

			if ( special.add ) {
				special.add.call( elem, handleObj );

				if ( !handleObj.handler.guid ) {
					handleObj.handler.guid = handler.guid;
				}
			}

			// Add to the element's handler list, delegates in front
			if ( selector ) {
				handlers.splice( handlers.delegateCount++, 0, handleObj );
			} else {
				handlers.push( handleObj );
			}

			// Keep track of which events have ever been used, for event optimization
			jQuery.event.global[ type ] = true;
		}

	},

	// Detach an event or set of events from an element
	remove: function( elem, types, handler, selector, mappedTypes ) {

		var j, origCount, tmp,
			events, t, handleObj,
			special, handlers, type, namespaces, origType,
			elemData = data_priv.hasData( elem ) && data_priv.get( elem );

		if ( !elemData || !(events = elemData.events) ) {
			return;
		}

		// Once for each type.namespace in types; type may be omitted
		types = ( types || "" ).match( rnotwhite ) || [ "" ];
		t = types.length;
		while ( t-- ) {
			tmp = rtypenamespace.exec( types[t] ) || [];
			type = origType = tmp[1];
			namespaces = ( tmp[2] || "" ).split( "." ).sort();

			// Unbind all events (on this namespace, if provided) for the element
			if ( !type ) {
				for ( type in events ) {
					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
				}
				continue;
			}

			special = jQuery.event.special[ type ] || {};
			type = ( selector ? special.delegateType : special.bindType ) || type;
			handlers = events[ type ] || [];
			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );

			// Remove matching events
			origCount = j = handlers.length;
			while ( j-- ) {
				handleObj = handlers[ j ];

				if ( ( mappedTypes || origType === handleObj.origType ) &&
					( !handler || handler.guid === handleObj.guid ) &&
					( !tmp || tmp.test( handleObj.namespace ) ) &&
					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
					handlers.splice( j, 1 );

					if ( handleObj.selector ) {
						handlers.delegateCount--;
					}
					if ( special.remove ) {
						special.remove.call( elem, handleObj );
					}
				}
			}

			// Remove generic event handler if we removed something and no more handlers exist
			// (avoids potential for endless recursion during removal of special event handlers)
			if ( origCount && !handlers.length ) {
				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
					jQuery.removeEvent( elem, type, elemData.handle );
				}

				delete events[ type ];
			}
		}

		// Remove the expando if it's no longer used
		if ( jQuery.isEmptyObject( events ) ) {
			delete elemData.handle;
			data_priv.remove( elem, "events" );
		}
	},

	trigger: function( event, data, elem, onlyHandlers ) {

		var i, cur, tmp, bubbleType, ontype, handle, special,
			eventPath = [ elem || document ],
			type = hasOwn.call( event, "type" ) ? event.type : event,
			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];

		cur = tmp = elem = elem || document;

		// Don't do events on text and comment nodes
		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
			return;
		}

		// focus/blur morphs to focusin/out; ensure we're not firing them right now
		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
			return;
		}

		if ( type.indexOf(".") >= 0 ) {
			// Namespaced trigger; create a regexp to match event type in handle()
			namespaces = type.split(".");
			type = namespaces.shift();
			namespaces.sort();
		}
		ontype = type.indexOf(":") < 0 && "on" + type;

		// Caller can pass in a jQuery.Event object, Object, or just an event type string
		event = event[ jQuery.expando ] ?
			event :
			new jQuery.Event( type, typeof event === "object" && event );

		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
		event.isTrigger = onlyHandlers ? 2 : 3;
		event.namespace = namespaces.join(".");
		event.namespace_re = event.namespace ?
			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
			null;

		// Clean up the event in case it is being reused
		event.result = undefined;
		if ( !event.target ) {
			event.target = elem;
		}

		// Clone any incoming data and prepend the event, creating the handler arg list
		data = data == null ?
			[ event ] :
			jQuery.makeArray( data, [ event ] );

		// Allow special events to draw outside the lines
		special = jQuery.event.special[ type ] || {};
		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
			return;
		}

		// Determine event propagation path in advance, per W3C events spec (#9951)
		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {

			bubbleType = special.delegateType || type;
			if ( !rfocusMorph.test( bubbleType + type ) ) {
				cur = cur.parentNode;
			}
			for ( ; cur; cur = cur.parentNode ) {
				eventPath.push( cur );
				tmp = cur;
			}

			// Only add window if we got to document (e.g., not plain obj or detached DOM)
			if ( tmp === (elem.ownerDocument || document) ) {
				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
			}
		}

		// Fire handlers on the event path
		i = 0;
		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {

			event.type = i > 1 ?
				bubbleType :
				special.bindType || type;

			// jQuery handler
			handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
			if ( handle ) {
				handle.apply( cur, data );
			}

			// Native handler
			handle = ontype && cur[ ontype ];
			if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
				event.result = handle.apply( cur, data );
				if ( event.result === false ) {
					event.preventDefault();
				}
			}
		}
		event.type = type;

		// If nobody prevented the default action, do it now
		if ( !onlyHandlers && !event.isDefaultPrevented() ) {

			if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
				jQuery.acceptData( elem ) ) {

				// Call a native DOM method on the target with the same name name as the event.
				// Don't do default actions on window, that's where global variables be (#6170)
				if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {

					// Don't re-trigger an onFOO event when we call its FOO() method
					tmp = elem[ ontype ];

					if ( tmp ) {
						elem[ ontype ] = null;
					}

					// Prevent re-triggering of the same event, since we already bubbled it above
					jQuery.event.triggered = type;
					elem[ type ]();
					jQuery.event.triggered = undefined;

					if ( tmp ) {
						elem[ ontype ] = tmp;
					}
				}
			}
		}

		return event.result;
	},

	dispatch: function( event ) {

		// Make a writable jQuery.Event from the native event object
		event = jQuery.event.fix( event );

		var i, j, ret, matched, handleObj,
			handlerQueue = [],
			args = slice.call( arguments ),
			handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],
			special = jQuery.event.special[ event.type ] || {};

		// Use the fix-ed jQuery.Event rather than the (read-only) native event
		args[0] = event;
		event.delegateTarget = this;

		// Call the preDispatch hook for the mapped type, and let it bail if desired
		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
			return;
		}

		// Determine handlers
		handlerQueue = jQuery.event.handlers.call( this, event, handlers );

		// Run delegates first; they may want to stop propagation beneath us
		i = 0;
		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
			event.currentTarget = matched.elem;

			j = 0;
			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {

				// Triggered event must either 1) have no namespace, or
				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {

					event.handleObj = handleObj;
					event.data = handleObj.data;

					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
							.apply( matched.elem, args );

					if ( ret !== undefined ) {
						if ( (event.result = ret) === false ) {
							event.preventDefault();
							event.stopPropagation();
						}
					}
				}
			}
		}

		// Call the postDispatch hook for the mapped type
		if ( special.postDispatch ) {
			special.postDispatch.call( this, event );
		}

		return event.result;
	},

	handlers: function( event, handlers ) {
		var i, matches, sel, handleObj,
			handlerQueue = [],
			delegateCount = handlers.delegateCount,
			cur = event.target;

		// Find delegate handlers
		// Black-hole SVG <use> instance trees (#13180)
		// Avoid non-left-click bubbling in Firefox (#3861)
		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {

			for ( ; cur !== this; cur = cur.parentNode || this ) {

				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
				if ( cur.disabled !== true || event.type !== "click" ) {
					matches = [];
					for ( i = 0; i < delegateCount; i++ ) {
						handleObj = handlers[ i ];

						// Don't conflict with Object.prototype properties (#13203)
						sel = handleObj.selector + " ";

						if ( matches[ sel ] === undefined ) {
							matches[ sel ] = handleObj.needsContext ?
								jQuery( sel, this ).index( cur ) >= 0 :
								jQuery.find( sel, this, null, [ cur ] ).length;
						}
						if ( matches[ sel ] ) {
							matches.push( handleObj );
						}
					}
					if ( matches.length ) {
						handlerQueue.push({ elem: cur, handlers: matches });
					}
				}
			}
		}

		// Add the remaining (directly-bound) handlers
		if ( delegateCount < handlers.length ) {
			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
		}

		return handlerQueue;
	},

	// Includes some event props shared by KeyEvent and MouseEvent
	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),

	fixHooks: {},

	keyHooks: {
		props: "char charCode key keyCode".split(" "),
		filter: function( event, original ) {

			// Add which for key events
			if ( event.which == null ) {
				event.which = original.charCode != null ? original.charCode : original.keyCode;
			}

			return event;
		}
	},

	mouseHooks: {
		props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
		filter: function( event, original ) {
			var eventDoc, doc, body,
				button = original.button;

			// Calculate pageX/Y if missing and clientX/Y available
			if ( event.pageX == null && original.clientX != null ) {
				eventDoc = event.target.ownerDocument || document;
				doc = eventDoc.documentElement;
				body = eventDoc.body;

				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
			}

			// Add which for click: 1 === left; 2 === middle; 3 === right
			// Note: button is not normalized, so don't use it
			if ( !event.which && button !== undefined ) {
				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
			}

			return event;
		}
	},

	fix: function( event ) {
		if ( event[ jQuery.expando ] ) {
			return event;
		}

		// Create a writable copy of the event object and normalize some properties
		var i, prop, copy,
			type = event.type,
			originalEvent = event,
			fixHook = this.fixHooks[ type ];

		if ( !fixHook ) {
			this.fixHooks[ type ] = fixHook =
				rmouseEvent.test( type ) ? this.mouseHooks :
				rkeyEvent.test( type ) ? this.keyHooks :
				{};
		}
		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;

		event = new jQuery.Event( originalEvent );

		i = copy.length;
		while ( i-- ) {
			prop = copy[ i ];
			event[ prop ] = originalEvent[ prop ];
		}

		// Support: Cordova 2.5 (WebKit) (#13255)
		// All events should have a target; Cordova deviceready doesn't
		if ( !event.target ) {
			event.target = document;
		}

		// Support: Safari 6.0+, Chrome < 28
		// Target should not be a text node (#504, #13143)
		if ( event.target.nodeType === 3 ) {
			event.target = event.target.parentNode;
		}

		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
	},

	special: {
		load: {
			// Prevent triggered image.load events from bubbling to window.load
			noBubble: true
		},
		focus: {
			// Fire native event if possible so blur/focus sequence is correct
			trigger: function() {
				if ( this !== safeActiveElement() && this.focus ) {
					this.focus();
					return false;
				}
			},
			delegateType: "focusin"
		},
		blur: {
			trigger: function() {
				if ( this === safeActiveElement() && this.blur ) {
					this.blur();
					return false;
				}
			},
			delegateType: "focusout"
		},
		click: {
			// For checkbox, fire native event so checked state will be right
			trigger: function() {
				if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
					this.click();
					return false;
				}
			},

			// For cross-browser consistency, don't fire native .click() on links
			_default: function( event ) {
				return jQuery.nodeName( event.target, "a" );
			}
		},

		beforeunload: {
			postDispatch: function( event ) {

				// Support: Firefox 20+
				// Firefox doesn't alert if the returnValue field is not set.
				if ( event.result !== undefined && event.originalEvent ) {
					event.originalEvent.returnValue = event.result;
				}
			}
		}
	},

	simulate: function( type, elem, event, bubble ) {
		// Piggyback on a donor event to simulate a different one.
		// Fake originalEvent to avoid donor's stopPropagation, but if the
		// simulated event prevents default then we do the same on the donor.
		var e = jQuery.extend(
			new jQuery.Event(),
			event,
			{
				type: type,
				isSimulated: true,
				originalEvent: {}
			}
		);
		if ( bubble ) {
			jQuery.event.trigger( e, null, elem );
		} else {
			jQuery.event.dispatch.call( elem, e );
		}
		if ( e.isDefaultPrevented() ) {
			event.preventDefault();
		}
	}
};

jQuery.removeEvent = function( elem, type, handle ) {
	if ( elem.removeEventListener ) {
		elem.removeEventListener( type, handle, false );
	}
};

jQuery.Event = function( src, props ) {
	// Allow instantiation without the 'new' keyword
	if ( !(this instanceof jQuery.Event) ) {
		return new jQuery.Event( src, props );
	}

	// Event object
	if ( src && src.type ) {
		this.originalEvent = src;
		this.type = src.type;

		// Events bubbling up the document may have been marked as prevented
		// by a handler lower down the tree; reflect the correct value.
		this.isDefaultPrevented = src.defaultPrevented ||
				src.defaultPrevented === undefined &&
				// Support: Android < 4.0
				src.returnValue === false ?
			returnTrue :
			returnFalse;

	// Event type
	} else {
		this.type = src;
	}

	// Put explicitly provided properties onto the event object
	if ( props ) {
		jQuery.extend( this, props );
	}

	// Create a timestamp if incoming event doesn't have one
	this.timeStamp = src && src.timeStamp || jQuery.now();

	// Mark it as fixed
	this[ jQuery.expando ] = true;
};

// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
	isDefaultPrevented: returnFalse,
	isPropagationStopped: returnFalse,
	isImmediatePropagationStopped: returnFalse,

	preventDefault: function() {
		var e = this.originalEvent;

		this.isDefaultPrevented = returnTrue;

		if ( e && e.preventDefault ) {
			e.preventDefault();
		}
	},
	stopPropagation: function() {
		var e = this.originalEvent;

		this.isPropagationStopped = returnTrue;

		if ( e && e.stopPropagation ) {
			e.stopPropagation();
		}
	},
	stopImmediatePropagation: function() {
		var e = this.originalEvent;

		this.isImmediatePropagationStopped = returnTrue;

		if ( e && e.stopImmediatePropagation ) {
			e.stopImmediatePropagation();
		}

		this.stopPropagation();
	}
};

// Create mouseenter/leave events using mouseover/out and event-time checks
// Support: Chrome 15+
jQuery.each({
	mouseenter: "mouseover",
	mouseleave: "mouseout",
	pointerenter: "pointerover",
	pointerleave: "pointerout"
}, function( orig, fix ) {
	jQuery.event.special[ orig ] = {
		delegateType: fix,
		bindType: fix,

		handle: function( event ) {
			var ret,
				target = this,
				related = event.relatedTarget,
				handleObj = event.handleObj;

			// For mousenter/leave call the handler if related is outside the target.
			// NB: No relatedTarget if the mouse left/entered the browser window
			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
				event.type = handleObj.origType;
				ret = handleObj.handler.apply( this, arguments );
				event.type = fix;
			}
			return ret;
		}
	};
});

// Create "bubbling" focus and blur events
// Support: Firefox, Chrome, Safari
if ( !support.focusinBubbles ) {
	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {

		// Attach a single capturing handler on the document while someone wants focusin/focusout
		var handler = function( event ) {
				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
			};

		jQuery.event.special[ fix ] = {
			setup: function() {
				var doc = this.ownerDocument || this,
					attaches = data_priv.access( doc, fix );

				if ( !attaches ) {
					doc.addEventListener( orig, handler, true );
				}
				data_priv.access( doc, fix, ( attaches || 0 ) + 1 );
			},
			teardown: function() {
				var doc = this.ownerDocument || this,
					attaches = data_priv.access( doc, fix ) - 1;

				if ( !attaches ) {
					doc.removeEventListener( orig, handler, true );
					data_priv.remove( doc, fix );

				} else {
					data_priv.access( doc, fix, attaches );
				}
			}
		};
	});
}

jQuery.fn.extend({

	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
		var origFn, type;

		// Types can be a map of types/handlers
		if ( typeof types === "object" ) {
			// ( types-Object, selector, data )
			if ( typeof selector !== "string" ) {
				// ( types-Object, data )
				data = data || selector;
				selector = undefined;
			}
			for ( type in types ) {
				this.on( type, selector, data, types[ type ], one );
			}
			return this;
		}

		if ( data == null && fn == null ) {
			// ( types, fn )
			fn = selector;
			data = selector = undefined;
		} else if ( fn == null ) {
			if ( typeof selector === "string" ) {
				// ( types, selector, fn )
				fn = data;
				data = undefined;
			} else {
				// ( types, data, fn )
				fn = data;
				data = selector;
				selector = undefined;
			}
		}
		if ( fn === false ) {
			fn = returnFalse;
		} else if ( !fn ) {
			return this;
		}

		if ( one === 1 ) {
			origFn = fn;
			fn = function( event ) {
				// Can use an empty set, since event contains the info
				jQuery().off( event );
				return origFn.apply( this, arguments );
			};
			// Use same guid so caller can remove using origFn
			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
		}
		return this.each( function() {
			jQuery.event.add( this, types, fn, data, selector );
		});
	},
	one: function( types, selector, data, fn ) {
		return this.on( types, selector, data, fn, 1 );
	},
	off: function( types, selector, fn ) {
		var handleObj, type;
		if ( types && types.preventDefault && types.handleObj ) {
			// ( event )  dispatched jQuery.Event
			handleObj = types.handleObj;
			jQuery( types.delegateTarget ).off(
				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
				handleObj.selector,
				handleObj.handler
			);
			return this;
		}
		if ( typeof types === "object" ) {
			// ( types-object [, selector] )
			for ( type in types ) {
				this.off( type, selector, types[ type ] );
			}
			return this;
		}
		if ( selector === false || typeof selector === "function" ) {
			// ( types [, fn] )
			fn = selector;
			selector = undefined;
		}
		if ( fn === false ) {
			fn = returnFalse;
		}
		return this.each(function() {
			jQuery.event.remove( this, types, fn, selector );
		});
	},

	trigger: function( type, data ) {
		return this.each(function() {
			jQuery.event.trigger( type, data, this );
		});
	},
	triggerHandler: function( type, data ) {
		var elem = this[0];
		if ( elem ) {
			return jQuery.event.trigger( type, data, elem, true );
		}
	}
});


var
	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
	rtagName = /<([\w:]+)/,
	rhtml = /<|&#?\w+;/,
	rnoInnerhtml = /<(?:script|style|link)/i,
	// checked="checked" or checked
	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
	rscriptType = /^$|\/(?:java|ecma)script/i,
	rscriptTypeMasked = /^true\/(.*)/,
	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,

	// We have to close these tags to support XHTML (#13200)
	wrapMap = {

		// Support: IE 9
		option: [ 1, "<select multiple='multiple'>", "</select>" ],

		thead: [ 1, "<table>", "</table>" ],
		col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],

		_default: [ 0, "", "" ]
	};

// Support: IE 9
wrapMap.optgroup = wrapMap.option;

wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;

// Support: 1.x compatibility
// Manipulating tables requires a tbody
function manipulationTarget( elem, content ) {
	return jQuery.nodeName( elem, "table" ) &&
		jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?

		elem.getElementsByTagName("tbody")[0] ||
			elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
		elem;
}

// Replace/restore the type attribute of script elements for safe DOM manipulation
function disableScript( elem ) {
	elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;
	return elem;
}
function restoreScript( elem ) {
	var match = rscriptTypeMasked.exec( elem.type );

	if ( match ) {
		elem.type = match[ 1 ];
	} else {
		elem.removeAttribute("type");
	}

	return elem;
}

// Mark scripts as having already been evaluated
function setGlobalEval( elems, refElements ) {
	var i = 0,
		l = elems.length;

	for ( ; i < l; i++ ) {
		data_priv.set(
			elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" )
		);
	}
}

function cloneCopyEvent( src, dest ) {
	var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;

	if ( dest.nodeType !== 1 ) {
		return;
	}

	// 1. Copy private data: events, handlers, etc.
	if ( data_priv.hasData( src ) ) {
		pdataOld = data_priv.access( src );
		pdataCur = data_priv.set( dest, pdataOld );
		events = pdataOld.events;

		if ( events ) {
			delete pdataCur.handle;
			pdataCur.events = {};

			for ( type in events ) {
				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
					jQuery.event.add( dest, type, events[ type ][ i ] );
				}
			}
		}
	}

	// 2. Copy user data
	if ( data_user.hasData( src ) ) {
		udataOld = data_user.access( src );
		udataCur = jQuery.extend( {}, udataOld );

		data_user.set( dest, udataCur );
	}
}

function getAll( context, tag ) {
	var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) :
			context.querySelectorAll ? context.querySelectorAll( tag || "*" ) :
			[];

	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
		jQuery.merge( [ context ], ret ) :
		ret;
}

// Support: IE >= 9
function fixInput( src, dest ) {
	var nodeName = dest.nodeName.toLowerCase();

	// Fails to persist the checked state of a cloned checkbox or radio button.
	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
		dest.checked = src.checked;

	// Fails to return the selected option to the default selected state when cloning options
	} else if ( nodeName === "input" || nodeName === "textarea" ) {
		dest.defaultValue = src.defaultValue;
	}
}

jQuery.extend({
	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
		var i, l, srcElements, destElements,
			clone = elem.cloneNode( true ),
			inPage = jQuery.contains( elem.ownerDocument, elem );

		// Support: IE >= 9
		// Fix Cloning issues
		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
				!jQuery.isXMLDoc( elem ) ) {

			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
			destElements = getAll( clone );
			srcElements = getAll( elem );

			for ( i = 0, l = srcElements.length; i < l; i++ ) {
				fixInput( srcElements[ i ], destElements[ i ] );
			}
		}

		// Copy the events from the original to the clone
		if ( dataAndEvents ) {
			if ( deepDataAndEvents ) {
				srcElements = srcElements || getAll( elem );
				destElements = destElements || getAll( clone );

				for ( i = 0, l = srcElements.length; i < l; i++ ) {
					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
				}
			} else {
				cloneCopyEvent( elem, clone );
			}
		}

		// Preserve script evaluation history
		destElements = getAll( clone, "script" );
		if ( destElements.length > 0 ) {
			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
		}

		// Return the cloned set
		return clone;
	},

	buildFragment: function( elems, context, scripts, selection ) {
		var elem, tmp, tag, wrap, contains, j,
			fragment = context.createDocumentFragment(),
			nodes = [],
			i = 0,
			l = elems.length;

		for ( ; i < l; i++ ) {
			elem = elems[ i ];

			if ( elem || elem === 0 ) {

				// Add nodes directly
				if ( jQuery.type( elem ) === "object" ) {
					// Support: QtWebKit
					// jQuery.merge because push.apply(_, arraylike) throws
					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );

				// Convert non-html into a text node
				} else if ( !rhtml.test( elem ) ) {
					nodes.push( context.createTextNode( elem ) );

				// Convert html into DOM nodes
				} else {
					tmp = tmp || fragment.appendChild( context.createElement("div") );

					// Deserialize a standard representation
					tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
					wrap = wrapMap[ tag ] || wrapMap._default;
					tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ];

					// Descend through wrappers to the right content
					j = wrap[ 0 ];
					while ( j-- ) {
						tmp = tmp.lastChild;
					}

					// Support: QtWebKit
					// jQuery.merge because push.apply(_, arraylike) throws
					jQuery.merge( nodes, tmp.childNodes );

					// Remember the top-level container
					tmp = fragment.firstChild;

					// Fixes #12346
					// Support: Webkit, IE
					tmp.textContent = "";
				}
			}
		}

		// Remove wrapper from fragment
		fragment.textContent = "";

		i = 0;
		while ( (elem = nodes[ i++ ]) ) {

			// #4087 - If origin and destination elements are the same, and this is
			// that element, do not do anything
			if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
				continue;
			}

			contains = jQuery.contains( elem.ownerDocument, elem );

			// Append to fragment
			tmp = getAll( fragment.appendChild( elem ), "script" );

			// Preserve script evaluation history
			if ( contains ) {
				setGlobalEval( tmp );
			}

			// Capture executables
			if ( scripts ) {
				j = 0;
				while ( (elem = tmp[ j++ ]) ) {
					if ( rscriptType.test( elem.type || "" ) ) {
						scripts.push( elem );
					}
				}
			}
		}

		return fragment;
	},

	cleanData: function( elems ) {
		var data, elem, type, key,
			special = jQuery.event.special,
			i = 0;

		for ( ; (elem = elems[ i ]) !== undefined; i++ ) {
			if ( jQuery.acceptData( elem ) ) {
				key = elem[ data_priv.expando ];

				if ( key && (data = data_priv.cache[ key ]) ) {
					if ( data.events ) {
						for ( type in data.events ) {
							if ( special[ type ] ) {
								jQuery.event.remove( elem, type );

							// This is a shortcut to avoid jQuery.event.remove's overhead
							} else {
								jQuery.removeEvent( elem, type, data.handle );
							}
						}
					}
					if ( data_priv.cache[ key ] ) {
						// Discard any remaining `private` data
						delete data_priv.cache[ key ];
					}
				}
			}
			// Discard any remaining `user` data
			delete data_user.cache[ elem[ data_user.expando ] ];
		}
	}
});

jQuery.fn.extend({
	text: function( value ) {
		return access( this, function( value ) {
			return value === undefined ?
				jQuery.text( this ) :
				this.empty().each(function() {
					if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
						this.textContent = value;
					}
				});
		}, null, value, arguments.length );
	},

	append: function() {
		return this.domManip( arguments, function( elem ) {
			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
				var target = manipulationTarget( this, elem );
				target.appendChild( elem );
			}
		});
	},

	prepend: function() {
		return this.domManip( arguments, function( elem ) {
			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
				var target = manipulationTarget( this, elem );
				target.insertBefore( elem, target.firstChild );
			}
		});
	},

	before: function() {
		return this.domManip( arguments, function( elem ) {
			if ( this.parentNode ) {
				this.parentNode.insertBefore( elem, this );
			}
		});
	},

	after: function() {
		return this.domManip( arguments, function( elem ) {
			if ( this.parentNode ) {
				this.parentNode.insertBefore( elem, this.nextSibling );
			}
		});
	},

	remove: function( selector, keepData /* Internal Use Only */ ) {
		var elem,
			elems = selector ? jQuery.filter( selector, this ) : this,
			i = 0;

		for ( ; (elem = elems[i]) != null; i++ ) {
			if ( !keepData && elem.nodeType === 1 ) {
				jQuery.cleanData( getAll( elem ) );
			}

			if ( elem.parentNode ) {
				if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
					setGlobalEval( getAll( elem, "script" ) );
				}
				elem.parentNode.removeChild( elem );
			}
		}

		return this;
	},

	empty: function() {
		var elem,
			i = 0;

		for ( ; (elem = this[i]) != null; i++ ) {
			if ( elem.nodeType === 1 ) {

				// Prevent memory leaks
				jQuery.cleanData( getAll( elem, false ) );

				// Remove any remaining nodes
				elem.textContent = "";
			}
		}

		return this;
	},

	clone: function( dataAndEvents, deepDataAndEvents ) {
		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;

		return this.map(function() {
			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
		});
	},

	html: function( value ) {
		return access( this, function( value ) {
			var elem = this[ 0 ] || {},
				i = 0,
				l = this.length;

			if ( value === undefined && elem.nodeType === 1 ) {
				return elem.innerHTML;
			}

			// See if we can take a shortcut and just use innerHTML
			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {

				value = value.replace( rxhtmlTag, "<$1></$2>" );

				try {
					for ( ; i < l; i++ ) {
						elem = this[ i ] || {};

						// Remove element nodes and prevent memory leaks
						if ( elem.nodeType === 1 ) {
							jQuery.cleanData( getAll( elem, false ) );
							elem.innerHTML = value;
						}
					}

					elem = 0;

				// If using innerHTML throws an exception, use the fallback method
				} catch( e ) {}
			}

			if ( elem ) {
				this.empty().append( value );
			}
		}, null, value, arguments.length );
	},

	replaceWith: function() {
		var arg = arguments[ 0 ];

		// Make the changes, replacing each context element with the new content
		this.domManip( arguments, function( elem ) {
			arg = this.parentNode;

			jQuery.cleanData( getAll( this ) );

			if ( arg ) {
				arg.replaceChild( elem, this );
			}
		});

		// Force removal if there was no new content (e.g., from empty arguments)
		return arg && (arg.length || arg.nodeType) ? this : this.remove();
	},

	detach: function( selector ) {
		return this.remove( selector, true );
	},

	domManip: function( args, callback ) {

		// Flatten any nested arrays
		args = concat.apply( [], args );

		var fragment, first, scripts, hasScripts, node, doc,
			i = 0,
			l = this.length,
			set = this,
			iNoClone = l - 1,
			value = args[ 0 ],
			isFunction = jQuery.isFunction( value );

		// We can't cloneNode fragments that contain checked, in WebKit
		if ( isFunction ||
				( l > 1 && typeof value === "string" &&
					!support.checkClone && rchecked.test( value ) ) ) {
			return this.each(function( index ) {
				var self = set.eq( index );
				if ( isFunction ) {
					args[ 0 ] = value.call( this, index, self.html() );
				}
				self.domManip( args, callback );
			});
		}

		if ( l ) {
			fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
			first = fragment.firstChild;

			if ( fragment.childNodes.length === 1 ) {
				fragment = first;
			}

			if ( first ) {
				scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
				hasScripts = scripts.length;

				// Use the original fragment for the last item instead of the first because it can end up
				// being emptied incorrectly in certain situations (#8070).
				for ( ; i < l; i++ ) {
					node = fragment;

					if ( i !== iNoClone ) {
						node = jQuery.clone( node, true, true );

						// Keep references to cloned scripts for later restoration
						if ( hasScripts ) {
							// Support: QtWebKit
							// jQuery.merge because push.apply(_, arraylike) throws
							jQuery.merge( scripts, getAll( node, "script" ) );
						}
					}

					callback.call( this[ i ], node, i );
				}

				if ( hasScripts ) {
					doc = scripts[ scripts.length - 1 ].ownerDocument;

					// Reenable scripts
					jQuery.map( scripts, restoreScript );

					// Evaluate executable scripts on first document insertion
					for ( i = 0; i < hasScripts; i++ ) {
						node = scripts[ i ];
						if ( rscriptType.test( node.type || "" ) &&
							!data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) {

							if ( node.src ) {
								// Optional AJAX dependency, but won't run scripts if not present
								if ( jQuery._evalUrl ) {
									jQuery._evalUrl( node.src );
								}
							} else {
								jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
							}
						}
					}
				}
			}
		}

		return this;
	}
});

jQuery.each({
	appendTo: "append",
	prependTo: "prepend",
	insertBefore: "before",
	insertAfter: "after",
	replaceAll: "replaceWith"
}, function( name, original ) {
	jQuery.fn[ name ] = function( selector ) {
		var elems,
			ret = [],
			insert = jQuery( selector ),
			last = insert.length - 1,
			i = 0;

		for ( ; i <= last; i++ ) {
			elems = i === last ? this : this.clone( true );
			jQuery( insert[ i ] )[ original ]( elems );

			// Support: QtWebKit
			// .get() because push.apply(_, arraylike) throws
			push.apply( ret, elems.get() );
		}

		return this.pushStack( ret );
	};
});


var iframe,
	elemdisplay = {};

/**
 * Retrieve the actual display of a element
 * @param {String} name nodeName of the element
 * @param {Object} doc Document object
 */
// Called only from within defaultDisplay
function actualDisplay( name, doc ) {
	var style,
		elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),

		// getDefaultComputedStyle might be reliably used only on attached element
		display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?

			// Use of this method is a temporary fix (more like optmization) until something better comes along,
			// since it was removed from specification and supported only in FF
			style.display : jQuery.css( elem[ 0 ], "display" );

	// We don't have any data stored on the element,
	// so use "detach" method as fast way to get rid of the element
	elem.detach();

	return display;
}

/**
 * Try to determine the default display value of an element
 * @param {String} nodeName
 */
function defaultDisplay( nodeName ) {
	var doc = document,
		display = elemdisplay[ nodeName ];

	if ( !display ) {
		display = actualDisplay( nodeName, doc );

		// If the simple way fails, read from inside an iframe
		if ( display === "none" || !display ) {

			// Use the already-created iframe if possible
			iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );

			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
			doc = iframe[ 0 ].contentDocument;

			// Support: IE
			doc.write();
			doc.close();

			display = actualDisplay( nodeName, doc );
			iframe.detach();
		}

		// Store the correct default display
		elemdisplay[ nodeName ] = display;
	}

	return display;
}
var rmargin = (/^margin/);

var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );

var getStyles = function( elem ) {
		return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
	};



function curCSS( elem, name, computed ) {
	var width, minWidth, maxWidth, ret,
		style = elem.style;

	computed = computed || getStyles( elem );

	// Support: IE9
	// getPropertyValue is only needed for .css('filter') in IE9, see #12537
	if ( computed ) {
		ret = computed.getPropertyValue( name ) || computed[ name ];
	}

	if ( computed ) {

		if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
			ret = jQuery.style( elem, name );
		}

		// Support: iOS < 6
		// A tribute to the "awesome hack by Dean Edwards"
		// iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
		// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
		if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {

			// Remember the original values
			width = style.width;
			minWidth = style.minWidth;
			maxWidth = style.maxWidth;

			// Put in the new values to get a computed value out
			style.minWidth = style.maxWidth = style.width = ret;
			ret = computed.width;

			// Revert the changed values
			style.width = width;
			style.minWidth = minWidth;
			style.maxWidth = maxWidth;
		}
	}

	return ret !== undefined ?
		// Support: IE
		// IE returns zIndex value as an integer.
		ret + "" :
		ret;
}


function addGetHookIf( conditionFn, hookFn ) {
	// Define the hook, we'll check on the first run if it's really needed.
	return {
		get: function() {
			if ( conditionFn() ) {
				// Hook not needed (or it's not possible to use it due to missing dependency),
				// remove it.
				// Since there are no other hooks for marginRight, remove the whole object.
				delete this.get;
				return;
			}

			// Hook needed; redefine it so that the support test is not executed again.

			return (this.get = hookFn).apply( this, arguments );
		}
	};
}


(function() {
	var pixelPositionVal, boxSizingReliableVal,
		docElem = document.documentElement,
		container = document.createElement( "div" ),
		div = document.createElement( "div" );

	if ( !div.style ) {
		return;
	}

	div.style.backgroundClip = "content-box";
	div.cloneNode( true ).style.backgroundClip = "";
	support.clearCloneStyle = div.style.backgroundClip === "content-box";

	container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" +
		"position:absolute";
	container.appendChild( div );

	// Executing both pixelPosition & boxSizingReliable tests require only one layout
	// so they're executed at the same time to save the second computation.
	function computePixelPositionAndBoxSizingReliable() {
		div.style.cssText =
			// Support: Firefox<29, Android 2.3
			// Vendor-prefix box-sizing
			"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
			"box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
			"border:1px;padding:1px;width:4px;position:absolute";
		div.innerHTML = "";
		docElem.appendChild( container );

		var divStyle = window.getComputedStyle( div, null );
		pixelPositionVal = divStyle.top !== "1%";
		boxSizingReliableVal = divStyle.width === "4px";

		docElem.removeChild( container );
	}

	// Support: node.js jsdom
	// Don't assume that getComputedStyle is a property of the global object
	if ( window.getComputedStyle ) {
		jQuery.extend( support, {
			pixelPosition: function() {
				// This test is executed only once but we still do memoizing
				// since we can use the boxSizingReliable pre-computing.
				// No need to check if the test was already performed, though.
				computePixelPositionAndBoxSizingReliable();
				return pixelPositionVal;
			},
			boxSizingReliable: function() {
				if ( boxSizingReliableVal == null ) {
					computePixelPositionAndBoxSizingReliable();
				}
				return boxSizingReliableVal;
			},
			reliableMarginRight: function() {
				// Support: Android 2.3
				// Check if div with explicit width and no margin-right incorrectly
				// gets computed margin-right based on width of container. (#3333)
				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
				// This support function is only executed once so no memoizing is needed.
				var ret,
					marginDiv = div.appendChild( document.createElement( "div" ) );

				// Reset CSS: box-sizing; display; margin; border; padding
				marginDiv.style.cssText = div.style.cssText =
					// Support: Firefox<29, Android 2.3
					// Vendor-prefix box-sizing
					"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
					"box-sizing:content-box;display:block;margin:0;border:0;padding:0";
				marginDiv.style.marginRight = marginDiv.style.width = "0";
				div.style.width = "1px";
				docElem.appendChild( container );

				ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );

				docElem.removeChild( container );

				return ret;
			}
		});
	}
})();


// A method for quickly swapping in/out CSS properties to get correct calculations.
jQuery.swap = function( elem, options, callback, args ) {
	var ret, name,
		old = {};

	// Remember the old values, and insert the new ones
	for ( name in options ) {
		old[ name ] = elem.style[ name ];
		elem.style[ name ] = options[ name ];
	}

	ret = callback.apply( elem, args || [] );

	// Revert the old values
	for ( name in options ) {
		elem.style[ name ] = old[ name ];
	}

	return ret;
};


var
	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),

	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
	cssNormalTransform = {
		letterSpacing: "0",
		fontWeight: "400"
	},

	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];

// return a css property mapped to a potentially vendor prefixed property
function vendorPropName( style, name ) {

	// shortcut for names that are not vendor prefixed
	if ( name in style ) {
		return name;
	}

	// check for vendor prefixed names
	var capName = name[0].toUpperCase() + name.slice(1),
		origName = name,
		i = cssPrefixes.length;

	while ( i-- ) {
		name = cssPrefixes[ i ] + capName;
		if ( name in style ) {
			return name;
		}
	}

	return origName;
}

function setPositiveNumber( elem, value, subtract ) {
	var matches = rnumsplit.exec( value );
	return matches ?
		// Guard against undefined "subtract", e.g., when used as in cssHooks
		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
		value;
}

function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
	var i = extra === ( isBorderBox ? "border" : "content" ) ?
		// If we already have the right measurement, avoid augmentation
		4 :
		// Otherwise initialize for horizontal or vertical properties
		name === "width" ? 1 : 0,

		val = 0;

	for ( ; i < 4; i += 2 ) {
		// both box models exclude margin, so add it if we want it
		if ( extra === "margin" ) {
			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
		}

		if ( isBorderBox ) {
			// border-box includes padding, so remove it if we want content
			if ( extra === "content" ) {
				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
			}

			// at this point, extra isn't border nor margin, so remove border
			if ( extra !== "margin" ) {
				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
			}
		} else {
			// at this point, extra isn't content, so add padding
			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );

			// at this point, extra isn't content nor padding, so add border
			if ( extra !== "padding" ) {
				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
			}
		}
	}

	return val;
}

function getWidthOrHeight( elem, name, extra ) {

	// Start with offset property, which is equivalent to the border-box value
	var valueIsBorderBox = true,
		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
		styles = getStyles( elem ),
		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";

	// some non-html elements return undefined for offsetWidth, so check for null/undefined
	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
	if ( val <= 0 || val == null ) {
		// Fall back to computed then uncomputed css if necessary
		val = curCSS( elem, name, styles );
		if ( val < 0 || val == null ) {
			val = elem.style[ name ];
		}

		// Computed unit is not pixels. Stop here and return.
		if ( rnumnonpx.test(val) ) {
			return val;
		}

		// we need the check for style in case a browser which returns unreliable values
		// for getComputedStyle silently falls back to the reliable elem.style
		valueIsBorderBox = isBorderBox &&
			( support.boxSizingReliable() || val === elem.style[ name ] );

		// Normalize "", auto, and prepare for extra
		val = parseFloat( val ) || 0;
	}

	// use the active box-sizing model to add/subtract irrelevant styles
	return ( val +
		augmentWidthOrHeight(
			elem,
			name,
			extra || ( isBorderBox ? "border" : "content" ),
			valueIsBorderBox,
			styles
		)
	) + "px";
}

function showHide( elements, show ) {
	var display, elem, hidden,
		values = [],
		index = 0,
		length = elements.length;

	for ( ; index < length; index++ ) {
		elem = elements[ index ];
		if ( !elem.style ) {
			continue;
		}

		values[ index ] = data_priv.get( elem, "olddisplay" );
		display = elem.style.display;
		if ( show ) {
			// Reset the inline display of this element to learn if it is
			// being hidden by cascaded rules or not
			if ( !values[ index ] && display === "none" ) {
				elem.style.display = "";
			}

			// Set elements which have been overridden with display: none
			// in a stylesheet to whatever the default browser style is
			// for such an element
			if ( elem.style.display === "" && isHidden( elem ) ) {
				values[ index ] = data_priv.access( elem, "olddisplay", defaultDisplay(elem.nodeName) );
			}
		} else {
			hidden = isHidden( elem );

			if ( display !== "none" || !hidden ) {
				data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
			}
		}
	}

	// Set the display of most of the elements in a second loop
	// to avoid the constant reflow
	for ( index = 0; index < length; index++ ) {
		elem = elements[ index ];
		if ( !elem.style ) {
			continue;
		}
		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
			elem.style.display = show ? values[ index ] || "" : "none";
		}
	}

	return elements;
}

jQuery.extend({
	// Add in style property hooks for overriding the default
	// behavior of getting and setting a style property
	cssHooks: {
		opacity: {
			get: function( elem, computed ) {
				if ( computed ) {
					// We should always get a number back from opacity
					var ret = curCSS( elem, "opacity" );
					return ret === "" ? "1" : ret;
				}
			}
		}
	},

	// Don't automatically add "px" to these possibly-unitless properties
	cssNumber: {
		"columnCount": true,
		"fillOpacity": true,
		"flexGrow": true,
		"flexShrink": true,
		"fontWeight": true,
		"lineHeight": true,
		"opacity": true,
		"order": true,
		"orphans": true,
		"widows": true,
		"zIndex": true,
		"zoom": true
	},

	// Add in properties whose names you wish to fix before
	// setting or getting the value
	cssProps: {
		// normalize float css property
		"float": "cssFloat"
	},

	// Get and set the style property on a DOM Node
	style: function( elem, name, value, extra ) {
		// Don't set styles on text and comment nodes
		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
			return;
		}

		// Make sure that we're working with the right name
		var ret, type, hooks,
			origName = jQuery.camelCase( name ),
			style = elem.style;

		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );

		// gets hook for the prefixed version
		// followed by the unprefixed version
		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];

		// Check if we're setting a value
		if ( value !== undefined ) {
			type = typeof value;

			// convert relative number strings (+= or -=) to relative numbers. #7345
			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
				// Fixes bug #9237
				type = "number";
			}

			// Make sure that null and NaN values aren't set. See: #7116
			if ( value == null || value !== value ) {
				return;
			}

			// If a number was passed in, add 'px' to the (except for certain CSS properties)
			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
				value += "px";
			}

			// Fixes #8908, it can be done more correctly by specifying setters in cssHooks,
			// but it would mean to define eight (for every problematic property) identical functions
			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
				style[ name ] = "inherit";
			}

			// If a hook was provided, use that value, otherwise just set the specified value
			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
				style[ name ] = value;
			}

		} else {
			// If a hook was provided get the non-computed value from there
			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
				return ret;
			}

			// Otherwise just get the value from the style object
			return style[ name ];
		}
	},

	css: function( elem, name, extra, styles ) {
		var val, num, hooks,
			origName = jQuery.camelCase( name );

		// Make sure that we're working with the right name
		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );

		// gets hook for the prefixed version
		// followed by the unprefixed version
		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];

		// If a hook was provided get the computed value from there
		if ( hooks && "get" in hooks ) {
			val = hooks.get( elem, true, extra );
		}

		// Otherwise, if a way to get the computed value exists, use that
		if ( val === undefined ) {
			val = curCSS( elem, name, styles );
		}

		//convert "normal" to computed value
		if ( val === "normal" && name in cssNormalTransform ) {
			val = cssNormalTransform[ name ];
		}

		// Return, converting to number if forced or a qualifier was provided and val looks numeric
		if ( extra === "" || extra ) {
			num = parseFloat( val );
			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
		}
		return val;
	}
});

jQuery.each([ "height", "width" ], function( i, name ) {
	jQuery.cssHooks[ name ] = {
		get: function( elem, computed, extra ) {
			if ( computed ) {
				// certain elements can have dimension info if we invisibly show them
				// however, it must have a current display style that would benefit from this
				return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
					jQuery.swap( elem, cssShow, function() {
						return getWidthOrHeight( elem, name, extra );
					}) :
					getWidthOrHeight( elem, name, extra );
			}
		},

		set: function( elem, value, extra ) {
			var styles = extra && getStyles( elem );
			return setPositiveNumber( elem, value, extra ?
				augmentWidthOrHeight(
					elem,
					name,
					extra,
					jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
					styles
				) : 0
			);
		}
	};
});

// Support: Android 2.3
jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
	function( elem, computed ) {
		if ( computed ) {
			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
			// Work around by temporarily setting element display to inline-block
			return jQuery.swap( elem, { "display": "inline-block" },
				curCSS, [ elem, "marginRight" ] );
		}
	}
);

// These hooks are used by animate to expand properties
jQuery.each({
	margin: "",
	padding: "",
	border: "Width"
}, function( prefix, suffix ) {
	jQuery.cssHooks[ prefix + suffix ] = {
		expand: function( value ) {
			var i = 0,
				expanded = {},

				// assumes a single number if not a string
				parts = typeof value === "string" ? value.split(" ") : [ value ];

			for ( ; i < 4; i++ ) {
				expanded[ prefix + cssExpand[ i ] + suffix ] =
					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
			}

			return expanded;
		}
	};

	if ( !rmargin.test( prefix ) ) {
		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
	}
});

jQuery.fn.extend({
	css: function( name, value ) {
		return access( this, function( elem, name, value ) {
			var styles, len,
				map = {},
				i = 0;

			if ( jQuery.isArray( name ) ) {
				styles = getStyles( elem );
				len = name.length;

				for ( ; i < len; i++ ) {
					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
				}

				return map;
			}

			return value !== undefined ?
				jQuery.style( elem, name, value ) :
				jQuery.css( elem, name );
		}, name, value, arguments.length > 1 );
	},
	show: function() {
		return showHide( this, true );
	},
	hide: function() {
		return showHide( this );
	},
	toggle: function( state ) {
		if ( typeof state === "boolean" ) {
			return state ? this.show() : this.hide();
		}

		return this.each(function() {
			if ( isHidden( this ) ) {
				jQuery( this ).show();
			} else {
				jQuery( this ).hide();
			}
		});
	}
});


function Tween( elem, options, prop, end, easing ) {
	return new Tween.prototype.init( elem, options, prop, end, easing );
}
jQuery.Tween = Tween;

Tween.prototype = {
	constructor: Tween,
	init: function( elem, options, prop, end, easing, unit ) {
		this.elem = elem;
		this.prop = prop;
		this.easing = easing || "swing";
		this.options = options;
		this.start = this.now = this.cur();
		this.end = end;
		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
	},
	cur: function() {
		var hooks = Tween.propHooks[ this.prop ];

		return hooks && hooks.get ?
			hooks.get( this ) :
			Tween.propHooks._default.get( this );
	},
	run: function( percent ) {
		var eased,
			hooks = Tween.propHooks[ this.prop ];

		if ( this.options.duration ) {
			this.pos = eased = jQuery.easing[ this.easing ](
				percent, this.options.duration * percent, 0, 1, this.options.duration
			);
		} else {
			this.pos = eased = percent;
		}
		this.now = ( this.end - this.start ) * eased + this.start;

		if ( this.options.step ) {
			this.options.step.call( this.elem, this.now, this );
		}

		if ( hooks && hooks.set ) {
			hooks.set( this );
		} else {
			Tween.propHooks._default.set( this );
		}
		return this;
	}
};

Tween.prototype.init.prototype = Tween.prototype;

Tween.propHooks = {
	_default: {
		get: function( tween ) {
			var result;

			if ( tween.elem[ tween.prop ] != null &&
				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
				return tween.elem[ tween.prop ];
			}

			// passing an empty string as a 3rd parameter to .css will automatically
			// attempt a parseFloat and fallback to a string if the parse fails
			// so, simple values such as "10px" are parsed to Float.
			// complex values such as "rotate(1rad)" are returned as is.
			result = jQuery.css( tween.elem, tween.prop, "" );
			// Empty strings, null, undefined and "auto" are converted to 0.
			return !result || result === "auto" ? 0 : result;
		},
		set: function( tween ) {
			// use step hook for back compat - use cssHook if its there - use .style if its
			// available and use plain properties where available
			if ( jQuery.fx.step[ tween.prop ] ) {
				jQuery.fx.step[ tween.prop ]( tween );
			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
			} else {
				tween.elem[ tween.prop ] = tween.now;
			}
		}
	}
};

// Support: IE9
// Panic based approach to setting things on disconnected nodes

Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
	set: function( tween ) {
		if ( tween.elem.nodeType && tween.elem.parentNode ) {
			tween.elem[ tween.prop ] = tween.now;
		}
	}
};

jQuery.easing = {
	linear: function( p ) {
		return p;
	},
	swing: function( p ) {
		return 0.5 - Math.cos( p * Math.PI ) / 2;
	}
};

jQuery.fx = Tween.prototype.init;

// Back Compat <1.8 extension point
jQuery.fx.step = {};




var
	fxNow, timerId,
	rfxtypes = /^(?:toggle|show|hide)$/,
	rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
	rrun = /queueHooks$/,
	animationPrefilters = [ defaultPrefilter ],
	tweeners = {
		"*": [ function( prop, value ) {
			var tween = this.createTween( prop, value ),
				target = tween.cur(),
				parts = rfxnum.exec( value ),
				unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),

				// Starting value computation is required for potential unit mismatches
				start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
					rfxnum.exec( jQuery.css( tween.elem, prop ) ),
				scale = 1,
				maxIterations = 20;

			if ( start && start[ 3 ] !== unit ) {
				// Trust units reported by jQuery.css
				unit = unit || start[ 3 ];

				// Make sure we update the tween properties later on
				parts = parts || [];

				// Iteratively approximate from a nonzero starting point
				start = +target || 1;

				do {
					// If previous iteration zeroed out, double until we get *something*
					// Use a string for doubling factor so we don't accidentally see scale as unchanged below
					scale = scale || ".5";

					// Adjust and apply
					start = start / scale;
					jQuery.style( tween.elem, prop, start + unit );

				// Update scale, tolerating zero or NaN from tween.cur()
				// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
			}

			// Update tween properties
			if ( parts ) {
				start = tween.start = +start || +target || 0;
				tween.unit = unit;
				// If a +=/-= token was provided, we're doing a relative animation
				tween.end = parts[ 1 ] ?
					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
					+parts[ 2 ];
			}

			return tween;
		} ]
	};

// Animations created synchronously will run synchronously
function createFxNow() {
	setTimeout(function() {
		fxNow = undefined;
	});
	return ( fxNow = jQuery.now() );
}

// Generate parameters to create a standard animation
function genFx( type, includeWidth ) {
	var which,
		i = 0,
		attrs = { height: type };

	// if we include width, step value is 1 to do all cssExpand values,
	// if we don't include width, step value is 2 to skip over Left and Right
	includeWidth = includeWidth ? 1 : 0;
	for ( ; i < 4 ; i += 2 - includeWidth ) {
		which = cssExpand[ i ];
		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
	}

	if ( includeWidth ) {
		attrs.opacity = attrs.width = type;
	}

	return attrs;
}

function createTween( value, prop, animation ) {
	var tween,
		collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
		index = 0,
		length = collection.length;
	for ( ; index < length; index++ ) {
		if ( (tween = collection[ index ].call( animation, prop, value )) ) {

			// we're done with this property
			return tween;
		}
	}
}

function defaultPrefilter( elem, props, opts ) {
	/* jshint validthis: true */
	var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
		anim = this,
		orig = {},
		style = elem.style,
		hidden = elem.nodeType && isHidden( elem ),
		dataShow = data_priv.get( elem, "fxshow" );

	// handle queue: false promises
	if ( !opts.queue ) {
		hooks = jQuery._queueHooks( elem, "fx" );
		if ( hooks.unqueued == null ) {
			hooks.unqueued = 0;
			oldfire = hooks.empty.fire;
			hooks.empty.fire = function() {
				if ( !hooks.unqueued ) {
					oldfire();
				}
			};
		}
		hooks.unqueued++;

		anim.always(function() {
			// doing this makes sure that the complete handler will be called
			// before this completes
			anim.always(function() {
				hooks.unqueued--;
				if ( !jQuery.queue( elem, "fx" ).length ) {
					hooks.empty.fire();
				}
			});
		});
	}

	// height/width overflow pass
	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
		// Make sure that nothing sneaks out
		// Record all 3 overflow attributes because IE9-10 do not
		// change the overflow attribute when overflowX and
		// overflowY are set to the same value
		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];

		// Set display property to inline-block for height/width
		// animations on inline elements that are having width/height animated
		display = jQuery.css( elem, "display" );

		// Test default display if display is currently "none"
		checkDisplay = display === "none" ?
			data_priv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;

		if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
			style.display = "inline-block";
		}
	}

	if ( opts.overflow ) {
		style.overflow = "hidden";
		anim.always(function() {
			style.overflow = opts.overflow[ 0 ];
			style.overflowX = opts.overflow[ 1 ];
			style.overflowY = opts.overflow[ 2 ];
		});
	}

	// show/hide pass
	for ( prop in props ) {
		value = props[ prop ];
		if ( rfxtypes.exec( value ) ) {
			delete props[ prop ];
			toggle = toggle || value === "toggle";
			if ( value === ( hidden ? "hide" : "show" ) ) {

				// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
					hidden = true;
				} else {
					continue;
				}
			}
			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );

		// Any non-fx value stops us from restoring the original display value
		} else {
			display = undefined;
		}
	}

	if ( !jQuery.isEmptyObject( orig ) ) {
		if ( dataShow ) {
			if ( "hidden" in dataShow ) {
				hidden = dataShow.hidden;
			}
		} else {
			dataShow = data_priv.access( elem, "fxshow", {} );
		}

		// store state if its toggle - enables .stop().toggle() to "reverse"
		if ( toggle ) {
			dataShow.hidden = !hidden;
		}
		if ( hidden ) {
			jQuery( elem ).show();
		} else {
			anim.done(function() {
				jQuery( elem ).hide();
			});
		}
		anim.done(function() {
			var prop;

			data_priv.remove( elem, "fxshow" );
			for ( prop in orig ) {
				jQuery.style( elem, prop, orig[ prop ] );
			}
		});
		for ( prop in orig ) {
			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );

			if ( !( prop in dataShow ) ) {
				dataShow[ prop ] = tween.start;
				if ( hidden ) {
					tween.end = tween.start;
					tween.start = prop === "width" || prop === "height" ? 1 : 0;
				}
			}
		}

	// If this is a noop like .hide().hide(), restore an overwritten display value
	} else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
		style.display = display;
	}
}

function propFilter( props, specialEasing ) {
	var index, name, easing, value, hooks;

	// camelCase, specialEasing and expand cssHook pass
	for ( index in props ) {
		name = jQuery.camelCase( index );
		easing = specialEasing[ name ];
		value = props[ index ];
		if ( jQuery.isArray( value ) ) {
			easing = value[ 1 ];
			value = props[ index ] = value[ 0 ];
		}

		if ( index !== name ) {
			props[ name ] = value;
			delete props[ index ];
		}

		hooks = jQuery.cssHooks[ name ];
		if ( hooks && "expand" in hooks ) {
			value = hooks.expand( value );
			delete props[ name ];

			// not quite $.extend, this wont overwrite keys already present.
			// also - reusing 'index' from above because we have the correct "name"
			for ( index in value ) {
				if ( !( index in props ) ) {
					props[ index ] = value[ index ];
					specialEasing[ index ] = easing;
				}
			}
		} else {
			specialEasing[ name ] = easing;
		}
	}
}

function Animation( elem, properties, options ) {
	var result,
		stopped,
		index = 0,
		length = animationPrefilters.length,
		deferred = jQuery.Deferred().always( function() {
			// don't match elem in the :animated selector
			delete tick.elem;
		}),
		tick = function() {
			if ( stopped ) {
				return false;
			}
			var currentTime = fxNow || createFxNow(),
				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
				// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
				temp = remaining / animation.duration || 0,
				percent = 1 - temp,
				index = 0,
				length = animation.tweens.length;

			for ( ; index < length ; index++ ) {
				animation.tweens[ index ].run( percent );
			}

			deferred.notifyWith( elem, [ animation, percent, remaining ]);

			if ( percent < 1 && length ) {
				return remaining;
			} else {
				deferred.resolveWith( elem, [ animation ] );
				return false;
			}
		},
		animation = deferred.promise({
			elem: elem,
			props: jQuery.extend( {}, properties ),
			opts: jQuery.extend( true, { specialEasing: {} }, options ),
			originalProperties: properties,
			originalOptions: options,
			startTime: fxNow || createFxNow(),
			duration: options.duration,
			tweens: [],
			createTween: function( prop, end ) {
				var tween = jQuery.Tween( elem, animation.opts, prop, end,
						animation.opts.specialEasing[ prop ] || animation.opts.easing );
				animation.tweens.push( tween );
				return tween;
			},
			stop: function( gotoEnd ) {
				var index = 0,
					// if we are going to the end, we want to run all the tweens
					// otherwise we skip this part
					length = gotoEnd ? animation.tweens.length : 0;
				if ( stopped ) {
					return this;
				}
				stopped = true;
				for ( ; index < length ; index++ ) {
					animation.tweens[ index ].run( 1 );
				}

				// resolve when we played the last frame
				// otherwise, reject
				if ( gotoEnd ) {
					deferred.resolveWith( elem, [ animation, gotoEnd ] );
				} else {
					deferred.rejectWith( elem, [ animation, gotoEnd ] );
				}
				return this;
			}
		}),
		props = animation.props;

	propFilter( props, animation.opts.specialEasing );

	for ( ; index < length ; index++ ) {
		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
		if ( result ) {
			return result;
		}
	}

	jQuery.map( props, createTween, animation );

	if ( jQuery.isFunction( animation.opts.start ) ) {
		animation.opts.start.call( elem, animation );
	}

	jQuery.fx.timer(
		jQuery.extend( tick, {
			elem: elem,
			anim: animation,
			queue: animation.opts.queue
		})
	);

	// attach callbacks from options
	return animation.progress( animation.opts.progress )
		.done( animation.opts.done, animation.opts.complete )
		.fail( animation.opts.fail )
		.always( animation.opts.always );
}

jQuery.Animation = jQuery.extend( Animation, {

	tweener: function( props, callback ) {
		if ( jQuery.isFunction( props ) ) {
			callback = props;
			props = [ "*" ];
		} else {
			props = props.split(" ");
		}

		var prop,
			index = 0,
			length = props.length;

		for ( ; index < length ; index++ ) {
			prop = props[ index ];
			tweeners[ prop ] = tweeners[ prop ] || [];
			tweeners[ prop ].unshift( callback );
		}
	},

	prefilter: function( callback, prepend ) {
		if ( prepend ) {
			animationPrefilters.unshift( callback );
		} else {
			animationPrefilters.push( callback );
		}
	}
});

jQuery.speed = function( speed, easing, fn ) {
	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
		complete: fn || !fn && easing ||
			jQuery.isFunction( speed ) && speed,
		duration: speed,
		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
	};

	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;

	// normalize opt.queue - true/undefined/null -> "fx"
	if ( opt.queue == null || opt.queue === true ) {
		opt.queue = "fx";
	}

	// Queueing
	opt.old = opt.complete;

	opt.complete = function() {
		if ( jQuery.isFunction( opt.old ) ) {
			opt.old.call( this );
		}

		if ( opt.queue ) {
			jQuery.dequeue( this, opt.queue );
		}
	};

	return opt;
};

jQuery.fn.extend({
	fadeTo: function( speed, to, easing, callback ) {

		// show any hidden elements after setting opacity to 0
		return this.filter( isHidden ).css( "opacity", 0 ).show()

			// animate to the value specified
			.end().animate({ opacity: to }, speed, easing, callback );
	},
	animate: function( prop, speed, easing, callback ) {
		var empty = jQuery.isEmptyObject( prop ),
			optall = jQuery.speed( speed, easing, callback ),
			doAnimation = function() {
				// Operate on a copy of prop so per-property easing won't be lost
				var anim = Animation( this, jQuery.extend( {}, prop ), optall );

				// Empty animations, or finishing resolves immediately
				if ( empty || data_priv.get( this, "finish" ) ) {
					anim.stop( true );
				}
			};
			doAnimation.finish = doAnimation;

		return empty || optall.queue === false ?
			this.each( doAnimation ) :
			this.queue( optall.queue, doAnimation );
	},
	stop: function( type, clearQueue, gotoEnd ) {
		var stopQueue = function( hooks ) {
			var stop = hooks.stop;
			delete hooks.stop;
			stop( gotoEnd );
		};

		if ( typeof type !== "string" ) {
			gotoEnd = clearQueue;
			clearQueue = type;
			type = undefined;
		}
		if ( clearQueue && type !== false ) {
			this.queue( type || "fx", [] );
		}

		return this.each(function() {
			var dequeue = true,
				index = type != null && type + "queueHooks",
				timers = jQuery.timers,
				data = data_priv.get( this );

			if ( index ) {
				if ( data[ index ] && data[ index ].stop ) {
					stopQueue( data[ index ] );
				}
			} else {
				for ( index in data ) {
					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
						stopQueue( data[ index ] );
					}
				}
			}

			for ( index = timers.length; index--; ) {
				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
					timers[ index ].anim.stop( gotoEnd );
					dequeue = false;
					timers.splice( index, 1 );
				}
			}

			// start the next in the queue if the last step wasn't forced
			// timers currently will call their complete callbacks, which will dequeue
			// but only if they were gotoEnd
			if ( dequeue || !gotoEnd ) {
				jQuery.dequeue( this, type );
			}
		});
	},
	finish: function( type ) {
		if ( type !== false ) {
			type = type || "fx";
		}
		return this.each(function() {
			var index,
				data = data_priv.get( this ),
				queue = data[ type + "queue" ],
				hooks = data[ type + "queueHooks" ],
				timers = jQuery.timers,
				length = queue ? queue.length : 0;

			// enable finishing flag on private data
			data.finish = true;

			// empty the queue first
			jQuery.queue( this, type, [] );

			if ( hooks && hooks.stop ) {
				hooks.stop.call( this, true );
			}

			// look for any active animations, and finish them
			for ( index = timers.length; index--; ) {
				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
					timers[ index ].anim.stop( true );
					timers.splice( index, 1 );
				}
			}

			// look for any animations in the old queue and finish them
			for ( index = 0; index < length; index++ ) {
				if ( queue[ index ] && queue[ index ].finish ) {
					queue[ index ].finish.call( this );
				}
			}

			// turn off finishing flag
			delete data.finish;
		});
	}
});

jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
	var cssFn = jQuery.fn[ name ];
	jQuery.fn[ name ] = function( speed, easing, callback ) {
		return speed == null || typeof speed === "boolean" ?
			cssFn.apply( this, arguments ) :
			this.animate( genFx( name, true ), speed, easing, callback );
	};
});

// Generate shortcuts for custom animations
jQuery.each({
	slideDown: genFx("show"),
	slideUp: genFx("hide"),
	slideToggle: genFx("toggle"),
	fadeIn: { opacity: "show" },
	fadeOut: { opacity: "hide" },
	fadeToggle: { opacity: "toggle" }
}, function( name, props ) {
	jQuery.fn[ name ] = function( speed, easing, callback ) {
		return this.animate( props, speed, easing, callback );
	};
});

jQuery.timers = [];
jQuery.fx.tick = function() {
	var timer,
		i = 0,
		timers = jQuery.timers;

	fxNow = jQuery.now();

	for ( ; i < timers.length; i++ ) {
		timer = timers[ i ];
		// Checks the timer has not already been removed
		if ( !timer() && timers[ i ] === timer ) {
			timers.splice( i--, 1 );
		}
	}

	if ( !timers.length ) {
		jQuery.fx.stop();
	}
	fxNow = undefined;
};

jQuery.fx.timer = function( timer ) {
	jQuery.timers.push( timer );
	if ( timer() ) {
		jQuery.fx.start();
	} else {
		jQuery.timers.pop();
	}
};

jQuery.fx.interval = 13;

jQuery.fx.start = function() {
	if ( !timerId ) {
		timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
	}
};

jQuery.fx.stop = function() {
	clearInterval( timerId );
	timerId = null;
};

jQuery.fx.speeds = {
	slow: 600,
	fast: 200,
	// Default speed
	_default: 400
};


// Based off of the plugin by Clint Helfers, with permission.
// http://blindsignals.com/index.php/2009/07/jquery-delay/
jQuery.fn.delay = function( time, type ) {
	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
	type = type || "fx";

	return this.queue( type, function( next, hooks ) {
		var timeout = setTimeout( next, time );
		hooks.stop = function() {
			clearTimeout( timeout );
		};
	});
};


(function() {
	var input = document.createElement( "input" ),
		select = document.createElement( "select" ),
		opt = select.appendChild( document.createElement( "option" ) );

	input.type = "checkbox";

	// Support: iOS 5.1, Android 4.x, Android 2.3
	// Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere)
	support.checkOn = input.value !== "";

	// Must access the parent to make an option select properly
	// Support: IE9, IE10
	support.optSelected = opt.selected;

	// Make sure that the options inside disabled selects aren't marked as disabled
	// (WebKit marks them as disabled)
	select.disabled = true;
	support.optDisabled = !opt.disabled;

	// Check if an input maintains its value after becoming a radio
	// Support: IE9, IE10
	input = document.createElement( "input" );
	input.value = "t";
	input.type = "radio";
	support.radioValue = input.value === "t";
})();


var nodeHook, boolHook,
	attrHandle = jQuery.expr.attrHandle;

jQuery.fn.extend({
	attr: function( name, value ) {
		return access( this, jQuery.attr, name, value, arguments.length > 1 );
	},

	removeAttr: function( name ) {
		return this.each(function() {
			jQuery.removeAttr( this, name );
		});
	}
});

jQuery.extend({
	attr: function( elem, name, value ) {
		var hooks, ret,
			nType = elem.nodeType;

		// don't get/set attributes on text, comment and attribute nodes
		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

		// Fallback to prop when attributes are not supported
		if ( typeof elem.getAttribute === strundefined ) {
			return jQuery.prop( elem, name, value );
		}

		// All attributes are lowercase
		// Grab necessary hook if one is defined
		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
			name = name.toLowerCase();
			hooks = jQuery.attrHooks[ name ] ||
				( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
		}

		if ( value !== undefined ) {

			if ( value === null ) {
				jQuery.removeAttr( elem, name );

			} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
				return ret;

			} else {
				elem.setAttribute( name, value + "" );
				return value;
			}

		} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
			return ret;

		} else {
			ret = jQuery.find.attr( elem, name );

			// Non-existent attributes return null, we normalize to undefined
			return ret == null ?
				undefined :
				ret;
		}
	},

	removeAttr: function( elem, value ) {
		var name, propName,
			i = 0,
			attrNames = value && value.match( rnotwhite );

		if ( attrNames && elem.nodeType === 1 ) {
			while ( (name = attrNames[i++]) ) {
				propName = jQuery.propFix[ name ] || name;

				// Boolean attributes get special treatment (#10870)
				if ( jQuery.expr.match.bool.test( name ) ) {
					// Set corresponding property to false
					elem[ propName ] = false;
				}

				elem.removeAttribute( name );
			}
		}
	},

	attrHooks: {
		type: {
			set: function( elem, value ) {
				if ( !support.radioValue && value === "radio" &&
					jQuery.nodeName( elem, "input" ) ) {
					// Setting the type on a radio button after the value resets the value in IE6-9
					// Reset value to default in case type is set after value during creation
					var val = elem.value;
					elem.setAttribute( "type", value );
					if ( val ) {
						elem.value = val;
					}
					return value;
				}
			}
		}
	}
});

// Hooks for boolean attributes
boolHook = {
	set: function( elem, value, name ) {
		if ( value === false ) {
			// Remove boolean attributes when set to false
			jQuery.removeAttr( elem, name );
		} else {
			elem.setAttribute( name, name );
		}
		return name;
	}
};
jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
	var getter = attrHandle[ name ] || jQuery.find.attr;

	attrHandle[ name ] = function( elem, name, isXML ) {
		var ret, handle;
		if ( !isXML ) {
			// Avoid an infinite loop by temporarily removing this function from the getter
			handle = attrHandle[ name ];
			attrHandle[ name ] = ret;
			ret = getter( elem, name, isXML ) != null ?
				name.toLowerCase() :
				null;
			attrHandle[ name ] = handle;
		}
		return ret;
	};
});




var rfocusable = /^(?:input|select|textarea|button)$/i;

jQuery.fn.extend({
	prop: function( name, value ) {
		return access( this, jQuery.prop, name, value, arguments.length > 1 );
	},

	removeProp: function( name ) {
		return this.each(function() {
			delete this[ jQuery.propFix[ name ] || name ];
		});
	}
});

jQuery.extend({
	propFix: {
		"for": "htmlFor",
		"class": "className"
	},

	prop: function( elem, name, value ) {
		var ret, hooks, notxml,
			nType = elem.nodeType;

		// don't get/set properties on text, comment and attribute nodes
		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

		if ( notxml ) {
			// Fix name and attach hooks
			name = jQuery.propFix[ name ] || name;
			hooks = jQuery.propHooks[ name ];
		}

		if ( value !== undefined ) {
			return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
				ret :
				( elem[ name ] = value );

		} else {
			return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
				ret :
				elem[ name ];
		}
	},

	propHooks: {
		tabIndex: {
			get: function( elem ) {
				return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?
					elem.tabIndex :
					-1;
			}
		}
	}
});

// Support: IE9+
// Selectedness for an option in an optgroup can be inaccurate
if ( !support.optSelected ) {
	jQuery.propHooks.selected = {
		get: function( elem ) {
			var parent = elem.parentNode;
			if ( parent && parent.parentNode ) {
				parent.parentNode.selectedIndex;
			}
			return null;
		}
	};
}

jQuery.each([
	"tabIndex",
	"readOnly",
	"maxLength",
	"cellSpacing",
	"cellPadding",
	"rowSpan",
	"colSpan",
	"useMap",
	"frameBorder",
	"contentEditable"
], function() {
	jQuery.propFix[ this.toLowerCase() ] = this;
});




var rclass = /[\t\r\n\f]/g;

jQuery.fn.extend({
	addClass: function( value ) {
		var classes, elem, cur, clazz, j, finalValue,
			proceed = typeof value === "string" && value,
			i = 0,
			len = this.length;

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( j ) {
				jQuery( this ).addClass( value.call( this, j, this.className ) );
			});
		}

		if ( proceed ) {
			// The disjunction here is for better compressibility (see removeClass)
			classes = ( value || "" ).match( rnotwhite ) || [];

			for ( ; i < len; i++ ) {
				elem = this[ i ];
				cur = elem.nodeType === 1 && ( elem.className ?
					( " " + elem.className + " " ).replace( rclass, " " ) :
					" "
				);

				if ( cur ) {
					j = 0;
					while ( (clazz = classes[j++]) ) {
						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
							cur += clazz + " ";
						}
					}

					// only assign if different to avoid unneeded rendering.
					finalValue = jQuery.trim( cur );
					if ( elem.className !== finalValue ) {
						elem.className = finalValue;
					}
				}
			}
		}

		return this;
	},

	removeClass: function( value ) {
		var classes, elem, cur, clazz, j, finalValue,
			proceed = arguments.length === 0 || typeof value === "string" && value,
			i = 0,
			len = this.length;

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( j ) {
				jQuery( this ).removeClass( value.call( this, j, this.className ) );
			});
		}
		if ( proceed ) {
			classes = ( value || "" ).match( rnotwhite ) || [];

			for ( ; i < len; i++ ) {
				elem = this[ i ];
				// This expression is here for better compressibility (see addClass)
				cur = elem.nodeType === 1 && ( elem.className ?
					( " " + elem.className + " " ).replace( rclass, " " ) :
					""
				);

				if ( cur ) {
					j = 0;
					while ( (clazz = classes[j++]) ) {
						// Remove *all* instances
						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
							cur = cur.replace( " " + clazz + " ", " " );
						}
					}

					// only assign if different to avoid unneeded rendering.
					finalValue = value ? jQuery.trim( cur ) : "";
					if ( elem.className !== finalValue ) {
						elem.className = finalValue;
					}
				}
			}
		}

		return this;
	},

	toggleClass: function( value, stateVal ) {
		var type = typeof value;

		if ( typeof stateVal === "boolean" && type === "string" ) {
			return stateVal ? this.addClass( value ) : this.removeClass( value );
		}

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( i ) {
				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
			});
		}

		return this.each(function() {
			if ( type === "string" ) {
				// toggle individual class names
				var className,
					i = 0,
					self = jQuery( this ),
					classNames = value.match( rnotwhite ) || [];

				while ( (className = classNames[ i++ ]) ) {
					// check each className given, space separated list
					if ( self.hasClass( className ) ) {
						self.removeClass( className );
					} else {
						self.addClass( className );
					}
				}

			// Toggle whole class name
			} else if ( type === strundefined || type === "boolean" ) {
				if ( this.className ) {
					// store className if set
					data_priv.set( this, "__className__", this.className );
				}

				// If the element has a class name or if we're passed "false",
				// then remove the whole classname (if there was one, the above saved it).
				// Otherwise bring back whatever was previously saved (if anything),
				// falling back to the empty string if nothing was stored.
				this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
			}
		});
	},

	hasClass: function( selector ) {
		var className = " " + selector + " ",
			i = 0,
			l = this.length;
		for ( ; i < l; i++ ) {
			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
				return true;
			}
		}

		return false;
	}
});




var rreturn = /\r/g;

jQuery.fn.extend({
	val: function( value ) {
		var hooks, ret, isFunction,
			elem = this[0];

		if ( !arguments.length ) {
			if ( elem ) {
				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];

				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
					return ret;
				}

				ret = elem.value;

				return typeof ret === "string" ?
					// handle most common string cases
					ret.replace(rreturn, "") :
					// handle cases where value is null/undef or number
					ret == null ? "" : ret;
			}

			return;
		}

		isFunction = jQuery.isFunction( value );

		return this.each(function( i ) {
			var val;

			if ( this.nodeType !== 1 ) {
				return;
			}

			if ( isFunction ) {
				val = value.call( this, i, jQuery( this ).val() );
			} else {
				val = value;
			}

			// Treat null/undefined as ""; convert numbers to string
			if ( val == null ) {
				val = "";

			} else if ( typeof val === "number" ) {
				val += "";

			} else if ( jQuery.isArray( val ) ) {
				val = jQuery.map( val, function( value ) {
					return value == null ? "" : value + "";
				});
			}

			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];

			// If set returns undefined, fall back to normal setting
			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
				this.value = val;
			}
		});
	}
});

jQuery.extend({
	valHooks: {
		option: {
			get: function( elem ) {
				var val = jQuery.find.attr( elem, "value" );
				return val != null ?
					val :
					// Support: IE10-11+
					// option.text throws exceptions (#14686, #14858)
					jQuery.trim( jQuery.text( elem ) );
			}
		},
		select: {
			get: function( elem ) {
				var value, option,
					options = elem.options,
					index = elem.selectedIndex,
					one = elem.type === "select-one" || index < 0,
					values = one ? null : [],
					max = one ? index + 1 : options.length,
					i = index < 0 ?
						max :
						one ? index : 0;

				// Loop through all the selected options
				for ( ; i < max; i++ ) {
					option = options[ i ];

					// IE6-9 doesn't update selected after form reset (#2551)
					if ( ( option.selected || i === index ) &&
							// Don't return options that are disabled or in a disabled optgroup
							( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) &&
							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {

						// Get the specific value for the option
						value = jQuery( option ).val();

						// We don't need an array for one selects
						if ( one ) {
							return value;
						}

						// Multi-Selects return an array
						values.push( value );
					}
				}

				return values;
			},

			set: function( elem, value ) {
				var optionSet, option,
					options = elem.options,
					values = jQuery.makeArray( value ),
					i = options.length;

				while ( i-- ) {
					option = options[ i ];
					if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {
						optionSet = true;
					}
				}

				// force browsers to behave consistently when non-matching value is set
				if ( !optionSet ) {
					elem.selectedIndex = -1;
				}
				return values;
			}
		}
	}
});

// Radios and checkboxes getter/setter
jQuery.each([ "radio", "checkbox" ], function() {
	jQuery.valHooks[ this ] = {
		set: function( elem, value ) {
			if ( jQuery.isArray( value ) ) {
				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
			}
		}
	};
	if ( !support.checkOn ) {
		jQuery.valHooks[ this ].get = function( elem ) {
			// Support: Webkit
			// "" is returned instead of "on" if a value isn't specified
			return elem.getAttribute("value") === null ? "on" : elem.value;
		};
	}
});




// Return jQuery for attributes-only inclusion


jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {

	// Handle event binding
	jQuery.fn[ name ] = function( data, fn ) {
		return arguments.length > 0 ?
			this.on( name, null, data, fn ) :
			this.trigger( name );
	};
});

jQuery.fn.extend({
	hover: function( fnOver, fnOut ) {
		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
	},

	bind: function( types, data, fn ) {
		return this.on( types, null, data, fn );
	},
	unbind: function( types, fn ) {
		return this.off( types, null, fn );
	},

	delegate: function( selector, types, data, fn ) {
		return this.on( types, selector, data, fn );
	},
	undelegate: function( selector, types, fn ) {
		// ( namespace ) or ( selector, types [, fn] )
		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
	}
});


var nonce = jQuery.now();

var rquery = (/\?/);



// Support: Android 2.3
// Workaround failure to string-cast null input
jQuery.parseJSON = function( data ) {
	return JSON.parse( data + "" );
};


// Cross-browser xml parsing
jQuery.parseXML = function( data ) {
	var xml, tmp;
	if ( !data || typeof data !== "string" ) {
		return null;
	}

	// Support: IE9
	try {
		tmp = new DOMParser();
		xml = tmp.parseFromString( data, "text/xml" );
	} catch ( e ) {
		xml = undefined;
	}

	if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
		jQuery.error( "Invalid XML: " + data );
	}
	return xml;
};


var
	// Document location
	ajaxLocParts,
	ajaxLocation,

	rhash = /#.*$/,
	rts = /([?&])_=[^&]*/,
	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
	// #7653, #8125, #8152: local protocol detection
	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
	rnoContent = /^(?:GET|HEAD)$/,
	rprotocol = /^\/\//,
	rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,

	/* Prefilters
	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
	 * 2) These are called:
	 *    - BEFORE asking for a transport
	 *    - AFTER param serialization (s.data is a string if s.processData is true)
	 * 3) key is the dataType
	 * 4) the catchall symbol "*" can be used
	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
	 */
	prefilters = {},

	/* Transports bindings
	 * 1) key is the dataType
	 * 2) the catchall symbol "*" can be used
	 * 3) selection will start with transport dataType and THEN go to "*" if needed
	 */
	transports = {},

	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
	allTypes = "*/".concat("*");

// #8138, IE may throw an exception when accessing
// a field from window.location if document.domain has been set
try {
	ajaxLocation = location.href;
} catch( e ) {
	// Use the href attribute of an A element
	// since IE will modify it given document.location
	ajaxLocation = document.createElement( "a" );
	ajaxLocation.href = "";
	ajaxLocation = ajaxLocation.href;
}

// Segment location into parts
ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];

// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) {

	// dataTypeExpression is optional and defaults to "*"
	return function( dataTypeExpression, func ) {

		if ( typeof dataTypeExpression !== "string" ) {
			func = dataTypeExpression;
			dataTypeExpression = "*";
		}

		var dataType,
			i = 0,
			dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];

		if ( jQuery.isFunction( func ) ) {
			// For each dataType in the dataTypeExpression
			while ( (dataType = dataTypes[i++]) ) {
				// Prepend if requested
				if ( dataType[0] === "+" ) {
					dataType = dataType.slice( 1 ) || "*";
					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );

				// Otherwise append
				} else {
					(structure[ dataType ] = structure[ dataType ] || []).push( func );
				}
			}
		}
	};
}

// Base inspection function for prefilters and transports
function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {

	var inspected = {},
		seekingTransport = ( structure === transports );

	function inspect( dataType ) {
		var selected;
		inspected[ dataType ] = true;
		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
			if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
				options.dataTypes.unshift( dataTypeOrTransport );
				inspect( dataTypeOrTransport );
				return false;
			} else if ( seekingTransport ) {
				return !( selected = dataTypeOrTransport );
			}
		});
		return selected;
	}

	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
}

// A special extend for ajax options
// that takes "flat" options (not to be deep extended)
// Fixes #9887
function ajaxExtend( target, src ) {
	var key, deep,
		flatOptions = jQuery.ajaxSettings.flatOptions || {};

	for ( key in src ) {
		if ( src[ key ] !== undefined ) {
			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
		}
	}
	if ( deep ) {
		jQuery.extend( true, target, deep );
	}

	return target;
}

/* Handles responses to an ajax request:
 * - finds the right dataType (mediates between content-type and expected dataType)
 * - returns the corresponding response
 */
function ajaxHandleResponses( s, jqXHR, responses ) {

	var ct, type, finalDataType, firstDataType,
		contents = s.contents,
		dataTypes = s.dataTypes;

	// Remove auto dataType and get content-type in the process
	while ( dataTypes[ 0 ] === "*" ) {
		dataTypes.shift();
		if ( ct === undefined ) {
			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
		}
	}

	// Check if we're dealing with a known content-type
	if ( ct ) {
		for ( type in contents ) {
			if ( contents[ type ] && contents[ type ].test( ct ) ) {
				dataTypes.unshift( type );
				break;
			}
		}
	}

	// Check to see if we have a response for the expected dataType
	if ( dataTypes[ 0 ] in responses ) {
		finalDataType = dataTypes[ 0 ];
	} else {
		// Try convertible dataTypes
		for ( type in responses ) {
			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
				finalDataType = type;
				break;
			}
			if ( !firstDataType ) {
				firstDataType = type;
			}
		}
		// Or just use first one
		finalDataType = finalDataType || firstDataType;
	}

	// If we found a dataType
	// We add the dataType to the list if needed
	// and return the corresponding response
	if ( finalDataType ) {
		if ( finalDataType !== dataTypes[ 0 ] ) {
			dataTypes.unshift( finalDataType );
		}
		return responses[ finalDataType ];
	}
}

/* Chain conversions given the request and the original response
 * Also sets the responseXXX fields on the jqXHR instance
 */
function ajaxConvert( s, response, jqXHR, isSuccess ) {
	var conv2, current, conv, tmp, prev,
		converters = {},
		// Work with a copy of dataTypes in case we need to modify it for conversion
		dataTypes = s.dataTypes.slice();

	// Create converters map with lowercased keys
	if ( dataTypes[ 1 ] ) {
		for ( conv in s.converters ) {
			converters[ conv.toLowerCase() ] = s.converters[ conv ];
		}
	}

	current = dataTypes.shift();

	// Convert to each sequential dataType
	while ( current ) {

		if ( s.responseFields[ current ] ) {
			jqXHR[ s.responseFields[ current ] ] = response;
		}

		// Apply the dataFilter if provided
		if ( !prev && isSuccess && s.dataFilter ) {
			response = s.dataFilter( response, s.dataType );
		}

		prev = current;
		current = dataTypes.shift();

		if ( current ) {

		// There's only work to do if current dataType is non-auto
			if ( current === "*" ) {

				current = prev;

			// Convert response if prev dataType is non-auto and differs from current
			} else if ( prev !== "*" && prev !== current ) {

				// Seek a direct converter
				conv = converters[ prev + " " + current ] || converters[ "* " + current ];

				// If none found, seek a pair
				if ( !conv ) {
					for ( conv2 in converters ) {

						// If conv2 outputs current
						tmp = conv2.split( " " );
						if ( tmp[ 1 ] === current ) {

							// If prev can be converted to accepted input
							conv = converters[ prev + " " + tmp[ 0 ] ] ||
								converters[ "* " + tmp[ 0 ] ];
							if ( conv ) {
								// Condense equivalence converters
								if ( conv === true ) {
									conv = converters[ conv2 ];

								// Otherwise, insert the intermediate dataType
								} else if ( converters[ conv2 ] !== true ) {
									current = tmp[ 0 ];
									dataTypes.unshift( tmp[ 1 ] );
								}
								break;
							}
						}
					}
				}

				// Apply converter (if not an equivalence)
				if ( conv !== true ) {

					// Unless errors are allowed to bubble, catch and return them
					if ( conv && s[ "throws" ] ) {
						response = conv( response );
					} else {
						try {
							response = conv( response );
						} catch ( e ) {
							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
						}
					}
				}
			}
		}
	}

	return { state: "success", data: response };
}

jQuery.extend({

	// Counter for holding the number of active queries
	active: 0,

	// Last-Modified header cache for next request
	lastModified: {},
	etag: {},

	ajaxSettings: {
		url: ajaxLocation,
		type: "GET",
		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
		global: true,
		processData: true,
		async: true,
		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
		/*
		timeout: 0,
		data: null,
		dataType: null,
		username: null,
		password: null,
		cache: null,
		throws: false,
		traditional: false,
		headers: {},
		*/

		accepts: {
			"*": allTypes,
			text: "text/plain",
			html: "text/html",
			xml: "application/xml, text/xml",
			json: "application/json, text/javascript"
		},

		contents: {
			xml: /xml/,
			html: /html/,
			json: /json/
		},

		responseFields: {
			xml: "responseXML",
			text: "responseText",
			json: "responseJSON"
		},

		// Data converters
		// Keys separate source (or catchall "*") and destination types with a single space
		converters: {

			// Convert anything to text
			"* text": String,

			// Text to html (true = no transformation)
			"text html": true,

			// Evaluate text as a json expression
			"text json": jQuery.parseJSON,

			// Parse text as xml
			"text xml": jQuery.parseXML
		},

		// For options that shouldn't be deep extended:
		// you can add your own custom options here if
		// and when you create one that shouldn't be
		// deep extended (see ajaxExtend)
		flatOptions: {
			url: true,
			context: true
		}
	},

	// Creates a full fledged settings object into target
	// with both ajaxSettings and settings fields.
	// If target is omitted, writes into ajaxSettings.
	ajaxSetup: function( target, settings ) {
		return settings ?

			// Building a settings object
			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :

			// Extending ajaxSettings
			ajaxExtend( jQuery.ajaxSettings, target );
	},

	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
	ajaxTransport: addToPrefiltersOrTransports( transports ),

	// Main method
	ajax: function( url, options ) {

		// If url is an object, simulate pre-1.5 signature
		if ( typeof url === "object" ) {
			options = url;
			url = undefined;
		}

		// Force options to be an object
		options = options || {};

		var transport,
			// URL without anti-cache param
			cacheURL,
			// Response headers
			responseHeadersString,
			responseHeaders,
			// timeout handle
			timeoutTimer,
			// Cross-domain detection vars
			parts,
			// To know if global events are to be dispatched
			fireGlobals,
			// Loop variable
			i,
			// Create the final options object
			s = jQuery.ajaxSetup( {}, options ),
			// Callbacks context
			callbackContext = s.context || s,
			// Context for global events is callbackContext if it is a DOM node or jQuery collection
			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
				jQuery( callbackContext ) :
				jQuery.event,
			// Deferreds
			deferred = jQuery.Deferred(),
			completeDeferred = jQuery.Callbacks("once memory"),
			// Status-dependent callbacks
			statusCode = s.statusCode || {},
			// Headers (they are sent all at once)
			requestHeaders = {},
			requestHeadersNames = {},
			// The jqXHR state
			state = 0,
			// Default abort message
			strAbort = "canceled",
			// Fake xhr
			jqXHR = {
				readyState: 0,

				// Builds headers hashtable if needed
				getResponseHeader: function( key ) {
					var match;
					if ( state === 2 ) {
						if ( !responseHeaders ) {
							responseHeaders = {};
							while ( (match = rheaders.exec( responseHeadersString )) ) {
								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
							}
						}
						match = responseHeaders[ key.toLowerCase() ];
					}
					return match == null ? null : match;
				},

				// Raw string
				getAllResponseHeaders: function() {
					return state === 2 ? responseHeadersString : null;
				},

				// Caches the header
				setRequestHeader: function( name, value ) {
					var lname = name.toLowerCase();
					if ( !state ) {
						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
						requestHeaders[ name ] = value;
					}
					return this;
				},

				// Overrides response content-type header
				overrideMimeType: function( type ) {
					if ( !state ) {
						s.mimeType = type;
					}
					return this;
				},

				// Status-dependent callbacks
				statusCode: function( map ) {
					var code;
					if ( map ) {
						if ( state < 2 ) {
							for ( code in map ) {
								// Lazy-add the new callback in a way that preserves old ones
								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
							}
						} else {
							// Execute the appropriate callbacks
							jqXHR.always( map[ jqXHR.status ] );
						}
					}
					return this;
				},

				// Cancel the request
				abort: function( statusText ) {
					var finalText = statusText || strAbort;
					if ( transport ) {
						transport.abort( finalText );
					}
					done( 0, finalText );
					return this;
				}
			};

		// Attach deferreds
		deferred.promise( jqXHR ).complete = completeDeferred.add;
		jqXHR.success = jqXHR.done;
		jqXHR.error = jqXHR.fail;

		// Remove hash character (#7531: and string promotion)
		// Add protocol if not provided (prefilters might expect it)
		// Handle falsy url in the settings object (#10093: consistency with old signature)
		// We also use the url parameter if available
		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" )
			.replace( rprotocol, ajaxLocParts[ 1 ] + "//" );

		// Alias method option to type as per ticket #12004
		s.type = options.method || options.type || s.method || s.type;

		// Extract dataTypes list
		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];

		// A cross-domain request is in order when we have a protocol:host:port mismatch
		if ( s.crossDomain == null ) {
			parts = rurl.exec( s.url.toLowerCase() );
			s.crossDomain = !!( parts &&
				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
			);
		}

		// Convert data if not already a string
		if ( s.data && s.processData && typeof s.data !== "string" ) {
			s.data = jQuery.param( s.data, s.traditional );
		}

		// Apply prefilters
		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );

		// If request was aborted inside a prefilter, stop there
		if ( state === 2 ) {
			return jqXHR;
		}

		// We can fire global events as of now if asked to
		fireGlobals = s.global;

		// Watch for a new set of requests
		if ( fireGlobals && jQuery.active++ === 0 ) {
			jQuery.event.trigger("ajaxStart");
		}

		// Uppercase the type
		s.type = s.type.toUpperCase();

		// Determine if request has content
		s.hasContent = !rnoContent.test( s.type );

		// Save the URL in case we're toying with the If-Modified-Since
		// and/or If-None-Match header later on
		cacheURL = s.url;

		// More options handling for requests with no content
		if ( !s.hasContent ) {

			// If data is available, append data to url
			if ( s.data ) {
				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
				// #9682: remove data so that it's not used in an eventual retry
				delete s.data;
			}

			// Add anti-cache in url if needed
			if ( s.cache === false ) {
				s.url = rts.test( cacheURL ) ?

					// If there is already a '_' parameter, set its value
					cacheURL.replace( rts, "$1_=" + nonce++ ) :

					// Otherwise add one to the end
					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
			}
		}

		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
		if ( s.ifModified ) {
			if ( jQuery.lastModified[ cacheURL ] ) {
				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
			}
			if ( jQuery.etag[ cacheURL ] ) {
				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
			}
		}

		// Set the correct header, if data is being sent
		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
			jqXHR.setRequestHeader( "Content-Type", s.contentType );
		}

		// Set the Accepts header for the server, depending on the dataType
		jqXHR.setRequestHeader(
			"Accept",
			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
				s.accepts[ "*" ]
		);

		// Check for headers option
		for ( i in s.headers ) {
			jqXHR.setRequestHeader( i, s.headers[ i ] );
		}

		// Allow custom headers/mimetypes and early abort
		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
			// Abort if not done already and return
			return jqXHR.abort();
		}

		// aborting is no longer a cancellation
		strAbort = "abort";

		// Install callbacks on deferreds
		for ( i in { success: 1, error: 1, complete: 1 } ) {
			jqXHR[ i ]( s[ i ] );
		}

		// Get transport
		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );

		// If no transport, we auto-abort
		if ( !transport ) {
			done( -1, "No Transport" );
		} else {
			jqXHR.readyState = 1;

			// Send global event
			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
			}
			// Timeout
			if ( s.async && s.timeout > 0 ) {
				timeoutTimer = setTimeout(function() {
					jqXHR.abort("timeout");
				}, s.timeout );
			}

			try {
				state = 1;
				transport.send( requestHeaders, done );
			} catch ( e ) {
				// Propagate exception as error if not done
				if ( state < 2 ) {
					done( -1, e );
				// Simply rethrow otherwise
				} else {
					throw e;
				}
			}
		}

		// Callback for when everything is done
		function done( status, nativeStatusText, responses, headers ) {
			var isSuccess, success, error, response, modified,
				statusText = nativeStatusText;

			// Called once
			if ( state === 2 ) {
				return;
			}

			// State is "done" now
			state = 2;

			// Clear timeout if it exists
			if ( timeoutTimer ) {
				clearTimeout( timeoutTimer );
			}

			// Dereference transport for early garbage collection
			// (no matter how long the jqXHR object will be used)
			transport = undefined;

			// Cache response headers
			responseHeadersString = headers || "";

			// Set readyState
			jqXHR.readyState = status > 0 ? 4 : 0;

			// Determine if successful
			isSuccess = status >= 200 && status < 300 || status === 304;

			// Get response data
			if ( responses ) {
				response = ajaxHandleResponses( s, jqXHR, responses );
			}

			// Convert no matter what (that way responseXXX fields are always set)
			response = ajaxConvert( s, response, jqXHR, isSuccess );

			// If successful, handle type chaining
			if ( isSuccess ) {

				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
				if ( s.ifModified ) {
					modified = jqXHR.getResponseHeader("Last-Modified");
					if ( modified ) {
						jQuery.lastModified[ cacheURL ] = modified;
					}
					modified = jqXHR.getResponseHeader("etag");
					if ( modified ) {
						jQuery.etag[ cacheURL ] = modified;
					}
				}

				// if no content
				if ( status === 204 || s.type === "HEAD" ) {
					statusText = "nocontent";

				// if not modified
				} else if ( status === 304 ) {
					statusText = "notmodified";

				// If we have data, let's convert it
				} else {
					statusText = response.state;
					success = response.data;
					error = response.error;
					isSuccess = !error;
				}
			} else {
				// We extract error from statusText
				// then normalize statusText and status for non-aborts
				error = statusText;
				if ( status || !statusText ) {
					statusText = "error";
					if ( status < 0 ) {
						status = 0;
					}
				}
			}

			// Set data for the fake xhr object
			jqXHR.status = status;
			jqXHR.statusText = ( nativeStatusText || statusText ) + "";

			// Success/Error
			if ( isSuccess ) {
				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
			} else {
				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
			}

			// Status-dependent callbacks
			jqXHR.statusCode( statusCode );
			statusCode = undefined;

			if ( fireGlobals ) {
				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
					[ jqXHR, s, isSuccess ? success : error ] );
			}

			// Complete
			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );

			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
				// Handle the global AJAX counter
				if ( !( --jQuery.active ) ) {
					jQuery.event.trigger("ajaxStop");
				}
			}
		}

		return jqXHR;
	},

	getJSON: function( url, data, callback ) {
		return jQuery.get( url, data, callback, "json" );
	},

	getScript: function( url, callback ) {
		return jQuery.get( url, undefined, callback, "script" );
	}
});

jQuery.each( [ "get", "post" ], function( i, method ) {
	jQuery[ method ] = function( url, data, callback, type ) {
		// shift arguments if data argument was omitted
		if ( jQuery.isFunction( data ) ) {
			type = type || callback;
			callback = data;
			data = undefined;
		}

		return jQuery.ajax({
			url: url,
			type: method,
			dataType: type,
			data: data,
			success: callback
		});
	};
});

// Attach a bunch of functions for handling common AJAX events
jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
	jQuery.fn[ type ] = function( fn ) {
		return this.on( type, fn );
	};
});


jQuery._evalUrl = function( url ) {
	return jQuery.ajax({
		url: url,
		type: "GET",
		dataType: "script",
		async: false,
		global: false,
		"throws": true
	});
};


jQuery.fn.extend({
	wrapAll: function( html ) {
		var wrap;

		if ( jQuery.isFunction( html ) ) {
			return this.each(function( i ) {
				jQuery( this ).wrapAll( html.call(this, i) );
			});
		}

		if ( this[ 0 ] ) {

			// The elements to wrap the target around
			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );

			if ( this[ 0 ].parentNode ) {
				wrap.insertBefore( this[ 0 ] );
			}

			wrap.map(function() {
				var elem = this;

				while ( elem.firstElementChild ) {
					elem = elem.firstElementChild;
				}

				return elem;
			}).append( this );
		}

		return this;
	},

	wrapInner: function( html ) {
		if ( jQuery.isFunction( html ) ) {
			return this.each(function( i ) {
				jQuery( this ).wrapInner( html.call(this, i) );
			});
		}

		return this.each(function() {
			var self = jQuery( this ),
				contents = self.contents();

			if ( contents.length ) {
				contents.wrapAll( html );

			} else {
				self.append( html );
			}
		});
	},

	wrap: function( html ) {
		var isFunction = jQuery.isFunction( html );

		return this.each(function( i ) {
			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
		});
	},

	unwrap: function() {
		return this.parent().each(function() {
			if ( !jQuery.nodeName( this, "body" ) ) {
				jQuery( this ).replaceWith( this.childNodes );
			}
		}).end();
	}
});


jQuery.expr.filters.hidden = function( elem ) {
	// Support: Opera <= 12.12
	// Opera reports offsetWidths and offsetHeights less than zero on some elements
	return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
};
jQuery.expr.filters.visible = function( elem ) {
	return !jQuery.expr.filters.hidden( elem );
};




var r20 = /%20/g,
	rbracket = /\[\]$/,
	rCRLF = /\r?\n/g,
	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
	rsubmittable = /^(?:input|select|textarea|keygen)/i;

function buildParams( prefix, obj, traditional, add ) {
	var name;

	if ( jQuery.isArray( obj ) ) {
		// Serialize array item.
		jQuery.each( obj, function( i, v ) {
			if ( traditional || rbracket.test( prefix ) ) {
				// Treat each array item as a scalar.
				add( prefix, v );

			} else {
				// Item is non-scalar (array or object), encode its numeric index.
				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
			}
		});

	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
		// Serialize object item.
		for ( name in obj ) {
			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
		}

	} else {
		// Serialize scalar item.
		add( prefix, obj );
	}
}

// Serialize an array of form elements or a set of
// key/values into a query string
jQuery.param = function( a, traditional ) {
	var prefix,
		s = [],
		add = function( key, value ) {
			// If value is a function, invoke it and return its value
			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
		};

	// Set traditional to true for jQuery <= 1.3.2 behavior.
	if ( traditional === undefined ) {
		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
	}

	// If an array was passed in, assume that it is an array of form elements.
	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
		// Serialize the form elements
		jQuery.each( a, function() {
			add( this.name, this.value );
		});

	} else {
		// If traditional, encode the "old" way (the way 1.3.2 or older
		// did it), otherwise encode params recursively.
		for ( prefix in a ) {
			buildParams( prefix, a[ prefix ], traditional, add );
		}
	}

	// Return the resulting serialization
	return s.join( "&" ).replace( r20, "+" );
};

jQuery.fn.extend({
	serialize: function() {
		return jQuery.param( this.serializeArray() );
	},
	serializeArray: function() {
		return this.map(function() {
			// Can add propHook for "elements" to filter or add form elements
			var elements = jQuery.prop( this, "elements" );
			return elements ? jQuery.makeArray( elements ) : this;
		})
		.filter(function() {
			var type = this.type;

			// Use .is( ":disabled" ) so that fieldset[disabled] works
			return this.name && !jQuery( this ).is( ":disabled" ) &&
				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
				( this.checked || !rcheckableType.test( type ) );
		})
		.map(function( i, elem ) {
			var val = jQuery( this ).val();

			return val == null ?
				null :
				jQuery.isArray( val ) ?
					jQuery.map( val, function( val ) {
						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
					}) :
					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
		}).get();
	}
});


jQuery.ajaxSettings.xhr = function() {
	try {
		return new XMLHttpRequest();
	} catch( e ) {}
};

var xhrId = 0,
	xhrCallbacks = {},
	xhrSuccessStatus = {
		// file protocol always yields status code 0, assume 200
		0: 200,
		// Support: IE9
		// #1450: sometimes IE returns 1223 when it should be 204
		1223: 204
	},
	xhrSupported = jQuery.ajaxSettings.xhr();

// Support: IE9
// Open requests must be manually aborted on unload (#5280)
if ( window.ActiveXObject ) {
	jQuery( window ).on( "unload", function() {
		for ( var key in xhrCallbacks ) {
			xhrCallbacks[ key ]();
		}
	});
}

support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
support.ajax = xhrSupported = !!xhrSupported;

jQuery.ajaxTransport(function( options ) {
	var callback;

	// Cross domain only allowed if supported through XMLHttpRequest
	if ( support.cors || xhrSupported && !options.crossDomain ) {
		return {
			send: function( headers, complete ) {
				var i,
					xhr = options.xhr(),
					id = ++xhrId;

				xhr.open( options.type, options.url, options.async, options.username, options.password );

				// Apply custom fields if provided
				if ( options.xhrFields ) {
					for ( i in options.xhrFields ) {
						xhr[ i ] = options.xhrFields[ i ];
					}
				}

				// Override mime type if needed
				if ( options.mimeType && xhr.overrideMimeType ) {
					xhr.overrideMimeType( options.mimeType );
				}

				// X-Requested-With header
				// For cross-domain requests, seeing as conditions for a preflight are
				// akin to a jigsaw puzzle, we simply never set it to be sure.
				// (it can always be set on a per-request basis or even using ajaxSetup)
				// For same-domain requests, won't change header if already provided.
				if ( !options.crossDomain && !headers["X-Requested-With"] ) {
					headers["X-Requested-With"] = "XMLHttpRequest";
				}

				// Set headers
				for ( i in headers ) {
					xhr.setRequestHeader( i, headers[ i ] );
				}

				// Callback
				callback = function( type ) {
					return function() {
						if ( callback ) {
							delete xhrCallbacks[ id ];
							callback = xhr.onload = xhr.onerror = null;

							if ( type === "abort" ) {
								xhr.abort();
							} else if ( type === "error" ) {
								complete(
									// file: protocol always yields status 0; see #8605, #14207
									xhr.status,
									xhr.statusText
								);
							} else {
								complete(
									xhrSuccessStatus[ xhr.status ] || xhr.status,
									xhr.statusText,
									// Support: IE9
									// Accessing binary-data responseText throws an exception
									// (#11426)
									typeof xhr.responseText === "string" ? {
										text: xhr.responseText
									} : undefined,
									xhr.getAllResponseHeaders()
								);
							}
						}
					};
				};

				// Listen to events
				xhr.onload = callback();
				xhr.onerror = callback("error");

				// Create the abort callback
				callback = xhrCallbacks[ id ] = callback("abort");

				try {
					// Do send the request (this may raise an exception)
					xhr.send( options.hasContent && options.data || null );
				} catch ( e ) {
					// #14683: Only rethrow if this hasn't been notified as an error yet
					if ( callback ) {
						throw e;
					}
				}
			},

			abort: function() {
				if ( callback ) {
					callback();
				}
			}
		};
	}
});




// Install script dataType
jQuery.ajaxSetup({
	accepts: {
		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
	},
	contents: {
		script: /(?:java|ecma)script/
	},
	converters: {
		"text script": function( text ) {
			jQuery.globalEval( text );
			return text;
		}
	}
});

// Handle cache's special case and crossDomain
jQuery.ajaxPrefilter( "script", function( s ) {
	if ( s.cache === undefined ) {
		s.cache = false;
	}
	if ( s.crossDomain ) {
		s.type = "GET";
	}
});

// Bind script tag hack transport
jQuery.ajaxTransport( "script", function( s ) {
	// This transport only deals with cross domain requests
	if ( s.crossDomain ) {
		var script, callback;
		return {
			send: function( _, complete ) {
				script = jQuery("<script>").prop({
					async: true,
					charset: s.scriptCharset,
					src: s.url
				}).on(
					"load error",
					callback = function( evt ) {
						script.remove();
						callback = null;
						if ( evt ) {
							complete( evt.type === "error" ? 404 : 200, evt.type );
						}
					}
				);
				document.head.appendChild( script[ 0 ] );
			},
			abort: function() {
				if ( callback ) {
					callback();
				}
			}
		};
	}
});




var oldCallbacks = [],
	rjsonp = /(=)\?(?=&|$)|\?\?/;

// Default jsonp settings
jQuery.ajaxSetup({
	jsonp: "callback",
	jsonpCallback: function() {
		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
		this[ callback ] = true;
		return callback;
	}
});

// Detect, normalize options and install callbacks for jsonp requests
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {

	var callbackName, overwritten, responseContainer,
		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
			"url" :
			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
		);

	// Handle iff the expected data type is "jsonp" or we have a parameter to set
	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {

		// Get callback name, remembering preexisting value associated with it
		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
			s.jsonpCallback() :
			s.jsonpCallback;

		// Insert callback into url or form data
		if ( jsonProp ) {
			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
		} else if ( s.jsonp !== false ) {
			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
		}

		// Use data converter to retrieve json after script execution
		s.converters["script json"] = function() {
			if ( !responseContainer ) {
				jQuery.error( callbackName + " was not called" );
			}
			return responseContainer[ 0 ];
		};

		// force json dataType
		s.dataTypes[ 0 ] = "json";

		// Install callback
		overwritten = window[ callbackName ];
		window[ callbackName ] = function() {
			responseContainer = arguments;
		};

		// Clean-up function (fires after converters)
		jqXHR.always(function() {
			// Restore preexisting value
			window[ callbackName ] = overwritten;

			// Save back as free
			if ( s[ callbackName ] ) {
				// make sure that re-using the options doesn't screw things around
				s.jsonpCallback = originalSettings.jsonpCallback;

				// save the callback name for future use
				oldCallbacks.push( callbackName );
			}

			// Call if it was a function and we have a response
			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
				overwritten( responseContainer[ 0 ] );
			}

			responseContainer = overwritten = undefined;
		});

		// Delegate to script
		return "script";
	}
});




// data: string of html
// context (optional): If specified, the fragment will be created in this context, defaults to document
// keepScripts (optional): If true, will include scripts passed in the html string
jQuery.parseHTML = function( data, context, keepScripts ) {
	if ( !data || typeof data !== "string" ) {
		return null;
	}
	if ( typeof context === "boolean" ) {
		keepScripts = context;
		context = false;
	}
	context = context || document;

	var parsed = rsingleTag.exec( data ),
		scripts = !keepScripts && [];

	// Single tag
	if ( parsed ) {
		return [ context.createElement( parsed[1] ) ];
	}

	parsed = jQuery.buildFragment( [ data ], context, scripts );

	if ( scripts && scripts.length ) {
		jQuery( scripts ).remove();
	}

	return jQuery.merge( [], parsed.childNodes );
};


// Keep a copy of the old load method
var _load = jQuery.fn.load;

/**
 * Load a url into a page
 */
jQuery.fn.load = function( url, params, callback ) {
	if ( typeof url !== "string" && _load ) {
		return _load.apply( this, arguments );
	}

	var selector, type, response,
		self = this,
		off = url.indexOf(" ");

	if ( off >= 0 ) {
		selector = jQuery.trim( url.slice( off ) );
		url = url.slice( 0, off );
	}

	// If it's a function
	if ( jQuery.isFunction( params ) ) {

		// We assume that it's the callback
		callback = params;
		params = undefined;

	// Otherwise, build a param string
	} else if ( params && typeof params === "object" ) {
		type = "POST";
	}

	// If we have elements to modify, make the request
	if ( self.length > 0 ) {
		jQuery.ajax({
			url: url,

			// if "type" variable is undefined, then "GET" method will be used
			type: type,
			dataType: "html",
			data: params
		}).done(function( responseText ) {

			// Save response for use in complete callback
			response = arguments;

			self.html( selector ?

				// If a selector was specified, locate the right elements in a dummy div
				// Exclude scripts to avoid IE 'Permission Denied' errors
				jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :

				// Otherwise use the full result
				responseText );

		}).complete( callback && function( jqXHR, status ) {
			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
		});
	}

	return this;
};




jQuery.expr.filters.animated = function( elem ) {
	return jQuery.grep(jQuery.timers, function( fn ) {
		return elem === fn.elem;
	}).length;
};




var docElem = window.document.documentElement;

/**
 * Gets a window from an element
 */
function getWindow( elem ) {
	return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
}

jQuery.offset = {
	setOffset: function( elem, options, i ) {
		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
			position = jQuery.css( elem, "position" ),
			curElem = jQuery( elem ),
			props = {};

		// Set position first, in-case top/left are set even on static elem
		if ( position === "static" ) {
			elem.style.position = "relative";
		}

		curOffset = curElem.offset();
		curCSSTop = jQuery.css( elem, "top" );
		curCSSLeft = jQuery.css( elem, "left" );
		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
			( curCSSTop + curCSSLeft ).indexOf("auto") > -1;

		// Need to be able to calculate position if either top or left is auto and position is either absolute or fixed
		if ( calculatePosition ) {
			curPosition = curElem.position();
			curTop = curPosition.top;
			curLeft = curPosition.left;

		} else {
			curTop = parseFloat( curCSSTop ) || 0;
			curLeft = parseFloat( curCSSLeft ) || 0;
		}

		if ( jQuery.isFunction( options ) ) {
			options = options.call( elem, i, curOffset );
		}

		if ( options.top != null ) {
			props.top = ( options.top - curOffset.top ) + curTop;
		}
		if ( options.left != null ) {
			props.left = ( options.left - curOffset.left ) + curLeft;
		}

		if ( "using" in options ) {
			options.using.call( elem, props );

		} else {
			curElem.css( props );
		}
	}
};

jQuery.fn.extend({
	offset: function( options ) {
		if ( arguments.length ) {
			return options === undefined ?
				this :
				this.each(function( i ) {
					jQuery.offset.setOffset( this, options, i );
				});
		}

		var docElem, win,
			elem = this[ 0 ],
			box = { top: 0, left: 0 },
			doc = elem && elem.ownerDocument;

		if ( !doc ) {
			return;
		}

		docElem = doc.documentElement;

		// Make sure it's not a disconnected DOM node
		if ( !jQuery.contains( docElem, elem ) ) {
			return box;
		}

		// If we don't have gBCR, just use 0,0 rather than error
		// BlackBerry 5, iOS 3 (original iPhone)
		if ( typeof elem.getBoundingClientRect !== strundefined ) {
			box = elem.getBoundingClientRect();
		}
		win = getWindow( doc );
		return {
			top: box.top + win.pageYOffset - docElem.clientTop,
			left: box.left + win.pageXOffset - docElem.clientLeft
		};
	},

	position: function() {
		if ( !this[ 0 ] ) {
			return;
		}

		var offsetParent, offset,
			elem = this[ 0 ],
			parentOffset = { top: 0, left: 0 };

		// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
		if ( jQuery.css( elem, "position" ) === "fixed" ) {
			// We assume that getBoundingClientRect is available when computed position is fixed
			offset = elem.getBoundingClientRect();

		} else {
			// Get *real* offsetParent
			offsetParent = this.offsetParent();

			// Get correct offsets
			offset = this.offset();
			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
				parentOffset = offsetParent.offset();
			}

			// Add offsetParent borders
			parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
		}

		// Subtract parent offsets and element margins
		return {
			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
		};
	},

	offsetParent: function() {
		return this.map(function() {
			var offsetParent = this.offsetParent || docElem;

			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
				offsetParent = offsetParent.offsetParent;
			}

			return offsetParent || docElem;
		});
	}
});

// Create scrollLeft and scrollTop methods
jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
	var top = "pageYOffset" === prop;

	jQuery.fn[ method ] = function( val ) {
		return access( this, function( elem, method, val ) {
			var win = getWindow( elem );

			if ( val === undefined ) {
				return win ? win[ prop ] : elem[ method ];
			}

			if ( win ) {
				win.scrollTo(
					!top ? val : window.pageXOffset,
					top ? val : window.pageYOffset
				);

			} else {
				elem[ method ] = val;
			}
		}, method, val, arguments.length, null );
	};
});

// Add the top/left cssHooks using jQuery.fn.position
// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
// getComputedStyle returns percent when specified for top/left/bottom/right
// rather than make the css module depend on the offset module, we just check for it here
jQuery.each( [ "top", "left" ], function( i, prop ) {
	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
		function( elem, computed ) {
			if ( computed ) {
				computed = curCSS( elem, prop );
				// if curCSS returns percentage, fallback to offset
				return rnumnonpx.test( computed ) ?
					jQuery( elem ).position()[ prop ] + "px" :
					computed;
			}
		}
	);
});


// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
		// margin is only for outerHeight, outerWidth
		jQuery.fn[ funcName ] = function( margin, value ) {
			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );

			return access( this, function( elem, type, value ) {
				var doc;

				if ( jQuery.isWindow( elem ) ) {
					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
					// isn't a whole lot we can do. See pull request at this URL for discussion:
					// https://github.com/jquery/jquery/pull/764
					return elem.document.documentElement[ "client" + name ];
				}

				// Get document width or height
				if ( elem.nodeType === 9 ) {
					doc = elem.documentElement;

					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
					// whichever is greatest
					return Math.max(
						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
						elem.body[ "offset" + name ], doc[ "offset" + name ],
						doc[ "client" + name ]
					);
				}

				return value === undefined ?
					// Get width or height on the element, requesting but not forcing parseFloat
					jQuery.css( elem, type, extra ) :

					// Set width or height on the element
					jQuery.style( elem, type, value, extra );
			}, type, chainable ? margin : undefined, chainable, null );
		};
	});
});


// The number of elements contained in the matched element set
jQuery.fn.size = function() {
	return this.length;
};

jQuery.fn.andSelf = jQuery.fn.addBack;




// Register as a named AMD module, since jQuery can be concatenated with other
// files that may use define, but not via a proper concatenation script that
// understands anonymous AMD modules. A named AMD is safest and most robust
// way to register. Lowercase jquery is used because AMD module names are
// derived from file names, and jQuery is normally delivered in a lowercase
// file name. Do this after creating the global so that if an AMD module wants
// to call noConflict to hide this version of jQuery, it will work.

// Note that for maximum portability, libraries that are not jQuery should
// declare themselves as anonymous modules, and avoid setting a global if an
// AMD loader is present. jQuery is a special case. For more information, see
// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon

if ( typeof define === "function" && define.amd ) {
	define( "jquery", [], function() {
		return jQuery;
	});
}




var
	// Map over jQuery in case of overwrite
	_jQuery = window.jQuery,

	// Map over the $ in case of overwrite
	_$ = window.$;

jQuery.noConflict = function( deep ) {
	if ( window.$ === jQuery ) {
		window.$ = _$;
	}

	if ( deep && window.jQuery === jQuery ) {
		window.jQuery = _jQuery;
	}

	return jQuery;
};

// Expose jQuery and $ identifiers, even in
// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
if ( typeof noGlobal === strundefined ) {
	window.jQuery = window.$ = jQuery;
}




return jQuery;

}));

(function() {
  window.Authy = {};

  if (document.getElementsByClassName == null) {
    document.getElementsByClassName = function(className, parentElement) {
      var child, children, elements, i, length;
      children = (parentElement || document.body).getElementsByTagName("*");
      elements = [];
      child = void 0;
      i = 0;
      length = children.length;
      while (i < length) {
        child = children[i];
        if ((" " + child.className + " ").indexOf(" " + className + " ") !== -1) {
          elements.push(child);
        }
        i++;
      }
      return elements;
    };
    HTMLDivElement.prototype.getElementsByClassName = function(className) {
      return document.getElementsByClassName(className, this);
    };
  }

  window.Authy.UI = function() {
    var absolutePosFor, buildItem, countriesList, disableAutocompleteAuthyToken, findAndSetupCountries, getKeyCode, hideAutocompleteList, processKey13, processKey38, processKey40, self, setActive, setCountryField, setupAuthyTokenValidation, setupCellphoneValidation, setupCountriesDropdown, setupCountriesDropdownPosition, setupEvents, setupTooltip, setupTooltipPosition, tooltipMessage, tooltipTitle;
    self = this;
    tooltipTitle = "Authy Help Tooltip";
    tooltipMessage = "This is a help tooltip for your users. You can set the message by doing: authyUI.setTooltip(\"title\", \"message\");";
    countriesList = [
      {
        "country": "United States of America (+1)",
        "code": "1"
      }, {
        "country": "Canada (+1)",
        "code": "1"
      }, {
        "country": "Russia (+7)",
        "code": "7"
      }, {
        "country": "Kazakhstan (+7)",
        "code": "7"
      }, {
        "country": "Egypt (+20)",
        "code": "20"
      }, {
        "country": "South Africa (+27)",
        "code": "27"
      }, {
        "country": "Greece (+30)",
        "code": "30"
      }, {
        "country": "Netherlands (+31)",
        "code": "31"
      }, {
        "country": "Belgium (+32)",
        "code": "32"
      }, {
        "country": "France (+33)",
        "code": "33"
      }, {
        "country": "Spain (+34)",
        "code": "34"
      }, {
        "country": "Hungary (+36)",
        "code": "36"
      }, {
        "country": "Italy (+39)",
        "code": "39"
      }, {
        "country": "Romania (+40)",
        "code": "40"
      }, {
        "country": "Switzerland (+41)",
        "code": "41"
      }, {
        "country": "Austria (+43)",
        "code": "43"
      }, {
        "country": "United Kingdom (+44)",
        "code": "44"
      }, {
        "country": "Guernsey (+44)",
        "code": "44"
      }, {
        "country": "Isle of Man (+44)",
        "code": "44"
      }, {
        "country": "Jersey (+44)",
        "code": "44"
      }, {
        "country": "Denmark (+45)",
        "code": "45"
      }, {
        "country": "Sweden (+46)",
        "code": "46"
      }, {
        "country": "Norway (+47)",
        "code": "47"
      }, {
        "country": "Poland (+48)",
        "code": "48"
      }, {
        "country": "Germany (+49)",
        "code": "49"
      }, {
        "country": "Peru (+51)",
        "code": "51"
      }, {
        "country": "Mexico (+52)",
        "code": "52"
      }, {
        "country": "Cuba (+53)",
        "code": "53"
      }, {
        "country": "Argentina (+54)",
        "code": "54"
      }, {
        "country": "Brazil (+55)",
        "code": "55"
      }, {
        "country": "Chile (+56)",
        "code": "56"
      }, {
        "country": "Colombia (+57)",
        "code": "57"
      }, {
        "country": "Venezuela (+58)",
        "code": "58"
      }, {
        "country": "Malaysia (+60)",
        "code": "60"
      }, {
        "country": "Australia (+61)",
        "code": "61"
      }, {
        "country": "Indonesia (+62)",
        "code": "62"
      }, {
        "country": "Philippines (+63)",
        "code": "63"
      }, {
        "country": "New Zealand (+64)",
        "code": "64"
      }, {
        "country": "Singapore (+65)",
        "code": "65"
      }, {
        "country": "Thailand (+66)",
        "code": "66"
      }, {
        "country": "Japan (+81)",
        "code": "81"
      }, {
        "country": "Korea (+South) (+82)",
        "code": "82"
      }, {
        "country": "Vietnam (+84)",
        "code": "84"
      }, {
        "country": "China (+86)",
        "code": "86"
      }, {
        "country": "Turkey (+90)",
        "code": "90"
      }, {
        "country": "India (+91)",
        "code": "91"
      }, {
        "country": "Pakistan (+92)",
        "code": "92"
      }, {
        "country": "Afghanistan (+93)",
        "code": "93"
      }, {
        "country": "Sri Lanka (+94)",
        "code": "94"
      }, {
        "country": "Myanmar (+95)",
        "code": "95"
      }, {
        "country": "Iran (+98)",
        "code": "98"
      }, {
        "country": "Morocco (+212)",
        "code": "212"
      }, {
        "country": "Algeria (+213)",
        "code": "213"
      }, {
        "country": "Tunisia (+216)",
        "code": "216"
      }, {
        "country": "Libya (+218)",
        "code": "218"
      }, {
        "country": "Gambia (+220)",
        "code": "220"
      }, {
        "country": "Senegal (+221)",
        "code": "221"
      }, {
        "country": "Mauritania (+222)",
        "code": "222"
      }, {
        "country": "Mali Republic (+223)",
        "code": "223"
      }, {
        "country": "Guinea (+224)",
        "code": "224"
      }, {
        "country": "Ivory Coast (+225)",
        "code": "225"
      }, {
        "country": "Burkina Faso (+226)",
        "code": "226"
      }, {
        "country": "Niger (+227)",
        "code": "227"
      }, {
        "country": "Togo (+228)",
        "code": "228"
      }, {
        "country": "Benin (+229)",
        "code": "229"
      }, {
        "country": "Mauritius (+230)",
        "code": "230"
      }, {
        "country": "Liberia (+231)",
        "code": "231"
      }, {
        "country": "Sierra Leone (+232)",
        "code": "232"
      }, {
        "country": "Ghana (+233)",
        "code": "233"
      }, {
        "country": "Nigeria (+234)",
        "code": "234"
      }, {
        "country": "Chad (+235)",
        "code": "235"
      }, {
        "country": "Central African Republic (+236)",
        "code": "236"
      }, {
        "country": "Cameroon (+237)",
        "code": "237"
      }, {
        "country": "Cape Verde Islands (+238)",
        "code": "238"
      }, {
        "country": "Sao Tome and Principe (+239)",
        "code": "239"
      }, {
        "country": "Gabon (+241)",
        "code": "241"
      }, {
        "country": "Congo, Democratic Republ (+243)",
        "code": "243"
      }, {
        "country": "Angola (+244)",
        "code": "244"
      }, {
        "country": "Guinea-Bissau (+245)",
        "code": "245"
      }, {
        "country": "Seychelles (+248)",
        "code": "248"
      }, {
        "country": "Sudan (+249)",
        "code": "249"
      }, {
        "country": "Rwanda (+250)",
        "code": "250"
      }, {
        "country": "Ethiopia (+251)",
        "code": "251"
      }, {
        "country": "Somalia (+252)",
        "code": "252"
      }, {
        "country": "Djibouti (+253)",
        "code": "253"
      }, {
        "country": "Kenya (+254)",
        "code": "254"
      }, {
        "country": "Tanzania (+255)",
        "code": "255"
      }, {
        "country": "Uganda (+256)",
        "code": "256"
      }, {
        "country": "Burundi (+257)",
        "code": "257"
      }, {
        "country": "Mozambique (+258)",
        "code": "258"
      }, {
        "country": "Zambia (+260)",
        "code": "260"
      }, {
        "country": "Madagascar (+261)",
        "code": "261"
      }, {
        "country": "Reunion (+262)",
        "code": "262"
      }, {
        "country": "Zimbabwe (+263)",
        "code": "263"
      }, {
        "country": "Namibia (+264)",
        "code": "264"
      }, {
        "country": "Malawi (+265)",
        "code": "265"
      }, {
        "country": "Lesotho (+266)",
        "code": "266"
      }, {
        "country": "Botswana (+267)",
        "code": "267"
      }, {
        "country": "Swaziland (+268)",
        "code": "268"
      }, {
        "country": "Mayotte Island (+269)",
        "code": "269"
      }, {
        "country": "Aruba (+297)",
        "code": "297"
      }, {
        "country": "Faroe Islands (+298)",
        "code": "298"
      }, {
        "country": "Greenland (+299)",
        "code": "299"
      }, {
        "country": "Gibraltar (+350)",
        "code": "350"
      }, {
        "country": "Portugal (+351)",
        "code": "351"
      }, {
        "country": "Luxembourg (+352)",
        "code": "352"
      }, {
        "country": "Ireland (+353)",
        "code": "353"
      }, {
        "country": "Iceland (+354)",
        "code": "354"
      }, {
        "country": "Albania (+355)",
        "code": "355"
      }, {
        "country": "Malta (+356)",
        "code": "356"
      }, {
        "country": "Cyprus (+357)",
        "code": "357"
      }, {
        "country": "Finland (+358)",
        "code": "358"
      }, {
        "country": "Bulgaria (+359)",
        "code": "359"
      }, {
        "country": "Lithuania (+370)",
        "code": "370"
      }, {
        "country": "Latvia (+371)",
        "code": "371"
      }, {
        "country": "Estonia (+372)",
        "code": "372"
      }, {
        "country": "Moldova (+373)",
        "code": "373"
      }, {
        "country": "Armenia (+374)",
        "code": "374"
      }, {
        "country": "Belarus (+375)",
        "code": "375"
      }, {
        "country": "Andorra (+376)",
        "code": "376"
      }, {
        "country": "Monaco (+377)",
        "code": "377"
      }, {
        "country": "San Marino (+378)",
        "code": "378"
      }, {
        "country": "Ukraine (+380)",
        "code": "380"
      }, {
        "country": "Serbia (+381)",
        "code": "381"
      }, {
        "country": "Montenegro (+382)",
        "code": "382"
      }, {
        "country": "Croatia (+385)",
        "code": "385"
      }, {
        "country": "Slovenia (+386)",
        "code": "386"
      }, {
        "country": "Bosnia-Herzegovina (+387)",
        "code": "387"
      }, {
        "country": "Macedonia (+389)",
        "code": "389"
      }, {
        "country": "Czech Republic (+420)",
        "code": "420"
      }, {
        "country": "Slovakia (+421)",
        "code": "421"
      }, {
        "country": "Liechtenstein (+423)",
        "code": "423"
      }, {
        "country": "Falkland Islands (+500)",
        "code": "500"
      }, {
        "country": "Belize (+501)",
        "code": "501"
      }, {
        "country": "Guatemala (+502)",
        "code": "502"
      }, {
        "country": "El Salvador (+503)",
        "code": "503"
      }, {
        "country": "Honduras (+504)",
        "code": "504"
      }, {
        "country": "Nicaragua (+505)",
        "code": "505"
      }, {
        "country": "Costa Rica (+506)",
        "code": "506"
      }, {
        "country": "Panama (+507)",
        "code": "507"
      }, {
        "country": "Haiti (+509)",
        "code": "509"
      }, {
        "country": "Guadeloupe (+590)",
        "code": "590"
      }, {
        "country": "Bolivia (+591)",
        "code": "591"
      }, {
        "country": "Guyana (+592)",
        "code": "592"
      }, {
        "country": "Ecuador (+593)",
        "code": "593"
      }, {
        "country": "French Guiana (+594)",
        "code": "594"
      }, {
        "country": "Paraguay (+595)",
        "code": "595"
      }, {
        "country": "Martinique (+596)",
        "code": "596"
      }, {
        "country": "Suriname (+597)",
        "code": "597"
      }, {
        "country": "Uruguay (+598)",
        "code": "598"
      }, {
        "country": "Netherlands Antilles (+599)",
        "code": "599"
      }, {
        "country": "Timor-Leste (+670)",
        "code": "670"
      }, {
        "country": "Guam (+671)",
        "code": "671"
      }, {
        "country": "Brunei (+673)",
        "code": "673"
      }, {
        "country": "Nauru (+674)",
        "code": "674"
      }, {
        "country": "Papua New Guinea (+675)",
        "code": "675"
      }, {
        "country": "Tonga (+676)",
        "code": "676"
      }, {
        "country": "Solomon Islands (+677)",
        "code": "677"
      }, {
        "country": "Vanuatu (+678)",
        "code": "678"
      }, {
        "country": "Fiji Islands (+679)",
        "code": "679"
      }, {
        "country": "Cook Islands (+682)",
        "code": "682"
      }, {
        "country": "Samoa (+685)",
        "code": "685"
      }, {
        "country": "New Caledonia (+687)",
        "code": "687"
      }, {
        "country": "French Polynesia (+689)",
        "code": "689"
      }, {
        "country": "Korea (+North) (+850)",
        "code": "850"
      }, {
        "country": "HongKong (+852)",
        "code": "852"
      }, {
        "country": "Macau (+853)",
        "code": "853"
      }, {
        "country": "Cambodia (+855)",
        "code": "855"
      }, {
        "country": "Laos (+856)",
        "code": "856"
      }, {
        "country": "Bangladesh (+880)",
        "code": "880"
      }, {
        "country": "International (+882)",
        "code": "882"
      }, {
        "country": "Taiwan (+886)",
        "code": "886"
      }, {
        "country": "Maldives (+960)",
        "code": "960"
      }, {
        "country": "Lebanon (+961)",
        "code": "961"
      }, {
        "country": "Jordan (+962)",
        "code": "962"
      }, {
        "country": "Syria (+963)",
        "code": "963"
      }, {
        "country": "Iraq (+964)",
        "code": "964"
      }, {
        "country": "Kuwait (+965)",
        "code": "965"
      }, {
        "country": "Saudi Arabia (+966)",
        "code": "966"
      }, {
        "country": "Yemen (+967)",
        "code": "967"
      }, {
        "country": "Oman (+968)",
        "code": "968"
      }, {
        "country": "Palestine (+970)",
        "code": "970"
      }, {
        "country": "United Arab Emirates (+971)",
        "code": "971"
      }, {
        "country": "Israel (+972)",
        "code": "972"
      }, {
        "country": "Bahrain (+973)",
        "code": "973"
      }, {
        "country": "Qatar (+974)",
        "code": "974"
      }, {
        "country": "Bhutan (+975)",
        "code": "975"
      }, {
        "country": "Mongolia (+976)",
        "code": "976"
      }, {
        "country": "Nepal (+977)",
        "code": "977"
      }, {
        "country": "Tajikistan (+992)",
        "code": "992"
      }, {
        "country": "Turkmenistan (+993)",
        "code": "993"
      }, {
        "country": "Azerbaijan (+994)",
        "code": "994"
      }, {
        "country": "Georgia (+995)",
        "code": "995"
      }, {
        "country": "Kyrgyzstan (+996)",
        "code": "996"
      }, {
        "country": "Uzbekistan (+998)",
        "code": "998"
      }, {
        "country": "Bahamas (+1242)",
        "code": "1242"
      }, {
        "country": "Barbados (+1246)",
        "code": "1246"
      }, {
        "country": "Anguilla (+1264)",
        "code": "1264"
      }, {
        "country": "Antigua and Barbuda (+1268)",
        "code": "1268"
      }, {
        "country": "Virgin Islands, British (+1284)",
        "code": "1284"
      }, {
        "country": "Cayman Islands (+1345)",
        "code": "1345"
      }, {
        "country": "Bermuda (+1441)",
        "code": "1441"
      }, {
        "country": "Grenada (+1473)",
        "code": "1473"
      }, {
        "country": "Turks and Caicos Islands (+1649)",
        "code": "1649"
      }, {
        "country": "Montserrat (+1664)",
        "code": "1664"
      }, {
        "country": "Saint Lucia (+1758)",
        "code": "1758"
      }, {
        "country": "Dominica (+1767)",
        "code": "1767"
      }, {
        "country": "St. Vincent and The Gren (+1784)",
        "code": "1784"
      }, {
        "country": "Puerto Rico (+1787)",
        "code": "1787"
      }, {
        "country": "Dominican Republic (+1809)",
        "code": "1809"
      }, {
        "country": "Dominican Republic2 (+1829)",
        "code": "1829"
      }, {
        "country": "Dominican Republic3 (+1849)",
        "code": "1849"
      }, {
        "country": "Trinidad and Tobago (+1868)",
        "code": "1868"
      }, {
        "country": "Saint Kitts and Nevis (+1869)",
        "code": "1869"
      }, {
        "country": "Jamaica (+1876)",
        "code": "1876"
      }, {
        "country": "Congo (+2420)",
        "code": "2420"
      }
    ];
    setupCellphoneValidation = function() {
      var cellPhone;
      cellPhone = document.getElementById("authy-cellphone");
      if (!cellPhone) {
        return;
      }
      cellPhone.onblur = function() {
        if (cellPhone.value !== "" && cellPhone.value.match(/^([0-9][0-9][0-9])\W*([0-9][0-9]{2})\W*([0-9]{0,5})$/)) {
          return cellPhone.style.backgroundColor = "white";
        } else {
          return cellPhone.style.backgroundColor = "#F2DEDE";
        }
      };
    };
    setupAuthyTokenValidation = function() {
      var token;
      token = document.getElementById("authy-token");
      if (!token) {
        return;
      }
      token.onblur = function() {
        if (token.value !== "" && token.value.match(/^\d+$/)) {
          return token.style.backgroundColor = "white";
        } else {
          return token.style.backgroundColor = "#F2DEDE";
        }
      };
    };
    disableAutocompleteAuthyToken = function() {
      var token;
      token = document.getElementById("authy-token");
      if (!token) {
        return;
      }
      token.setAttribute("autocomplete", "off");
    };
    setupTooltip = function() {
      var authy_help, tooltip;
      authy_help = document.getElementById("authy-help");
      if (!authy_help) {
        return;
      }
      tooltip = document.createElement("div");
      tooltip.setAttribute("id", "authy-tooltip");
      tooltip.innerHTML = "<a id=\"authy-tooltip-close\"></a><h3 class=\"tooltip-title\">" + tooltipTitle + "</h3><p class=\"tooltip-content\">" + tooltipMessage + "</p>";
      document.body.appendChild(tooltip);
      document.getElementById("authy-help").onclick = function() {
        tooltip = document.getElementById("authy-tooltip");
        setupTooltipPosition(this, tooltip);
        return tooltip.style.display = "block";
      };
      document.getElementById("authy-tooltip-close").onclick = function() {
        return document.getElementById("authy-tooltip").style.display = "none";
      };
      setupTooltipPosition(authy_help, tooltip);
    };
    setupTooltipPosition = function(helpLink, tooltip) {
      var pos, tooltipLeft, tooltipTop;
      pos = absolutePosFor(helpLink);
      tooltipTop = pos[0];
      tooltipLeft = pos[1] + helpLink.offsetWidth + 5;
      return tooltip.setAttribute("style", "top:" + tooltipTop + "px;left:" + tooltipLeft + "px;");
    };
    processKey40 = function(authyElements) {
      var activeElement, caId, countriesArr, i, li, _i, _len;
      countriesArr = authyElements.dropdown.getElementsByTagName("li");
      i = 0;
      for (_i = 0, _len = countriesArr.length; _i < _len; _i++) {
        li = countriesArr[_i];
        if (li.className === "active" && countriesArr.length > (i + 1)) {
          activeElement = countriesArr[i + 1];
          li.className = "";
          setActive(authyElements.dropdown, activeElement);
          self.autocomplete(authyElements, activeElement, false);
          break;
        }
        i++;
      }
      return false;
    };
    processKey38 = function(authyElements) {
      var activeElement, caId, countriesArr, i;
      countriesArr = authyElements.dropdown.getElementsByTagName("li");
      i = countriesArr.length - 1;
      while (i >= 0) {
        if (authyElements.dropdown.getElementsByTagName("li")[i].className === "active") {
          authyElements.dropdown.getElementsByTagName("li")[i].className = "";
          activeElement = null;
          if (i === 0) {
            activeElement = authyElements.dropdown.getElementsByTagName("li")[countriesArr.length - 1];
          } else {
            activeElement = authyElements.dropdown.getElementsByTagName("li")[i - 1];
          }
          setActive(authyElements.dropdown, activeElement);
          self.autocomplete(authyElements, activeElement, false);
          return false;
        }
        i--;
      }
      document.getElementById(caId).getElementsByTagName("li")[0].setAttribute("class", "active");
    };
    
    processKey13 = function(authyElements) {
      var obj;
      obj = authyElements.dropdown.getElementsByClassName("active")[0];
      self.autocomplete(authyElements, obj, true);
      return false;
    };
    
    setActive = function(dropdown, liElement) {
      var li, liElements, _i, _len;
      liElements = dropdown.getElementsByTagName("li");
      for (_i = 0, _len = liElements.length; _i < _len; _i++) {
        li = liElements[_i];
        li.className = "";
      }
      return liElement.className = "active";
    };
    
    setupEvents = function(authyElements) {
      authyElements.input.onblur = function(event) {
        return processKey13(authyElements);
      };
      
      authyElements.input.onfocus = function() {
        setupCountriesDropdownPosition(authyElements);
        authyElements.dropdown.style.display = "block";
      };
      
      authyElements.input.onkeyup = function(event) {
        var keyID;
        authyElements.dropdown.style.display = "block";
        keyID = getKeyCode(event);
        switch (keyID) {
          case 13:
            processKey13(authyElements);
            return false;
          case 40:
            if (processKey40(authyElements) === false) {
              return false;
            }
            break;
          case 38:
            if (processKey38(authyElements) === false) {
              return false;
            }
        }
        return self.searchItem(authyElements);
      };
       authyElements.input.onkeypress = function(event) {
        if (getKeyCode(event) === 13) {
          processKey13(authyElements);
          return false;
        }
      };
       authyElements.dropdown.onclick = function(e) {
        if (e && e.stopPropagation) {
          authyElements.dropdown.style.display = "none";
          return e.stopPropagation();
        } else {
          e = window.event;
          return e.cancelBubble = true;
        }
      };
      authyElements.input.onclick = function(e) {
        if (e && e.stopPropagation) {
          e.stopPropagation();
          authyElements.input.focus();
          return authyElements.input.select();
        } else {
          e = window.event;
          return e.cancelBubble = true;
        }
      };
      return document.onclick = function() {
        authyElements.dropdown.style.display = "none";
      };
    };

    buildItem = function(dropdown, classActive, country) {
      var cc, flag, li, name;
      
      cc = country.country.substring(0, 2).toLowerCase() + country.code;
      li = document.createElement("li");
      li.setAttribute("class", classActive);
      li.setAttribute("rel", country.code);
      li.setAttribute("data-name", country.country);
      li.onmouseover = function(event) {
        return setActive(dropdown, li);
      };
      flag = document.createElement("span");
      flag.setAttribute("class", "aflag flag-" + cc);
      li.appendChild(flag);
      name = document.createElement("span");
      name.innerHTML = country.country;
      li.appendChild(name);
      return li;
    };
    
    absolutePosFor = function(element) {
      var absLeft, absTop;
      absTop = 0;
      absLeft = 0;
      while (element) {
        absTop += element.offsetTop;
        absLeft += element.offsetLeft;
        element = element.offsetParent;
      }
      return [absTop, absLeft];
    };
    
    setupCountriesDropdown = function(countryCode) {
      var buf, classActive, classList, countries, countriesAutocompleteList, countriesDropdown, countriesInput, countriesInputType, countryCodeValue, i, name, placeholder;
      var authyElements;
      
      if (!countryCode) {
        return;
      }

      //delete the existing ones if there are any
      if (countryCode.parentNode.getElementsByClassName("countries-input").length) {
        var input    = countryCode.parentNode.getElementsByClassName("countries-input")[0];
        var dropdown = countryCode.parentNode.getElementsByClassName("countries-autocomplete")[0];
        countryCode.parentNode.removeChild(input);
        countryCode.parentNode.removeChild(dropdown);
      }
    
      authyElements = {
        code     : countryCode,
        input    : document.createElement("input"),
        dropdown : document.createElement("div"),
      };

      classActive = "";
      countriesAutocompleteList = document.createElement("ul");
      i = 0;
      while (i < countriesList.length) {
        classActive = (i === 0 ? "active" : "");
        countriesAutocompleteList.appendChild(buildItem(authyElements.dropdown, classActive, countriesList[i]));
        i++;
      }

      classList = authyElements.code.getAttribute('class');
      classList = classList.split(" ");
      var classes = "";
      classList.forEach(function(c){
        if (c === 'authy-countries') return;
        if (c.indexOf("ng-") !== 0) classes += c + " ";
      });
      
      authyElements.input.setAttribute("class", classes + ' countries-input');
      authyElements.input.setAttribute("type", "text");
      authyElements.input.setAttribute("autocomplete", "off");
            
      authyElements.code.style.display = "none";
      authyElements.dropdown.innerHTML = "";
      authyElements.dropdown.appendChild(countriesAutocompleteList);

      countriesInputType = authyElements.code.getAttribute("data-show-as");
      if (/^number/i.exec(countriesInputType)) {
        authyElements.input.setAttribute("data-show-as", "number");
      }
      
      authyElements.code.parentNode.appendChild(authyElements.input);
      authyElements.code.parentNode.appendChild(authyElements.dropdown);
      authyElements.dropdown.setAttribute("class", "countries-autocomplete");
      setupCountriesDropdownPosition(authyElements);
      setupEvents(authyElements);
    };
    setupCountriesDropdownPosition = function(authyElements) {
      var pos, width;
      pos = absolutePosFor(authyElements.input);
      width = authyElements.input.offsetWidth;
      if (width < 220) {
        width = 220;
      }
      return authyElements.dropdown.setAttribute("style", "width: " + width + "px;");
    };
    
    findAndSetupCountries = function() {
      var authyCountries, countries, i;
      authyCountries = document.getElementById("authy-countries");
      if (authyCountries) {
        setupCountriesDropdown(authyCountries);
      }
      countries = document.getElementsByClassName("authy-countries");
      i = 0;
      while (i < countries.length) {
        setupCountriesDropdown(countries[i]);
        i++;
      }
    };
    
    setCountryField = function(countryCode) {
      var country, field, _i, _len, _results;
      
      if (!countryCode) {
        field = document.getElementById("authy-countries");    
        if (!field) {
          return;
        }
        countryCode = field.value;
      }
      
      if (countryCode !== '') {
        _results = [];
        for (_i = 0, _len = countriesList.length; _i < _len; _i++) {
          country = countriesList[_i];
          if (country.code === countryCode) {
            inputs = document.getElementsByClassName("authy-countries");

            for (var i=0; i < inputs.length; i++) {
              authyElements = {
                code     : inputs[i],
                input    : inputs[i].parentNode.getElementsByClassName("countries-input")[0],
                dropdown : inputs[i].parentNode.getElementsByClassName("countries-autocomplete")[0]              
              }
            
            self.autocomplete(authyElements, buildItem(authyElements.dropdown, 'active', country), true);
            }
            
            break;
          } else {
            _results.push(void 0);
          }
        }
        return _results;
      }
    };
    getKeyCode = function(event) {
      var keyCode;
      if (event && event.which) {
        keyCode = event.which;
      } else if (window.event) {
        keyCode = window.event.keyCode;
      }
      return keyCode;
    };
    this.init = function(countryCode) {
      setupAuthyTokenValidation();
      disableAutocompleteAuthyToken();
      setupTooltip();
      findAndSetupCountries();
      setCountryField(countryCode);
      return setupCellphoneValidation();
    };
    this.searchItem = function(authyElements) {
      var classActive, countryItem, countryWords, countriesAutocompleteList, cw, dropdownMenu, firstCountryCodeFound, i, matches, reg, str;
      classActive = "active";
      str = authyElements.input.value;
      countriesAutocompleteList = document.createElement("ul");
      firstCountryCodeFound = null;
      matches = false;
      str = str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
      reg = new RegExp("^" + str, "i");
      i = 0;
      while (i < countriesList.length) {
        countryItem = countriesList[i];
        countryWords = countryItem.country.toLowerCase().split(/\s+/);
        cw = 0;
        while (cw < countryWords.length) {
          if ((countryWords[cw].length > 2 && countryWords[cw].match(reg)) || ("" + countryItem.code).match(reg)) {
            countriesAutocompleteList.appendChild(buildItem(authyElements.dropdown, classActive, countryItem));
            classActive = "";
            matches = true;
            if (firstCountryCodeFound == null) {
              firstCountryCodeFound = countryItem.code;
            }
            break;
          }
          cw++;
        }
        i++;
      }
      if (matches) {
        authyElements.dropdown.innerHTML = "";
        authyElements.dropdown.appendChild(countriesAutocompleteList);
        changeValue(authyElements.code, firstCountryCodeFound);
        return;
      }
    };
    
    function changeValue (input, value) {
      input.value = value;
      var event = new Event('change');
      input.dispatchEvent(event);
    }
    
    this.autocomplete = function(authyElements, obj, hideList) {
      var countryCode;
      countryCode = obj.getAttribute("rel");
      if (authyElements.input.getAttribute("data-show-as") === "number") {
        authyElements.input.value = "+" + countryCode;
      } else {
        authyElements.input.value = obj.getAttribute("data-name");
      }
      
      changeValue (authyElements.code, countryCode);
      if (hideList) {
        authyElements.dropdown.style.display = "none";
      }
    };

    this.setTooltip = function(title, msg) {
      var tooltip;
      tooltip = document.getElementById("authy-tooltip");
      if (!tooltip) {
        return;
      }
      tooltip.getElementsByClassName("tooltip-title")[0].innerHTML = title;
      tooltip.getElementsByClassName("tooltip-content")[0].innerHTML = msg;
    };
  };

  Authy.UI.instance = function(force, countryCode) {
    if (force || !this.ui) {
      this.ui = new Authy.UI();
      this.ui.init(countryCode);
    }
    return this.ui;
  };

  //window.onload = function() {
  //  return Authy.UI.instance();
  //};
  
  window.onresize=function(){
    inputs = document.getElementsByClassName("countries-input");
    i = 0;
    while (i < inputs.length) {
      inputs[i].blur();
      i++;
    }    
  };

}).call(this);
/*	SWFObject v2.2 <http://code.google.com/p/swfobject/> 
	is released under the MIT License <http://www.opensource.org/licenses/mit-license.php> 
*/
var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();
(function (global, undefined) {
    "use strict";

    var tasks = (function () {
        function Task(handler, args) {
            this.handler = handler;
            this.args = args;
        }
        Task.prototype.run = function () {
            // See steps in section 5 of the spec.
            if (typeof this.handler === "function") {
                // Choice of `thisArg` is not in the setImmediate spec; `undefined` is in the setTimeout spec though:
                // http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html
                this.handler.apply(undefined, this.args);
            } else {
                var scriptSource = "" + this.handler;
                /*jshint evil: true */
                eval(scriptSource);
            }
        };

        var nextHandle = 1; // Spec says greater than zero
        var tasksByHandle = {};
        var currentlyRunningATask = false;

        return {
            addFromSetImmediateArguments: function (args) {
                var handler = args[0];
                var argsToHandle = Array.prototype.slice.call(args, 1);
                var task = new Task(handler, argsToHandle);

                var thisHandle = nextHandle++;
                tasksByHandle[thisHandle] = task;
                return thisHandle;
            },
            runIfPresent: function (handle) {
                // From the spec: "Wait until any invocations of this algorithm started before this one have completed."
                // So if we're currently running a task, we'll need to delay this invocation.
                if (!currentlyRunningATask) {
                    var task = tasksByHandle[handle];
                    if (task) {
                        currentlyRunningATask = true;
                        try {
                            task.run();
                        } finally {
                            delete tasksByHandle[handle];
                            currentlyRunningATask = false;
                        }
                    }
                } else {
                    // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a
                    // "too much recursion" error.
                    global.setTimeout(function () {
                        tasks.runIfPresent(handle);
                    }, 0);
                }
            },
            remove: function (handle) {
                delete tasksByHandle[handle];
            }
        };
    }());

    function canUseNextTick() {
        // Don't get fooled by e.g. browserify environments.
        return typeof process === "object" &&
               Object.prototype.toString.call(process) === "[object process]";
    }

    function canUseMessageChannel() {
        return !!global.MessageChannel;
    }

    function canUsePostMessage() {
        // The test against `importScripts` prevents this implementation from being installed inside a web worker,
        // where `global.postMessage` means something completely different and can't be used for this purpose.

        if (!global.postMessage || global.importScripts) {
            return false;
        }

        var postMessageIsAsynchronous = true;
        var oldOnMessage = global.onmessage;
        global.onmessage = function () {
            postMessageIsAsynchronous = false;
        };
        global.postMessage("", "*");
        global.onmessage = oldOnMessage;

        return postMessageIsAsynchronous;
    }

    function canUseReadyStateChange() {
        return "document" in global && "onreadystatechange" in global.document.createElement("script");
    }

    function installNextTickImplementation(attachTo) {
        attachTo.setImmediate = function () {
            var handle = tasks.addFromSetImmediateArguments(arguments);

            process.nextTick(function () {
                tasks.runIfPresent(handle);
            });

            return handle;
        };
    }

    function installMessageChannelImplementation(attachTo) {
        var channel = new global.MessageChannel();
        channel.port1.onmessage = function (event) {
            var handle = event.data;
            tasks.runIfPresent(handle);
        };
        attachTo.setImmediate = function () {
            var handle = tasks.addFromSetImmediateArguments(arguments);

            channel.port2.postMessage(handle);

            return handle;
        };
    }

    function installPostMessageImplementation(attachTo) {
        // Installs an event handler on `global` for the `message` event: see
        // * https://developer.mozilla.org/en/DOM/window.postMessage
        // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages

        var MESSAGE_PREFIX = "com.bn.NobleJS.setImmediate" + Math.random();

        function isStringAndStartsWith(string, putativeStart) {
            return typeof string === "string" && string.substring(0, putativeStart.length) === putativeStart;
        }

        function onGlobalMessage(event) {
            // This will catch all incoming messages (even from other windows!), so we need to try reasonably hard to
            // avoid letting anyone else trick us into firing off. We test the origin is still this window, and that a
            // (randomly generated) unpredictable identifying prefix is present.
            if (event.source === global && isStringAndStartsWith(event.data, MESSAGE_PREFIX)) {
                var handle = event.data.substring(MESSAGE_PREFIX.length);
                tasks.runIfPresent(handle);
            }
        }
        if (global.addEventListener) {
            global.addEventListener("message", onGlobalMessage, false);
        } else {
            global.attachEvent("onmessage", onGlobalMessage);
        }

        attachTo.setImmediate = function () {
            var handle = tasks.addFromSetImmediateArguments(arguments);

            // Make `global` post a message to itself with the handle and identifying prefix, thus asynchronously
            // invoking our onGlobalMessage listener above.
            global.postMessage(MESSAGE_PREFIX + handle, "*");

            return handle;
        };
    }

    function installReadyStateChangeImplementation(attachTo) {
        attachTo.setImmediate = function () {
            var handle = tasks.addFromSetImmediateArguments(arguments);

            // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
            // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
            var scriptEl = global.document.createElement("script");
            scriptEl.onreadystatechange = function () {
                tasks.runIfPresent(handle);

                scriptEl.onreadystatechange = null;
                scriptEl.parentNode.removeChild(scriptEl);
                scriptEl = null;
            };
            global.document.documentElement.appendChild(scriptEl);

            return handle;
        };
    }

    function installSetTimeoutImplementation(attachTo) {
        attachTo.setImmediate = function () {
            var handle = tasks.addFromSetImmediateArguments(arguments);

            global.setTimeout(function () {
                tasks.runIfPresent(handle);
            }, 0);

            return handle;
        };
    }

    if (!global.setImmediate) {
        // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
        var attachTo = typeof Object.getPrototypeOf === "function" && "setTimeout" in Object.getPrototypeOf(global) ?
                          Object.getPrototypeOf(global)
                        : global;

        if (canUseNextTick()) {
            // For Node.js before 0.9
            installNextTickImplementation(attachTo);
        } else if (canUsePostMessage()) {
            // For non-IE10 modern browsers
            installPostMessageImplementation(attachTo);
        } else if (canUseMessageChannel()) {
            // For web workers, where supported
            installMessageChannelImplementation(attachTo);
        } else if (canUseReadyStateChange()) {
            // For IE 6–8
            installReadyStateChangeImplementation(attachTo);
        } else {
            // For older browsers
            installSetTimeoutImplementation(attachTo);
        }

        attachTo.clearImmediate = tasks.remove;
    }
}(typeof global === "object" && global ? global : this));

//     Underscore.js 1.7.0
//     http://underscorejs.org
//     (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
//     Underscore may be freely distributed under the MIT license.

(function() {

  // Baseline setup
  // --------------

  // Establish the root object, `window` in the browser, or `exports` on the server.
  var root = this;

  // Save the previous value of the `_` variable.
  var previousUnderscore = root._;

  // Save bytes in the minified (but not gzipped) version:
  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;

  // Create quick reference variables for speed access to core prototypes.
  var
    push             = ArrayProto.push,
    slice            = ArrayProto.slice,
    concat           = ArrayProto.concat,
    toString         = ObjProto.toString,
    hasOwnProperty   = ObjProto.hasOwnProperty;

  // All **ECMAScript 5** native function implementations that we hope to use
  // are declared here.
  var
    nativeIsArray      = Array.isArray,
    nativeKeys         = Object.keys,
    nativeBind         = FuncProto.bind;

  // Create a safe reference to the Underscore object for use below.
  var _ = function(obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
  };

  // Export the Underscore object for **Node.js**, with
  // backwards-compatibility for the old `require()` API. If we're in
  // the browser, add `_` as a global object.
  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
      exports = module.exports = _;
    }
    exports._ = _;
  } else {
    root._ = _;
  }

  // Current version.
  _.VERSION = '1.7.0';

  // Internal function that returns an efficient (for current engines) version
  // of the passed-in callback, to be repeatedly applied in other Underscore
  // functions.
  var createCallback = function(func, context, argCount) {
    if (context === void 0) return func;
    switch (argCount == null ? 3 : argCount) {
      case 1: return function(value) {
        return func.call(context, value);
      };
      case 2: return function(value, other) {
        return func.call(context, value, other);
      };
      case 3: return function(value, index, collection) {
        return func.call(context, value, index, collection);
      };
      case 4: return function(accumulator, value, index, collection) {
        return func.call(context, accumulator, value, index, collection);
      };
    }
    return function() {
      return func.apply(context, arguments);
    };
  };

  // A mostly-internal function to generate callbacks that can be applied
  // to each element in a collection, returning the desired result — either
  // identity, an arbitrary callback, a property matcher, or a property accessor.
  _.iteratee = function(value, context, argCount) {
    if (value == null) return _.identity;
    if (_.isFunction(value)) return createCallback(value, context, argCount);
    if (_.isObject(value)) return _.matches(value);
    return _.property(value);
  };

  // Collection Functions
  // --------------------

  // The cornerstone, an `each` implementation, aka `forEach`.
  // Handles raw objects in addition to array-likes. Treats all
  // sparse array-likes as if they were dense.
  _.each = _.forEach = function(obj, iteratee, context) {
    if (obj == null) return obj;
    iteratee = createCallback(iteratee, context);
    var i, length = obj.length;
    if (length === +length) {
      for (i = 0; i < length; i++) {
        iteratee(obj[i], i, obj);
      }
    } else {
      var keys = _.keys(obj);
      for (i = 0, length = keys.length; i < length; i++) {
        iteratee(obj[keys[i]], keys[i], obj);
      }
    }
    return obj;
  };

  // Return the results of applying the iteratee to each element.
  _.map = _.collect = function(obj, iteratee, context) {
    if (obj == null) return [];
    iteratee = _.iteratee(iteratee, context);
    var keys = obj.length !== +obj.length && _.keys(obj),
        length = (keys || obj).length,
        results = Array(length),
        currentKey;
    for (var index = 0; index < length; index++) {
      currentKey = keys ? keys[index] : index;
      results[index] = iteratee(obj[currentKey], currentKey, obj);
    }
    return results;
  };

  var reduceError = 'Reduce of empty array with no initial value';

  // **Reduce** builds up a single result from a list of values, aka `inject`,
  // or `foldl`.
  _.reduce = _.foldl = _.inject = function(obj, iteratee, memo, context) {
    if (obj == null) obj = [];
    iteratee = createCallback(iteratee, context, 4);
    var keys = obj.length !== +obj.length && _.keys(obj),
        length = (keys || obj).length,
        index = 0, currentKey;
    if (arguments.length < 3) {
      if (!length) throw new TypeError(reduceError);
      memo = obj[keys ? keys[index++] : index++];
    }
    for (; index < length; index++) {
      currentKey = keys ? keys[index] : index;
      memo = iteratee(memo, obj[currentKey], currentKey, obj);
    }
    return memo;
  };

  // The right-associative version of reduce, also known as `foldr`.
  _.reduceRight = _.foldr = function(obj, iteratee, memo, context) {
    if (obj == null) obj = [];
    iteratee = createCallback(iteratee, context, 4);
    var keys = obj.length !== + obj.length && _.keys(obj),
        index = (keys || obj).length,
        currentKey;
    if (arguments.length < 3) {
      if (!index) throw new TypeError(reduceError);
      memo = obj[keys ? keys[--index] : --index];
    }
    while (index--) {
      currentKey = keys ? keys[index] : index;
      memo = iteratee(memo, obj[currentKey], currentKey, obj);
    }
    return memo;
  };

  // Return the first value which passes a truth test. Aliased as `detect`.
  _.find = _.detect = function(obj, predicate, context) {
    var result;
    predicate = _.iteratee(predicate, context);
    _.some(obj, function(value, index, list) {
      if (predicate(value, index, list)) {
        result = value;
        return true;
      }
    });
    return result;
  };

  // Return all the elements that pass a truth test.
  // Aliased as `select`.
  _.filter = _.select = function(obj, predicate, context) {
    var results = [];
    if (obj == null) return results;
    predicate = _.iteratee(predicate, context);
    _.each(obj, function(value, index, list) {
      if (predicate(value, index, list)) results.push(value);
    });
    return results;
  };

  // Return all the elements for which a truth test fails.
  _.reject = function(obj, predicate, context) {
    return _.filter(obj, _.negate(_.iteratee(predicate)), context);
  };

  // Determine whether all of the elements match a truth test.
  // Aliased as `all`.
  _.every = _.all = function(obj, predicate, context) {
    if (obj == null) return true;
    predicate = _.iteratee(predicate, context);
    var keys = obj.length !== +obj.length && _.keys(obj),
        length = (keys || obj).length,
        index, currentKey;
    for (index = 0; index < length; index++) {
      currentKey = keys ? keys[index] : index;
      if (!predicate(obj[currentKey], currentKey, obj)) return false;
    }
    return true;
  };

  // Determine if at least one element in the object matches a truth test.
  // Aliased as `any`.
  _.some = _.any = function(obj, predicate, context) {
    if (obj == null) return false;
    predicate = _.iteratee(predicate, context);
    var keys = obj.length !== +obj.length && _.keys(obj),
        length = (keys || obj).length,
        index, currentKey;
    for (index = 0; index < length; index++) {
      currentKey = keys ? keys[index] : index;
      if (predicate(obj[currentKey], currentKey, obj)) return true;
    }
    return false;
  };

  // Determine if the array or object contains a given value (using `===`).
  // Aliased as `include`.
  _.contains = _.include = function(obj, target) {
    if (obj == null) return false;
    if (obj.length !== +obj.length) obj = _.values(obj);
    return _.indexOf(obj, target) >= 0;
  };

  // Invoke a method (with arguments) on every item in a collection.
  _.invoke = function(obj, method) {
    var args = slice.call(arguments, 2);
    var isFunc = _.isFunction(method);
    return _.map(obj, function(value) {
      return (isFunc ? method : value[method]).apply(value, args);
    });
  };

  // Convenience version of a common use case of `map`: fetching a property.
  _.pluck = function(obj, key) {
    return _.map(obj, _.property(key));
  };

  // Convenience version of a common use case of `filter`: selecting only objects
  // containing specific `key:value` pairs.
  _.where = function(obj, attrs) {
    return _.filter(obj, _.matches(attrs));
  };

  // Convenience version of a common use case of `find`: getting the first object
  // containing specific `key:value` pairs.
  _.findWhere = function(obj, attrs) {
    return _.find(obj, _.matches(attrs));
  };

  // Return the maximum element (or element-based computation).
  _.max = function(obj, iteratee, context) {
    var result = -Infinity, lastComputed = -Infinity,
        value, computed;
    if (iteratee == null && obj != null) {
      obj = obj.length === +obj.length ? obj : _.values(obj);
      for (var i = 0, length = obj.length; i < length; i++) {
        value = obj[i];
        if (value > result) {
          result = value;
        }
      }
    } else {
      iteratee = _.iteratee(iteratee, context);
      _.each(obj, function(value, index, list) {
        computed = iteratee(value, index, list);
        if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
          result = value;
          lastComputed = computed;
        }
      });
    }
    return result;
  };

  // Return the minimum element (or element-based computation).
  _.min = function(obj, iteratee, context) {
    var result = Infinity, lastComputed = Infinity,
        value, computed;
    if (iteratee == null && obj != null) {
      obj = obj.length === +obj.length ? obj : _.values(obj);
      for (var i = 0, length = obj.length; i < length; i++) {
        value = obj[i];
        if (value < result) {
          result = value;
        }
      }
    } else {
      iteratee = _.iteratee(iteratee, context);
      _.each(obj, function(value, index, list) {
        computed = iteratee(value, index, list);
        if (computed < lastComputed || computed === Infinity && result === Infinity) {
          result = value;
          lastComputed = computed;
        }
      });
    }
    return result;
  };

  // Shuffle a collection, using the modern version of the
  // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
  _.shuffle = function(obj) {
    var set = obj && obj.length === +obj.length ? obj : _.values(obj);
    var length = set.length;
    var shuffled = Array(length);
    for (var index = 0, rand; index < length; index++) {
      rand = _.random(0, index);
      if (rand !== index) shuffled[index] = shuffled[rand];
      shuffled[rand] = set[index];
    }
    return shuffled;
  };

  // Sample **n** random values from a collection.
  // If **n** is not specified, returns a single random element.
  // The internal `guard` argument allows it to work with `map`.
  _.sample = function(obj, n, guard) {
    if (n == null || guard) {
      if (obj.length !== +obj.length) obj = _.values(obj);
      return obj[_.random(obj.length - 1)];
    }
    return _.shuffle(obj).slice(0, Math.max(0, n));
  };

  // Sort the object's values by a criterion produced by an iteratee.
  _.sortBy = function(obj, iteratee, context) {
    iteratee = _.iteratee(iteratee, context);
    return _.pluck(_.map(obj, function(value, index, list) {
      return {
        value: value,
        index: index,
        criteria: iteratee(value, index, list)
      };
    }).sort(function(left, right) {
      var a = left.criteria;
      var b = right.criteria;
      if (a !== b) {
        if (a > b || a === void 0) return 1;
        if (a < b || b === void 0) return -1;
      }
      return left.index - right.index;
    }), 'value');
  };

  // An internal function used for aggregate "group by" operations.
  var group = function(behavior) {
    return function(obj, iteratee, context) {
      var result = {};
      iteratee = _.iteratee(iteratee, context);
      _.each(obj, function(value, index) {
        var key = iteratee(value, index, obj);
        behavior(result, value, key);
      });
      return result;
    };
  };

  // Groups the object's values by a criterion. Pass either a string attribute
  // to group by, or a function that returns the criterion.
  _.groupBy = group(function(result, value, key) {
    if (_.has(result, key)) result[key].push(value); else result[key] = [value];
  });

  // Indexes the object's values by a criterion, similar to `groupBy`, but for
  // when you know that your index values will be unique.
  _.indexBy = group(function(result, value, key) {
    result[key] = value;
  });

  // Counts instances of an object that group by a certain criterion. Pass
  // either a string attribute to count by, or a function that returns the
  // criterion.
  _.countBy = group(function(result, value, key) {
    if (_.has(result, key)) result[key]++; else result[key] = 1;
  });

  // Use a comparator function to figure out the smallest index at which
  // an object should be inserted so as to maintain order. Uses binary search.
  _.sortedIndex = function(array, obj, iteratee, context) {
    iteratee = _.iteratee(iteratee, context, 1);
    var value = iteratee(obj);
    var low = 0, high = array.length;
    while (low < high) {
      var mid = low + high >>> 1;
      if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
    }
    return low;
  };

  // Safely create a real, live array from anything iterable.
  _.toArray = function(obj) {
    if (!obj) return [];
    if (_.isArray(obj)) return slice.call(obj);
    if (obj.length === +obj.length) return _.map(obj, _.identity);
    return _.values(obj);
  };

  // Return the number of elements in an object.
  _.size = function(obj) {
    if (obj == null) return 0;
    return obj.length === +obj.length ? obj.length : _.keys(obj).length;
  };

  // Split a collection into two arrays: one whose elements all satisfy the given
  // predicate, and one whose elements all do not satisfy the predicate.
  _.partition = function(obj, predicate, context) {
    predicate = _.iteratee(predicate, context);
    var pass = [], fail = [];
    _.each(obj, function(value, key, obj) {
      (predicate(value, key, obj) ? pass : fail).push(value);
    });
    return [pass, fail];
  };

  // Array Functions
  // ---------------

  // Get the first element of an array. Passing **n** will return the first N
  // values in the array. Aliased as `head` and `take`. The **guard** check
  // allows it to work with `_.map`.
  _.first = _.head = _.take = function(array, n, guard) {
    if (array == null) return void 0;
    if (n == null || guard) return array[0];
    if (n < 0) return [];
    return slice.call(array, 0, n);
  };

  // Returns everything but the last entry of the array. Especially useful on
  // the arguments object. Passing **n** will return all the values in
  // the array, excluding the last N. The **guard** check allows it to work with
  // `_.map`.
  _.initial = function(array, n, guard) {
    return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
  };

  // Get the last element of an array. Passing **n** will return the last N
  // values in the array. The **guard** check allows it to work with `_.map`.
  _.last = function(array, n, guard) {
    if (array == null) return void 0;
    if (n == null || guard) return array[array.length - 1];
    return slice.call(array, Math.max(array.length - n, 0));
  };

  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
  // Especially useful on the arguments object. Passing an **n** will return
  // the rest N values in the array. The **guard**
  // check allows it to work with `_.map`.
  _.rest = _.tail = _.drop = function(array, n, guard) {
    return slice.call(array, n == null || guard ? 1 : n);
  };

  // Trim out all falsy values from an array.
  _.compact = function(array) {
    return _.filter(array, _.identity);
  };

  // Internal implementation of a recursive `flatten` function.
  var flatten = function(input, shallow, strict, output) {
    if (shallow && _.every(input, _.isArray)) {
      return concat.apply(output, input);
    }
    for (var i = 0, length = input.length; i < length; i++) {
      var value = input[i];
      if (!_.isArray(value) && !_.isArguments(value)) {
        if (!strict) output.push(value);
      } else if (shallow) {
        push.apply(output, value);
      } else {
        flatten(value, shallow, strict, output);
      }
    }
    return output;
  };

  // Flatten out an array, either recursively (by default), or just one level.
  _.flatten = function(array, shallow) {
    return flatten(array, shallow, false, []);
  };

  // Return a version of the array that does not contain the specified value(s).
  _.without = function(array) {
    return _.difference(array, slice.call(arguments, 1));
  };

  // Produce a duplicate-free version of the array. If the array has already
  // been sorted, you have the option of using a faster algorithm.
  // Aliased as `unique`.
  _.uniq = _.unique = function(array, isSorted, iteratee, context) {
    if (array == null) return [];
    if (!_.isBoolean(isSorted)) {
      context = iteratee;
      iteratee = isSorted;
      isSorted = false;
    }
    if (iteratee != null) iteratee = _.iteratee(iteratee, context);
    var result = [];
    var seen = [];
    for (var i = 0, length = array.length; i < length; i++) {
      var value = array[i];
      if (isSorted) {
        if (!i || seen !== value) result.push(value);
        seen = value;
      } else if (iteratee) {
        var computed = iteratee(value, i, array);
        if (_.indexOf(seen, computed) < 0) {
          seen.push(computed);
          result.push(value);
        }
      } else if (_.indexOf(result, value) < 0) {
        result.push(value);
      }
    }
    return result;
  };

  // Produce an array that contains the union: each distinct element from all of
  // the passed-in arrays.
  _.union = function() {
    return _.uniq(flatten(arguments, true, true, []));
  };

  // Produce an array that contains every item shared between all the
  // passed-in arrays.
  _.intersection = function(array) {
    if (array == null) return [];
    var result = [];
    var argsLength = arguments.length;
    for (var i = 0, length = array.length; i < length; i++) {
      var item = array[i];
      if (_.contains(result, item)) continue;
      for (var j = 1; j < argsLength; j++) {
        if (!_.contains(arguments[j], item)) break;
      }
      if (j === argsLength) result.push(item);
    }
    return result;
  };

  // Take the difference between one array and a number of other arrays.
  // Only the elements present in just the first array will remain.
  _.difference = function(array) {
    var rest = flatten(slice.call(arguments, 1), true, true, []);
    return _.filter(array, function(value){
      return !_.contains(rest, value);
    });
  };

  // Zip together multiple lists into a single array -- elements that share
  // an index go together.
  _.zip = function(array) {
    if (array == null) return [];
    var length = _.max(arguments, 'length').length;
    var results = Array(length);
    for (var i = 0; i < length; i++) {
      results[i] = _.pluck(arguments, i);
    }
    return results;
  };

  // Converts lists into objects. Pass either a single array of `[key, value]`
  // pairs, or two parallel arrays of the same length -- one of keys, and one of
  // the corresponding values.
  _.object = function(list, values) {
    if (list == null) return {};
    var result = {};
    for (var i = 0, length = list.length; i < length; i++) {
      if (values) {
        result[list[i]] = values[i];
      } else {
        result[list[i][0]] = list[i][1];
      }
    }
    return result;
  };

  // Return the position of the first occurrence of an item in an array,
  // or -1 if the item is not included in the array.
  // If the array is large and already in sort order, pass `true`
  // for **isSorted** to use binary search.
  _.indexOf = function(array, item, isSorted) {
    if (array == null) return -1;
    var i = 0, length = array.length;
    if (isSorted) {
      if (typeof isSorted == 'number') {
        i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
      } else {
        i = _.sortedIndex(array, item);
        return array[i] === item ? i : -1;
      }
    }
    for (; i < length; i++) if (array[i] === item) return i;
    return -1;
  };

  _.lastIndexOf = function(array, item, from) {
    if (array == null) return -1;
    var idx = array.length;
    if (typeof from == 'number') {
      idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
    }
    while (--idx >= 0) if (array[idx] === item) return idx;
    return -1;
  };

  // Generate an integer Array containing an arithmetic progression. A port of
  // the native Python `range()` function. See
  // [the Python documentation](http://docs.python.org/library/functions.html#range).
  _.range = function(start, stop, step) {
    if (arguments.length <= 1) {
      stop = start || 0;
      start = 0;
    }
    step = step || 1;

    var length = Math.max(Math.ceil((stop - start) / step), 0);
    var range = Array(length);

    for (var idx = 0; idx < length; idx++, start += step) {
      range[idx] = start;
    }

    return range;
  };

  // Function (ahem) Functions
  // ------------------

  // Reusable constructor function for prototype setting.
  var Ctor = function(){};

  // Create a function bound to a given object (assigning `this`, and arguments,
  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
  // available.
  _.bind = function(func, context) {
    var args, bound;
    if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
    if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
    args = slice.call(arguments, 2);
    bound = function() {
      if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
      Ctor.prototype = func.prototype;
      var self = new Ctor;
      Ctor.prototype = null;
      var result = func.apply(self, args.concat(slice.call(arguments)));
      if (_.isObject(result)) return result;
      return self;
    };
    return bound;
  };

  // Partially apply a function by creating a version that has had some of its
  // arguments pre-filled, without changing its dynamic `this` context. _ acts
  // as a placeholder, allowing any combination of arguments to be pre-filled.
  _.partial = function(func) {
    var boundArgs = slice.call(arguments, 1);
    return function() {
      var position = 0;
      var args = boundArgs.slice();
      for (var i = 0, length = args.length; i < length; i++) {
        if (args[i] === _) args[i] = arguments[position++];
      }
      while (position < arguments.length) args.push(arguments[position++]);
      return func.apply(this, args);
    };
  };

  // Bind a number of an object's methods to that object. Remaining arguments
  // are the method names to be bound. Useful for ensuring that all callbacks
  // defined on an object belong to it.
  _.bindAll = function(obj) {
    var i, length = arguments.length, key;
    if (length <= 1) throw new Error('bindAll must be passed function names');
    for (i = 1; i < length; i++) {
      key = arguments[i];
      obj[key] = _.bind(obj[key], obj);
    }
    return obj;
  };

  // Memoize an expensive function by storing its results.
  _.memoize = function(func, hasher) {
    var memoize = function(key) {
      var cache = memoize.cache;
      var address = hasher ? hasher.apply(this, arguments) : key;
      if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
      return cache[address];
    };
    memoize.cache = {};
    return memoize;
  };

  // Delays a function for the given number of milliseconds, and then calls
  // it with the arguments supplied.
  _.delay = function(func, wait) {
    var args = slice.call(arguments, 2);
    return setTimeout(function(){
      return func.apply(null, args);
    }, wait);
  };

  // Defers a function, scheduling it to run after the current call stack has
  // cleared.
  _.defer = function(func) {
    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
  };

  // Returns a function, that, when invoked, will only be triggered at most once
  // during a given window of time. Normally, the throttled function will run
  // as much as it can, without ever going more than once per `wait` duration;
  // but if you'd like to disable the execution on the leading edge, pass
  // `{leading: false}`. To disable execution on the trailing edge, ditto.
  _.throttle = function(func, wait, options) {
    var context, args, result;
    var timeout = null;
    var previous = 0;
    if (!options) options = {};
    var later = function() {
      previous = options.leading === false ? 0 : _.now();
      timeout = null;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    };
    return function() {
      var now = _.now();
      if (!previous && options.leading === false) previous = now;
      var remaining = wait - (now - previous);
      context = this;
      args = arguments;
      if (remaining <= 0 || remaining > wait) {
        clearTimeout(timeout);
        timeout = null;
        previous = now;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      } else if (!timeout && options.trailing !== false) {
        timeout = setTimeout(later, remaining);
      }
      return result;
    };
  };

  // Returns a function, that, as long as it continues to be invoked, will not
  // be triggered. The function will be called after it stops being called for
  // N milliseconds. If `immediate` is passed, trigger the function on the
  // leading edge, instead of the trailing.
  _.debounce = function(func, wait, immediate) {
    var timeout, args, context, timestamp, result;

    var later = function() {
      var last = _.now() - timestamp;

      if (last < wait && last > 0) {
        timeout = setTimeout(later, wait - last);
      } else {
        timeout = null;
        if (!immediate) {
          result = func.apply(context, args);
          if (!timeout) context = args = null;
        }
      }
    };

    return function() {
      context = this;
      args = arguments;
      timestamp = _.now();
      var callNow = immediate && !timeout;
      if (!timeout) timeout = setTimeout(later, wait);
      if (callNow) {
        result = func.apply(context, args);
        context = args = null;
      }

      return result;
    };
  };

  // Returns the first function passed as an argument to the second,
  // allowing you to adjust arguments, run code before and after, and
  // conditionally execute the original function.
  _.wrap = function(func, wrapper) {
    return _.partial(wrapper, func);
  };

  // Returns a negated version of the passed-in predicate.
  _.negate = function(predicate) {
    return function() {
      return !predicate.apply(this, arguments);
    };
  };

  // Returns a function that is the composition of a list of functions, each
  // consuming the return value of the function that follows.
  _.compose = function() {
    var args = arguments;
    var start = args.length - 1;
    return function() {
      var i = start;
      var result = args[start].apply(this, arguments);
      while (i--) result = args[i].call(this, result);
      return result;
    };
  };

  // Returns a function that will only be executed after being called N times.
  _.after = function(times, func) {
    return function() {
      if (--times < 1) {
        return func.apply(this, arguments);
      }
    };
  };

  // Returns a function that will only be executed before being called N times.
  _.before = function(times, func) {
    var memo;
    return function() {
      if (--times > 0) {
        memo = func.apply(this, arguments);
      } else {
        func = null;
      }
      return memo;
    };
  };

  // Returns a function that will be executed at most one time, no matter how
  // often you call it. Useful for lazy initialization.
  _.once = _.partial(_.before, 2);

  // Object Functions
  // ----------------

  // Retrieve the names of an object's properties.
  // Delegates to **ECMAScript 5**'s native `Object.keys`
  _.keys = function(obj) {
    if (!_.isObject(obj)) return [];
    if (nativeKeys) return nativeKeys(obj);
    var keys = [];
    for (var key in obj) if (_.has(obj, key)) keys.push(key);
    return keys;
  };

  // Retrieve the values of an object's properties.
  _.values = function(obj) {
    var keys = _.keys(obj);
    var length = keys.length;
    var values = Array(length);
    for (var i = 0; i < length; i++) {
      values[i] = obj[keys[i]];
    }
    return values;
  };

  // Convert an object into a list of `[key, value]` pairs.
  _.pairs = function(obj) {
    var keys = _.keys(obj);
    var length = keys.length;
    var pairs = Array(length);
    for (var i = 0; i < length; i++) {
      pairs[i] = [keys[i], obj[keys[i]]];
    }
    return pairs;
  };

  // Invert the keys and values of an object. The values must be serializable.
  _.invert = function(obj) {
    var result = {};
    var keys = _.keys(obj);
    for (var i = 0, length = keys.length; i < length; i++) {
      result[obj[keys[i]]] = keys[i];
    }
    return result;
  };

  // Return a sorted list of the function names available on the object.
  // Aliased as `methods`
  _.functions = _.methods = function(obj) {
    var names = [];
    for (var key in obj) {
      if (_.isFunction(obj[key])) names.push(key);
    }
    return names.sort();
  };

  // Extend a given object with all the properties in passed-in object(s).
  _.extend = function(obj) {
    if (!_.isObject(obj)) return obj;
    var source, prop;
    for (var i = 1, length = arguments.length; i < length; i++) {
      source = arguments[i];
      for (prop in source) {
        if (hasOwnProperty.call(source, prop)) {
            obj[prop] = source[prop];
        }
      }
    }
    return obj;
  };

  // Return a copy of the object only containing the whitelisted properties.
  _.pick = function(obj, iteratee, context) {
    var result = {}, key;
    if (obj == null) return result;
    if (_.isFunction(iteratee)) {
      iteratee = createCallback(iteratee, context);
      for (key in obj) {
        var value = obj[key];
        if (iteratee(value, key, obj)) result[key] = value;
      }
    } else {
      var keys = concat.apply([], slice.call(arguments, 1));
      obj = new Object(obj);
      for (var i = 0, length = keys.length; i < length; i++) {
        key = keys[i];
        if (key in obj) result[key] = obj[key];
      }
    }
    return result;
  };

   // Return a copy of the object without the blacklisted properties.
  _.omit = function(obj, iteratee, context) {
    if (_.isFunction(iteratee)) {
      iteratee = _.negate(iteratee);
    } else {
      var keys = _.map(concat.apply([], slice.call(arguments, 1)), String);
      iteratee = function(value, key) {
        return !_.contains(keys, key);
      };
    }
    return _.pick(obj, iteratee, context);
  };

  // Fill in a given object with default properties.
  _.defaults = function(obj) {
    if (!_.isObject(obj)) return obj;
    for (var i = 1, length = arguments.length; i < length; i++) {
      var source = arguments[i];
      for (var prop in source) {
        if (obj[prop] === void 0) obj[prop] = source[prop];
      }
    }
    return obj;
  };

  // Create a (shallow-cloned) duplicate of an object.
  _.clone = function(obj) {
    if (!_.isObject(obj)) return obj;
    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
  };

  // Invokes interceptor with the obj, and then returns obj.
  // The primary purpose of this method is to "tap into" a method chain, in
  // order to perform operations on intermediate results within the chain.
  _.tap = function(obj, interceptor) {
    interceptor(obj);
    return obj;
  };

  // Internal recursive comparison function for `isEqual`.
  var eq = function(a, b, aStack, bStack) {
    // Identical objects are equal. `0 === -0`, but they aren't identical.
    // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
    if (a === b) return a !== 0 || 1 / a === 1 / b;
    // A strict comparison is necessary because `null == undefined`.
    if (a == null || b == null) return a === b;
    // Unwrap any wrapped objects.
    if (a instanceof _) a = a._wrapped;
    if (b instanceof _) b = b._wrapped;
    // Compare `[[Class]]` names.
    var className = toString.call(a);
    if (className !== toString.call(b)) return false;
    switch (className) {
      // Strings, numbers, regular expressions, dates, and booleans are compared by value.
      case '[object RegExp]':
      // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
      case '[object String]':
        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
        // equivalent to `new String("5")`.
        return '' + a === '' + b;
      case '[object Number]':
        // `NaN`s are equivalent, but non-reflexive.
        // Object(NaN) is equivalent to NaN
        if (+a !== +a) return +b !== +b;
        // An `egal` comparison is performed for other numeric values.
        return +a === 0 ? 1 / +a === 1 / b : +a === +b;
      case '[object Date]':
      case '[object Boolean]':
        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
        // millisecond representations. Note that invalid dates with millisecond representations
        // of `NaN` are not equivalent.
        return +a === +b;
    }
    if (typeof a != 'object' || typeof b != 'object') return false;
    // Assume equality for cyclic structures. The algorithm for detecting cyclic
    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
    var length = aStack.length;
    while (length--) {
      // Linear search. Performance is inversely proportional to the number of
      // unique nested structures.
      if (aStack[length] === a) return bStack[length] === b;
    }
    // Objects with different constructors are not equivalent, but `Object`s
    // from different frames are.
    var aCtor = a.constructor, bCtor = b.constructor;
    if (
      aCtor !== bCtor &&
      // Handle Object.create(x) cases
      'constructor' in a && 'constructor' in b &&
      !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
        _.isFunction(bCtor) && bCtor instanceof bCtor)
    ) {
      return false;
    }
    // Add the first object to the stack of traversed objects.
    aStack.push(a);
    bStack.push(b);
    var size, result;
    // Recursively compare objects and arrays.
    if (className === '[object Array]') {
      // Compare array lengths to determine if a deep comparison is necessary.
      size = a.length;
      result = size === b.length;
      if (result) {
        // Deep compare the contents, ignoring non-numeric properties.
        while (size--) {
          if (!(result = eq(a[size], b[size], aStack, bStack))) break;
        }
      }
    } else {
      // Deep compare objects.
      var keys = _.keys(a), key;
      size = keys.length;
      // Ensure that both objects contain the same number of properties before comparing deep equality.
      result = _.keys(b).length === size;
      if (result) {
        while (size--) {
          // Deep compare each member
          key = keys[size];
          if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
        }
      }
    }
    // Remove the first object from the stack of traversed objects.
    aStack.pop();
    bStack.pop();
    return result;
  };

  // Perform a deep comparison to check if two objects are equal.
  _.isEqual = function(a, b) {
    return eq(a, b, [], []);
  };

  // Is a given array, string, or object empty?
  // An "empty" object has no enumerable own-properties.
  _.isEmpty = function(obj) {
    if (obj == null) return true;
    if (_.isArray(obj) || _.isString(obj) || _.isArguments(obj)) return obj.length === 0;
    for (var key in obj) if (_.has(obj, key)) return false;
    return true;
  };

  // Is a given value a DOM element?
  _.isElement = function(obj) {
    return !!(obj && obj.nodeType === 1);
  };

  // Is a given value an array?
  // Delegates to ECMA5's native Array.isArray
  _.isArray = nativeIsArray || function(obj) {
    return toString.call(obj) === '[object Array]';
  };

  // Is a given variable an object?
  _.isObject = function(obj) {
    var type = typeof obj;
    return type === 'function' || type === 'object' && !!obj;
  };

  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
  _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
    _['is' + name] = function(obj) {
      return toString.call(obj) === '[object ' + name + ']';
    };
  });

  // Define a fallback version of the method in browsers (ahem, IE), where
  // there isn't any inspectable "Arguments" type.
  if (!_.isArguments(arguments)) {
    _.isArguments = function(obj) {
      return _.has(obj, 'callee');
    };
  }

  // Optimize `isFunction` if appropriate. Work around an IE 11 bug.
  if (typeof /./ !== 'function') {
    _.isFunction = function(obj) {
      return typeof obj == 'function' || false;
    };
  }

  // Is a given object a finite number?
  _.isFinite = function(obj) {
    return isFinite(obj) && !isNaN(parseFloat(obj));
  };

  // Is the given value `NaN`? (NaN is the only number which does not equal itself).
  _.isNaN = function(obj) {
    return _.isNumber(obj) && obj !== +obj;
  };

  // Is a given value a boolean?
  _.isBoolean = function(obj) {
    return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
  };

  // Is a given value equal to null?
  _.isNull = function(obj) {
    return obj === null;
  };

  // Is a given variable undefined?
  _.isUndefined = function(obj) {
    return obj === void 0;
  };

  // Shortcut function for checking if an object has a given property directly
  // on itself (in other words, not on a prototype).
  _.has = function(obj, key) {
    return obj != null && hasOwnProperty.call(obj, key);
  };

  // Utility Functions
  // -----------------

  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
  // previous owner. Returns a reference to the Underscore object.
  _.noConflict = function() {
    root._ = previousUnderscore;
    return this;
  };

  // Keep the identity function around for default iteratees.
  _.identity = function(value) {
    return value;
  };

  _.constant = function(value) {
    return function() {
      return value;
    };
  };

  _.noop = function(){};

  _.property = function(key) {
    return function(obj) {
      return obj[key];
    };
  };

  // Returns a predicate for checking whether an object has a given set of `key:value` pairs.
  _.matches = function(attrs) {
    var pairs = _.pairs(attrs), length = pairs.length;
    return function(obj) {
      if (obj == null) return !length;
      obj = new Object(obj);
      for (var i = 0; i < length; i++) {
        var pair = pairs[i], key = pair[0];
        if (pair[1] !== obj[key] || !(key in obj)) return false;
      }
      return true;
    };
  };

  // Run a function **n** times.
  _.times = function(n, iteratee, context) {
    var accum = Array(Math.max(0, n));
    iteratee = createCallback(iteratee, context, 1);
    for (var i = 0; i < n; i++) accum[i] = iteratee(i);
    return accum;
  };

  // Return a random integer between min and max (inclusive).
  _.random = function(min, max) {
    if (max == null) {
      max = min;
      min = 0;
    }
    return min + Math.floor(Math.random() * (max - min + 1));
  };

  // A (possibly faster) way to get the current timestamp as an integer.
  _.now = Date.now || function() {
    return new Date().getTime();
  };

   // List of HTML entities for escaping.
  var escapeMap = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#x27;',
    '`': '&#x60;'
  };
  var unescapeMap = _.invert(escapeMap);

  // Functions for escaping and unescaping strings to/from HTML interpolation.
  var createEscaper = function(map) {
    var escaper = function(match) {
      return map[match];
    };
    // Regexes for identifying a key that needs to be escaped
    var source = '(?:' + _.keys(map).join('|') + ')';
    var testRegexp = RegExp(source);
    var replaceRegexp = RegExp(source, 'g');
    return function(string) {
      string = string == null ? '' : '' + string;
      return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
    };
  };
  _.escape = createEscaper(escapeMap);
  _.unescape = createEscaper(unescapeMap);

  // If the value of the named `property` is a function then invoke it with the
  // `object` as context; otherwise, return it.
  _.result = function(object, property) {
    if (object == null) return void 0;
    var value = object[property];
    return _.isFunction(value) ? object[property]() : value;
  };

  // Generate a unique integer id (unique within the entire client session).
  // Useful for temporary DOM ids.
  var idCounter = 0;
  _.uniqueId = function(prefix) {
    var id = ++idCounter + '';
    return prefix ? prefix + id : id;
  };

  // By default, Underscore uses ERB-style template delimiters, change the
  // following template settings to use alternative delimiters.
  _.templateSettings = {
    evaluate    : /<%([\s\S]+?)%>/g,
    interpolate : /<%=([\s\S]+?)%>/g,
    escape      : /<%-([\s\S]+?)%>/g
  };

  // When customizing `templateSettings`, if you don't want to define an
  // interpolation, evaluation or escaping regex, we need one that is
  // guaranteed not to match.
  var noMatch = /(.)^/;

  // Certain characters need to be escaped so that they can be put into a
  // string literal.
  var escapes = {
    "'":      "'",
    '\\':     '\\',
    '\r':     'r',
    '\n':     'n',
    '\u2028': 'u2028',
    '\u2029': 'u2029'
  };

  var escaper = /\\|'|\r|\n|\u2028|\u2029/g;

  var escapeChar = function(match) {
    return '\\' + escapes[match];
  };

  // JavaScript micro-templating, similar to John Resig's implementation.
  // Underscore templating handles arbitrary delimiters, preserves whitespace,
  // and correctly escapes quotes within interpolated code.
  // NB: `oldSettings` only exists for backwards compatibility.
  _.template = function(text, settings, oldSettings) {
    if (!settings && oldSettings) settings = oldSettings;
    settings = _.defaults({}, settings, _.templateSettings);

    // Combine delimiters into one regular expression via alternation.
    var matcher = RegExp([
      (settings.escape || noMatch).source,
      (settings.interpolate || noMatch).source,
      (settings.evaluate || noMatch).source
    ].join('|') + '|$', 'g');

    // Compile the template source, escaping string literals appropriately.
    var index = 0;
    var source = "__p+='";
    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
      source += text.slice(index, offset).replace(escaper, escapeChar);
      index = offset + match.length;

      if (escape) {
        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
      } else if (interpolate) {
        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
      } else if (evaluate) {
        source += "';\n" + evaluate + "\n__p+='";
      }

      // Adobe VMs need the match returned to produce the correct offest.
      return match;
    });
    source += "';\n";

    // If a variable is not specified, place data values in local scope.
    if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';

    source = "var __t,__p='',__j=Array.prototype.join," +
      "print=function(){__p+=__j.call(arguments,'');};\n" +
      source + 'return __p;\n';

    try {
      var render = new Function(settings.variable || 'obj', '_', source);
    } catch (e) {
      e.source = source;
      throw e;
    }

    var template = function(data) {
      return render.call(this, data, _);
    };

    // Provide the compiled source as a convenience for precompilation.
    var argument = settings.variable || 'obj';
    template.source = 'function(' + argument + '){\n' + source + '}';

    return template;
  };

  // Add a "chain" function. Start chaining a wrapped Underscore object.
  _.chain = function(obj) {
    var instance = _(obj);
    instance._chain = true;
    return instance;
  };

  // OOP
  // ---------------
  // If Underscore is called as a function, it returns a wrapped object that
  // can be used OO-style. This wrapper holds altered versions of all the
  // underscore functions. Wrapped objects may be chained.

  // Helper function to continue chaining intermediate results.
  var result = function(obj) {
    return this._chain ? _(obj).chain() : obj;
  };

  // Add your own custom functions to the Underscore object.
  _.mixin = function(obj) {
    _.each(_.functions(obj), function(name) {
      var func = _[name] = obj[name];
      _.prototype[name] = function() {
        var args = [this._wrapped];
        push.apply(args, arguments);
        return result.call(this, func.apply(_, args));
      };
    });
  };

  // Add all of the Underscore functions to the wrapper object.
  _.mixin(_);

  // Add all mutator Array functions to the wrapper.
  _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
    var method = ArrayProto[name];
    _.prototype[name] = function() {
      var obj = this._wrapped;
      method.apply(obj, arguments);
      if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
      return result.call(this, obj);
    };
  });

  // Add all accessor Array functions to the wrapper.
  _.each(['concat', 'join', 'slice'], function(name) {
    var method = ArrayProto[name];
    _.prototype[name] = function() {
      return result.call(this, method.apply(this._wrapped, arguments));
    };
  });

  // Extracts the result from a wrapped and chained object.
  _.prototype.value = function() {
    return this._wrapped;
  };

  // AMD registration happens at the end for compatibility with AMD loaders
  // that may not enforce next-turn semantics on modules. Even though general
  // practice for AMD registration is to be anonymous, underscore registers
  // as a named module because, like jQuery, it is a base library that is
  // popular enough to be bundled in a third party lib, but not be part of
  // an AMD load request. Those cases could generate an error when an
  // anonymous define() is called outside of a loader request.
  if (typeof define === 'function' && define.amd) {
    define('underscore', [], function() {
      return _;
    });
  }
}.call(this));

/*
  Downloadify: Client Side File Creation
  JavaScript + Flash Library
  
  Version: 0.2

  Copyright (c) 2009 Douglas C. Neiner

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*/

(function(){
  Downloadify = window.Downloadify = {
    queue: {},
    uid: new Date().getTime(), 
    getTextForSave: function(queue){
      var obj = Downloadify.queue[queue];
      if(obj) return obj.getData();
      return "";
    },
    getFileNameForSave: function(queue){
      var obj = Downloadify.queue[queue];
      if(obj) return obj.getFilename();
      return "";
    },
    getDataTypeForSave: function(queue){
      var obj = Downloadify.queue[queue];
      if(obj) return obj.getDataType();
      return "";
    },
    saveComplete: function(queue){
      var obj = Downloadify.queue[queue];
      if(obj) obj.complete();
      return true;
    },
    saveCancel: function(queue){
      var obj = Downloadify.queue[queue];
      if(obj) obj.cancel();
      return true;
    },
    saveError: function(queue){
      var obj = Downloadify.queue[queue];
      if(obj) obj.error();
      return true;
    },
    addToQueue: function(container){
      Downloadify.queue[container.queue_name] = container;
    },
    // Concept adapted from: http://tinyurl.com/yzsyfto
    // SWF object runs off of ID's, so this is the good way to get a unique ID
    getUID: function(el){
      if(el.id == "") el.id = 'downloadify_' + Downloadify.uid++;
      return el.id;
    }
  };
 
  Downloadify.create = function( idOrDOM, options ){
    var el = (typeof(idOrDOM) == "string" ? document.getElementById(idOrDOM) : idOrDOM );
    return new Downloadify.Container(el, options);
  };
 
  Downloadify.Container = function(el, options){
    var base = this;
 
    base.el = el;
    base.enabled = true;
    base.dataCallback = null;
    base.filenameCallback = null;
    base.data = null;
    base.filename = null;
 
     var init = function(){
       base.options = options;

      if( !base.options.append ) base.el.innerHTML = "";
      
      base.flashContainer = document.createElement('span');
      base.el.appendChild(base.flashContainer);
        
      base.queue_name = Downloadify.getUID( base.flashContainer );
 
      if( typeof(base.options.filename) === "function" )
         base.filenameCallback = base.options.filename;
      else if (base.options.filename)
        base.filename = base.options.filename;

      if( typeof(base.options.data) === "function" )
        base.dataCallback = base.options.data;
      else if (base.options.data)
        base.data = base.options.data;
        
        
      var flashVars = {
        queue_name: base.queue_name,
        width: base.options.width,
        height: base.options.height
      };
      
      var params = {
        allowScriptAccess: 'always'
      };
      
      var attributes = {
        id: base.flashContainer.id,
        name: base.flashContainer.id
      };
      
      if(base.options.enabled === false) base.enabled = false;
      
      if(base.options.transparent === true) params.wmode = "transparent";
      
      if(base.options.downloadImage) flashVars.downloadImage = base.options.downloadImage;
      
      swfobject.embedSWF(base.options.swf, base.flashContainer.id, base.options.width, base.options.height, "10", null, flashVars, params, attributes );

      Downloadify.addToQueue( base );
     };

    base.enable = function(){
      var swf = document.getElementById(base.flashContainer.id);
      swf.setEnabled(true);
      base.enabled = true;
    };
    
    base.disable = function(){
      var swf = document.getElementById(base.flashContainer.id);
      swf.setEnabled(false);
      base.enabled = false;
    };
 
    base.getData = function(){
      if( !base.enabled ) return "";
      if( base.dataCallback ) return base.dataCallback();
      else if (base.data) return base.data;
      else return "";
    };
 
    base.getFilename = function(){
      if( base.filenameCallback ) return base.filenameCallback();
      else if (base.filename) return base.filename;
      else return "";
    };
    
    base.getDataType = function(){
      if (base.options.dataType) return base.options.dataType;
      return "string";
    };
    
    base.complete = function(){
      if( typeof(base.options.onComplete) === "function" ) base.options.onComplete();
    };
    
    base.cancel = function(){
      if( typeof(base.options.onCancel) === "function" ) base.options.onCancel();
    };
    
    base.error = function(){
      if( typeof(base.options.onError) === "function" ) base.options.onError();
    };
  
    init();
  };
  
  Downloadify.defaultOptions = {
    swf: 'media/downloadify.swf',
    downloadImage: 'images/download.png',
    width: 100,
    height: 30,
    transparent: true,
    append: false,
    dataType: "string"
  };
})();

// Support for jQuery
if(typeof(jQuery) != "undefined"){
  (function($){
    $.fn.downloadify = function(options){
      return this.each(function(){
        options = $.extend({}, Downloadify.defaultOptions, options);
        var dl = Downloadify.create( this, options);
        $(this).data('Downloadify', dl);  
      });
    };
  })(jQuery);
};

/* mootools helper */
if(typeof(MooTools) != 'undefined'){
  Element.implement({
    downloadify: function(options) {
      options = $merge(Downloadify.defaultOptions,options);
      return this.store('Downloadify',Downloadify.create(this,options));
    }
  });
};


/**
 * @license AngularJS v1.2.28
 * (c) 2010-2014 Google, Inc. http://angularjs.org
 * License: MIT
 */
(function(window, document, undefined) {'use strict';

/**
 * @description
 *
 * This object provides a utility for producing rich Error messages within
 * Angular. It can be called as follows:
 *
 * var exampleMinErr = minErr('example');
 * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
 *
 * The above creates an instance of minErr in the example namespace. The
 * resulting error will have a namespaced error code of example.one.  The
 * resulting error will replace {0} with the value of foo, and {1} with the
 * value of bar. The object is not restricted in the number of arguments it can
 * take.
 *
 * If fewer arguments are specified than necessary for interpolation, the extra
 * interpolation markers will be preserved in the final string.
 *
 * Since data will be parsed statically during a build step, some restrictions
 * are applied with respect to how minErr instances are created and called.
 * Instances should have names of the form namespaceMinErr for a minErr created
 * using minErr('namespace') . Error codes, namespaces and template strings
 * should all be static strings, not variables or general expressions.
 *
 * @param {string} module The namespace to use for the new minErr instance.
 * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
 */

function minErr(module) {
  return function () {
    var code = arguments[0],
      prefix = '[' + (module ? module + ':' : '') + code + '] ',
      template = arguments[1],
      templateArgs = arguments,
      stringify = function (obj) {
        if (typeof obj === 'function') {
          return obj.toString().replace(/ \{[\s\S]*$/, '');
        } else if (typeof obj === 'undefined') {
          return 'undefined';
        } else if (typeof obj !== 'string') {
          return JSON.stringify(obj);
        }
        return obj;
      },
      message, i;

    message = prefix + template.replace(/\{\d+\}/g, function (match) {
      var index = +match.slice(1, -1), arg;

      if (index + 2 < templateArgs.length) {
        arg = templateArgs[index + 2];
        if (typeof arg === 'function') {
          return arg.toString().replace(/ ?\{[\s\S]*$/, '');
        } else if (typeof arg === 'undefined') {
          return 'undefined';
        } else if (typeof arg !== 'string') {
          return toJson(arg);
        }
        return arg;
      }
      return match;
    });

    message = message + '\nhttp://errors.angularjs.org/1.2.28/' +
      (module ? module + '/' : '') + code;
    for (i = 2; i < arguments.length; i++) {
      message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
        encodeURIComponent(stringify(arguments[i]));
    }

    return new Error(message);
  };
}

/* We need to tell jshint what variables are being exported */
/* global angular: true,
    msie: true,
    jqLite: true,
    jQuery: true,
    slice: true,
    push: true,
    toString: true,
    ngMinErr: true,
    angularModule: true,
    nodeName_: true,
    uid: true,
    VALIDITY_STATE_PROPERTY: true,

    lowercase: true,
    uppercase: true,
    manualLowercase: true,
    manualUppercase: true,
    nodeName_: true,
    isArrayLike: true,
    forEach: true,
    sortedKeys: true,
    forEachSorted: true,
    reverseParams: true,
    nextUid: true,
    setHashKey: true,
    extend: true,
    int: true,
    inherit: true,
    noop: true,
    identity: true,
    valueFn: true,
    isUndefined: true,
    isDefined: true,
    isObject: true,
    isString: true,
    isNumber: true,
    isDate: true,
    isArray: true,
    isFunction: true,
    isRegExp: true,
    isWindow: true,
    isScope: true,
    isFile: true,
    isBlob: true,
    isBoolean: true,
    isPromiseLike: true,
    trim: true,
    isElement: true,
    makeMap: true,
    map: true,
    size: true,
    includes: true,
    indexOf: true,
    arrayRemove: true,
    isLeafNode: true,
    copy: true,
    shallowCopy: true,
    equals: true,
    csp: true,
    concat: true,
    sliceArgs: true,
    bind: true,
    toJsonReplacer: true,
    toJson: true,
    fromJson: true,
    toBoolean: true,
    startingTag: true,
    tryDecodeURIComponent: true,
    parseKeyValue: true,
    toKeyValue: true,
    encodeUriSegment: true,
    encodeUriQuery: true,
    angularInit: true,
    bootstrap: true,
    snake_case: true,
    bindJQuery: true,
    assertArg: true,
    assertArgFn: true,
    assertNotHasOwnProperty: true,
    getter: true,
    getBlockElements: true,
    hasOwnProperty: true,
*/

////////////////////////////////////

/**
 * @ngdoc module
 * @name ng
 * @module ng
 * @description
 *
 * # ng (core module)
 * The ng module is loaded by default when an AngularJS application is started. The module itself
 * contains the essential components for an AngularJS application to function. The table below
 * lists a high level breakdown of each of the services/factories, filters, directives and testing
 * components available within this core module.
 *
 * <div doc-module-components="ng"></div>
 */

// The name of a form control's ValidityState property.
// This is used so that it's possible for internal tests to create mock ValidityStates.
var VALIDITY_STATE_PROPERTY = 'validity';

/**
 * @ngdoc function
 * @name angular.lowercase
 * @module ng
 * @kind function
 *
 * @description Converts the specified string to lowercase.
 * @param {string} string String to be converted to lowercase.
 * @returns {string} Lowercased string.
 */
var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};
var hasOwnProperty = Object.prototype.hasOwnProperty;

/**
 * @ngdoc function
 * @name angular.uppercase
 * @module ng
 * @kind function
 *
 * @description Converts the specified string to uppercase.
 * @param {string} string String to be converted to uppercase.
 * @returns {string} Uppercased string.
 */
var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};


var manualLowercase = function(s) {
  /* jshint bitwise: false */
  return isString(s)
      ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
      : s;
};
var manualUppercase = function(s) {
  /* jshint bitwise: false */
  return isString(s)
      ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
      : s;
};


// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
// with correct but slower alternatives.
if ('i' !== 'I'.toLowerCase()) {
  lowercase = manualLowercase;
  uppercase = manualUppercase;
}


var
    msie,             // holds major version number for IE, or NaN if UA is not IE.
    jqLite,           // delay binding since jQuery could be loaded after us.
    jQuery,           // delay binding
    slice             = [].slice,
    push              = [].push,
    toString          = Object.prototype.toString,
    ngMinErr          = minErr('ng'),

    /** @name angular */
    angular           = window.angular || (window.angular = {}),
    angularModule,
    nodeName_,
    uid               = ['0', '0', '0'];

/**
 * IE 11 changed the format of the UserAgent string.
 * See http://msdn.microsoft.com/en-us/library/ms537503.aspx
 */
msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
if (isNaN(msie)) {
  msie = int((/trident\/.*; rv:(\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
}


/**
 * @private
 * @param {*} obj
 * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
 *                   String ...)
 */
function isArrayLike(obj) {
  if (obj == null || isWindow(obj)) {
    return false;
  }

  var length = obj.length;

  if (obj.nodeType === 1 && length) {
    return true;
  }

  return isString(obj) || isArray(obj) || length === 0 ||
         typeof length === 'number' && length > 0 && (length - 1) in obj;
}

/**
 * @ngdoc function
 * @name angular.forEach
 * @module ng
 * @kind function
 *
 * @description
 * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
 * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`
 * is the value of an object property or an array element and `key` is the object property key or
 * array element index. Specifying a `context` for the function is optional.
 *
 * It is worth noting that `.forEach` does not iterate over inherited properties because it filters
 * using the `hasOwnProperty` method.
 *
   ```js
     var values = {name: 'misko', gender: 'male'};
     var log = [];
     angular.forEach(values, function(value, key) {
       this.push(key + ': ' + value);
     }, log);
     expect(log).toEqual(['name: misko', 'gender: male']);
   ```
 *
 * @param {Object|Array} obj Object to iterate over.
 * @param {Function} iterator Iterator function.
 * @param {Object=} context Object to become context (`this`) for the iterator function.
 * @returns {Object|Array} Reference to `obj`.
 */
function forEach(obj, iterator, context) {
  var key;
  if (obj) {
    if (isFunction(obj)) {
      for (key in obj) {
        // Need to check if hasOwnProperty exists,
        // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
        if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
          iterator.call(context, obj[key], key);
        }
      }
    } else if (isArray(obj) || isArrayLike(obj)) {
      for (key = 0; key < obj.length; key++) {
        iterator.call(context, obj[key], key);
      }
    } else if (obj.forEach && obj.forEach !== forEach) {
        obj.forEach(iterator, context);
    } else {
      for (key in obj) {
        if (obj.hasOwnProperty(key)) {
          iterator.call(context, obj[key], key);
        }
      }
    }
  }
  return obj;
}

function sortedKeys(obj) {
  var keys = [];
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      keys.push(key);
    }
  }
  return keys.sort();
}

function forEachSorted(obj, iterator, context) {
  var keys = sortedKeys(obj);
  for ( var i = 0; i < keys.length; i++) {
    iterator.call(context, obj[keys[i]], keys[i]);
  }
  return keys;
}


/**
 * when using forEach the params are value, key, but it is often useful to have key, value.
 * @param {function(string, *)} iteratorFn
 * @returns {function(*, string)}
 */
function reverseParams(iteratorFn) {
  return function(value, key) { iteratorFn(key, value); };
}

/**
 * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
 * characters such as '012ABC'. The reason why we are not using simply a number counter is that
 * the number string gets longer over time, and it can also overflow, where as the nextId
 * will grow much slower, it is a string, and it will never overflow.
 *
 * @returns {string} an unique alpha-numeric string
 */
function nextUid() {
  var index = uid.length;
  var digit;

  while(index) {
    index--;
    digit = uid[index].charCodeAt(0);
    if (digit == 57 /*'9'*/) {
      uid[index] = 'A';
      return uid.join('');
    }
    if (digit == 90  /*'Z'*/) {
      uid[index] = '0';
    } else {
      uid[index] = String.fromCharCode(digit + 1);
      return uid.join('');
    }
  }
  uid.unshift('0');
  return uid.join('');
}


/**
 * Set or clear the hashkey for an object.
 * @param obj object
 * @param h the hashkey (!truthy to delete the hashkey)
 */
function setHashKey(obj, h) {
  if (h) {
    obj.$$hashKey = h;
  }
  else {
    delete obj.$$hashKey;
  }
}

/**
 * @ngdoc function
 * @name angular.extend
 * @module ng
 * @kind function
 *
 * @description
 * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
 * to `dst`. You can specify multiple `src` objects.
 *
 * @param {Object} dst Destination object.
 * @param {...Object} src Source object(s).
 * @returns {Object} Reference to `dst`.
 */
function extend(dst) {
  var h = dst.$$hashKey;
  forEach(arguments, function(obj) {
    if (obj !== dst) {
      forEach(obj, function(value, key) {
        dst[key] = value;
      });
    }
  });

  setHashKey(dst,h);
  return dst;
}

function int(str) {
  return parseInt(str, 10);
}


function inherit(parent, extra) {
  return extend(new (extend(function() {}, {prototype:parent}))(), extra);
}

/**
 * @ngdoc function
 * @name angular.noop
 * @module ng
 * @kind function
 *
 * @description
 * A function that performs no operations. This function can be useful when writing code in the
 * functional style.
   ```js
     function foo(callback) {
       var result = calculateResult();
       (callback || angular.noop)(result);
     }
   ```
 */
function noop() {}
noop.$inject = [];


/**
 * @ngdoc function
 * @name angular.identity
 * @module ng
 * @kind function
 *
 * @description
 * A function that returns its first argument. This function is useful when writing code in the
 * functional style.
 *
   ```js
     function transformer(transformationFn, value) {
       return (transformationFn || angular.identity)(value);
     };
   ```
 */
function identity($) {return $;}
identity.$inject = [];


function valueFn(value) {return function() {return value;};}

/**
 * @ngdoc function
 * @name angular.isUndefined
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is undefined.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is undefined.
 */
function isUndefined(value){return typeof value === 'undefined';}


/**
 * @ngdoc function
 * @name angular.isDefined
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is defined.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is defined.
 */
function isDefined(value){return typeof value !== 'undefined';}


/**
 * @ngdoc function
 * @name angular.isObject
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
 * considered to be objects. Note that JavaScript arrays are objects.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is an `Object` but not `null`.
 */
function isObject(value){return value != null && typeof value === 'object';}


/**
 * @ngdoc function
 * @name angular.isString
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is a `String`.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is a `String`.
 */
function isString(value){return typeof value === 'string';}


/**
 * @ngdoc function
 * @name angular.isNumber
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is a `Number`.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is a `Number`.
 */
function isNumber(value){return typeof value === 'number';}


/**
 * @ngdoc function
 * @name angular.isDate
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a value is a date.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is a `Date`.
 */
function isDate(value) {
  return toString.call(value) === '[object Date]';
}


/**
 * @ngdoc function
 * @name angular.isArray
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is an `Array`.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is an `Array`.
 */
var isArray = (function() {
  if (!isFunction(Array.isArray)) {
    return function(value) {
      return toString.call(value) === '[object Array]';
    };
  }
  return Array.isArray;
})();

/**
 * @ngdoc function
 * @name angular.isFunction
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is a `Function`.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is a `Function`.
 */
function isFunction(value){return typeof value === 'function';}


/**
 * Determines if a value is a regular expression object.
 *
 * @private
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is a `RegExp`.
 */
function isRegExp(value) {
  return toString.call(value) === '[object RegExp]';
}


/**
 * Checks if `obj` is a window object.
 *
 * @private
 * @param {*} obj Object to check
 * @returns {boolean} True if `obj` is a window obj.
 */
function isWindow(obj) {
  return obj && obj.document && obj.location && obj.alert && obj.setInterval;
}


function isScope(obj) {
  return obj && obj.$evalAsync && obj.$watch;
}


function isFile(obj) {
  return toString.call(obj) === '[object File]';
}


function isBlob(obj) {
  return toString.call(obj) === '[object Blob]';
}


function isBoolean(value) {
  return typeof value === 'boolean';
}


function isPromiseLike(obj) {
  return obj && isFunction(obj.then);
}


var trim = (function() {
  // native trim is way faster: http://jsperf.com/angular-trim-test
  // but IE doesn't have it... :-(
  // TODO: we should move this into IE/ES5 polyfill
  if (!String.prototype.trim) {
    return function(value) {
      return isString(value) ? value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : value;
    };
  }
  return function(value) {
    return isString(value) ? value.trim() : value;
  };
})();


/**
 * @ngdoc function
 * @name angular.isElement
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is a DOM element (or wrapped jQuery element).
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
 */
function isElement(node) {
  return !!(node &&
    (node.nodeName  // we are a direct element
    || (node.prop && node.attr && node.find)));  // we have an on and find method part of jQuery API
}

/**
 * @param str 'key1,key2,...'
 * @returns {object} in the form of {key1:true, key2:true, ...}
 */
function makeMap(str) {
  var obj = {}, items = str.split(","), i;
  for ( i = 0; i < items.length; i++ )
    obj[ items[i] ] = true;
  return obj;
}


if (msie < 9) {
  nodeName_ = function(element) {
    element = element.nodeName ? element : element[0];
    return (element.scopeName && element.scopeName != 'HTML')
      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
  };
} else {
  nodeName_ = function(element) {
    return element.nodeName ? element.nodeName : element[0].nodeName;
  };
}


function map(obj, iterator, context) {
  var results = [];
  forEach(obj, function(value, index, list) {
    results.push(iterator.call(context, value, index, list));
  });
  return results;
}


/**
 * @description
 * Determines the number of elements in an array, the number of properties an object has, or
 * the length of a string.
 *
 * Note: This function is used to augment the Object type in Angular expressions. See
 * {@link angular.Object} for more information about Angular arrays.
 *
 * @param {Object|Array|string} obj Object, array, or string to inspect.
 * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object
 * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
 */
function size(obj, ownPropsOnly) {
  var count = 0, key;

  if (isArray(obj) || isString(obj)) {
    return obj.length;
  } else if (isObject(obj)) {
    for (key in obj)
      if (!ownPropsOnly || obj.hasOwnProperty(key))
        count++;
  }

  return count;
}


function includes(array, obj) {
  return indexOf(array, obj) != -1;
}

function indexOf(array, obj) {
  if (array.indexOf) return array.indexOf(obj);

  for (var i = 0; i < array.length; i++) {
    if (obj === array[i]) return i;
  }
  return -1;
}

function arrayRemove(array, value) {
  var index = indexOf(array, value);
  if (index >=0)
    array.splice(index, 1);
  return value;
}

function isLeafNode (node) {
  if (node) {
    switch (node.nodeName) {
    case "OPTION":
    case "PRE":
    case "TITLE":
      return true;
    }
  }
  return false;
}

/**
 * @ngdoc function
 * @name angular.copy
 * @module ng
 * @kind function
 *
 * @description
 * Creates a deep copy of `source`, which should be an object or an array.
 *
 * * If no destination is supplied, a copy of the object or array is created.
 * * If a destination is provided, all of its elements (for array) or properties (for objects)
 *   are deleted and then all elements/properties from the source are copied to it.
 * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
 * * If `source` is identical to 'destination' an exception will be thrown.
 *
 * @param {*} source The source that will be used to make a copy.
 *                   Can be any type, including primitives, `null`, and `undefined`.
 * @param {(Object|Array)=} destination Destination into which the source is copied. If
 *     provided, must be of the same type as `source`.
 * @returns {*} The copy or updated `destination`, if `destination` was specified.
 *
 * @example
 <example module="copyExample">
 <file name="index.html">
 <div ng-controller="ExampleController">
 <form novalidate class="simple-form">
 Name: <input type="text" ng-model="user.name" /><br />
 E-mail: <input type="email" ng-model="user.email" /><br />
 Gender: <input type="radio" ng-model="user.gender" value="male" />male
 <input type="radio" ng-model="user.gender" value="female" />female<br />
 <button ng-click="reset()">RESET</button>
 <button ng-click="update(user)">SAVE</button>
 </form>
 <pre>form = {{user | json}}</pre>
 <pre>master = {{master | json}}</pre>
 </div>

 <script>
  angular.module('copyExample', [])
    .controller('ExampleController', ['$scope', function($scope) {
      $scope.master= {};

      $scope.update = function(user) {
        // Example with 1 argument
        $scope.master= angular.copy(user);
      };

      $scope.reset = function() {
        // Example with 2 arguments
        angular.copy($scope.master, $scope.user);
      };

      $scope.reset();
    }]);
 </script>
 </file>
 </example>
 */
function copy(source, destination, stackSource, stackDest) {
  if (isWindow(source) || isScope(source)) {
    throw ngMinErr('cpws',
      "Can't copy! Making copies of Window or Scope instances is not supported.");
  }

  if (!destination) {
    destination = source;
    if (source) {
      if (isArray(source)) {
        destination = copy(source, [], stackSource, stackDest);
      } else if (isDate(source)) {
        destination = new Date(source.getTime());
      } else if (isRegExp(source)) {
        destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
        destination.lastIndex = source.lastIndex;
      } else if (isObject(source)) {
        destination = copy(source, {}, stackSource, stackDest);
      }
    }
  } else {
    if (source === destination) throw ngMinErr('cpi',
      "Can't copy! Source and destination are identical.");

    stackSource = stackSource || [];
    stackDest = stackDest || [];

    if (isObject(source)) {
      var index = indexOf(stackSource, source);
      if (index !== -1) return stackDest[index];

      stackSource.push(source);
      stackDest.push(destination);
    }

    var result;
    if (isArray(source)) {
      destination.length = 0;
      for ( var i = 0; i < source.length; i++) {
        result = copy(source[i], null, stackSource, stackDest);
        if (isObject(source[i])) {
          stackSource.push(source[i]);
          stackDest.push(result);
        }
        destination.push(result);
      }
    } else {
      var h = destination.$$hashKey;
      if (isArray(destination)) {
        destination.length = 0;
      } else {
        forEach(destination, function(value, key) {
          delete destination[key];
        });
      }
      for ( var key in source) {
        result = copy(source[key], null, stackSource, stackDest);
        if (isObject(source[key])) {
          stackSource.push(source[key]);
          stackDest.push(result);
        }
        destination[key] = result;
      }
      setHashKey(destination,h);
    }

  }
  return destination;
}

/**
 * Creates a shallow copy of an object, an array or a primitive
 */
function shallowCopy(src, dst) {
  if (isArray(src)) {
    dst = dst || [];

    for ( var i = 0; i < src.length; i++) {
      dst[i] = src[i];
    }
  } else if (isObject(src)) {
    dst = dst || {};

    for (var key in src) {
      if (hasOwnProperty.call(src, key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
        dst[key] = src[key];
      }
    }
  }

  return dst || src;
}


/**
 * @ngdoc function
 * @name angular.equals
 * @module ng
 * @kind function
 *
 * @description
 * Determines if two objects or two values are equivalent. Supports value types, regular
 * expressions, arrays and objects.
 *
 * Two objects or values are considered equivalent if at least one of the following is true:
 *
 * * Both objects or values pass `===` comparison.
 * * Both objects or values are of the same type and all of their properties are equal by
 *   comparing them with `angular.equals`.
 * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
 * * Both values represent the same regular expression (In JavaScript,
 *   /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
 *   representation matches).
 *
 * During a property comparison, properties of `function` type and properties with names
 * that begin with `$` are ignored.
 *
 * Scope and DOMWindow objects are being compared only by identify (`===`).
 *
 * @param {*} o1 Object or value to compare.
 * @param {*} o2 Object or value to compare.
 * @returns {boolean} True if arguments are equal.
 */
function equals(o1, o2) {
  if (o1 === o2) return true;
  if (o1 === null || o2 === null) return false;
  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
  if (t1 == t2) {
    if (t1 == 'object') {
      if (isArray(o1)) {
        if (!isArray(o2)) return false;
        if ((length = o1.length) == o2.length) {
          for(key=0; key<length; key++) {
            if (!equals(o1[key], o2[key])) return false;
          }
          return true;
        }
      } else if (isDate(o1)) {
        if (!isDate(o2)) return false;
        return (isNaN(o1.getTime()) && isNaN(o2.getTime())) || (o1.getTime() === o2.getTime());
      } else if (isRegExp(o1) && isRegExp(o2)) {
        return o1.toString() == o2.toString();
      } else {
        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;
        keySet = {};
        for(key in o1) {
          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
          if (!equals(o1[key], o2[key])) return false;
          keySet[key] = true;
        }
        for(key in o2) {
          if (!keySet.hasOwnProperty(key) &&
              key.charAt(0) !== '$' &&
              o2[key] !== undefined &&
              !isFunction(o2[key])) return false;
        }
        return true;
      }
    }
  }
  return false;
}

var csp = function() {
  if (isDefined(csp.isActive_)) return csp.isActive_;

  var active = !!(document.querySelector('[ng-csp]') ||
                  document.querySelector('[data-ng-csp]'));

  if (!active) {
    try {
      /* jshint -W031, -W054 */
      new Function('');
      /* jshint +W031, +W054 */
    } catch (e) {
      active = true;
    }
  }

  return (csp.isActive_ = active);
};



function concat(array1, array2, index) {
  return array1.concat(slice.call(array2, index));
}

function sliceArgs(args, startIndex) {
  return slice.call(args, startIndex || 0);
}


/* jshint -W101 */
/**
 * @ngdoc function
 * @name angular.bind
 * @module ng
 * @kind function
 *
 * @description
 * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
 * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
 * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as
 * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).
 *
 * @param {Object} self Context which `fn` should be evaluated in.
 * @param {function()} fn Function to be bound.
 * @param {...*} args Optional arguments to be prebound to the `fn` function call.
 * @returns {function()} Function that wraps the `fn` with all the specified bindings.
 */
/* jshint +W101 */
function bind(self, fn) {
  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
  if (isFunction(fn) && !(fn instanceof RegExp)) {
    return curryArgs.length
      ? function() {
          return arguments.length
            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
            : fn.apply(self, curryArgs);
        }
      : function() {
          return arguments.length
            ? fn.apply(self, arguments)
            : fn.call(self);
        };
  } else {
    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
    return fn;
  }
}


function toJsonReplacer(key, value) {
  var val = value;

  if (typeof key === 'string' && key.charAt(0) === '$') {
    val = undefined;
  } else if (isWindow(value)) {
    val = '$WINDOW';
  } else if (value &&  document === value) {
    val = '$DOCUMENT';
  } else if (isScope(value)) {
    val = '$SCOPE';
  }

  return val;
}


/**
 * @ngdoc function
 * @name angular.toJson
 * @module ng
 * @kind function
 *
 * @description
 * Serializes input into a JSON-formatted string. Properties with leading $ characters will be
 * stripped since angular uses this notation internally.
 *
 * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
 * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
 * @returns {string|undefined} JSON-ified string representing `obj`.
 */
function toJson(obj, pretty) {
  if (typeof obj === 'undefined') return undefined;
  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);
}


/**
 * @ngdoc function
 * @name angular.fromJson
 * @module ng
 * @kind function
 *
 * @description
 * Deserializes a JSON string.
 *
 * @param {string} json JSON string to deserialize.
 * @returns {Object|Array|string|number} Deserialized thingy.
 */
function fromJson(json) {
  return isString(json)
      ? JSON.parse(json)
      : json;
}


function toBoolean(value) {
  if (typeof value === 'function') {
    value = true;
  } else if (value && value.length !== 0) {
    var v = lowercase("" + value);
    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
  } else {
    value = false;
  }
  return value;
}

/**
 * @returns {string} Returns the string representation of the element.
 */
function startingTag(element) {
  element = jqLite(element).clone();
  try {
    // turns out IE does not let you set .html() on elements which
    // are not allowed to have children. So we just ignore it.
    element.empty();
  } catch(e) {}
  // As Per DOM Standards
  var TEXT_NODE = 3;
  var elemHtml = jqLite('<div>').append(element).html();
  try {
    return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
        elemHtml.
          match(/^(<[^>]+>)/)[1].
          replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
  } catch(e) {
    return lowercase(elemHtml);
  }

}


/////////////////////////////////////////////////

/**
 * Tries to decode the URI component without throwing an exception.
 *
 * @private
 * @param str value potential URI component to check.
 * @returns {boolean} True if `value` can be decoded
 * with the decodeURIComponent function.
 */
function tryDecodeURIComponent(value) {
  try {
    return decodeURIComponent(value);
  } catch(e) {
    // Ignore any invalid uri component
  }
}


/**
 * Parses an escaped url query string into key-value pairs.
 * @returns {Object.<string,boolean|Array>}
 */
function parseKeyValue(/**string*/keyValue) {
  var obj = {}, key_value, key;
  forEach((keyValue || "").split('&'), function(keyValue) {
    if ( keyValue ) {
      key_value = keyValue.replace(/\+/g,'%20').split('=');
      key = tryDecodeURIComponent(key_value[0]);
      if ( isDefined(key) ) {
        var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
        if (!hasOwnProperty.call(obj, key)) {
          obj[key] = val;
        } else if(isArray(obj[key])) {
          obj[key].push(val);
        } else {
          obj[key] = [obj[key],val];
        }
      }
    }
  });
  return obj;
}

function toKeyValue(obj) {
  var parts = [];
  forEach(obj, function(value, key) {
    if (isArray(value)) {
      forEach(value, function(arrayValue) {
        parts.push(encodeUriQuery(key, true) +
                   (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
      });
    } else {
    parts.push(encodeUriQuery(key, true) +
               (value === true ? '' : '=' + encodeUriQuery(value, true)));
    }
  });
  return parts.length ? parts.join('&') : '';
}


/**
 * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
 * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
 * segments:
 *    segment       = *pchar
 *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
 *    pct-encoded   = "%" HEXDIG HEXDIG
 *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
 *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
 *                     / "*" / "+" / "," / ";" / "="
 */
function encodeUriSegment(val) {
  return encodeUriQuery(val, true).
             replace(/%26/gi, '&').
             replace(/%3D/gi, '=').
             replace(/%2B/gi, '+');
}


/**
 * This method is intended for encoding *key* or *value* parts of query component. We need a custom
 * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
 * encoded per http://tools.ietf.org/html/rfc3986:
 *    query       = *( pchar / "/" / "?" )
 *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
 *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
 *    pct-encoded   = "%" HEXDIG HEXDIG
 *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
 *                     / "*" / "+" / "," / ";" / "="
 */
function encodeUriQuery(val, pctEncodeSpaces) {
  return encodeURIComponent(val).
             replace(/%40/gi, '@').
             replace(/%3A/gi, ':').
             replace(/%24/g, '$').
             replace(/%2C/gi, ',').
             replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
}


/**
 * @ngdoc directive
 * @name ngApp
 * @module ng
 *
 * @element ANY
 * @param {angular.Module} ngApp an optional application
 *   {@link angular.module module} name to load.
 *
 * @description
 *
 * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive
 * designates the **root element** of the application and is typically placed near the root element
 * of the page - e.g. on the `<body>` or `<html>` tags.
 *
 * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`
 * found in the document will be used to define the root element to auto-bootstrap as an
 * application. To run multiple applications in an HTML document you must manually bootstrap them using
 * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
 *
 * You can specify an **AngularJS module** to be used as the root module for the application.  This
 * module will be loaded into the {@link auto.$injector} when the application is bootstrapped and
 * should contain the application code needed or have dependencies on other modules that will
 * contain the code. See {@link angular.module} for more information.
 *
 * In the example below if the `ngApp` directive were not placed on the `html` element then the
 * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
 * would not be resolved to `3`.
 *
 * `ngApp` is the easiest, and most common, way to bootstrap an application.
 *
 <example module="ngAppDemo">
   <file name="index.html">
   <div ng-controller="ngAppDemoController">
     I can add: {{a}} + {{b}} =  {{ a+b }}
   </div>
   </file>
   <file name="script.js">
   angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
     $scope.a = 1;
     $scope.b = 2;
   });
   </file>
 </example>
 *
 */
function angularInit(element, bootstrap) {
  var elements = [element],
      appElement,
      module,
      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],
      NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;

  function append(element) {
    element && elements.push(element);
  }

  forEach(names, function(name) {
    names[name] = true;
    append(document.getElementById(name));
    name = name.replace(':', '\\:');
    if (element.querySelectorAll) {
      forEach(element.querySelectorAll('.' + name), append);
      forEach(element.querySelectorAll('.' + name + '\\:'), append);
      forEach(element.querySelectorAll('[' + name + ']'), append);
    }
  });

  forEach(elements, function(element) {
    if (!appElement) {
      var className = ' ' + element.className + ' ';
      var match = NG_APP_CLASS_REGEXP.exec(className);
      if (match) {
        appElement = element;
        module = (match[2] || '').replace(/\s+/g, ',');
      } else {
        forEach(element.attributes, function(attr) {
          if (!appElement && names[attr.name]) {
            appElement = element;
            module = attr.value;
          }
        });
      }
    }
  });
  if (appElement) {
    bootstrap(appElement, module ? [module] : []);
  }
}

/**
 * @ngdoc function
 * @name angular.bootstrap
 * @module ng
 * @description
 * Use this function to manually start up angular application.
 *
 * See: {@link guide/bootstrap Bootstrap}
 *
 * Note that ngScenario-based end-to-end tests cannot use this function to bootstrap manually.
 * They must use {@link ng.directive:ngApp ngApp}.
 *
 * Angular will detect if it has been loaded into the browser more than once and only allow the
 * first loaded script to be bootstrapped and will report a warning to the browser console for
 * each of the subsequent scripts. This prevents strange results in applications, where otherwise
 * multiple instances of Angular try to work on the DOM.
 *
 * <example name="multi-bootstrap" module="multi-bootstrap">
 * <file name="index.html">
 * <script src="../../../angular.js"></script>
 * <div ng-controller="BrokenTable">
 *   <table>
 *   <tr>
 *     <th ng-repeat="heading in headings">{{heading}}</th>
 *   </tr>
 *   <tr ng-repeat="filling in fillings">
 *     <td ng-repeat="fill in filling">{{fill}}</td>
 *   </tr>
 * </table>
 * </div>
 * </file>
 * <file name="controller.js">
 * var app = angular.module('multi-bootstrap', [])
 *
 * .controller('BrokenTable', function($scope) {
 *     $scope.headings = ['One', 'Two', 'Three'];
 *     $scope.fillings = [[1, 2, 3], ['A', 'B', 'C'], [7, 8, 9]];
 * });
 * </file>
 * <file name="protractor.js" type="protractor">
 * it('should only insert one table cell for each item in $scope.fillings', function() {
 *  expect(element.all(by.css('td')).count())
 *      .toBe(9);
 * });
 * </file>
 * </example>
 *
 * @param {DOMElement} element DOM element which is the root of angular application.
 * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
 *     Each item in the array should be the name of a predefined module or a (DI annotated)
 *     function that will be invoked by the injector as a run block.
 *     See: {@link angular.module modules}
 * @returns {auto.$injector} Returns the newly created injector for this app.
 */
function bootstrap(element, modules) {
  var doBootstrap = function() {
    element = jqLite(element);

    if (element.injector()) {
      var tag = (element[0] === document) ? 'document' : startingTag(element);
      //Encode angle brackets to prevent input from being sanitized to empty string #8683
      throw ngMinErr(
          'btstrpd',
          "App Already Bootstrapped with this Element '{0}'",
          tag.replace(/</,'&lt;').replace(/>/,'&gt;'));
    }

    modules = modules || [];
    modules.unshift(['$provide', function($provide) {
      $provide.value('$rootElement', element);
    }]);
    modules.unshift('ng');
    var injector = createInjector(modules);
    injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate',
       function(scope, element, compile, injector, animate) {
        scope.$apply(function() {
          element.data('$injector', injector);
          compile(element)(scope);
        });
      }]
    );
    return injector;
  };

  var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;

  if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
    return doBootstrap();
  }

  window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
  angular.resumeBootstrap = function(extraModules) {
    forEach(extraModules, function(module) {
      modules.push(module);
    });
    doBootstrap();
  };
}

var SNAKE_CASE_REGEXP = /[A-Z]/g;
function snake_case(name, separator) {
  separator = separator || '_';
  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
    return (pos ? separator : '') + letter.toLowerCase();
  });
}

function bindJQuery() {
  // bind to jQuery if present;
  jQuery = window.jQuery;
  // Use jQuery if it exists with proper functionality, otherwise default to us.
  // Angular 1.2+ requires jQuery 1.7.1+ for on()/off() support.
  if (jQuery && jQuery.fn.on) {
    jqLite = jQuery;
    extend(jQuery.fn, {
      scope: JQLitePrototype.scope,
      isolateScope: JQLitePrototype.isolateScope,
      controller: JQLitePrototype.controller,
      injector: JQLitePrototype.injector,
      inheritedData: JQLitePrototype.inheritedData
    });
    // Method signature:
    //     jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments)
    jqLitePatchJQueryRemove('remove', true, true, false);
    jqLitePatchJQueryRemove('empty', false, false, false);
    jqLitePatchJQueryRemove('html', false, false, true);
  } else {
    jqLite = JQLite;
  }
  angular.element = jqLite;
}

/**
 * throw error if the argument is falsy.
 */
function assertArg(arg, name, reason) {
  if (!arg) {
    throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
  }
  return arg;
}

function assertArgFn(arg, name, acceptArrayAnnotation) {
  if (acceptArrayAnnotation && isArray(arg)) {
      arg = arg[arg.length - 1];
  }

  assertArg(isFunction(arg), name, 'not a function, got ' +
      (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
  return arg;
}

/**
 * throw error if the name given is hasOwnProperty
 * @param  {String} name    the name to test
 * @param  {String} context the context in which the name is used, such as module or directive
 */
function assertNotHasOwnProperty(name, context) {
  if (name === 'hasOwnProperty') {
    throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context);
  }
}

/**
 * Return the value accessible from the object by path. Any undefined traversals are ignored
 * @param {Object} obj starting object
 * @param {String} path path to traverse
 * @param {boolean} [bindFnToScope=true]
 * @returns {Object} value as accessible by path
 */
//TODO(misko): this function needs to be removed
function getter(obj, path, bindFnToScope) {
  if (!path) return obj;
  var keys = path.split('.');
  var key;
  var lastInstance = obj;
  var len = keys.length;

  for (var i = 0; i < len; i++) {
    key = keys[i];
    if (obj) {
      obj = (lastInstance = obj)[key];
    }
  }
  if (!bindFnToScope && isFunction(obj)) {
    return bind(lastInstance, obj);
  }
  return obj;
}

/**
 * Return the DOM siblings between the first and last node in the given array.
 * @param {Array} array like object
 * @returns {DOMElement} object containing the elements
 */
function getBlockElements(nodes) {
  var startNode = nodes[0],
      endNode = nodes[nodes.length - 1];
  if (startNode === endNode) {
    return jqLite(startNode);
  }

  var element = startNode;
  var elements = [element];

  do {
    element = element.nextSibling;
    if (!element) break;
    elements.push(element);
  } while (element !== endNode);

  return jqLite(elements);
}

/**
 * @ngdoc type
 * @name angular.Module
 * @module ng
 * @description
 *
 * Interface for configuring angular {@link angular.module modules}.
 */

function setupModuleLoader(window) {

  var $injectorMinErr = minErr('$injector');
  var ngMinErr = minErr('ng');

  function ensure(obj, name, factory) {
    return obj[name] || (obj[name] = factory());
  }

  var angular = ensure(window, 'angular', Object);

  // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
  angular.$$minErr = angular.$$minErr || minErr;

  return ensure(angular, 'module', function() {
    /** @type {Object.<string, angular.Module>} */
    var modules = {};

    /**
     * @ngdoc function
     * @name angular.module
     * @module ng
     * @description
     *
     * The `angular.module` is a global place for creating, registering and retrieving Angular
     * modules.
     * All modules (angular core or 3rd party) that should be available to an application must be
     * registered using this mechanism.
     *
     * When passed two or more arguments, a new module is created.  If passed only one argument, an
     * existing module (the name passed as the first argument to `module`) is retrieved.
     *
     *
     * # Module
     *
     * A module is a collection of services, directives, controllers, filters, and configuration information.
     * `angular.module` is used to configure the {@link auto.$injector $injector}.
     *
     * ```js
     * // Create a new module
     * var myModule = angular.module('myModule', []);
     *
     * // register a new service
     * myModule.value('appName', 'MyCoolApp');
     *
     * // configure existing services inside initialization blocks.
     * myModule.config(['$locationProvider', function($locationProvider) {
     *   // Configure existing providers
     *   $locationProvider.hashPrefix('!');
     * }]);
     * ```
     *
     * Then you can create an injector and load your modules like this:
     *
     * ```js
     * var injector = angular.injector(['ng', 'myModule'])
     * ```
     *
     * However it's more likely that you'll just use
     * {@link ng.directive:ngApp ngApp} or
     * {@link angular.bootstrap} to simplify this process for you.
     *
     * @param {!string} name The name of the module to create or retrieve.
     * @param {!Array.<string>=} requires If specified then new module is being created. If
     *        unspecified then the module is being retrieved for further configuration.
     * @param {Function=} configFn Optional configuration function for the module. Same as
     *        {@link angular.Module#config Module#config()}.
     * @returns {module} new module with the {@link angular.Module} api.
     */
    return function module(name, requires, configFn) {
      var assertNotHasOwnProperty = function(name, context) {
        if (name === 'hasOwnProperty') {
          throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
        }
      };

      assertNotHasOwnProperty(name, 'module');
      if (requires && modules.hasOwnProperty(name)) {
        modules[name] = null;
      }
      return ensure(modules, name, function() {
        if (!requires) {
          throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
             "the module name or forgot to load it. If registering a module ensure that you " +
             "specify the dependencies as the second argument.", name);
        }

        /** @type {!Array.<Array.<*>>} */
        var invokeQueue = [];

        /** @type {!Array.<Function>} */
        var runBlocks = [];

        var config = invokeLater('$injector', 'invoke');

        /** @type {angular.Module} */
        var moduleInstance = {
          // Private state
          _invokeQueue: invokeQueue,
          _runBlocks: runBlocks,

          /**
           * @ngdoc property
           * @name angular.Module#requires
           * @module ng
           *
           * @description
           * Holds the list of modules which the injector will load before the current module is
           * loaded.
           */
          requires: requires,

          /**
           * @ngdoc property
           * @name angular.Module#name
           * @module ng
           *
           * @description
           * Name of the module.
           */
          name: name,


          /**
           * @ngdoc method
           * @name angular.Module#provider
           * @module ng
           * @param {string} name service name
           * @param {Function} providerType Construction function for creating new instance of the
           *                                service.
           * @description
           * See {@link auto.$provide#provider $provide.provider()}.
           */
          provider: invokeLater('$provide', 'provider'),

          /**
           * @ngdoc method
           * @name angular.Module#factory
           * @module ng
           * @param {string} name service name
           * @param {Function} providerFunction Function for creating new instance of the service.
           * @description
           * See {@link auto.$provide#factory $provide.factory()}.
           */
          factory: invokeLater('$provide', 'factory'),

          /**
           * @ngdoc method
           * @name angular.Module#service
           * @module ng
           * @param {string} name service name
           * @param {Function} constructor A constructor function that will be instantiated.
           * @description
           * See {@link auto.$provide#service $provide.service()}.
           */
          service: invokeLater('$provide', 'service'),

          /**
           * @ngdoc method
           * @name angular.Module#value
           * @module ng
           * @param {string} name service name
           * @param {*} object Service instance object.
           * @description
           * See {@link auto.$provide#value $provide.value()}.
           */
          value: invokeLater('$provide', 'value'),

          /**
           * @ngdoc method
           * @name angular.Module#constant
           * @module ng
           * @param {string} name constant name
           * @param {*} object Constant value.
           * @description
           * Because the constant are fixed, they get applied before other provide methods.
           * See {@link auto.$provide#constant $provide.constant()}.
           */
          constant: invokeLater('$provide', 'constant', 'unshift'),

          /**
           * @ngdoc method
           * @name angular.Module#animation
           * @module ng
           * @param {string} name animation name
           * @param {Function} animationFactory Factory function for creating new instance of an
           *                                    animation.
           * @description
           *
           * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
           *
           *
           * Defines an animation hook that can be later used with
           * {@link ngAnimate.$animate $animate} service and directives that use this service.
           *
           * ```js
           * module.animation('.animation-name', function($inject1, $inject2) {
           *   return {
           *     eventName : function(element, done) {
           *       //code to run the animation
           *       //once complete, then run done()
           *       return function cancellationFunction(element) {
           *         //code to cancel the animation
           *       }
           *     }
           *   }
           * })
           * ```
           *
           * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and
           * {@link ngAnimate ngAnimate module} for more information.
           */
          animation: invokeLater('$animateProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#filter
           * @module ng
           * @param {string} name Filter name.
           * @param {Function} filterFactory Factory function for creating new instance of filter.
           * @description
           * See {@link ng.$filterProvider#register $filterProvider.register()}.
           */
          filter: invokeLater('$filterProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#controller
           * @module ng
           * @param {string|Object} name Controller name, or an object map of controllers where the
           *    keys are the names and the values are the constructors.
           * @param {Function} constructor Controller constructor function.
           * @description
           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
           */
          controller: invokeLater('$controllerProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#directive
           * @module ng
           * @param {string|Object} name Directive name, or an object map of directives where the
           *    keys are the names and the values are the factories.
           * @param {Function} directiveFactory Factory function for creating new instance of
           * directives.
           * @description
           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
           */
          directive: invokeLater('$compileProvider', 'directive'),

          /**
           * @ngdoc method
           * @name angular.Module#config
           * @module ng
           * @param {Function} configFn Execute this function on module load. Useful for service
           *    configuration.
           * @description
           * Use this method to register work which needs to be performed on module loading.
           * For more about how to configure services, see
           * {@link providers#providers_provider-recipe Provider Recipe}.
           */
          config: config,

          /**
           * @ngdoc method
           * @name angular.Module#run
           * @module ng
           * @param {Function} initializationFn Execute this function after injector creation.
           *    Useful for application initialization.
           * @description
           * Use this method to register work which should be performed when the injector is done
           * loading all modules.
           */
          run: function(block) {
            runBlocks.push(block);
            return this;
          }
        };

        if (configFn) {
          config(configFn);
        }

        return  moduleInstance;

        /**
         * @param {string} provider
         * @param {string} method
         * @param {String=} insertMethod
         * @returns {angular.Module}
         */
        function invokeLater(provider, method, insertMethod) {
          return function() {
            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
            return moduleInstance;
          };
        }
      });
    };
  });

}

/* global angularModule: true,
  version: true,

  $LocaleProvider,
  $CompileProvider,

    htmlAnchorDirective,
    inputDirective,
    inputDirective,
    formDirective,
    scriptDirective,
    selectDirective,
    styleDirective,
    optionDirective,
    ngBindDirective,
    ngBindHtmlDirective,
    ngBindTemplateDirective,
    ngClassDirective,
    ngClassEvenDirective,
    ngClassOddDirective,
    ngCspDirective,
    ngCloakDirective,
    ngControllerDirective,
    ngFormDirective,
    ngHideDirective,
    ngIfDirective,
    ngIncludeDirective,
    ngIncludeFillContentDirective,
    ngInitDirective,
    ngNonBindableDirective,
    ngPluralizeDirective,
    ngRepeatDirective,
    ngShowDirective,
    ngStyleDirective,
    ngSwitchDirective,
    ngSwitchWhenDirective,
    ngSwitchDefaultDirective,
    ngOptionsDirective,
    ngTranscludeDirective,
    ngModelDirective,
    ngListDirective,
    ngChangeDirective,
    requiredDirective,
    requiredDirective,
    ngValueDirective,
    ngAttributeAliasDirectives,
    ngEventDirectives,

    $AnchorScrollProvider,
    $AnimateProvider,
    $BrowserProvider,
    $CacheFactoryProvider,
    $ControllerProvider,
    $DocumentProvider,
    $ExceptionHandlerProvider,
    $FilterProvider,
    $InterpolateProvider,
    $IntervalProvider,
    $HttpProvider,
    $HttpBackendProvider,
    $LocationProvider,
    $LogProvider,
    $ParseProvider,
    $RootScopeProvider,
    $QProvider,
    $$SanitizeUriProvider,
    $SceProvider,
    $SceDelegateProvider,
    $SnifferProvider,
    $TemplateCacheProvider,
    $TimeoutProvider,
    $$RAFProvider,
    $$AsyncCallbackProvider,
    $WindowProvider
*/


/**
 * @ngdoc object
 * @name angular.version
 * @module ng
 * @description
 * An object that contains information about the current AngularJS version. This object has the
 * following properties:
 *
 * - `full` – `{string}` – Full version string, such as "0.9.18".
 * - `major` – `{number}` – Major version number, such as "0".
 * - `minor` – `{number}` – Minor version number, such as "9".
 * - `dot` – `{number}` – Dot version number, such as "18".
 * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
 */
var version = {
  full: '1.2.28',    // all of these placeholder strings will be replaced by grunt's
  major: 1,    // package task
  minor: 2,
  dot: 28,
  codeName: 'finnish-disembarkation'
};


function publishExternalAPI(angular){
  extend(angular, {
    'bootstrap': bootstrap,
    'copy': copy,
    'extend': extend,
    'equals': equals,
    'element': jqLite,
    'forEach': forEach,
    'injector': createInjector,
    'noop': noop,
    'bind': bind,
    'toJson': toJson,
    'fromJson': fromJson,
    'identity': identity,
    'isUndefined': isUndefined,
    'isDefined': isDefined,
    'isString': isString,
    'isFunction': isFunction,
    'isObject': isObject,
    'isNumber': isNumber,
    'isElement': isElement,
    'isArray': isArray,
    'version': version,
    'isDate': isDate,
    'lowercase': lowercase,
    'uppercase': uppercase,
    'callbacks': {counter: 0},
    '$$minErr': minErr,
    '$$csp': csp
  });

  angularModule = setupModuleLoader(window);
  try {
    angularModule('ngLocale');
  } catch (e) {
    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
  }

  angularModule('ng', ['ngLocale'], ['$provide',
    function ngModule($provide) {
      // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
      $provide.provider({
        $$sanitizeUri: $$SanitizeUriProvider
      });
      $provide.provider('$compile', $CompileProvider).
        directive({
            a: htmlAnchorDirective,
            input: inputDirective,
            textarea: inputDirective,
            form: formDirective,
            script: scriptDirective,
            select: selectDirective,
            style: styleDirective,
            option: optionDirective,
            ngBind: ngBindDirective,
            ngBindHtml: ngBindHtmlDirective,
            ngBindTemplate: ngBindTemplateDirective,
            ngClass: ngClassDirective,
            ngClassEven: ngClassEvenDirective,
            ngClassOdd: ngClassOddDirective,
            ngCloak: ngCloakDirective,
            ngController: ngControllerDirective,
            ngForm: ngFormDirective,
            ngHide: ngHideDirective,
            ngIf: ngIfDirective,
            ngInclude: ngIncludeDirective,
            ngInit: ngInitDirective,
            ngNonBindable: ngNonBindableDirective,
            ngPluralize: ngPluralizeDirective,
            ngRepeat: ngRepeatDirective,
            ngShow: ngShowDirective,
            ngStyle: ngStyleDirective,
            ngSwitch: ngSwitchDirective,
            ngSwitchWhen: ngSwitchWhenDirective,
            ngSwitchDefault: ngSwitchDefaultDirective,
            ngOptions: ngOptionsDirective,
            ngTransclude: ngTranscludeDirective,
            ngModel: ngModelDirective,
            ngList: ngListDirective,
            ngChange: ngChangeDirective,
            required: requiredDirective,
            ngRequired: requiredDirective,
            ngValue: ngValueDirective
        }).
        directive({
          ngInclude: ngIncludeFillContentDirective
        }).
        directive(ngAttributeAliasDirectives).
        directive(ngEventDirectives);
      $provide.provider({
        $anchorScroll: $AnchorScrollProvider,
        $animate: $AnimateProvider,
        $browser: $BrowserProvider,
        $cacheFactory: $CacheFactoryProvider,
        $controller: $ControllerProvider,
        $document: $DocumentProvider,
        $exceptionHandler: $ExceptionHandlerProvider,
        $filter: $FilterProvider,
        $interpolate: $InterpolateProvider,
        $interval: $IntervalProvider,
        $http: $HttpProvider,
        $httpBackend: $HttpBackendProvider,
        $location: $LocationProvider,
        $log: $LogProvider,
        $parse: $ParseProvider,
        $rootScope: $RootScopeProvider,
        $q: $QProvider,
        $sce: $SceProvider,
        $sceDelegate: $SceDelegateProvider,
        $sniffer: $SnifferProvider,
        $templateCache: $TemplateCacheProvider,
        $timeout: $TimeoutProvider,
        $window: $WindowProvider,
        $$rAF: $$RAFProvider,
        $$asyncCallback : $$AsyncCallbackProvider
      });
    }
  ]);
}

/* global JQLitePrototype: true,
  addEventListenerFn: true,
  removeEventListenerFn: true,
  BOOLEAN_ATTR: true
*/

//////////////////////////////////
//JQLite
//////////////////////////////////

/**
 * @ngdoc function
 * @name angular.element
 * @module ng
 * @kind function
 *
 * @description
 * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
 *
 * If jQuery is available, `angular.element` is an alias for the
 * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
 * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite."
 *
 * <div class="alert alert-success">jqLite is a tiny, API-compatible subset of jQuery that allows
 * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
 * commonly needed functionality with the goal of having a very small footprint.</div>
 *
 * To use jQuery, simply load it before `DOMContentLoaded` event fired.
 *
 * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
 * jqLite; they are never raw DOM references.</div>
 *
 * ## Angular's jqLite
 * jqLite provides only the following jQuery methods:
 *
 * - [`addClass()`](http://api.jquery.com/addClass/)
 * - [`after()`](http://api.jquery.com/after/)
 * - [`append()`](http://api.jquery.com/append/)
 * - [`attr()`](http://api.jquery.com/attr/)
 * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData
 * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
 * - [`clone()`](http://api.jquery.com/clone/)
 * - [`contents()`](http://api.jquery.com/contents/)
 * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyles()`
 * - [`data()`](http://api.jquery.com/data/)
 * - [`empty()`](http://api.jquery.com/empty/)
 * - [`eq()`](http://api.jquery.com/eq/)
 * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
 * - [`hasClass()`](http://api.jquery.com/hasClass/)
 * - [`html()`](http://api.jquery.com/html/)
 * - [`next()`](http://api.jquery.com/next/) - Does not support selectors
 * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
 * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors
 * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
 * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
 * - [`prepend()`](http://api.jquery.com/prepend/)
 * - [`prop()`](http://api.jquery.com/prop/)
 * - [`ready()`](http://api.jquery.com/ready/)
 * - [`remove()`](http://api.jquery.com/remove/)
 * - [`removeAttr()`](http://api.jquery.com/removeAttr/)
 * - [`removeClass()`](http://api.jquery.com/removeClass/)
 * - [`removeData()`](http://api.jquery.com/removeData/)
 * - [`replaceWith()`](http://api.jquery.com/replaceWith/)
 * - [`text()`](http://api.jquery.com/text/)
 * - [`toggleClass()`](http://api.jquery.com/toggleClass/)
 * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
 * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces
 * - [`val()`](http://api.jquery.com/val/)
 * - [`wrap()`](http://api.jquery.com/wrap/)
 *
 * ## jQuery/jqLite Extras
 * Angular also provides the following additional methods and events to both jQuery and jqLite:
 *
 * ### Events
 * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event
 *    on all DOM nodes being removed.  This can be used to clean up any 3rd party bindings to the DOM
 *    element before it is removed.
 *
 * ### Methods
 * - `controller(name)` - retrieves the controller of the current element or its parent. By default
 *   retrieves controller associated with the `ngController` directive. If `name` is provided as
 *   camelCase directive name, then the controller for this directive will be retrieved (e.g.
 *   `'ngModel'`).
 * - `injector()` - retrieves the injector of the current element or its parent.
 * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current
 *   element or its parent.
 * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the
 *   current element. This getter should be used only on elements that contain a directive which starts a new isolate
 *   scope. Calling `scope()` on this element always returns the original non-isolate scope.
 * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
 *   parent element is reached.
 *
 * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
 * @returns {Object} jQuery object.
 */

JQLite.expando = 'ng339';

var jqCache = JQLite.cache = {},
    jqId = 1,
    addEventListenerFn = (window.document.addEventListener
      ? function(element, type, fn) {element.addEventListener(type, fn, false);}
      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),
    removeEventListenerFn = (window.document.removeEventListener
      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }
      : function(element, type, fn) {element.detachEvent('on' + type, fn); });

/*
 * !!! This is an undocumented "private" function !!!
 */
var jqData = JQLite._data = function(node) {
  //jQuery always returns an object on cache miss
  return this.cache[node[this.expando]] || {};
};

function jqNextId() { return ++jqId; }


var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
var MOZ_HACK_REGEXP = /^moz([A-Z])/;
var jqLiteMinErr = minErr('jqLite');

/**
 * Converts snake_case to camelCase.
 * Also there is special case for Moz prefix starting with upper case letter.
 * @param name Name to normalize
 */
function camelCase(name) {
  return name.
    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
      return offset ? letter.toUpperCase() : letter;
    }).
    replace(MOZ_HACK_REGEXP, 'Moz$1');
}

/////////////////////////////////////////////
// jQuery mutation patch
//
// In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a
// $destroy event on all DOM nodes being removed.
//
/////////////////////////////////////////////

function jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments) {
  var originalJqFn = jQuery.fn[name];
  originalJqFn = originalJqFn.$original || originalJqFn;
  removePatch.$original = originalJqFn;
  jQuery.fn[name] = removePatch;

  function removePatch(param) {
    // jshint -W040
    var list = filterElems && param ? [this.filter(param)] : [this],
        fireEvent = dispatchThis,
        set, setIndex, setLength,
        element, childIndex, childLength, children;

    if (!getterIfNoArguments || param != null) {
      while(list.length) {
        set = list.shift();
        for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {
          element = jqLite(set[setIndex]);
          if (fireEvent) {
            element.triggerHandler('$destroy');
          } else {
            fireEvent = !fireEvent;
          }
          for(childIndex = 0, childLength = (children = element.children()).length;
              childIndex < childLength;
              childIndex++) {
            list.push(jQuery(children[childIndex]));
          }
        }
      }
    }
    return originalJqFn.apply(this, arguments);
  }
}

var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
var HTML_REGEXP = /<|&#?\w+;/;
var TAG_NAME_REGEXP = /<([\w:]+)/;
var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;

var wrapMap = {
  'option': [1, '<select multiple="multiple">', '</select>'],

  'thead': [1, '<table>', '</table>'],
  'col': [2, '<table><colgroup>', '</colgroup></table>'],
  'tr': [2, '<table><tbody>', '</tbody></table>'],
  'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],
  '_default': [0, "", ""]
};

wrapMap.optgroup = wrapMap.option;
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;

function jqLiteIsTextNode(html) {
  return !HTML_REGEXP.test(html);
}

function jqLiteBuildFragment(html, context) {
  var elem, tmp, tag, wrap,
      fragment = context.createDocumentFragment(),
      nodes = [], i, j, jj;

  if (jqLiteIsTextNode(html)) {
    // Convert non-html into a text node
    nodes.push(context.createTextNode(html));
  } else {
    tmp = fragment.appendChild(context.createElement('div'));
    // Convert html into DOM nodes
    tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
    wrap = wrapMap[tag] || wrapMap._default;
    tmp.innerHTML = '<div>&#160;</div>' +
      wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
    tmp.removeChild(tmp.firstChild);

    // Descend through wrappers to the right content
    i = wrap[0];
    while (i--) {
      tmp = tmp.lastChild;
    }

    for (j=0, jj=tmp.childNodes.length; j<jj; ++j) nodes.push(tmp.childNodes[j]);

    tmp = fragment.firstChild;
    tmp.textContent = "";
  }

  // Remove wrapper from fragment
  fragment.textContent = "";
  fragment.innerHTML = ""; // Clear inner HTML
  return nodes;
}

function jqLiteParseHTML(html, context) {
  context = context || document;
  var parsed;

  if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
    return [context.createElement(parsed[1])];
  }

  return jqLiteBuildFragment(html, context);
}

/////////////////////////////////////////////
function JQLite(element) {
  if (element instanceof JQLite) {
    return element;
  }
  if (isString(element)) {
    element = trim(element);
  }
  if (!(this instanceof JQLite)) {
    if (isString(element) && element.charAt(0) != '<') {
      throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
    }
    return new JQLite(element);
  }

  if (isString(element)) {
    jqLiteAddNodes(this, jqLiteParseHTML(element));
    var fragment = jqLite(document.createDocumentFragment());
    fragment.append(this);
  } else {
    jqLiteAddNodes(this, element);
  }
}

function jqLiteClone(element) {
  return element.cloneNode(true);
}

function jqLiteDealoc(element){
  jqLiteRemoveData(element);
  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {
    jqLiteDealoc(children[i]);
  }
}

function jqLiteOff(element, type, fn, unsupported) {
  if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');

  var events = jqLiteExpandoStore(element, 'events'),
      handle = jqLiteExpandoStore(element, 'handle');

  if (!handle) return; //no listeners registered

  if (isUndefined(type)) {
    forEach(events, function(eventHandler, type) {
      removeEventListenerFn(element, type, eventHandler);
      delete events[type];
    });
  } else {
    forEach(type.split(' '), function(type) {
      if (isUndefined(fn)) {
        removeEventListenerFn(element, type, events[type]);
        delete events[type];
      } else {
        arrayRemove(events[type] || [], fn);
      }
    });
  }
}

function jqLiteRemoveData(element, name) {
  var expandoId = element.ng339,
      expandoStore = jqCache[expandoId];

  if (expandoStore) {
    if (name) {
      delete jqCache[expandoId].data[name];
      return;
    }

    if (expandoStore.handle) {
      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');
      jqLiteOff(element);
    }
    delete jqCache[expandoId];
    element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it
  }
}

function jqLiteExpandoStore(element, key, value) {
  var expandoId = element.ng339,
      expandoStore = jqCache[expandoId || -1];

  if (isDefined(value)) {
    if (!expandoStore) {
      element.ng339 = expandoId = jqNextId();
      expandoStore = jqCache[expandoId] = {};
    }
    expandoStore[key] = value;
  } else {
    return expandoStore && expandoStore[key];
  }
}

function jqLiteData(element, key, value) {
  var data = jqLiteExpandoStore(element, 'data'),
      isSetter = isDefined(value),
      keyDefined = !isSetter && isDefined(key),
      isSimpleGetter = keyDefined && !isObject(key);

  if (!data && !isSimpleGetter) {
    jqLiteExpandoStore(element, 'data', data = {});
  }

  if (isSetter) {
    data[key] = value;
  } else {
    if (keyDefined) {
      if (isSimpleGetter) {
        // don't create data in this case.
        return data && data[key];
      } else {
        extend(data, key);
      }
    } else {
      return data;
    }
  }
}

function jqLiteHasClass(element, selector) {
  if (!element.getAttribute) return false;
  return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
      indexOf( " " + selector + " " ) > -1);
}

function jqLiteRemoveClass(element, cssClasses) {
  if (cssClasses && element.setAttribute) {
    forEach(cssClasses.split(' '), function(cssClass) {
      element.setAttribute('class', trim(
          (" " + (element.getAttribute('class') || '') + " ")
          .replace(/[\n\t]/g, " ")
          .replace(" " + trim(cssClass) + " ", " "))
      );
    });
  }
}

function jqLiteAddClass(element, cssClasses) {
  if (cssClasses && element.setAttribute) {
    var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
                            .replace(/[\n\t]/g, " ");

    forEach(cssClasses.split(' '), function(cssClass) {
      cssClass = trim(cssClass);
      if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
        existingClasses += cssClass + ' ';
      }
    });

    element.setAttribute('class', trim(existingClasses));
  }
}

function jqLiteAddNodes(root, elements) {
  if (elements) {
    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))
      ? elements
      : [ elements ];
    for(var i=0; i < elements.length; i++) {
      root.push(elements[i]);
    }
  }
}

function jqLiteController(element, name) {
  return jqLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');
}

function jqLiteInheritedData(element, name, value) {
  // if element is the document object work with the html element instead
  // this makes $(document).scope() possible
  if(element.nodeType == 9) {
    element = element.documentElement;
  }
  var names = isArray(name) ? name : [name];

  while (element) {
    for (var i = 0, ii = names.length; i < ii; i++) {
      if ((value = jqLite.data(element, names[i])) !== undefined) return value;
    }

    // If dealing with a document fragment node with a host element, and no parent, use the host
    // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
    // to lookup parent controllers.
    element = element.parentNode || (element.nodeType === 11 && element.host);
  }
}

function jqLiteEmpty(element) {
  for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
    jqLiteDealoc(childNodes[i]);
  }
  while (element.firstChild) {
    element.removeChild(element.firstChild);
  }
}

//////////////////////////////////////////
// Functions which are declared directly.
//////////////////////////////////////////
var JQLitePrototype = JQLite.prototype = {
  ready: function(fn) {
    var fired = false;

    function trigger() {
      if (fired) return;
      fired = true;
      fn();
    }

    // check if document already is loaded
    if (document.readyState === 'complete'){
      setTimeout(trigger);
    } else {
      this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
      // we can not use jqLite since we are not done loading and jQuery could be loaded later.
      // jshint -W064
      JQLite(window).on('load', trigger); // fallback to window.onload for others
      // jshint +W064
    }
  },
  toString: function() {
    var value = [];
    forEach(this, function(e){ value.push('' + e);});
    return '[' + value.join(', ') + ']';
  },

  eq: function(index) {
      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
  },

  length: 0,
  push: push,
  sort: [].sort,
  splice: [].splice
};

//////////////////////////////////////////
// Functions iterating getter/setters.
// these functions return self on setter and
// value on get.
//////////////////////////////////////////
var BOOLEAN_ATTR = {};
forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
  BOOLEAN_ATTR[lowercase(value)] = value;
});
var BOOLEAN_ELEMENTS = {};
forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
  BOOLEAN_ELEMENTS[uppercase(value)] = true;
});

function getBooleanAttrName(element, name) {
  // check dom last since we will most likely fail on name
  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];

  // booleanAttr is here twice to minimize DOM access
  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
}

forEach({
  data: jqLiteData,
  removeData: jqLiteRemoveData
}, function(fn, name) {
  JQLite[name] = fn;
});

forEach({
  data: jqLiteData,
  inheritedData: jqLiteInheritedData,

  scope: function(element) {
    // Can't use jqLiteData here directly so we stay compatible with jQuery!
    return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);
  },

  isolateScope: function(element) {
    // Can't use jqLiteData here directly so we stay compatible with jQuery!
    return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');
  },

  controller: jqLiteController,

  injector: function(element) {
    return jqLiteInheritedData(element, '$injector');
  },

  removeAttr: function(element,name) {
    element.removeAttribute(name);
  },

  hasClass: jqLiteHasClass,

  css: function(element, name, value) {
    name = camelCase(name);

    if (isDefined(value)) {
      element.style[name] = value;
    } else {
      var val;

      if (msie <= 8) {
        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why
        val = element.currentStyle && element.currentStyle[name];
        if (val === '') val = 'auto';
      }

      val = val || element.style[name];

      if (msie <= 8) {
        // jquery weirdness :-/
        val = (val === '') ? undefined : val;
      }

      return  val;
    }
  },

  attr: function(element, name, value){
    var lowercasedName = lowercase(name);
    if (BOOLEAN_ATTR[lowercasedName]) {
      if (isDefined(value)) {
        if (!!value) {
          element[name] = true;
          element.setAttribute(name, lowercasedName);
        } else {
          element[name] = false;
          element.removeAttribute(lowercasedName);
        }
      } else {
        return (element[name] ||
                 (element.attributes.getNamedItem(name)|| noop).specified)
               ? lowercasedName
               : undefined;
      }
    } else if (isDefined(value)) {
      element.setAttribute(name, value);
    } else if (element.getAttribute) {
      // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
      // some elements (e.g. Document) don't have get attribute, so return undefined
      var ret = element.getAttribute(name, 2);
      // normalize non-existing attributes to undefined (as jQuery)
      return ret === null ? undefined : ret;
    }
  },

  prop: function(element, name, value) {
    if (isDefined(value)) {
      element[name] = value;
    } else {
      return element[name];
    }
  },

  text: (function() {
    var NODE_TYPE_TEXT_PROPERTY = [];
    if (msie < 9) {
      NODE_TYPE_TEXT_PROPERTY[1] = 'innerText';    /** Element **/
      NODE_TYPE_TEXT_PROPERTY[3] = 'nodeValue';    /** Text **/
    } else {
      NODE_TYPE_TEXT_PROPERTY[1] =                 /** Element **/
      NODE_TYPE_TEXT_PROPERTY[3] = 'textContent';  /** Text **/
    }
    getText.$dv = '';
    return getText;

    function getText(element, value) {
      var textProp = NODE_TYPE_TEXT_PROPERTY[element.nodeType];
      if (isUndefined(value)) {
        return textProp ? element[textProp] : '';
      }
      element[textProp] = value;
    }
  })(),

  val: function(element, value) {
    if (isUndefined(value)) {
      if (nodeName_(element) === 'SELECT' && element.multiple) {
        var result = [];
        forEach(element.options, function (option) {
          if (option.selected) {
            result.push(option.value || option.text);
          }
        });
        return result.length === 0 ? null : result;
      }
      return element.value;
    }
    element.value = value;
  },

  html: function(element, value) {
    if (isUndefined(value)) {
      return element.innerHTML;
    }
    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
      jqLiteDealoc(childNodes[i]);
    }
    element.innerHTML = value;
  },

  empty: jqLiteEmpty
}, function(fn, name){
  /**
   * Properties: writes return selection, reads return first value
   */
  JQLite.prototype[name] = function(arg1, arg2) {
    var i, key;
    var nodeCount = this.length;

    // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
    // in a way that survives minification.
    // jqLiteEmpty takes no arguments but is a setter.
    if (fn !== jqLiteEmpty &&
        (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {
      if (isObject(arg1)) {

        // we are a write, but the object properties are the key/values
        for (i = 0; i < nodeCount; i++) {
          if (fn === jqLiteData) {
            // data() takes the whole object in jQuery
            fn(this[i], arg1);
          } else {
            for (key in arg1) {
              fn(this[i], key, arg1[key]);
            }
          }
        }
        // return self for chaining
        return this;
      } else {
        // we are a read, so read the first child.
        // TODO: do we still need this?
        var value = fn.$dv;
        // Only if we have $dv do we iterate over all, otherwise it is just the first element.
        var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;
        for (var j = 0; j < jj; j++) {
          var nodeValue = fn(this[j], arg1, arg2);
          value = value ? value + nodeValue : nodeValue;
        }
        return value;
      }
    } else {
      // we are a write, so apply to all children
      for (i = 0; i < nodeCount; i++) {
        fn(this[i], arg1, arg2);
      }
      // return self for chaining
      return this;
    }
  };
});

function createEventHandler(element, events) {
  var eventHandler = function (event, type) {
    if (!event.preventDefault) {
      event.preventDefault = function() {
        event.returnValue = false; //ie
      };
    }

    if (!event.stopPropagation) {
      event.stopPropagation = function() {
        event.cancelBubble = true; //ie
      };
    }

    if (!event.target) {
      event.target = event.srcElement || document;
    }

    if (isUndefined(event.defaultPrevented)) {
      var prevent = event.preventDefault;
      event.preventDefault = function() {
        event.defaultPrevented = true;
        prevent.call(event);
      };
      event.defaultPrevented = false;
    }

    event.isDefaultPrevented = function() {
      return event.defaultPrevented || event.returnValue === false;
    };

    // Copy event handlers in case event handlers array is modified during execution.
    var eventHandlersCopy = shallowCopy(events[type || event.type] || []);

    forEach(eventHandlersCopy, function(fn) {
      fn.call(element, event);
    });

    // Remove monkey-patched methods (IE),
    // as they would cause memory leaks in IE8.
    if (msie <= 8) {
      // IE7/8 does not allow to delete property on native object
      event.preventDefault = null;
      event.stopPropagation = null;
      event.isDefaultPrevented = null;
    } else {
      // It shouldn't affect normal browsers (native methods are defined on prototype).
      delete event.preventDefault;
      delete event.stopPropagation;
      delete event.isDefaultPrevented;
    }
  };
  eventHandler.elem = element;
  return eventHandler;
}

//////////////////////////////////////////
// Functions iterating traversal.
// These functions chain results into a single
// selector.
//////////////////////////////////////////
forEach({
  removeData: jqLiteRemoveData,

  dealoc: jqLiteDealoc,

  on: function onFn(element, type, fn, unsupported){
    if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');

    var events = jqLiteExpandoStore(element, 'events'),
        handle = jqLiteExpandoStore(element, 'handle');

    if (!events) jqLiteExpandoStore(element, 'events', events = {});
    if (!handle) jqLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));

    forEach(type.split(' '), function(type){
      var eventFns = events[type];

      if (!eventFns) {
        if (type == 'mouseenter' || type == 'mouseleave') {
          var contains = document.body.contains || document.body.compareDocumentPosition ?
          function( a, b ) {
            // jshint bitwise: false
            var adown = a.nodeType === 9 ? a.documentElement : a,
            bup = b && b.parentNode;
            return a === bup || !!( bup && bup.nodeType === 1 && (
              adown.contains ?
              adown.contains( bup ) :
              a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
              ));
            } :
            function( a, b ) {
              if ( b ) {
                while ( (b = b.parentNode) ) {
                  if ( b === a ) {
                    return true;
                  }
                }
              }
              return false;
            };

          events[type] = [];

          // Refer to jQuery's implementation of mouseenter & mouseleave
          // Read about mouseenter and mouseleave:
          // http://www.quirksmode.org/js/events_mouse.html#link8
          var eventmap = { mouseleave : "mouseout", mouseenter : "mouseover"};

          onFn(element, eventmap[type], function(event) {
            var target = this, related = event.relatedTarget;
            // For mousenter/leave call the handler if related is outside the target.
            // NB: No relatedTarget if the mouse left/entered the browser window
            if ( !related || (related !== target && !contains(target, related)) ){
              handle(event, type);
            }
          });

        } else {
          addEventListenerFn(element, type, handle);
          events[type] = [];
        }
        eventFns = events[type];
      }
      eventFns.push(fn);
    });
  },

  off: jqLiteOff,

  one: function(element, type, fn) {
    element = jqLite(element);

    //add the listener twice so that when it is called
    //you can remove the original function and still be
    //able to call element.off(ev, fn) normally
    element.on(type, function onFn() {
      element.off(type, fn);
      element.off(type, onFn);
    });
    element.on(type, fn);
  },

  replaceWith: function(element, replaceNode) {
    var index, parent = element.parentNode;
    jqLiteDealoc(element);
    forEach(new JQLite(replaceNode), function(node){
      if (index) {
        parent.insertBefore(node, index.nextSibling);
      } else {
        parent.replaceChild(node, element);
      }
      index = node;
    });
  },

  children: function(element) {
    var children = [];
    forEach(element.childNodes, function(element){
      if (element.nodeType === 1)
        children.push(element);
    });
    return children;
  },

  contents: function(element) {
    return element.contentDocument || element.childNodes || [];
  },

  append: function(element, node) {
    forEach(new JQLite(node), function(child){
      if (element.nodeType === 1 || element.nodeType === 11) {
        element.appendChild(child);
      }
    });
  },

  prepend: function(element, node) {
    if (element.nodeType === 1) {
      var index = element.firstChild;
      forEach(new JQLite(node), function(child){
        element.insertBefore(child, index);
      });
    }
  },

  wrap: function(element, wrapNode) {
    wrapNode = jqLite(wrapNode)[0];
    var parent = element.parentNode;
    if (parent) {
      parent.replaceChild(wrapNode, element);
    }
    wrapNode.appendChild(element);
  },

  remove: function(element) {
    jqLiteDealoc(element);
    var parent = element.parentNode;
    if (parent) parent.removeChild(element);
  },

  after: function(element, newElement) {
    var index = element, parent = element.parentNode;
    forEach(new JQLite(newElement), function(node){
      parent.insertBefore(node, index.nextSibling);
      index = node;
    });
  },

  addClass: jqLiteAddClass,
  removeClass: jqLiteRemoveClass,

  toggleClass: function(element, selector, condition) {
    if (selector) {
      forEach(selector.split(' '), function(className){
        var classCondition = condition;
        if (isUndefined(classCondition)) {
          classCondition = !jqLiteHasClass(element, className);
        }
        (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
      });
    }
  },

  parent: function(element) {
    var parent = element.parentNode;
    return parent && parent.nodeType !== 11 ? parent : null;
  },

  next: function(element) {
    if (element.nextElementSibling) {
      return element.nextElementSibling;
    }

    // IE8 doesn't have nextElementSibling
    var elm = element.nextSibling;
    while (elm != null && elm.nodeType !== 1) {
      elm = elm.nextSibling;
    }
    return elm;
  },

  find: function(element, selector) {
    if (element.getElementsByTagName) {
      return element.getElementsByTagName(selector);
    } else {
      return [];
    }
  },

  clone: jqLiteClone,

  triggerHandler: function(element, event, extraParameters) {

    var dummyEvent, eventFnsCopy, handlerArgs;
    var eventName = event.type || event;
    var eventFns = (jqLiteExpandoStore(element, 'events') || {})[eventName];

    if (eventFns) {

      // Create a dummy event to pass to the handlers
      dummyEvent = {
        preventDefault: function() { this.defaultPrevented = true; },
        isDefaultPrevented: function() { return this.defaultPrevented === true; },
        stopPropagation: noop,
        type: eventName,
        target: element
      };

      // If a custom event was provided then extend our dummy event with it
      if (event.type) {
        dummyEvent = extend(dummyEvent, event);
      }

      // Copy event handlers in case event handlers array is modified during execution.
      eventFnsCopy = shallowCopy(eventFns);
      handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];

      forEach(eventFnsCopy, function(fn) {
        fn.apply(element, handlerArgs);
      });

    }
  }
}, function(fn, name){
  /**
   * chaining functions
   */
  JQLite.prototype[name] = function(arg1, arg2, arg3) {
    var value;
    for(var i=0; i < this.length; i++) {
      if (isUndefined(value)) {
        value = fn(this[i], arg1, arg2, arg3);
        if (isDefined(value)) {
          // any function which returns a value needs to be wrapped
          value = jqLite(value);
        }
      } else {
        jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
      }
    }
    return isDefined(value) ? value : this;
  };

  // bind legacy bind/unbind to on/off
  JQLite.prototype.bind = JQLite.prototype.on;
  JQLite.prototype.unbind = JQLite.prototype.off;
});

/**
 * Computes a hash of an 'obj'.
 * Hash of a:
 *  string is string
 *  number is number as string
 *  object is either result of calling $$hashKey function on the object or uniquely generated id,
 *         that is also assigned to the $$hashKey property of the object.
 *
 * @param obj
 * @returns {string} hash string such that the same input will have the same hash string.
 *         The resulting string key is in 'type:hashKey' format.
 */
function hashKey(obj, nextUidFn) {
  var objType = typeof obj,
      key;

  if (objType == 'function' || (objType == 'object' && obj !== null)) {
    if (typeof (key = obj.$$hashKey) == 'function') {
      // must invoke on object to keep the right this
      key = obj.$$hashKey();
    } else if (key === undefined) {
      key = obj.$$hashKey = (nextUidFn || nextUid)();
    }
  } else {
    key = obj;
  }

  return objType + ':' + key;
}

/**
 * HashMap which can use objects as keys
 */
function HashMap(array, isolatedUid) {
  if (isolatedUid) {
    var uid = 0;
    this.nextUid = function() {
      return ++uid;
    };
  }
  forEach(array, this.put, this);
}
HashMap.prototype = {
  /**
   * Store key value pair
   * @param key key to store can be any type
   * @param value value to store can be any type
   */
  put: function(key, value) {
    this[hashKey(key, this.nextUid)] = value;
  },

  /**
   * @param key
   * @returns {Object} the value for the key
   */
  get: function(key) {
    return this[hashKey(key, this.nextUid)];
  },

  /**
   * Remove the key/value pair
   * @param key
   */
  remove: function(key) {
    var value = this[key = hashKey(key, this.nextUid)];
    delete this[key];
    return value;
  }
};

/**
 * @ngdoc function
 * @module ng
 * @name angular.injector
 * @kind function
 *
 * @description
 * Creates an injector object that can be used for retrieving services as well as for
 * dependency injection (see {@link guide/di dependency injection}).
 *

 * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
 *        {@link angular.module}. The `ng` module must be explicitly added.
 * @returns {injector} Injector object. See {@link auto.$injector $injector}.
 *
 * @example
 * Typical usage
 * ```js
 *   // create an injector
 *   var $injector = angular.injector(['ng']);
 *
 *   // use the injector to kick off your application
 *   // use the type inference to auto inject arguments, or use implicit injection
 *   $injector.invoke(function($rootScope, $compile, $document){
 *     $compile($document)($rootScope);
 *     $rootScope.$digest();
 *   });
 * ```
 *
 * Sometimes you want to get access to the injector of a currently running Angular app
 * from outside Angular. Perhaps, you want to inject and compile some markup after the
 * application has been bootstrapped. You can do this using the extra `injector()` added
 * to JQuery/jqLite elements. See {@link angular.element}.
 *
 * *This is fairly rare but could be the case if a third party library is injecting the
 * markup.*
 *
 * In the following example a new block of HTML containing a `ng-controller`
 * directive is added to the end of the document body by JQuery. We then compile and link
 * it into the current AngularJS scope.
 *
 * ```js
 * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
 * $(document.body).append($div);
 *
 * angular.element(document).injector().invoke(function($compile) {
 *   var scope = angular.element($div).scope();
 *   $compile($div)(scope);
 * });
 * ```
 */


/**
 * @ngdoc module
 * @name auto
 * @description
 *
 * Implicit module which gets automatically added to each {@link auto.$injector $injector}.
 */

var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var $injectorMinErr = minErr('$injector');
function annotate(fn) {
  var $inject,
      fnText,
      argDecl,
      last;

  if (typeof fn === 'function') {
    if (!($inject = fn.$inject)) {
      $inject = [];
      if (fn.length) {
        fnText = fn.toString().replace(STRIP_COMMENTS, '');
        argDecl = fnText.match(FN_ARGS);
        forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
          arg.replace(FN_ARG, function(all, underscore, name){
            $inject.push(name);
          });
        });
      }
      fn.$inject = $inject;
    }
  } else if (isArray(fn)) {
    last = fn.length - 1;
    assertArgFn(fn[last], 'fn');
    $inject = fn.slice(0, last);
  } else {
    assertArgFn(fn, 'fn', true);
  }
  return $inject;
}

///////////////////////////////////////

/**
 * @ngdoc service
 * @name $injector
 *
 * @description
 *
 * `$injector` is used to retrieve object instances as defined by
 * {@link auto.$provide provider}, instantiate types, invoke methods,
 * and load modules.
 *
 * The following always holds true:
 *
 * ```js
 *   var $injector = angular.injector();
 *   expect($injector.get('$injector')).toBe($injector);
 *   expect($injector.invoke(function($injector){
 *     return $injector;
 *   })).toBe($injector);
 * ```
 *
 * # Injection Function Annotation
 *
 * JavaScript does not have annotations, and annotations are needed for dependency injection. The
 * following are all valid ways of annotating function with injection arguments and are equivalent.
 *
 * ```js
 *   // inferred (only works if code not minified/obfuscated)
 *   $injector.invoke(function(serviceA){});
 *
 *   // annotated
 *   function explicit(serviceA) {};
 *   explicit.$inject = ['serviceA'];
 *   $injector.invoke(explicit);
 *
 *   // inline
 *   $injector.invoke(['serviceA', function(serviceA){}]);
 * ```
 *
 * ## Inference
 *
 * In JavaScript calling `toString()` on a function returns the function definition. The definition
 * can then be parsed and the function arguments can be extracted. *NOTE:* This does not work with
 * minification, and obfuscation tools since these tools change the argument names.
 *
 * ## `$inject` Annotation
 * By adding an `$inject` property onto a function the injection parameters can be specified.
 *
 * ## Inline
 * As an array of injection names, where the last item in the array is the function to call.
 */

/**
 * @ngdoc method
 * @name $injector#get
 *
 * @description
 * Return an instance of the service.
 *
 * @param {string} name The name of the instance to retrieve.
 * @return {*} The instance.
 */

/**
 * @ngdoc method
 * @name $injector#invoke
 *
 * @description
 * Invoke the method and supply the method arguments from the `$injector`.
 *
 * @param {!Function} fn The function to invoke. Function parameters are injected according to the
 *   {@link guide/di $inject Annotation} rules.
 * @param {Object=} self The `this` for the invoked method.
 * @param {Object=} locals Optional object. If preset then any argument names are read from this
 *                         object first, before the `$injector` is consulted.
 * @returns {*} the value returned by the invoked `fn` function.
 */

/**
 * @ngdoc method
 * @name $injector#has
 *
 * @description
 * Allows the user to query if the particular service exists.
 *
 * @param {string} name Name of the service to query.
 * @returns {boolean} `true` if injector has given service.
 */

/**
 * @ngdoc method
 * @name $injector#instantiate
 * @description
 * Create a new instance of JS type. The method takes a constructor function, invokes the new
 * operator, and supplies all of the arguments to the constructor function as specified by the
 * constructor annotation.
 *
 * @param {Function} Type Annotated constructor function.
 * @param {Object=} locals Optional object. If preset then any argument names are read from this
 * object first, before the `$injector` is consulted.
 * @returns {Object} new instance of `Type`.
 */

/**
 * @ngdoc method
 * @name $injector#annotate
 *
 * @description
 * Returns an array of service names which the function is requesting for injection. This API is
 * used by the injector to determine which services need to be injected into the function when the
 * function is invoked. There are three ways in which the function can be annotated with the needed
 * dependencies.
 *
 * # Argument names
 *
 * The simplest form is to extract the dependencies from the arguments of the function. This is done
 * by converting the function into a string using `toString()` method and extracting the argument
 * names.
 * ```js
 *   // Given
 *   function MyController($scope, $route) {
 *     // ...
 *   }
 *
 *   // Then
 *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
 * ```
 *
 * This method does not work with code minification / obfuscation. For this reason the following
 * annotation strategies are supported.
 *
 * # The `$inject` property
 *
 * If a function has an `$inject` property and its value is an array of strings, then the strings
 * represent names of services to be injected into the function.
 * ```js
 *   // Given
 *   var MyController = function(obfuscatedScope, obfuscatedRoute) {
 *     // ...
 *   }
 *   // Define function dependencies
 *   MyController['$inject'] = ['$scope', '$route'];
 *
 *   // Then
 *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
 * ```
 *
 * # The array notation
 *
 * It is often desirable to inline Injected functions and that's when setting the `$inject` property
 * is very inconvenient. In these situations using the array notation to specify the dependencies in
 * a way that survives minification is a better choice:
 *
 * ```js
 *   // We wish to write this (not minification / obfuscation safe)
 *   injector.invoke(function($compile, $rootScope) {
 *     // ...
 *   });
 *
 *   // We are forced to write break inlining
 *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
 *     // ...
 *   };
 *   tmpFn.$inject = ['$compile', '$rootScope'];
 *   injector.invoke(tmpFn);
 *
 *   // To better support inline function the inline annotation is supported
 *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
 *     // ...
 *   }]);
 *
 *   // Therefore
 *   expect(injector.annotate(
 *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
 *    ).toEqual(['$compile', '$rootScope']);
 * ```
 *
 * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to
 * be retrieved as described above.
 *
 * @returns {Array.<string>} The names of the services which the function requires.
 */




/**
 * @ngdoc service
 * @name $provide
 *
 * @description
 *
 * The {@link auto.$provide $provide} service has a number of methods for registering components
 * with the {@link auto.$injector $injector}. Many of these functions are also exposed on
 * {@link angular.Module}.
 *
 * An Angular **service** is a singleton object created by a **service factory**.  These **service
 * factories** are functions which, in turn, are created by a **service provider**.
 * The **service providers** are constructor functions. When instantiated they must contain a
 * property called `$get`, which holds the **service factory** function.
 *
 * When you request a service, the {@link auto.$injector $injector} is responsible for finding the
 * correct **service provider**, instantiating it and then calling its `$get` **service factory**
 * function to get the instance of the **service**.
 *
 * Often services have no configuration options and there is no need to add methods to the service
 * provider.  The provider will be no more than a constructor function with a `$get` property. For
 * these cases the {@link auto.$provide $provide} service has additional helper methods to register
 * services without specifying a provider.
 *
 * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the
 *     {@link auto.$injector $injector}
 * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by
 *     providers and services.
 * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by
 *     services, not providers.
 * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,
 *     that will be wrapped in a **service provider** object, whose `$get` property will contain the
 *     given factory function.
 * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`
 *     that will be wrapped in a **service provider** object, whose `$get` property will instantiate
 *      a new object using the given constructor function.
 *
 * See the individual methods for more information and examples.
 */

/**
 * @ngdoc method
 * @name $provide#provider
 * @description
 *
 * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions
 * are constructor functions, whose instances are responsible for "providing" a factory for a
 * service.
 *
 * Service provider names start with the name of the service they provide followed by `Provider`.
 * For example, the {@link ng.$log $log} service has a provider called
 * {@link ng.$logProvider $logProvider}.
 *
 * Service provider objects can have additional methods which allow configuration of the provider
 * and its service. Importantly, you can configure what kind of service is created by the `$get`
 * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a
 * method {@link ng.$logProvider#debugEnabled debugEnabled}
 * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
 * console or not.
 *
 * @param {string} name The name of the instance. NOTE: the provider will be available under `name +
                        'Provider'` key.
 * @param {(Object|function())} provider If the provider is:
 *
 *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
 *     {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.
 *   - `Constructor`: a new instance of the provider will be created using
 *     {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.
 *
 * @returns {Object} registered provider instance

 * @example
 *
 * The following example shows how to create a simple event tracking service and register it using
 * {@link auto.$provide#provider $provide.provider()}.
 *
 * ```js
 *  // Define the eventTracker provider
 *  function EventTrackerProvider() {
 *    var trackingUrl = '/track';
 *
 *    // A provider method for configuring where the tracked events should been saved
 *    this.setTrackingUrl = function(url) {
 *      trackingUrl = url;
 *    };
 *
 *    // The service factory function
 *    this.$get = ['$http', function($http) {
 *      var trackedEvents = {};
 *      return {
 *        // Call this to track an event
 *        event: function(event) {
 *          var count = trackedEvents[event] || 0;
 *          count += 1;
 *          trackedEvents[event] = count;
 *          return count;
 *        },
 *        // Call this to save the tracked events to the trackingUrl
 *        save: function() {
 *          $http.post(trackingUrl, trackedEvents);
 *        }
 *      };
 *    }];
 *  }
 *
 *  describe('eventTracker', function() {
 *    var postSpy;
 *
 *    beforeEach(module(function($provide) {
 *      // Register the eventTracker provider
 *      $provide.provider('eventTracker', EventTrackerProvider);
 *    }));
 *
 *    beforeEach(module(function(eventTrackerProvider) {
 *      // Configure eventTracker provider
 *      eventTrackerProvider.setTrackingUrl('/custom-track');
 *    }));
 *
 *    it('tracks events', inject(function(eventTracker) {
 *      expect(eventTracker.event('login')).toEqual(1);
 *      expect(eventTracker.event('login')).toEqual(2);
 *    }));
 *
 *    it('saves to the tracking url', inject(function(eventTracker, $http) {
 *      postSpy = spyOn($http, 'post');
 *      eventTracker.event('login');
 *      eventTracker.save();
 *      expect(postSpy).toHaveBeenCalled();
 *      expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
 *      expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
 *      expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
 *    }));
 *  });
 * ```
 */

/**
 * @ngdoc method
 * @name $provide#factory
 * @description
 *
 * Register a **service factory**, which will be called to return the service instance.
 * This is short for registering a service where its provider consists of only a `$get` property,
 * which is the given service factory function.
 * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to
 * configure your service in a provider.
 *
 * @param {string} name The name of the instance.
 * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand
 *                            for `$provide.provider(name, {$get: $getFn})`.
 * @returns {Object} registered provider instance
 *
 * @example
 * Here is an example of registering a service
 * ```js
 *   $provide.factory('ping', ['$http', function($http) {
 *     return function ping() {
 *       return $http.send('/ping');
 *     };
 *   }]);
 * ```
 * You would then inject and use this service like this:
 * ```js
 *   someModule.controller('Ctrl', ['ping', function(ping) {
 *     ping();
 *   }]);
 * ```
 */


/**
 * @ngdoc method
 * @name $provide#service
 * @description
 *
 * Register a **service constructor**, which will be invoked with `new` to create the service
 * instance.
 * This is short for registering a service where its provider's `$get` property is the service
 * constructor function that will be used to instantiate the service instance.
 *
 * You should use {@link auto.$provide#service $provide.service(class)} if you define your service
 * as a type/class.
 *
 * @param {string} name The name of the instance.
 * @param {Function} constructor A class (constructor function) that will be instantiated.
 * @returns {Object} registered provider instance
 *
 * @example
 * Here is an example of registering a service using
 * {@link auto.$provide#service $provide.service(class)}.
 * ```js
 *   var Ping = function($http) {
 *     this.$http = $http;
 *   };
 *
 *   Ping.$inject = ['$http'];
 *
 *   Ping.prototype.send = function() {
 *     return this.$http.get('/ping');
 *   };
 *   $provide.service('ping', Ping);
 * ```
 * You would then inject and use this service like this:
 * ```js
 *   someModule.controller('Ctrl', ['ping', function(ping) {
 *     ping.send();
 *   }]);
 * ```
 */


/**
 * @ngdoc method
 * @name $provide#value
 * @description
 *
 * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a
 * number, an array, an object or a function.  This is short for registering a service where its
 * provider's `$get` property is a factory function that takes no arguments and returns the **value
 * service**.
 *
 * Value services are similar to constant services, except that they cannot be injected into a
 * module configuration function (see {@link angular.Module#config}) but they can be overridden by
 * an Angular
 * {@link auto.$provide#decorator decorator}.
 *
 * @param {string} name The name of the instance.
 * @param {*} value The value.
 * @returns {Object} registered provider instance
 *
 * @example
 * Here are some examples of creating value services.
 * ```js
 *   $provide.value('ADMIN_USER', 'admin');
 *
 *   $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
 *
 *   $provide.value('halfOf', function(value) {
 *     return value / 2;
 *   });
 * ```
 */


/**
 * @ngdoc method
 * @name $provide#constant
 * @description
 *
 * Register a **constant service**, such as a string, a number, an array, an object or a function,
 * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be
 * injected into a module configuration function (see {@link angular.Module#config}) and it cannot
 * be overridden by an Angular {@link auto.$provide#decorator decorator}.
 *
 * @param {string} name The name of the constant.
 * @param {*} value The constant value.
 * @returns {Object} registered instance
 *
 * @example
 * Here a some examples of creating constants:
 * ```js
 *   $provide.constant('SHARD_HEIGHT', 306);
 *
 *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
 *
 *   $provide.constant('double', function(value) {
 *     return value * 2;
 *   });
 * ```
 */


/**
 * @ngdoc method
 * @name $provide#decorator
 * @description
 *
 * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
 * intercepts the creation of a service, allowing it to override or modify the behaviour of the
 * service. The object returned by the decorator may be the original service, or a new service
 * object which replaces or wraps and delegates to the original service.
 *
 * @param {string} name The name of the service to decorate.
 * @param {function()} decorator This function will be invoked when the service needs to be
 *    instantiated and should return the decorated service instance. The function is called using
 *    the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
 *    Local injection arguments:
 *
 *    * `$delegate` - The original service instance, which can be monkey patched, configured,
 *      decorated or delegated to.
 *
 * @example
 * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
 * calls to {@link ng.$log#error $log.warn()}.
 * ```js
 *   $provide.decorator('$log', ['$delegate', function($delegate) {
 *     $delegate.warn = $delegate.error;
 *     return $delegate;
 *   }]);
 * ```
 */


function createInjector(modulesToLoad) {
  var INSTANTIATING = {},
      providerSuffix = 'Provider',
      path = [],
      loadedModules = new HashMap([], true),
      providerCache = {
        $provide: {
            provider: supportObject(provider),
            factory: supportObject(factory),
            service: supportObject(service),
            value: supportObject(value),
            constant: supportObject(constant),
            decorator: decorator
          }
      },
      providerInjector = (providerCache.$injector =
          createInternalInjector(providerCache, function() {
            throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
          })),
      instanceCache = {},
      instanceInjector = (instanceCache.$injector =
          createInternalInjector(instanceCache, function(servicename) {
            var provider = providerInjector.get(servicename + providerSuffix);
            return instanceInjector.invoke(provider.$get, provider);
          }));


  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });

  return instanceInjector;

  ////////////////////////////////////
  // $provider
  ////////////////////////////////////

  function supportObject(delegate) {
    return function(key, value) {
      if (isObject(key)) {
        forEach(key, reverseParams(delegate));
      } else {
        return delegate(key, value);
      }
    };
  }

  function provider(name, provider_) {
    assertNotHasOwnProperty(name, 'service');
    if (isFunction(provider_) || isArray(provider_)) {
      provider_ = providerInjector.instantiate(provider_);
    }
    if (!provider_.$get) {
      throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name);
    }
    return providerCache[name + providerSuffix] = provider_;
  }

  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }

  function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
  }

  function value(name, val) { return factory(name, valueFn(val)); }

  function constant(name, value) {
    assertNotHasOwnProperty(name, 'constant');
    providerCache[name] = value;
    instanceCache[name] = value;
  }

  function decorator(serviceName, decorFn) {
    var origProvider = providerInjector.get(serviceName + providerSuffix),
        orig$get = origProvider.$get;

    origProvider.$get = function() {
      var origInstance = instanceInjector.invoke(orig$get, origProvider);
      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
    };
  }

  ////////////////////////////////////
  // Module Loading
  ////////////////////////////////////
  function loadModules(modulesToLoad){
    var runBlocks = [], moduleFn, invokeQueue, i, ii;
    forEach(modulesToLoad, function(module) {
      if (loadedModules.get(module)) return;
      loadedModules.put(module, true);

      try {
        if (isString(module)) {
          moduleFn = angularModule(module);
          runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);

          for(invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
            var invokeArgs = invokeQueue[i],
                provider = providerInjector.get(invokeArgs[0]);

            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
          }
        } else if (isFunction(module)) {
            runBlocks.push(providerInjector.invoke(module));
        } else if (isArray(module)) {
            runBlocks.push(providerInjector.invoke(module));
        } else {
          assertArgFn(module, 'module');
        }
      } catch (e) {
        if (isArray(module)) {
          module = module[module.length - 1];
        }
        if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
          // Safari & FF's stack traces don't contain error.message content
          // unlike those of Chrome and IE
          // So if stack doesn't contain message, we create a new string that contains both.
          // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.
          /* jshint -W022 */
          e = e.message + '\n' + e.stack;
        }
        throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
                  module, e.stack || e.message || e);
      }
    });
    return runBlocks;
  }

  ////////////////////////////////////
  // internal Injector
  ////////////////////////////////////

  function createInternalInjector(cache, factory) {

    function getService(serviceName) {
      if (cache.hasOwnProperty(serviceName)) {
        if (cache[serviceName] === INSTANTIATING) {
          throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
                    serviceName + ' <- ' + path.join(' <- '));
        }
        return cache[serviceName];
      } else {
        try {
          path.unshift(serviceName);
          cache[serviceName] = INSTANTIATING;
          return cache[serviceName] = factory(serviceName);
        } catch (err) {
          if (cache[serviceName] === INSTANTIATING) {
            delete cache[serviceName];
          }
          throw err;
        } finally {
          path.shift();
        }
      }
    }

    function invoke(fn, self, locals){
      var args = [],
          $inject = annotate(fn),
          length, i,
          key;

      for(i = 0, length = $inject.length; i < length; i++) {
        key = $inject[i];
        if (typeof key !== 'string') {
          throw $injectorMinErr('itkn',
                  'Incorrect injection token! Expected service name as string, got {0}', key);
        }
        args.push(
          locals && locals.hasOwnProperty(key)
          ? locals[key]
          : getService(key)
        );
      }
      if (isArray(fn)) {
        fn = fn[length];
      }

      // http://jsperf.com/angularjs-invoke-apply-vs-switch
      // #5388
      return fn.apply(self, args);
    }

    function instantiate(Type, locals) {
      var Constructor = function() {},
          instance, returnedValue;

      // Check if Type is annotated and use just the given function at n-1 as parameter
      // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
      instance = new Constructor();
      returnedValue = invoke(Type, instance, locals);

      return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
    }

    return {
      invoke: invoke,
      instantiate: instantiate,
      get: getService,
      annotate: annotate,
      has: function(name) {
        return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
      }
    };
  }
}

/**
 * @ngdoc service
 * @name $anchorScroll
 * @kind function
 * @requires $window
 * @requires $location
 * @requires $rootScope
 *
 * @description
 * When called, it checks current value of `$location.hash()` and scrolls to the related element,
 * according to rules specified in
 * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
 *
 * It also watches the `$location.hash()` and scrolls whenever it changes to match any anchor.
 * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
 *
 * @example
   <example>
     <file name="index.html">
       <div id="scrollArea" ng-controller="ScrollCtrl">
         <a ng-click="gotoBottom()">Go to bottom</a>
         <a id="bottom"></a> You're at the bottom!
       </div>
     </file>
     <file name="script.js">
       function ScrollCtrl($scope, $location, $anchorScroll) {
         $scope.gotoBottom = function (){
           // set the location.hash to the id of
           // the element you wish to scroll to.
           $location.hash('bottom');

           // call $anchorScroll()
           $anchorScroll();
         };
       }
     </file>
     <file name="style.css">
       #scrollArea {
         height: 350px;
         overflow: auto;
       }

       #bottom {
         display: block;
         margin-top: 2000px;
       }
     </file>
   </example>
 */
function $AnchorScrollProvider() {

  var autoScrollingEnabled = true;

  /**
   * @ngdoc method
   * @name $anchorScrollProvider#disableAutoScrolling
   *
   * @description
   * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to
   * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />
   * Use this method to disable automatic scrolling.
   *
   * If automatic scrolling is disabled, one must explicitly call
   * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the
   * current hash.
   */
  this.disableAutoScrolling = function() {
    autoScrollingEnabled = false;
  };

  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
    var document = $window.document;

    // helper function to get first anchor from a NodeList
    // can't use filter.filter, as it accepts only instances of Array
    // and IE can't convert NodeList to an array using [].slice
    // TODO(vojta): use filter if we change it to accept lists as well
    function getFirstAnchor(list) {
      var result = null;
      forEach(list, function(element) {
        if (!result && lowercase(element.nodeName) === 'a') result = element;
      });
      return result;
    }

    function scroll() {
      var hash = $location.hash(), elm;

      // empty hash, scroll to the top of the page
      if (!hash) $window.scrollTo(0, 0);

      // element with given id
      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();

      // first anchor with given name :-D
      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();

      // no element and hash == 'top', scroll to the top of the page
      else if (hash === 'top') $window.scrollTo(0, 0);
    }

    // does not scroll when user clicks on anchor link that is currently on
    // (no url change, no $location.hash() change), browser native does scroll
    if (autoScrollingEnabled) {
      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
        function autoScrollWatchAction() {
          $rootScope.$evalAsync(scroll);
        });
    }

    return scroll;
  }];
}

var $animateMinErr = minErr('$animate');

/**
 * @ngdoc provider
 * @name $animateProvider
 *
 * @description
 * Default implementation of $animate that doesn't perform any animations, instead just
 * synchronously performs DOM
 * updates and calls done() callbacks.
 *
 * In order to enable animations the ngAnimate module has to be loaded.
 *
 * To see the functional implementation check out src/ngAnimate/animate.js
 */
var $AnimateProvider = ['$provide', function($provide) {


  this.$$selectors = {};


  /**
   * @ngdoc method
   * @name $animateProvider#register
   *
   * @description
   * Registers a new injectable animation factory function. The factory function produces the
   * animation object which contains callback functions for each event that is expected to be
   * animated.
   *
   *   * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`
   *   must be called once the element animation is complete. If a function is returned then the
   *   animation service will use this function to cancel the animation whenever a cancel event is
   *   triggered.
   *
   *
   * ```js
   *   return {
     *     eventFn : function(element, done) {
     *       //code to run the animation
     *       //once complete, then run done()
     *       return function cancellationFunction() {
     *         //code to cancel the animation
     *       }
     *     }
     *   }
   * ```
   *
   * @param {string} name The name of the animation.
   * @param {Function} factory The factory function that will be executed to return the animation
   *                           object.
   */
  this.register = function(name, factory) {
    var key = name + '-animation';
    if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',
        "Expecting class selector starting with '.' got '{0}'.", name);
    this.$$selectors[name.substr(1)] = key;
    $provide.factory(key, factory);
  };

  /**
   * @ngdoc method
   * @name $animateProvider#classNameFilter
   *
   * @description
   * Sets and/or returns the CSS class regular expression that is checked when performing
   * an animation. Upon bootstrap the classNameFilter value is not set at all and will
   * therefore enable $animate to attempt to perform an animation on any element.
   * When setting the classNameFilter value, animations will only be performed on elements
   * that successfully match the filter expression. This in turn can boost performance
   * for low-powered devices as well as applications containing a lot of structural operations.
   * @param {RegExp=} expression The className expression which will be checked against all animations
   * @return {RegExp} The current CSS className expression value. If null then there is no expression value
   */
  this.classNameFilter = function(expression) {
    if(arguments.length === 1) {
      this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
    }
    return this.$$classNameFilter;
  };

  this.$get = ['$timeout', '$$asyncCallback', function($timeout, $$asyncCallback) {

    function async(fn) {
      fn && $$asyncCallback(fn);
    }

    /**
     *
     * @ngdoc service
     * @name $animate
     * @description The $animate service provides rudimentary DOM manipulation functions to
     * insert, remove and move elements within the DOM, as well as adding and removing classes.
     * This service is the core service used by the ngAnimate $animator service which provides
     * high-level animation hooks for CSS and JavaScript.
     *
     * $animate is available in the AngularJS core, however, the ngAnimate module must be included
     * to enable full out animation support. Otherwise, $animate will only perform simple DOM
     * manipulation operations.
     *
     * To learn more about enabling animation support, click here to visit the {@link ngAnimate
     * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service
     * page}.
     */
    return {

      /**
       *
       * @ngdoc method
       * @name $animate#enter
       * @kind function
       * @description Inserts the element into the DOM either after the `after` element or within
       *   the `parent` element. Once complete, the done() callback will be fired (if provided).
       * @param {DOMElement} element the element which will be inserted into the DOM
       * @param {DOMElement} parent the parent element which will append the element as
       *   a child (if the after element is not present)
       * @param {DOMElement} after the sibling element which will append the element
       *   after itself
       * @param {Function=} done callback function that will be called after the element has been
       *   inserted into the DOM
       */
      enter : function(element, parent, after, done) {
        if (after) {
          after.after(element);
        } else {
          if (!parent || !parent[0]) {
            parent = after.parent();
          }
          parent.append(element);
        }
        async(done);
      },

      /**
       *
       * @ngdoc method
       * @name $animate#leave
       * @kind function
       * @description Removes the element from the DOM. Once complete, the done() callback will be
       *   fired (if provided).
       * @param {DOMElement} element the element which will be removed from the DOM
       * @param {Function=} done callback function that will be called after the element has been
       *   removed from the DOM
       */
      leave : function(element, done) {
        element.remove();
        async(done);
      },

      /**
       *
       * @ngdoc method
       * @name $animate#move
       * @kind function
       * @description Moves the position of the provided element within the DOM to be placed
       * either after the `after` element or inside of the `parent` element. Once complete, the
       * done() callback will be fired (if provided).
       *
       * @param {DOMElement} element the element which will be moved around within the
       *   DOM
       * @param {DOMElement} parent the parent element where the element will be
       *   inserted into (if the after element is not present)
       * @param {DOMElement} after the sibling element where the element will be
       *   positioned next to
       * @param {Function=} done the callback function (if provided) that will be fired after the
       *   element has been moved to its new position
       */
      move : function(element, parent, after, done) {
        // Do not remove element before insert. Removing will cause data associated with the
        // element to be dropped. Insert will implicitly do the remove.
        this.enter(element, parent, after, done);
      },

      /**
       *
       * @ngdoc method
       * @name $animate#addClass
       * @kind function
       * @description Adds the provided className CSS class value to the provided element. Once
       * complete, the done() callback will be fired (if provided).
       * @param {DOMElement} element the element which will have the className value
       *   added to it
       * @param {string} className the CSS class which will be added to the element
       * @param {Function=} done the callback function (if provided) that will be fired after the
       *   className value has been added to the element
       */
      addClass : function(element, className, done) {
        className = isString(className) ?
                      className :
                      isArray(className) ? className.join(' ') : '';
        forEach(element, function (element) {
          jqLiteAddClass(element, className);
        });
        async(done);
      },

      /**
       *
       * @ngdoc method
       * @name $animate#removeClass
       * @kind function
       * @description Removes the provided className CSS class value from the provided element.
       * Once complete, the done() callback will be fired (if provided).
       * @param {DOMElement} element the element which will have the className value
       *   removed from it
       * @param {string} className the CSS class which will be removed from the element
       * @param {Function=} done the callback function (if provided) that will be fired after the
       *   className value has been removed from the element
       */
      removeClass : function(element, className, done) {
        className = isString(className) ?
                      className :
                      isArray(className) ? className.join(' ') : '';
        forEach(element, function (element) {
          jqLiteRemoveClass(element, className);
        });
        async(done);
      },

      /**
       *
       * @ngdoc method
       * @name $animate#setClass
       * @kind function
       * @description Adds and/or removes the given CSS classes to and from the element.
       * Once complete, the done() callback will be fired (if provided).
       * @param {DOMElement} element the element which will have its CSS classes changed
       *   removed from it
       * @param {string} add the CSS classes which will be added to the element
       * @param {string} remove the CSS class which will be removed from the element
       * @param {Function=} done the callback function (if provided) that will be fired after the
       *   CSS classes have been set on the element
       */
      setClass : function(element, add, remove, done) {
        forEach(element, function (element) {
          jqLiteAddClass(element, add);
          jqLiteRemoveClass(element, remove);
        });
        async(done);
      },

      enabled : noop
    };
  }];
}];

function $$AsyncCallbackProvider(){
  this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {
    return $$rAF.supported
      ? function(fn) { return $$rAF(fn); }
      : function(fn) {
        return $timeout(fn, 0, false);
      };
  }];
}

/* global stripHash: true */

/**
 * ! This is a private undocumented service !
 *
 * @name $browser
 * @requires $log
 * @description
 * This object has two goals:
 *
 * - hide all the global state in the browser caused by the window object
 * - abstract away all the browser specific features and inconsistencies
 *
 * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`
 * service, which can be used for convenient testing of the application without the interaction with
 * the real browser apis.
 */
/**
 * @param {object} window The global window object.
 * @param {object} document jQuery wrapped document.
 * @param {function()} XHR XMLHttpRequest constructor.
 * @param {object} $log console.log or an object with the same interface.
 * @param {object} $sniffer $sniffer service
 */
function Browser(window, document, $log, $sniffer) {
  var self = this,
      rawDocument = document[0],
      location = window.location,
      history = window.history,
      setTimeout = window.setTimeout,
      clearTimeout = window.clearTimeout,
      pendingDeferIds = {};

  self.isMock = false;

  var outstandingRequestCount = 0;
  var outstandingRequestCallbacks = [];

  // TODO(vojta): remove this temporary api
  self.$$completeOutstandingRequest = completeOutstandingRequest;
  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };

  /**
   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`
   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.
   */
  function completeOutstandingRequest(fn) {
    try {
      fn.apply(null, sliceArgs(arguments, 1));
    } finally {
      outstandingRequestCount--;
      if (outstandingRequestCount === 0) {
        while(outstandingRequestCallbacks.length) {
          try {
            outstandingRequestCallbacks.pop()();
          } catch (e) {
            $log.error(e);
          }
        }
      }
    }
  }

  /**
   * @private
   * Note: this method is used only by scenario runner
   * TODO(vojta): prefix this method with $$ ?
   * @param {function()} callback Function that will be called when no outstanding request
   */
  self.notifyWhenNoOutstandingRequests = function(callback) {
    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire
    // at some deterministic time in respect to the test runner's actions. Leaving things up to the
    // regular poller would result in flaky tests.
    forEach(pollFns, function(pollFn){ pollFn(); });

    if (outstandingRequestCount === 0) {
      callback();
    } else {
      outstandingRequestCallbacks.push(callback);
    }
  };

  //////////////////////////////////////////////////////////////
  // Poll Watcher API
  //////////////////////////////////////////////////////////////
  var pollFns = [],
      pollTimeout;

  /**
   * @name $browser#addPollFn
   *
   * @param {function()} fn Poll function to add
   *
   * @description
   * Adds a function to the list of functions that poller periodically executes,
   * and starts polling if not started yet.
   *
   * @returns {function()} the added function
   */
  self.addPollFn = function(fn) {
    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);
    pollFns.push(fn);
    return fn;
  };

  /**
   * @param {number} interval How often should browser call poll functions (ms)
   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.
   *
   * @description
   * Configures the poller to run in the specified intervals, using the specified
   * setTimeout fn and kicks it off.
   */
  function startPoller(interval, setTimeout) {
    (function check() {
      forEach(pollFns, function(pollFn){ pollFn(); });
      pollTimeout = setTimeout(check, interval);
    })();
  }

  //////////////////////////////////////////////////////////////
  // URL API
  //////////////////////////////////////////////////////////////

  var lastBrowserUrl = location.href,
      baseElement = document.find('base'),
      reloadLocation = null;

  /**
   * @name $browser#url
   *
   * @description
   * GETTER:
   * Without any argument, this method just returns current value of location.href.
   *
   * SETTER:
   * With at least one argument, this method sets url to new value.
   * If html5 history api supported, pushState/replaceState is used, otherwise
   * location.href/location.replace is used.
   * Returns its own instance to allow chaining
   *
   * NOTE: this api is intended for use only by the $location service. Please use the
   * {@link ng.$location $location service} to change url.
   *
   * @param {string} url New url (when used as setter)
   * @param {boolean=} replace Should new url replace current history record ?
   */
  self.url = function(url, replace) {
    // Android Browser BFCache causes location, history reference to become stale.
    if (location !== window.location) location = window.location;
    if (history !== window.history) history = window.history;

    // setter
    if (url) {
      if (lastBrowserUrl == url) return;
      var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);
      lastBrowserUrl = url;
      // Don't use history API if only the hash changed
      // due to a bug in IE10/IE11 which leads
      // to not firing a `hashchange` nor `popstate` event
      // in some cases (see #9143).
      if (!sameBase && $sniffer.history) {
        if (replace) history.replaceState(null, '', url);
        else {
          history.pushState(null, '', url);
          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462
          baseElement.attr('href', baseElement.attr('href'));
        }
      } else {
        if (!sameBase) {
          reloadLocation = url;
        }
        if (replace) {
          location.replace(url);
        } else {
          location.href = url;
        }
      }
      return self;
    // getter
    } else {
      // - reloadLocation is needed as browsers don't allow to read out
      //   the new location.href if a reload happened.
      // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
      return reloadLocation || location.href.replace(/%27/g,"'");
    }
  };

  var urlChangeListeners = [],
      urlChangeInit = false;

  function fireUrlChange() {
    if (lastBrowserUrl == self.url()) return;

    lastBrowserUrl = self.url();
    forEach(urlChangeListeners, function(listener) {
      listener(self.url());
    });
  }

  /**
   * @name $browser#onUrlChange
   *
   * @description
   * Register callback function that will be called, when url changes.
   *
   * It's only called when the url is changed from outside of angular:
   * - user types different url into address bar
   * - user clicks on history (forward/back) button
   * - user clicks on a link
   *
   * It's not called when url is changed by $browser.url() method
   *
   * The listener gets called with new url as parameter.
   *
   * NOTE: this api is intended for use only by the $location service. Please use the
   * {@link ng.$location $location service} to monitor url changes in angular apps.
   *
   * @param {function(string)} listener Listener function to be called when url changes.
   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.
   */
  self.onUrlChange = function(callback) {
    // TODO(vojta): refactor to use node's syntax for events
    if (!urlChangeInit) {
      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
      // don't fire popstate when user change the address bar and don't fire hashchange when url
      // changed by push/replaceState

      // html5 history api - popstate event
      if ($sniffer.history) jqLite(window).on('popstate', fireUrlChange);
      // hashchange event
      if ($sniffer.hashchange) jqLite(window).on('hashchange', fireUrlChange);
      // polling
      else self.addPollFn(fireUrlChange);

      urlChangeInit = true;
    }

    urlChangeListeners.push(callback);
    return callback;
  };

  /**
   * Checks whether the url has changed outside of Angular.
   * Needs to be exported to be able to check for changes that have been done in sync,
   * as hashchange/popstate events fire in async.
   */
  self.$$checkUrlChange = fireUrlChange;

  //////////////////////////////////////////////////////////////
  // Misc API
  //////////////////////////////////////////////////////////////

  /**
   * @name $browser#baseHref
   *
   * @description
   * Returns current <base href>
   * (always relative - without domain)
   *
   * @returns {string} The current base href
   */
  self.baseHref = function() {
    var href = baseElement.attr('href');
    return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
  };

  //////////////////////////////////////////////////////////////
  // Cookies API
  //////////////////////////////////////////////////////////////
  var lastCookies = {};
  var lastCookieString = '';
  var cookiePath = self.baseHref();

  /**
   * @name $browser#cookies
   *
   * @param {string=} name Cookie name
   * @param {string=} value Cookie value
   *
   * @description
   * The cookies method provides a 'private' low level access to browser cookies.
   * It is not meant to be used directly, use the $cookie service instead.
   *
   * The return values vary depending on the arguments that the method was called with as follows:
   *
   * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify
   *   it
   * - cookies(name, value) -> set name to value, if value is undefined delete the cookie
   * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that
   *   way)
   *
   * @returns {Object} Hash of all cookies (if called without any parameter)
   */
  self.cookies = function(name, value) {
    /* global escape: false, unescape: false */
    var cookieLength, cookieArray, cookie, i, index;

    if (name) {
      if (value === undefined) {
        rawDocument.cookie = escape(name) + "=;path=" + cookiePath +
                                ";expires=Thu, 01 Jan 1970 00:00:00 GMT";
      } else {
        if (isString(value)) {
          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) +
                                ';path=' + cookiePath).length + 1;

          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
          // - 300 cookies
          // - 20 cookies per unique domain
          // - 4096 bytes per cookie
          if (cookieLength > 4096) {
            $log.warn("Cookie '"+ name +
              "' possibly not set or overflowed because it was too large ("+
              cookieLength + " > 4096 bytes)!");
          }
        }
      }
    } else {
      if (rawDocument.cookie !== lastCookieString) {
        lastCookieString = rawDocument.cookie;
        cookieArray = lastCookieString.split("; ");
        lastCookies = {};

        for (i = 0; i < cookieArray.length; i++) {
          cookie = cookieArray[i];
          index = cookie.indexOf('=');
          if (index > 0) { //ignore nameless cookies
            name = unescape(cookie.substring(0, index));
            // the first value that is seen for a cookie is the most
            // specific one.  values for the same cookie name that
            // follow are for less specific paths.
            if (lastCookies[name] === undefined) {
              lastCookies[name] = unescape(cookie.substring(index + 1));
            }
          }
        }
      }
      return lastCookies;
    }
  };


  /**
   * @name $browser#defer
   * @param {function()} fn A function, who's execution should be deferred.
   * @param {number=} [delay=0] of milliseconds to defer the function execution.
   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
   *
   * @description
   * Executes a fn asynchronously via `setTimeout(fn, delay)`.
   *
   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed
   * via `$browser.defer.flush()`.
   *
   */
  self.defer = function(fn, delay) {
    var timeoutId;
    outstandingRequestCount++;
    timeoutId = setTimeout(function() {
      delete pendingDeferIds[timeoutId];
      completeOutstandingRequest(fn);
    }, delay || 0);
    pendingDeferIds[timeoutId] = true;
    return timeoutId;
  };


  /**
   * @name $browser#defer.cancel
   *
   * @description
   * Cancels a deferred task identified with `deferId`.
   *
   * @param {*} deferId Token returned by the `$browser.defer` function.
   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
   *                    canceled.
   */
  self.defer.cancel = function(deferId) {
    if (pendingDeferIds[deferId]) {
      delete pendingDeferIds[deferId];
      clearTimeout(deferId);
      completeOutstandingRequest(noop);
      return true;
    }
    return false;
  };

}

function $BrowserProvider(){
  this.$get = ['$window', '$log', '$sniffer', '$document',
      function( $window,   $log,   $sniffer,   $document){
        return new Browser($window, $document, $log, $sniffer);
      }];
}

/**
 * @ngdoc service
 * @name $cacheFactory
 *
 * @description
 * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to
 * them.
 *
 * ```js
 *
 *  var cache = $cacheFactory('cacheId');
 *  expect($cacheFactory.get('cacheId')).toBe(cache);
 *  expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
 *
 *  cache.put("key", "value");
 *  cache.put("another key", "another value");
 *
 *  // We've specified no options on creation
 *  expect(cache.info()).toEqual({id: 'cacheId', size: 2});
 *
 * ```
 *
 *
 * @param {string} cacheId Name or id of the newly created cache.
 * @param {object=} options Options object that specifies the cache behavior. Properties:
 *
 *   - `{number=}` `capacity` — turns the cache into LRU cache.
 *
 * @returns {object} Newly created cache object with the following set of methods:
 *
 * - `{object}` `info()` — Returns id, size, and options of cache.
 * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns
 *   it.
 * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
 * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
 * - `{void}` `removeAll()` — Removes all cached values.
 * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
 *
 * @example
   <example module="cacheExampleApp">
     <file name="index.html">
       <div ng-controller="CacheController">
         <input ng-model="newCacheKey" placeholder="Key">
         <input ng-model="newCacheValue" placeholder="Value">
         <button ng-click="put(newCacheKey, newCacheValue)">Cache</button>

         <p ng-if="keys.length">Cached Values</p>
         <div ng-repeat="key in keys">
           <span ng-bind="key"></span>
           <span>: </span>
           <b ng-bind="cache.get(key)"></b>
         </div>

         <p>Cache Info</p>
         <div ng-repeat="(key, value) in cache.info()">
           <span ng-bind="key"></span>
           <span>: </span>
           <b ng-bind="value"></b>
         </div>
       </div>
     </file>
     <file name="script.js">
       angular.module('cacheExampleApp', []).
         controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {
           $scope.keys = [];
           $scope.cache = $cacheFactory('cacheId');
           $scope.put = function(key, value) {
             if ($scope.cache.get(key) === undefined) {
               $scope.keys.push(key);
             }
             $scope.cache.put(key, value === undefined ? null : value);
           };
         }]);
     </file>
     <file name="style.css">
       p {
         margin: 10px 0 3px;
       }
     </file>
   </example>
 */
function $CacheFactoryProvider() {

  this.$get = function() {
    var caches = {};

    function cacheFactory(cacheId, options) {
      if (cacheId in caches) {
        throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId);
      }

      var size = 0,
          stats = extend({}, options, {id: cacheId}),
          data = {},
          capacity = (options && options.capacity) || Number.MAX_VALUE,
          lruHash = {},
          freshEnd = null,
          staleEnd = null;

      /**
       * @ngdoc type
       * @name $cacheFactory.Cache
       *
       * @description
       * A cache object used to store and retrieve data, primarily used by
       * {@link $http $http} and the {@link ng.directive:script script} directive to cache
       * templates and other data.
       *
       * ```js
       *  angular.module('superCache')
       *    .factory('superCache', ['$cacheFactory', function($cacheFactory) {
       *      return $cacheFactory('super-cache');
       *    }]);
       * ```
       *
       * Example test:
       *
       * ```js
       *  it('should behave like a cache', inject(function(superCache) {
       *    superCache.put('key', 'value');
       *    superCache.put('another key', 'another value');
       *
       *    expect(superCache.info()).toEqual({
       *      id: 'super-cache',
       *      size: 2
       *    });
       *
       *    superCache.remove('another key');
       *    expect(superCache.get('another key')).toBeUndefined();
       *
       *    superCache.removeAll();
       *    expect(superCache.info()).toEqual({
       *      id: 'super-cache',
       *      size: 0
       *    });
       *  }));
       * ```
       */
      return caches[cacheId] = {

        /**
         * @ngdoc method
         * @name $cacheFactory.Cache#put
         * @kind function
         *
         * @description
         * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be
         * retrieved later, and incrementing the size of the cache if the key was not already
         * present in the cache. If behaving like an LRU cache, it will also remove stale
         * entries from the set.
         *
         * It will not insert undefined values into the cache.
         *
         * @param {string} key the key under which the cached data is stored.
         * @param {*} value the value to store alongside the key. If it is undefined, the key
         *    will not be stored.
         * @returns {*} the value stored.
         */
        put: function(key, value) {
          if (capacity < Number.MAX_VALUE) {
            var lruEntry = lruHash[key] || (lruHash[key] = {key: key});

            refresh(lruEntry);
          }

          if (isUndefined(value)) return;
          if (!(key in data)) size++;
          data[key] = value;

          if (size > capacity) {
            this.remove(staleEnd.key);
          }

          return value;
        },

        /**
         * @ngdoc method
         * @name $cacheFactory.Cache#get
         * @kind function
         *
         * @description
         * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.
         *
         * @param {string} key the key of the data to be retrieved
         * @returns {*} the value stored.
         */
        get: function(key) {
          if (capacity < Number.MAX_VALUE) {
            var lruEntry = lruHash[key];

            if (!lruEntry) return;

            refresh(lruEntry);
          }

          return data[key];
        },


        /**
         * @ngdoc method
         * @name $cacheFactory.Cache#remove
         * @kind function
         *
         * @description
         * Removes an entry from the {@link $cacheFactory.Cache Cache} object.
         *
         * @param {string} key the key of the entry to be removed
         */
        remove: function(key) {
          if (capacity < Number.MAX_VALUE) {
            var lruEntry = lruHash[key];

            if (!lruEntry) return;

            if (lruEntry == freshEnd) freshEnd = lruEntry.p;
            if (lruEntry == staleEnd) staleEnd = lruEntry.n;
            link(lruEntry.n,lruEntry.p);

            delete lruHash[key];
          }

          delete data[key];
          size--;
        },


        /**
         * @ngdoc method
         * @name $cacheFactory.Cache#removeAll
         * @kind function
         *
         * @description
         * Clears the cache object of any entries.
         */
        removeAll: function() {
          data = {};
          size = 0;
          lruHash = {};
          freshEnd = staleEnd = null;
        },


        /**
         * @ngdoc method
         * @name $cacheFactory.Cache#destroy
         * @kind function
         *
         * @description
         * Destroys the {@link $cacheFactory.Cache Cache} object entirely,
         * removing it from the {@link $cacheFactory $cacheFactory} set.
         */
        destroy: function() {
          data = null;
          stats = null;
          lruHash = null;
          delete caches[cacheId];
        },


        /**
         * @ngdoc method
         * @name $cacheFactory.Cache#info
         * @kind function
         *
         * @description
         * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.
         *
         * @returns {object} an object with the following properties:
         *   <ul>
         *     <li>**id**: the id of the cache instance</li>
         *     <li>**size**: the number of entries kept in the cache instance</li>
         *     <li>**...**: any additional properties from the options object when creating the
         *       cache.</li>
         *   </ul>
         */
        info: function() {
          return extend({}, stats, {size: size});
        }
      };


      /**
       * makes the `entry` the freshEnd of the LRU linked list
       */
      function refresh(entry) {
        if (entry != freshEnd) {
          if (!staleEnd) {
            staleEnd = entry;
          } else if (staleEnd == entry) {
            staleEnd = entry.n;
          }

          link(entry.n, entry.p);
          link(entry, freshEnd);
          freshEnd = entry;
          freshEnd.n = null;
        }
      }


      /**
       * bidirectionally links two entries of the LRU linked list
       */
      function link(nextEntry, prevEntry) {
        if (nextEntry != prevEntry) {
          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify
          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify
        }
      }
    }


  /**
   * @ngdoc method
   * @name $cacheFactory#info
   *
   * @description
   * Get information about all the caches that have been created
   *
   * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`
   */
    cacheFactory.info = function() {
      var info = {};
      forEach(caches, function(cache, cacheId) {
        info[cacheId] = cache.info();
      });
      return info;
    };


  /**
   * @ngdoc method
   * @name $cacheFactory#get
   *
   * @description
   * Get access to a cache object by the `cacheId` used when it was created.
   *
   * @param {string} cacheId Name or id of a cache to access.
   * @returns {object} Cache object identified by the cacheId or undefined if no such cache.
   */
    cacheFactory.get = function(cacheId) {
      return caches[cacheId];
    };


    return cacheFactory;
  };
}

/**
 * @ngdoc service
 * @name $templateCache
 *
 * @description
 * The first time a template is used, it is loaded in the template cache for quick retrieval. You
 * can load templates directly into the cache in a `script` tag, or by consuming the
 * `$templateCache` service directly.
 *
 * Adding via the `script` tag:
 *
 * ```html
 *   <script type="text/ng-template" id="templateId.html">
 *     <p>This is the content of the template</p>
 *   </script>
 * ```
 *
 * **Note:** the `script` tag containing the template does not need to be included in the `head` of
 * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,
 * element with ng-app attribute), otherwise the template will be ignored.
 *
 * Adding via the $templateCache service:
 *
 * ```js
 * var myApp = angular.module('myApp', []);
 * myApp.run(function($templateCache) {
 *   $templateCache.put('templateId.html', 'This is the content of the template');
 * });
 * ```
 *
 * To retrieve the template later, simply use it in your HTML:
 * ```html
 * <div ng-include=" 'templateId.html' "></div>
 * ```
 *
 * or get it via Javascript:
 * ```js
 * $templateCache.get('templateId.html')
 * ```
 *
 * See {@link ng.$cacheFactory $cacheFactory}.
 *
 */
function $TemplateCacheProvider() {
  this.$get = ['$cacheFactory', function($cacheFactory) {
    return $cacheFactory('templates');
  }];
}

/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!
 *
 * DOM-related variables:
 *
 * - "node" - DOM Node
 * - "element" - DOM Element or Node
 * - "$node" or "$element" - jqLite-wrapped node or element
 *
 *
 * Compiler related stuff:
 *
 * - "linkFn" - linking fn of a single directive
 * - "nodeLinkFn" - function that aggregates all linking fns for a particular node
 * - "childLinkFn" -  function that aggregates all linking fns for child nodes of a particular node
 * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList)
 */


/**
 * @ngdoc service
 * @name $compile
 * @kind function
 *
 * @description
 * Compiles an HTML string or DOM into a template and produces a template function, which
 * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.
 *
 * The compilation is a process of walking the DOM tree and matching DOM elements to
 * {@link ng.$compileProvider#directive directives}.
 *
 * <div class="alert alert-warning">
 * **Note:** This document is an in-depth reference of all directive options.
 * For a gentle introduction to directives with examples of common use cases,
 * see the {@link guide/directive directive guide}.
 * </div>
 *
 * ## Comprehensive Directive API
 *
 * There are many different options for a directive.
 *
 * The difference resides in the return value of the factory function.
 * You can either return a "Directive Definition Object" (see below) that defines the directive properties,
 * or just the `postLink` function (all other properties will have the default values).
 *
 * <div class="alert alert-success">
 * **Best Practice:** It's recommended to use the "directive definition object" form.
 * </div>
 *
 * Here's an example directive declared with a Directive Definition Object:
 *
 * ```js
 *   var myModule = angular.module(...);
 *
 *   myModule.directive('directiveName', function factory(injectables) {
 *     var directiveDefinitionObject = {
 *       priority: 0,
 *       template: '<div></div>', // or // function(tElement, tAttrs) { ... },
 *       // or
 *       // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
 *       transclude: false,
 *       restrict: 'A',
 *       scope: false,
 *       controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
 *       controllerAs: 'stringAlias',
 *       require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
 *       compile: function compile(tElement, tAttrs, transclude) {
 *         return {
 *           pre: function preLink(scope, iElement, iAttrs, controller) { ... },
 *           post: function postLink(scope, iElement, iAttrs, controller) { ... }
 *         }
 *         // or
 *         // return function postLink( ... ) { ... }
 *       },
 *       // or
 *       // link: {
 *       //  pre: function preLink(scope, iElement, iAttrs, controller) { ... },
 *       //  post: function postLink(scope, iElement, iAttrs, controller) { ... }
 *       // }
 *       // or
 *       // link: function postLink( ... ) { ... }
 *     };
 *     return directiveDefinitionObject;
 *   });
 * ```
 *
 * <div class="alert alert-warning">
 * **Note:** Any unspecified options will use the default value. You can see the default values below.
 * </div>
 *
 * Therefore the above can be simplified as:
 *
 * ```js
 *   var myModule = angular.module(...);
 *
 *   myModule.directive('directiveName', function factory(injectables) {
 *     var directiveDefinitionObject = {
 *       link: function postLink(scope, iElement, iAttrs) { ... }
 *     };
 *     return directiveDefinitionObject;
 *     // or
 *     // return function postLink(scope, iElement, iAttrs) { ... }
 *   });
 * ```
 *
 *
 *
 * ### Directive Definition Object
 *
 * The directive definition object provides instructions to the {@link ng.$compile
 * compiler}. The attributes are:
 *
 * #### `priority`
 * When there are multiple directives defined on a single DOM element, sometimes it
 * is necessary to specify the order in which the directives are applied. The `priority` is used
 * to sort the directives before their `compile` functions get called. Priority is defined as a
 * number. Directives with greater numerical `priority` are compiled first. Pre-link functions
 * are also run in priority order, but post-link functions are run in reverse order. The order
 * of directives with the same priority is undefined. The default priority is `0`.
 *
 * #### `terminal`
 * If set to true then the current `priority` will be the last set of directives
 * which will execute (any directives at the current priority will still execute
 * as the order of execution on same `priority` is undefined).
 *
 * #### `scope`
 * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the
 * same element request a new scope, only one new scope is created. The new scope rule does not
 * apply for the root of the template since the root of the template always gets a new scope.
 *
 * **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from
 * normal scope in that it does not prototypically inherit from the parent scope. This is useful
 * when creating reusable components, which should not accidentally read or modify data in the
 * parent scope.
 *
 * The 'isolate' scope takes an object hash which defines a set of local scope properties
 * derived from the parent scope. These local properties are useful for aliasing values for
 * templates. Locals definition is a hash of local scope property to its source:
 *
 * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
 *   always a string since DOM attributes are strings. If no `attr` name is specified  then the
 *   attribute name is assumed to be the same as the local name.
 *   Given `<widget my-attr="hello {{name}}">` and widget definition
 *   of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect
 *   the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the
 *   `localName` property on the widget scope. The `name` is read from the parent scope (not
 *   component scope).
 *
 * * `=` or `=attr` - set up bi-directional binding between a local scope property and the
 *   parent scope property of name defined via the value of the `attr` attribute. If no `attr`
 *   name is specified then the attribute name is assumed to be the same as the local name.
 *   Given `<widget my-attr="parentModel">` and widget definition of
 *   `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
 *   value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
 *   in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
 *   scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
 *   can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional.
 *
 * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
 *   If no `attr` name is specified then the attribute name is assumed to be the same as the
 *   local name. Given `<widget my-attr="count = count + value">` and widget definition of
 *   `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
 *   a function wrapper for the `count = count + value` expression. Often it's desirable to
 *   pass data from the isolated scope via an expression to the parent scope, this can be
 *   done by passing a map of local variable names and values into the expression wrapper fn.
 *   For example, if the expression is `increment(amount)` then we can specify the amount value
 *   by calling the `localFn` as `localFn({amount: 22})`.
 *
 *
 *
 * #### `controller`
 * Controller constructor function. The controller is instantiated before the
 * pre-linking phase and it is shared with other directives (see
 * `require` attribute). This allows the directives to communicate with each other and augment
 * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
 *
 * * `$scope` - Current scope associated with the element
 * * `$element` - Current element
 * * `$attrs` - Current attributes object for the element
 * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope.
 *    The scope can be overridden by an optional first argument.
 *   `function([scope], cloneLinkingFn)`.
 *
 *
 * #### `require`
 * Require another directive and inject its controller as the fourth argument to the linking function. The
 * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the
 * injected argument will be an array in corresponding order. If no such directive can be
 * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with:
 *
 * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
 * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
 * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.
 * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass
 *   `null` to the `link` fn if not found.
 *
 *
 * #### `controllerAs`
 * Controller alias at the directive scope. An alias for the controller so it
 * can be referenced at the directive template. The directive needs to define a scope for this
 * configuration to be used. Useful in the case when directive is used as component.
 *
 *
 * #### `restrict`
 * String of subset of `EACM` which restricts the directive to a specific directive
 * declaration style. If omitted, the default (attributes only) is used.
 *
 * * `E` - Element name: `<my-directive></my-directive>`
 * * `A` - Attribute (default): `<div my-directive="exp"></div>`
 * * `C` - Class: `<div class="my-directive: exp;"></div>`
 * * `M` - Comment: `<!-- directive: my-directive exp -->`
 *
 *
 * #### `template`
 * HTML markup that may:
 * * Replace the contents of the directive's element (default).
 * * Replace the directive's element itself (if `replace` is true - DEPRECATED).
 * * Wrap the contents of the directive's element (if `transclude` is true).
 *
 * Value may be:
 *
 * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.
 * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`
 *   function api below) and returns a string value.
 *
 *
 * #### `templateUrl`
 * Same as `template` but the template is loaded from the specified URL. Because
 * the template loading is asynchronous the compilation/linking is suspended until the template
 * is loaded.
 *
 * You can specify `templateUrl` as a string representing the URL or as a function which takes two
 * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
 * a string value representing the url.  In either case, the template URL is passed through {@link
 * api/ng.$sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.
 *
 *
 * #### `replace` ([*DEPRECATED*!], will be removed in next major release)
 * specify what the template should replace. Defaults to `false`.
 *
 * * `true` - the template will replace the directive's element.
 * * `false` - the template will replace the contents of the directive's element.
 *
 * The replacement process migrates all of the attributes / classes from the old element to the new
 * one. See the {@link guide/directive#creating-custom-directives_creating-directives_template-expanding-directive
 * Directives Guide} for an example.
 *
 * #### `transclude`
 * compile the content of the element and make it available to the directive.
 * Typically used with {@link ng.directive:ngTransclude
 * ngTransclude}. The advantage of transclusion is that the linking function receives a
 * transclusion function which is pre-bound to the correct scope. In a typical setup the widget
 * creates an `isolate` scope, but the transclusion is not a child, but a sibling of the `isolate`
 * scope. This makes it possible for the widget to have private state, and the transclusion to
 * be bound to the parent (pre-`isolate`) scope.
 *
 * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the
 * directive's element or the entire element:
 *
 * * `true` - transclude the content (i.e. the child nodes) of the directive's element.
 * * `'element'` - transclude the whole of the directive's element including any directives on this
 *   element that defined at a lower priority than this directive. When used, the `template`
 *   property is ignored.
 *
 * <div class="alert alert-warning">
 * **Note:** When testing an element transclude directive you must not place the directive at the root of the
 * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives
 * Testing Transclusion Directives}.
 * </div>
 *
 * #### `compile`
 *
 * ```js
 *   function compile(tElement, tAttrs, transclude) { ... }
 * ```
 *
 * The compile function deals with transforming the template DOM. Since most directives do not do
 * template transformation, it is not used often. The compile function takes the following arguments:
 *
 *   * `tElement` - template element - The element where the directive has been declared. It is
 *     safe to do template transformation on the element and child elements only.
 *
 *   * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
 *     between all directive compile functions.
 *
 *   * `transclude` -  [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`
 *
 * <div class="alert alert-warning">
 * **Note:** The template instance and the link instance may be different objects if the template has
 * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that
 * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration
 * should be done in a linking function rather than in a compile function.
 * </div>

 * <div class="alert alert-warning">
 * **Note:** The compile function cannot handle directives that recursively use themselves in their
 * own templates or compile functions. Compiling these directives results in an infinite loop and a
 * stack overflow errors.
 *
 * This can be avoided by manually using $compile in the postLink function to imperatively compile
 * a directive's template instead of relying on automatic template compilation via `template` or
 * `templateUrl` declaration or manual compilation inside the compile function.
 * </div>
 *
 * <div class="alert alert-error">
 * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it
 *   e.g. does not know about the right outer scope. Please use the transclude function that is passed
 *   to the link function instead.
 * </div>

 * A compile function can have a return value which can be either a function or an object.
 *
 * * returning a (post-link) function - is equivalent to registering the linking function via the
 *   `link` property of the config object when the compile function is empty.
 *
 * * returning an object with function(s) registered via `pre` and `post` properties - allows you to
 *   control when a linking function should be called during the linking phase. See info about
 *   pre-linking and post-linking functions below.
 *
 *
 * #### `link`
 * This property is used only if the `compile` property is not defined.
 *
 * ```js
 *   function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
 * ```
 *
 * The link function is responsible for registering DOM listeners as well as updating the DOM. It is
 * executed after the template has been cloned. This is where most of the directive logic will be
 * put.
 *
 *   * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the
 *     directive for registering {@link ng.$rootScope.Scope#$watch watches}.
 *
 *   * `iElement` - instance element - The element where the directive is to be used. It is safe to
 *     manipulate the children of the element only in `postLink` function since the children have
 *     already been linked.
 *
 *   * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
 *     between all directive linking functions.
 *
 *   * `controller` - a controller instance - A controller instance if at least one directive on the
 *     element defines a controller. The controller is shared among all the directives, which allows
 *     the directives to use the controllers as a communication channel.
 *
 *   * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
 *     The scope can be overridden by an optional first argument. This is the same as the `$transclude`
 *     parameter of directive controllers.
 *     `function([scope], cloneLinkingFn)`.
 *
 *
 * #### Pre-linking function
 *
 * Executed before the child elements are linked. Not safe to do DOM transformation since the
 * compiler linking function will fail to locate the correct elements for linking.
 *
 * #### Post-linking function
 *
 * Executed after the child elements are linked. It is safe to do DOM transformation in the post-linking function.
 *
 * <a name="Attributes"></a>
 * ### Attributes
 *
 * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the
 * `link()` or `compile()` functions. It has a variety of uses.
 *
 * accessing *Normalized attribute names:*
 * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.
 * the attributes object allows for normalized access to
 *   the attributes.
 *
 * * *Directive inter-communication:* All directives share the same instance of the attributes
 *   object which allows the directives to use the attributes object as inter directive
 *   communication.
 *
 * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object
 *   allowing other directives to read the interpolated value.
 *
 * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes
 *   that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also
 *   the only way to easily get the actual value because during the linking phase the interpolation
 *   hasn't been evaluated yet and so the value is at this time set to `undefined`.
 *
 * ```js
 * function linkingFn(scope, elm, attrs, ctrl) {
 *   // get the attribute value
 *   console.log(attrs.ngModel);
 *
 *   // change the attribute
 *   attrs.$set('ngModel', 'new value');
 *
 *   // observe changes to interpolated attribute
 *   attrs.$observe('ngModel', function(value) {
 *     console.log('ngModel has changed value to ' + value);
 *   });
 * }
 * ```
 *
 * ## Example
 *
 * <div class="alert alert-warning">
 * **Note**: Typically directives are registered with `module.directive`. The example below is
 * to illustrate how `$compile` works.
 * </div>
 *
 <example module="compileExample">
   <file name="index.html">
    <script>
      angular.module('compileExample', [], function($compileProvider) {
        // configure new 'compile' directive by passing a directive
        // factory function. The factory function injects the '$compile'
        $compileProvider.directive('compile', function($compile) {
          // directive factory creates a link function
          return function(scope, element, attrs) {
            scope.$watch(
              function(scope) {
                 // watch the 'compile' expression for changes
                return scope.$eval(attrs.compile);
              },
              function(value) {
                // when the 'compile' expression changes
                // assign it into the current DOM
                element.html(value);

                // compile the new DOM and link it to the current
                // scope.
                // NOTE: we only compile .childNodes so that
                // we don't get into infinite loop compiling ourselves
                $compile(element.contents())(scope);
              }
            );
          };
        });
      })
      .controller('GreeterController', ['$scope', function($scope) {
        $scope.name = 'Angular';
        $scope.html = 'Hello {{name}}';
      }]);
    </script>
    <div ng-controller="GreeterController">
      <input ng-model="name"> <br>
      <textarea ng-model="html"></textarea> <br>
      <div compile="html"></div>
    </div>
   </file>
   <file name="protractor.js" type="protractor">
     it('should auto compile', function() {
       var textarea = $('textarea');
       var output = $('div[compile]');
       // The initial state reads 'Hello Angular'.
       expect(output.getText()).toBe('Hello Angular');
       textarea.clear();
       textarea.sendKeys('{{name}}!');
       expect(output.getText()).toBe('Angular!');
     });
   </file>
 </example>

 *
 *
 * @param {string|DOMElement} element Element or HTML string to compile into a template function.
 * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives.
 * @param {number} maxPriority only apply directives lower than given priority (Only effects the
 *                 root element(s), not their children)
 * @returns {function(scope, cloneAttachFn=)} a link function which is used to bind template
 * (a DOM element/tree) to a scope. Where:
 *
 *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.
 *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
 *  `template` and call the `cloneAttachFn` function allowing the caller to attach the
 *  cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
 *  called as: <br> `cloneAttachFn(clonedElement, scope)` where:
 *
 *      * `clonedElement` - is a clone of the original `element` passed into the compiler.
 *      * `scope` - is the current scope with which the linking function is working with.
 *
 * Calling the linking function returns the element of the template. It is either the original
 * element passed in, or the clone of the element if the `cloneAttachFn` is provided.
 *
 * After linking the view is not updated until after a call to $digest which typically is done by
 * Angular automatically.
 *
 * If you need access to the bound view, there are two ways to do it:
 *
 * - If you are not asking the linking function to clone the template, create the DOM element(s)
 *   before you send them to the compiler and keep this reference around.
 *   ```js
 *     var element = $compile('<p>{{total}}</p>')(scope);
 *   ```
 *
 * - if on the other hand, you need the element to be cloned, the view reference from the original
 *   example would not point to the clone, but rather to the original template that was cloned. In
 *   this case, you can access the clone via the cloneAttachFn:
 *   ```js
 *     var templateElement = angular.element('<p>{{total}}</p>'),
 *         scope = ....;
 *
 *     var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {
 *       //attach the clone to DOM document at the right place
 *     });
 *
 *     //now we have reference to the cloned DOM via `clonedElement`
 *   ```
 *
 *
 * For information on how the compiler works, see the
 * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.
 */

var $compileMinErr = minErr('$compile');

/**
 * @ngdoc provider
 * @name $compileProvider
 * @kind function
 *
 * @description
 */
$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
function $CompileProvider($provide, $$sanitizeUriProvider) {
  var hasDirectives = {},
      Suffix = 'Directive',
      COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w_\-]+)\s+(.*)$/,
      CLASS_DIRECTIVE_REGEXP = /(([\d\w_\-]+)(?:\:([^;]+))?;?)/;

  // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
  // The assumption is that future DOM event attribute names will begin with
  // 'on' and be composed of only English letters.
  var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;

  /**
   * @ngdoc method
   * @name $compileProvider#directive
   * @kind function
   *
   * @description
   * Register a new directive with the compiler.
   *
   * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which
   *    will match as <code>ng-bind</code>), or an object map of directives where the keys are the
   *    names and the values are the factories.
   * @param {Function|Array} directiveFactory An injectable directive factory function. See
   *    {@link guide/directive} for more info.
   * @returns {ng.$compileProvider} Self for chaining.
   */
   this.directive = function registerDirective(name, directiveFactory) {
    assertNotHasOwnProperty(name, 'directive');
    if (isString(name)) {
      assertArg(directiveFactory, 'directiveFactory');
      if (!hasDirectives.hasOwnProperty(name)) {
        hasDirectives[name] = [];
        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',
          function($injector, $exceptionHandler) {
            var directives = [];
            forEach(hasDirectives[name], function(directiveFactory, index) {
              try {
                var directive = $injector.invoke(directiveFactory);
                if (isFunction(directive)) {
                  directive = { compile: valueFn(directive) };
                } else if (!directive.compile && directive.link) {
                  directive.compile = valueFn(directive.link);
                }
                directive.priority = directive.priority || 0;
                directive.index = index;
                directive.name = directive.name || name;
                directive.require = directive.require || (directive.controller && directive.name);
                directive.restrict = directive.restrict || 'A';
                directives.push(directive);
              } catch (e) {
                $exceptionHandler(e);
              }
            });
            return directives;
          }]);
      }
      hasDirectives[name].push(directiveFactory);
    } else {
      forEach(name, reverseParams(registerDirective));
    }
    return this;
  };


  /**
   * @ngdoc method
   * @name $compileProvider#aHrefSanitizationWhitelist
   * @kind function
   *
   * @description
   * Retrieves or overrides the default regular expression that is used for whitelisting of safe
   * urls during a[href] sanitization.
   *
   * The sanitization is a security measure aimed at prevent XSS attacks via html links.
   *
   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
   * regular expression. If a match is found, the original url is written into the dom. Otherwise,
   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
   *
   * @param {RegExp=} regexp New regexp to whitelist urls with.
   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
   *    chaining otherwise.
   */
  this.aHrefSanitizationWhitelist = function(regexp) {
    if (isDefined(regexp)) {
      $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);
      return this;
    } else {
      return $$sanitizeUriProvider.aHrefSanitizationWhitelist();
    }
  };


  /**
   * @ngdoc method
   * @name $compileProvider#imgSrcSanitizationWhitelist
   * @kind function
   *
   * @description
   * Retrieves or overrides the default regular expression that is used for whitelisting of safe
   * urls during img[src] sanitization.
   *
   * The sanitization is a security measure aimed at prevent XSS attacks via html links.
   *
   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
   * regular expression. If a match is found, the original url is written into the dom. Otherwise,
   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
   *
   * @param {RegExp=} regexp New regexp to whitelist urls with.
   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
   *    chaining otherwise.
   */
  this.imgSrcSanitizationWhitelist = function(regexp) {
    if (isDefined(regexp)) {
      $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);
      return this;
    } else {
      return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();
    }
  };

  this.$get = [
            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',
            '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',
    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,
             $controller,   $rootScope,   $document,   $sce,   $animate,   $$sanitizeUri) {

    var Attributes = function(element, attr) {
      this.$$element = element;
      this.$attr = attr || {};
    };

    Attributes.prototype = {
      /**
       * @ngdoc method
       * @name $compile.directive.Attributes#$normalize
       * @kind function
       *
       * @description
       * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or
       * `data-`) to its normalized, camelCase form.
       *
       * Also there is special case for Moz prefix starting with upper case letter.
       *
       * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
       *
       * @param {string} name Name to normalize
       */
      $normalize: directiveNormalize,


      /**
       * @ngdoc method
       * @name $compile.directive.Attributes#$addClass
       * @kind function
       *
       * @description
       * Adds the CSS class value specified by the classVal parameter to the element. If animations
       * are enabled then an animation will be triggered for the class addition.
       *
       * @param {string} classVal The className value that will be added to the element
       */
      $addClass : function(classVal) {
        if(classVal && classVal.length > 0) {
          $animate.addClass(this.$$element, classVal);
        }
      },

      /**
       * @ngdoc method
       * @name $compile.directive.Attributes#$removeClass
       * @kind function
       *
       * @description
       * Removes the CSS class value specified by the classVal parameter from the element. If
       * animations are enabled then an animation will be triggered for the class removal.
       *
       * @param {string} classVal The className value that will be removed from the element
       */
      $removeClass : function(classVal) {
        if(classVal && classVal.length > 0) {
          $animate.removeClass(this.$$element, classVal);
        }
      },

      /**
       * @ngdoc method
       * @name $compile.directive.Attributes#$updateClass
       * @kind function
       *
       * @description
       * Adds and removes the appropriate CSS class values to the element based on the difference
       * between the new and old CSS class values (specified as newClasses and oldClasses).
       *
       * @param {string} newClasses The current CSS className value
       * @param {string} oldClasses The former CSS className value
       */
      $updateClass : function(newClasses, oldClasses) {
        var toAdd = tokenDifference(newClasses, oldClasses);
        var toRemove = tokenDifference(oldClasses, newClasses);

        if(toAdd.length === 0) {
          $animate.removeClass(this.$$element, toRemove);
        } else if(toRemove.length === 0) {
          $animate.addClass(this.$$element, toAdd);
        } else {
          $animate.setClass(this.$$element, toAdd, toRemove);
        }
      },

      /**
       * Set a normalized attribute on the element in a way such that all directives
       * can share the attribute. This function properly handles boolean attributes.
       * @param {string} key Normalized key. (ie ngAttribute)
       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.
       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.
       *     Defaults to true.
       * @param {string=} attrName Optional none normalized name. Defaults to key.
       */
      $set: function(key, value, writeAttr, attrName) {
        // TODO: decide whether or not to throw an error if "class"
        //is set through this function since it may cause $updateClass to
        //become unstable.

        var booleanKey = getBooleanAttrName(this.$$element[0], key),
            normalizedVal,
            nodeName;

        if (booleanKey) {
          this.$$element.prop(key, value);
          attrName = booleanKey;
        }

        this[key] = value;

        // translate normalized key to actual key
        if (attrName) {
          this.$attr[key] = attrName;
        } else {
          attrName = this.$attr[key];
          if (!attrName) {
            this.$attr[key] = attrName = snake_case(key, '-');
          }
        }

        nodeName = nodeName_(this.$$element);

        // sanitize a[href] and img[src] values
        if ((nodeName === 'A' && key === 'href') ||
            (nodeName === 'IMG' && key === 'src')) {
          this[key] = value = $$sanitizeUri(value, key === 'src');
        }

        if (writeAttr !== false) {
          if (value === null || value === undefined) {
            this.$$element.removeAttr(attrName);
          } else {
            this.$$element.attr(attrName, value);
          }
        }

        // fire observers
        var $$observers = this.$$observers;
        $$observers && forEach($$observers[key], function(fn) {
          try {
            fn(value);
          } catch (e) {
            $exceptionHandler(e);
          }
        });
      },


      /**
       * @ngdoc method
       * @name $compile.directive.Attributes#$observe
       * @kind function
       *
       * @description
       * Observes an interpolated attribute.
       *
       * The observer function will be invoked once during the next `$digest` following
       * compilation. The observer is then invoked whenever the interpolated value
       * changes.
       *
       * @param {string} key Normalized key. (ie ngAttribute) .
       * @param {function(interpolatedValue)} fn Function that will be called whenever
                the interpolated value of the attribute changes.
       *        See the {@link guide/directive#Attributes Directives} guide for more info.
       * @returns {function()} the `fn` parameter.
       */
      $observe: function(key, fn) {
        var attrs = this,
            $$observers = (attrs.$$observers || (attrs.$$observers = {})),
            listeners = ($$observers[key] || ($$observers[key] = []));

        listeners.push(fn);
        $rootScope.$evalAsync(function() {
          if (!listeners.$$inter) {
            // no one registered attribute interpolation function, so lets call it manually
            fn(attrs[key]);
          }
        });
        return fn;
      }
    };

    var startSymbol = $interpolate.startSymbol(),
        endSymbol = $interpolate.endSymbol(),
        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')
            ? identity
            : function denormalizeTemplate(template) {
              return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
        },
        NG_ATTR_BINDING = /^ngAttr[A-Z]/;


    return compile;

    //================================

    function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,
                        previousCompileContext) {
      if (!($compileNodes instanceof jqLite)) {
        // jquery always rewraps, whereas we need to preserve the original selector so that we can
        // modify it.
        $compileNodes = jqLite($compileNodes);
      }
      // We can not compile top level text elements since text nodes can be merged and we will
      // not be able to attach scope data to them, so we will wrap them in <span>
      forEach($compileNodes, function(node, index){
        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\S+/) /* non-empty */ ) {
          $compileNodes[index] = node = jqLite(node).wrap('<span></span>').parent()[0];
        }
      });
      var compositeLinkFn =
              compileNodes($compileNodes, transcludeFn, $compileNodes,
                           maxPriority, ignoreDirective, previousCompileContext);
      safeAddClass($compileNodes, 'ng-scope');
      return function publicLinkFn(scope, cloneConnectFn, transcludeControllers, parentBoundTranscludeFn){
        assertArg(scope, 'scope');
        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
        // and sometimes changes the structure of the DOM.
        var $linkNode = cloneConnectFn
          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
          : $compileNodes;

        forEach(transcludeControllers, function(instance, name) {
          $linkNode.data('$' + name + 'Controller', instance);
        });

        // Attach scope only to non-text nodes.
        for(var i = 0, ii = $linkNode.length; i<ii; i++) {
          var node = $linkNode[i],
              nodeType = node.nodeType;
          if (nodeType === 1 /* element */ || nodeType === 9 /* document */) {
            $linkNode.eq(i).data('$scope', scope);
          }
        }

        if (cloneConnectFn) cloneConnectFn($linkNode, scope);
        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
        return $linkNode;
      };
    }

    function safeAddClass($element, className) {
      try {
        $element.addClass(className);
      } catch(e) {
        // ignore, since it means that we are trying to set class on
        // SVG element, where class name is read-only.
      }
    }

    /**
     * Compile function matches each node in nodeList against the directives. Once all directives
     * for a particular node are collected their compile functions are executed. The compile
     * functions return values - the linking functions - are combined into a composite linking
     * function, which is the a linking function for the node.
     *
     * @param {NodeList} nodeList an array of nodes or NodeList to compile
     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
     *        scope argument is auto-generated to the new child of the transcluded parent scope.
     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then
     *        the rootElement must be set the jqLite collection of the compile root. This is
     *        needed so that the jqLite collection items can be replaced with widgets.
     * @param {number=} maxPriority Max directive priority.
     * @returns {Function} A composite linking function of all of the matched directives or null.
     */
    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
                            previousCompileContext) {
      var linkFns = [],
          attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound;

      for (var i = 0; i < nodeList.length; i++) {
        attrs = new Attributes();

        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
        directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,
                                        ignoreDirective);

        nodeLinkFn = (directives.length)
            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,
                                      null, [], [], previousCompileContext)
            : null;

        if (nodeLinkFn && nodeLinkFn.scope) {
          safeAddClass(attrs.$$element, 'ng-scope');
        }

        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
                      !(childNodes = nodeList[i].childNodes) ||
                      !childNodes.length)
            ? null
            : compileNodes(childNodes,
                 nodeLinkFn ? (
                  (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
                     && nodeLinkFn.transclude) : transcludeFn);

        linkFns.push(nodeLinkFn, childLinkFn);
        linkFnFound = linkFnFound || nodeLinkFn || childLinkFn;
        //use the previous context only for the first element in the virtual group
        previousCompileContext = null;
      }

      // return a linking function if we have found anything, null otherwise
      return linkFnFound ? compositeLinkFn : null;

      function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
        var nodeLinkFn, childLinkFn, node, childScope, i, ii, n, childBoundTranscludeFn;

        // copy nodeList so that linking doesn't break due to live list updates.
        var nodeListLength = nodeList.length,
            stableNodeList = new Array(nodeListLength);
        for (i = 0; i < nodeListLength; i++) {
          stableNodeList[i] = nodeList[i];
        }

        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
          node = stableNodeList[n];
          nodeLinkFn = linkFns[i++];
          childLinkFn = linkFns[i++];

          if (nodeLinkFn) {
            if (nodeLinkFn.scope) {
              childScope = scope.$new();
              jqLite.data(node, '$scope', childScope);
            } else {
              childScope = scope;
            }

            if ( nodeLinkFn.transcludeOnThisElement ) {
              childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude, parentBoundTranscludeFn);

            } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
              childBoundTranscludeFn = parentBoundTranscludeFn;

            } else if (!parentBoundTranscludeFn && transcludeFn) {
              childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);

            } else {
              childBoundTranscludeFn = null;
            }

            nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);

          } else if (childLinkFn) {
            childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
          }
        }
      }
    }

    function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {

      var boundTranscludeFn = function(transcludedScope, cloneFn, controllers) {
        var scopeCreated = false;

        if (!transcludedScope) {
          transcludedScope = scope.$new();
          transcludedScope.$$transcluded = true;
          scopeCreated = true;
        }

        var clone = transcludeFn(transcludedScope, cloneFn, controllers, previousBoundTranscludeFn);
        if (scopeCreated) {
          clone.on('$destroy', function() { transcludedScope.$destroy(); });
        }
        return clone;
      };

      return boundTranscludeFn;
    }

    /**
     * Looks for directives on the given node and adds them to the directive collection which is
     * sorted.
     *
     * @param node Node to search.
     * @param directives An array to which the directives are added to. This array is sorted before
     *        the function returns.
     * @param attrs The shared attrs object which is used to populate the normalized attributes.
     * @param {number=} maxPriority Max directive priority.
     */
    function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {
      var nodeType = node.nodeType,
          attrsMap = attrs.$attr,
          match,
          className;

      switch(nodeType) {
        case 1: /* Element */
          // use the node name: <directive>
          addDirective(directives,
              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority, ignoreDirective);

          // iterate over the attributes
          for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
            var attrStartName = false;
            var attrEndName = false;

            attr = nAttrs[j];
            if (!msie || msie >= 8 || attr.specified) {
              name = attr.name;
              value = trim(attr.value);

              // support ngAttr attribute binding
              ngAttrName = directiveNormalize(name);
              if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
                name = snake_case(ngAttrName.substr(6), '-');
              }

              var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
              if (ngAttrName === directiveNName + 'Start') {
                attrStartName = name;
                attrEndName = name.substr(0, name.length - 5) + 'end';
                name = name.substr(0, name.length - 6);
              }

              nName = directiveNormalize(name.toLowerCase());
              attrsMap[nName] = name;
              if (isNgAttr || !attrs.hasOwnProperty(nName)) {
                  attrs[nName] = value;
                  if (getBooleanAttrName(node, nName)) {
                    attrs[nName] = true; // presence means true
                  }
              }
              addAttrInterpolateDirective(node, directives, value, nName);
              addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
                            attrEndName);
            }
          }

          // use class as directive
          className = node.className;
          if (isString(className) && className !== '') {
            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
              nName = directiveNormalize(match[2]);
              if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {
                attrs[nName] = trim(match[3]);
              }
              className = className.substr(match.index + match[0].length);
            }
          }
          break;
        case 3: /* Text Node */
          addTextInterpolateDirective(directives, node.nodeValue);
          break;
        case 8: /* Comment */
          try {
            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);
            if (match) {
              nName = directiveNormalize(match[1]);
              if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {
                attrs[nName] = trim(match[2]);
              }
            }
          } catch (e) {
            // turns out that under some circumstances IE9 throws errors when one attempts to read
            // comment's node value.
            // Just ignore it and continue. (Can't seem to reproduce in test case.)
          }
          break;
      }

      directives.sort(byPriority);
      return directives;
    }

    /**
     * Given a node with an directive-start it collects all of the siblings until it finds
     * directive-end.
     * @param node
     * @param attrStart
     * @param attrEnd
     * @returns {*}
     */
    function groupScan(node, attrStart, attrEnd) {
      var nodes = [];
      var depth = 0;
      if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {
        var startNode = node;
        do {
          if (!node) {
            throw $compileMinErr('uterdir',
                      "Unterminated attribute, found '{0}' but no matching '{1}' found.",
                      attrStart, attrEnd);
          }
          if (node.nodeType == 1 /** Element **/) {
            if (node.hasAttribute(attrStart)) depth++;
            if (node.hasAttribute(attrEnd)) depth--;
          }
          nodes.push(node);
          node = node.nextSibling;
        } while (depth > 0);
      } else {
        nodes.push(node);
      }

      return jqLite(nodes);
    }

    /**
     * Wrapper for linking function which converts normal linking function into a grouped
     * linking function.
     * @param linkFn
     * @param attrStart
     * @param attrEnd
     * @returns {Function}
     */
    function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
      return function(scope, element, attrs, controllers, transcludeFn) {
        element = groupScan(element[0], attrStart, attrEnd);
        return linkFn(scope, element, attrs, controllers, transcludeFn);
      };
    }

    /**
     * Once the directives have been collected, their compile functions are executed. This method
     * is responsible for inlining directive templates as well as terminating the application
     * of the directives if the terminal directive has been reached.
     *
     * @param {Array} directives Array of collected directives to execute their compile function.
     *        this needs to be pre-sorted by priority order.
     * @param {Node} compileNode The raw DOM node to apply the compile functions to
     * @param {Object} templateAttrs The shared attribute function
     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
     *                                                  scope argument is auto-generated to the new
     *                                                  child of the transcluded parent scope.
     * @param {JQLite} jqCollection If we are working on the root of the compile tree then this
     *                              argument has the root jqLite array so that we can replace nodes
     *                              on it.
     * @param {Object=} originalReplaceDirective An optional directive that will be ignored when
     *                                           compiling the transclusion.
     * @param {Array.<Function>} preLinkFns
     * @param {Array.<Function>} postLinkFns
     * @param {Object} previousCompileContext Context used for previous compilation of the current
     *                                        node
     * @returns {Function} linkFn
     */
    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
                                   jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,
                                   previousCompileContext) {
      previousCompileContext = previousCompileContext || {};

      var terminalPriority = -Number.MAX_VALUE,
          newScopeDirective,
          controllerDirectives = previousCompileContext.controllerDirectives,
          newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
          templateDirective = previousCompileContext.templateDirective,
          nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
          hasTranscludeDirective = false,
          hasTemplate = false,
          hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
          $compileNode = templateAttrs.$$element = jqLite(compileNode),
          directive,
          directiveName,
          $template,
          replaceDirective = originalReplaceDirective,
          childTranscludeFn = transcludeFn,
          linkFn,
          directiveValue;

      // executes all directives on the current element
      for(var i = 0, ii = directives.length; i < ii; i++) {
        directive = directives[i];
        var attrStart = directive.$$start;
        var attrEnd = directive.$$end;

        // collect multiblock sections
        if (attrStart) {
          $compileNode = groupScan(compileNode, attrStart, attrEnd);
        }
        $template = undefined;

        if (terminalPriority > directive.priority) {
          break; // prevent further processing of directives
        }

        if (directiveValue = directive.scope) {
          newScopeDirective = newScopeDirective || directive;

          // skip the check for directives with async templates, we'll check the derived sync
          // directive when the template arrives
          if (!directive.templateUrl) {
            assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,
                              $compileNode);
            if (isObject(directiveValue)) {
              newIsolateScopeDirective = directive;
            }
          }
        }

        directiveName = directive.name;

        if (!directive.templateUrl && directive.controller) {
          directiveValue = directive.controller;
          controllerDirectives = controllerDirectives || {};
          assertNoDuplicate("'" + directiveName + "' controller",
              controllerDirectives[directiveName], directive, $compileNode);
          controllerDirectives[directiveName] = directive;
        }

        if (directiveValue = directive.transclude) {
          hasTranscludeDirective = true;

          // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
          // This option should only be used by directives that know how to safely handle element transclusion,
          // where the transcluded nodes are added or replaced after linking.
          if (!directive.$$tlb) {
            assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);
            nonTlbTranscludeDirective = directive;
          }

          if (directiveValue == 'element') {
            hasElementTranscludeDirective = true;
            terminalPriority = directive.priority;
            $template = $compileNode;
            $compileNode = templateAttrs.$$element =
                jqLite(document.createComment(' ' + directiveName + ': ' +
                                              templateAttrs[directiveName] + ' '));
            compileNode = $compileNode[0];
            replaceWith(jqCollection, sliceArgs($template), compileNode);

            childTranscludeFn = compile($template, transcludeFn, terminalPriority,
                                        replaceDirective && replaceDirective.name, {
                                          // Don't pass in:
                                          // - controllerDirectives - otherwise we'll create duplicates controllers
                                          // - newIsolateScopeDirective or templateDirective - combining templates with
                                          //   element transclusion doesn't make sense.
                                          //
                                          // We need only nonTlbTranscludeDirective so that we prevent putting transclusion
                                          // on the same element more than once.
                                          nonTlbTranscludeDirective: nonTlbTranscludeDirective
                                        });
          } else {
            $template = jqLite(jqLiteClone(compileNode)).contents();
            $compileNode.empty(); // clear contents
            childTranscludeFn = compile($template, transcludeFn);
          }
        }

        if (directive.template) {
          hasTemplate = true;
          assertNoDuplicate('template', templateDirective, directive, $compileNode);
          templateDirective = directive;

          directiveValue = (isFunction(directive.template))
              ? directive.template($compileNode, templateAttrs)
              : directive.template;

          directiveValue = denormalizeTemplate(directiveValue);

          if (directive.replace) {
            replaceDirective = directive;
            if (jqLiteIsTextNode(directiveValue)) {
              $template = [];
            } else {
              $template = jqLite(trim(directiveValue));
            }
            compileNode = $template[0];

            if ($template.length != 1 || compileNode.nodeType !== 1) {
              throw $compileMinErr('tplrt',
                  "Template for directive '{0}' must have exactly one root element. {1}",
                  directiveName, '');
            }

            replaceWith(jqCollection, $compileNode, compileNode);

            var newTemplateAttrs = {$attr: {}};

            // combine directives from the original node and from the template:
            // - take the array of directives for this element
            // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)
            // - collect directives from the template and sort them by priority
            // - combine directives as: processed + template + unprocessed
            var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
            var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));

            if (newIsolateScopeDirective) {
              markDirectivesAsIsolate(templateDirectives);
            }
            directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);

            ii = directives.length;
          } else {
            $compileNode.html(directiveValue);
          }
        }

        if (directive.templateUrl) {
          hasTemplate = true;
          assertNoDuplicate('template', templateDirective, directive, $compileNode);
          templateDirective = directive;

          if (directive.replace) {
            replaceDirective = directive;
          }

          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
              templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
                controllerDirectives: controllerDirectives,
                newIsolateScopeDirective: newIsolateScopeDirective,
                templateDirective: templateDirective,
                nonTlbTranscludeDirective: nonTlbTranscludeDirective
              });
          ii = directives.length;
        } else if (directive.compile) {
          try {
            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);
            if (isFunction(linkFn)) {
              addLinkFns(null, linkFn, attrStart, attrEnd);
            } else if (linkFn) {
              addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);
            }
          } catch (e) {
            $exceptionHandler(e, startingTag($compileNode));
          }
        }

        if (directive.terminal) {
          nodeLinkFn.terminal = true;
          terminalPriority = Math.max(terminalPriority, directive.priority);
        }

      }

      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
      nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
      nodeLinkFn.templateOnThisElement = hasTemplate;
      nodeLinkFn.transclude = childTranscludeFn;

      previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;

      // might be normal or delayed nodeLinkFn depending on if templateUrl is present
      return nodeLinkFn;

      ////////////////////

      function addLinkFns(pre, post, attrStart, attrEnd) {
        if (pre) {
          if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);
          pre.require = directive.require;
          pre.directiveName = directiveName;
          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
            pre = cloneAndAnnotateFn(pre, {isolateScope: true});
          }
          preLinkFns.push(pre);
        }
        if (post) {
          if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);
          post.require = directive.require;
          post.directiveName = directiveName;
          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
            post = cloneAndAnnotateFn(post, {isolateScope: true});
          }
          postLinkFns.push(post);
        }
      }


      function getControllers(directiveName, require, $element, elementControllers) {
        var value, retrievalMethod = 'data', optional = false;
        if (isString(require)) {
          while((value = require.charAt(0)) == '^' || value == '?') {
            require = require.substr(1);
            if (value == '^') {
              retrievalMethod = 'inheritedData';
            }
            optional = optional || value == '?';
          }
          value = null;

          if (elementControllers && retrievalMethod === 'data') {
            value = elementControllers[require];
          }
          value = value || $element[retrievalMethod]('$' + require + 'Controller');

          if (!value && !optional) {
            throw $compileMinErr('ctreq',
                "Controller '{0}', required by directive '{1}', can't be found!",
                require, directiveName);
          }
          return value;
        } else if (isArray(require)) {
          value = [];
          forEach(require, function(require) {
            value.push(getControllers(directiveName, require, $element, elementControllers));
          });
        }
        return value;
      }


      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
        var attrs, $element, i, ii, linkFn, controller, isolateScope, elementControllers = {}, transcludeFn;

        attrs = (compileNode === linkNode)
          ? templateAttrs
          : shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));
        $element = attrs.$$element;

        if (newIsolateScopeDirective) {
          var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;

          isolateScope = scope.$new(true);

          if (templateDirective && (templateDirective === newIsolateScopeDirective ||
              templateDirective === newIsolateScopeDirective.$$originalDirective)) {
            $element.data('$isolateScope', isolateScope);
          } else {
            $element.data('$isolateScopeNoTemplate', isolateScope);
          }



          safeAddClass($element, 'ng-isolate-scope');

          forEach(newIsolateScopeDirective.scope, function(definition, scopeName) {
            var match = definition.match(LOCAL_REGEXP) || [],
                attrName = match[3] || scopeName,
                optional = (match[2] == '?'),
                mode = match[1], // @, =, or &
                lastValue,
                parentGet, parentSet, compare;

            isolateScope.$$isolateBindings[scopeName] = mode + attrName;

            switch (mode) {

              case '@':
                attrs.$observe(attrName, function(value) {
                  isolateScope[scopeName] = value;
                });
                attrs.$$observers[attrName].$$scope = scope;
                if( attrs[attrName] ) {
                  // If the attribute has been provided then we trigger an interpolation to ensure
                  // the value is there for use in the link fn
                  isolateScope[scopeName] = $interpolate(attrs[attrName])(scope);
                }
                break;

              case '=':
                if (optional && !attrs[attrName]) {
                  return;
                }
                parentGet = $parse(attrs[attrName]);
                if (parentGet.literal) {
                  compare = equals;
                } else {
                  compare = function(a,b) { return a === b || (a !== a && b !== b); };
                }
                parentSet = parentGet.assign || function() {
                  // reset the change, or we will throw this exception on every $digest
                  lastValue = isolateScope[scopeName] = parentGet(scope);
                  throw $compileMinErr('nonassign',
                      "Expression '{0}' used with directive '{1}' is non-assignable!",
                      attrs[attrName], newIsolateScopeDirective.name);
                };
                lastValue = isolateScope[scopeName] = parentGet(scope);
                isolateScope.$watch(function parentValueWatch() {
                  var parentValue = parentGet(scope);
                  if (!compare(parentValue, isolateScope[scopeName])) {
                    // we are out of sync and need to copy
                    if (!compare(parentValue, lastValue)) {
                      // parent changed and it has precedence
                      isolateScope[scopeName] = parentValue;
                    } else {
                      // if the parent can be assigned then do so
                      parentSet(scope, parentValue = isolateScope[scopeName]);
                    }
                  }
                  return lastValue = parentValue;
                }, null, parentGet.literal);
                break;

              case '&':
                parentGet = $parse(attrs[attrName]);
                isolateScope[scopeName] = function(locals) {
                  return parentGet(scope, locals);
                };
                break;

              default:
                throw $compileMinErr('iscp',
                    "Invalid isolate scope definition for directive '{0}'." +
                    " Definition: {... {1}: '{2}' ...}",
                    newIsolateScopeDirective.name, scopeName, definition);
            }
          });
        }
        transcludeFn = boundTranscludeFn && controllersBoundTransclude;
        if (controllerDirectives) {
          forEach(controllerDirectives, function(directive) {
            var locals = {
              $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
              $element: $element,
              $attrs: attrs,
              $transclude: transcludeFn
            }, controllerInstance;

            controller = directive.controller;
            if (controller == '@') {
              controller = attrs[directive.name];
            }

            controllerInstance = $controller(controller, locals);
            // For directives with element transclusion the element is a comment,
            // but jQuery .data doesn't support attaching data to comment nodes as it's hard to
            // clean up (http://bugs.jquery.com/ticket/8335).
            // Instead, we save the controllers for the element in a local hash and attach to .data
            // later, once we have the actual element.
            elementControllers[directive.name] = controllerInstance;
            if (!hasElementTranscludeDirective) {
              $element.data('$' + directive.name + 'Controller', controllerInstance);
            }

            if (directive.controllerAs) {
              locals.$scope[directive.controllerAs] = controllerInstance;
            }
          });
        }

        // PRELINKING
        for(i = 0, ii = preLinkFns.length; i < ii; i++) {
          try {
            linkFn = preLinkFns[i];
            linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
                linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);
          } catch (e) {
            $exceptionHandler(e, startingTag($element));
          }
        }

        // RECURSION
        // We only pass the isolate scope, if the isolate directive has a template,
        // otherwise the child elements do not belong to the isolate directive.
        var scopeToChild = scope;
        if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {
          scopeToChild = isolateScope;
        }
        childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);

        // POSTLINKING
        for(i = postLinkFns.length - 1; i >= 0; i--) {
          try {
            linkFn = postLinkFns[i];
            linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
                linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);
          } catch (e) {
            $exceptionHandler(e, startingTag($element));
          }
        }

        // This is the function that is injected as `$transclude`.
        function controllersBoundTransclude(scope, cloneAttachFn) {
          var transcludeControllers;

          // no scope passed
          if (arguments.length < 2) {
            cloneAttachFn = scope;
            scope = undefined;
          }

          if (hasElementTranscludeDirective) {
            transcludeControllers = elementControllers;
          }

          return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers);
        }
      }
    }

    function markDirectivesAsIsolate(directives) {
      // mark all directives as needing isolate scope.
      for (var j = 0, jj = directives.length; j < jj; j++) {
        directives[j] = inherit(directives[j], {$$isolateScope: true});
      }
    }

    /**
     * looks up the directive and decorates it with exception handling and proper parameters. We
     * call this the boundDirective.
     *
     * @param {string} name name of the directive to look up.
     * @param {string} location The directive must be found in specific format.
     *   String containing any of theses characters:
     *
     *   * `E`: element name
     *   * `A': attribute
     *   * `C`: class
     *   * `M`: comment
     * @returns {boolean} true if directive was added.
     */
    function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,
                          endAttrName) {
      if (name === ignoreDirective) return null;
      var match = null;
      if (hasDirectives.hasOwnProperty(name)) {
        for(var directive, directives = $injector.get(name + Suffix),
            i = 0, ii = directives.length; i<ii; i++) {
          try {
            directive = directives[i];
            if ( (maxPriority === undefined || maxPriority > directive.priority) &&
                 directive.restrict.indexOf(location) != -1) {
              if (startAttrName) {
                directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
              }
              tDirectives.push(directive);
              match = directive;
            }
          } catch(e) { $exceptionHandler(e); }
        }
      }
      return match;
    }


    /**
     * When the element is replaced with HTML template then the new attributes
     * on the template need to be merged with the existing attributes in the DOM.
     * The desired effect is to have both of the attributes present.
     *
     * @param {object} dst destination attributes (original DOM)
     * @param {object} src source attributes (from the directive template)
     */
    function mergeTemplateAttributes(dst, src) {
      var srcAttr = src.$attr,
          dstAttr = dst.$attr,
          $element = dst.$$element;

      // reapply the old attributes to the new element
      forEach(dst, function(value, key) {
        if (key.charAt(0) != '$') {
          if (src[key] && src[key] !== value) {
            value += (key === 'style' ? ';' : ' ') + src[key];
          }
          dst.$set(key, value, true, srcAttr[key]);
        }
      });

      // copy the new attributes on the old attrs object
      forEach(src, function(value, key) {
        if (key == 'class') {
          safeAddClass($element, value);
          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;
        } else if (key == 'style') {
          $element.attr('style', $element.attr('style') + ';' + value);
          dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;
          // `dst` will never contain hasOwnProperty as DOM parser won't let it.
          // You will get an "InvalidCharacterError: DOM Exception 5" error if you
          // have an attribute like "has-own-property" or "data-has-own-property", etc.
        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {
          dst[key] = value;
          dstAttr[key] = srcAttr[key];
        }
      });
    }


    function compileTemplateUrl(directives, $compileNode, tAttrs,
        $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
      var linkQueue = [],
          afterTemplateNodeLinkFn,
          afterTemplateChildLinkFn,
          beforeTemplateCompileNode = $compileNode[0],
          origAsyncDirective = directives.shift(),
          // The fact that we have to copy and patch the directive seems wrong!
          derivedSyncDirective = extend({}, origAsyncDirective, {
            templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective
          }),
          templateUrl = (isFunction(origAsyncDirective.templateUrl))
              ? origAsyncDirective.templateUrl($compileNode, tAttrs)
              : origAsyncDirective.templateUrl;

      $compileNode.empty();

      $http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}).
        success(function(content) {
          var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;

          content = denormalizeTemplate(content);

          if (origAsyncDirective.replace) {
            if (jqLiteIsTextNode(content)) {
              $template = [];
            } else {
              $template = jqLite(trim(content));
            }
            compileNode = $template[0];

            if ($template.length != 1 || compileNode.nodeType !== 1) {
              throw $compileMinErr('tplrt',
                  "Template for directive '{0}' must have exactly one root element. {1}",
                  origAsyncDirective.name, templateUrl);
            }

            tempTemplateAttrs = {$attr: {}};
            replaceWith($rootElement, $compileNode, compileNode);
            var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);

            if (isObject(origAsyncDirective.scope)) {
              markDirectivesAsIsolate(templateDirectives);
            }
            directives = templateDirectives.concat(directives);
            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
          } else {
            compileNode = beforeTemplateCompileNode;
            $compileNode.html(content);
          }

          directives.unshift(derivedSyncDirective);

          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,
              childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,
              previousCompileContext);
          forEach($rootElement, function(node, i) {
            if (node == compileNode) {
              $rootElement[i] = $compileNode[0];
            }
          });
          afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);

          while(linkQueue.length) {
            var scope = linkQueue.shift(),
                beforeTemplateLinkNode = linkQueue.shift(),
                linkRootElement = linkQueue.shift(),
                boundTranscludeFn = linkQueue.shift(),
                linkNode = $compileNode[0];

            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
              var oldClasses = beforeTemplateLinkNode.className;

              if (!(previousCompileContext.hasElementTranscludeDirective &&
                  origAsyncDirective.replace)) {
                // it was cloned therefore we have to clone as well.
                linkNode = jqLiteClone(compileNode);
              }

              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);

              // Copy in CSS classes from original node
              safeAddClass(jqLite(linkNode), oldClasses);
            }
            if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
              childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
            } else {
              childBoundTranscludeFn = boundTranscludeFn;
            }
            afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
              childBoundTranscludeFn);
          }
          linkQueue = null;
        }).
        error(function(response, code, headers, config) {
          throw $compileMinErr('tpload', 'Failed to load template: {0}', config.url);
        });

      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
        var childBoundTranscludeFn = boundTranscludeFn;
        if (linkQueue) {
          linkQueue.push(scope);
          linkQueue.push(node);
          linkQueue.push(rootElement);
          linkQueue.push(childBoundTranscludeFn);
        } else {
          if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
            childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
          }
          afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
        }
      };
    }


    /**
     * Sorting function for bound directives.
     */
    function byPriority(a, b) {
      var diff = b.priority - a.priority;
      if (diff !== 0) return diff;
      if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;
      return a.index - b.index;
    }


    function assertNoDuplicate(what, previousDirective, directive, element) {
      if (previousDirective) {
        throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',
            previousDirective.name, directive.name, what, startingTag(element));
      }
    }


      function addTextInterpolateDirective(directives, text) {
        var interpolateFn = $interpolate(text, true);
        if (interpolateFn) {
          directives.push({
            priority: 0,
            compile: function textInterpolateCompileFn(templateNode) {
              // when transcluding a template that has bindings in the root
              // then we don't have a parent and should do this in the linkFn
              var parent = templateNode.parent(), hasCompileParent = parent.length;
              if (hasCompileParent) safeAddClass(templateNode.parent(), 'ng-binding');

              return function textInterpolateLinkFn(scope, node) {
                var parent = node.parent(),
                  bindings = parent.data('$binding') || [];
                bindings.push(interpolateFn);
                parent.data('$binding', bindings);
                if (!hasCompileParent) safeAddClass(parent, 'ng-binding');
                scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
                  node[0].nodeValue = value;
                });
              };
            }
          });
        }
      }


    function getTrustedContext(node, attrNormalizedName) {
      if (attrNormalizedName == "srcdoc") {
        return $sce.HTML;
      }
      var tag = nodeName_(node);
      // maction[xlink:href] can source SVG.  It's not limited to <maction>.
      if (attrNormalizedName == "xlinkHref" ||
          (tag == "FORM" && attrNormalizedName == "action") ||
          (tag != "IMG" && (attrNormalizedName == "src" ||
                            attrNormalizedName == "ngSrc"))) {
        return $sce.RESOURCE_URL;
      }
    }


    function addAttrInterpolateDirective(node, directives, value, name) {
      var interpolateFn = $interpolate(value, true);

      // no interpolation found -> ignore
      if (!interpolateFn) return;


      if (name === "multiple" && nodeName_(node) === "SELECT") {
        throw $compileMinErr("selmulti",
            "Binding to the 'multiple' attribute is not supported. Element: {0}",
            startingTag(node));
      }

      directives.push({
        priority: 100,
        compile: function() {
            return {
              pre: function attrInterpolatePreLinkFn(scope, element, attr) {
                var $$observers = (attr.$$observers || (attr.$$observers = {}));

                if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
                  throw $compileMinErr('nodomevents',
                      "Interpolations for HTML DOM event attributes are disallowed.  Please use the " +
                          "ng- versions (such as ng-click instead of onclick) instead.");
                }

                // we need to interpolate again, in case the attribute value has been updated
                // (e.g. by another directive's compile function)
                interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name));

                // if attribute was updated so that there is no interpolation going on we don't want to
                // register any observers
                if (!interpolateFn) return;

                // TODO(i): this should likely be attr.$set(name, iterpolateFn(scope) so that we reset the
                // actual attr value
                attr[name] = interpolateFn(scope);
                ($$observers[name] || ($$observers[name] = [])).$$inter = true;
                (attr.$$observers && attr.$$observers[name].$$scope || scope).
                  $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {
                    //special case for class attribute addition + removal
                    //so that class changes can tap into the animation
                    //hooks provided by the $animate service. Be sure to
                    //skip animations when the first digest occurs (when
                    //both the new and the old values are the same) since
                    //the CSS classes are the non-interpolated values
                    if(name === 'class' && newValue != oldValue) {
                      attr.$updateClass(newValue, oldValue);
                    } else {
                      attr.$set(name, newValue);
                    }
                  });
              }
            };
          }
      });
    }


    /**
     * This is a special jqLite.replaceWith, which can replace items which
     * have no parents, provided that the containing jqLite collection is provided.
     *
     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes
     *                               in the root of the tree.
     * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep
     *                                  the shell, but replace its DOM node reference.
     * @param {Node} newNode The new DOM node.
     */
    function replaceWith($rootElement, elementsToRemove, newNode) {
      var firstElementToRemove = elementsToRemove[0],
          removeCount = elementsToRemove.length,
          parent = firstElementToRemove.parentNode,
          i, ii;

      if ($rootElement) {
        for(i = 0, ii = $rootElement.length; i < ii; i++) {
          if ($rootElement[i] == firstElementToRemove) {
            $rootElement[i++] = newNode;
            for (var j = i, j2 = j + removeCount - 1,
                     jj = $rootElement.length;
                 j < jj; j++, j2++) {
              if (j2 < jj) {
                $rootElement[j] = $rootElement[j2];
              } else {
                delete $rootElement[j];
              }
            }
            $rootElement.length -= removeCount - 1;
            break;
          }
        }
      }

      if (parent) {
        parent.replaceChild(newNode, firstElementToRemove);
      }
      var fragment = document.createDocumentFragment();
      fragment.appendChild(firstElementToRemove);
      newNode[jqLite.expando] = firstElementToRemove[jqLite.expando];
      for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
        var element = elementsToRemove[k];
        jqLite(element).remove(); // must do this way to clean up expando
        fragment.appendChild(element);
        delete elementsToRemove[k];
      }

      elementsToRemove[0] = newNode;
      elementsToRemove.length = 1;
    }


    function cloneAndAnnotateFn(fn, annotation) {
      return extend(function() { return fn.apply(null, arguments); }, fn, annotation);
    }
  }];
}

var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i;
/**
 * Converts all accepted directives format into proper directive name.
 * @param name Name to normalize
 */
function directiveNormalize(name) {
  return camelCase(name.replace(PREFIX_REGEXP, ''));
}

/**
 * @ngdoc type
 * @name $compile.directive.Attributes
 *
 * @description
 * A shared object between directive compile / linking functions which contains normalized DOM
 * element attributes. The values reflect current binding state `{{ }}`. The normalization is
 * needed since all of these are treated as equivalent in Angular:
 *
 * ```
 *    <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a">
 * ```
 */

/**
 * @ngdoc property
 * @name $compile.directive.Attributes#$attr
 *
 * @description
 * A map of DOM element attribute names to the normalized name. This is
 * needed to do reverse lookup from normalized name back to actual name.
 */


/**
 * @ngdoc method
 * @name $compile.directive.Attributes#$set
 * @kind function
 *
 * @description
 * Set DOM element attribute value.
 *
 *
 * @param {string} name Normalized element attribute name of the property to modify. The name is
 *          reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}
 *          property to the original name.
 * @param {string} value Value to set the attribute to. The value can be an interpolated string.
 */



/**
 * Closure compiler type information
 */

function nodesetLinkingFn(
  /* angular.Scope */ scope,
  /* NodeList */ nodeList,
  /* Element */ rootElement,
  /* function(Function) */ boundTranscludeFn
){}

function directiveLinkingFn(
  /* nodesetLinkingFn */ nodesetLinkingFn,
  /* angular.Scope */ scope,
  /* Node */ node,
  /* Element */ rootElement,
  /* function(Function) */ boundTranscludeFn
){}

function tokenDifference(str1, str2) {
  var values = '',
      tokens1 = str1.split(/\s+/),
      tokens2 = str2.split(/\s+/);

  outer:
  for(var i = 0; i < tokens1.length; i++) {
    var token = tokens1[i];
    for(var j = 0; j < tokens2.length; j++) {
      if(token == tokens2[j]) continue outer;
    }
    values += (values.length > 0 ? ' ' : '') + token;
  }
  return values;
}

/**
 * @ngdoc provider
 * @name $controllerProvider
 * @description
 * The {@link ng.$controller $controller service} is used by Angular to create new
 * controllers.
 *
 * This provider allows controller registration via the
 * {@link ng.$controllerProvider#register register} method.
 */
function $ControllerProvider() {
  var controllers = {},
      CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;


  /**
   * @ngdoc method
   * @name $controllerProvider#register
   * @param {string|Object} name Controller name, or an object map of controllers where the keys are
   *    the names and the values are the constructors.
   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI
   *    annotations in the array notation).
   */
  this.register = function(name, constructor) {
    assertNotHasOwnProperty(name, 'controller');
    if (isObject(name)) {
      extend(controllers, name);
    } else {
      controllers[name] = constructor;
    }
  };


  this.$get = ['$injector', '$window', function($injector, $window) {

    /**
     * @ngdoc service
     * @name $controller
     * @requires $injector
     *
     * @param {Function|string} constructor If called with a function then it's considered to be the
     *    controller constructor function. Otherwise it's considered to be a string which is used
     *    to retrieve the controller constructor using the following steps:
     *
     *    * check if a controller with given name is registered via `$controllerProvider`
     *    * check if evaluating the string on the current scope returns a constructor
     *    * check `window[constructor]` on the global `window` object
     *
     * @param {Object} locals Injection locals for Controller.
     * @return {Object} Instance of given controller.
     *
     * @description
     * `$controller` service is responsible for instantiating controllers.
     *
     * It's just a simple call to {@link auto.$injector $injector}, but extracted into
     * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).
     */
    return function(expression, locals) {
      var instance, match, constructor, identifier;

      if(isString(expression)) {
        match = expression.match(CNTRL_REG),
        constructor = match[1],
        identifier = match[3];
        expression = controllers.hasOwnProperty(constructor)
            ? controllers[constructor]
            : getter(locals.$scope, constructor, true) || getter($window, constructor, true);

        assertArgFn(expression, constructor, true);
      }

      instance = $injector.instantiate(expression, locals);

      if (identifier) {
        if (!(locals && typeof locals.$scope === 'object')) {
          throw minErr('$controller')('noscp',
              "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
              constructor || expression.name, identifier);
        }

        locals.$scope[identifier] = instance;
      }

      return instance;
    };
  }];
}

/**
 * @ngdoc service
 * @name $document
 * @requires $window
 *
 * @description
 * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
 *
 * @example
   <example module="documentExample">
     <file name="index.html">
       <div ng-controller="ExampleController">
         <p>$document title: <b ng-bind="title"></b></p>
         <p>window.document title: <b ng-bind="windowTitle"></b></p>
       </div>
     </file>
     <file name="script.js">
       angular.module('documentExample', [])
         .controller('ExampleController', ['$scope', '$document', function($scope, $document) {
           $scope.title = $document[0].title;
           $scope.windowTitle = angular.element(window.document)[0].title;
         }]);
     </file>
   </example>
 */
function $DocumentProvider(){
  this.$get = ['$window', function(window){
    return jqLite(window.document);
  }];
}

/**
 * @ngdoc service
 * @name $exceptionHandler
 * @requires ng.$log
 *
 * @description
 * Any uncaught exception in angular expressions is delegated to this service.
 * The default implementation simply delegates to `$log.error` which logs it into
 * the browser console.
 *
 * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
 * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
 *
 * ## Example:
 *
 * ```js
 *   angular.module('exceptionOverride', []).factory('$exceptionHandler', function () {
 *     return function (exception, cause) {
 *       exception.message += ' (caused by "' + cause + '")';
 *       throw exception;
 *     };
 *   });
 * ```
 *
 * This example will override the normal action of `$exceptionHandler`, to make angular
 * exceptions fail hard when they happen, instead of just logging to the console.
 *
 * @param {Error} exception Exception associated with the error.
 * @param {string=} cause optional information about the context in which
 *       the error was thrown.
 *
 */
function $ExceptionHandlerProvider() {
  this.$get = ['$log', function($log) {
    return function(exception, cause) {
      $log.error.apply($log, arguments);
    };
  }];
}

/**
 * Parse headers into key value object
 *
 * @param {string} headers Raw headers as a string
 * @returns {Object} Parsed headers as key value object
 */
function parseHeaders(headers) {
  var parsed = {}, key, val, i;

  if (!headers) return parsed;

  forEach(headers.split('\n'), function(line) {
    i = line.indexOf(':');
    key = lowercase(trim(line.substr(0, i)));
    val = trim(line.substr(i + 1));

    if (key) {
      parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
    }
  });

  return parsed;
}


/**
 * Returns a function that provides access to parsed headers.
 *
 * Headers are lazy parsed when first requested.
 * @see parseHeaders
 *
 * @param {(string|Object)} headers Headers to provide access to.
 * @returns {function(string=)} Returns a getter function which if called with:
 *
 *   - if called with single an argument returns a single header value or null
 *   - if called with no arguments returns an object containing all headers.
 */
function headersGetter(headers) {
  var headersObj = isObject(headers) ? headers : undefined;

  return function(name) {
    if (!headersObj) headersObj =  parseHeaders(headers);

    if (name) {
      return headersObj[lowercase(name)] || null;
    }

    return headersObj;
  };
}


/**
 * Chain all given functions
 *
 * This function is used for both request and response transforming
 *
 * @param {*} data Data to transform.
 * @param {function(string=)} headers Http headers getter fn.
 * @param {(Function|Array.<Function>)} fns Function or an array of functions.
 * @returns {*} Transformed data.
 */
function transformData(data, headers, fns) {
  if (isFunction(fns))
    return fns(data, headers);

  forEach(fns, function(fn) {
    data = fn(data, headers);
  });

  return data;
}


function isSuccess(status) {
  return 200 <= status && status < 300;
}


/**
 * @ngdoc provider
 * @name $httpProvider
 * @description
 * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
 * */
function $HttpProvider() {
  var JSON_START = /^\s*(\[|\{[^\{])/,
      JSON_END = /[\}\]]\s*$/,
      PROTECTION_PREFIX = /^\)\]\}',?\n/,
      CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': 'application/json;charset=utf-8'};

  /**
   * @ngdoc property
   * @name $httpProvider#defaults
   * @description
   *
   * Object containing default values for all {@link ng.$http $http} requests.
   *
   * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
   * Defaults value is `'XSRF-TOKEN'`.
   *
   * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
   * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
   *
   * - **`defaults.headers`** - {Object} - Default headers for all $http requests.
   * Refer to {@link ng.$http#setting-http-headers $http} for documentation on
   * setting default headers.
   *     - **`defaults.headers.common`**
   *     - **`defaults.headers.post`**
   *     - **`defaults.headers.put`**
   *     - **`defaults.headers.patch`**
   **/
  var defaults = this.defaults = {
    // transform incoming response data
    transformResponse: [function(data) {
      if (isString(data)) {
        // strip json vulnerability protection prefix
        data = data.replace(PROTECTION_PREFIX, '');
        if (JSON_START.test(data) && JSON_END.test(data))
          data = fromJson(data);
      }
      return data;
    }],

    // transform outgoing request data
    transformRequest: [function(d) {
      return isObject(d) && !isFile(d) && !isBlob(d) ? toJson(d) : d;
    }],

    // default headers
    headers: {
      common: {
        'Accept': 'application/json, text/plain, */*'
      },
      post:   shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
      put:    shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
      patch:  shallowCopy(CONTENT_TYPE_APPLICATION_JSON)
    },

    xsrfCookieName: 'XSRF-TOKEN',
    xsrfHeaderName: 'X-XSRF-TOKEN'
  };

  /**
   * @ngdoc property
   * @name $httpProvider#interceptors
   * @description
   *
   * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}
   * pre-processing of request or postprocessing of responses.
   *
   * These service factories are ordered by request, i.e. they are applied in the same order as the
   * array, on request, but reverse order, on response.
   *
   * {@link ng.$http#interceptors Interceptors detailed info}
   **/
  var interceptorFactories = this.interceptors = [];

  /**
   * For historical reasons, response interceptors are ordered by the order in which
   * they are applied to the response. (This is the opposite of interceptorFactories)
   */
  var responseInterceptorFactories = this.responseInterceptors = [];

  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',
      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {

    var defaultCache = $cacheFactory('$http');

    /**
     * Interceptors stored in reverse order. Inner interceptors before outer interceptors.
     * The reversal is needed so that we can build up the interception chain around the
     * server request.
     */
    var reversedInterceptors = [];

    forEach(interceptorFactories, function(interceptorFactory) {
      reversedInterceptors.unshift(isString(interceptorFactory)
          ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
    });

    forEach(responseInterceptorFactories, function(interceptorFactory, index) {
      var responseFn = isString(interceptorFactory)
          ? $injector.get(interceptorFactory)
          : $injector.invoke(interceptorFactory);

      /**
       * Response interceptors go before "around" interceptors (no real reason, just
       * had to pick one.) But they are already reversed, so we can't use unshift, hence
       * the splice.
       */
      reversedInterceptors.splice(index, 0, {
        response: function(response) {
          return responseFn($q.when(response));
        },
        responseError: function(response) {
          return responseFn($q.reject(response));
        }
      });
    });


    /**
     * @ngdoc service
     * @kind function
     * @name $http
     * @requires ng.$httpBackend
     * @requires $cacheFactory
     * @requires $rootScope
     * @requires $q
     * @requires $injector
     *
     * @description
     * The `$http` service is a core Angular service that facilitates communication with the remote
     * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)
     * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).
     *
     * For unit testing applications that use `$http` service, see
     * {@link ngMock.$httpBackend $httpBackend mock}.
     *
     * For a higher level of abstraction, please check out the {@link ngResource.$resource
     * $resource} service.
     *
     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by
     * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage
     * it is important to familiarize yourself with these APIs and the guarantees they provide.
     *
     *
     * # General usage
     * The `$http` service is a function which takes a single argument — a configuration object —
     * that is used to generate an HTTP request and returns  a {@link ng.$q promise}
     * with two $http specific methods: `success` and `error`.
     *
     * ```js
     *   $http({method: 'GET', url: '/someUrl'}).
     *     success(function(data, status, headers, config) {
     *       // this callback will be called asynchronously
     *       // when the response is available
     *     }).
     *     error(function(data, status, headers, config) {
     *       // called asynchronously if an error occurs
     *       // or server returns response with an error status.
     *     });
     * ```
     *
     * Since the returned value of calling the $http function is a `promise`, you can also use
     * the `then` method to register callbacks, and these callbacks will receive a single argument –
     * an object representing the response. See the API signature and type info below for more
     * details.
     *
     * A response status code between 200 and 299 is considered a success status and
     * will result in the success callback being called. Note that if the response is a redirect,
     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be
     * called for such responses.
     *
     * # Writing Unit Tests that use $http
     * When unit testing (using {@link ngMock ngMock}), it is necessary to call
     * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending
     * request using trained responses.
     *
     * ```
     * $httpBackend.expectGET(...);
     * $http.get(...);
     * $httpBackend.flush();
     * ```
     *
     * # Shortcut methods
     *
     * Shortcut methods are also available. All shortcut methods require passing in the URL, and
     * request data must be passed in for POST/PUT requests.
     *
     * ```js
     *   $http.get('/someUrl').success(successCallback);
     *   $http.post('/someUrl', data).success(successCallback);
     * ```
     *
     * Complete list of shortcut methods:
     *
     * - {@link ng.$http#get $http.get}
     * - {@link ng.$http#head $http.head}
     * - {@link ng.$http#post $http.post}
     * - {@link ng.$http#put $http.put}
     * - {@link ng.$http#delete $http.delete}
     * - {@link ng.$http#jsonp $http.jsonp}
     * - {@link ng.$http#patch $http.patch}
     *
     *
     * # Setting HTTP Headers
     *
     * The $http service will automatically add certain HTTP headers to all requests. These defaults
     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration
     * object, which currently contains this default configuration:
     *
     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
     *   - `Accept: application/json, text/plain, * / *`
     * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)
     *   - `Content-Type: application/json`
     * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)
     *   - `Content-Type: application/json`
     *
     * To add or overwrite these defaults, simply add or remove a property from these configuration
     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object
     * with the lowercased HTTP method name as the key, e.g.
     * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }.
     *
     * The defaults can also be set at runtime via the `$http.defaults` object in the same
     * fashion. For example:
     *
     * ```
     * module.run(function($http) {
     *   $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'
     * });
     * ```
     *
     * In addition, you can supply a `headers` property in the config object passed when
     * calling `$http(config)`, which overrides the defaults without changing them globally.
     *
     * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,
     * Use the `headers` property, setting the desired header to `undefined`. For example:
     *
     * ```js
     * var req = {
     *  method: 'POST',
     *  url: 'http://example.com',
     *  headers: {
     *    'Content-Type': undefined
     *  },
     *  data: { test: 'test' },
     * }
     *
     * $http(req).success(function(){...}).error(function(){...});
     * ```
     *
     * # Transforming Requests and Responses
     *
     * Both requests and responses can be transformed using transform functions. By default, Angular
     * applies these transformations:
     *
     * Request transformations:
     *
     * - If the `data` property of the request configuration object contains an object, serialize it
     *   into JSON format.
     *
     * Response transformations:
     *
     *  - If XSRF prefix is detected, strip it (see Security Considerations section below).
     *  - If JSON response is detected, deserialize it using a JSON parser.
     *
     * To globally augment or override the default transforms, modify the
     * `$httpProvider.defaults.transformRequest` and `$httpProvider.defaults.transformResponse`
     * properties. These properties are by default an array of transform functions, which allows you
     * to `push` or `unshift` a new transformation function into the transformation chain. You can
     * also decide to completely override any default transformations by assigning your
     * transformation functions to these properties directly without the array wrapper.  These defaults
     * are again available on the $http factory at run-time, which may be useful if you have run-time
     * services you wish to be involved in your transformations.
     *
     * Similarly, to locally override the request/response transforms, augment the
     * `transformRequest` and/or `transformResponse` properties of the configuration object passed
     * into `$http`.
     *
     *
     * # Caching
     *
     * To enable caching, set the request configuration `cache` property to `true` (to use default
     * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).
     * When the cache is enabled, `$http` stores the response from the server in the specified
     * cache. The next time the same request is made, the response is served from the cache without
     * sending a request to the server.
     *
     * Note that even if the response is served from cache, delivery of the data is asynchronous in
     * the same way that real requests are.
     *
     * If there are multiple GET requests for the same URL that should be cached using the same
     * cache, but the cache is not populated yet, only one request to the server will be made and
     * the remaining requests will be fulfilled using the response from the first request.
     *
     * You can change the default cache to a new object (built with
     * {@link ng.$cacheFactory `$cacheFactory`}) by updating the
     * {@link ng.$http#properties_defaults `$http.defaults.cache`} property. All requests who set
     * their `cache` property to `true` will now use this cache object.
     *
     * If you set the default cache to `false` then only requests that specify their own custom
     * cache object will be cached.
     *
     * # Interceptors
     *
     * Before you start creating interceptors, be sure to understand the
     * {@link ng.$q $q and deferred/promise APIs}.
     *
     * For purposes of global error handling, authentication, or any kind of synchronous or
     * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be
     * able to intercept requests before they are handed to the server and
     * responses before they are handed over to the application code that
     * initiated these requests. The interceptors leverage the {@link ng.$q
     * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.
     *
     * The interceptors are service factories that are registered with the `$httpProvider` by
     * adding them to the `$httpProvider.interceptors` array. The factory is called and
     * injected with dependencies (if specified) and returns the interceptor.
     *
     * There are two kinds of interceptors (and two kinds of rejection interceptors):
     *
     *   * `request`: interceptors get called with a http `config` object. The function is free to
     *     modify the `config` object or create a new one. The function needs to return the `config`
     *     object directly, or a promise containing the `config` or a new `config` object.
     *   * `requestError`: interceptor gets called when a previous interceptor threw an error or
     *     resolved with a rejection.
     *   * `response`: interceptors get called with http `response` object. The function is free to
     *     modify the `response` object or create a new one. The function needs to return the `response`
     *     object directly, or as a promise containing the `response` or a new `response` object.
     *   * `responseError`: interceptor gets called when a previous interceptor threw an error or
     *     resolved with a rejection.
     *
     *
     * ```js
     *   // register the interceptor as a service
     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
     *     return {
     *       // optional method
     *       'request': function(config) {
     *         // do something on success
     *         return config;
     *       },
     *
     *       // optional method
     *      'requestError': function(rejection) {
     *         // do something on error
     *         if (canRecover(rejection)) {
     *           return responseOrNewPromise
     *         }
     *         return $q.reject(rejection);
     *       },
     *
     *
     *
     *       // optional method
     *       'response': function(response) {
     *         // do something on success
     *         return response;
     *       },
     *
     *       // optional method
     *      'responseError': function(rejection) {
     *         // do something on error
     *         if (canRecover(rejection)) {
     *           return responseOrNewPromise
     *         }
     *         return $q.reject(rejection);
     *       }
     *     };
     *   });
     *
     *   $httpProvider.interceptors.push('myHttpInterceptor');
     *
     *
     *   // alternatively, register the interceptor via an anonymous factory
     *   $httpProvider.interceptors.push(function($q, dependency1, dependency2) {
     *     return {
     *      'request': function(config) {
     *          // same as above
     *       },
     *
     *       'response': function(response) {
     *          // same as above
     *       }
     *     };
     *   });
     * ```
     *
     * # Response interceptors (DEPRECATED)
     *
     * Before you start creating interceptors, be sure to understand the
     * {@link ng.$q $q and deferred/promise APIs}.
     *
     * For purposes of global error handling, authentication or any kind of synchronous or
     * asynchronous preprocessing of received responses, it is desirable to be able to intercept
     * responses for http requests before they are handed over to the application code that
     * initiated these requests. The response interceptors leverage the {@link ng.$q
     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.
     *
     * The interceptors are service factories that are registered with the $httpProvider by
     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and
     * injected with dependencies (if specified) and returns the interceptor  — a function that
     * takes a {@link ng.$q promise} and returns the original or a new promise.
     *
     * ```js
     *   // register the interceptor as a service
     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
     *     return function(promise) {
     *       return promise.then(function(response) {
     *         // do something on success
     *         return response;
     *       }, function(response) {
     *         // do something on error
     *         if (canRecover(response)) {
     *           return responseOrNewPromise
     *         }
     *         return $q.reject(response);
     *       });
     *     }
     *   });
     *
     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');
     *
     *
     *   // register the interceptor via an anonymous factory
     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {
     *     return function(promise) {
     *       // same as above
     *     }
     *   });
     * ```
     *
     *
     * # Security Considerations
     *
     * When designing web applications, consider security threats from:
     *
     * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
     * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)
     *
     * Both server and the client must cooperate in order to eliminate these threats. Angular comes
     * pre-configured with strategies that address these issues, but for this to work backend server
     * cooperation is required.
     *
     * ## JSON Vulnerability Protection
     *
     * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
     * allows third party website to turn your JSON resource URL into
     * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To
     * counter this your server can prefix all JSON requests with following string `")]}',\n"`.
     * Angular will automatically strip the prefix before processing it as JSON.
     *
     * For example if your server needs to return:
     * ```js
     * ['one','two']
     * ```
     *
     * which is vulnerable to attack, your server can return:
     * ```js
     * )]}',
     * ['one','two']
     * ```
     *
     * Angular will strip the prefix, before processing the JSON.
     *
     *
     * ## Cross Site Request Forgery (XSRF) Protection
     *
     * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which
     * an unauthorized site can gain your user's private data. Angular provides a mechanism
     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
     * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only
     * JavaScript that runs on your domain could read the cookie, your server can be assured that
     * the XHR came from JavaScript running on your domain. The header will not be set for
     * cross-domain requests.
     *
     * To take advantage of this, your server needs to set a token in a JavaScript readable session
     * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure
     * that only JavaScript running on your domain could have sent the request. The token must be
     * unique for each user and must be verifiable by the server (to prevent the JavaScript from
     * making up its own tokens). We recommend that the token is a digest of your site's
     * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)
     * for added security.
     *
     * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
     * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
     * or the per-request config object.
     *
     *
     * @param {object} config Object describing the request to be made and how it should be
     *    processed. The object has following properties:
     *
     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)
     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.
     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned
     *      to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be
     *      JSONified.
     *    - **data** – `{string|Object}` – Data to be sent as the request message data.
     *    - **headers** – `{Object}` – Map of strings or functions which return strings representing
     *      HTTP headers to send to the server. If the return value of a function is null, the
     *      header will not be sent.
     *    - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.
     *    - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.
     *    - **transformRequest** –
     *      `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
     *      transform function or an array of such functions. The transform function takes the http
     *      request body and headers and returns its transformed (typically serialized) version.
     *    - **transformResponse** –
     *      `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
     *      transform function or an array of such functions. The transform function takes the http
     *      response body and headers and returns its transformed (typically deserialized) version.
     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
     *      GET request, otherwise if a cache instance built with
     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
     *      caching.
     *    - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
     *      that should abort the request when resolved.
     *    - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the
     *      XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)
     *      for more information.
     *    - **responseType** - `{string}` - see
     *      [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).
     *
     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
     *   standard `then` method and two http specific methods: `success` and `error`. The `then`
     *   method takes two arguments a success and an error callback which will be called with a
     *   response object. The `success` and `error` methods take a single argument - a function that
     *   will be called when the request succeeds or fails respectively. The arguments passed into
     *   these functions are destructured representation of the response object passed into the
     *   `then` method. The response object has these properties:
     *
     *   - **data** – `{string|Object}` – The response body transformed with the transform
     *     functions.
     *   - **status** – `{number}` – HTTP status code of the response.
     *   - **headers** – `{function([headerName])}` – Header getter function.
     *   - **config** – `{Object}` – The configuration object that was used to generate the request.
     *   - **statusText** – `{string}` – HTTP status text of the response.
     *
     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending
     *   requests. This is primarily meant to be used for debugging purposes.
     *
     *
     * @example
<example module="httpExample">
<file name="index.html">
  <div ng-controller="FetchController">
    <select ng-model="method">
      <option>GET</option>
      <option>JSONP</option>
    </select>
    <input type="text" ng-model="url" size="80"/>
    <button id="fetchbtn" ng-click="fetch()">fetch</button><br>
    <button id="samplegetbtn" ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button>
    <button id="samplejsonpbtn"
      ng-click="updateModel('JSONP',
                    'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
      Sample JSONP
    </button>
    <button id="invalidjsonpbtn"
      ng-click="updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
        Invalid JSONP
      </button>
    <pre>http status code: {{status}}</pre>
    <pre>http response data: {{data}}</pre>
  </div>
</file>
<file name="script.js">
  angular.module('httpExample', [])
    .controller('FetchController', ['$scope', '$http', '$templateCache',
      function($scope, $http, $templateCache) {
        $scope.method = 'GET';
        $scope.url = 'http-hello.html';

        $scope.fetch = function() {
          $scope.code = null;
          $scope.response = null;

          $http({method: $scope.method, url: $scope.url, cache: $templateCache}).
            success(function(data, status) {
              $scope.status = status;
              $scope.data = data;
            }).
            error(function(data, status) {
              $scope.data = data || "Request failed";
              $scope.status = status;
          });
        };

        $scope.updateModel = function(method, url) {
          $scope.method = method;
          $scope.url = url;
        };
      }]);
</file>
<file name="http-hello.html">
  Hello, $http!
</file>
<file name="protractor.js" type="protractor">
  var status = element(by.binding('status'));
  var data = element(by.binding('data'));
  var fetchBtn = element(by.id('fetchbtn'));
  var sampleGetBtn = element(by.id('samplegetbtn'));
  var sampleJsonpBtn = element(by.id('samplejsonpbtn'));
  var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));

  it('should make an xhr GET request', function() {
    sampleGetBtn.click();
    fetchBtn.click();
    expect(status.getText()).toMatch('200');
    expect(data.getText()).toMatch(/Hello, \$http!/);
  });

// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185
// it('should make a JSONP request to angularjs.org', function() {
//   sampleJsonpBtn.click();
//   fetchBtn.click();
//   expect(status.getText()).toMatch('200');
//   expect(data.getText()).toMatch(/Super Hero!/);
// });

  it('should make JSONP request to invalid URL and invoke the error handler',
      function() {
    invalidJsonpBtn.click();
    fetchBtn.click();
    expect(status.getText()).toMatch('0');
    expect(data.getText()).toMatch('Request failed');
  });
</file>
</example>
     */
    function $http(requestConfig) {
      var config = {
        method: 'get',
        transformRequest: defaults.transformRequest,
        transformResponse: defaults.transformResponse
      };
      var headers = mergeHeaders(requestConfig);

      extend(config, requestConfig);
      config.headers = headers;
      config.method = uppercase(config.method);

      var serverRequest = function(config) {
        headers = config.headers;
        var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);

        // strip content-type if data is undefined
        if (isUndefined(reqData)) {
          forEach(headers, function(value, header) {
            if (lowercase(header) === 'content-type') {
                delete headers[header];
            }
          });
        }

        if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
          config.withCredentials = defaults.withCredentials;
        }

        // send request
        return sendReq(config, reqData, headers).then(transformResponse, transformResponse);
      };

      var chain = [serverRequest, undefined];
      var promise = $q.when(config);

      // apply interceptors
      forEach(reversedInterceptors, function(interceptor) {
        if (interceptor.request || interceptor.requestError) {
          chain.unshift(interceptor.request, interceptor.requestError);
        }
        if (interceptor.response || interceptor.responseError) {
          chain.push(interceptor.response, interceptor.responseError);
        }
      });

      while(chain.length) {
        var thenFn = chain.shift();
        var rejectFn = chain.shift();

        promise = promise.then(thenFn, rejectFn);
      }

      promise.success = function(fn) {
        promise.then(function(response) {
          fn(response.data, response.status, response.headers, config);
        });
        return promise;
      };

      promise.error = function(fn) {
        promise.then(null, function(response) {
          fn(response.data, response.status, response.headers, config);
        });
        return promise;
      };

      return promise;

      function transformResponse(response) {
        // make a copy since the response must be cacheable
        var resp = extend({}, response, {
          data: transformData(response.data, response.headers, config.transformResponse)
        });
        return (isSuccess(response.status))
          ? resp
          : $q.reject(resp);
      }

      function mergeHeaders(config) {
        var defHeaders = defaults.headers,
            reqHeaders = extend({}, config.headers),
            defHeaderName, lowercaseDefHeaderName, reqHeaderName;

        defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);

        // using for-in instead of forEach to avoid unecessary iteration after header has been found
        defaultHeadersIteration:
        for (defHeaderName in defHeaders) {
          lowercaseDefHeaderName = lowercase(defHeaderName);

          for (reqHeaderName in reqHeaders) {
            if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {
              continue defaultHeadersIteration;
            }
          }

          reqHeaders[defHeaderName] = defHeaders[defHeaderName];
        }

        // execute if header value is a function for merged headers
        execHeaders(reqHeaders);
        return reqHeaders;

        function execHeaders(headers) {
          var headerContent;

          forEach(headers, function(headerFn, header) {
            if (isFunction(headerFn)) {
              headerContent = headerFn();
              if (headerContent != null) {
                headers[header] = headerContent;
              } else {
                delete headers[header];
              }
            }
          });
        }
      }
    }

    $http.pendingRequests = [];

    /**
     * @ngdoc method
     * @name $http#get
     *
     * @description
     * Shortcut method to perform `GET` request.
     *
     * @param {string} url Relative or absolute URL specifying the destination of the request
     * @param {Object=} config Optional configuration object
     * @returns {HttpPromise} Future object
     */

    /**
     * @ngdoc method
     * @name $http#delete
     *
     * @description
     * Shortcut method to perform `DELETE` request.
     *
     * @param {string} url Relative or absolute URL specifying the destination of the request
     * @param {Object=} config Optional configuration object
     * @returns {HttpPromise} Future object
     */

    /**
     * @ngdoc method
     * @name $http#head
     *
     * @description
     * Shortcut method to perform `HEAD` request.
     *
     * @param {string} url Relative or absolute URL specifying the destination of the request
     * @param {Object=} config Optional configuration object
     * @returns {HttpPromise} Future object
     */

    /**
     * @ngdoc method
     * @name $http#jsonp
     *
     * @description
     * Shortcut method to perform `JSONP` request.
     *
     * @param {string} url Relative or absolute URL specifying the destination of the request.
     *                     The name of the callback should be the string `JSON_CALLBACK`.
     * @param {Object=} config Optional configuration object
     * @returns {HttpPromise} Future object
     */
    createShortMethods('get', 'delete', 'head', 'jsonp');

    /**
     * @ngdoc method
     * @name $http#post
     *
     * @description
     * Shortcut method to perform `POST` request.
     *
     * @param {string} url Relative or absolute URL specifying the destination of the request
     * @param {*} data Request content
     * @param {Object=} config Optional configuration object
     * @returns {HttpPromise} Future object
     */

    /**
     * @ngdoc method
     * @name $http#put
     *
     * @description
     * Shortcut method to perform `PUT` request.
     *
     * @param {string} url Relative or absolute URL specifying the destination of the request
     * @param {*} data Request content
     * @param {Object=} config Optional configuration object
     * @returns {HttpPromise} Future object
     */

    /**
     * @ngdoc method
     * @name $http#patch
     *
     * @description
     * Shortcut method to perform `PATCH` request.
     *
     * @param {string} url Relative or absolute URL specifying the destination of the request
     * @param {*} data Request content
     * @param {Object=} config Optional configuration object
     * @returns {HttpPromise} Future object
     */
    createShortMethodsWithData('post', 'put', 'patch');

    /**
     * @ngdoc property
     * @name $http#defaults
     *
     * @description
     * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of
     * default headers, withCredentials as well as request and response transformations.
     *
     * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above.
     */
    $http.defaults = defaults;


    return $http;


    function createShortMethods(names) {
      forEach(arguments, function(name) {
        $http[name] = function(url, config) {
          return $http(extend(config || {}, {
            method: name,
            url: url
          }));
        };
      });
    }


    function createShortMethodsWithData(name) {
      forEach(arguments, function(name) {
        $http[name] = function(url, data, config) {
          return $http(extend(config || {}, {
            method: name,
            url: url,
            data: data
          }));
        };
      });
    }


    /**
     * Makes the request.
     *
     * !!! ACCESSES CLOSURE VARS:
     * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
     */
    function sendReq(config, reqData, reqHeaders) {
      var deferred = $q.defer(),
          promise = deferred.promise,
          cache,
          cachedResp,
          url = buildUrl(config.url, config.params);

      $http.pendingRequests.push(config);
      promise.then(removePendingReq, removePendingReq);


      if ((config.cache || defaults.cache) && config.cache !== false &&
          (config.method === 'GET' || config.method === 'JSONP')) {
        cache = isObject(config.cache) ? config.cache
              : isObject(defaults.cache) ? defaults.cache
              : defaultCache;
      }

      if (cache) {
        cachedResp = cache.get(url);
        if (isDefined(cachedResp)) {
          if (isPromiseLike(cachedResp)) {
            // cached request has already been sent, but there is no response yet
            cachedResp.then(removePendingReq, removePendingReq);
            return cachedResp;
          } else {
            // serving from cache
            if (isArray(cachedResp)) {
              resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
            } else {
              resolvePromise(cachedResp, 200, {}, 'OK');
            }
          }
        } else {
          // put the promise for the non-transformed response into cache as a placeholder
          cache.put(url, promise);
        }
      }


      // if we won't have the response in cache, set the xsrf headers and
      // send the request to the backend
      if (isUndefined(cachedResp)) {
        var xsrfValue = urlIsSameOrigin(config.url)
            ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]
            : undefined;
        if (xsrfValue) {
          reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
        }

        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
            config.withCredentials, config.responseType);
      }

      return promise;


      /**
       * Callback registered to $httpBackend():
       *  - caches the response if desired
       *  - resolves the raw $http promise
       *  - calls $apply
       */
      function done(status, response, headersString, statusText) {
        if (cache) {
          if (isSuccess(status)) {
            cache.put(url, [status, response, parseHeaders(headersString), statusText]);
          } else {
            // remove promise from the cache
            cache.remove(url);
          }
        }

        resolvePromise(response, status, headersString, statusText);
        if (!$rootScope.$$phase) $rootScope.$apply();
      }


      /**
       * Resolves the raw $http promise.
       */
      function resolvePromise(response, status, headers, statusText) {
        // normalize internal statuses to 0
        status = Math.max(status, 0);

        (isSuccess(status) ? deferred.resolve : deferred.reject)({
          data: response,
          status: status,
          headers: headersGetter(headers),
          config: config,
          statusText : statusText
        });
      }


      function removePendingReq() {
        var idx = indexOf($http.pendingRequests, config);
        if (idx !== -1) $http.pendingRequests.splice(idx, 1);
      }
    }


    function buildUrl(url, params) {
      if (!params) return url;
      var parts = [];
      forEachSorted(params, function(value, key) {
        if (value === null || isUndefined(value)) return;
        if (!isArray(value)) value = [value];

        forEach(value, function(v) {
          if (isObject(v)) {
            if (isDate(v)){
              v = v.toISOString();
            } else {
              v = toJson(v);
            }
          }
          parts.push(encodeUriQuery(key) + '=' +
                     encodeUriQuery(v));
        });
      });
      if(parts.length > 0) {
        url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
      }
      return url;
    }
  }];
}

function createXhr(method) {
    //if IE and the method is not RFC2616 compliant, or if XMLHttpRequest
    //is not available, try getting an ActiveXObject. Otherwise, use XMLHttpRequest
    //if it is available
    if (msie <= 8 && (!method.match(/^(get|post|head|put|delete|options)$/i) ||
      !window.XMLHttpRequest)) {
      return new window.ActiveXObject("Microsoft.XMLHTTP");
    } else if (window.XMLHttpRequest) {
      return new window.XMLHttpRequest();
    }

    throw minErr('$httpBackend')('noxhr', "This browser does not support XMLHttpRequest.");
}

/**
 * @ngdoc service
 * @name $httpBackend
 * @requires $window
 * @requires $document
 *
 * @description
 * HTTP backend used by the {@link ng.$http service} that delegates to
 * XMLHttpRequest object or JSONP and deals with browser incompatibilities.
 *
 * You should never need to use this service directly, instead use the higher-level abstractions:
 * {@link ng.$http $http} or {@link ngResource.$resource $resource}.
 *
 * During testing this implementation is swapped with {@link ngMock.$httpBackend mock
 * $httpBackend} which can be trained with responses.
 */
function $HttpBackendProvider() {
  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
    return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);
  }];
}

function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {
  var ABORTED = -1;

  // TODO(vojta): fix the signature
  return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
    var status;
    $browser.$$incOutstandingRequestCount();
    url = url || $browser.url();

    if (lowercase(method) == 'jsonp') {
      var callbackId = '_' + (callbacks.counter++).toString(36);
      callbacks[callbackId] = function(data) {
        callbacks[callbackId].data = data;
        callbacks[callbackId].called = true;
      };

      var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
          callbackId, function(status, text) {
        completeRequest(callback, status, callbacks[callbackId].data, "", text);
        callbacks[callbackId] = noop;
      });
    } else {

      var xhr = createXhr(method);

      xhr.open(method, url, true);
      forEach(headers, function(value, key) {
        if (isDefined(value)) {
            xhr.setRequestHeader(key, value);
        }
      });

      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the
      // response is in the cache. the promise api will ensure that to the app code the api is
      // always async
      xhr.onreadystatechange = function() {
        // onreadystatechange might get called multiple times with readyState === 4 on mobile webkit caused by
        // xhrs that are resolved while the app is in the background (see #5426).
        // since calling completeRequest sets the `xhr` variable to null, we just check if it's not null before
        // continuing
        //
        // we can't set xhr.onreadystatechange to undefined or delete it because that breaks IE8 (method=PATCH) and
        // Safari respectively.
        if (xhr && xhr.readyState == 4) {
          var responseHeaders = null,
              response = null,
              statusText = '';

          if(status !== ABORTED) {
            responseHeaders = xhr.getAllResponseHeaders();

            // responseText is the old-school way of retrieving response (supported by IE8 & 9)
            // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
            response = ('response' in xhr) ? xhr.response : xhr.responseText;
          }

          // Accessing statusText on an aborted xhr object will
          // throw an 'c00c023f error' in IE9 and lower, don't touch it.
          if (!(status === ABORTED && msie < 10)) {
            statusText = xhr.statusText;
          }

          completeRequest(callback,
              status || xhr.status,
              response,
              responseHeaders,
              statusText);
        }
      };

      if (withCredentials) {
        xhr.withCredentials = true;
      }

      if (responseType) {
        try {
          xhr.responseType = responseType;
        } catch (e) {
          // WebKit added support for the json responseType value on 09/03/2013
          // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are
          // known to throw when setting the value "json" as the response type. Other older
          // browsers implementing the responseType
          //
          // The json response type can be ignored if not supported, because JSON payloads are
          // parsed on the client-side regardless.
          if (responseType !== 'json') {
            throw e;
          }
        }
      }

      xhr.send(post || null);
    }

    if (timeout > 0) {
      var timeoutId = $browserDefer(timeoutRequest, timeout);
    } else if (isPromiseLike(timeout)) {
      timeout.then(timeoutRequest);
    }


    function timeoutRequest() {
      status = ABORTED;
      jsonpDone && jsonpDone();
      xhr && xhr.abort();
    }

    function completeRequest(callback, status, response, headersString, statusText) {
      // cancel timeout and subsequent timeout promise resolution
      timeoutId && $browserDefer.cancel(timeoutId);
      jsonpDone = xhr = null;

      // fix status code when it is 0 (0 status is undocumented).
      // Occurs when accessing file resources or on Android 4.1 stock browser
      // while retrieving files from application cache.
      if (status === 0) {
        status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;
      }

      // normalize IE bug (http://bugs.jquery.com/ticket/1450)
      status = status === 1223 ? 204 : status;
      statusText = statusText || '';

      callback(status, response, headersString, statusText);
      $browser.$$completeOutstandingRequest(noop);
    }
  };

  function jsonpReq(url, callbackId, done) {
    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:
    // - fetches local scripts via XHR and evals them
    // - adds and immediately removes script elements from the document
    var script = rawDocument.createElement('script'), callback = null;
    script.type = "text/javascript";
    script.src = url;
    script.async = true;

    callback = function(event) {
      removeEventListenerFn(script, "load", callback);
      removeEventListenerFn(script, "error", callback);
      rawDocument.body.removeChild(script);
      script = null;
      var status = -1;
      var text = "unknown";

      if (event) {
        if (event.type === "load" && !callbacks[callbackId].called) {
          event = { type: "error" };
        }
        text = event.type;
        status = event.type === "error" ? 404 : 200;
      }

      if (done) {
        done(status, text);
      }
    };

    addEventListenerFn(script, "load", callback);
    addEventListenerFn(script, "error", callback);

    if (msie <= 8) {
      script.onreadystatechange = function() {
        if (isString(script.readyState) && /loaded|complete/.test(script.readyState)) {
          script.onreadystatechange = null;
          callback({
            type: 'load'
          });
        }
      };
    }

    rawDocument.body.appendChild(script);
    return callback;
  }
}

var $interpolateMinErr = minErr('$interpolate');

/**
 * @ngdoc provider
 * @name $interpolateProvider
 * @kind function
 *
 * @description
 *
 * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
 *
 * @example
<example module="customInterpolationApp">
<file name="index.html">
<script>
  var customInterpolationApp = angular.module('customInterpolationApp', []);

  customInterpolationApp.config(function($interpolateProvider) {
    $interpolateProvider.startSymbol('//');
    $interpolateProvider.endSymbol('//');
  });


  customInterpolationApp.controller('DemoController', function() {
      this.label = "This binding is brought you by // interpolation symbols.";
  });
</script>
<div ng-app="App" ng-controller="DemoController as demo">
    //demo.label//
</div>
</file>
<file name="protractor.js" type="protractor">
  it('should interpolate binding with custom symbols', function() {
    expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');
  });
</file>
</example>
 */
function $InterpolateProvider() {
  var startSymbol = '{{';
  var endSymbol = '}}';

  /**
   * @ngdoc method
   * @name $interpolateProvider#startSymbol
   * @description
   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
   *
   * @param {string=} value new value to set the starting symbol to.
   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
   */
  this.startSymbol = function(value){
    if (value) {
      startSymbol = value;
      return this;
    } else {
      return startSymbol;
    }
  };

  /**
   * @ngdoc method
   * @name $interpolateProvider#endSymbol
   * @description
   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
   *
   * @param {string=} value new value to set the ending symbol to.
   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
   */
  this.endSymbol = function(value){
    if (value) {
      endSymbol = value;
      return this;
    } else {
      return endSymbol;
    }
  };


  this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
    var startSymbolLength = startSymbol.length,
        endSymbolLength = endSymbol.length;

    /**
     * @ngdoc service
     * @name $interpolate
     * @kind function
     *
     * @requires $parse
     * @requires $sce
     *
     * @description
     *
     * Compiles a string with markup into an interpolation function. This service is used by the
     * HTML {@link ng.$compile $compile} service for data binding. See
     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the
     * interpolation markup.
     *
     *
     * ```js
     *   var $interpolate = ...; // injected
     *   var exp = $interpolate('Hello {{name | uppercase}}!');
     *   expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');
     * ```
     *
     *
     * @param {string} text The text with markup to interpolate.
     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
     *    embedded expression in order to return an interpolation function. Strings with no
     *    embedded expression will return null for the interpolation function.
     * @param {string=} trustedContext when provided, the returned function passes the interpolated
     *    result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
     *    trustedContext)} before returning it.  Refer to the {@link ng.$sce $sce} service that
     *    provides Strict Contextual Escaping for details.
     * @returns {function(context)} an interpolation function which is used to compute the
     *    interpolated string. The function has these parameters:
     *
     *    * `context`: an object against which any expressions embedded in the strings are evaluated
     *      against.
     *
     */
    function $interpolate(text, mustHaveExpression, trustedContext) {
      var startIndex,
          endIndex,
          index = 0,
          parts = [],
          length = text.length,
          hasInterpolation = false,
          fn,
          exp,
          concat = [];

      while(index < length) {
        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&
             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {
          (index != startIndex) && parts.push(text.substring(index, startIndex));
          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));
          fn.exp = exp;
          index = endIndex + endSymbolLength;
          hasInterpolation = true;
        } else {
          // we did not find anything, so we have to add the remainder to the parts array
          (index != length) && parts.push(text.substring(index));
          index = length;
        }
      }

      if (!(length = parts.length)) {
        // we added, nothing, must have been an empty string.
        parts.push('');
        length = 1;
      }

      // Concatenating expressions makes it hard to reason about whether some combination of
      // concatenated values are unsafe to use and could easily lead to XSS.  By requiring that a
      // single expression be used for iframe[src], object[src], etc., we ensure that the value
      // that's used is assigned or constructed by some JS code somewhere that is more testable or
      // make it obvious that you bound the value to some user controlled value.  This helps reduce
      // the load when auditing for XSS issues.
      if (trustedContext && parts.length > 1) {
          throw $interpolateMinErr('noconcat',
              "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
              "interpolations that concatenate multiple expressions when a trusted value is " +
              "required.  See http://docs.angularjs.org/api/ng.$sce", text);
      }

      if (!mustHaveExpression  || hasInterpolation) {
        concat.length = length;
        fn = function(context) {
          try {
            for(var i = 0, ii = length, part; i<ii; i++) {
              if (typeof (part = parts[i]) == 'function') {
                part = part(context);
                if (trustedContext) {
                  part = $sce.getTrusted(trustedContext, part);
                } else {
                  part = $sce.valueOf(part);
                }
                if (part == null) { // null || undefined
                  part = '';
                } else {
                  switch (typeof part) {
                    case 'string':
                    {
                      break;
                    }
                    case 'number':
                    {
                      part = '' + part;
                      break;
                    }
                    default:
                    {
                      part = toJson(part);
                    }
                  }
                }
              }
              concat[i] = part;
            }
            return concat.join('');
          }
          catch(err) {
            var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
                err.toString());
            $exceptionHandler(newErr);
          }
        };
        fn.exp = text;
        fn.parts = parts;
        return fn;
      }
    }


    /**
     * @ngdoc method
     * @name $interpolate#startSymbol
     * @description
     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
     *
     * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change
     * the symbol.
     *
     * @returns {string} start symbol.
     */
    $interpolate.startSymbol = function() {
      return startSymbol;
    };


    /**
     * @ngdoc method
     * @name $interpolate#endSymbol
     * @description
     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
     *
     * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change
     * the symbol.
     *
     * @returns {string} end symbol.
     */
    $interpolate.endSymbol = function() {
      return endSymbol;
    };

    return $interpolate;
  }];
}

function $IntervalProvider() {
  this.$get = ['$rootScope', '$window', '$q',
       function($rootScope,   $window,   $q) {
    var intervals = {};


     /**
      * @ngdoc service
      * @name $interval
      *
      * @description
      * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`
      * milliseconds.
      *
      * The return value of registering an interval function is a promise. This promise will be
      * notified upon each tick of the interval, and will be resolved after `count` iterations, or
      * run indefinitely if `count` is not defined. The value of the notification will be the
      * number of iterations that have run.
      * To cancel an interval, call `$interval.cancel(promise)`.
      *
      * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
      * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
      * time.
      *
      * <div class="alert alert-warning">
      * **Note**: Intervals created by this service must be explicitly destroyed when you are finished
      * with them.  In particular they are not automatically destroyed when a controller's scope or a
      * directive's element are destroyed.
      * You should take this into consideration and make sure to always cancel the interval at the
      * appropriate moment.  See the example below for more details on how and when to do this.
      * </div>
      *
      * @param {function()} fn A function that should be called repeatedly.
      * @param {number} delay Number of milliseconds between each function call.
      * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
      *   indefinitely.
      * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
      * @returns {promise} A promise which will be notified on each iteration.
      *
      * @example
      * <example module="intervalExample">
      * <file name="index.html">
      *   <script>
      *     angular.module('intervalExample', [])
      *       .controller('ExampleController', ['$scope', '$interval',
      *         function($scope, $interval) {
      *           $scope.format = 'M/d/yy h:mm:ss a';
      *           $scope.blood_1 = 100;
      *           $scope.blood_2 = 120;
      *
      *           var stop;
      *           $scope.fight = function() {
      *             // Don't start a new fight if we are already fighting
      *             if ( angular.isDefined(stop) ) return;
      *
      *             stop = $interval(function() {
      *               if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
      *                 $scope.blood_1 = $scope.blood_1 - 3;
      *                 $scope.blood_2 = $scope.blood_2 - 4;
      *               } else {
      *                 $scope.stopFight();
      *               }
      *             }, 100);
      *           };
      *
      *           $scope.stopFight = function() {
      *             if (angular.isDefined(stop)) {
      *               $interval.cancel(stop);
      *               stop = undefined;
      *             }
      *           };
      *
      *           $scope.resetFight = function() {
      *             $scope.blood_1 = 100;
      *             $scope.blood_2 = 120;
      *           };
      *
      *           $scope.$on('$destroy', function() {
      *             // Make sure that the interval is destroyed too
      *             $scope.stopFight();
      *           });
      *         }])
      *       // Register the 'myCurrentTime' directive factory method.
      *       // We inject $interval and dateFilter service since the factory method is DI.
      *       .directive('myCurrentTime', ['$interval', 'dateFilter',
      *         function($interval, dateFilter) {
      *           // return the directive link function. (compile function not needed)
      *           return function(scope, element, attrs) {
      *             var format,  // date format
      *                 stopTime; // so that we can cancel the time updates
      *
      *             // used to update the UI
      *             function updateTime() {
      *               element.text(dateFilter(new Date(), format));
      *             }
      *
      *             // watch the expression, and update the UI on change.
      *             scope.$watch(attrs.myCurrentTime, function(value) {
      *               format = value;
      *               updateTime();
      *             });
      *
      *             stopTime = $interval(updateTime, 1000);
      *
      *             // listen on DOM destroy (removal) event, and cancel the next UI update
      *             // to prevent updating time after the DOM element was removed.
      *             element.bind('$destroy', function() {
      *               $interval.cancel(stopTime);
      *             });
      *           }
      *         }]);
      *   </script>
      *
      *   <div>
      *     <div ng-controller="ExampleController">
      *       Date format: <input ng-model="format"> <hr/>
      *       Current time is: <span my-current-time="format"></span>
      *       <hr/>
      *       Blood 1 : <font color='red'>{{blood_1}}</font>
      *       Blood 2 : <font color='red'>{{blood_2}}</font>
      *       <button type="button" data-ng-click="fight()">Fight</button>
      *       <button type="button" data-ng-click="stopFight()">StopFight</button>
      *       <button type="button" data-ng-click="resetFight()">resetFight</button>
      *     </div>
      *   </div>
      *
      * </file>
      * </example>
      */
    function interval(fn, delay, count, invokeApply) {
      var setInterval = $window.setInterval,
          clearInterval = $window.clearInterval,
          deferred = $q.defer(),
          promise = deferred.promise,
          iteration = 0,
          skipApply = (isDefined(invokeApply) && !invokeApply);

      count = isDefined(count) ? count : 0;

      promise.then(null, null, fn);

      promise.$$intervalId = setInterval(function tick() {
        deferred.notify(iteration++);

        if (count > 0 && iteration >= count) {
          deferred.resolve(iteration);
          clearInterval(promise.$$intervalId);
          delete intervals[promise.$$intervalId];
        }

        if (!skipApply) $rootScope.$apply();

      }, delay);

      intervals[promise.$$intervalId] = deferred;

      return promise;
    }


     /**
      * @ngdoc method
      * @name $interval#cancel
      *
      * @description
      * Cancels a task associated with the `promise`.
      *
      * @param {promise} promise returned by the `$interval` function.
      * @returns {boolean} Returns `true` if the task was successfully canceled.
      */
    interval.cancel = function(promise) {
      if (promise && promise.$$intervalId in intervals) {
        intervals[promise.$$intervalId].reject('canceled');
        $window.clearInterval(promise.$$intervalId);
        delete intervals[promise.$$intervalId];
        return true;
      }
      return false;
    };

    return interval;
  }];
}

/**
 * @ngdoc service
 * @name $locale
 *
 * @description
 * $locale service provides localization rules for various Angular components. As of right now the
 * only public api is:
 *
 * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
 */
function $LocaleProvider(){
  this.$get = function() {
    return {
      id: 'en-us',

      NUMBER_FORMATS: {
        DECIMAL_SEP: '.',
        GROUP_SEP: ',',
        PATTERNS: [
          { // Decimal Pattern
            minInt: 1,
            minFrac: 0,
            maxFrac: 3,
            posPre: '',
            posSuf: '',
            negPre: '-',
            negSuf: '',
            gSize: 3,
            lgSize: 3
          },{ //Currency Pattern
            minInt: 1,
            minFrac: 2,
            maxFrac: 2,
            posPre: '\u00A4',
            posSuf: '',
            negPre: '(\u00A4',
            negSuf: ')',
            gSize: 3,
            lgSize: 3
          }
        ],
        CURRENCY_SYM: '$'
      },

      DATETIME_FORMATS: {
        MONTH:
            'January,February,March,April,May,June,July,August,September,October,November,December'
            .split(','),
        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),
        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),
        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),
        AMPMS: ['AM','PM'],
        medium: 'MMM d, y h:mm:ss a',
        short: 'M/d/yy h:mm a',
        fullDate: 'EEEE, MMMM d, y',
        longDate: 'MMMM d, y',
        mediumDate: 'MMM d, y',
        shortDate: 'M/d/yy',
        mediumTime: 'h:mm:ss a',
        shortTime: 'h:mm a'
      },

      pluralCat: function(num) {
        if (num === 1) {
          return 'one';
        }
        return 'other';
      }
    };
  };
}

var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/,
    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
var $locationMinErr = minErr('$location');


/**
 * Encode path using encodeUriSegment, ignoring forward slashes
 *
 * @param {string} path Path to encode
 * @returns {string}
 */
function encodePath(path) {
  var segments = path.split('/'),
      i = segments.length;

  while (i--) {
    segments[i] = encodeUriSegment(segments[i]);
  }

  return segments.join('/');
}

function parseAbsoluteUrl(absoluteUrl, locationObj, appBase) {
  var parsedUrl = urlResolve(absoluteUrl, appBase);

  locationObj.$$protocol = parsedUrl.protocol;
  locationObj.$$host = parsedUrl.hostname;
  locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
}


function parseAppUrl(relativeUrl, locationObj, appBase) {
  var prefixed = (relativeUrl.charAt(0) !== '/');
  if (prefixed) {
    relativeUrl = '/' + relativeUrl;
  }
  var match = urlResolve(relativeUrl, appBase);
  locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
      match.pathname.substring(1) : match.pathname);
  locationObj.$$search = parseKeyValue(match.search);
  locationObj.$$hash = decodeURIComponent(match.hash);

  // make sure path starts with '/';
  if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {
    locationObj.$$path = '/' + locationObj.$$path;
  }
}


/**
 *
 * @param {string} begin
 * @param {string} whole
 * @returns {string} returns text from whole after begin or undefined if it does not begin with
 *                   expected string.
 */
function beginsWith(begin, whole) {
  if (whole.indexOf(begin) === 0) {
    return whole.substr(begin.length);
  }
}


function stripHash(url) {
  var index = url.indexOf('#');
  return index == -1 ? url : url.substr(0, index);
}


function stripFile(url) {
  return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
}

/* return the server only (scheme://host:port) */
function serverBase(url) {
  return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));
}


/**
 * LocationHtml5Url represents an url
 * This object is exposed as $location service when HTML5 mode is enabled and supported
 *
 * @constructor
 * @param {string} appBase application base URL
 * @param {string} basePrefix url path prefix
 */
function LocationHtml5Url(appBase, basePrefix) {
  this.$$html5 = true;
  basePrefix = basePrefix || '';
  var appBaseNoFile = stripFile(appBase);
  parseAbsoluteUrl(appBase, this, appBase);


  /**
   * Parse given html5 (regular) url string into properties
   * @param {string} newAbsoluteUrl HTML5 url
   * @private
   */
  this.$$parse = function(url) {
    var pathUrl = beginsWith(appBaseNoFile, url);
    if (!isString(pathUrl)) {
      throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
          appBaseNoFile);
    }

    parseAppUrl(pathUrl, this, appBase);

    if (!this.$$path) {
      this.$$path = '/';
    }

    this.$$compose();
  };

  /**
   * Compose url and update `absUrl` property
   * @private
   */
  this.$$compose = function() {
    var search = toKeyValue(this.$$search),
        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';

    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
    this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'
  };

  this.$$parseLinkUrl = function(url, relHref) {
    var appUrl, prevAppUrl;
    var rewrittenUrl;

    if ( (appUrl = beginsWith(appBase, url)) !== undefined ) {
      prevAppUrl = appUrl;
      if ( (appUrl = beginsWith(basePrefix, appUrl)) !== undefined ) {
        rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
      } else {
        rewrittenUrl = appBase + prevAppUrl;
      }
    } else if ( (appUrl = beginsWith(appBaseNoFile, url)) !== undefined ) {
      rewrittenUrl = appBaseNoFile + appUrl;
    } else if (appBaseNoFile == url + '/') {
      rewrittenUrl = appBaseNoFile;
    }
    if (rewrittenUrl) {
      this.$$parse(rewrittenUrl);
    }
    return !!rewrittenUrl;
  };
}


/**
 * LocationHashbangUrl represents url
 * This object is exposed as $location service when developer doesn't opt into html5 mode.
 * It also serves as the base class for html5 mode fallback on legacy browsers.
 *
 * @constructor
 * @param {string} appBase application base URL
 * @param {string} hashPrefix hashbang prefix
 */
function LocationHashbangUrl(appBase, hashPrefix) {
  var appBaseNoFile = stripFile(appBase);

  parseAbsoluteUrl(appBase, this, appBase);


  /**
   * Parse given hashbang url into properties
   * @param {string} url Hashbang url
   * @private
   */
  this.$$parse = function(url) {
    var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
    var withoutHashUrl = withoutBaseUrl.charAt(0) == '#'
        ? beginsWith(hashPrefix, withoutBaseUrl)
        : (this.$$html5)
          ? withoutBaseUrl
          : '';

    if (!isString(withoutHashUrl)) {
      throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url,
          hashPrefix);
    }
    parseAppUrl(withoutHashUrl, this, appBase);

    this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);

    this.$$compose();

    /*
     * In Windows, on an anchor node on documents loaded from
     * the filesystem, the browser will return a pathname
     * prefixed with the drive name ('/C:/path') when a
     * pathname without a drive is set:
     *  * a.setAttribute('href', '/foo')
     *   * a.pathname === '/C:/foo' //true
     *
     * Inside of Angular, we're always using pathnames that
     * do not include drive names for routing.
     */
    function removeWindowsDriveName (path, url, base) {
      /*
      Matches paths for file protocol on windows,
      such as /C:/foo/bar, and captures only /foo/bar.
      */
      var windowsFilePathExp = /^\/[A-Z]:(\/.*)/;

      var firstPathSegmentMatch;

      //Get the relative path from the input URL.
      if (url.indexOf(base) === 0) {
        url = url.replace(base, '');
      }

      // The input URL intentionally contains a first path segment that ends with a colon.
      if (windowsFilePathExp.exec(url)) {
        return path;
      }

      firstPathSegmentMatch = windowsFilePathExp.exec(path);
      return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;
    }
  };

  /**
   * Compose hashbang url and update `absUrl` property
   * @private
   */
  this.$$compose = function() {
    var search = toKeyValue(this.$$search),
        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';

    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
    this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
  };

  this.$$parseLinkUrl = function(url, relHref) {
    if(stripHash(appBase) == stripHash(url)) {
      this.$$parse(url);
      return true;
    }
    return false;
  };
}


/**
 * LocationHashbangUrl represents url
 * This object is exposed as $location service when html5 history api is enabled but the browser
 * does not support it.
 *
 * @constructor
 * @param {string} appBase application base URL
 * @param {string} hashPrefix hashbang prefix
 */
function LocationHashbangInHtml5Url(appBase, hashPrefix) {
  this.$$html5 = true;
  LocationHashbangUrl.apply(this, arguments);

  var appBaseNoFile = stripFile(appBase);

  this.$$parseLinkUrl = function(url, relHref) {
    var rewrittenUrl;
    var appUrl;

    if ( appBase == stripHash(url) ) {
      rewrittenUrl = url;
    } else if ( (appUrl = beginsWith(appBaseNoFile, url)) ) {
      rewrittenUrl = appBase + hashPrefix + appUrl;
    } else if ( appBaseNoFile === url + '/') {
      rewrittenUrl = appBaseNoFile;
    }
    if (rewrittenUrl) {
      this.$$parse(rewrittenUrl);
    }
    return !!rewrittenUrl;
  };

  this.$$compose = function() {
    var search = toKeyValue(this.$$search),
        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';

    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
    // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#'
    this.$$absUrl = appBase + hashPrefix + this.$$url;
  };

}


LocationHashbangInHtml5Url.prototype =
  LocationHashbangUrl.prototype =
  LocationHtml5Url.prototype = {

  /**
   * Are we in html5 mode?
   * @private
   */
  $$html5: false,

  /**
   * Has any change been replacing ?
   * @private
   */
  $$replace: false,

  /**
   * @ngdoc method
   * @name $location#absUrl
   *
   * @description
   * This method is getter only.
   *
   * Return full url representation with all segments encoded according to rules specified in
   * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).
   *
   * @return {string} full url
   */
  absUrl: locationGetter('$$absUrl'),

  /**
   * @ngdoc method
   * @name $location#url
   *
   * @description
   * This method is getter / setter.
   *
   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.
   *
   * Change path, search and hash, when called with parameter and return `$location`.
   *
   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
   * @return {string} url
   */
  url: function(url) {
    if (isUndefined(url))
      return this.$$url;

    var match = PATH_MATCH.exec(url);
    if (match[1]) this.path(decodeURIComponent(match[1]));
    if (match[2] || match[1]) this.search(match[3] || '');
    this.hash(match[5] || '');

    return this;
  },

  /**
   * @ngdoc method
   * @name $location#protocol
   *
   * @description
   * This method is getter only.
   *
   * Return protocol of current url.
   *
   * @return {string} protocol of current url
   */
  protocol: locationGetter('$$protocol'),

  /**
   * @ngdoc method
   * @name $location#host
   *
   * @description
   * This method is getter only.
   *
   * Return host of current url.
   *
   * @return {string} host of current url.
   */
  host: locationGetter('$$host'),

  /**
   * @ngdoc method
   * @name $location#port
   *
   * @description
   * This method is getter only.
   *
   * Return port of current url.
   *
   * @return {Number} port
   */
  port: locationGetter('$$port'),

  /**
   * @ngdoc method
   * @name $location#path
   *
   * @description
   * This method is getter / setter.
   *
   * Return path of current url when called without any parameter.
   *
   * Change path when called with parameter and return `$location`.
   *
   * Note: Path should always begin with forward slash (/), this method will add the forward slash
   * if it is missing.
   *
   * @param {(string|number)=} path New path
   * @return {string} path
   */
  path: locationGetterSetter('$$path', function(path) {
    path = path !== null ? path.toString() : '';
    return path.charAt(0) == '/' ? path : '/' + path;
  }),

  /**
   * @ngdoc method
   * @name $location#search
   *
   * @description
   * This method is getter / setter.
   *
   * Return search part (as object) of current url when called without any parameter.
   *
   * Change search part when called with parameter and return `$location`.
   *
   *
   * ```js
   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
   * var searchObject = $location.search();
   * // => {foo: 'bar', baz: 'xoxo'}
   *
   *
   * // set foo to 'yipee'
   * $location.search('foo', 'yipee');
   * // => $location
   * ```
   *
   * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
   * hash object.
   *
   * When called with a single argument the method acts as a setter, setting the `search` component
   * of `$location` to the specified value.
   *
   * If the argument is a hash object containing an array of values, these values will be encoded
   * as duplicate search parameters in the url.
   *
   * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`
   * will override only a single search property.
   *
   * If `paramValue` is an array, it will override the property of the `search` component of
   * `$location` specified via the first argument.
   *
   * If `paramValue` is `null`, the property specified via the first argument will be deleted.
   *
   * If `paramValue` is `true`, the property specified via the first argument will be added with no
   * value nor trailing equal sign.
   *
   * @return {Object} If called with no arguments returns the parsed `search` object. If called with
   * one or more arguments returns `$location` object itself.
   */
  search: function(search, paramValue) {
    switch (arguments.length) {
      case 0:
        return this.$$search;
      case 1:
        if (isString(search) || isNumber(search)) {
          search = search.toString();
          this.$$search = parseKeyValue(search);
        } else if (isObject(search)) {
          // remove object undefined or null properties
          forEach(search, function(value, key) {
            if (value == null) delete search[key];
          });

          this.$$search = search;
        } else {
          throw $locationMinErr('isrcharg',
              'The first argument of the `$location#search()` call must be a string or an object.');
        }
        break;
      default:
        if (isUndefined(paramValue) || paramValue === null) {
          delete this.$$search[search];
        } else {
          this.$$search[search] = paramValue;
        }
    }

    this.$$compose();
    return this;
  },

  /**
   * @ngdoc method
   * @name $location#hash
   *
   * @description
   * This method is getter / setter.
   *
   * Return hash fragment when called without any parameter.
   *
   * Change hash fragment when called with parameter and return `$location`.
   *
   * @param {(string|number)=} hash New hash fragment
   * @return {string} hash
   */
  hash: locationGetterSetter('$$hash', function(hash) {
    return hash !== null ? hash.toString() : '';
  }),

  /**
   * @ngdoc method
   * @name $location#replace
   *
   * @description
   * If called, all changes to $location during current `$digest` will be replacing current history
   * record, instead of adding new one.
   */
  replace: function() {
    this.$$replace = true;
    return this;
  }
};

function locationGetter(property) {
  return function() {
    return this[property];
  };
}


function locationGetterSetter(property, preprocess) {
  return function(value) {
    if (isUndefined(value))
      return this[property];

    this[property] = preprocess(value);
    this.$$compose();

    return this;
  };
}


/**
 * @ngdoc service
 * @name $location
 *
 * @requires $rootElement
 *
 * @description
 * The $location service parses the URL in the browser address bar (based on the
 * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL
 * available to your application. Changes to the URL in the address bar are reflected into
 * $location service and changes to $location are reflected into the browser address bar.
 *
 * **The $location service:**
 *
 * - Exposes the current URL in the browser address bar, so you can
 *   - Watch and observe the URL.
 *   - Change the URL.
 * - Synchronizes the URL with the browser when the user
 *   - Changes the address bar.
 *   - Clicks the back or forward button (or clicks a History link).
 *   - Clicks on a link.
 * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).
 *
 * For more information see {@link guide/$location Developer Guide: Using $location}
 */

/**
 * @ngdoc provider
 * @name $locationProvider
 * @description
 * Use the `$locationProvider` to configure how the application deep linking paths are stored.
 */
function $LocationProvider(){
  var hashPrefix = '',
      html5Mode = false;

  /**
   * @ngdoc method
   * @name $locationProvider#hashPrefix
   * @description
   * @param {string=} prefix Prefix for hash part (containing path and search)
   * @returns {*} current value if used as getter or itself (chaining) if used as setter
   */
  this.hashPrefix = function(prefix) {
    if (isDefined(prefix)) {
      hashPrefix = prefix;
      return this;
    } else {
      return hashPrefix;
    }
  };

  /**
   * @ngdoc method
   * @name $locationProvider#html5Mode
   * @description
   * @param {boolean=} mode Use HTML5 strategy if available.
   * @returns {*} current value if used as getter or itself (chaining) if used as setter
   */
  this.html5Mode = function(mode) {
    if (isDefined(mode)) {
      html5Mode = mode;
      return this;
    } else {
      return html5Mode;
    }
  };

  /**
   * @ngdoc event
   * @name $location#$locationChangeStart
   * @eventType broadcast on root scope
   * @description
   * Broadcasted before a URL will change. This change can be prevented by calling
   * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
   * details about event object. Upon successful change
   * {@link ng.$location#events_$locationChangeSuccess $locationChangeSuccess} is fired.
   *
   * @param {Object} angularEvent Synthetic event object.
   * @param {string} newUrl New URL
   * @param {string=} oldUrl URL that was before it was changed.
   */

  /**
   * @ngdoc event
   * @name $location#$locationChangeSuccess
   * @eventType broadcast on root scope
   * @description
   * Broadcasted after a URL was changed.
   *
   * @param {Object} angularEvent Synthetic event object.
   * @param {string} newUrl New URL
   * @param {string=} oldUrl URL that was before it was changed.
   */

  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
      function( $rootScope,   $browser,   $sniffer,   $rootElement) {
    var $location,
        LocationMode,
        baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
        initialUrl = $browser.url(),
        appBase;

    if (html5Mode) {
      appBase = serverBase(initialUrl) + (baseHref || '/');
      LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;
    } else {
      appBase = stripHash(initialUrl);
      LocationMode = LocationHashbangUrl;
    }
    $location = new LocationMode(appBase, '#' + hashPrefix);
    $location.$$parseLinkUrl(initialUrl, initialUrl);

    var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;

    $rootElement.on('click', function(event) {
      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
      // currently we open nice url link and redirect then

      if (event.ctrlKey || event.metaKey || event.which == 2) return;

      var elm = jqLite(event.target);

      // traverse the DOM up to find first A tag
      while (lowercase(elm[0].nodeName) !== 'a') {
        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
      }

      var absHref = elm.prop('href');
      // get the actual href attribute - see
      // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
      var relHref = elm.attr('href') || elm.attr('xlink:href');

      if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {
        // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during
        // an animation.
        absHref = urlResolve(absHref.animVal).href;
      }

      // Ignore when url is started with javascript: or mailto:
      if (IGNORE_URI_REGEXP.test(absHref)) return;

      if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {
        if ($location.$$parseLinkUrl(absHref, relHref)) {
          // We do a preventDefault for all urls that are part of the angular application,
          // in html5mode and also without, so that we are able to abort navigation without
          // getting double entries in the location history.
          event.preventDefault();
          // update location manually
          if ($location.absUrl() != $browser.url()) {
            $rootScope.$apply();
            // hack to work around FF6 bug 684208 when scenario runner clicks on links
            window.angular['ff-684208-preventDefault'] = true;
          }
        }
      }
    });


    // rewrite hashbang url <> html5 url
    if ($location.absUrl() != initialUrl) {
      $browser.url($location.absUrl(), true);
    }

    // update $location when $browser url changes
    $browser.onUrlChange(function(newUrl) {
      if ($location.absUrl() != newUrl) {
        $rootScope.$evalAsync(function() {
          var oldUrl = $location.absUrl();

          $location.$$parse(newUrl);
          if ($rootScope.$broadcast('$locationChangeStart', newUrl,
                                    oldUrl).defaultPrevented) {
            $location.$$parse(oldUrl);
            $browser.url(oldUrl);
          } else {
            afterLocationChange(oldUrl);
          }
        });
        if (!$rootScope.$$phase) $rootScope.$digest();
      }
    });

    // update browser
    var changeCounter = 0;
    $rootScope.$watch(function $locationWatch() {
      var oldUrl = $browser.url();
      var currentReplace = $location.$$replace;

      if (!changeCounter || oldUrl != $location.absUrl()) {
        changeCounter++;
        $rootScope.$evalAsync(function() {
          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).
              defaultPrevented) {
            $location.$$parse(oldUrl);
          } else {
            $browser.url($location.absUrl(), currentReplace);
            afterLocationChange(oldUrl);
          }
        });
      }
      $location.$$replace = false;

      return changeCounter;
    });

    return $location;

    function afterLocationChange(oldUrl) {
      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);
    }
}];
}

/**
 * @ngdoc service
 * @name $log
 * @requires $window
 *
 * @description
 * Simple service for logging. Default implementation safely writes the message
 * into the browser's console (if present).
 *
 * The main purpose of this service is to simplify debugging and troubleshooting.
 *
 * The default is to log `debug` messages. You can use
 * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
 *
 * @example
   <example module="logExample">
     <file name="script.js">
       angular.module('logExample', [])
         .controller('LogController', ['$scope', '$log', function($scope, $log) {
           $scope.$log = $log;
           $scope.message = 'Hello World!';
         }]);
     </file>
     <file name="index.html">
       <div ng-controller="LogController">
         <p>Reload this page with open console, enter text and hit the log button...</p>
         Message:
         <input type="text" ng-model="message"/>
         <button ng-click="$log.log(message)">log</button>
         <button ng-click="$log.warn(message)">warn</button>
         <button ng-click="$log.info(message)">info</button>
         <button ng-click="$log.error(message)">error</button>
       </div>
     </file>
   </example>
 */

/**
 * @ngdoc provider
 * @name $logProvider
 * @description
 * Use the `$logProvider` to configure how the application logs messages
 */
function $LogProvider(){
  var debug = true,
      self = this;

  /**
   * @ngdoc method
   * @name $logProvider#debugEnabled
   * @description
   * @param {boolean=} flag enable or disable debug level messages
   * @returns {*} current value if used as getter or itself (chaining) if used as setter
   */
  this.debugEnabled = function(flag) {
    if (isDefined(flag)) {
      debug = flag;
    return this;
    } else {
      return debug;
    }
  };

  this.$get = ['$window', function($window){
    return {
      /**
       * @ngdoc method
       * @name $log#log
       *
       * @description
       * Write a log message
       */
      log: consoleLog('log'),

      /**
       * @ngdoc method
       * @name $log#info
       *
       * @description
       * Write an information message
       */
      info: consoleLog('info'),

      /**
       * @ngdoc method
       * @name $log#warn
       *
       * @description
       * Write a warning message
       */
      warn: consoleLog('warn'),

      /**
       * @ngdoc method
       * @name $log#error
       *
       * @description
       * Write an error message
       */
      error: consoleLog('error'),

      /**
       * @ngdoc method
       * @name $log#debug
       *
       * @description
       * Write a debug message
       */
      debug: (function () {
        var fn = consoleLog('debug');

        return function() {
          if (debug) {
            fn.apply(self, arguments);
          }
        };
      }())
    };

    function formatError(arg) {
      if (arg instanceof Error) {
        if (arg.stack) {
          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
              ? 'Error: ' + arg.message + '\n' + arg.stack
              : arg.stack;
        } else if (arg.sourceURL) {
          arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line;
        }
      }
      return arg;
    }

    function consoleLog(type) {
      var console = $window.console || {},
          logFn = console[type] || console.log || noop,
          hasApply = false;

      // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
      // The reason behind this is that console.log has type "object" in IE8...
      try {
        hasApply = !!logFn.apply;
      } catch (e) {}

      if (hasApply) {
        return function() {
          var args = [];
          forEach(arguments, function(arg) {
            args.push(formatError(arg));
          });
          return logFn.apply(console, args);
        };
      }

      // we are IE which either doesn't have window.console => this is noop and we do nothing,
      // or we are IE where console.log doesn't have apply so we log at least first 2 args
      return function(arg1, arg2) {
        logFn(arg1, arg2 == null ? '' : arg2);
      };
    }
  }];
}

var $parseMinErr = minErr('$parse');
var promiseWarningCache = {};
var promiseWarning;

// Sandboxing Angular Expressions
// ------------------------------
// Angular expressions are generally considered safe because these expressions only have direct
// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by
// obtaining a reference to native JS functions such as the Function constructor.
//
// As an example, consider the following Angular expression:
//
//   {}.toString.constructor('alert("evil JS code")')
//
// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
// against the expression language, but not to prevent exploits that were enabled by exposing
// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good
// practice and therefore we are not even trying to protect against interaction with an object
// explicitly exposed in this way.
//
// In general, it is not possible to access a Window object from an angular expression unless a
// window or some DOM object that has a reference to window is published onto a Scope.
// Similarly we prevent invocations of function known to be dangerous, as well as assignments to
// native objects.
//
// See https://docs.angularjs.org/guide/security


function ensureSafeMemberName(name, fullExpression) {
  if (name === "__defineGetter__" || name === "__defineSetter__"
      || name === "__lookupGetter__" || name === "__lookupSetter__"
      || name === "__proto__") {
    throw $parseMinErr('isecfld',
        'Attempting to access a disallowed field in Angular expressions! '
        +'Expression: {0}', fullExpression);
  }
  return name;
}

function ensureSafeObject(obj, fullExpression) {
  // nifty check if obj is Function that is fast and works across iframes and other contexts
  if (obj) {
    if (obj.constructor === obj) {
      throw $parseMinErr('isecfn',
          'Referencing Function in Angular expressions is disallowed! Expression: {0}',
          fullExpression);
    } else if (// isWindow(obj)
        obj.document && obj.location && obj.alert && obj.setInterval) {
      throw $parseMinErr('isecwindow',
          'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
          fullExpression);
    } else if (// isElement(obj)
        obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {
      throw $parseMinErr('isecdom',
          'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
          fullExpression);
    } else if (// block Object so that we can't get hold of dangerous Object.* methods
        obj === Object) {
      throw $parseMinErr('isecobj',
          'Referencing Object in Angular expressions is disallowed! Expression: {0}',
          fullExpression);
    }
  }
  return obj;
}

var CALL = Function.prototype.call;
var APPLY = Function.prototype.apply;
var BIND = Function.prototype.bind;

function ensureSafeFunction(obj, fullExpression) {
  if (obj) {
    if (obj.constructor === obj) {
      throw $parseMinErr('isecfn',
        'Referencing Function in Angular expressions is disallowed! Expression: {0}',
        fullExpression);
    } else if (obj === CALL || obj === APPLY || (BIND && obj === BIND)) {
      throw $parseMinErr('isecff',
        'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
        fullExpression);
    }
  }
}

var OPERATORS = {
    /* jshint bitwise : false */
    'null':function(){return null;},
    'true':function(){return true;},
    'false':function(){return false;},
    undefined:noop,
    '+':function(self, locals, a,b){
      a=a(self, locals); b=b(self, locals);
      if (isDefined(a)) {
        if (isDefined(b)) {
          return a + b;
        }
        return a;
      }
      return isDefined(b)?b:undefined;},
    '-':function(self, locals, a,b){
          a=a(self, locals); b=b(self, locals);
          return (isDefined(a)?a:0)-(isDefined(b)?b:0);
        },
    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},
    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},
    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},
    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},
    '=':noop,
    '===':function(self, locals, a, b){return a(self, locals)===b(self, locals);},
    '!==':function(self, locals, a, b){return a(self, locals)!==b(self, locals);},
    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},
    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},
    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},
    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},
    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},
    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},
    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},
    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},
    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},
//    '|':function(self, locals, a,b){return a|b;},
    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},
    '!':function(self, locals, a){return !a(self, locals);}
};
/* jshint bitwise: true */
var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};


/////////////////////////////////////////


/**
 * @constructor
 */
var Lexer = function (options) {
  this.options = options;
};

Lexer.prototype = {
  constructor: Lexer,

  lex: function (text) {
    this.text = text;

    this.index = 0;
    this.ch = undefined;
    this.lastCh = ':'; // can start regexp

    this.tokens = [];

    while (this.index < this.text.length) {
      this.ch = this.text.charAt(this.index);
      if (this.is('"\'')) {
        this.readString(this.ch);
      } else if (this.isNumber(this.ch) || this.is('.') && this.isNumber(this.peek())) {
        this.readNumber();
      } else if (this.isIdent(this.ch)) {
        this.readIdent();
      } else if (this.is('(){}[].,;:?')) {
        this.tokens.push({
          index: this.index,
          text: this.ch
        });
        this.index++;
      } else if (this.isWhitespace(this.ch)) {
        this.index++;
        continue;
      } else {
        var ch2 = this.ch + this.peek();
        var ch3 = ch2 + this.peek(2);
        var fn = OPERATORS[this.ch];
        var fn2 = OPERATORS[ch2];
        var fn3 = OPERATORS[ch3];
        if (fn3) {
          this.tokens.push({index: this.index, text: ch3, fn: fn3});
          this.index += 3;
        } else if (fn2) {
          this.tokens.push({index: this.index, text: ch2, fn: fn2});
          this.index += 2;
        } else if (fn) {
          this.tokens.push({
            index: this.index,
            text: this.ch,
            fn: fn
          });
          this.index += 1;
        } else {
          this.throwError('Unexpected next character ', this.index, this.index + 1);
        }
      }
      this.lastCh = this.ch;
    }
    return this.tokens;
  },

  is: function(chars) {
    return chars.indexOf(this.ch) !== -1;
  },

  was: function(chars) {
    return chars.indexOf(this.lastCh) !== -1;
  },

  peek: function(i) {
    var num = i || 1;
    return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
  },

  isNumber: function(ch) {
    return ('0' <= ch && ch <= '9');
  },

  isWhitespace: function(ch) {
    // IE treats non-breaking space as \u00A0
    return (ch === ' ' || ch === '\r' || ch === '\t' ||
            ch === '\n' || ch === '\v' || ch === '\u00A0');
  },

  isIdent: function(ch) {
    return ('a' <= ch && ch <= 'z' ||
            'A' <= ch && ch <= 'Z' ||
            '_' === ch || ch === '$');
  },

  isExpOperator: function(ch) {
    return (ch === '-' || ch === '+' || this.isNumber(ch));
  },

  throwError: function(error, start, end) {
    end = end || this.index;
    var colStr = (isDefined(start)
            ? 's ' + start +  '-' + this.index + ' [' + this.text.substring(start, end) + ']'
            : ' ' + end);
    throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',
        error, colStr, this.text);
  },

  readNumber: function() {
    var number = '';
    var start = this.index;
    while (this.index < this.text.length) {
      var ch = lowercase(this.text.charAt(this.index));
      if (ch == '.' || this.isNumber(ch)) {
        number += ch;
      } else {
        var peekCh = this.peek();
        if (ch == 'e' && this.isExpOperator(peekCh)) {
          number += ch;
        } else if (this.isExpOperator(ch) &&
            peekCh && this.isNumber(peekCh) &&
            number.charAt(number.length - 1) == 'e') {
          number += ch;
        } else if (this.isExpOperator(ch) &&
            (!peekCh || !this.isNumber(peekCh)) &&
            number.charAt(number.length - 1) == 'e') {
          this.throwError('Invalid exponent');
        } else {
          break;
        }
      }
      this.index++;
    }
    number = 1 * number;
    this.tokens.push({
      index: start,
      text: number,
      literal: true,
      constant: true,
      fn: function() { return number; }
    });
  },

  readIdent: function() {
    var parser = this;

    var ident = '';
    var start = this.index;

    var lastDot, peekIndex, methodName, ch;

    while (this.index < this.text.length) {
      ch = this.text.charAt(this.index);
      if (ch === '.' || this.isIdent(ch) || this.isNumber(ch)) {
        if (ch === '.') lastDot = this.index;
        ident += ch;
      } else {
        break;
      }
      this.index++;
    }

    //check if this is not a method invocation and if it is back out to last dot
    if (lastDot) {
      peekIndex = this.index;
      while (peekIndex < this.text.length) {
        ch = this.text.charAt(peekIndex);
        if (ch === '(') {
          methodName = ident.substr(lastDot - start + 1);
          ident = ident.substr(0, lastDot - start);
          this.index = peekIndex;
          break;
        }
        if (this.isWhitespace(ch)) {
          peekIndex++;
        } else {
          break;
        }
      }
    }


    var token = {
      index: start,
      text: ident
    };

    // OPERATORS is our own object so we don't need to use special hasOwnPropertyFn
    if (OPERATORS.hasOwnProperty(ident)) {
      token.fn = OPERATORS[ident];
      token.literal = true;
      token.constant = true;
    } else {
      var getter = getterFn(ident, this.options, this.text);
      token.fn = extend(function(self, locals) {
        return (getter(self, locals));
      }, {
        assign: function(self, value) {
          return setter(self, ident, value, parser.text, parser.options);
        }
      });
    }

    this.tokens.push(token);

    if (methodName) {
      this.tokens.push({
        index:lastDot,
        text: '.'
      });
      this.tokens.push({
        index: lastDot + 1,
        text: methodName
      });
    }
  },

  readString: function(quote) {
    var start = this.index;
    this.index++;
    var string = '';
    var rawString = quote;
    var escape = false;
    while (this.index < this.text.length) {
      var ch = this.text.charAt(this.index);
      rawString += ch;
      if (escape) {
        if (ch === 'u') {
          var hex = this.text.substring(this.index + 1, this.index + 5);
          if (!hex.match(/[\da-f]{4}/i))
            this.throwError('Invalid unicode escape [\\u' + hex + ']');
          this.index += 4;
          string += String.fromCharCode(parseInt(hex, 16));
        } else {
          var rep = ESCAPE[ch];
          string = string + (rep || ch);
        }
        escape = false;
      } else if (ch === '\\') {
        escape = true;
      } else if (ch === quote) {
        this.index++;
        this.tokens.push({
          index: start,
          text: rawString,
          string: string,
          literal: true,
          constant: true,
          fn: function() { return string; }
        });
        return;
      } else {
        string += ch;
      }
      this.index++;
    }
    this.throwError('Unterminated quote', start);
  }
};


/**
 * @constructor
 */
var Parser = function (lexer, $filter, options) {
  this.lexer = lexer;
  this.$filter = $filter;
  this.options = options;
};

Parser.ZERO = extend(function () {
  return 0;
}, {
  constant: true
});

Parser.prototype = {
  constructor: Parser,

  parse: function (text) {
    this.text = text;

    this.tokens = this.lexer.lex(text);

    var value = this.statements();

    if (this.tokens.length !== 0) {
      this.throwError('is an unexpected token', this.tokens[0]);
    }

    value.literal = !!value.literal;
    value.constant = !!value.constant;

    return value;
  },

  primary: function () {
    var primary;
    if (this.expect('(')) {
      primary = this.filterChain();
      this.consume(')');
    } else if (this.expect('[')) {
      primary = this.arrayDeclaration();
    } else if (this.expect('{')) {
      primary = this.object();
    } else {
      var token = this.expect();
      primary = token.fn;
      if (!primary) {
        this.throwError('not a primary expression', token);
      }
      primary.literal = !!token.literal;
      primary.constant = !!token.constant;
    }

    var next, context;
    while ((next = this.expect('(', '[', '.'))) {
      if (next.text === '(') {
        primary = this.functionCall(primary, context);
        context = null;
      } else if (next.text === '[') {
        context = primary;
        primary = this.objectIndex(primary);
      } else if (next.text === '.') {
        context = primary;
        primary = this.fieldAccess(primary);
      } else {
        this.throwError('IMPOSSIBLE');
      }
    }
    return primary;
  },

  throwError: function(msg, token) {
    throw $parseMinErr('syntax',
        'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].',
          token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));
  },

  peekToken: function() {
    if (this.tokens.length === 0)
      throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
    return this.tokens[0];
  },

  peek: function(e1, e2, e3, e4) {
    if (this.tokens.length > 0) {
      var token = this.tokens[0];
      var t = token.text;
      if (t === e1 || t === e2 || t === e3 || t === e4 ||
          (!e1 && !e2 && !e3 && !e4)) {
        return token;
      }
    }
    return false;
  },

  expect: function(e1, e2, e3, e4){
    var token = this.peek(e1, e2, e3, e4);
    if (token) {
      this.tokens.shift();
      return token;
    }
    return false;
  },

  consume: function(e1){
    if (!this.expect(e1)) {
      this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
    }
  },

  unaryFn: function(fn, right) {
    return extend(function(self, locals) {
      return fn(self, locals, right);
    }, {
      constant:right.constant
    });
  },

  ternaryFn: function(left, middle, right){
    return extend(function(self, locals){
      return left(self, locals) ? middle(self, locals) : right(self, locals);
    }, {
      constant: left.constant && middle.constant && right.constant
    });
  },

  binaryFn: function(left, fn, right) {
    return extend(function(self, locals) {
      return fn(self, locals, left, right);
    }, {
      constant:left.constant && right.constant
    });
  },

  statements: function() {
    var statements = [];
    while (true) {
      if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))
        statements.push(this.filterChain());
      if (!this.expect(';')) {
        // optimize for the common case where there is only one statement.
        // TODO(size): maybe we should not support multiple statements?
        return (statements.length === 1)
            ? statements[0]
            : function(self, locals) {
                var value;
                for (var i = 0; i < statements.length; i++) {
                  var statement = statements[i];
                  if (statement) {
                    value = statement(self, locals);
                  }
                }
                return value;
              };
      }
    }
  },

  filterChain: function() {
    var left = this.expression();
    var token;
    while (true) {
      if ((token = this.expect('|'))) {
        left = this.binaryFn(left, token.fn, this.filter());
      } else {
        return left;
      }
    }
  },

  filter: function() {
    var token = this.expect();
    var fn = this.$filter(token.text);
    var argsFn = [];
    while (true) {
      if ((token = this.expect(':'))) {
        argsFn.push(this.expression());
      } else {
        var fnInvoke = function(self, locals, input) {
          var args = [input];
          for (var i = 0; i < argsFn.length; i++) {
            args.push(argsFn[i](self, locals));
          }
          return fn.apply(self, args);
        };
        return function() {
          return fnInvoke;
        };
      }
    }
  },

  expression: function() {
    return this.assignment();
  },

  assignment: function() {
    var left = this.ternary();
    var right;
    var token;
    if ((token = this.expect('='))) {
      if (!left.assign) {
        this.throwError('implies assignment but [' +
            this.text.substring(0, token.index) + '] can not be assigned to', token);
      }
      right = this.ternary();
      return function(scope, locals) {
        return left.assign(scope, right(scope, locals), locals);
      };
    }
    return left;
  },

  ternary: function() {
    var left = this.logicalOR();
    var middle;
    var token;
    if ((token = this.expect('?'))) {
      middle = this.assignment();
      if ((token = this.expect(':'))) {
        return this.ternaryFn(left, middle, this.assignment());
      } else {
        this.throwError('expected :', token);
      }
    } else {
      return left;
    }
  },

  logicalOR: function() {
    var left = this.logicalAND();
    var token;
    while (true) {
      if ((token = this.expect('||'))) {
        left = this.binaryFn(left, token.fn, this.logicalAND());
      } else {
        return left;
      }
    }
  },

  logicalAND: function() {
    var left = this.equality();
    var token;
    if ((token = this.expect('&&'))) {
      left = this.binaryFn(left, token.fn, this.logicalAND());
    }
    return left;
  },

  equality: function() {
    var left = this.relational();
    var token;
    if ((token = this.expect('==','!=','===','!=='))) {
      left = this.binaryFn(left, token.fn, this.equality());
    }
    return left;
  },

  relational: function() {
    var left = this.additive();
    var token;
    if ((token = this.expect('<', '>', '<=', '>='))) {
      left = this.binaryFn(left, token.fn, this.relational());
    }
    return left;
  },

  additive: function() {
    var left = this.multiplicative();
    var token;
    while ((token = this.expect('+','-'))) {
      left = this.binaryFn(left, token.fn, this.multiplicative());
    }
    return left;
  },

  multiplicative: function() {
    var left = this.unary();
    var token;
    while ((token = this.expect('*','/','%'))) {
      left = this.binaryFn(left, token.fn, this.unary());
    }
    return left;
  },

  unary: function() {
    var token;
    if (this.expect('+')) {
      return this.primary();
    } else if ((token = this.expect('-'))) {
      return this.binaryFn(Parser.ZERO, token.fn, this.unary());
    } else if ((token = this.expect('!'))) {
      return this.unaryFn(token.fn, this.unary());
    } else {
      return this.primary();
    }
  },

  fieldAccess: function(object) {
    var parser = this;
    var field = this.expect().text;
    var getter = getterFn(field, this.options, this.text);

    return extend(function(scope, locals, self) {
      return getter(self || object(scope, locals));
    }, {
      assign: function(scope, value, locals) {
        var o = object(scope, locals);
        if (!o) object.assign(scope, o = {});
        return setter(o, field, value, parser.text, parser.options);
      }
    });
  },

  objectIndex: function(obj) {
    var parser = this;

    var indexFn = this.expression();
    this.consume(']');

    return extend(function(self, locals) {
      var o = obj(self, locals),
          i = indexFn(self, locals),
          v, p;

      ensureSafeMemberName(i, parser.text);
      if (!o) return undefined;
      v = ensureSafeObject(o[i], parser.text);
      if (v && v.then && parser.options.unwrapPromises) {
        p = v;
        if (!('$$v' in v)) {
          p.$$v = undefined;
          p.then(function(val) { p.$$v = val; });
        }
        v = v.$$v;
      }
      return v;
    }, {
      assign: function(self, value, locals) {
        var key = ensureSafeMemberName(indexFn(self, locals), parser.text);
        // prevent overwriting of Function.constructor which would break ensureSafeObject check
        var o = ensureSafeObject(obj(self, locals), parser.text);
        if (!o) obj.assign(self, o = {});
        return o[key] = value;
      }
    });
  },

  functionCall: function(fn, contextGetter) {
    var argsFn = [];
    if (this.peekToken().text !== ')') {
      do {
        argsFn.push(this.expression());
      } while (this.expect(','));
    }
    this.consume(')');

    var parser = this;

    return function(scope, locals) {
      var args = [];
      var context = contextGetter ? contextGetter(scope, locals) : scope;

      for (var i = 0; i < argsFn.length; i++) {
        args.push(ensureSafeObject(argsFn[i](scope, locals), parser.text));
      }
      var fnPtr = fn(scope, locals, context) || noop;

      ensureSafeObject(context, parser.text);
      ensureSafeFunction(fnPtr, parser.text);

      // IE doesn't have apply for some native functions
      var v = fnPtr.apply
            ? fnPtr.apply(context, args)
            : fnPtr(args[0], args[1], args[2], args[3], args[4]);

      return ensureSafeObject(v, parser.text);
    };
  },

  // This is used with json array declaration
  arrayDeclaration: function () {
    var elementFns = [];
    var allConstant = true;
    if (this.peekToken().text !== ']') {
      do {
        if (this.peek(']')) {
          // Support trailing commas per ES5.1.
          break;
        }
        var elementFn = this.expression();
        elementFns.push(elementFn);
        if (!elementFn.constant) {
          allConstant = false;
        }
      } while (this.expect(','));
    }
    this.consume(']');

    return extend(function(self, locals) {
      var array = [];
      for (var i = 0; i < elementFns.length; i++) {
        array.push(elementFns[i](self, locals));
      }
      return array;
    }, {
      literal: true,
      constant: allConstant
    });
  },

  object: function () {
    var keyValues = [];
    var allConstant = true;
    if (this.peekToken().text !== '}') {
      do {
        if (this.peek('}')) {
          // Support trailing commas per ES5.1.
          break;
        }
        var token = this.expect(),
        key = token.string || token.text;
        this.consume(':');
        var value = this.expression();
        keyValues.push({key: key, value: value});
        if (!value.constant) {
          allConstant = false;
        }
      } while (this.expect(','));
    }
    this.consume('}');

    return extend(function(self, locals) {
      var object = {};
      for (var i = 0; i < keyValues.length; i++) {
        var keyValue = keyValues[i];
        object[keyValue.key] = keyValue.value(self, locals);
      }
      return object;
    }, {
      literal: true,
      constant: allConstant
    });
  }
};


//////////////////////////////////////////////////
// Parser helper functions
//////////////////////////////////////////////////

function setter(obj, path, setValue, fullExp, options) {
  ensureSafeObject(obj, fullExp);

  //needed?
  options = options || {};

  var element = path.split('.'), key;
  for (var i = 0; element.length > 1; i++) {
    key = ensureSafeMemberName(element.shift(), fullExp);
    var propertyObj = ensureSafeObject(obj[key], fullExp);
    if (!propertyObj) {
      propertyObj = {};
      obj[key] = propertyObj;
    }
    obj = propertyObj;
    if (obj.then && options.unwrapPromises) {
      promiseWarning(fullExp);
      if (!("$$v" in obj)) {
        (function(promise) {
          promise.then(function(val) { promise.$$v = val; }); }
        )(obj);
      }
      if (obj.$$v === undefined) {
        obj.$$v = {};
      }
      obj = obj.$$v;
    }
  }
  key = ensureSafeMemberName(element.shift(), fullExp);
  ensureSafeObject(obj[key], fullExp);
  obj[key] = setValue;
  return setValue;
}

var getterFnCacheDefault = {};
var getterFnCacheExpensive = {};

function isPossiblyDangerousMemberName(name) {
  return name == 'constructor';
}

/**
 * Implementation of the "Black Hole" variant from:
 * - http://jsperf.com/angularjs-parse-getter/4
 * - http://jsperf.com/path-evaluation-simplified/7
 */
function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
  ensureSafeMemberName(key0, fullExp);
  ensureSafeMemberName(key1, fullExp);
  ensureSafeMemberName(key2, fullExp);
  ensureSafeMemberName(key3, fullExp);
  ensureSafeMemberName(key4, fullExp);
  var eso = function(o) {
    return ensureSafeObject(o, fullExp);
  };
  var expensiveChecks = options.expensiveChecks;
  var eso0 = (expensiveChecks || isPossiblyDangerousMemberName(key0)) ? eso : identity;
  var eso1 = (expensiveChecks || isPossiblyDangerousMemberName(key1)) ? eso : identity;
  var eso2 = (expensiveChecks || isPossiblyDangerousMemberName(key2)) ? eso : identity;
  var eso3 = (expensiveChecks || isPossiblyDangerousMemberName(key3)) ? eso : identity;
  var eso4 = (expensiveChecks || isPossiblyDangerousMemberName(key4)) ? eso : identity;

  return !options.unwrapPromises
      ? function cspSafeGetter(scope, locals) {
          var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;

          if (pathVal == null) return pathVal;
          pathVal = eso0(pathVal[key0]);

          if (!key1) return pathVal;
          if (pathVal == null) return undefined;
          pathVal = eso1(pathVal[key1]);

          if (!key2) return pathVal;
          if (pathVal == null) return undefined;
          pathVal = eso2(pathVal[key2]);

          if (!key3) return pathVal;
          if (pathVal == null) return undefined;
          pathVal = eso3(pathVal[key3]);

          if (!key4) return pathVal;
          if (pathVal == null) return undefined;
          pathVal = eso4(pathVal[key4]);

          return pathVal;
        }
      : function cspSafePromiseEnabledGetter(scope, locals) {
          var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,
              promise;

          if (pathVal == null) return pathVal;

          pathVal = eso0(pathVal[key0]);
          if (pathVal && pathVal.then) {
            promiseWarning(fullExp);
            if (!("$$v" in pathVal)) {
              promise = pathVal;
              promise.$$v = undefined;
              promise.then(function(val) { promise.$$v = eso0(val); });
            }
            pathVal = eso0(pathVal.$$v);
          }

          if (!key1) return pathVal;
          if (pathVal == null) return undefined;
          pathVal = eso1(pathVal[key1]);
          if (pathVal && pathVal.then) {
            promiseWarning(fullExp);
            if (!("$$v" in pathVal)) {
              promise = pathVal;
              promise.$$v = undefined;
              promise.then(function(val) { promise.$$v = eso1(val); });
            }
            pathVal = eso1(pathVal.$$v);
          }

          if (!key2) return pathVal;
          if (pathVal == null) return undefined;
          pathVal = eso2(pathVal[key2]);
          if (pathVal && pathVal.then) {
            promiseWarning(fullExp);
            if (!("$$v" in pathVal)) {
              promise = pathVal;
              promise.$$v = undefined;
              promise.then(function(val) { promise.$$v = eso2(val); });
            }
            pathVal = eso2(pathVal.$$v);
          }

          if (!key3) return pathVal;
          if (pathVal == null) return undefined;
          pathVal = eso3(pathVal[key3]);
          if (pathVal && pathVal.then) {
            promiseWarning(fullExp);
            if (!("$$v" in pathVal)) {
              promise = pathVal;
              promise.$$v = undefined;
              promise.then(function(val) { promise.$$v = eso3(val); });
            }
            pathVal = eso3(pathVal.$$v);
          }

          if (!key4) return pathVal;
          if (pathVal == null) return undefined;
          pathVal = eso4(pathVal[key4]);
          if (pathVal && pathVal.then) {
            promiseWarning(fullExp);
            if (!("$$v" in pathVal)) {
              promise = pathVal;
              promise.$$v = undefined;
              promise.then(function(val) { promise.$$v = eso4(val); });
            }
            pathVal = eso4(pathVal.$$v);
          }
          return pathVal;
        };
}

function getterFnWithExtraArgs(fn, fullExpression) {
  return function(s, l) {
    return fn(s, l, promiseWarning, ensureSafeObject, fullExpression);
  };
}

function getterFn(path, options, fullExp) {
  var expensiveChecks = options.expensiveChecks;
  var getterFnCache = (expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault);
  // Check whether the cache has this getter already.
  // We can use hasOwnProperty directly on the cache because we ensure,
  // see below, that the cache never stores a path called 'hasOwnProperty'
  if (getterFnCache.hasOwnProperty(path)) {
    return getterFnCache[path];
  }

  var pathKeys = path.split('.'),
      pathKeysLength = pathKeys.length,
      fn;

  // http://jsperf.com/angularjs-parse-getter/6
  if (options.csp) {
    if (pathKeysLength < 6) {
      fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp,
                          options);
    } else {
      fn = function(scope, locals) {
        var i = 0, val;
        do {
          val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],
                                pathKeys[i++], fullExp, options)(scope, locals);

          locals = undefined; // clear after first iteration
          scope = val;
        } while (i < pathKeysLength);
        return val;
      };
    }
  } else {
    var code = 'var p;\n';
    if (expensiveChecks) {
      code += 's = eso(s, fe);\nl = eso(l, fe);\n';
    }
    var needsEnsureSafeObject = expensiveChecks;
    forEach(pathKeys, function(key, index) {
      ensureSafeMemberName(key, fullExp);
      var lookupJs = (index
                      // we simply dereference 's' on any .dot notation
                      ? 's'
                      // but if we are first then we check locals first, and if so read it first
                      : '((l&&l.hasOwnProperty("' + key + '"))?l:s)') + '["' + key + '"]';
      var wrapWithEso = expensiveChecks || isPossiblyDangerousMemberName(key);
      if (wrapWithEso) {
        lookupJs = 'eso(' + lookupJs + ', fe)';
        needsEnsureSafeObject = true;
      }
      code += 'if(s == null) return undefined;\n' +
              's=' + lookupJs + ';\n';
      if (options.unwrapPromises) {
        code += 'if (s && s.then) {\n' +
                  ' pw("' + fullExp.replace(/(["\r\n])/g, '\\$1') + '");\n' +
                  ' if (!("$$v" in s)) {\n' +
                    ' p=s;\n' +
                    ' p.$$v = undefined;\n' +
                    ' p.then(function(v) {p.$$v=' + (wrapWithEso ? 'eso(v)' : 'v') + ';});\n' +
                    '}\n' +
                  ' s=' + (wrapWithEso ? 'eso(s.$$v)' : 's.$$v') + '\n' +
                '}\n';

      }
    });
    code += 'return s;';

    /* jshint -W054 */
    // s=scope, l=locals, pw=promiseWarning, eso=ensureSafeObject, fe=fullExpression
    var evaledFnGetter = new Function('s', 'l', 'pw', 'eso', 'fe', code);
    /* jshint +W054 */
    evaledFnGetter.toString = valueFn(code);
    if (needsEnsureSafeObject || options.unwrapPromises) {
      evaledFnGetter = getterFnWithExtraArgs(evaledFnGetter, fullExp);
    }
    fn = evaledFnGetter;
  }

  // Only cache the value if it's not going to mess up the cache object
  // This is more performant that using Object.prototype.hasOwnProperty.call
  if (path !== 'hasOwnProperty') {
    getterFnCache[path] = fn;
  }
  return fn;
}

///////////////////////////////////

/**
 * @ngdoc service
 * @name $parse
 * @kind function
 *
 * @description
 *
 * Converts Angular {@link guide/expression expression} into a function.
 *
 * ```js
 *   var getter = $parse('user.name');
 *   var setter = getter.assign;
 *   var context = {user:{name:'angular'}};
 *   var locals = {user:{name:'local'}};
 *
 *   expect(getter(context)).toEqual('angular');
 *   setter(context, 'newValue');
 *   expect(context.user.name).toEqual('newValue');
 *   expect(getter(context, locals)).toEqual('local');
 * ```
 *
 *
 * @param {string} expression String expression to compile.
 * @returns {function(context, locals)} a function which represents the compiled expression:
 *
 *    * `context` – `{object}` – an object against which any expressions embedded in the strings
 *      are evaluated against (typically a scope object).
 *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
 *      `context`.
 *
 *    The returned function also has the following properties:
 *      * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript
 *        literal.
 *      * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript
 *        constant literals.
 *      * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be
 *        set to a function to change its value on the given context.
 *
 */


/**
 * @ngdoc provider
 * @name $parseProvider
 * @kind function
 *
 * @description
 * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
 *  service.
 */
function $ParseProvider() {
  var cacheDefault = {};
  var cacheExpensive = {};

  var $parseOptions = {
    csp: false,
    unwrapPromises: false,
    logPromiseWarnings: true,
    expensiveChecks: false
  };


  /**
   * @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.
   *
   * @ngdoc method
   * @name $parseProvider#unwrapPromises
   * @description
   *
   * **This feature is deprecated, see deprecation notes below for more info**
   *
   * If set to true (default is false), $parse will unwrap promises automatically when a promise is
   * found at any part of the expression. In other words, if set to true, the expression will always
   * result in a non-promise value.
   *
   * While the promise is unresolved, it's treated as undefined, but once resolved and fulfilled,
   * the fulfillment value is used in place of the promise while evaluating the expression.
   *
   * **Deprecation notice**
   *
   * This is a feature that didn't prove to be wildly useful or popular, primarily because of the
   * dichotomy between data access in templates (accessed as raw values) and controller code
   * (accessed as promises).
   *
   * In most code we ended up resolving promises manually in controllers anyway and thus unifying
   * the model access there.
   *
   * Other downsides of automatic promise unwrapping:
   *
   * - when building components it's often desirable to receive the raw promises
   * - adds complexity and slows down expression evaluation
   * - makes expression code pre-generation unattractive due to the amount of code that needs to be
   *   generated
   * - makes IDE auto-completion and tool support hard
   *
   * **Warning Logs**
   *
   * If the unwrapping is enabled, Angular will log a warning about each expression that unwraps a
   * promise (to reduce the noise, each expression is logged only once). To disable this logging use
   * `$parseProvider.logPromiseWarnings(false)` api.
   *
   *
   * @param {boolean=} value New value.
   * @returns {boolean|self} Returns the current setting when used as getter and self if used as
   *                         setter.
   */
  this.unwrapPromises = function(value) {
    if (isDefined(value)) {
      $parseOptions.unwrapPromises = !!value;
      return this;
    } else {
      return $parseOptions.unwrapPromises;
    }
  };


  /**
   * @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.
   *
   * @ngdoc method
   * @name $parseProvider#logPromiseWarnings
   * @description
   *
   * Controls whether Angular should log a warning on any encounter of a promise in an expression.
   *
   * The default is set to `true`.
   *
   * This setting applies only if `$parseProvider.unwrapPromises` setting is set to true as well.
   *
   * @param {boolean=} value New value.
   * @returns {boolean|self} Returns the current setting when used as getter and self if used as
   *                         setter.
   */
 this.logPromiseWarnings = function(value) {
    if (isDefined(value)) {
      $parseOptions.logPromiseWarnings = value;
      return this;
    } else {
      return $parseOptions.logPromiseWarnings;
    }
  };


  this.$get = ['$filter', '$sniffer', '$log', function($filter, $sniffer, $log) {
    $parseOptions.csp = $sniffer.csp;
    var $parseOptionsExpensive = {
      csp: $parseOptions.csp,
      unwrapPromises: $parseOptions.unwrapPromises,
      logPromiseWarnings: $parseOptions.logPromiseWarnings,
      expensiveChecks: true
    };

    promiseWarning = function promiseWarningFn(fullExp) {
      if (!$parseOptions.logPromiseWarnings || promiseWarningCache.hasOwnProperty(fullExp)) return;
      promiseWarningCache[fullExp] = true;
      $log.warn('[$parse] Promise found in the expression `' + fullExp + '`. ' +
          'Automatic unwrapping of promises in Angular expressions is deprecated.');
    };

    return function(exp, expensiveChecks) {
      var parsedExpression;

      switch (typeof exp) {
        case 'string':

          var cache = (expensiveChecks ? cacheExpensive : cacheDefault);
          if (cache.hasOwnProperty(exp)) {
            return cache[exp];
          }

          var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;
          var lexer = new Lexer(parseOptions);
          var parser = new Parser(lexer, $filter, parseOptions);
          parsedExpression = parser.parse(exp);

          if (exp !== 'hasOwnProperty') {
            // Only cache the value if it's not going to mess up the cache object
            // This is more performant that using Object.prototype.hasOwnProperty.call
            cache[exp] = parsedExpression;
          }

          return parsedExpression;

        case 'function':
          return exp;

        default:
          return noop;
      }
    };
  }];
}

/**
 * @ngdoc service
 * @name $q
 * @requires $rootScope
 *
 * @description
 * A service that helps you run functions asynchronously, and use their return values (or exceptions)
 * when they are done processing.
 *
 * This is an implementation of promises/deferred objects inspired by
 * [Kris Kowal's Q](https://github.com/kriskowal/q).
 *
 * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
 * interface for interacting with an object that represents the result of an action that is
 * performed asynchronously, and may or may not be finished at any given point in time.
 *
 * From the perspective of dealing with error handling, deferred and promise APIs are to
 * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
 *
 * ```js
 *   // for the purpose of this example let's assume that variables `$q`, `scope` and `okToGreet`
 *   // are available in the current lexical scope (they could have been injected or passed in).
 *
 *   function asyncGreet(name) {
 *     var deferred = $q.defer();
 *
 *     setTimeout(function() {
 *       deferred.notify('About to greet ' + name + '.');
 *
 *       if (okToGreet(name)) {
 *         deferred.resolve('Hello, ' + name + '!');
 *       } else {
 *         deferred.reject('Greeting ' + name + ' is not allowed.');
 *       }
 *     }, 1000);
 *
 *     return deferred.promise;
 *   }
 *
 *   var promise = asyncGreet('Robin Hood');
 *   promise.then(function(greeting) {
 *     alert('Success: ' + greeting);
 *   }, function(reason) {
 *     alert('Failed: ' + reason);
 *   }, function(update) {
 *     alert('Got notification: ' + update);
 *   });
 * ```
 *
 * At first it might not be obvious why this extra complexity is worth the trouble. The payoff
 * comes in the way of guarantees that promise and deferred APIs make, see
 * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.
 *
 * Additionally the promise api allows for composition that is very hard to do with the
 * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
 * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the
 * section on serial or parallel joining of promises.
 *
 *
 * # The Deferred API
 *
 * A new instance of deferred is constructed by calling `$q.defer()`.
 *
 * The purpose of the deferred object is to expose the associated Promise instance as well as APIs
 * that can be used for signaling the successful or unsuccessful completion, as well as the status
 * of the task.
 *
 * **Methods**
 *
 * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
 *   constructed via `$q.reject`, the promise will be rejected instead.
 * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
 *   resolving it with a rejection constructed via `$q.reject`.
 * - `notify(value)` - provides updates on the status of the promise's execution. This may be called
 *   multiple times before the promise is either resolved or rejected.
 *
 * **Properties**
 *
 * - promise – `{Promise}` – promise object associated with this deferred.
 *
 *
 * # The Promise API
 *
 * A new promise instance is created when a deferred instance is created and can be retrieved by
 * calling `deferred.promise`.
 *
 * The purpose of the promise object is to allow for interested parties to get access to the result
 * of the deferred task when it completes.
 *
 * **Methods**
 *
 * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or
 *   will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously
 *   as soon as the result is available. The callbacks are called with a single argument: the result
 *   or rejection reason. Additionally, the notify callback may be called zero or more times to
 *   provide a progress indication, before the promise is resolved or rejected.
 *
 *   This method *returns a new promise* which is resolved or rejected via the return value of the
 *   `successCallback`, `errorCallback`. It also notifies via the return value of the
 *   `notifyCallback` method. The promise can not be resolved or rejected from the notifyCallback
 *   method.
 *
 * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`
 *
 *   Because `catch` is a reserved word in JavaScript and reserved keywords are not supported as
 *   property names by ES3, you'll need to invoke the method like `promise['catch'](callback)` or
 *  `promise.then(null, errorCallback)` to make your code IE8 and Android 2.x compatible.
 *
 * - `finally(callback)` – allows you to observe either the fulfillment or rejection of a promise,
 *   but to do so without modifying the final value. This is useful to release resources or do some
 *   clean-up that needs to be done whether the promise was rejected or resolved. See the [full
 *   specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for
 *   more information.
 *
 *   Because `finally` is a reserved word in JavaScript and reserved keywords are not supported as
 *   property names by ES3, you'll need to invoke the method like `promise['finally'](callback)` to
 *   make your code IE8 and Android 2.x compatible.
 *
 * # Chaining promises
 *
 * Because calling the `then` method of a promise returns a new derived promise, it is easily
 * possible to create a chain of promises:
 *
 * ```js
 *   promiseB = promiseA.then(function(result) {
 *     return result + 1;
 *   });
 *
 *   // promiseB will be resolved immediately after promiseA is resolved and its value
 *   // will be the result of promiseA incremented by 1
 * ```
 *
 * It is possible to create chains of any length and since a promise can be resolved with another
 * promise (which will defer its resolution further), it is possible to pause/defer resolution of
 * the promises at any point in the chain. This makes it possible to implement powerful APIs like
 * $http's response interceptors.
 *
 *
 * # Differences between Kris Kowal's Q and $q
 *
 *  There are two main differences:
 *
 * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation
 *   mechanism in angular, which means faster propagation of resolution or rejection into your
 *   models and avoiding unnecessary browser repaints, which would result in flickering UI.
 * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains
 *   all the important functionality needed for common async tasks.
 *
 *  # Testing
 *
 *  ```js
 *    it('should simulate promise', inject(function($q, $rootScope) {
 *      var deferred = $q.defer();
 *      var promise = deferred.promise;
 *      var resolvedValue;
 *
 *      promise.then(function(value) { resolvedValue = value; });
 *      expect(resolvedValue).toBeUndefined();
 *
 *      // Simulate resolving of promise
 *      deferred.resolve(123);
 *      // Note that the 'then' function does not get called synchronously.
 *      // This is because we want the promise API to always be async, whether or not
 *      // it got called synchronously or asynchronously.
 *      expect(resolvedValue).toBeUndefined();
 *
 *      // Propagate promise resolution to 'then' functions using $apply().
 *      $rootScope.$apply();
 *      expect(resolvedValue).toEqual(123);
 *    }));
 *  ```
 */
function $QProvider() {

  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
    return qFactory(function(callback) {
      $rootScope.$evalAsync(callback);
    }, $exceptionHandler);
  }];
}


/**
 * Constructs a promise manager.
 *
 * @param {function(Function)} nextTick Function for executing functions in the next turn.
 * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for
 *     debugging purposes.
 * @returns {object} Promise manager.
 */
function qFactory(nextTick, exceptionHandler) {

  /**
   * @ngdoc method
   * @name $q#defer
   * @kind function
   *
   * @description
   * Creates a `Deferred` object which represents a task which will finish in the future.
   *
   * @returns {Deferred} Returns a new instance of deferred.
   */
  var defer = function() {
    var pending = [],
        value, deferred;

    deferred = {

      resolve: function(val) {
        if (pending) {
          var callbacks = pending;
          pending = undefined;
          value = ref(val);

          if (callbacks.length) {
            nextTick(function() {
              var callback;
              for (var i = 0, ii = callbacks.length; i < ii; i++) {
                callback = callbacks[i];
                value.then(callback[0], callback[1], callback[2]);
              }
            });
          }
        }
      },


      reject: function(reason) {
        deferred.resolve(createInternalRejectedPromise(reason));
      },


      notify: function(progress) {
        if (pending) {
          var callbacks = pending;

          if (pending.length) {
            nextTick(function() {
              var callback;
              for (var i = 0, ii = callbacks.length; i < ii; i++) {
                callback = callbacks[i];
                callback[2](progress);
              }
            });
          }
        }
      },


      promise: {
        then: function(callback, errback, progressback) {
          var result = defer();

          var wrappedCallback = function(value) {
            try {
              result.resolve((isFunction(callback) ? callback : defaultCallback)(value));
            } catch(e) {
              result.reject(e);
              exceptionHandler(e);
            }
          };

          var wrappedErrback = function(reason) {
            try {
              result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
            } catch(e) {
              result.reject(e);
              exceptionHandler(e);
            }
          };

          var wrappedProgressback = function(progress) {
            try {
              result.notify((isFunction(progressback) ? progressback : defaultCallback)(progress));
            } catch(e) {
              exceptionHandler(e);
            }
          };

          if (pending) {
            pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]);
          } else {
            value.then(wrappedCallback, wrappedErrback, wrappedProgressback);
          }

          return result.promise;
        },

        "catch": function(callback) {
          return this.then(null, callback);
        },

        "finally": function(callback) {

          function makePromise(value, resolved) {
            var result = defer();
            if (resolved) {
              result.resolve(value);
            } else {
              result.reject(value);
            }
            return result.promise;
          }

          function handleCallback(value, isResolved) {
            var callbackOutput = null;
            try {
              callbackOutput = (callback ||defaultCallback)();
            } catch(e) {
              return makePromise(e, false);
            }
            if (isPromiseLike(callbackOutput)) {
              return callbackOutput.then(function() {
                return makePromise(value, isResolved);
              }, function(error) {
                return makePromise(error, false);
              });
            } else {
              return makePromise(value, isResolved);
            }
          }

          return this.then(function(value) {
            return handleCallback(value, true);
          }, function(error) {
            return handleCallback(error, false);
          });
        }
      }
    };

    return deferred;
  };


  var ref = function(value) {
    if (isPromiseLike(value)) return value;
    return {
      then: function(callback) {
        var result = defer();
        nextTick(function() {
          result.resolve(callback(value));
        });
        return result.promise;
      }
    };
  };


  /**
   * @ngdoc method
   * @name $q#reject
   * @kind function
   *
   * @description
   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be
   * used to forward rejection in a chain of promises. If you are dealing with the last promise in
   * a promise chain, you don't need to worry about it.
   *
   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of
   * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via
   * a promise error callback and you want to forward the error to the promise derived from the
   * current promise, you have to "rethrow" the error by returning a rejection constructed via
   * `reject`.
   *
   * ```js
   *   promiseB = promiseA.then(function(result) {
   *     // success: do something and resolve promiseB
   *     //          with the old or a new result
   *     return result;
   *   }, function(reason) {
   *     // error: handle the error if possible and
   *     //        resolve promiseB with newPromiseOrValue,
   *     //        otherwise forward the rejection to promiseB
   *     if (canHandle(reason)) {
   *      // handle the error and recover
   *      return newPromiseOrValue;
   *     }
   *     return $q.reject(reason);
   *   });
   * ```
   *
   * @param {*} reason Constant, message, exception or an object representing the rejection reason.
   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
   */
  var reject = function(reason) {
    var result = defer();
    result.reject(reason);
    return result.promise;
  };

  var createInternalRejectedPromise = function(reason) {
    return {
      then: function(callback, errback) {
        var result = defer();
        nextTick(function() {
          try {
            result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
          } catch(e) {
            result.reject(e);
            exceptionHandler(e);
          }
        });
        return result.promise;
      }
    };
  };


  /**
   * @ngdoc method
   * @name $q#when
   * @kind function
   *
   * @description
   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
   * This is useful when you are dealing with an object that might or might not be a promise, or if
   * the promise comes from a source that can't be trusted.
   *
   * @param {*} value Value or a promise
   * @returns {Promise} Returns a promise of the passed value or promise
   */
  var when = function(value, callback, errback, progressback) {
    var result = defer(),
        done;

    var wrappedCallback = function(value) {
      try {
        return (isFunction(callback) ? callback : defaultCallback)(value);
      } catch (e) {
        exceptionHandler(e);
        return reject(e);
      }
    };

    var wrappedErrback = function(reason) {
      try {
        return (isFunction(errback) ? errback : defaultErrback)(reason);
      } catch (e) {
        exceptionHandler(e);
        return reject(e);
      }
    };

    var wrappedProgressback = function(progress) {
      try {
        return (isFunction(progressback) ? progressback : defaultCallback)(progress);
      } catch (e) {
        exceptionHandler(e);
      }
    };

    nextTick(function() {
      ref(value).then(function(value) {
        if (done) return;
        done = true;
        result.resolve(ref(value).then(wrappedCallback, wrappedErrback, wrappedProgressback));
      }, function(reason) {
        if (done) return;
        done = true;
        result.resolve(wrappedErrback(reason));
      }, function(progress) {
        if (done) return;
        result.notify(wrappedProgressback(progress));
      });
    });

    return result.promise;
  };


  function defaultCallback(value) {
    return value;
  }


  function defaultErrback(reason) {
    return reject(reason);
  }


  /**
   * @ngdoc method
   * @name $q#all
   * @kind function
   *
   * @description
   * Combines multiple promises into a single promise that is resolved when all of the input
   * promises are resolved.
   *
   * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.
   * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,
   *   each value corresponding to the promise at the same index/key in the `promises` array/hash.
   *   If any of the promises is resolved with a rejection, this resulting promise will be rejected
   *   with the same rejection value.
   */
  function all(promises) {
    var deferred = defer(),
        counter = 0,
        results = isArray(promises) ? [] : {};

    forEach(promises, function(promise, key) {
      counter++;
      ref(promise).then(function(value) {
        if (results.hasOwnProperty(key)) return;
        results[key] = value;
        if (!(--counter)) deferred.resolve(results);
      }, function(reason) {
        if (results.hasOwnProperty(key)) return;
        deferred.reject(reason);
      });
    });

    if (counter === 0) {
      deferred.resolve(results);
    }

    return deferred.promise;
  }

  return {
    defer: defer,
    reject: reject,
    when: when,
    all: all
  };
}

function $$RAFProvider(){ //rAF
  this.$get = ['$window', '$timeout', function($window, $timeout) {
    var requestAnimationFrame = $window.requestAnimationFrame ||
                                $window.webkitRequestAnimationFrame ||
                                $window.mozRequestAnimationFrame;

    var cancelAnimationFrame = $window.cancelAnimationFrame ||
                               $window.webkitCancelAnimationFrame ||
                               $window.mozCancelAnimationFrame ||
                               $window.webkitCancelRequestAnimationFrame;

    var rafSupported = !!requestAnimationFrame;
    var raf = rafSupported
      ? function(fn) {
          var id = requestAnimationFrame(fn);
          return function() {
            cancelAnimationFrame(id);
          };
        }
      : function(fn) {
          var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666
          return function() {
            $timeout.cancel(timer);
          };
        };

    raf.supported = rafSupported;

    return raf;
  }];
}

/**
 * DESIGN NOTES
 *
 * The design decisions behind the scope are heavily favored for speed and memory consumption.
 *
 * The typical use of scope is to watch the expressions, which most of the time return the same
 * value as last time so we optimize the operation.
 *
 * Closures construction is expensive in terms of speed as well as memory:
 *   - No closures, instead use prototypical inheritance for API
 *   - Internal state needs to be stored on scope directly, which means that private state is
 *     exposed as $$____ properties
 *
 * Loop operations are optimized by using while(count--) { ... }
 *   - this means that in order to keep the same order of execution as addition we have to add
 *     items to the array at the beginning (unshift) instead of at the end (push)
 *
 * Child scopes are created and removed often
 *   - Using an array would be slow since inserts in middle are expensive so we use linked list
 *
 * There are few watches then a lot of observers. This is why you don't want the observer to be
 * implemented in the same way as watch. Watch requires return of initialization function which
 * are expensive to construct.
 */


/**
 * @ngdoc provider
 * @name $rootScopeProvider
 * @description
 *
 * Provider for the $rootScope service.
 */

/**
 * @ngdoc method
 * @name $rootScopeProvider#digestTtl
 * @description
 *
 * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and
 * assuming that the model is unstable.
 *
 * The current default is 10 iterations.
 *
 * In complex applications it's possible that the dependencies between `$watch`s will result in
 * several digest iterations. However if an application needs more than the default 10 digest
 * iterations for its model to stabilize then you should investigate what is causing the model to
 * continuously change during the digest.
 *
 * Increasing the TTL could have performance implications, so you should not change it without
 * proper justification.
 *
 * @param {number} limit The number of digest iterations.
 */


/**
 * @ngdoc service
 * @name $rootScope
 * @description
 *
 * Every application has a single root {@link ng.$rootScope.Scope scope}.
 * All other scopes are descendant scopes of the root scope. Scopes provide separation
 * between the model and the view, via a mechanism for watching the model for changes.
 * They also provide an event emission/broadcast and subscription facility. See the
 * {@link guide/scope developer guide on scopes}.
 */
function $RootScopeProvider(){
  var TTL = 10;
  var $rootScopeMinErr = minErr('$rootScope');
  var lastDirtyWatch = null;

  this.digestTtl = function(value) {
    if (arguments.length) {
      TTL = value;
    }
    return TTL;
  };

  this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
      function( $injector,   $exceptionHandler,   $parse,   $browser) {

    /**
     * @ngdoc type
     * @name $rootScope.Scope
     *
     * @description
     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the
     * {@link auto.$injector $injector}. Child scopes are created using the
     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when
     * compiled HTML template is executed.)
     *
     * Here is a simple scope snippet to show how you can interact with the scope.
     * ```html
     * <file src="./test/ng/rootScopeSpec.js" tag="docs1" />
     * ```
     *
     * # Inheritance
     * A scope can inherit from a parent scope, as in this example:
     * ```js
         var parent = $rootScope;
         var child = parent.$new();

         parent.salutation = "Hello";
         child.name = "World";
         expect(child.salutation).toEqual('Hello');

         child.salutation = "Welcome";
         expect(child.salutation).toEqual('Welcome');
         expect(parent.salutation).toEqual('Hello');
     * ```
     *
     *
     * @param {Object.<string, function()>=} providers Map of service factory which need to be
     *                                       provided for the current scope. Defaults to {@link ng}.
     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should
     *                              append/override services provided by `providers`. This is handy
     *                              when unit-testing and having the need to override a default
     *                              service.
     * @returns {Object} Newly created scope.
     *
     */
    function Scope() {
      this.$id = nextUid();
      this.$$phase = this.$parent = this.$$watchers =
                     this.$$nextSibling = this.$$prevSibling =
                     this.$$childHead = this.$$childTail = null;
      this['this'] = this.$root =  this;
      this.$$destroyed = false;
      this.$$asyncQueue = [];
      this.$$postDigestQueue = [];
      this.$$listeners = {};
      this.$$listenerCount = {};
      this.$$isolateBindings = {};
    }

    /**
     * @ngdoc property
     * @name $rootScope.Scope#$id
     *
     * @description
     * Unique scope ID (monotonically increasing) useful for debugging.
     */

     /**
      * @ngdoc property
      * @name $rootScope.Scope#$parent
      *
      * @description
      * Reference to the parent scope.
      */

      /**
       * @ngdoc property
       * @name $rootScope.Scope#$root
       *
       * @description
       * Reference to the root scope.
       */

    Scope.prototype = {
      constructor: Scope,
      /**
       * @ngdoc method
       * @name $rootScope.Scope#$new
       * @kind function
       *
       * @description
       * Creates a new child {@link ng.$rootScope.Scope scope}.
       *
       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.
       * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
       *
       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is
       * desired for the scope and its child scopes to be permanently detached from the parent and
       * thus stop participating in model change detection and listener notification by invoking.
       *
       * @param {boolean} isolate If true, then the scope does not prototypically inherit from the
       *         parent scope. The scope is isolated, as it can not see parent scope properties.
       *         When creating widgets, it is useful for the widget to not accidentally read parent
       *         state.
       *
       * @returns {Object} The newly created child scope.
       *
       */
      $new: function(isolate) {
        var ChildScope,
            child;

        if (isolate) {
          child = new Scope();
          child.$root = this.$root;
          // ensure that there is just one async queue per $rootScope and its children
          child.$$asyncQueue = this.$$asyncQueue;
          child.$$postDigestQueue = this.$$postDigestQueue;
        } else {
          // Only create a child scope class if somebody asks for one,
          // but cache it to allow the VM to optimize lookups.
          if (!this.$$childScopeClass) {
            this.$$childScopeClass = function() {
              this.$$watchers = this.$$nextSibling =
                  this.$$childHead = this.$$childTail = null;
              this.$$listeners = {};
              this.$$listenerCount = {};
              this.$id = nextUid();
              this.$$childScopeClass = null;
            };
            this.$$childScopeClass.prototype = this;
          }
          child = new this.$$childScopeClass();
        }
        child['this'] = child;
        child.$parent = this;
        child.$$prevSibling = this.$$childTail;
        if (this.$$childHead) {
          this.$$childTail.$$nextSibling = child;
          this.$$childTail = child;
        } else {
          this.$$childHead = this.$$childTail = child;
        }
        return child;
      },

      /**
       * @ngdoc method
       * @name $rootScope.Scope#$watch
       * @kind function
       *
       * @description
       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.
       *
       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest
       *   $digest()} and should return the value that will be watched. (Since
       *   {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the
       *   `watchExpression` can execute multiple times per
       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)
       * - The `listener` is called only when the value from the current `watchExpression` and the
       *   previous call to `watchExpression` are not equal (with the exception of the initial run,
       *   see below). Inequality is determined according to reference inequality,
       *   [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)
       *    via the `!==` Javascript operator, unless `objectEquality == true`
       *   (see next point)
       * - When `objectEquality == true`, inequality of the `watchExpression` is determined
       *   according to the {@link angular.equals} function. To save the value of the object for
       *   later comparison, the {@link angular.copy} function is used. This therefore means that
       *   watching complex objects will have adverse memory and performance implications.
       * - The watch `listener` may change the model, which may trigger other `listener`s to fire.
       *   This is achieved by rerunning the watchers until no changes are detected. The rerun
       *   iteration limit is 10 to prevent an infinite loop deadlock.
       *
       *
       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`
       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a
       * change is detected, be prepared for multiple calls to your listener.)
       *
       * After a watcher is registered with the scope, the `listener` fn is called asynchronously
       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the
       * watcher. In rare cases, this is undesirable because the listener is called when the result
       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you
       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the
       * listener was called due to initialization.
       *
       * The example below contains an illustration of using a function as your $watch listener
       *
       *
       * # Example
       * ```js
           // let's assume that scope was dependency injected as the $rootScope
           var scope = $rootScope;
           scope.name = 'misko';
           scope.counter = 0;

           expect(scope.counter).toEqual(0);
           scope.$watch('name', function(newValue, oldValue) {
             scope.counter = scope.counter + 1;
           });
           expect(scope.counter).toEqual(0);

           scope.$digest();
           // the listener is always called during the first $digest loop after it was registered
           expect(scope.counter).toEqual(1);

           scope.$digest();
           // but now it will not be called unless the value changes
           expect(scope.counter).toEqual(1);

           scope.name = 'adam';
           scope.$digest();
           expect(scope.counter).toEqual(2);



           // Using a listener function
           var food;
           scope.foodCounter = 0;
           expect(scope.foodCounter).toEqual(0);
           scope.$watch(
             // This is the listener function
             function() { return food; },
             // This is the change handler
             function(newValue, oldValue) {
               if ( newValue !== oldValue ) {
                 // Only increment the counter if the value changed
                 scope.foodCounter = scope.foodCounter + 1;
               }
             }
           );
           // No digest has been run so the counter will be zero
           expect(scope.foodCounter).toEqual(0);

           // Run the digest but since food has not changed count will still be zero
           scope.$digest();
           expect(scope.foodCounter).toEqual(0);

           // Update food and run digest.  Now the counter will increment
           food = 'cheeseburger';
           scope.$digest();
           expect(scope.foodCounter).toEqual(1);

       * ```
       *
       *
       *
       * @param {(function()|string)} watchExpression Expression that is evaluated on each
       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers
       *    a call to the `listener`.
       *
       *    - `string`: Evaluated as {@link guide/expression expression}
       *    - `function(scope)`: called with current `scope` as a parameter.
       * @param {(function()|string)=} listener Callback called whenever the return value of
       *   the `watchExpression` changes.
       *
       *    - `string`: Evaluated as {@link guide/expression expression}
       *    - `function(newValue, oldValue, scope)`: called with current and previous values as
       *      parameters.
       *
       * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of
       *     comparing for reference equality.
       * @returns {function()} Returns a deregistration function for this listener.
       */
      $watch: function(watchExp, listener, objectEquality) {
        var scope = this,
            get = compileToFn(watchExp, 'watch'),
            array = scope.$$watchers,
            watcher = {
              fn: listener,
              last: initWatchVal,
              get: get,
              exp: watchExp,
              eq: !!objectEquality
            };

        lastDirtyWatch = null;

        // in the case user pass string, we need to compile it, do we really need this ?
        if (!isFunction(listener)) {
          var listenFn = compileToFn(listener || noop, 'listener');
          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};
        }

        if (typeof watchExp == 'string' && get.constant) {
          var originalFn = watcher.fn;
          watcher.fn = function(newVal, oldVal, scope) {
            originalFn.call(this, newVal, oldVal, scope);
            arrayRemove(array, watcher);
          };
        }

        if (!array) {
          array = scope.$$watchers = [];
        }
        // we use unshift since we use a while loop in $digest for speed.
        // the while loop reads in reverse order.
        array.unshift(watcher);

        return function deregisterWatch() {
          arrayRemove(array, watcher);
          lastDirtyWatch = null;
        };
      },


      /**
       * @ngdoc method
       * @name $rootScope.Scope#$watchCollection
       * @kind function
       *
       * @description
       * Shallow watches the properties of an object and fires whenever any of the properties change
       * (for arrays, this implies watching the array items; for object maps, this implies watching
       * the properties). If a change is detected, the `listener` callback is fired.
       *
       * - The `obj` collection is observed via standard $watch operation and is examined on every
       *   call to $digest() to see if any items have been added, removed, or moved.
       * - The `listener` is called whenever anything within the `obj` has changed. Examples include
       *   adding, removing, and moving items belonging to an object or array.
       *
       *
       * # Example
       * ```js
          $scope.names = ['igor', 'matias', 'misko', 'james'];
          $scope.dataCount = 4;

          $scope.$watchCollection('names', function(newNames, oldNames) {
            $scope.dataCount = newNames.length;
          });

          expect($scope.dataCount).toEqual(4);
          $scope.$digest();

          //still at 4 ... no changes
          expect($scope.dataCount).toEqual(4);

          $scope.names.pop();
          $scope.$digest();

          //now there's been a change
          expect($scope.dataCount).toEqual(3);
       * ```
       *
       *
       * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The
       *    expression value should evaluate to an object or an array which is observed on each
       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the
       *    collection will trigger a call to the `listener`.
       *
       * @param {function(newCollection, oldCollection, scope)} listener a callback function called
       *    when a change is detected.
       *    - The `newCollection` object is the newly modified data obtained from the `obj` expression
       *    - The `oldCollection` object is a copy of the former collection data.
       *      Due to performance considerations, the`oldCollection` value is computed only if the
       *      `listener` function declares two or more arguments.
       *    - The `scope` argument refers to the current scope.
       *
       * @returns {function()} Returns a de-registration function for this listener. When the
       *    de-registration function is executed, the internal watch operation is terminated.
       */
      $watchCollection: function(obj, listener) {
        var self = this;
        // the current value, updated on each dirty-check run
        var newValue;
        // a shallow copy of the newValue from the last dirty-check run,
        // updated to match newValue during dirty-check run
        var oldValue;
        // a shallow copy of the newValue from when the last change happened
        var veryOldValue;
        // only track veryOldValue if the listener is asking for it
        var trackVeryOldValue = (listener.length > 1);
        var changeDetected = 0;
        var objGetter = $parse(obj);
        var internalArray = [];
        var internalObject = {};
        var initRun = true;
        var oldLength = 0;

        function $watchCollectionWatch() {
          newValue = objGetter(self);
          var newLength, key, bothNaN;

          if (!isObject(newValue)) { // if primitive
            if (oldValue !== newValue) {
              oldValue = newValue;
              changeDetected++;
            }
          } else if (isArrayLike(newValue)) {
            if (oldValue !== internalArray) {
              // we are transitioning from something which was not an array into array.
              oldValue = internalArray;
              oldLength = oldValue.length = 0;
              changeDetected++;
            }

            newLength = newValue.length;

            if (oldLength !== newLength) {
              // if lengths do not match we need to trigger change notification
              changeDetected++;
              oldValue.length = oldLength = newLength;
            }
            // copy the items to oldValue and look for changes.
            for (var i = 0; i < newLength; i++) {
              bothNaN = (oldValue[i] !== oldValue[i]) &&
                  (newValue[i] !== newValue[i]);
              if (!bothNaN && (oldValue[i] !== newValue[i])) {
                changeDetected++;
                oldValue[i] = newValue[i];
              }
            }
          } else {
            if (oldValue !== internalObject) {
              // we are transitioning from something which was not an object into object.
              oldValue = internalObject = {};
              oldLength = 0;
              changeDetected++;
            }
            // copy the items to oldValue and look for changes.
            newLength = 0;
            for (key in newValue) {
              if (newValue.hasOwnProperty(key)) {
                newLength++;
                if (oldValue.hasOwnProperty(key)) {
                  bothNaN = (oldValue[key] !== oldValue[key]) &&
                      (newValue[key] !== newValue[key]);
                  if (!bothNaN && (oldValue[key] !== newValue[key])) {
                    changeDetected++;
                    oldValue[key] = newValue[key];
                  }
                } else {
                  oldLength++;
                  oldValue[key] = newValue[key];
                  changeDetected++;
                }
              }
            }
            if (oldLength > newLength) {
              // we used to have more keys, need to find them and destroy them.
              changeDetected++;
              for(key in oldValue) {
                if (oldValue.hasOwnProperty(key) && !newValue.hasOwnProperty(key)) {
                  oldLength--;
                  delete oldValue[key];
                }
              }
            }
          }
          return changeDetected;
        }

        function $watchCollectionAction() {
          if (initRun) {
            initRun = false;
            listener(newValue, newValue, self);
          } else {
            listener(newValue, veryOldValue, self);
          }

          // make a copy for the next time a collection is changed
          if (trackVeryOldValue) {
            if (!isObject(newValue)) {
              //primitive
              veryOldValue = newValue;
            } else if (isArrayLike(newValue)) {
              veryOldValue = new Array(newValue.length);
              for (var i = 0; i < newValue.length; i++) {
                veryOldValue[i] = newValue[i];
              }
            } else { // if object
              veryOldValue = {};
              for (var key in newValue) {
                if (hasOwnProperty.call(newValue, key)) {
                  veryOldValue[key] = newValue[key];
                }
              }
            }
          }
        }

        return this.$watch($watchCollectionWatch, $watchCollectionAction);
      },

      /**
       * @ngdoc method
       * @name $rootScope.Scope#$digest
       * @kind function
       *
       * @description
       * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and
       * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change
       * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}
       * until no more listeners are firing. This means that it is possible to get into an infinite
       * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of
       * iterations exceeds 10.
       *
       * Usually, you don't call `$digest()` directly in
       * {@link ng.directive:ngController controllers} or in
       * {@link ng.$compileProvider#directive directives}.
       * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within
       * a {@link ng.$compileProvider#directive directives}), which will force a `$digest()`.
       *
       * If you want to be notified whenever `$digest()` is called,
       * you can register a `watchExpression` function with
       * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.
       *
       * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.
       *
       * # Example
       * ```js
           var scope = ...;
           scope.name = 'misko';
           scope.counter = 0;

           expect(scope.counter).toEqual(0);
           scope.$watch('name', function(newValue, oldValue) {
             scope.counter = scope.counter + 1;
           });
           expect(scope.counter).toEqual(0);

           scope.$digest();
           // the listener is always called during the first $digest loop after it was registered
           expect(scope.counter).toEqual(1);

           scope.$digest();
           // but now it will not be called unless the value changes
           expect(scope.counter).toEqual(1);

           scope.name = 'adam';
           scope.$digest();
           expect(scope.counter).toEqual(2);
       * ```
       *
       */
      $digest: function() {
        var watch, value, last,
            watchers,
            asyncQueue = this.$$asyncQueue,
            postDigestQueue = this.$$postDigestQueue,
            length,
            dirty, ttl = TTL,
            next, current, target = this,
            watchLog = [],
            logIdx, logMsg, asyncTask;

        beginPhase('$digest');
        // Check for changes to browser url that happened in sync before the call to $digest
        $browser.$$checkUrlChange();

        lastDirtyWatch = null;

        do { // "while dirty" loop
          dirty = false;
          current = target;

          while(asyncQueue.length) {
            try {
              asyncTask = asyncQueue.shift();
              asyncTask.scope.$eval(asyncTask.expression);
            } catch (e) {
              clearPhase();
              $exceptionHandler(e);
            }
            lastDirtyWatch = null;
          }

          traverseScopesLoop:
          do { // "traverse the scopes" loop
            if ((watchers = current.$$watchers)) {
              // process our watches
              length = watchers.length;
              while (length--) {
                try {
                  watch = watchers[length];
                  // Most common watches are on primitives, in which case we can short
                  // circuit it with === operator, only when === fails do we use .equals
                  if (watch) {
                    if ((value = watch.get(current)) !== (last = watch.last) &&
                        !(watch.eq
                            ? equals(value, last)
                            : (typeof value === 'number' && typeof last === 'number'
                               && isNaN(value) && isNaN(last)))) {
                      dirty = true;
                      lastDirtyWatch = watch;
                      watch.last = watch.eq ? copy(value, null) : value;
                      watch.fn(value, ((last === initWatchVal) ? value : last), current);
                      if (ttl < 5) {
                        logIdx = 4 - ttl;
                        if (!watchLog[logIdx]) watchLog[logIdx] = [];
                        logMsg = (isFunction(watch.exp))
                            ? 'fn: ' + (watch.exp.name || watch.exp.toString())
                            : watch.exp;
                        logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);
                        watchLog[logIdx].push(logMsg);
                      }
                    } else if (watch === lastDirtyWatch) {
                      // If the most recently dirty watcher is now clean, short circuit since the remaining watchers
                      // have already been tested.
                      dirty = false;
                      break traverseScopesLoop;
                    }
                  }
                } catch (e) {
                  clearPhase();
                  $exceptionHandler(e);
                }
              }
            }

            // Insanity Warning: scope depth-first traversal
            // yes, this code is a bit crazy, but it works and we have tests to prove it!
            // this piece should be kept in sync with the traversal in $broadcast
            if (!(next = (current.$$childHead ||
                (current !== target && current.$$nextSibling)))) {
              while(current !== target && !(next = current.$$nextSibling)) {
                current = current.$parent;
              }
            }
          } while ((current = next));

          // `break traverseScopesLoop;` takes us to here

          if((dirty || asyncQueue.length) && !(ttl--)) {
            clearPhase();
            throw $rootScopeMinErr('infdig',
                '{0} $digest() iterations reached. Aborting!\n' +
                'Watchers fired in the last 5 iterations: {1}',
                TTL, toJson(watchLog));
          }

        } while (dirty || asyncQueue.length);

        clearPhase();

        while(postDigestQueue.length) {
          try {
            postDigestQueue.shift()();
          } catch (e) {
            $exceptionHandler(e);
          }
        }
      },


      /**
       * @ngdoc event
       * @name $rootScope.Scope#$destroy
       * @eventType broadcast on scope being destroyed
       *
       * @description
       * Broadcasted when a scope and its children are being destroyed.
       *
       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
       * clean up DOM bindings before an element is removed from the DOM.
       */

      /**
       * @ngdoc method
       * @name $rootScope.Scope#$destroy
       * @kind function
       *
       * @description
       * Removes the current scope (and all of its children) from the parent scope. Removal implies
       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer
       * propagate to the current scope and its children. Removal also implies that the current
       * scope is eligible for garbage collection.
       *
       * The `$destroy()` is usually used by directives such as
       * {@link ng.directive:ngRepeat ngRepeat} for managing the
       * unrolling of the loop.
       *
       * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.
       * Application code can register a `$destroy` event handler that will give it a chance to
       * perform any necessary cleanup.
       *
       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
       * clean up DOM bindings before an element is removed from the DOM.
       */
      $destroy: function() {
        // we can't destroy the root scope or a scope that has been already destroyed
        if (this.$$destroyed) return;
        var parent = this.$parent;

        this.$broadcast('$destroy');
        this.$$destroyed = true;
        if (this === $rootScope) return;

        forEach(this.$$listenerCount, bind(null, decrementListenerCount, this));

        // sever all the references to parent scopes (after this cleanup, the current scope should
        // not be retained by any of our references and should be eligible for garbage collection)
        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;


        // All of the code below is bogus code that works around V8's memory leak via optimized code
        // and inline caches.
        //
        // see:
        // - https://code.google.com/p/v8/issues/detail?id=2073#c26
        // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
        // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451

        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =
            this.$$childTail = this.$root = null;

        // don't reset these to null in case some async task tries to register a listener/watch/task
        this.$$listeners = {};
        this.$$watchers = this.$$asyncQueue = this.$$postDigestQueue = [];

        // prevent NPEs since these methods have references to properties we nulled out
        this.$destroy = this.$digest = this.$apply = noop;
        this.$on = this.$watch = function() { return noop; };
      },

      /**
       * @ngdoc method
       * @name $rootScope.Scope#$eval
       * @kind function
       *
       * @description
       * Executes the `expression` on the current scope and returns the result. Any exceptions in
       * the expression are propagated (uncaught). This is useful when evaluating Angular
       * expressions.
       *
       * # Example
       * ```js
           var scope = ng.$rootScope.Scope();
           scope.a = 1;
           scope.b = 2;

           expect(scope.$eval('a+b')).toEqual(3);
           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
       * ```
       *
       * @param {(string|function())=} expression An angular expression to be executed.
       *
       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.
       *    - `function(scope)`: execute the function with the current `scope` parameter.
       *
       * @param {(object)=} locals Local variables object, useful for overriding values in scope.
       * @returns {*} The result of evaluating the expression.
       */
      $eval: function(expr, locals) {
        return $parse(expr)(this, locals);
      },

      /**
       * @ngdoc method
       * @name $rootScope.Scope#$evalAsync
       * @kind function
       *
       * @description
       * Executes the expression on the current scope at a later point in time.
       *
       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only
       * that:
       *
       *   - it will execute after the function that scheduled the evaluation (preferably before DOM
       *     rendering).
       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after
       *     `expression` execution.
       *
       * Any exceptions from the execution of the expression are forwarded to the
       * {@link ng.$exceptionHandler $exceptionHandler} service.
       *
       * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle
       * will be scheduled. However, it is encouraged to always call code that changes the model
       * from within an `$apply` call. That includes code evaluated via `$evalAsync`.
       *
       * @param {(string|function())=} expression An angular expression to be executed.
       *
       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.
       *    - `function(scope)`: execute the function with the current `scope` parameter.
       *
       */
      $evalAsync: function(expr) {
        // if we are outside of an $digest loop and this is the first time we are scheduling async
        // task also schedule async auto-flush
        if (!$rootScope.$$phase && !$rootScope.$$asyncQueue.length) {
          $browser.defer(function() {
            if ($rootScope.$$asyncQueue.length) {
              $rootScope.$digest();
            }
          });
        }

        this.$$asyncQueue.push({scope: this, expression: expr});
      },

      $$postDigest : function(fn) {
        this.$$postDigestQueue.push(fn);
      },

      /**
       * @ngdoc method
       * @name $rootScope.Scope#$apply
       * @kind function
       *
       * @description
       * `$apply()` is used to execute an expression in angular from outside of the angular
       * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
       * Because we are calling into the angular framework we need to perform proper scope life
       * cycle of {@link ng.$exceptionHandler exception handling},
       * {@link ng.$rootScope.Scope#$digest executing watches}.
       *
       * ## Life cycle
       *
       * # Pseudo-Code of `$apply()`
       * ```js
           function $apply(expr) {
             try {
               return $eval(expr);
             } catch (e) {
               $exceptionHandler(e);
             } finally {
               $root.$digest();
             }
           }
       * ```
       *
       *
       * Scope's `$apply()` method transitions through the following stages:
       *
       * 1. The {@link guide/expression expression} is executed using the
       *    {@link ng.$rootScope.Scope#$eval $eval()} method.
       * 2. Any exceptions from the execution of the expression are forwarded to the
       *    {@link ng.$exceptionHandler $exceptionHandler} service.
       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the
       *    expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.
       *
       *
       * @param {(string|function())=} exp An angular expression to be executed.
       *
       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.
       *    - `function(scope)`: execute the function with current `scope` parameter.
       *
       * @returns {*} The result of evaluating the expression.
       */
      $apply: function(expr) {
        try {
          beginPhase('$apply');
          return this.$eval(expr);
        } catch (e) {
          $exceptionHandler(e);
        } finally {
          clearPhase();
          try {
            $rootScope.$digest();
          } catch (e) {
            $exceptionHandler(e);
            throw e;
          }
        }
      },

      /**
       * @ngdoc method
       * @name $rootScope.Scope#$on
       * @kind function
       *
       * @description
       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for
       * discussion of event life cycle.
       *
       * The event listener function format is: `function(event, args...)`. The `event` object
       * passed into the listener has the following attributes:
       *
       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or
       *     `$broadcast`-ed.
       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.
       *   - `name` - `{string}`: name of the event.
       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel
       *     further event propagation (available only for events that were `$emit`-ed).
       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag
       *     to true.
       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
       *
       * @param {string} name Event name to listen on.
       * @param {function(event, ...args)} listener Function to call when the event is emitted.
       * @returns {function()} Returns a deregistration function for this listener.
       */
      $on: function(name, listener) {
        var namedListeners = this.$$listeners[name];
        if (!namedListeners) {
          this.$$listeners[name] = namedListeners = [];
        }
        namedListeners.push(listener);

        var current = this;
        do {
          if (!current.$$listenerCount[name]) {
            current.$$listenerCount[name] = 0;
          }
          current.$$listenerCount[name]++;
        } while ((current = current.$parent));

        var self = this;
        return function() {
          var indexOfListener = indexOf(namedListeners, listener);
          if (indexOfListener !== -1) {
            namedListeners[indexOfListener] = null;
            decrementListenerCount(self, 1, name);
          }
        };
      },


      /**
       * @ngdoc method
       * @name $rootScope.Scope#$emit
       * @kind function
       *
       * @description
       * Dispatches an event `name` upwards through the scope hierarchy notifying the
       * registered {@link ng.$rootScope.Scope#$on} listeners.
       *
       * The event life cycle starts at the scope on which `$emit` was called. All
       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
       * notified. Afterwards, the event traverses upwards toward the root scope and calls all
       * registered listeners along the way. The event will stop propagating if one of the listeners
       * cancels it.
       *
       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
       *
       * @param {string} name Event name to emit.
       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
       * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).
       */
      $emit: function(name, args) {
        var empty = [],
            namedListeners,
            scope = this,
            stopPropagation = false,
            event = {
              name: name,
              targetScope: scope,
              stopPropagation: function() {stopPropagation = true;},
              preventDefault: function() {
                event.defaultPrevented = true;
              },
              defaultPrevented: false
            },
            listenerArgs = concat([event], arguments, 1),
            i, length;

        do {
          namedListeners = scope.$$listeners[name] || empty;
          event.currentScope = scope;
          for (i=0, length=namedListeners.length; i<length; i++) {

            // if listeners were deregistered, defragment the array
            if (!namedListeners[i]) {
              namedListeners.splice(i, 1);
              i--;
              length--;
              continue;
            }
            try {
              //allow all listeners attached to the current scope to run
              namedListeners[i].apply(null, listenerArgs);
            } catch (e) {
              $exceptionHandler(e);
            }
          }
          //if any listener on the current scope stops propagation, prevent bubbling
          if (stopPropagation) return event;
          //traverse upwards
          scope = scope.$parent;
        } while (scope);

        return event;
      },


      /**
       * @ngdoc method
       * @name $rootScope.Scope#$broadcast
       * @kind function
       *
       * @description
       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the
       * registered {@link ng.$rootScope.Scope#$on} listeners.
       *
       * The event life cycle starts at the scope on which `$broadcast` was called. All
       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
       * notified. Afterwards, the event propagates to all direct and indirect scopes of the current
       * scope and calls all registered listeners along the way. The event cannot be canceled.
       *
       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
       *
       * @param {string} name Event name to broadcast.
       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
       */
      $broadcast: function(name, args) {
        var target = this,
            current = target,
            next = target,
            event = {
              name: name,
              targetScope: target,
              preventDefault: function() {
                event.defaultPrevented = true;
              },
              defaultPrevented: false
            },
            listenerArgs = concat([event], arguments, 1),
            listeners, i, length;

        //down while you can, then up and next sibling or up and next sibling until back at root
        while ((current = next)) {
          event.currentScope = current;
          listeners = current.$$listeners[name] || [];
          for (i=0, length = listeners.length; i<length; i++) {
            // if listeners were deregistered, defragment the array
            if (!listeners[i]) {
              listeners.splice(i, 1);
              i--;
              length--;
              continue;
            }

            try {
              listeners[i].apply(null, listenerArgs);
            } catch(e) {
              $exceptionHandler(e);
            }
          }

          // Insanity Warning: scope depth-first traversal
          // yes, this code is a bit crazy, but it works and we have tests to prove it!
          // this piece should be kept in sync with the traversal in $digest
          // (though it differs due to having the extra check for $$listenerCount)
          if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||
              (current !== target && current.$$nextSibling)))) {
            while(current !== target && !(next = current.$$nextSibling)) {
              current = current.$parent;
            }
          }
        }

        return event;
      }
    };

    var $rootScope = new Scope();

    return $rootScope;


    function beginPhase(phase) {
      if ($rootScope.$$phase) {
        throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);
      }

      $rootScope.$$phase = phase;
    }

    function clearPhase() {
      $rootScope.$$phase = null;
    }

    function compileToFn(exp, name) {
      var fn = $parse(exp);
      assertArgFn(fn, name);
      return fn;
    }

    function decrementListenerCount(current, count, name) {
      do {
        current.$$listenerCount[name] -= count;

        if (current.$$listenerCount[name] === 0) {
          delete current.$$listenerCount[name];
        }
      } while ((current = current.$parent));
    }

    /**
     * function used as an initial value for watchers.
     * because it's unique we can easily tell it apart from other values
     */
    function initWatchVal() {}
  }];
}

/**
 * @description
 * Private service to sanitize uris for links and images. Used by $compile and $sanitize.
 */
function $$SanitizeUriProvider() {
  var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
    imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file):|data:image\/)/;

  /**
   * @description
   * Retrieves or overrides the default regular expression that is used for whitelisting of safe
   * urls during a[href] sanitization.
   *
   * The sanitization is a security measure aimed at prevent XSS attacks via html links.
   *
   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
   * regular expression. If a match is found, the original url is written into the dom. Otherwise,
   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
   *
   * @param {RegExp=} regexp New regexp to whitelist urls with.
   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
   *    chaining otherwise.
   */
  this.aHrefSanitizationWhitelist = function(regexp) {
    if (isDefined(regexp)) {
      aHrefSanitizationWhitelist = regexp;
      return this;
    }
    return aHrefSanitizationWhitelist;
  };


  /**
   * @description
   * Retrieves or overrides the default regular expression that is used for whitelisting of safe
   * urls during img[src] sanitization.
   *
   * The sanitization is a security measure aimed at prevent XSS attacks via html links.
   *
   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
   * regular expression. If a match is found, the original url is written into the dom. Otherwise,
   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
   *
   * @param {RegExp=} regexp New regexp to whitelist urls with.
   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
   *    chaining otherwise.
   */
  this.imgSrcSanitizationWhitelist = function(regexp) {
    if (isDefined(regexp)) {
      imgSrcSanitizationWhitelist = regexp;
      return this;
    }
    return imgSrcSanitizationWhitelist;
  };

  this.$get = function() {
    return function sanitizeUri(uri, isImage) {
      var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
      var normalizedVal;
      // NOTE: urlResolve() doesn't support IE < 8 so we don't sanitize for that case.
      if (!msie || msie >= 8 ) {
        normalizedVal = urlResolve(uri).href;
        if (normalizedVal !== '' && !normalizedVal.match(regex)) {
          return 'unsafe:'+normalizedVal;
        }
      }
      return uri;
    };
  };
}

var $sceMinErr = minErr('$sce');

var SCE_CONTEXTS = {
  HTML: 'html',
  CSS: 'css',
  URL: 'url',
  // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a
  // url.  (e.g. ng-include, script src, templateUrl)
  RESOURCE_URL: 'resourceUrl',
  JS: 'js'
};

// Helper functions follow.

// Copied from:
// http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962
// Prereq: s is a string.
function escapeForRegexp(s) {
  return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
           replace(/\x08/g, '\\x08');
}


function adjustMatcher(matcher) {
  if (matcher === 'self') {
    return matcher;
  } else if (isString(matcher)) {
    // Strings match exactly except for 2 wildcards - '*' and '**'.
    // '*' matches any character except those from the set ':/.?&'.
    // '**' matches any character (like .* in a RegExp).
    // More than 2 *'s raises an error as it's ill defined.
    if (matcher.indexOf('***') > -1) {
      throw $sceMinErr('iwcard',
          'Illegal sequence *** in string matcher.  String: {0}', matcher);
    }
    matcher = escapeForRegexp(matcher).
                  replace('\\*\\*', '.*').
                  replace('\\*', '[^:/.?&;]*');
    return new RegExp('^' + matcher + '$');
  } else if (isRegExp(matcher)) {
    // The only other type of matcher allowed is a Regexp.
    // Match entire URL / disallow partial matches.
    // Flags are reset (i.e. no global, ignoreCase or multiline)
    return new RegExp('^' + matcher.source + '$');
  } else {
    throw $sceMinErr('imatcher',
        'Matchers may only be "self", string patterns or RegExp objects');
  }
}


function adjustMatchers(matchers) {
  var adjustedMatchers = [];
  if (isDefined(matchers)) {
    forEach(matchers, function(matcher) {
      adjustedMatchers.push(adjustMatcher(matcher));
    });
  }
  return adjustedMatchers;
}


/**
 * @ngdoc service
 * @name $sceDelegate
 * @kind function
 *
 * @description
 *
 * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
 * Contextual Escaping (SCE)} services to AngularJS.
 *
 * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of
 * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS.  This is
 * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to
 * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things
 * work because `$sce` delegates to `$sceDelegate` for these operations.
 *
 * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.
 *
 * The default instance of `$sceDelegate` should work out of the box with little pain.  While you
 * can override it completely to change the behavior of `$sce`, the common case would
 * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting
 * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as
 * templates.  Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist
 * $sceDelegateProvider.resourceUrlWhitelist} and {@link
 * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
 */

/**
 * @ngdoc provider
 * @name $sceDelegateProvider
 * @description
 *
 * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
 * $sceDelegate} service.  This allows one to get/set the whitelists and blacklists used to ensure
 * that the URLs used for sourcing Angular templates are safe.  Refer {@link
 * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and
 * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
 *
 * For the general details about this service in Angular, read the main page for {@link ng.$sce
 * Strict Contextual Escaping (SCE)}.
 *
 * **Example**:  Consider the following case. <a name="example"></a>
 *
 * - your app is hosted at url `http://myapp.example.com/`
 * - but some of your templates are hosted on other domains you control such as
 *   `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.
 * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.
 *
 * Here is what a secure configuration for this scenario might look like:
 *
 * ```
 *  angular.module('myApp', []).config(function($sceDelegateProvider) {
 *    $sceDelegateProvider.resourceUrlWhitelist([
 *      // Allow same origin resource loads.
 *      'self',
 *      // Allow loading from our assets domain.  Notice the difference between * and **.
 *      'http://srv*.assets.example.com/**'
 *    ]);
 *
 *    // The blacklist overrides the whitelist so the open redirect here is blocked.
 *    $sceDelegateProvider.resourceUrlBlacklist([
 *      'http://myapp.example.com/clickThru**'
 *    ]);
 *  });
 * ```
 */

function $SceDelegateProvider() {
  this.SCE_CONTEXTS = SCE_CONTEXTS;

  // Resource URLs can also be trusted by policy.
  var resourceUrlWhitelist = ['self'],
      resourceUrlBlacklist = [];

  /**
   * @ngdoc method
   * @name $sceDelegateProvider#resourceUrlWhitelist
   * @kind function
   *
   * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
   *     provided.  This must be an array or null.  A snapshot of this array is used so further
   *     changes to the array are ignored.
   *
   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
   *     allowed in this array.
   *
   *     Note: **an empty whitelist array will block all URLs**!
   *
   * @return {Array} the currently set whitelist array.
   *
   * The **default value** when no whitelist has been explicitly set is `['self']` allowing only
   * same origin resource requests.
   *
   * @description
   * Sets/Gets the whitelist of trusted resource URLs.
   */
  this.resourceUrlWhitelist = function (value) {
    if (arguments.length) {
      resourceUrlWhitelist = adjustMatchers(value);
    }
    return resourceUrlWhitelist;
  };

  /**
   * @ngdoc method
   * @name $sceDelegateProvider#resourceUrlBlacklist
   * @kind function
   *
   * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
   *     provided.  This must be an array or null.  A snapshot of this array is used so further
   *     changes to the array are ignored.
   *
   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
   *     allowed in this array.
   *
   *     The typical usage for the blacklist is to **block
   *     [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
   *     these would otherwise be trusted but actually return content from the redirected domain.
   *
   *     Finally, **the blacklist overrides the whitelist** and has the final say.
   *
   * @return {Array} the currently set blacklist array.
   *
   * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there
   * is no blacklist.)
   *
   * @description
   * Sets/Gets the blacklist of trusted resource URLs.
   */

  this.resourceUrlBlacklist = function (value) {
    if (arguments.length) {
      resourceUrlBlacklist = adjustMatchers(value);
    }
    return resourceUrlBlacklist;
  };

  this.$get = ['$injector', function($injector) {

    var htmlSanitizer = function htmlSanitizer(html) {
      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
    };

    if ($injector.has('$sanitize')) {
      htmlSanitizer = $injector.get('$sanitize');
    }


    function matchUrl(matcher, parsedUrl) {
      if (matcher === 'self') {
        return urlIsSameOrigin(parsedUrl);
      } else {
        // definitely a regex.  See adjustMatchers()
        return !!matcher.exec(parsedUrl.href);
      }
    }

    function isResourceUrlAllowedByPolicy(url) {
      var parsedUrl = urlResolve(url.toString());
      var i, n, allowed = false;
      // Ensure that at least one item from the whitelist allows this url.
      for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {
        if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {
          allowed = true;
          break;
        }
      }
      if (allowed) {
        // Ensure that no item from the blacklist blocked this url.
        for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {
          if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {
            allowed = false;
            break;
          }
        }
      }
      return allowed;
    }

    function generateHolderType(Base) {
      var holderType = function TrustedValueHolderType(trustedValue) {
        this.$$unwrapTrustedValue = function() {
          return trustedValue;
        };
      };
      if (Base) {
        holderType.prototype = new Base();
      }
      holderType.prototype.valueOf = function sceValueOf() {
        return this.$$unwrapTrustedValue();
      };
      holderType.prototype.toString = function sceToString() {
        return this.$$unwrapTrustedValue().toString();
      };
      return holderType;
    }

    var trustedValueHolderBase = generateHolderType(),
        byType = {};

    byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);
    byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);
    byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);
    byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);
    byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);

    /**
     * @ngdoc method
     * @name $sceDelegate#trustAs
     *
     * @description
     * Returns an object that is trusted by angular for use in specified strict
     * contextual escaping contexts (such as ng-bind-html, ng-include, any src
     * attribute interpolation, any dom event binding attribute interpolation
     * such as for onclick,  etc.) that uses the provided value.
     * See {@link ng.$sce $sce} for enabling strict contextual escaping.
     *
     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,
     *   resourceUrl, html, js and css.
     * @param {*} value The value that that should be considered trusted/safe.
     * @returns {*} A value that can be used to stand in for the provided `value` in places
     * where Angular expects a $sce.trustAs() return value.
     */
    function trustAs(type, trustedValue) {
      var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
      if (!Constructor) {
        throw $sceMinErr('icontext',
            'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
            type, trustedValue);
      }
      if (trustedValue === null || trustedValue === undefined || trustedValue === '') {
        return trustedValue;
      }
      // All the current contexts in SCE_CONTEXTS happen to be strings.  In order to avoid trusting
      // mutable objects, we ensure here that the value passed in is actually a string.
      if (typeof trustedValue !== 'string') {
        throw $sceMinErr('itype',
            'Attempted to trust a non-string value in a content requiring a string: Context: {0}',
            type);
      }
      return new Constructor(trustedValue);
    }

    /**
     * @ngdoc method
     * @name $sceDelegate#valueOf
     *
     * @description
     * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs
     * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link
     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.
     *
     * If the passed parameter is not a value that had been returned by {@link
     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.
     *
     * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}
     *      call or anything else.
     * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs
     *     `$sceDelegate.trustAs`} if `value` is the result of such a call.  Otherwise, returns
     *     `value` unchanged.
     */
    function valueOf(maybeTrusted) {
      if (maybeTrusted instanceof trustedValueHolderBase) {
        return maybeTrusted.$$unwrapTrustedValue();
      } else {
        return maybeTrusted;
      }
    }

    /**
     * @ngdoc method
     * @name $sceDelegate#getTrusted
     *
     * @description
     * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and
     * returns the originally supplied value if the queried context type is a supertype of the
     * created type.  If this condition isn't satisfied, throws an exception.
     *
     * @param {string} type The kind of context in which this value is to be used.
     * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs
     *     `$sceDelegate.trustAs`} call.
     * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs
     *     `$sceDelegate.trustAs`} if valid in this context.  Otherwise, throws an exception.
     */
    function getTrusted(type, maybeTrusted) {
      if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {
        return maybeTrusted;
      }
      var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
      if (constructor && maybeTrusted instanceof constructor) {
        return maybeTrusted.$$unwrapTrustedValue();
      }
      // If we get here, then we may only take one of two actions.
      // 1. sanitize the value for the requested type, or
      // 2. throw an exception.
      if (type === SCE_CONTEXTS.RESOURCE_URL) {
        if (isResourceUrlAllowedByPolicy(maybeTrusted)) {
          return maybeTrusted;
        } else {
          throw $sceMinErr('insecurl',
              'Blocked loading resource from url not allowed by $sceDelegate policy.  URL: {0}',
              maybeTrusted.toString());
        }
      } else if (type === SCE_CONTEXTS.HTML) {
        return htmlSanitizer(maybeTrusted);
      }
      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
    }

    return { trustAs: trustAs,
             getTrusted: getTrusted,
             valueOf: valueOf };
  }];
}


/**
 * @ngdoc provider
 * @name $sceProvider
 * @description
 *
 * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.
 * -   enable/disable Strict Contextual Escaping (SCE) in a module
 * -   override the default implementation with a custom delegate
 *
 * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.
 */

/* jshint maxlen: false*/

/**
 * @ngdoc service
 * @name $sce
 * @kind function
 *
 * @description
 *
 * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.
 *
 * # Strict Contextual Escaping
 *
 * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain
 * contexts to result in a value that is marked as safe to use for that context.  One example of
 * such a context is binding arbitrary html controlled by the user via `ng-bind-html`.  We refer
 * to these contexts as privileged or SCE contexts.
 *
 * As of version 1.2, Angular ships with SCE enabled by default.
 *
 * Note:  When enabled (the default), IE8 in quirks mode is not supported.  In this mode, IE8 allows
 * one to execute arbitrary javascript by the use of the expression() syntax.  Refer
 * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.
 * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
 * to the top of your HTML document.
 *
 * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for
 * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
 *
 * Here's an example of a binding in a privileged context:
 *
 * ```
 * <input ng-model="userHtml">
 * <div ng-bind-html="userHtml"></div>
 * ```
 *
 * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user.  With SCE
 * disabled, this application allows the user to render arbitrary HTML into the DIV.
 * In a more realistic example, one may be rendering user comments, blog articles, etc. via
 * bindings.  (HTML is just one example of a context where rendering user controlled input creates
 * security vulnerabilities.)
 *
 * For the case of HTML, you might use a library, either on the client side, or on the server side,
 * to sanitize unsafe HTML before binding to the value and rendering it in the document.
 *
 * How would you ensure that every place that used these types of bindings was bound to a value that
 * was sanitized by your library (or returned as safe for rendering by your server?)  How can you
 * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some
 * properties/fields and forgot to update the binding to the sanitized value?
 *
 * To be secure by default, you want to ensure that any such bindings are disallowed unless you can
 * determine that something explicitly says it's safe to use a value for binding in that
 * context.  You can then audit your code (a simple grep would do) to ensure that this is only done
 * for those values that you can easily tell are safe - because they were received from your server,
 * sanitized by your library, etc.  You can organize your codebase to help with this - perhaps
 * allowing only the files in a specific directory to do this.  Ensuring that the internal API
 * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.
 *
 * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}
 * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to
 * obtain values that will be accepted by SCE / privileged contexts.
 *
 *
 * ## How does it work?
 *
 * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted
 * $sce.getTrusted(context, value)} rather than to the value directly.  Directives use {@link
 * ng.$sce#parse $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the
 * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.
 *
 * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link
 * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}.  Here's the actual code (slightly
 * simplified):
 *
 * ```
 * var ngBindHtmlDirective = ['$sce', function($sce) {
 *   return function(scope, element, attr) {
 *     scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
 *       element.html(value || '');
 *     });
 *   };
 * }];
 * ```
 *
 * ## Impact on loading templates
 *
 * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as
 * `templateUrl`'s specified by {@link guide/directive directives}.
 *
 * By default, Angular only loads templates from the same domain and protocol as the application
 * document.  This is done by calling {@link ng.$sce#getTrustedResourceUrl
 * $sce.getTrustedResourceUrl} on the template URL.  To load templates from other domains and/or
 * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist
 * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.
 *
 * *Please note*:
 * The browser's
 * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
 * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
 * policy apply in addition to this and may further restrict whether the template is successfully
 * loaded.  This means that without the right CORS policy, loading templates from a different domain
 * won't work on all browsers.  Also, loading templates from `file://` URL does not work on some
 * browsers.
 *
 * ## This feels like too much overhead for the developer?
 *
 * It's important to remember that SCE only applies to interpolation expressions.
 *
 * If your expressions are constant literals, they're automatically trusted and you don't need to
 * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.
 * `<div ng-bind-html="'<b>implicitly trusted</b>'"></div>`) just works.
 *
 * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them
 * through {@link ng.$sce#getTrusted $sce.getTrusted}.  SCE doesn't play a role here.
 *
 * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load
 * templates in `ng-include` from your application's domain without having to even know about SCE.
 * It blocks loading templates from other domains or loading templates over http from an https
 * served document.  You can change these by setting your own custom {@link
 * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link
 * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.
 *
 * This significantly reduces the overhead.  It is far easier to pay the small overhead and have an
 * application that's secure and can be audited to verify that with much more ease than bolting
 * security onto an application later.
 *
 * <a name="contexts"></a>
 * ## What trusted context types are supported?
 *
 * | Context             | Notes          |
 * |---------------------|----------------|
 * | `$sce.HTML`         | For HTML that's safe to source into the application.  The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |
 * | `$sce.CSS`          | For CSS that's safe to source into the application.  Currently unused.  Feel free to use it in your own directives. |
 * | `$sce.URL`          | For URLs that are safe to follow as links.  Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |
 * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application.  Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.)  <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
 * | `$sce.JS`           | For JavaScript that is safe to execute in your application's context.  Currently unused.  Feel free to use it in your own directives. |
 *
 * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a>
 *
 *  Each element in these arrays must be one of the following:
 *
 *  - **'self'**
 *    - The special **string**, `'self'`, can be used to match against all URLs of the **same
 *      domain** as the application document using the **same protocol**.
 *  - **String** (except the special value `'self'`)
 *    - The string is matched against the full *normalized / absolute URL* of the resource
 *      being tested (substring matches are not good enough.)
 *    - There are exactly **two wildcard sequences** - `*` and `**`.  All other characters
 *      match themselves.
 *    - `*`: matches zero or more occurrences of any character other than one of the following 6
 *      characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'.  It's a useful wildcard for use
 *      in a whitelist.
 *    - `**`: matches zero or more occurrences of *any* character.  As such, it's not
 *      not appropriate to use in for a scheme, domain, etc. as it would match too much.  (e.g.
 *      http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
 *      not have been the intention.)  Its usage at the very end of the path is ok.  (e.g.
 *      http://foo.example.com/templates/**).
 *  - **RegExp** (*see caveat below*)
 *    - *Caveat*:  While regular expressions are powerful and offer great flexibility,  their syntax
 *      (and all the inevitable escaping) makes them *harder to maintain*.  It's easy to
 *      accidentally introduce a bug when one updates a complex expression (imho, all regexes should
 *      have good test coverage.).  For instance, the use of `.` in the regex is correct only in a
 *      small number of cases.  A `.` character in the regex used when matching the scheme or a
 *      subdomain could be matched against a `:` or literal `.` that was likely not intended.   It
 *      is highly recommended to use the string patterns and only fall back to regular expressions
 *      if they as a last resort.
 *    - The regular expression must be an instance of RegExp (i.e. not a string.)  It is
 *      matched against the **entire** *normalized / absolute URL* of the resource being tested
 *      (even when the RegExp did not have the `^` and `$` codes.)  In addition, any flags
 *      present on the RegExp (such as multiline, global, ignoreCase) are ignored.
 *    - If you are generating your JavaScript from some other templating engine (not
 *      recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),
 *      remember to escape your regular expression (and be aware that you might need more than
 *      one level of escaping depending on your templating engine and the way you interpolated
 *      the value.)  Do make use of your platform's escaping mechanism as it might be good
 *      enough before coding your own.  e.g. Ruby has
 *      [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)
 *      and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).
 *      Javascript lacks a similar built in function for escaping.  Take a look at Google
 *      Closure library's [goog.string.regExpEscape(s)](
 *      http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).
 *
 * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.
 *
 * ## Show me an example using SCE.
 *
 * <example module="mySceApp" deps="angular-sanitize.js">
 * <file name="index.html">
 *   <div ng-controller="myAppController as myCtrl">
 *     <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
 *     <b>User comments</b><br>
 *     By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
 *     $sanitize is available.  If $sanitize isn't available, this results in an error instead of an
 *     exploit.
 *     <div class="well">
 *       <div ng-repeat="userComment in myCtrl.userComments">
 *         <b>{{userComment.name}}</b>:
 *         <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
 *         <br>
 *       </div>
 *     </div>
 *   </div>
 * </file>
 *
 * <file name="script.js">
 *   var mySceApp = angular.module('mySceApp', ['ngSanitize']);
 *
 *   mySceApp.controller("myAppController", function myAppController($http, $templateCache, $sce) {
 *     var self = this;
 *     $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
 *       self.userComments = userComments;
 *     });
 *     self.explicitlyTrustedHtml = $sce.trustAsHtml(
 *         '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
 *         'sanitization.&quot;">Hover over this text.</span>');
 *   });
 * </file>
 *
 * <file name="test_data.json">
 * [
 *   { "name": "Alice",
 *     "htmlComment":
 *         "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
 *   },
 *   { "name": "Bob",
 *     "htmlComment": "<i>Yes!</i>  Am I the only other one?"
 *   }
 * ]
 * </file>
 *
 * <file name="protractor.js" type="protractor">
 *   describe('SCE doc demo', function() {
 *     it('should sanitize untrusted values', function() {
 *       expect(element.all(by.css('.htmlComment')).first().getInnerHtml())
 *           .toBe('<span>Is <i>anyone</i> reading this?</span>');
 *     });
 *
 *     it('should NOT sanitize explicitly trusted values', function() {
 *       expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
 *           '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
 *           'sanitization.&quot;">Hover over this text.</span>');
 *     });
 *   });
 * </file>
 * </example>
 *
 *
 *
 * ## Can I disable SCE completely?
 *
 * Yes, you can.  However, this is strongly discouraged.  SCE gives you a lot of security benefits
 * for little coding overhead.  It will be much harder to take an SCE disabled application and
 * either secure it on your own or enable SCE at a later stage.  It might make sense to disable SCE
 * for cases where you have a lot of existing code that was written before SCE was introduced and
 * you're migrating them a module at a time.
 *
 * That said, here's how you can completely disable SCE:
 *
 * ```
 * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
 *   // Completely disable SCE.  For demonstration purposes only!
 *   // Do not use in new projects.
 *   $sceProvider.enabled(false);
 * });
 * ```
 *
 */
/* jshint maxlen: 100 */

function $SceProvider() {
  var enabled = true;

  /**
   * @ngdoc method
   * @name $sceProvider#enabled
   * @kind function
   *
   * @param {boolean=} value If provided, then enables/disables SCE.
   * @return {boolean} true if SCE is enabled, false otherwise.
   *
   * @description
   * Enables/disables SCE and returns the current value.
   */
  this.enabled = function (value) {
    if (arguments.length) {
      enabled = !!value;
    }
    return enabled;
  };


  /* Design notes on the default implementation for SCE.
   *
   * The API contract for the SCE delegate
   * -------------------------------------
   * The SCE delegate object must provide the following 3 methods:
   *
   * - trustAs(contextEnum, value)
   *     This method is used to tell the SCE service that the provided value is OK to use in the
   *     contexts specified by contextEnum.  It must return an object that will be accepted by
   *     getTrusted() for a compatible contextEnum and return this value.
   *
   * - valueOf(value)
   *     For values that were not produced by trustAs(), return them as is.  For values that were
   *     produced by trustAs(), return the corresponding input value to trustAs.  Basically, if
   *     trustAs is wrapping the given values into some type, this operation unwraps it when given
   *     such a value.
   *
   * - getTrusted(contextEnum, value)
   *     This function should return the a value that is safe to use in the context specified by
   *     contextEnum or throw and exception otherwise.
   *
   * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be
   * opaque or wrapped in some holder object.  That happens to be an implementation detail.  For
   * instance, an implementation could maintain a registry of all trusted objects by context.  In
   * such a case, trustAs() would return the same object that was passed in.  getTrusted() would
   * return the same object passed in if it was found in the registry under a compatible context or
   * throw an exception otherwise.  An implementation might only wrap values some of the time based
   * on some criteria.  getTrusted() might return a value and not throw an exception for special
   * constants or objects even if not wrapped.  All such implementations fulfill this contract.
   *
   *
   * A note on the inheritance model for SCE contexts
   * ------------------------------------------------
   * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types.  This
   * is purely an implementation details.
   *
   * The contract is simply this:
   *
   *     getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)
   *     will also succeed.
   *
   * Inheritance happens to capture this in a natural way.  In some future, we
   * may not use inheritance anymore.  That is OK because no code outside of
   * sce.js and sceSpecs.js would need to be aware of this detail.
   */

  this.$get = ['$parse', '$sniffer', '$sceDelegate', function(
                $parse,   $sniffer,   $sceDelegate) {
    // Prereq: Ensure that we're not running in IE8 quirks mode.  In that mode, IE allows
    // the "expression(javascript expression)" syntax which is insecure.
    if (enabled && $sniffer.msie && $sniffer.msieDocumentMode < 8) {
      throw $sceMinErr('iequirks',
        'Strict Contextual Escaping does not support Internet Explorer version < 9 in quirks ' +
        'mode.  You can fix this by adding the text <!doctype html> to the top of your HTML ' +
        'document.  See http://docs.angularjs.org/api/ng.$sce for more information.');
    }

    var sce = shallowCopy(SCE_CONTEXTS);

    /**
     * @ngdoc method
     * @name $sce#isEnabled
     * @kind function
     *
     * @return {Boolean} true if SCE is enabled, false otherwise.  If you want to set the value, you
     * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
     *
     * @description
     * Returns a boolean indicating if SCE is enabled.
     */
    sce.isEnabled = function () {
      return enabled;
    };
    sce.trustAs = $sceDelegate.trustAs;
    sce.getTrusted = $sceDelegate.getTrusted;
    sce.valueOf = $sceDelegate.valueOf;

    if (!enabled) {
      sce.trustAs = sce.getTrusted = function(type, value) { return value; };
      sce.valueOf = identity;
    }

    /**
     * @ngdoc method
     * @name $sce#parseAs
     *
     * @description
     * Converts Angular {@link guide/expression expression} into a function.  This is like {@link
     * ng.$parse $parse} and is identical when the expression is a literal constant.  Otherwise, it
     * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,
     * *result*)}
     *
     * @param {string} type The kind of SCE context in which this result will be used.
     * @param {string} expression String expression to compile.
     * @returns {function(context, locals)} a function which represents the compiled expression:
     *
     *    * `context` – `{object}` – an object against which any expressions embedded in the strings
     *      are evaluated against (typically a scope object).
     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
     *      `context`.
     */
    sce.parseAs = function sceParseAs(type, expr) {
      var parsed = $parse(expr);
      if (parsed.literal && parsed.constant) {
        return parsed;
      } else {
        return function sceParseAsTrusted(self, locals) {
          return sce.getTrusted(type, parsed(self, locals));
        };
      }
    };

    /**
     * @ngdoc method
     * @name $sce#trustAs
     *
     * @description
     * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.  As such,
     * returns an object that is trusted by angular for use in specified strict contextual
     * escaping contexts (such as ng-bind-html, ng-include, any src attribute
     * interpolation, any dom event binding attribute interpolation such as for onclick,  etc.)
     * that uses the provided value.  See * {@link ng.$sce $sce} for enabling strict contextual
     * escaping.
     *
     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,
     *   resource_url, html, js and css.
     * @param {*} value The value that that should be considered trusted/safe.
     * @returns {*} A value that can be used to stand in for the provided `value` in places
     * where Angular expects a $sce.trustAs() return value.
     */

    /**
     * @ngdoc method
     * @name $sce#trustAsHtml
     *
     * @description
     * Shorthand method.  `$sce.trustAsHtml(value)` →
     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
     *
     * @param {*} value The value to trustAs.
     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml
     *     $sce.getTrustedHtml(value)} to obtain the original value.  (privileged directives
     *     only accept expressions that are either literal constants or are the
     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)
     */

    /**
     * @ngdoc method
     * @name $sce#trustAsUrl
     *
     * @description
     * Shorthand method.  `$sce.trustAsUrl(value)` →
     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}
     *
     * @param {*} value The value to trustAs.
     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl
     *     $sce.getTrustedUrl(value)} to obtain the original value.  (privileged directives
     *     only accept expressions that are either literal constants or are the
     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)
     */

    /**
     * @ngdoc method
     * @name $sce#trustAsResourceUrl
     *
     * @description
     * Shorthand method.  `$sce.trustAsResourceUrl(value)` →
     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
     *
     * @param {*} value The value to trustAs.
     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl
     *     $sce.getTrustedResourceUrl(value)} to obtain the original value.  (privileged directives
     *     only accept expressions that are either literal constants or are the return
     *     value of {@link ng.$sce#trustAs $sce.trustAs}.)
     */

    /**
     * @ngdoc method
     * @name $sce#trustAsJs
     *
     * @description
     * Shorthand method.  `$sce.trustAsJs(value)` →
     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}
     *
     * @param {*} value The value to trustAs.
     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs
     *     $sce.getTrustedJs(value)} to obtain the original value.  (privileged directives
     *     only accept expressions that are either literal constants or are the
     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)
     */

    /**
     * @ngdoc method
     * @name $sce#getTrusted
     *
     * @description
     * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}.  As such,
     * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the
     * originally supplied value if the queried context type is a supertype of the created type.
     * If this condition isn't satisfied, throws an exception.
     *
     * @param {string} type The kind of context in which this value is to be used.
     * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}
     *                         call.
     * @returns {*} The value the was originally provided to
     *              {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.
     *              Otherwise, throws an exception.
     */

    /**
     * @ngdoc method
     * @name $sce#getTrustedHtml
     *
     * @description
     * Shorthand method.  `$sce.getTrustedHtml(value)` →
     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
     *
     * @param {*} value The value to pass to `$sce.getTrusted`.
     * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`
     */

    /**
     * @ngdoc method
     * @name $sce#getTrustedCss
     *
     * @description
     * Shorthand method.  `$sce.getTrustedCss(value)` →
     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
     *
     * @param {*} value The value to pass to `$sce.getTrusted`.
     * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`
     */

    /**
     * @ngdoc method
     * @name $sce#getTrustedUrl
     *
     * @description
     * Shorthand method.  `$sce.getTrustedUrl(value)` →
     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
     *
     * @param {*} value The value to pass to `$sce.getTrusted`.
     * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`
     */

    /**
     * @ngdoc method
     * @name $sce#getTrustedResourceUrl
     *
     * @description
     * Shorthand method.  `$sce.getTrustedResourceUrl(value)` →
     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
     *
     * @param {*} value The value to pass to `$sceDelegate.getTrusted`.
     * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
     */

    /**
     * @ngdoc method
     * @name $sce#getTrustedJs
     *
     * @description
     * Shorthand method.  `$sce.getTrustedJs(value)` →
     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
     *
     * @param {*} value The value to pass to `$sce.getTrusted`.
     * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`
     */

    /**
     * @ngdoc method
     * @name $sce#parseAsHtml
     *
     * @description
     * Shorthand method.  `$sce.parseAsHtml(expression string)` →
     *     {@link ng.$sce#parse `$sce.parseAs($sce.HTML, value)`}
     *
     * @param {string} expression String expression to compile.
     * @returns {function(context, locals)} a function which represents the compiled expression:
     *
     *    * `context` – `{object}` – an object against which any expressions embedded in the strings
     *      are evaluated against (typically a scope object).
     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
     *      `context`.
     */

    /**
     * @ngdoc method
     * @name $sce#parseAsCss
     *
     * @description
     * Shorthand method.  `$sce.parseAsCss(value)` →
     *     {@link ng.$sce#parse `$sce.parseAs($sce.CSS, value)`}
     *
     * @param {string} expression String expression to compile.
     * @returns {function(context, locals)} a function which represents the compiled expression:
     *
     *    * `context` – `{object}` – an object against which any expressions embedded in the strings
     *      are evaluated against (typically a scope object).
     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
     *      `context`.
     */

    /**
     * @ngdoc method
     * @name $sce#parseAsUrl
     *
     * @description
     * Shorthand method.  `$sce.parseAsUrl(value)` →
     *     {@link ng.$sce#parse `$sce.parseAs($sce.URL, value)`}
     *
     * @param {string} expression String expression to compile.
     * @returns {function(context, locals)} a function which represents the compiled expression:
     *
     *    * `context` – `{object}` – an object against which any expressions embedded in the strings
     *      are evaluated against (typically a scope object).
     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
     *      `context`.
     */

    /**
     * @ngdoc method
     * @name $sce#parseAsResourceUrl
     *
     * @description
     * Shorthand method.  `$sce.parseAsResourceUrl(value)` →
     *     {@link ng.$sce#parse `$sce.parseAs($sce.RESOURCE_URL, value)`}
     *
     * @param {string} expression String expression to compile.
     * @returns {function(context, locals)} a function which represents the compiled expression:
     *
     *    * `context` – `{object}` – an object against which any expressions embedded in the strings
     *      are evaluated against (typically a scope object).
     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
     *      `context`.
     */

    /**
     * @ngdoc method
     * @name $sce#parseAsJs
     *
     * @description
     * Shorthand method.  `$sce.parseAsJs(value)` →
     *     {@link ng.$sce#parse `$sce.parseAs($sce.JS, value)`}
     *
     * @param {string} expression String expression to compile.
     * @returns {function(context, locals)} a function which represents the compiled expression:
     *
     *    * `context` – `{object}` – an object against which any expressions embedded in the strings
     *      are evaluated against (typically a scope object).
     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
     *      `context`.
     */

    // Shorthand delegations.
    var parse = sce.parseAs,
        getTrusted = sce.getTrusted,
        trustAs = sce.trustAs;

    forEach(SCE_CONTEXTS, function (enumValue, name) {
      var lName = lowercase(name);
      sce[camelCase("parse_as_" + lName)] = function (expr) {
        return parse(enumValue, expr);
      };
      sce[camelCase("get_trusted_" + lName)] = function (value) {
        return getTrusted(enumValue, value);
      };
      sce[camelCase("trust_as_" + lName)] = function (value) {
        return trustAs(enumValue, value);
      };
    });

    return sce;
  }];
}

/**
 * !!! This is an undocumented "private" service !!!
 *
 * @name $sniffer
 * @requires $window
 * @requires $document
 *
 * @property {boolean} history Does the browser support html5 history api ?
 * @property {boolean} hashchange Does the browser support hashchange event ?
 * @property {boolean} transitions Does the browser support CSS transition events ?
 * @property {boolean} animations Does the browser support CSS animation events ?
 *
 * @description
 * This is very simple implementation of testing browser's features.
 */
function $SnifferProvider() {
  this.$get = ['$window', '$document', function($window, $document) {
    var eventSupport = {},
        android =
          int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),
        boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
        document = $document[0] || {},
        documentMode = document.documentMode,
        vendorPrefix,
        vendorRegex = /^(Moz|webkit|O|ms)(?=[A-Z])/,
        bodyStyle = document.body && document.body.style,
        transitions = false,
        animations = false,
        match;

    if (bodyStyle) {
      for(var prop in bodyStyle) {
        if(match = vendorRegex.exec(prop)) {
          vendorPrefix = match[0];
          vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
          break;
        }
      }

      if(!vendorPrefix) {
        vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';
      }

      transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
      animations  = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));

      if (android && (!transitions||!animations)) {
        transitions = isString(document.body.style.webkitTransition);
        animations = isString(document.body.style.webkitAnimation);
      }
    }


    return {
      // Android has history.pushState, but it does not update location correctly
      // so let's not use the history API at all.
      // http://code.google.com/p/android/issues/detail?id=17471
      // https://github.com/angular/angular.js/issues/904

      // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has
      // so let's not use the history API also
      // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined
      // jshint -W018
      history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),
      // jshint +W018
      hashchange: 'onhashchange' in $window &&
                  // IE8 compatible mode lies
                  (!documentMode || documentMode > 7),
      hasEvent: function(event) {
        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
        // it. In particular the event is not fired when backspace or delete key are pressed or
        // when cut operation is performed.
        if (event == 'input' && msie == 9) return false;

        if (isUndefined(eventSupport[event])) {
          var divElm = document.createElement('div');
          eventSupport[event] = 'on' + event in divElm;
        }

        return eventSupport[event];
      },
      csp: csp(),
      vendorPrefix: vendorPrefix,
      transitions : transitions,
      animations : animations,
      android: android,
      msie : msie,
      msieDocumentMode: documentMode
    };
  }];
}

function $TimeoutProvider() {
  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',
       function($rootScope,   $browser,   $q,   $exceptionHandler) {
    var deferreds = {};


     /**
      * @ngdoc service
      * @name $timeout
      *
      * @description
      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch
      * block and delegates any exceptions to
      * {@link ng.$exceptionHandler $exceptionHandler} service.
      *
      * The return value of registering a timeout function is a promise, which will be resolved when
      * the timeout is reached and the timeout function is executed.
      *
      * To cancel a timeout request, call `$timeout.cancel(promise)`.
      *
      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to
      * synchronously flush the queue of deferred functions.
      *
      * @param {function()} fn A function, whose execution should be delayed.
      * @param {number=} [delay=0] Delay in milliseconds.
      * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
      *   promise will be resolved with is the return value of the `fn` function.
      *
      */
    function timeout(fn, delay, invokeApply) {
      var deferred = $q.defer(),
          promise = deferred.promise,
          skipApply = (isDefined(invokeApply) && !invokeApply),
          timeoutId;

      timeoutId = $browser.defer(function() {
        try {
          deferred.resolve(fn());
        } catch(e) {
          deferred.reject(e);
          $exceptionHandler(e);
        }
        finally {
          delete deferreds[promise.$$timeoutId];
        }

        if (!skipApply) $rootScope.$apply();
      }, delay);

      promise.$$timeoutId = timeoutId;
      deferreds[timeoutId] = deferred;

      return promise;
    }


     /**
      * @ngdoc method
      * @name $timeout#cancel
      *
      * @description
      * Cancels a task associated with the `promise`. As a result of this, the promise will be
      * resolved with a rejection.
      *
      * @param {Promise=} promise Promise returned by the `$timeout` function.
      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
      *   canceled.
      */
    timeout.cancel = function(promise) {
      if (promise && promise.$$timeoutId in deferreds) {
        deferreds[promise.$$timeoutId].reject('canceled');
        delete deferreds[promise.$$timeoutId];
        return $browser.defer.cancel(promise.$$timeoutId);
      }
      return false;
    };

    return timeout;
  }];
}

// NOTE:  The usage of window and document instead of $window and $document here is
// deliberate.  This service depends on the specific behavior of anchor nodes created by the
// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and
// cause us to break tests.  In addition, when the browser resolves a URL for XHR, it
// doesn't know about mocked locations and resolves URLs to the real document - which is
// exactly the behavior needed here.  There is little value is mocking these out for this
// service.
var urlParsingNode = document.createElement("a");
var originUrl = urlResolve(window.location.href, true);


/**
 *
 * Implementation Notes for non-IE browsers
 * ----------------------------------------
 * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,
 * results both in the normalizing and parsing of the URL.  Normalizing means that a relative
 * URL will be resolved into an absolute URL in the context of the application document.
 * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related
 * properties are all populated to reflect the normalized URL.  This approach has wide
 * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc.  See
 * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
 *
 * Implementation Notes for IE
 * ---------------------------
 * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other
 * browsers.  However, the parsed components will not be set if the URL assigned did not specify
 * them.  (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.)  We
 * work around that by performing the parsing in a 2nd step by taking a previously normalized
 * URL (e.g. by assigning to a.href) and assigning it a.href again.  This correctly populates the
 * properties such as protocol, hostname, port, etc.
 *
 * IE7 does not normalize the URL when assigned to an anchor node.  (Apparently, it does, if one
 * uses the inner HTML approach to assign the URL as part of an HTML snippet -
 * http://stackoverflow.com/a/472729)  However, setting img[src] does normalize the URL.
 * Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception.
 * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that
 * method and IE < 8 is unsupported.
 *
 * References:
 *   http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
 *   http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
 *   http://url.spec.whatwg.org/#urlutils
 *   https://github.com/angular/angular.js/pull/2902
 *   http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
 *
 * @kind function
 * @param {string} url The URL to be parsed.
 * @description Normalizes and parses a URL.
 * @returns {object} Returns the normalized URL as a dictionary.
 *
 *   | member name   | Description    |
 *   |---------------|----------------|
 *   | href          | A normalized version of the provided URL if it was not an absolute URL |
 *   | protocol      | The protocol including the trailing colon                              |
 *   | host          | The host and port (if the port is non-default) of the normalizedUrl    |
 *   | search        | The search params, minus the question mark                             |
 *   | hash          | The hash string, minus the hash symbol
 *   | hostname      | The hostname
 *   | port          | The port, without ":"
 *   | pathname      | The pathname, beginning with "/"
 *
 */
function urlResolve(url, base) {
  var href = url;

  if (msie) {
    // Normalize before parse.  Refer Implementation Notes on why this is
    // done in two steps on IE.
    urlParsingNode.setAttribute("href", href);
    href = urlParsingNode.href;
  }

  urlParsingNode.setAttribute('href', href);

  // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
  return {
    href: urlParsingNode.href,
    protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
    host: urlParsingNode.host,
    search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
    hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
    hostname: urlParsingNode.hostname,
    port: urlParsingNode.port,
    pathname: (urlParsingNode.pathname.charAt(0) === '/')
      ? urlParsingNode.pathname
      : '/' + urlParsingNode.pathname
  };
}

/**
 * Parse a request URL and determine whether this is a same-origin request as the application document.
 *
 * @param {string|object} requestUrl The url of the request as a string that will be resolved
 * or a parsed URL object.
 * @returns {boolean} Whether the request is for the same origin as the application document.
 */
function urlIsSameOrigin(requestUrl) {
  var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;
  return (parsed.protocol === originUrl.protocol &&
          parsed.host === originUrl.host);
}

/**
 * @ngdoc service
 * @name $window
 *
 * @description
 * A reference to the browser's `window` object. While `window`
 * is globally available in JavaScript, it causes testability problems, because
 * it is a global variable. In angular we always refer to it through the
 * `$window` service, so it may be overridden, removed or mocked for testing.
 *
 * Expressions, like the one defined for the `ngClick` directive in the example
 * below, are evaluated with respect to the current scope.  Therefore, there is
 * no risk of inadvertently coding in a dependency on a global value in such an
 * expression.
 *
 * @example
   <example module="windowExample">
     <file name="index.html">
       <script>
         angular.module('windowExample', [])
           .controller('ExampleController', ['$scope', '$window', function ($scope, $window) {
             $scope.greeting = 'Hello, World!';
             $scope.doGreeting = function(greeting) {
               $window.alert(greeting);
             };
           }]);
       </script>
       <div ng-controller="ExampleController">
         <input type="text" ng-model="greeting" />
         <button ng-click="doGreeting(greeting)">ALERT</button>
       </div>
     </file>
     <file name="protractor.js" type="protractor">
      it('should display the greeting in the input box', function() {
       element(by.model('greeting')).sendKeys('Hello, E2E Tests');
       // If we click the button it will block the test runner
       // element(':button').click();
      });
     </file>
   </example>
 */
function $WindowProvider(){
  this.$get = valueFn(window);
}

/* global currencyFilter: true,
 dateFilter: true,
 filterFilter: true,
 jsonFilter: true,
 limitToFilter: true,
 lowercaseFilter: true,
 numberFilter: true,
 orderByFilter: true,
 uppercaseFilter: true,
 */

/**
 * @ngdoc provider
 * @name $filterProvider
 * @description
 *
 * Filters are just functions which transform input to an output. However filters need to be
 * Dependency Injected. To achieve this a filter definition consists of a factory function which is
 * annotated with dependencies and is responsible for creating a filter function.
 *
 * ```js
 *   // Filter registration
 *   function MyModule($provide, $filterProvider) {
 *     // create a service to demonstrate injection (not always needed)
 *     $provide.value('greet', function(name){
 *       return 'Hello ' + name + '!';
 *     });
 *
 *     // register a filter factory which uses the
 *     // greet service to demonstrate DI.
 *     $filterProvider.register('greet', function(greet){
 *       // return the filter function which uses the greet service
 *       // to generate salutation
 *       return function(text) {
 *         // filters need to be forgiving so check input validity
 *         return text && greet(text) || text;
 *       };
 *     });
 *   }
 * ```
 *
 * The filter function is registered with the `$injector` under the filter name suffix with
 * `Filter`.
 *
 * ```js
 *   it('should be the same instance', inject(
 *     function($filterProvider) {
 *       $filterProvider.register('reverse', function(){
 *         return ...;
 *       });
 *     },
 *     function($filter, reverseFilter) {
 *       expect($filter('reverse')).toBe(reverseFilter);
 *     });
 * ```
 *
 *
 * For more information about how angular filters work, and how to create your own filters, see
 * {@link guide/filter Filters} in the Angular Developer Guide.
 */

/**
 * @ngdoc service
 * @name $filter
 * @kind function
 * @description
 * Filters are used for formatting data displayed to the user.
 *
 * The general syntax in templates is as follows:
 *
 *         {{ expression [| filter_name[:parameter_value] ... ] }}
 *
 * @param {String} name Name of the filter function to retrieve
 * @return {Function} the filter function
 * @example
   <example name="$filter" module="filterExample">
     <file name="index.html">
       <div ng-controller="MainCtrl">
        <h3>{{ originalText }}</h3>
        <h3>{{ filteredText }}</h3>
       </div>
     </file>

     <file name="script.js">
      angular.module('filterExample', [])
      .controller('MainCtrl', function($scope, $filter) {
        $scope.originalText = 'hello';
        $scope.filteredText = $filter('uppercase')($scope.originalText);
      });
     </file>
   </example>
  */
$FilterProvider.$inject = ['$provide'];
function $FilterProvider($provide) {
  var suffix = 'Filter';

  /**
   * @ngdoc method
   * @name $filterProvider#register
   * @param {string|Object} name Name of the filter function, or an object map of filters where
   *    the keys are the filter names and the values are the filter factories.
   * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
   *    of the registered filter instances.
   */
  function register(name, factory) {
    if(isObject(name)) {
      var filters = {};
      forEach(name, function(filter, key) {
        filters[key] = register(key, filter);
      });
      return filters;
    } else {
      return $provide.factory(name + suffix, factory);
    }
  }
  this.register = register;

  this.$get = ['$injector', function($injector) {
    return function(name) {
      return $injector.get(name + suffix);
    };
  }];

  ////////////////////////////////////////

  /* global
    currencyFilter: false,
    dateFilter: false,
    filterFilter: false,
    jsonFilter: false,
    limitToFilter: false,
    lowercaseFilter: false,
    numberFilter: false,
    orderByFilter: false,
    uppercaseFilter: false,
  */

  register('currency', currencyFilter);
  register('date', dateFilter);
  register('filter', filterFilter);
  register('json', jsonFilter);
  register('limitTo', limitToFilter);
  register('lowercase', lowercaseFilter);
  register('number', numberFilter);
  register('orderBy', orderByFilter);
  register('uppercase', uppercaseFilter);
}

/**
 * @ngdoc filter
 * @name filter
 * @kind function
 *
 * @description
 * Selects a subset of items from `array` and returns it as a new array.
 *
 * @param {Array} array The source array.
 * @param {string|Object|function()} expression The predicate to be used for selecting items from
 *   `array`.
 *
 *   Can be one of:
 *
 *   - `string`: The string is evaluated as an expression and the resulting value is used for substring match against
 *     the contents of the `array`. All strings or objects with string properties in `array` that contain this string
 *     will be returned. The predicate can be negated by prefixing the string with `!`.
 *
 *   - `Object`: A pattern object can be used to filter specific properties on objects contained
 *     by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
 *     which have property `name` containing "M" and property `phone` containing "1". A special
 *     property name `$` can be used (as in `{$:"text"}`) to accept a match against any
 *     property of the object. That's equivalent to the simple substring match with a `string`
 *     as described above. The predicate can be negated by prefixing the string with `!`.
 *     For Example `{name: "!M"}` predicate will return an array of items which have property `name`
 *     not containing "M".
 *
 *   - `function(value)`: A predicate function can be used to write arbitrary filters. The function is
 *     called for each element of `array`. The final result is an array of those elements that
 *     the predicate returned true for.
 *
 * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in
 *     determining if the expected value (from the filter expression) and actual value (from
 *     the object in the array) should be considered a match.
 *
 *   Can be one of:
 *
 *   - `function(actual, expected)`:
 *     The function will be given the object value and the predicate value to compare and
 *     should return true if the item should be included in filtered result.
 *
 *   - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.
 *     this is essentially strict comparison of expected and actual.
 *
 *   - `false|undefined`: A short hand for a function which will look for a substring match in case
 *     insensitive way.
 *
 * @example
   <example>
     <file name="index.html">
       <div ng-init="friends = [{name:'John', phone:'555-1276'},
                                {name:'Mary', phone:'800-BIG-MARY'},
                                {name:'Mike', phone:'555-4321'},
                                {name:'Adam', phone:'555-5678'},
                                {name:'Julie', phone:'555-8765'},
                                {name:'Juliette', phone:'555-5678'}]"></div>

       Search: <input ng-model="searchText">
       <table id="searchTextResults">
         <tr><th>Name</th><th>Phone</th></tr>
         <tr ng-repeat="friend in friends | filter:searchText">
           <td>{{friend.name}}</td>
           <td>{{friend.phone}}</td>
         </tr>
       </table>
       <hr>
       Any: <input ng-model="search.$"> <br>
       Name only <input ng-model="search.name"><br>
       Phone only <input ng-model="search.phone"><br>
       Equality <input type="checkbox" ng-model="strict"><br>
       <table id="searchObjResults">
         <tr><th>Name</th><th>Phone</th></tr>
         <tr ng-repeat="friendObj in friends | filter:search:strict">
           <td>{{friendObj.name}}</td>
           <td>{{friendObj.phone}}</td>
         </tr>
       </table>
     </file>
     <file name="protractor.js" type="protractor">
       var expectFriendNames = function(expectedNames, key) {
         element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {
           arr.forEach(function(wd, i) {
             expect(wd.getText()).toMatch(expectedNames[i]);
           });
         });
       };

       it('should search across all fields when filtering with a string', function() {
         var searchText = element(by.model('searchText'));
         searchText.clear();
         searchText.sendKeys('m');
         expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');

         searchText.clear();
         searchText.sendKeys('76');
         expectFriendNames(['John', 'Julie'], 'friend');
       });

       it('should search in specific fields when filtering with a predicate object', function() {
         var searchAny = element(by.model('search.$'));
         searchAny.clear();
         searchAny.sendKeys('i');
         expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');
       });
       it('should use a equal comparison when comparator is true', function() {
         var searchName = element(by.model('search.name'));
         var strict = element(by.model('strict'));
         searchName.clear();
         searchName.sendKeys('Julie');
         strict.click();
         expectFriendNames(['Julie'], 'friendObj');
       });
     </file>
   </example>
 */
function filterFilter() {
  return function(array, expression, comparator) {
    if (!isArray(array)) return array;

    var comparatorType = typeof(comparator),
        predicates = [];

    predicates.check = function(value) {
      for (var j = 0; j < predicates.length; j++) {
        if(!predicates[j](value)) {
          return false;
        }
      }
      return true;
    };

    if (comparatorType !== 'function') {
      if (comparatorType === 'boolean' && comparator) {
        comparator = function(obj, text) {
          return angular.equals(obj, text);
        };
      } else {
        comparator = function(obj, text) {
          if (obj && text && typeof obj === 'object' && typeof text === 'object') {
            for (var objKey in obj) {
              if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) &&
                  comparator(obj[objKey], text[objKey])) {
                return true;
              }
            }
            return false;
          }
          text = (''+text).toLowerCase();
          return (''+obj).toLowerCase().indexOf(text) > -1;
        };
      }
    }

    var search = function(obj, text){
      if (typeof text === 'string' && text.charAt(0) === '!') {
        return !search(obj, text.substr(1));
      }
      switch (typeof obj) {
        case 'boolean':
        case 'number':
        case 'string':
          return comparator(obj, text);
        case 'object':
          switch (typeof text) {
            case 'object':
              return comparator(obj, text);
            default:
              for ( var objKey in obj) {
                if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
                  return true;
                }
              }
              break;
          }
          return false;
        case 'array':
          for ( var i = 0; i < obj.length; i++) {
            if (search(obj[i], text)) {
              return true;
            }
          }
          return false;
        default:
          return false;
      }
    };
    switch (typeof expression) {
      case 'boolean':
      case 'number':
      case 'string':
        // Set up expression object and fall through
        expression = {$:expression};
        // jshint -W086
      case 'object':
        // jshint +W086
        for (var key in expression) {
          (function(path) {
            if (typeof expression[path] === 'undefined') return;
            predicates.push(function(value) {
              return search(path == '$' ? value : (value && value[path]), expression[path]);
            });
          })(key);
        }
        break;
      case 'function':
        predicates.push(expression);
        break;
      default:
        return array;
    }
    var filtered = [];
    for ( var j = 0; j < array.length; j++) {
      var value = array[j];
      if (predicates.check(value)) {
        filtered.push(value);
      }
    }
    return filtered;
  };
}

/**
 * @ngdoc filter
 * @name currency
 * @kind function
 *
 * @description
 * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
 * symbol for current locale is used.
 *
 * @param {number} amount Input to filter.
 * @param {string=} symbol Currency symbol or identifier to be displayed.
 * @returns {string} Formatted number.
 *
 *
 * @example
   <example module="currencyExample">
     <file name="index.html">
       <script>
         angular.module('currencyExample', [])
           .controller('ExampleController', ['$scope', function($scope) {
             $scope.amount = 1234.56;
           }]);
       </script>
       <div ng-controller="ExampleController">
         <input type="number" ng-model="amount"> <br>
         default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
         custom currency identifier (USD$): <span>{{amount | currency:"USD$"}}</span>
       </div>
     </file>
     <file name="protractor.js" type="protractor">
       it('should init with 1234.56', function() {
         expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');
         expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('USD$1,234.56');
       });
       it('should update', function() {
         if (browser.params.browser == 'safari') {
           // Safari does not understand the minus key. See
           // https://github.com/angular/protractor/issues/481
           return;
         }
         element(by.model('amount')).clear();
         element(by.model('amount')).sendKeys('-1234');
         expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');
         expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('(USD$1,234.00)');
       });
     </file>
   </example>
 */
currencyFilter.$inject = ['$locale'];
function currencyFilter($locale) {
  var formats = $locale.NUMBER_FORMATS;
  return function(amount, currencySymbol){
    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;
    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).
                replace(/\u00A4/g, currencySymbol);
  };
}

/**
 * @ngdoc filter
 * @name number
 * @kind function
 *
 * @description
 * Formats a number as text.
 *
 * If the input is not a number an empty string is returned.
 *
 * @param {number|string} number Number to format.
 * @param {(number|string)=} fractionSize Number of decimal places to round the number to.
 * If this is not provided then the fraction size is computed from the current locale's number
 * formatting pattern. In the case of the default locale, it will be 3.
 * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
 *
 * @example
   <example module="numberFilterExample">
     <file name="index.html">
       <script>
         angular.module('numberFilterExample', [])
           .controller('ExampleController', ['$scope', function($scope) {
             $scope.val = 1234.56789;
           }]);
       </script>
       <div ng-controller="ExampleController">
         Enter number: <input ng-model='val'><br>
         Default formatting: <span id='number-default'>{{val | number}}</span><br>
         No fractions: <span>{{val | number:0}}</span><br>
         Negative number: <span>{{-val | number:4}}</span>
       </div>
     </file>
     <file name="protractor.js" type="protractor">
       it('should format numbers', function() {
         expect(element(by.id('number-default')).getText()).toBe('1,234.568');
         expect(element(by.binding('val | number:0')).getText()).toBe('1,235');
         expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');
       });

       it('should update', function() {
         element(by.model('val')).clear();
         element(by.model('val')).sendKeys('3374.333');
         expect(element(by.id('number-default')).getText()).toBe('3,374.333');
         expect(element(by.binding('val | number:0')).getText()).toBe('3,374');
         expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');
      });
     </file>
   </example>
 */


numberFilter.$inject = ['$locale'];
function numberFilter($locale) {
  var formats = $locale.NUMBER_FORMATS;
  return function(number, fractionSize) {
    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,
      fractionSize);
  };
}

var DECIMAL_SEP = '.';
function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
  if (number == null || !isFinite(number) || isObject(number)) return '';

  var isNegative = number < 0;
  number = Math.abs(number);
  var numStr = number + '',
      formatedText = '',
      parts = [];

  var hasExponent = false;
  if (numStr.indexOf('e') !== -1) {
    var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
    if (match && match[2] == '-' && match[3] > fractionSize + 1) {
      numStr = '0';
      number = 0;
    } else {
      formatedText = numStr;
      hasExponent = true;
    }
  }

  if (!hasExponent) {
    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;

    // determine fractionSize if it is not specified
    if (isUndefined(fractionSize)) {
      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
    }

    // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
    // inspired by:
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
    number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);

    if (number === 0) {
      isNegative = false;
    }

    var fraction = ('' + number).split(DECIMAL_SEP);
    var whole = fraction[0];
    fraction = fraction[1] || '';

    var i, pos = 0,
        lgroup = pattern.lgSize,
        group = pattern.gSize;

    if (whole.length >= (lgroup + group)) {
      pos = whole.length - lgroup;
      for (i = 0; i < pos; i++) {
        if ((pos - i)%group === 0 && i !== 0) {
          formatedText += groupSep;
        }
        formatedText += whole.charAt(i);
      }
    }

    for (i = pos; i < whole.length; i++) {
      if ((whole.length - i)%lgroup === 0 && i !== 0) {
        formatedText += groupSep;
      }
      formatedText += whole.charAt(i);
    }

    // format fraction part.
    while(fraction.length < fractionSize) {
      fraction += '0';
    }

    if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
  } else {

    if (fractionSize > 0 && number > -1 && number < 1) {
      formatedText = number.toFixed(fractionSize);
    }
  }

  parts.push(isNegative ? pattern.negPre : pattern.posPre);
  parts.push(formatedText);
  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);
  return parts.join('');
}

function padNumber(num, digits, trim) {
  var neg = '';
  if (num < 0) {
    neg =  '-';
    num = -num;
  }
  num = '' + num;
  while(num.length < digits) num = '0' + num;
  if (trim)
    num = num.substr(num.length - digits);
  return neg + num;
}


function dateGetter(name, size, offset, trim) {
  offset = offset || 0;
  return function(date) {
    var value = date['get' + name]();
    if (offset > 0 || value > -offset)
      value += offset;
    if (value === 0 && offset == -12 ) value = 12;
    return padNumber(value, size, trim);
  };
}

function dateStrGetter(name, shortForm) {
  return function(date, formats) {
    var value = date['get' + name]();
    var get = uppercase(shortForm ? ('SHORT' + name) : name);

    return formats[get][value];
  };
}

function timeZoneGetter(date) {
  var zone = -1 * date.getTimezoneOffset();
  var paddedZone = (zone >= 0) ? "+" : "";

  paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +
                padNumber(Math.abs(zone % 60), 2);

  return paddedZone;
}

function ampmGetter(date, formats) {
  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
}

var DATE_FORMATS = {
  yyyy: dateGetter('FullYear', 4),
    yy: dateGetter('FullYear', 2, 0, true),
     y: dateGetter('FullYear', 1),
  MMMM: dateStrGetter('Month'),
   MMM: dateStrGetter('Month', true),
    MM: dateGetter('Month', 2, 1),
     M: dateGetter('Month', 1, 1),
    dd: dateGetter('Date', 2),
     d: dateGetter('Date', 1),
    HH: dateGetter('Hours', 2),
     H: dateGetter('Hours', 1),
    hh: dateGetter('Hours', 2, -12),
     h: dateGetter('Hours', 1, -12),
    mm: dateGetter('Minutes', 2),
     m: dateGetter('Minutes', 1),
    ss: dateGetter('Seconds', 2),
     s: dateGetter('Seconds', 1),
     // while ISO 8601 requires fractions to be prefixed with `.` or `,`
     // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions
   sss: dateGetter('Milliseconds', 3),
  EEEE: dateStrGetter('Day'),
   EEE: dateStrGetter('Day', true),
     a: ampmGetter,
     Z: timeZoneGetter
};

var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,
    NUMBER_STRING = /^\-?\d+$/;

/**
 * @ngdoc filter
 * @name date
 * @kind function
 *
 * @description
 *   Formats `date` to a string based on the requested `format`.
 *
 *   `format` string can be composed of the following elements:
 *
 *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
 *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
 *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)
 *   * `'MMMM'`: Month in year (January-December)
 *   * `'MMM'`: Month in year (Jan-Dec)
 *   * `'MM'`: Month in year, padded (01-12)
 *   * `'M'`: Month in year (1-12)
 *   * `'dd'`: Day in month, padded (01-31)
 *   * `'d'`: Day in month (1-31)
 *   * `'EEEE'`: Day in Week,(Sunday-Saturday)
 *   * `'EEE'`: Day in Week, (Sun-Sat)
 *   * `'HH'`: Hour in day, padded (00-23)
 *   * `'H'`: Hour in day (0-23)
 *   * `'hh'`: Hour in am/pm, padded (01-12)
 *   * `'h'`: Hour in am/pm, (1-12)
 *   * `'mm'`: Minute in hour, padded (00-59)
 *   * `'m'`: Minute in hour (0-59)
 *   * `'ss'`: Second in minute, padded (00-59)
 *   * `'s'`: Second in minute (0-59)
 *   * `'.sss' or ',sss'`: Millisecond in second, padded (000-999)
 *   * `'a'`: am/pm marker
 *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
 *
 *   `format` string can also be one of the following predefined
 *   {@link guide/i18n localizable formats}:
 *
 *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
 *     (e.g. Sep 3, 2010 12:05:08 pm)
 *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)
 *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale
 *     (e.g. Friday, September 3, 2010)
 *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010)
 *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)
 *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)
 *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)
 *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)
 *
 *   `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.
 *   `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence
 *   (e.g. `"h 'o''clock'"`).
 *
 * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
 *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its
 *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
 *    specified in the string input, the time is considered to be in the local timezone.
 * @param {string=} format Formatting rules (see Description). If not specified,
 *    `mediumDate` is used.
 * @returns {string} Formatted string or the input if input is not recognized as date/millis.
 *
 * @example
   <example>
     <file name="index.html">
       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:
           <span>{{1288323623006 | date:'medium'}}</span><br>
       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:
          <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>
       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
          <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>
       <span ng-non-bindable>{{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}</span>:
          <span>{{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}</span><br>
     </file>
     <file name="protractor.js" type="protractor">
       it('should format date', function() {
         expect(element(by.binding("1288323623006 | date:'medium'")).getText()).
            toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/);
         expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()).
            toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
         expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()).
            toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
         expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()).
            toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/);
       });
     </file>
   </example>
 */
dateFilter.$inject = ['$locale'];
function dateFilter($locale) {


  var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
                     // 1        2       3         4          5          6          7          8  9     10      11
  function jsonStringToDate(string) {
    var match;
    if (match = string.match(R_ISO8601_STR)) {
      var date = new Date(0),
          tzHour = 0,
          tzMin  = 0,
          dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,
          timeSetter = match[8] ? date.setUTCHours : date.setHours;

      if (match[9]) {
        tzHour = int(match[9] + match[10]);
        tzMin = int(match[9] + match[11]);
      }
      dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
      var h = int(match[4]||0) - tzHour;
      var m = int(match[5]||0) - tzMin;
      var s = int(match[6]||0);
      var ms = Math.round(parseFloat('0.' + (match[7]||0)) * 1000);
      timeSetter.call(date, h, m, s, ms);
      return date;
    }
    return string;
  }


  return function(date, format) {
    var text = '',
        parts = [],
        fn, match;

    format = format || 'mediumDate';
    format = $locale.DATETIME_FORMATS[format] || format;
    if (isString(date)) {
      date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date);
    }

    if (isNumber(date)) {
      date = new Date(date);
    }

    if (!isDate(date)) {
      return date;
    }

    while(format) {
      match = DATE_FORMATS_SPLIT.exec(format);
      if (match) {
        parts = concat(parts, match, 1);
        format = parts.pop();
      } else {
        parts.push(format);
        format = null;
      }
    }

    forEach(parts, function(value){
      fn = DATE_FORMATS[value];
      text += fn ? fn(date, $locale.DATETIME_FORMATS)
                 : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
    });

    return text;
  };
}


/**
 * @ngdoc filter
 * @name json
 * @kind function
 *
 * @description
 *   Allows you to convert a JavaScript object into JSON string.
 *
 *   This filter is mostly useful for debugging. When using the double curly {{value}} notation
 *   the binding is automatically converted to JSON.
 *
 * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
 * @returns {string} JSON string.
 *
 *
 * @example
   <example>
     <file name="index.html">
       <pre>{{ {'name':'value'} | json }}</pre>
     </file>
     <file name="protractor.js" type="protractor">
       it('should jsonify filtered objects', function() {
         expect(element(by.binding("{'name':'value'}")).getText()).toMatch(/\{\n  "name": ?"value"\n}/);
       });
     </file>
   </example>
 *
 */
function jsonFilter() {
  return function(object) {
    return toJson(object, true);
  };
}


/**
 * @ngdoc filter
 * @name lowercase
 * @kind function
 * @description
 * Converts string to lowercase.
 * @see angular.lowercase
 */
var lowercaseFilter = valueFn(lowercase);


/**
 * @ngdoc filter
 * @name uppercase
 * @kind function
 * @description
 * Converts string to uppercase.
 * @see angular.uppercase
 */
var uppercaseFilter = valueFn(uppercase);

/**
 * @ngdoc filter
 * @name limitTo
 * @kind function
 *
 * @description
 * Creates a new array or string containing only a specified number of elements. The elements
 * are taken from either the beginning or the end of the source array or string, as specified by
 * the value and sign (positive or negative) of `limit`.
 *
 * @param {Array|string} input Source array or string to be limited.
 * @param {string|number} limit The length of the returned array or string. If the `limit` number
 *     is positive, `limit` number of items from the beginning of the source array/string are copied.
 *     If the number is negative, `limit` number  of items from the end of the source array/string
 *     are copied. The `limit` will be trimmed if it exceeds `array.length`
 * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
 *     had less than `limit` elements.
 *
 * @example
   <example module="limitToExample">
     <file name="index.html">
       <script>
         angular.module('limitToExample', [])
           .controller('ExampleController', ['$scope', function($scope) {
             $scope.numbers = [1,2,3,4,5,6,7,8,9];
             $scope.letters = "abcdefghi";
             $scope.numLimit = 3;
             $scope.letterLimit = 3;
           }]);
       </script>
       <div ng-controller="ExampleController">
         Limit {{numbers}} to: <input type="number" step="1" ng-model="numLimit">
         <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
         Limit {{letters}} to: <input type="number" step="1" ng-model="letterLimit">
         <p>Output letters: {{ letters | limitTo:letterLimit }}</p>
       </div>
     </file>
     <file name="protractor.js" type="protractor">
       var numLimitInput = element(by.model('numLimit'));
       var letterLimitInput = element(by.model('letterLimit'));
       var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));
       var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));

       it('should limit the number array to first three items', function() {
         expect(numLimitInput.getAttribute('value')).toBe('3');
         expect(letterLimitInput.getAttribute('value')).toBe('3');
         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');
         expect(limitedLetters.getText()).toEqual('Output letters: abc');
       });

       // There is a bug in safari and protractor that doesn't like the minus key
       // it('should update the output when -3 is entered', function() {
       //   numLimitInput.clear();
       //   numLimitInput.sendKeys('-3');
       //   letterLimitInput.clear();
       //   letterLimitInput.sendKeys('-3');
       //   expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');
       //   expect(limitedLetters.getText()).toEqual('Output letters: ghi');
       // });

       it('should not exceed the maximum size of input array', function() {
         numLimitInput.clear();
         numLimitInput.sendKeys('100');
         letterLimitInput.clear();
         letterLimitInput.sendKeys('100');
         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');
         expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');
       });
     </file>
   </example>
 */
function limitToFilter(){
  return function(input, limit) {
    if (!isArray(input) && !isString(input)) return input;

    if (Math.abs(Number(limit)) === Infinity) {
      limit = Number(limit);
    } else {
      limit = int(limit);
    }

    if (isString(input)) {
      //NaN check on limit
      if (limit) {
        return limit >= 0 ? input.slice(0, limit) : input.slice(limit, input.length);
      } else {
        return "";
      }
    }

    var out = [],
      i, n;

    // if abs(limit) exceeds maximum length, trim it
    if (limit > input.length)
      limit = input.length;
    else if (limit < -input.length)
      limit = -input.length;

    if (limit > 0) {
      i = 0;
      n = limit;
    } else {
      i = input.length + limit;
      n = input.length;
    }

    for (; i<n; i++) {
      out.push(input[i]);
    }

    return out;
  };
}

/**
 * @ngdoc filter
 * @name orderBy
 * @kind function
 *
 * @description
 * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
 * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
 * correctly, make sure they are actually being saved as numbers and not strings.
 *
 * @param {Array} array The array to sort.
 * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be
 *    used by the comparator to determine the order of elements.
 *
 *    Can be one of:
 *
 *    - `function`: Getter function. The result of this function will be sorted using the
 *      `<`, `=`, `>` operator.
 *    - `string`: An Angular expression. The result of this expression is used to compare elements
 *      (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by
 *      3 first characters of a property called `name`). The result of a constant expression
 *      is interpreted as a property name to be used in comparisons (for example `"special name"`
 *      to sort object by the value of their `special name` property). An expression can be
 *      optionally prefixed with `+` or `-` to control ascending or descending sort order
 *      (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array
 *      element itself is used to compare where sorting.
 *    - `Array`: An array of function or string predicates. The first predicate in the array
 *      is used for sorting, but when two items are equivalent, the next predicate is used.
 *
 *    If the predicate is missing or empty then it defaults to `'+'`.
 *
 * @param {boolean=} reverse Reverse the order of the array.
 * @returns {Array} Sorted copy of the source array.
 *
 * @example
   <example module="orderByExample">
     <file name="index.html">
       <script>
         angular.module('orderByExample', [])
           .controller('ExampleController', ['$scope', function($scope) {
             $scope.friends =
                 [{name:'John', phone:'555-1212', age:10},
                  {name:'Mary', phone:'555-9876', age:19},
                  {name:'Mike', phone:'555-4321', age:21},
                  {name:'Adam', phone:'555-5678', age:35},
                  {name:'Julie', phone:'555-8765', age:29}];
             $scope.predicate = '-age';
           }]);
       </script>
       <div ng-controller="ExampleController">
         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
         <hr/>
         [ <a href="" ng-click="predicate=''">unsorted</a> ]
         <table class="friend">
           <tr>
             <th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a>
                 (<a href="" ng-click="predicate = '-name'; reverse=false">^</a>)</th>
             <th><a href="" ng-click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
             <th><a href="" ng-click="predicate = 'age'; reverse=!reverse">Age</a></th>
           </tr>
           <tr ng-repeat="friend in friends | orderBy:predicate:reverse">
             <td>{{friend.name}}</td>
             <td>{{friend.phone}}</td>
             <td>{{friend.age}}</td>
           </tr>
         </table>
       </div>
     </file>
   </example>
 *
 * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
 * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the
 * desired parameters.
 *
 * Example:
 *
 * @example
  <example module="orderByExample">
    <file name="index.html">
      <div ng-controller="ExampleController">
        <table class="friend">
          <tr>
            <th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
              (<a href="" ng-click="order('-name',false)">^</a>)</th>
            <th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th>
            <th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th>
          </tr>
          <tr ng-repeat="friend in friends">
            <td>{{friend.name}}</td>
            <td>{{friend.phone}}</td>
            <td>{{friend.age}}</td>
          </tr>
        </table>
      </div>
    </file>

    <file name="script.js">
      angular.module('orderByExample', [])
        .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
          var orderBy = $filter('orderBy');
          $scope.friends = [
            { name: 'John',    phone: '555-1212',    age: 10 },
            { name: 'Mary',    phone: '555-9876',    age: 19 },
            { name: 'Mike',    phone: '555-4321',    age: 21 },
            { name: 'Adam',    phone: '555-5678',    age: 35 },
            { name: 'Julie',   phone: '555-8765',    age: 29 }
          ];
          $scope.order = function(predicate, reverse) {
            $scope.friends = orderBy($scope.friends, predicate, reverse);
          };
          $scope.order('-age',false);
        }]);
    </file>
</example>
 */
orderByFilter.$inject = ['$parse'];
function orderByFilter($parse){
  return function(array, sortPredicate, reverseOrder) {
    if (!(isArrayLike(array))) return array;
    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
    if (sortPredicate.length === 0) { sortPredicate = ['+']; }
    sortPredicate = map(sortPredicate, function(predicate){
      var descending = false, get = predicate || identity;
      if (isString(predicate)) {
        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
          descending = predicate.charAt(0) == '-';
          predicate = predicate.substring(1);
        }
        if ( predicate === '' ) {
          // Effectively no predicate was passed so we compare identity
          return reverseComparator(function(a,b) {
            return compare(a, b);
          }, descending);
        }
        get = $parse(predicate);
        if (get.constant) {
          var key = get();
          return reverseComparator(function(a,b) {
            return compare(a[key], b[key]);
          }, descending);
        }
      }
      return reverseComparator(function(a,b){
        return compare(get(a),get(b));
      }, descending);
    });
    return slice.call(array).sort(reverseComparator(comparator, reverseOrder));

    function comparator(o1, o2){
      for ( var i = 0; i < sortPredicate.length; i++) {
        var comp = sortPredicate[i](o1, o2);
        if (comp !== 0) return comp;
      }
      return 0;
    }
    function reverseComparator(comp, descending) {
      return toBoolean(descending)
          ? function(a,b){return comp(b,a);}
          : comp;
    }
    function compare(v1, v2){
      var t1 = typeof v1;
      var t2 = typeof v2;
      if (t1 == t2) {
        if (isDate(v1) && isDate(v2)) {
          v1 = v1.valueOf();
          v2 = v2.valueOf();
        }
        if (t1 == "string") {
           v1 = v1.toLowerCase();
           v2 = v2.toLowerCase();
        }
        if (v1 === v2) return 0;
        return v1 < v2 ? -1 : 1;
      } else {
        return t1 < t2 ? -1 : 1;
      }
    }
  };
}

function ngDirective(directive) {
  if (isFunction(directive)) {
    directive = {
      link: directive
    };
  }
  directive.restrict = directive.restrict || 'AC';
  return valueFn(directive);
}

/**
 * @ngdoc directive
 * @name a
 * @restrict E
 *
 * @description
 * Modifies the default behavior of the html A tag so that the default action is prevented when
 * the href attribute is empty.
 *
 * This change permits the easy creation of action links with the `ngClick` directive
 * without changing the location or causing page reloads, e.g.:
 * `<a href="" ng-click="list.addItem()">Add Item</a>`
 */
var htmlAnchorDirective = valueFn({
  restrict: 'E',
  compile: function(element, attr) {

    if (msie <= 8) {

      // turn <a href ng-click="..">link</a> into a stylable link in IE
      // but only if it doesn't have name attribute, in which case it's an anchor
      if (!attr.href && !attr.name) {
        attr.$set('href', '');
      }

      // add a comment node to anchors to workaround IE bug that causes element content to be reset
      // to new attribute content if attribute is updated with value containing @ and element also
      // contains value with @
      // see issue #1949
      element.append(document.createComment('IE fix'));
    }

    if (!attr.href && !attr.xlinkHref && !attr.name) {
      return function(scope, element) {
        // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
        var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
                   'xlink:href' : 'href';
        element.on('click', function(event){
          // if we have no href url, then don't navigate anywhere.
          if (!element.attr(href)) {
            event.preventDefault();
          }
        });
      };
    }
  }
});

/**
 * @ngdoc directive
 * @name ngHref
 * @restrict A
 * @priority 99
 *
 * @description
 * Using Angular markup like `{{hash}}` in an href attribute will
 * make the link go to the wrong URL if the user clicks it before
 * Angular has a chance to replace the `{{hash}}` markup with its
 * value. Until Angular replaces the markup the link will be broken
 * and will most likely return a 404 error. The `ngHref` directive
 * solves this problem.
 *
 * The wrong way to write it:
 * ```html
 * <a href="http://www.gravatar.com/avatar/{{hash}}"/>
 * ```
 *
 * The correct way to write it:
 * ```html
 * <a ng-href="http://www.gravatar.com/avatar/{{hash}}"/>
 * ```
 *
 * @element A
 * @param {template} ngHref any string which can contain `{{}}` markup.
 *
 * @example
 * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes
 * in links and their different behaviors:
    <example>
      <file name="index.html">
        <input ng-model="value" /><br />
        <a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br />
        <a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br />
        <a id="link-3" ng-href="/{{'123'}}">link 3</a> (link, reload!)<br />
        <a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br />
        <a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br />
        <a id="link-6" ng-href="{{value}}">link</a> (link, change location)
      </file>
      <file name="protractor.js" type="protractor">
        it('should execute ng-click but not reload when href without value', function() {
          element(by.id('link-1')).click();
          expect(element(by.model('value')).getAttribute('value')).toEqual('1');
          expect(element(by.id('link-1')).getAttribute('href')).toBe('');
        });

        it('should execute ng-click but not reload when href empty string', function() {
          element(by.id('link-2')).click();
          expect(element(by.model('value')).getAttribute('value')).toEqual('2');
          expect(element(by.id('link-2')).getAttribute('href')).toBe('');
        });

        it('should execute ng-click and change url when ng-href specified', function() {
          expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/);

          element(by.id('link-3')).click();

          // At this point, we navigate away from an Angular page, so we need
          // to use browser.driver to get the base webdriver.

          browser.wait(function() {
            return browser.driver.getCurrentUrl().then(function(url) {
              return url.match(/\/123$/);
            });
          }, 5000, 'page should navigate to /123');
        });

        xit('should execute ng-click but not reload when href empty string and name specified', function() {
          element(by.id('link-4')).click();
          expect(element(by.model('value')).getAttribute('value')).toEqual('4');
          expect(element(by.id('link-4')).getAttribute('href')).toBe('');
        });

        it('should execute ng-click but not reload when no href but name specified', function() {
          element(by.id('link-5')).click();
          expect(element(by.model('value')).getAttribute('value')).toEqual('5');
          expect(element(by.id('link-5')).getAttribute('href')).toBe(null);
        });

        it('should only change url when only ng-href', function() {
          element(by.model('value')).clear();
          element(by.model('value')).sendKeys('6');
          expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/);

          element(by.id('link-6')).click();

          // At this point, we navigate away from an Angular page, so we need
          // to use browser.driver to get the base webdriver.
          browser.wait(function() {
            return browser.driver.getCurrentUrl().then(function(url) {
              return url.match(/\/6$/);
            });
          }, 5000, 'page should navigate to /6');
        });
      </file>
    </example>
 */

/**
 * @ngdoc directive
 * @name ngSrc
 * @restrict A
 * @priority 99
 *
 * @description
 * Using Angular markup like `{{hash}}` in a `src` attribute doesn't
 * work right: The browser will fetch from the URL with the literal
 * text `{{hash}}` until Angular replaces the expression inside
 * `{{hash}}`. The `ngSrc` directive solves this problem.
 *
 * The buggy way to write it:
 * ```html
 * <img src="http://www.gravatar.com/avatar/{{hash}}"/>
 * ```
 *
 * The correct way to write it:
 * ```html
 * <img ng-src="http://www.gravatar.com/avatar/{{hash}}"/>
 * ```
 *
 * @element IMG
 * @param {template} ngSrc any string which can contain `{{}}` markup.
 */

/**
 * @ngdoc directive
 * @name ngSrcset
 * @restrict A
 * @priority 99
 *
 * @description
 * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't
 * work right: The browser will fetch from the URL with the literal
 * text `{{hash}}` until Angular replaces the expression inside
 * `{{hash}}`. The `ngSrcset` directive solves this problem.
 *
 * The buggy way to write it:
 * ```html
 * <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
 * ```
 *
 * The correct way to write it:
 * ```html
 * <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
 * ```
 *
 * @element IMG
 * @param {template} ngSrcset any string which can contain `{{}}` markup.
 */

/**
 * @ngdoc directive
 * @name ngDisabled
 * @restrict A
 * @priority 100
 *
 * @description
 *
 * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:
 * ```html
 * <div ng-init="scope = { isDisabled: false }">
 *  <button disabled="{{scope.isDisabled}}">Disabled</button>
 * </div>
 * ```
 *
 * The HTML specification does not require browsers to preserve the values of boolean attributes
 * such as disabled. (Their presence means true and their absence means false.)
 * If we put an Angular interpolation expression into such an attribute then the
 * binding information would be lost when the browser removes the attribute.
 * The `ngDisabled` directive solves this problem for the `disabled` attribute.
 * This complementary directive is not removed by the browser and so provides
 * a permanent reliable place to store the binding information.
 *
 * @example
    <example>
      <file name="index.html">
        Click me to toggle: <input type="checkbox" ng-model="checked"><br/>
        <button ng-model="button" ng-disabled="checked">Button</button>
      </file>
      <file name="protractor.js" type="protractor">
        it('should toggle button', function() {
          expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();
          element(by.model('checked')).click();
          expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();
        });
      </file>
    </example>
 *
 * @element INPUT
 * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,
 *     then special attribute "disabled" will be set on the element
 */


/**
 * @ngdoc directive
 * @name ngChecked
 * @restrict A
 * @priority 100
 *
 * @description
 * The HTML specification does not require browsers to preserve the values of boolean attributes
 * such as checked. (Their presence means true and their absence means false.)
 * If we put an Angular interpolation expression into such an attribute then the
 * binding information would be lost when the browser removes the attribute.
 * The `ngChecked` directive solves this problem for the `checked` attribute.
 * This complementary directive is not removed by the browser and so provides
 * a permanent reliable place to store the binding information.
 * @example
    <example>
      <file name="index.html">
        Check me to check both: <input type="checkbox" ng-model="master"><br/>
        <input id="checkSlave" type="checkbox" ng-checked="master">
      </file>
      <file name="protractor.js" type="protractor">
        it('should check both checkBoxes', function() {
          expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();
          element(by.model('master')).click();
          expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();
        });
      </file>
    </example>
 *
 * @element INPUT
 * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,
 *     then special attribute "checked" will be set on the element
 */


/**
 * @ngdoc directive
 * @name ngReadonly
 * @restrict A
 * @priority 100
 *
 * @description
 * The HTML specification does not require browsers to preserve the values of boolean attributes
 * such as readonly. (Their presence means true and their absence means false.)
 * If we put an Angular interpolation expression into such an attribute then the
 * binding information would be lost when the browser removes the attribute.
 * The `ngReadonly` directive solves this problem for the `readonly` attribute.
 * This complementary directive is not removed by the browser and so provides
 * a permanent reliable place to store the binding information.
 * @example
    <example>
      <file name="index.html">
        Check me to make text readonly: <input type="checkbox" ng-model="checked"><br/>
        <input type="text" ng-readonly="checked" value="I'm Angular"/>
      </file>
      <file name="protractor.js" type="protractor">
        it('should toggle readonly attr', function() {
          expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy();
          element(by.model('checked')).click();
          expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy();
        });
      </file>
    </example>
 *
 * @element INPUT
 * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,
 *     then special attribute "readonly" will be set on the element
 */


/**
 * @ngdoc directive
 * @name ngSelected
 * @restrict A
 * @priority 100
 *
 * @description
 * The HTML specification does not require browsers to preserve the values of boolean attributes
 * such as selected. (Their presence means true and their absence means false.)
 * If we put an Angular interpolation expression into such an attribute then the
 * binding information would be lost when the browser removes the attribute.
 * The `ngSelected` directive solves this problem for the `selected` attribute.
 * This complementary directive is not removed by the browser and so provides
 * a permanent reliable place to store the binding information.
 *
 * @example
    <example>
      <file name="index.html">
        Check me to select: <input type="checkbox" ng-model="selected"><br/>
        <select>
          <option>Hello!</option>
          <option id="greet" ng-selected="selected">Greetings!</option>
        </select>
      </file>
      <file name="protractor.js" type="protractor">
        it('should select Greetings!', function() {
          expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();
          element(by.model('selected')).click();
          expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();
        });
      </file>
    </example>
 *
 * @element OPTION
 * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,
 *     then special attribute "selected" will be set on the element
 */

/**
 * @ngdoc directive
 * @name ngOpen
 * @restrict A
 * @priority 100
 *
 * @description
 * The HTML specification does not require browsers to preserve the values of boolean attributes
 * such as open. (Their presence means true and their absence means false.)
 * If we put an Angular interpolation expression into such an attribute then the
 * binding information would be lost when the browser removes the attribute.
 * The `ngOpen` directive solves this problem for the `open` attribute.
 * This complementary directive is not removed by the browser and so provides
 * a permanent reliable place to store the binding information.
 * @example
     <example>
       <file name="index.html">
         Check me check multiple: <input type="checkbox" ng-model="open"><br/>
         <details id="details" ng-open="open">
            <summary>Show/Hide me</summary>
         </details>
       </file>
       <file name="protractor.js" type="protractor">
         it('should toggle open', function() {
           expect(element(by.id('details')).getAttribute('open')).toBeFalsy();
           element(by.model('open')).click();
           expect(element(by.id('details')).getAttribute('open')).toBeTruthy();
         });
       </file>
     </example>
 *
 * @element DETAILS
 * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,
 *     then special attribute "open" will be set on the element
 */

var ngAttributeAliasDirectives = {};


// boolean attrs are evaluated
forEach(BOOLEAN_ATTR, function(propName, attrName) {
  // binding to multiple is not supported
  if (propName == "multiple") return;

  var normalized = directiveNormalize('ng-' + attrName);
  ngAttributeAliasDirectives[normalized] = function() {
    return {
      priority: 100,
      link: function(scope, element, attr) {
        scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
          attr.$set(attrName, !!value);
        });
      }
    };
  };
});


// ng-src, ng-srcset, ng-href are interpolated
forEach(['src', 'srcset', 'href'], function(attrName) {
  var normalized = directiveNormalize('ng-' + attrName);
  ngAttributeAliasDirectives[normalized] = function() {
    return {
      priority: 99, // it needs to run after the attributes are interpolated
      link: function(scope, element, attr) {
        var propName = attrName,
            name = attrName;

        if (attrName === 'href' &&
            toString.call(element.prop('href')) === '[object SVGAnimatedString]') {
          name = 'xlinkHref';
          attr.$attr[name] = 'xlink:href';
          propName = null;
        }

        attr.$observe(normalized, function(value) {
          if (!value) {
            if (attrName === 'href') {
              attr.$set(name, null);
            }
            return;
          }

          attr.$set(name, value);

          // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
          // to set the property as well to achieve the desired effect.
          // we use attr[attrName] value since $set can sanitize the url.
          if (msie && propName) element.prop(propName, attr[name]);
        });
      }
    };
  };
});

/* global -nullFormCtrl */
var nullFormCtrl = {
  $addControl: noop,
  $removeControl: noop,
  $setValidity: noop,
  $setDirty: noop,
  $setPristine: noop
};

/**
 * @ngdoc type
 * @name form.FormController
 *
 * @property {boolean} $pristine True if user has not interacted with the form yet.
 * @property {boolean} $dirty True if user has already interacted with the form.
 * @property {boolean} $valid True if all of the containing forms and controls are valid.
 * @property {boolean} $invalid True if at least one containing control or form is invalid.
 *
 * @property {Object} $error Is an object hash, containing references to all invalid controls or
 *  forms, where:
 *
 *  - keys are validation tokens (error names),
 *  - values are arrays of controls or forms that are invalid for given error name.
 *
 *
 *  Built-in validation tokens:
 *
 *  - `email`
 *  - `max`
 *  - `maxlength`
 *  - `min`
 *  - `minlength`
 *  - `number`
 *  - `pattern`
 *  - `required`
 *  - `url`
 *
 * @description
 * `FormController` keeps track of all its controls and nested forms as well as the state of them,
 * such as being valid/invalid or dirty/pristine.
 *
 * Each {@link ng.directive:form form} directive creates an instance
 * of `FormController`.
 *
 */
//asks for $scope to fool the BC controller module
FormController.$inject = ['$element', '$attrs', '$scope', '$animate'];
function FormController(element, attrs, $scope, $animate) {
  var form = this,
      parentForm = element.parent().controller('form') || nullFormCtrl,
      invalidCount = 0, // used to easily determine if we are valid
      errors = form.$error = {},
      controls = [];

  // init state
  form.$name = attrs.name || attrs.ngForm;
  form.$dirty = false;
  form.$pristine = true;
  form.$valid = true;
  form.$invalid = false;

  parentForm.$addControl(form);

  // Setup initial state of the control
  element.addClass(PRISTINE_CLASS);
  toggleValidCss(true);

  // convenience method for easy toggling of classes
  function toggleValidCss(isValid, validationErrorKey) {
    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
    $animate.setClass(element,
      (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey,
      (isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);
  }

  /**
   * @ngdoc method
   * @name form.FormController#$addControl
   *
   * @description
   * Register a control with the form.
   *
   * Input elements using ngModelController do this automatically when they are linked.
   */
  form.$addControl = function(control) {
    // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
    // and not added to the scope.  Now we throw an error.
    assertNotHasOwnProperty(control.$name, 'input');
    controls.push(control);

    if (control.$name) {
      form[control.$name] = control;
    }
  };

  /**
   * @ngdoc method
   * @name form.FormController#$removeControl
   *
   * @description
   * Deregister a control from the form.
   *
   * Input elements using ngModelController do this automatically when they are destroyed.
   */
  form.$removeControl = function(control) {
    if (control.$name && form[control.$name] === control) {
      delete form[control.$name];
    }
    forEach(errors, function(queue, validationToken) {
      form.$setValidity(validationToken, true, control);
    });

    arrayRemove(controls, control);
  };

  /**
   * @ngdoc method
   * @name form.FormController#$setValidity
   *
   * @description
   * Sets the validity of a form control.
   *
   * This method will also propagate to parent forms.
   */
  form.$setValidity = function(validationToken, isValid, control) {
    var queue = errors[validationToken];

    if (isValid) {
      if (queue) {
        arrayRemove(queue, control);
        if (!queue.length) {
          invalidCount--;
          if (!invalidCount) {
            toggleValidCss(isValid);
            form.$valid = true;
            form.$invalid = false;
          }
          errors[validationToken] = false;
          toggleValidCss(true, validationToken);
          parentForm.$setValidity(validationToken, true, form);
        }
      }

    } else {
      if (!invalidCount) {
        toggleValidCss(isValid);
      }
      if (queue) {
        if (includes(queue, control)) return;
      } else {
        errors[validationToken] = queue = [];
        invalidCount++;
        toggleValidCss(false, validationToken);
        parentForm.$setValidity(validationToken, false, form);
      }
      queue.push(control);

      form.$valid = false;
      form.$invalid = true;
    }
  };

  /**
   * @ngdoc method
   * @name form.FormController#$setDirty
   *
   * @description
   * Sets the form to a dirty state.
   *
   * This method can be called to add the 'ng-dirty' class and set the form to a dirty
   * state (ng-dirty class). This method will also propagate to parent forms.
   */
  form.$setDirty = function() {
    $animate.removeClass(element, PRISTINE_CLASS);
    $animate.addClass(element, DIRTY_CLASS);
    form.$dirty = true;
    form.$pristine = false;
    parentForm.$setDirty();
  };

  /**
   * @ngdoc method
   * @name form.FormController#$setPristine
   *
   * @description
   * Sets the form to its pristine state.
   *
   * This method can be called to remove the 'ng-dirty' class and set the form to its pristine
   * state (ng-pristine class). This method will also propagate to all the controls contained
   * in this form.
   *
   * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
   * saving or resetting it.
   */
  form.$setPristine = function () {
    $animate.removeClass(element, DIRTY_CLASS);
    $animate.addClass(element, PRISTINE_CLASS);
    form.$dirty = false;
    form.$pristine = true;
    forEach(controls, function(control) {
      control.$setPristine();
    });
  };
}


/**
 * @ngdoc directive
 * @name ngForm
 * @restrict EAC
 *
 * @description
 * Nestable alias of {@link ng.directive:form `form`} directive. HTML
 * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
 * sub-group of controls needs to be determined.
 *
 * Note: the purpose of `ngForm` is to group controls,
 * but not to be a replacement for the `<form>` tag with all of its capabilities
 * (e.g. posting to the server, ...).
 *
 * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
 *                       related scope, under this name.
 *
 */

 /**
 * @ngdoc directive
 * @name form
 * @restrict E
 *
 * @description
 * Directive that instantiates
 * {@link form.FormController FormController}.
 *
 * If the `name` attribute is specified, the form controller is published onto the current scope under
 * this name.
 *
 * # Alias: {@link ng.directive:ngForm `ngForm`}
 *
 * In Angular forms can be nested. This means that the outer form is valid when all of the child
 * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
 * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
 * `<form>` but can be nested.  This allows you to have nested forms, which is very useful when
 * using Angular validation directives in forms that are dynamically generated using the
 * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
 * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
 * `ngForm` directive and nest these in an outer `form` element.
 *
 *
 * # CSS classes
 *  - `ng-valid` is set if the form is valid.
 *  - `ng-invalid` is set if the form is invalid.
 *  - `ng-pristine` is set if the form is pristine.
 *  - `ng-dirty` is set if the form is dirty.
 *
 * Keep in mind that ngAnimate can detect each of these classes when added and removed.
 *
 *
 * # Submitting a form and preventing the default action
 *
 * Since the role of forms in client-side Angular applications is different than in classical
 * roundtrip apps, it is desirable for the browser not to translate the form submission into a full
 * page reload that sends the data to the server. Instead some javascript logic should be triggered
 * to handle the form submission in an application-specific way.
 *
 * For this reason, Angular prevents the default action (form submission to the server) unless the
 * `<form>` element has an `action` attribute specified.
 *
 * You can use one of the following two ways to specify what javascript method should be called when
 * a form is submitted:
 *
 * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element
 * - {@link ng.directive:ngClick ngClick} directive on the first
  *  button or input field of type submit (input[type=submit])
 *
 * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}
 * or {@link ng.directive:ngClick ngClick} directives.
 * This is because of the following form submission rules in the HTML specification:
 *
 * - If a form has only one input field then hitting enter in this field triggers form submit
 * (`ngSubmit`)
 * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter
 * doesn't trigger submit
 * - if a form has one or more input fields and one or more buttons or input[type=submit] then
 * hitting enter in any of the input fields will trigger the click handler on the *first* button or
 * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)
 *
 *
 * ## Animation Hooks
 *
 * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.
 * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any
 * other validations that are performed within the form. Animations in ngForm are similar to how
 * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well
 * as JS animations.
 *
 * The following example shows a simple way to utilize CSS transitions to style a form element
 * that has been rendered as invalid after it has been validated:
 *
 * <pre>
 * //be sure to include ngAnimate as a module to hook into more
 * //advanced animations
 * .my-form {
 *   transition:0.5s linear all;
 *   background: white;
 * }
 * .my-form.ng-invalid {
 *   background: red;
 *   color:white;
 * }
 * </pre>
 *
 * @example
    <example deps="angular-animate.js" animations="true" fixBase="true" module="formExample">
      <file name="index.html">
       <script>
         angular.module('formExample', [])
           .controller('FormController', ['$scope', function($scope) {
             $scope.userType = 'guest';
           }]);
       </script>
       <style>
        .my-form {
          -webkit-transition:all linear 0.5s;
          transition:all linear 0.5s;
          background: transparent;
        }
        .my-form.ng-invalid {
          background: red;
        }
       </style>
       <form name="myForm" ng-controller="FormController" class="my-form">
         userType: <input name="input" ng-model="userType" required>
         <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
         <tt>userType = {{userType}}</tt><br>
         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>
         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>
         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>
         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
        </form>
      </file>
      <file name="protractor.js" type="protractor">
        it('should initialize to model', function() {
          var userType = element(by.binding('userType'));
          var valid = element(by.binding('myForm.input.$valid'));

          expect(userType.getText()).toContain('guest');
          expect(valid.getText()).toContain('true');
        });

        it('should be invalid if empty', function() {
          var userType = element(by.binding('userType'));
          var valid = element(by.binding('myForm.input.$valid'));
          var userInput = element(by.model('userType'));

          userInput.clear();
          userInput.sendKeys('');

          expect(userType.getText()).toEqual('userType =');
          expect(valid.getText()).toContain('false');
        });
      </file>
    </example>
 *
 * @param {string=} name Name of the form. If specified, the form controller will be published into
 *                       related scope, under this name.
 */
var formDirectiveFactory = function(isNgForm) {
  return ['$timeout', function($timeout) {
    var formDirective = {
      name: 'form',
      restrict: isNgForm ? 'EAC' : 'E',
      controller: FormController,
      compile: function() {
        return {
          pre: function(scope, formElement, attr, controller) {
            if (!attr.action) {
              // we can't use jq events because if a form is destroyed during submission the default
              // action is not prevented. see #1238
              //
              // IE 9 is not affected because it doesn't fire a submit event and try to do a full
              // page reload if the form was destroyed by submission of the form via a click handler
              // on a button in the form. Looks like an IE9 specific bug.
              var preventDefaultListener = function(event) {
                event.preventDefault
                  ? event.preventDefault()
                  : event.returnValue = false; // IE
              };

              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);

              // unregister the preventDefault listener so that we don't not leak memory but in a
              // way that will achieve the prevention of the default action.
              formElement.on('$destroy', function() {
                $timeout(function() {
                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);
                }, 0, false);
              });
            }

            var parentFormCtrl = formElement.parent().controller('form'),
                alias = attr.name || attr.ngForm;

            if (alias) {
              setter(scope, alias, controller, alias);
            }
            if (parentFormCtrl) {
              formElement.on('$destroy', function() {
                parentFormCtrl.$removeControl(controller);
                if (alias) {
                  setter(scope, alias, undefined, alias);
                }
                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
              });
            }
          }
        };
      }
    };

    return formDirective;
  }];
};

var formDirective = formDirectiveFactory();
var ngFormDirective = formDirectiveFactory(true);

/* global VALID_CLASS: true,
    INVALID_CLASS: true,
    PRISTINE_CLASS: true,
    DIRTY_CLASS: true
*/

var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;

var inputType = {

  /**
   * @ngdoc input
   * @name input[text]
   *
   * @description
   * Standard HTML text input with angular data binding, inherited by most of the `input` elements.
   *
   * *NOTE* Not every feature offered is available for all input types.
   *
   * @param {string} ngModel Assignable angular expression to data-bind to.
   * @param {string=} name Property name of the form under which the control is published.
   * @param {string=} required Adds `required` validation error key if the value is not entered.
   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
   *    `required` when you want to data-bind to the `required` attribute.
   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
   *    minlength.
   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
   *    maxlength.
   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
   *    patterns defined as scope expressions.
   * @param {string=} ngChange Angular expression to be executed when input changes due to user
   *    interaction with the input element.
   * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
   *    This parameter is ignored for input[type=password] controls, which will never trim the
   *    input.
   *
   * @example
      <example name="text-input-directive" module="textInputExample">
        <file name="index.html">
         <script>
           angular.module('textInputExample', [])
             .controller('ExampleController', ['$scope', function($scope) {
               $scope.text = 'guest';
               $scope.word = /^\s*\w*\s*$/;
             }]);
         </script>
         <form name="myForm" ng-controller="ExampleController">
           Single word: <input type="text" name="input" ng-model="text"
                               ng-pattern="word" required ng-trim="false">
           <span class="error" ng-show="myForm.input.$error.required">
             Required!</span>
           <span class="error" ng-show="myForm.input.$error.pattern">
             Single word only!</span>

           <tt>text = {{text}}</tt><br/>
           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
          </form>
        </file>
        <file name="protractor.js" type="protractor">
          var text = element(by.binding('text'));
          var valid = element(by.binding('myForm.input.$valid'));
          var input = element(by.model('text'));

          it('should initialize to model', function() {
            expect(text.getText()).toContain('guest');
            expect(valid.getText()).toContain('true');
          });

          it('should be invalid if empty', function() {
            input.clear();
            input.sendKeys('');

            expect(text.getText()).toEqual('text =');
            expect(valid.getText()).toContain('false');
          });

          it('should be invalid if multi word', function() {
            input.clear();
            input.sendKeys('hello world');

            expect(valid.getText()).toContain('false');
          });
        </file>
      </example>
   */
  'text': textInputType,


  /**
   * @ngdoc input
   * @name input[number]
   *
   * @description
   * Text input with number validation and transformation. Sets the `number` validation
   * error if not a valid number.
   *
   * @param {string} ngModel Assignable angular expression to data-bind to.
   * @param {string=} name Property name of the form under which the control is published.
   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
   * @param {string=} required Sets `required` validation error key if the value is not entered.
   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
   *    `required` when you want to data-bind to the `required` attribute.
   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
   *    minlength.
   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
   *    maxlength.
   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
   *    patterns defined as scope expressions.
   * @param {string=} ngChange Angular expression to be executed when input changes due to user
   *    interaction with the input element.
   *
   * @example
      <example name="number-input-directive" module="numberExample">
        <file name="index.html">
         <script>
           angular.module('numberExample', [])
             .controller('ExampleController', ['$scope', function($scope) {
               $scope.value = 12;
             }]);
         </script>
         <form name="myForm" ng-controller="ExampleController">
           Number: <input type="number" name="input" ng-model="value"
                          min="0" max="99" required>
           <span class="error" ng-show="myForm.input.$error.required">
             Required!</span>
           <span class="error" ng-show="myForm.input.$error.number">
             Not valid number!</span>
           <tt>value = {{value}}</tt><br/>
           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
          </form>
        </file>
        <file name="protractor.js" type="protractor">
          var value = element(by.binding('value'));
          var valid = element(by.binding('myForm.input.$valid'));
          var input = element(by.model('value'));

          it('should initialize to model', function() {
            expect(value.getText()).toContain('12');
            expect(valid.getText()).toContain('true');
          });

          it('should be invalid if empty', function() {
            input.clear();
            input.sendKeys('');
            expect(value.getText()).toEqual('value =');
            expect(valid.getText()).toContain('false');
          });

          it('should be invalid if over max', function() {
            input.clear();
            input.sendKeys('123');
            expect(value.getText()).toEqual('value =');
            expect(valid.getText()).toContain('false');
          });
        </file>
      </example>
   */
  'number': numberInputType,


  /**
   * @ngdoc input
   * @name input[url]
   *
   * @description
   * Text input with URL validation. Sets the `url` validation error key if the content is not a
   * valid URL.
   *
   * @param {string} ngModel Assignable angular expression to data-bind to.
   * @param {string=} name Property name of the form under which the control is published.
   * @param {string=} required Sets `required` validation error key if the value is not entered.
   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
   *    `required` when you want to data-bind to the `required` attribute.
   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
   *    minlength.
   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
   *    maxlength.
   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
   *    patterns defined as scope expressions.
   * @param {string=} ngChange Angular expression to be executed when input changes due to user
   *    interaction with the input element.
   *
   * @example
      <example name="url-input-directive" module="urlExample">
        <file name="index.html">
         <script>
           angular.module('urlExample', [])
             .controller('ExampleController', ['$scope', function($scope) {
               $scope.text = 'http://google.com';
             }]);
         </script>
         <form name="myForm" ng-controller="ExampleController">
           URL: <input type="url" name="input" ng-model="text" required>
           <span class="error" ng-show="myForm.input.$error.required">
             Required!</span>
           <span class="error" ng-show="myForm.input.$error.url">
             Not valid url!</span>
           <tt>text = {{text}}</tt><br/>
           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>
          </form>
        </file>
        <file name="protractor.js" type="protractor">
          var text = element(by.binding('text'));
          var valid = element(by.binding('myForm.input.$valid'));
          var input = element(by.model('text'));

          it('should initialize to model', function() {
            expect(text.getText()).toContain('http://google.com');
            expect(valid.getText()).toContain('true');
          });

          it('should be invalid if empty', function() {
            input.clear();
            input.sendKeys('');

            expect(text.getText()).toEqual('text =');
            expect(valid.getText()).toContain('false');
          });

          it('should be invalid if not url', function() {
            input.clear();
            input.sendKeys('box');

            expect(valid.getText()).toContain('false');
          });
        </file>
      </example>
   */
  'url': urlInputType,


  /**
   * @ngdoc input
   * @name input[email]
   *
   * @description
   * Text input with email validation. Sets the `email` validation error key if not a valid email
   * address.
   *
   * @param {string} ngModel Assignable angular expression to data-bind to.
   * @param {string=} name Property name of the form under which the control is published.
   * @param {string=} required Sets `required` validation error key if the value is not entered.
   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
   *    `required` when you want to data-bind to the `required` attribute.
   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
   *    minlength.
   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
   *    maxlength.
   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
   *    patterns defined as scope expressions.
   * @param {string=} ngChange Angular expression to be executed when input changes due to user
   *    interaction with the input element.
   *
   * @example
      <example name="email-input-directive" module="emailExample">
        <file name="index.html">
         <script>
           angular.module('emailExample', [])
             .controller('ExampleController', ['$scope', function($scope) {
               $scope.text = 'me@example.com';
             }]);
         </script>
           <form name="myForm" ng-controller="ExampleController">
             Email: <input type="email" name="input" ng-model="text" required>
             <span class="error" ng-show="myForm.input.$error.required">
               Required!</span>
             <span class="error" ng-show="myForm.input.$error.email">
               Not valid email!</span>
             <tt>text = {{text}}</tt><br/>
             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>
           </form>
         </file>
        <file name="protractor.js" type="protractor">
          var text = element(by.binding('text'));
          var valid = element(by.binding('myForm.input.$valid'));
          var input = element(by.model('text'));

          it('should initialize to model', function() {
            expect(text.getText()).toContain('me@example.com');
            expect(valid.getText()).toContain('true');
          });

          it('should be invalid if empty', function() {
            input.clear();
            input.sendKeys('');
            expect(text.getText()).toEqual('text =');
            expect(valid.getText()).toContain('false');
          });

          it('should be invalid if not email', function() {
            input.clear();
            input.sendKeys('xxx');

            expect(valid.getText()).toContain('false');
          });
        </file>
      </example>
   */
  'email': emailInputType,


  /**
   * @ngdoc input
   * @name input[radio]
   *
   * @description
   * HTML radio button.
   *
   * @param {string} ngModel Assignable angular expression to data-bind to.
   * @param {string} value The value to which the expression should be set when selected.
   * @param {string=} name Property name of the form under which the control is published.
   * @param {string=} ngChange Angular expression to be executed when input changes due to user
   *    interaction with the input element.
   * @param {string} ngValue Angular expression which sets the value to which the expression should
   *    be set when selected.
   *
   * @example
      <example name="radio-input-directive" module="radioExample">
        <file name="index.html">
         <script>
           angular.module('radioExample', [])
             .controller('ExampleController', ['$scope', function($scope) {
               $scope.color = 'blue';
               $scope.specialValue = {
                 "id": "12345",
                 "value": "green"
               };
             }]);
         </script>
         <form name="myForm" ng-controller="ExampleController">
           <input type="radio" ng-model="color" value="red">  Red <br/>
           <input type="radio" ng-model="color" ng-value="specialValue"> Green <br/>
           <input type="radio" ng-model="color" value="blue"> Blue <br/>
           <tt>color = {{color | json}}</tt><br/>
          </form>
          Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`.
        </file>
        <file name="protractor.js" type="protractor">
          it('should change state', function() {
            var color = element(by.binding('color'));

            expect(color.getText()).toContain('blue');

            element.all(by.model('color')).get(0).click();

            expect(color.getText()).toContain('red');
          });
        </file>
      </example>
   */
  'radio': radioInputType,


  /**
   * @ngdoc input
   * @name input[checkbox]
   *
   * @description
   * HTML checkbox.
   *
   * @param {string} ngModel Assignable angular expression to data-bind to.
   * @param {string=} name Property name of the form under which the control is published.
   * @param {string=} ngTrueValue The value to which the expression should be set when selected.
   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.
   * @param {string=} ngChange Angular expression to be executed when input changes due to user
   *    interaction with the input element.
   *
   * @example
      <example name="checkbox-input-directive" module="checkboxExample">
        <file name="index.html">
         <script>
           angular.module('checkboxExample', [])
             .controller('ExampleController', ['$scope', function($scope) {
               $scope.value1 = true;
               $scope.value2 = 'YES'
             }]);
         </script>
         <form name="myForm" ng-controller="ExampleController">
           Value1: <input type="checkbox" ng-model="value1"> <br/>
           Value2: <input type="checkbox" ng-model="value2"
                          ng-true-value="YES" ng-false-value="NO"> <br/>
           <tt>value1 = {{value1}}</tt><br/>
           <tt>value2 = {{value2}}</tt><br/>
          </form>
        </file>
        <file name="protractor.js" type="protractor">
          it('should change state', function() {
            var value1 = element(by.binding('value1'));
            var value2 = element(by.binding('value2'));

            expect(value1.getText()).toContain('true');
            expect(value2.getText()).toContain('YES');

            element(by.model('value1')).click();
            element(by.model('value2')).click();

            expect(value1.getText()).toContain('false');
            expect(value2.getText()).toContain('NO');
          });
        </file>
      </example>
   */
  'checkbox': checkboxInputType,

  'hidden': noop,
  'button': noop,
  'submit': noop,
  'reset': noop,
  'file': noop
};

// A helper function to call $setValidity and return the value / undefined,
// a pattern that is repeated a lot in the input validation logic.
function validate(ctrl, validatorName, validity, value){
  ctrl.$setValidity(validatorName, validity);
  return validity ? value : undefined;
}

function testFlags(validity, flags) {
  var i, flag;
  if (flags) {
    for (i=0; i<flags.length; ++i) {
      flag = flags[i];
      if (validity[flag]) {
        return true;
      }
    }
  }
  return false;
}

// Pass validity so that behaviour can be mocked easier.
function addNativeHtml5Validators(ctrl, validatorName, badFlags, ignoreFlags, validity) {
  if (isObject(validity)) {
    ctrl.$$hasNativeValidators = true;
    var validator = function(value) {
      // Don't overwrite previous validation, don't consider valueMissing to apply (ng-required can
      // perform the required validation)
      if (!ctrl.$error[validatorName] &&
          !testFlags(validity, ignoreFlags) &&
          testFlags(validity, badFlags)) {
        ctrl.$setValidity(validatorName, false);
        return;
      }
      return value;
    };
    ctrl.$parsers.push(validator);
  }
}

function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
  var validity = element.prop(VALIDITY_STATE_PROPERTY);
  var placeholder = element[0].placeholder, noevent = {};
  var type = lowercase(element[0].type);
  ctrl.$$validityState = validity;

  // In composition mode, users are still inputing intermediate text buffer,
  // hold the listener until composition is done.
  // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
  if (!$sniffer.android) {
    var composing = false;

    element.on('compositionstart', function(data) {
      composing = true;
    });

    element.on('compositionend', function() {
      composing = false;
      listener();
    });
  }

  var listener = function(ev) {
    if (composing) return;
    var value = element.val();

    // IE (11 and under) seem to emit an 'input' event if the placeholder value changes.
    // We don't want to dirty the value when this happens, so we abort here. Unfortunately,
    // IE also sends input events for other non-input-related things, (such as focusing on a
    // form control), so this change is not entirely enough to solve this.
    if (msie && (ev || noevent).type === 'input' && element[0].placeholder !== placeholder) {
      placeholder = element[0].placeholder;
      return;
    }

    // By default we will trim the value
    // If the attribute ng-trim exists we will avoid trimming
    // If input type is 'password', the value is never trimmed
    if (type !== 'password' && (toBoolean(attr.ngTrim || 'T'))) {
      value = trim(value);
    }

    // If a control is suffering from bad input, browsers discard its value, so it may be
    // necessary to revalidate even if the control's value is the same empty value twice in
    // a row.
    var revalidate = validity && ctrl.$$hasNativeValidators;
    if (ctrl.$viewValue !== value || (value === '' && revalidate)) {
      if (scope.$root.$$phase) {
        ctrl.$setViewValue(value);
      } else {
        scope.$apply(function() {
          ctrl.$setViewValue(value);
        });
      }
    }
  };

  // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the
  // input event on backspace, delete or cut
  if ($sniffer.hasEvent('input')) {
    element.on('input', listener);
  } else {
    var timeout;

    var deferListener = function() {
      if (!timeout) {
        timeout = $browser.defer(function() {
          listener();
          timeout = null;
        });
      }
    };

    element.on('keydown', function(event) {
      var key = event.keyCode;

      // ignore
      //    command            modifiers                   arrows
      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;

      deferListener();
    });

    // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
    if ($sniffer.hasEvent('paste')) {
      element.on('paste cut', deferListener);
    }
  }

  // if user paste into input using mouse on older browser
  // or form autocomplete on newer browser, we need "change" event to catch it
  element.on('change', listener);

  ctrl.$render = function() {
    element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);
  };

  // pattern validator
  var pattern = attr.ngPattern,
      patternValidator,
      match;

  if (pattern) {
    var validateRegex = function(regexp, value) {
      return validate(ctrl, 'pattern', ctrl.$isEmpty(value) || regexp.test(value), value);
    };
    match = pattern.match(/^\/(.*)\/([gim]*)$/);
    if (match) {
      pattern = new RegExp(match[1], match[2]);
      patternValidator = function(value) {
        return validateRegex(pattern, value);
      };
    } else {
      patternValidator = function(value) {
        var patternObj = scope.$eval(pattern);

        if (!patternObj || !patternObj.test) {
          throw minErr('ngPattern')('noregexp',
            'Expected {0} to be a RegExp but was {1}. Element: {2}', pattern,
            patternObj, startingTag(element));
        }
        return validateRegex(patternObj, value);
      };
    }

    ctrl.$formatters.push(patternValidator);
    ctrl.$parsers.push(patternValidator);
  }

  // min length validator
  if (attr.ngMinlength) {
    var minlength = int(attr.ngMinlength);
    var minLengthValidator = function(value) {
      return validate(ctrl, 'minlength', ctrl.$isEmpty(value) || value.length >= minlength, value);
    };

    ctrl.$parsers.push(minLengthValidator);
    ctrl.$formatters.push(minLengthValidator);
  }

  // max length validator
  if (attr.ngMaxlength) {
    var maxlength = int(attr.ngMaxlength);
    var maxLengthValidator = function(value) {
      return validate(ctrl, 'maxlength', ctrl.$isEmpty(value) || value.length <= maxlength, value);
    };

    ctrl.$parsers.push(maxLengthValidator);
    ctrl.$formatters.push(maxLengthValidator);
  }
}

var numberBadFlags = ['badInput'];

function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
  textInputType(scope, element, attr, ctrl, $sniffer, $browser);

  ctrl.$parsers.push(function(value) {
    var empty = ctrl.$isEmpty(value);
    if (empty || NUMBER_REGEXP.test(value)) {
      ctrl.$setValidity('number', true);
      return value === '' ? null : (empty ? value : parseFloat(value));
    } else {
      ctrl.$setValidity('number', false);
      return undefined;
    }
  });

  addNativeHtml5Validators(ctrl, 'number', numberBadFlags, null, ctrl.$$validityState);

  ctrl.$formatters.push(function(value) {
    return ctrl.$isEmpty(value) ? '' : '' + value;
  });

  if (attr.min) {
    var minValidator = function(value) {
      var min = parseFloat(attr.min);
      return validate(ctrl, 'min', ctrl.$isEmpty(value) || value >= min, value);
    };

    ctrl.$parsers.push(minValidator);
    ctrl.$formatters.push(minValidator);
  }

  if (attr.max) {
    var maxValidator = function(value) {
      var max = parseFloat(attr.max);
      return validate(ctrl, 'max', ctrl.$isEmpty(value) || value <= max, value);
    };

    ctrl.$parsers.push(maxValidator);
    ctrl.$formatters.push(maxValidator);
  }

  ctrl.$formatters.push(function(value) {
    return validate(ctrl, 'number', ctrl.$isEmpty(value) || isNumber(value), value);
  });
}

function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
  textInputType(scope, element, attr, ctrl, $sniffer, $browser);

  var urlValidator = function(value) {
    return validate(ctrl, 'url', ctrl.$isEmpty(value) || URL_REGEXP.test(value), value);
  };

  ctrl.$formatters.push(urlValidator);
  ctrl.$parsers.push(urlValidator);
}

function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
  textInputType(scope, element, attr, ctrl, $sniffer, $browser);

  var emailValidator = function(value) {
    return validate(ctrl, 'email', ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value), value);
  };

  ctrl.$formatters.push(emailValidator);
  ctrl.$parsers.push(emailValidator);
}

function radioInputType(scope, element, attr, ctrl) {
  // make the name unique, if not defined
  if (isUndefined(attr.name)) {
    element.attr('name', nextUid());
  }

  element.on('click', function() {
    if (element[0].checked) {
      scope.$apply(function() {
        ctrl.$setViewValue(attr.value);
      });
    }
  });

  ctrl.$render = function() {
    var value = attr.value;
    element[0].checked = (value == ctrl.$viewValue);
  };

  attr.$observe('value', ctrl.$render);
}

function checkboxInputType(scope, element, attr, ctrl) {
  var trueValue = attr.ngTrueValue,
      falseValue = attr.ngFalseValue;

  if (!isString(trueValue)) trueValue = true;
  if (!isString(falseValue)) falseValue = false;

  element.on('click', function() {
    scope.$apply(function() {
      ctrl.$setViewValue(element[0].checked);
    });
  });

  ctrl.$render = function() {
    element[0].checked = ctrl.$viewValue;
  };

  // Override the standard `$isEmpty` because a value of `false` means empty in a checkbox.
  ctrl.$isEmpty = function(value) {
    return value !== trueValue;
  };

  ctrl.$formatters.push(function(value) {
    return value === trueValue;
  });

  ctrl.$parsers.push(function(value) {
    return value ? trueValue : falseValue;
  });
}


/**
 * @ngdoc directive
 * @name textarea
 * @restrict E
 *
 * @description
 * HTML textarea element control with angular data-binding. The data-binding and validation
 * properties of this element are exactly the same as those of the
 * {@link ng.directive:input input element}.
 *
 * @param {string} ngModel Assignable angular expression to data-bind to.
 * @param {string=} name Property name of the form under which the control is published.
 * @param {string=} required Sets `required` validation error key if the value is not entered.
 * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
 *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
 *    `required` when you want to data-bind to the `required` attribute.
 * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 *    minlength.
 * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 *    maxlength.
 * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
 *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
 *    patterns defined as scope expressions.
 * @param {string=} ngChange Angular expression to be executed when input changes due to user
 *    interaction with the input element.
 * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
 */


/**
 * @ngdoc directive
 * @name input
 * @restrict E
 *
 * @description
 * HTML input element control with angular data-binding. Input control follows HTML5 input types
 * and polyfills the HTML5 validation behavior for older browsers.
 *
 * *NOTE* Not every feature offered is available for all input types.
 *
 * @param {string} ngModel Assignable angular expression to data-bind to.
 * @param {string=} name Property name of the form under which the control is published.
 * @param {string=} required Sets `required` validation error key if the value is not entered.
 * @param {boolean=} ngRequired Sets `required` attribute if set to true
 * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 *    minlength.
 * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 *    maxlength.
 * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
 *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
 *    patterns defined as scope expressions.
 * @param {string=} ngChange Angular expression to be executed when input changes due to user
 *    interaction with the input element.
 * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
 *    This parameter is ignored for input[type=password] controls, which will never trim the
 *    input.
 *
 * @example
    <example name="input-directive" module="inputExample">
      <file name="index.html">
       <script>
          angular.module('inputExample', [])
            .controller('ExampleController', ['$scope', function($scope) {
              $scope.user = {name: 'guest', last: 'visitor'};
            }]);
       </script>
       <div ng-controller="ExampleController">
         <form name="myForm">
           User name: <input type="text" name="userName" ng-model="user.name" required>
           <span class="error" ng-show="myForm.userName.$error.required">
             Required!</span><br>
           Last name: <input type="text" name="lastName" ng-model="user.last"
             ng-minlength="3" ng-maxlength="10">
           <span class="error" ng-show="myForm.lastName.$error.minlength">
             Too short!</span>
           <span class="error" ng-show="myForm.lastName.$error.maxlength">
             Too long!</span><br>
         </form>
         <hr>
         <tt>user = {{user}}</tt><br/>
         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>
         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>
         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>
         <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>
         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>
         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>
         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>
       </div>
      </file>
      <file name="protractor.js" type="protractor">
        var user = element(by.binding('{{user}}'));
        var userNameValid = element(by.binding('myForm.userName.$valid'));
        var lastNameValid = element(by.binding('myForm.lastName.$valid'));
        var lastNameError = element(by.binding('myForm.lastName.$error'));
        var formValid = element(by.binding('myForm.$valid'));
        var userNameInput = element(by.model('user.name'));
        var userLastInput = element(by.model('user.last'));

        it('should initialize to model', function() {
          expect(user.getText()).toContain('{"name":"guest","last":"visitor"}');
          expect(userNameValid.getText()).toContain('true');
          expect(formValid.getText()).toContain('true');
        });

        it('should be invalid if empty when required', function() {
          userNameInput.clear();
          userNameInput.sendKeys('');

          expect(user.getText()).toContain('{"last":"visitor"}');
          expect(userNameValid.getText()).toContain('false');
          expect(formValid.getText()).toContain('false');
        });

        it('should be valid if empty when min length is set', function() {
          userLastInput.clear();
          userLastInput.sendKeys('');

          expect(user.getText()).toContain('{"name":"guest","last":""}');
          expect(lastNameValid.getText()).toContain('true');
          expect(formValid.getText()).toContain('true');
        });

        it('should be invalid if less than required min length', function() {
          userLastInput.clear();
          userLastInput.sendKeys('xx');

          expect(user.getText()).toContain('{"name":"guest"}');
          expect(lastNameValid.getText()).toContain('false');
          expect(lastNameError.getText()).toContain('minlength');
          expect(formValid.getText()).toContain('false');
        });

        it('should be invalid if longer than max length', function() {
          userLastInput.clear();
          userLastInput.sendKeys('some ridiculously long name');

          expect(user.getText()).toContain('{"name":"guest"}');
          expect(lastNameValid.getText()).toContain('false');
          expect(lastNameError.getText()).toContain('maxlength');
          expect(formValid.getText()).toContain('false');
        });
      </file>
    </example>
 */
var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {
  return {
    restrict: 'E',
    require: '?ngModel',
    link: function(scope, element, attr, ctrl) {
      if (ctrl) {
        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,
                                                            $browser);
      }
    }
  };
}];

var VALID_CLASS = 'ng-valid',
    INVALID_CLASS = 'ng-invalid',
    PRISTINE_CLASS = 'ng-pristine',
    DIRTY_CLASS = 'ng-dirty';

/**
 * @ngdoc type
 * @name ngModel.NgModelController
 *
 * @property {string} $viewValue Actual string value in the view.
 * @property {*} $modelValue The value in the model, that the control is bound to.
 * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
       the control reads value from the DOM.  Each function is called, in turn, passing the value
       through to the next. The last return value is used to populate the model.
       Used to sanitize / convert the value as well as validation. For validation,
       the parsers should update the validity state using
       {@link ngModel.NgModelController#$setValidity $setValidity()},
       and return `undefined` for invalid values.

 *
 * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
       the model value changes. Each function is called, in turn, passing the value through to the
       next. Used to format / convert values for display in the control and validation.
 * ```js
 * function formatter(value) {
 *   if (value) {
 *     return value.toUpperCase();
 *   }
 * }
 * ngModel.$formatters.push(formatter);
 * ```
 *
 * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
 *     view value has changed. It is called with no arguments, and its return value is ignored.
 *     This can be used in place of additional $watches against the model value.
 *
 * @property {Object} $error An object hash with all errors as keys.
 *
 * @property {boolean} $pristine True if user has not interacted with the control yet.
 * @property {boolean} $dirty True if user has already interacted with the control.
 * @property {boolean} $valid True if there is no error.
 * @property {boolean} $invalid True if at least one error on the control.
 *
 * @description
 *
 * `NgModelController` provides API for the `ng-model` directive. The controller contains
 * services for data-binding, validation, CSS updates, and value formatting and parsing. It
 * purposefully does not contain any logic which deals with DOM rendering or listening to
 * DOM events. Such DOM related logic should be provided by other directives which make use of
 * `NgModelController` for data-binding.
 *
 * ## Custom Control Example
 * This example shows how to use `NgModelController` with a custom control to achieve
 * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)
 * collaborate together to achieve the desired result.
 *
 * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element
 * contents be edited in place by the user.  This will not work on older browsers.
 *
 * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
 * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
 * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks
 * that content using the `$sce` service.
 *
 * <example name="NgModelController" module="customControl" deps="angular-sanitize.js">
    <file name="style.css">
      [contenteditable] {
        border: 1px solid black;
        background-color: white;
        min-height: 20px;
      }

      .ng-invalid {
        border: 1px solid red;
      }

    </file>
    <file name="script.js">
      angular.module('customControl', ['ngSanitize']).
        directive('contenteditable', ['$sce', function($sce) {
          return {
            restrict: 'A', // only activate on element attribute
            require: '?ngModel', // get a hold of NgModelController
            link: function(scope, element, attrs, ngModel) {
              if(!ngModel) return; // do nothing if no ng-model

              // Specify how UI should be updated
              ngModel.$render = function() {
                element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
              };

              // Listen for change events to enable binding
              element.on('blur keyup change', function() {
                scope.$evalAsync(read);
              });
              read(); // initialize

              // Write data to the model
              function read() {
                var html = element.html();
                // When we clear the content editable the browser leaves a <br> behind
                // If strip-br attribute is provided then we strip this out
                if( attrs.stripBr && html == '<br>' ) {
                  html = '';
                }
                ngModel.$setViewValue(html);
              }
            }
          };
        }]);
    </file>
    <file name="index.html">
      <form name="myForm">
       <div contenteditable
            name="myWidget" ng-model="userContent"
            strip-br="true"
            required>Change me!</div>
        <span ng-show="myForm.myWidget.$error.required">Required!</span>
       <hr>
       <textarea ng-model="userContent"></textarea>
      </form>
    </file>
    <file name="protractor.js" type="protractor">
    it('should data-bind and become invalid', function() {
      if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {
        // SafariDriver can't handle contenteditable
        // and Firefox driver can't clear contenteditables very well
        return;
      }
      var contentEditable = element(by.css('[contenteditable]'));
      var content = 'Change me!';

      expect(contentEditable.getText()).toEqual(content);

      contentEditable.clear();
      contentEditable.sendKeys(protractor.Key.BACK_SPACE);
      expect(contentEditable.getText()).toEqual('');
      expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);
    });
    </file>
 * </example>
 *
 *
 */
var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate',
    function($scope, $exceptionHandler, $attr, $element, $parse, $animate) {
  this.$viewValue = Number.NaN;
  this.$modelValue = Number.NaN;
  this.$parsers = [];
  this.$formatters = [];
  this.$viewChangeListeners = [];
  this.$pristine = true;
  this.$dirty = false;
  this.$valid = true;
  this.$invalid = false;
  this.$name = $attr.name;

  var ngModelGet = $parse($attr.ngModel),
      ngModelSet = ngModelGet.assign;

  if (!ngModelSet) {
    throw minErr('ngModel')('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
        $attr.ngModel, startingTag($element));
  }

  /**
   * @ngdoc method
   * @name ngModel.NgModelController#$render
   *
   * @description
   * Called when the view needs to be updated. It is expected that the user of the ng-model
   * directive will implement this method.
   */
  this.$render = noop;

  /**
   * @ngdoc method
   * @name ngModel.NgModelController#$isEmpty
   *
   * @description
   * This is called when we need to determine if the value of the input is empty.
   *
   * For instance, the required directive does this to work out if the input has data or not.
   * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.
   *
   * You can override this for input directives whose concept of being empty is different to the
   * default. The `checkboxInputType` directive does this because in its case a value of `false`
   * implies empty.
   *
   * @param {*} value Reference to check.
   * @returns {boolean} True if `value` is empty.
   */
  this.$isEmpty = function(value) {
    return isUndefined(value) || value === '' || value === null || value !== value;
  };

  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,
      invalidCount = 0, // used to easily determine if we are valid
      $error = this.$error = {}; // keep invalid keys here


  // Setup initial state of the control
  $element.addClass(PRISTINE_CLASS);
  toggleValidCss(true);

  // convenience method for easy toggling of classes
  function toggleValidCss(isValid, validationErrorKey) {
    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
    $animate.removeClass($element, (isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);
    $animate.addClass($element, (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
  }

  /**
   * @ngdoc method
   * @name ngModel.NgModelController#$setValidity
   *
   * @description
   * Change the validity state, and notifies the form when the control changes validity. (i.e. it
   * does not notify form if given validator is already marked as invalid).
   *
   * This method should be called by validators - i.e. the parser or formatter functions.
   *
   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign
   *        to `$error[validationErrorKey]=!isValid` so that it is available for data-binding.
   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case
   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .
   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).
   */
  this.$setValidity = function(validationErrorKey, isValid) {
    // Purposeful use of ! here to cast isValid to boolean in case it is undefined
    // jshint -W018
    if ($error[validationErrorKey] === !isValid) return;
    // jshint +W018

    if (isValid) {
      if ($error[validationErrorKey]) invalidCount--;
      if (!invalidCount) {
        toggleValidCss(true);
        this.$valid = true;
        this.$invalid = false;
      }
    } else {
      toggleValidCss(false);
      this.$invalid = true;
      this.$valid = false;
      invalidCount++;
    }

    $error[validationErrorKey] = !isValid;
    toggleValidCss(isValid, validationErrorKey);

    parentForm.$setValidity(validationErrorKey, isValid, this);
  };

  /**
   * @ngdoc method
   * @name ngModel.NgModelController#$setPristine
   *
   * @description
   * Sets the control to its pristine state.
   *
   * This method can be called to remove the 'ng-dirty' class and set the control to its pristine
   * state (ng-pristine class).
   */
  this.$setPristine = function () {
    this.$dirty = false;
    this.$pristine = true;
    $animate.removeClass($element, DIRTY_CLASS);
    $animate.addClass($element, PRISTINE_CLASS);
  };

  /**
   * @ngdoc method
   * @name ngModel.NgModelController#$setViewValue
   *
   * @description
   * Update the view value.
   *
   * This method should be called when the view value changes, typically from within a DOM event handler.
   * For example {@link ng.directive:input input} and
   * {@link ng.directive:select select} directives call it.
   *
   * It will update the $viewValue, then pass this value through each of the functions in `$parsers`,
   * which includes any validators. The value that comes out of this `$parsers` pipeline, be applied to
   * `$modelValue` and the **expression** specified in the `ng-model` attribute.
   *
   * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
   *
   * Note that calling this function does not trigger a `$digest`.
   *
   * @param {string} value Value from the view.
   */
  this.$setViewValue = function(value) {
    this.$viewValue = value;

    // change to dirty
    if (this.$pristine) {
      this.$dirty = true;
      this.$pristine = false;
      $animate.removeClass($element, PRISTINE_CLASS);
      $animate.addClass($element, DIRTY_CLASS);
      parentForm.$setDirty();
    }

    forEach(this.$parsers, function(fn) {
      value = fn(value);
    });

    if (this.$modelValue !== value) {
      this.$modelValue = value;
      ngModelSet($scope, value);
      forEach(this.$viewChangeListeners, function(listener) {
        try {
          listener();
        } catch(e) {
          $exceptionHandler(e);
        }
      });
    }
  };

  // model -> value
  var ctrl = this;

  $scope.$watch(function ngModelWatch() {
    var value = ngModelGet($scope);

    // if scope model value and ngModel value are out of sync
    if (ctrl.$modelValue !== value) {

      var formatters = ctrl.$formatters,
          idx = formatters.length;

      ctrl.$modelValue = value;
      while(idx--) {
        value = formatters[idx](value);
      }

      if (ctrl.$viewValue !== value) {
        ctrl.$viewValue = value;
        ctrl.$render();
      }
    }

    return value;
  });
}];


/**
 * @ngdoc directive
 * @name ngModel
 *
 * @element input
 *
 * @description
 * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a
 * property on the scope using {@link ngModel.NgModelController NgModelController},
 * which is created and exposed by this directive.
 *
 * `ngModel` is responsible for:
 *
 * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`
 *   require.
 * - Providing validation behavior (i.e. required, number, email, url).
 * - Keeping the state of the control (valid/invalid, dirty/pristine, validation errors).
 * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`) including animations.
 * - Registering the control with its parent {@link ng.directive:form form}.
 *
 * Note: `ngModel` will try to bind to the property given by evaluating the expression on the
 * current scope. If the property doesn't already exist on this scope, it will be created
 * implicitly and added to the scope.
 *
 * For best practices on using `ngModel`, see:
 *
 *  - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)
 *
 * For basic examples, how to use `ngModel`, see:
 *
 *  - {@link ng.directive:input input}
 *    - {@link input[text] text}
 *    - {@link input[checkbox] checkbox}
 *    - {@link input[radio] radio}
 *    - {@link input[number] number}
 *    - {@link input[email] email}
 *    - {@link input[url] url}
 *  - {@link ng.directive:select select}
 *  - {@link ng.directive:textarea textarea}
 *
 * # CSS classes
 * The following CSS classes are added and removed on the associated input/select/textarea element
 * depending on the validity of the model.
 *
 *  - `ng-valid` is set if the model is valid.
 *  - `ng-invalid` is set if the model is invalid.
 *  - `ng-pristine` is set if the model is pristine.
 *  - `ng-dirty` is set if the model is dirty.
 *
 * Keep in mind that ngAnimate can detect each of these classes when added and removed.
 *
 * ## Animation Hooks
 *
 * Animations within models are triggered when any of the associated CSS classes are added and removed
 * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,
 * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.
 * The animations that are triggered within ngModel are similar to how they work in ngClass and
 * animations can be hooked into using CSS transitions, keyframes as well as JS animations.
 *
 * The following example shows a simple way to utilize CSS transitions to style an input element
 * that has been rendered as invalid after it has been validated:
 *
 * <pre>
 * //be sure to include ngAnimate as a module to hook into more
 * //advanced animations
 * .my-input {
 *   transition:0.5s linear all;
 *   background: white;
 * }
 * .my-input.ng-invalid {
 *   background: red;
 *   color:white;
 * }
 * </pre>
 *
 * @example
 * <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample">
     <file name="index.html">
       <script>
        angular.module('inputExample', [])
          .controller('ExampleController', ['$scope', function($scope) {
            $scope.val = '1';
          }]);
       </script>
       <style>
         .my-input {
           -webkit-transition:all linear 0.5s;
           transition:all linear 0.5s;
           background: transparent;
         }
         .my-input.ng-invalid {
           color:white;
           background: red;
         }
       </style>
       Update input to see transitions when valid/invalid.
       Integer is a valid value.
       <form name="testForm" ng-controller="ExampleController">
         <input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input" />
       </form>
     </file>
 * </example>
 */
var ngModelDirective = function() {
  return {
    require: ['ngModel', '^?form'],
    controller: NgModelController,
    link: function(scope, element, attr, ctrls) {
      // notify others, especially parent forms

      var modelCtrl = ctrls[0],
          formCtrl = ctrls[1] || nullFormCtrl;

      formCtrl.$addControl(modelCtrl);

      scope.$on('$destroy', function() {
        formCtrl.$removeControl(modelCtrl);
      });
    }
  };
};


/**
 * @ngdoc directive
 * @name ngChange
 *
 * @description
 * Evaluate the given expression when the user changes the input.
 * The expression is evaluated immediately, unlike the JavaScript onchange event
 * which only triggers at the end of a change (usually, when the user leaves the
 * form element or presses the return key).
 * The expression is not evaluated when the value change is coming from the model.
 *
 * Note, this directive requires `ngModel` to be present.
 *
 * @element input
 * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change
 * in input value.
 *
 * @example
 * <example name="ngChange-directive" module="changeExample">
 *   <file name="index.html">
 *     <script>
 *       angular.module('changeExample', [])
 *         .controller('ExampleController', ['$scope', function($scope) {
 *           $scope.counter = 0;
 *           $scope.change = function() {
 *             $scope.counter++;
 *           };
 *         }]);
 *     </script>
 *     <div ng-controller="ExampleController">
 *       <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" />
 *       <input type="checkbox" ng-model="confirmed" id="ng-change-example2" />
 *       <label for="ng-change-example2">Confirmed</label><br />
 *       <tt>debug = {{confirmed}}</tt><br/>
 *       <tt>counter = {{counter}}</tt><br/>
 *     </div>
 *   </file>
 *   <file name="protractor.js" type="protractor">
 *     var counter = element(by.binding('counter'));
 *     var debug = element(by.binding('confirmed'));
 *
 *     it('should evaluate the expression if changing from view', function() {
 *       expect(counter.getText()).toContain('0');
 *
 *       element(by.id('ng-change-example1')).click();
 *
 *       expect(counter.getText()).toContain('1');
 *       expect(debug.getText()).toContain('true');
 *     });
 *
 *     it('should not evaluate the expression if changing from model', function() {
 *       element(by.id('ng-change-example2')).click();

 *       expect(counter.getText()).toContain('0');
 *       expect(debug.getText()).toContain('true');
 *     });
 *   </file>
 * </example>
 */
var ngChangeDirective = valueFn({
  require: 'ngModel',
  link: function(scope, element, attr, ctrl) {
    ctrl.$viewChangeListeners.push(function() {
      scope.$eval(attr.ngChange);
    });
  }
});


var requiredDirective = function() {
  return {
    require: '?ngModel',
    link: function(scope, elm, attr, ctrl) {
      if (!ctrl) return;
      attr.required = true; // force truthy in case we are on non input element

      var validator = function(value) {
        if (attr.required && ctrl.$isEmpty(value)) {
          ctrl.$setValidity('required', false);
          return;
        } else {
          ctrl.$setValidity('required', true);
          return value;
        }
      };

      ctrl.$formatters.push(validator);
      ctrl.$parsers.unshift(validator);

      attr.$observe('required', function() {
        validator(ctrl.$viewValue);
      });
    }
  };
};


/**
 * @ngdoc directive
 * @name ngList
 *
 * @description
 * Text input that converts between a delimited string and an array of strings. The delimiter
 * can be a fixed string (by default a comma) or a regular expression.
 *
 * @element input
 * @param {string=} ngList optional delimiter that should be used to split the value. If
 *   specified in form `/something/` then the value will be converted into a regular expression.
 *
 * @example
    <example name="ngList-directive" module="listExample">
      <file name="index.html">
       <script>
         angular.module('listExample', [])
           .controller('ExampleController', ['$scope', function($scope) {
             $scope.names = ['igor', 'misko', 'vojta'];
           }]);
       </script>
       <form name="myForm" ng-controller="ExampleController">
         List: <input name="namesInput" ng-model="names" ng-list required>
         <span class="error" ng-show="myForm.namesInput.$error.required">
           Required!</span>
         <br>
         <tt>names = {{names}}</tt><br/>
         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>
         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>
         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
        </form>
      </file>
      <file name="protractor.js" type="protractor">
        var listInput = element(by.model('names'));
        var names = element(by.binding('{{names}}'));
        var valid = element(by.binding('myForm.namesInput.$valid'));
        var error = element(by.css('span.error'));

        it('should initialize to model', function() {
          expect(names.getText()).toContain('["igor","misko","vojta"]');
          expect(valid.getText()).toContain('true');
          expect(error.getCssValue('display')).toBe('none');
        });

        it('should be invalid if empty', function() {
          listInput.clear();
          listInput.sendKeys('');

          expect(names.getText()).toContain('');
          expect(valid.getText()).toContain('false');
          expect(error.getCssValue('display')).not.toBe('none');        });
      </file>
    </example>
 */
var ngListDirective = function() {
  return {
    require: 'ngModel',
    link: function(scope, element, attr, ctrl) {
      var match = /\/(.*)\//.exec(attr.ngList),
          separator = match && new RegExp(match[1]) || attr.ngList || ',';

      var parse = function(viewValue) {
        // If the viewValue is invalid (say required but empty) it will be `undefined`
        if (isUndefined(viewValue)) return;

        var list = [];

        if (viewValue) {
          forEach(viewValue.split(separator), function(value) {
            if (value) list.push(trim(value));
          });
        }

        return list;
      };

      ctrl.$parsers.push(parse);
      ctrl.$formatters.push(function(value) {
        if (isArray(value)) {
          return value.join(', ');
        }

        return undefined;
      });

      // Override the standard $isEmpty because an empty array means the input is empty.
      ctrl.$isEmpty = function(value) {
        return !value || !value.length;
      };
    }
  };
};


var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
/**
 * @ngdoc directive
 * @name ngValue
 *
 * @description
 * Binds the given expression to the value of `input[select]` or `input[radio]`, so
 * that when the element is selected, the `ngModel` of that element is set to the
 * bound value.
 *
 * `ngValue` is useful when dynamically generating lists of radio buttons using `ng-repeat`, as
 * shown below.
 *
 * @element input
 * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute
 *   of the `input` element
 *
 * @example
    <example name="ngValue-directive" module="valueExample">
      <file name="index.html">
       <script>
          angular.module('valueExample', [])
            .controller('ExampleController', ['$scope', function($scope) {
              $scope.names = ['pizza', 'unicorns', 'robots'];
              $scope.my = { favorite: 'unicorns' };
            }]);
       </script>
        <form ng-controller="ExampleController">
          <h2>Which is your favorite?</h2>
            <label ng-repeat="name in names" for="{{name}}">
              {{name}}
              <input type="radio"
                     ng-model="my.favorite"
                     ng-value="name"
                     id="{{name}}"
                     name="favorite">
            </label>
          <div>You chose {{my.favorite}}</div>
        </form>
      </file>
      <file name="protractor.js" type="protractor">
        var favorite = element(by.binding('my.favorite'));

        it('should initialize to model', function() {
          expect(favorite.getText()).toContain('unicorns');
        });
        it('should bind the values to the inputs', function() {
          element.all(by.model('my.favorite')).get(0).click();
          expect(favorite.getText()).toContain('pizza');
        });
      </file>
    </example>
 */
var ngValueDirective = function() {
  return {
    priority: 100,
    compile: function(tpl, tplAttr) {
      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {
        return function ngValueConstantLink(scope, elm, attr) {
          attr.$set('value', scope.$eval(attr.ngValue));
        };
      } else {
        return function ngValueLink(scope, elm, attr) {
          scope.$watch(attr.ngValue, function valueWatchAction(value) {
            attr.$set('value', value);
          });
        };
      }
    }
  };
};

/**
 * @ngdoc directive
 * @name ngBind
 * @restrict AC
 *
 * @description
 * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element
 * with the value of a given expression, and to update the text content when the value of that
 * expression changes.
 *
 * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
 * `{{ expression }}` which is similar but less verbose.
 *
 * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily
 * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an
 * element attribute, it makes the bindings invisible to the user while the page is loading.
 *
 * An alternative solution to this problem would be using the
 * {@link ng.directive:ngCloak ngCloak} directive.
 *
 *
 * @element ANY
 * @param {expression} ngBind {@link guide/expression Expression} to evaluate.
 *
 * @example
 * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
   <example module="bindExample">
     <file name="index.html">
       <script>
         angular.module('bindExample', [])
           .controller('ExampleController', ['$scope', function($scope) {
             $scope.name = 'Whirled';
           }]);
       </script>
       <div ng-controller="ExampleController">
         Enter name: <input type="text" ng-model="name"><br>
         Hello <span ng-bind="name"></span>!
       </div>
     </file>
     <file name="protractor.js" type="protractor">
       it('should check ng-bind', function() {
         var nameInput = element(by.model('name'));

         expect(element(by.binding('name')).getText()).toBe('Whirled');
         nameInput.clear();
         nameInput.sendKeys('world');
         expect(element(by.binding('name')).getText()).toBe('world');
       });
     </file>
   </example>
 */
var ngBindDirective = ngDirective({
  compile: function(templateElement) {
    templateElement.addClass('ng-binding');
    return function (scope, element, attr) {
      element.data('$binding', attr.ngBind);
      scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
        // We are purposefully using == here rather than === because we want to
        // catch when value is "null or undefined"
        // jshint -W041
        element.text(value == undefined ? '' : value);
      });
    };
  }
});


/**
 * @ngdoc directive
 * @name ngBindTemplate
 *
 * @description
 * The `ngBindTemplate` directive specifies that the element
 * text content should be replaced with the interpolation of the template
 * in the `ngBindTemplate` attribute.
 * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`
 * expressions. This directive is needed since some HTML elements
 * (such as TITLE and OPTION) cannot contain SPAN elements.
 *
 * @element ANY
 * @param {string} ngBindTemplate template of form
 *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.
 *
 * @example
 * Try it here: enter text in text box and watch the greeting change.
   <example module="bindExample">
     <file name="index.html">
       <script>
         angular.module('bindExample', [])
           .controller('ExampleController', ['$scope', function ($scope) {
             $scope.salutation = 'Hello';
             $scope.name = 'World';
           }]);
       </script>
       <div ng-controller="ExampleController">
        Salutation: <input type="text" ng-model="salutation"><br>
        Name: <input type="text" ng-model="name"><br>
        <pre ng-bind-template="{{salutation}} {{name}}!"></pre>
       </div>
     </file>
     <file name="protractor.js" type="protractor">
       it('should check ng-bind', function() {
         var salutationElem = element(by.binding('salutation'));
         var salutationInput = element(by.model('salutation'));
         var nameInput = element(by.model('name'));

         expect(salutationElem.getText()).toBe('Hello World!');

         salutationInput.clear();
         salutationInput.sendKeys('Greetings');
         nameInput.clear();
         nameInput.sendKeys('user');

         expect(salutationElem.getText()).toBe('Greetings user!');
       });
     </file>
   </example>
 */
var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
  return function(scope, element, attr) {
    // TODO: move this to scenario runner
    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));
    element.addClass('ng-binding').data('$binding', interpolateFn);
    attr.$observe('ngBindTemplate', function(value) {
      element.text(value);
    });
  };
}];


/**
 * @ngdoc directive
 * @name ngBindHtml
 *
 * @description
 * Creates a binding that will innerHTML the result of evaluating the `expression` into the current
 * element in a secure way.  By default, the innerHTML-ed content will be sanitized using the {@link
 * ngSanitize.$sanitize $sanitize} service.  To utilize this functionality, ensure that `$sanitize`
 * is available, for example, by including {@link ngSanitize} in your module's dependencies (not in
 * core Angular). In order to use {@link ngSanitize} in your module's dependencies, you need to
 * include "angular-sanitize.js" in your application.
 *
 * You may also bypass sanitization for values you know are safe. To do so, bind to
 * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}.  See the example
 * under {@link ng.$sce#Example Strict Contextual Escaping (SCE)}.
 *
 * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you
 * will have an exception (instead of an exploit.)
 *
 * @element ANY
 * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
 *
 * @example

   <example module="bindHtmlExample" deps="angular-sanitize.js">
     <file name="index.html">
       <div ng-controller="ExampleController">
        <p ng-bind-html="myHTML"></p>
       </div>
     </file>

     <file name="script.js">
       angular.module('bindHtmlExample', ['ngSanitize'])
         .controller('ExampleController', ['$scope', function($scope) {
           $scope.myHTML =
              'I am an <code>HTML</code>string with ' +
              '<a href="#">links!</a> and other <em>stuff</em>';
         }]);
     </file>

     <file name="protractor.js" type="protractor">
       it('should check ng-bind-html', function() {
         expect(element(by.binding('myHTML')).getText()).toBe(
             'I am an HTMLstring with links! and other stuff');
       });
     </file>
   </example>
 */
var ngBindHtmlDirective = ['$sce', '$parse', function($sce, $parse) {
  return {
    compile: function (tElement) {
      tElement.addClass('ng-binding');

      return function (scope, element, attr) {
        element.data('$binding', attr.ngBindHtml);

        var parsed = $parse(attr.ngBindHtml);

        function getStringValue() {
          return (parsed(scope) || '').toString();
        }

        scope.$watch(getStringValue, function ngBindHtmlWatchAction(value) {
          element.html($sce.getTrustedHtml(parsed(scope)) || '');
        });
      };
    }
  };
}];

function classDirective(name, selector) {
  name = 'ngClass' + name;
  return ['$animate', function($animate) {
    return {
      restrict: 'AC',
      link: function(scope, element, attr) {
        var oldVal;

        scope.$watch(attr[name], ngClassWatchAction, true);

        attr.$observe('class', function(value) {
          ngClassWatchAction(scope.$eval(attr[name]));
        });


        if (name !== 'ngClass') {
          scope.$watch('$index', function($index, old$index) {
            // jshint bitwise: false
            var mod = $index & 1;
            if (mod !== (old$index & 1)) {
              var classes = arrayClasses(scope.$eval(attr[name]));
              mod === selector ?
                addClasses(classes) :
                removeClasses(classes);
            }
          });
        }

        function addClasses(classes) {
          var newClasses = digestClassCounts(classes, 1);
          attr.$addClass(newClasses);
        }

        function removeClasses(classes) {
          var newClasses = digestClassCounts(classes, -1);
          attr.$removeClass(newClasses);
        }

        function digestClassCounts (classes, count) {
          var classCounts = element.data('$classCounts') || {};
          var classesToUpdate = [];
          forEach(classes, function (className) {
            if (count > 0 || classCounts[className]) {
              classCounts[className] = (classCounts[className] || 0) + count;
              if (classCounts[className] === +(count > 0)) {
                classesToUpdate.push(className);
              }
            }
          });
          element.data('$classCounts', classCounts);
          return classesToUpdate.join(' ');
        }

        function updateClasses (oldClasses, newClasses) {
          var toAdd = arrayDifference(newClasses, oldClasses);
          var toRemove = arrayDifference(oldClasses, newClasses);
          toRemove = digestClassCounts(toRemove, -1);
          toAdd = digestClassCounts(toAdd, 1);

          if (toAdd.length === 0) {
            $animate.removeClass(element, toRemove);
          } else if (toRemove.length === 0) {
            $animate.addClass(element, toAdd);
          } else {
            $animate.setClass(element, toAdd, toRemove);
          }
        }

        function ngClassWatchAction(newVal) {
          if (selector === true || scope.$index % 2 === selector) {
            var newClasses = arrayClasses(newVal || []);
            if (!oldVal) {
              addClasses(newClasses);
            } else if (!equals(newVal,oldVal)) {
              var oldClasses = arrayClasses(oldVal);
              updateClasses(oldClasses, newClasses);
            }
          }
          oldVal = shallowCopy(newVal);
        }
      }
    };

    function arrayDifference(tokens1, tokens2) {
      var values = [];

      outer:
      for(var i = 0; i < tokens1.length; i++) {
        var token = tokens1[i];
        for(var j = 0; j < tokens2.length; j++) {
          if(token == tokens2[j]) continue outer;
        }
        values.push(token);
      }
      return values;
    }

    function arrayClasses (classVal) {
      if (isArray(classVal)) {
        return classVal;
      } else if (isString(classVal)) {
        return classVal.split(' ');
      } else if (isObject(classVal)) {
        var classes = [], i = 0;
        forEach(classVal, function(v, k) {
          if (v) {
            classes = classes.concat(k.split(' '));
          }
        });
        return classes;
      }
      return classVal;
    }
  }];
}

/**
 * @ngdoc directive
 * @name ngClass
 * @restrict AC
 *
 * @description
 * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding
 * an expression that represents all classes to be added.
 *
 * The directive operates in three different ways, depending on which of three types the expression
 * evaluates to:
 *
 * 1. If the expression evaluates to a string, the string should be one or more space-delimited class
 * names.
 *
 * 2. If the expression evaluates to an array, each element of the array should be a string that is
 * one or more space-delimited class names.
 *
 * 3. If the expression evaluates to an object, then for each key-value pair of the
 * object with a truthy value the corresponding key is used as a class name.
 *
 * The directive won't add duplicate classes if a particular class was already set.
 *
 * When the expression changes, the previously added classes are removed and only then the
 * new classes are added.
 *
 * @animations
 * add - happens just before the class is applied to the element
 * remove - happens just before the class is removed from the element
 *
 * @element ANY
 * @param {expression} ngClass {@link guide/expression Expression} to eval. The result
 *   of the evaluation can be a string representing space delimited class
 *   names, an array, or a map of class names to boolean values. In the case of a map, the
 *   names of the properties whose values are truthy will be added as css classes to the
 *   element.
 *
 * @example Example that demonstrates basic bindings via ngClass directive.
   <example>
     <file name="index.html">
       <p ng-class="{strike: deleted, bold: important, red: error}">Map Syntax Example</p>
       <input type="checkbox" ng-model="deleted"> deleted (apply "strike" class)<br>
       <input type="checkbox" ng-model="important"> important (apply "bold" class)<br>
       <input type="checkbox" ng-model="error"> error (apply "red" class)
       <hr>
       <p ng-class="style">Using String Syntax</p>
       <input type="text" ng-model="style" placeholder="Type: bold strike red">
       <hr>
       <p ng-class="[style1, style2, style3]">Using Array Syntax</p>
       <input ng-model="style1" placeholder="Type: bold, strike or red"><br>
       <input ng-model="style2" placeholder="Type: bold, strike or red"><br>
       <input ng-model="style3" placeholder="Type: bold, strike or red"><br>
     </file>
     <file name="style.css">
       .strike {
         text-decoration: line-through;
       }
       .bold {
           font-weight: bold;
       }
       .red {
           color: red;
       }
     </file>
     <file name="protractor.js" type="protractor">
       var ps = element.all(by.css('p'));

       it('should let you toggle the class', function() {

         expect(ps.first().getAttribute('class')).not.toMatch(/bold/);
         expect(ps.first().getAttribute('class')).not.toMatch(/red/);

         element(by.model('important')).click();
         expect(ps.first().getAttribute('class')).toMatch(/bold/);

         element(by.model('error')).click();
         expect(ps.first().getAttribute('class')).toMatch(/red/);
       });

       it('should let you toggle string example', function() {
         expect(ps.get(1).getAttribute('class')).toBe('');
         element(by.model('style')).clear();
         element(by.model('style')).sendKeys('red');
         expect(ps.get(1).getAttribute('class')).toBe('red');
       });

       it('array example should have 3 classes', function() {
         expect(ps.last().getAttribute('class')).toBe('');
         element(by.model('style1')).sendKeys('bold');
         element(by.model('style2')).sendKeys('strike');
         element(by.model('style3')).sendKeys('red');
         expect(ps.last().getAttribute('class')).toBe('bold strike red');
       });
     </file>
   </example>

   ## Animations

   The example below demonstrates how to perform animations using ngClass.

   <example module="ngAnimate" deps="angular-animate.js" animations="true">
     <file name="index.html">
      <input id="setbtn" type="button" value="set" ng-click="myVar='my-class'">
      <input id="clearbtn" type="button" value="clear" ng-click="myVar=''">
      <br>
      <span class="base-class" ng-class="myVar">Sample Text</span>
     </file>
     <file name="style.css">
       .base-class {
         -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
         transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
       }

       .base-class.my-class {
         color: red;
         font-size:3em;
       }
     </file>
     <file name="protractor.js" type="protractor">
       it('should check ng-class', function() {
         expect(element(by.css('.base-class')).getAttribute('class')).not.
           toMatch(/my-class/);

         element(by.id('setbtn')).click();

         expect(element(by.css('.base-class')).getAttribute('class')).
           toMatch(/my-class/);

         element(by.id('clearbtn')).click();

         expect(element(by.css('.base-class')).getAttribute('class')).not.
           toMatch(/my-class/);
       });
     </file>
   </example>


   ## ngClass and pre-existing CSS3 Transitions/Animations
   The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
   Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder
   any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure
   to view the step by step details of {@link ngAnimate.$animate#addclass $animate.addClass} and
   {@link ngAnimate.$animate#removeclass $animate.removeClass}.
 */
var ngClassDirective = classDirective('', true);

/**
 * @ngdoc directive
 * @name ngClassOdd
 * @restrict AC
 *
 * @description
 * The `ngClassOdd` and `ngClassEven` directives work exactly as
 * {@link ng.directive:ngClass ngClass}, except they work in
 * conjunction with `ngRepeat` and take effect only on odd (even) rows.
 *
 * This directive can be applied only within the scope of an
 * {@link ng.directive:ngRepeat ngRepeat}.
 *
 * @element ANY
 * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result
 *   of the evaluation can be a string representing space delimited class names or an array.
 *
 * @example
   <example>
     <file name="index.html">
        <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
          <li ng-repeat="name in names">
           <span ng-class-odd="'odd'" ng-class-even="'even'">
             {{name}}
           </span>
          </li>
        </ol>
     </file>
     <file name="style.css">
       .odd {
         color: red;
       }
       .even {
         color: blue;
       }
     </file>
     <file name="protractor.js" type="protractor">
       it('should check ng-class-odd and ng-class-even', function() {
         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
           toMatch(/odd/);
         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
           toMatch(/even/);
       });
     </file>
   </example>
 */
var ngClassOddDirective = classDirective('Odd', 0);

/**
 * @ngdoc directive
 * @name ngClassEven
 * @restrict AC
 *
 * @description
 * The `ngClassOdd` and `ngClassEven` directives work exactly as
 * {@link ng.directive:ngClass ngClass}, except they work in
 * conjunction with `ngRepeat` and take effect only on odd (even) rows.
 *
 * This directive can be applied only within the scope of an
 * {@link ng.directive:ngRepeat ngRepeat}.
 *
 * @element ANY
 * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The
 *   result of the evaluation can be a string representing space delimited class names or an array.
 *
 * @example
   <example>
     <file name="index.html">
        <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
          <li ng-repeat="name in names">
           <span ng-class-odd="'odd'" ng-class-even="'even'">
             {{name}} &nbsp; &nbsp; &nbsp;
           </span>
          </li>
        </ol>
     </file>
     <file name="style.css">
       .odd {
         color: red;
       }
       .even {
         color: blue;
       }
     </file>
     <file name="protractor.js" type="protractor">
       it('should check ng-class-odd and ng-class-even', function() {
         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
           toMatch(/odd/);
         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
           toMatch(/even/);
       });
     </file>
   </example>
 */
var ngClassEvenDirective = classDirective('Even', 1);

/**
 * @ngdoc directive
 * @name ngCloak
 * @restrict AC
 *
 * @description
 * The `ngCloak` directive is used to prevent the Angular html template from being briefly
 * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this
 * directive to avoid the undesirable flicker effect caused by the html template display.
 *
 * The directive can be applied to the `<body>` element, but the preferred usage is to apply
 * multiple `ngCloak` directives to small portions of the page to permit progressive rendering
 * of the browser view.
 *
 * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and
 * `angular.min.js`.
 * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
 *
 * ```css
 * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
 *   display: none !important;
 * }
 * ```
 *
 * When this css rule is loaded by the browser, all html elements (including their children) that
 * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive
 * during the compilation of the template it deletes the `ngCloak` element attribute, making
 * the compiled element visible.
 *
 * For the best result, the `angular.js` script must be loaded in the head section of the html
 * document; alternatively, the css rule above must be included in the external stylesheet of the
 * application.
 *
 * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they
 * cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css
 * class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below.
 *
 * @element ANY
 *
 * @example
   <example>
     <file name="index.html">
        <div id="template1" ng-cloak>{{ 'hello' }}</div>
        <div id="template2" ng-cloak class="ng-cloak">{{ 'hello IE7' }}</div>
     </file>
     <file name="protractor.js" type="protractor">
       it('should remove the template directive and css class', function() {
         expect($('#template1').getAttribute('ng-cloak')).
           toBeNull();
         expect($('#template2').getAttribute('ng-cloak')).
           toBeNull();
       });
     </file>
   </example>
 *
 */
var ngCloakDirective = ngDirective({
  compile: function(element, attr) {
    attr.$set('ngCloak', undefined);
    element.removeClass('ng-cloak');
  }
});

/**
 * @ngdoc directive
 * @name ngController
 *
 * @description
 * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular
 * supports the principles behind the Model-View-Controller design pattern.
 *
 * MVC components in angular:
 *
 * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties
 *   are accessed through bindings.
 * * View — The template (HTML with data bindings) that is rendered into the View.
 * * Controller — The `ngController` directive specifies a Controller class; the class contains business
 *   logic behind the application to decorate the scope with functions and values
 *
 * Note that you can also attach controllers to the DOM by declaring it in a route definition
 * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller
 * again using `ng-controller` in the template itself.  This will cause the controller to be attached
 * and executed twice.
 *
 * @element ANY
 * @scope
 * @priority 500
 * @param {expression} ngController Name of a globally accessible constructor function or an
 *     {@link guide/expression expression} that on the current scope evaluates to a
 *     constructor function. The controller instance can be published into a scope property
 *     by specifying `as propertyName`.
 *
 * @example
 * Here is a simple form for editing user contact information. Adding, removing, clearing, and
 * greeting are methods declared on the controller (see source tab). These methods can
 * easily be called from the angular markup. Any changes to the data are automatically reflected
 * in the View without the need for a manual update.
 *
 * Two different declaration styles are included below:
 *
 * * one binds methods and properties directly onto the controller using `this`:
 * `ng-controller="SettingsController1 as settings"`
 * * one injects `$scope` into the controller:
 * `ng-controller="SettingsController2"`
 *
 * The second option is more common in the Angular community, and is generally used in boilerplates
 * and in this guide. However, there are advantages to binding properties directly to the controller
 * and avoiding scope.
 *
 * * Using `controller as` makes it obvious which controller you are accessing in the template when
 * multiple controllers apply to an element.
 * * If you are writing your controllers as classes you have easier access to the properties and
 * methods, which will appear on the scope, from inside the controller code.
 * * Since there is always a `.` in the bindings, you don't have to worry about prototypal
 * inheritance masking primitives.
 *
 * This example demonstrates the `controller as` syntax.
 *
 * <example name="ngControllerAs" module="controllerAsExample">
 *   <file name="index.html">
 *    <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
 *      Name: <input type="text" ng-model="settings.name"/>
 *      [ <a href="" ng-click="settings.greet()">greet</a> ]<br/>
 *      Contact:
 *      <ul>
 *        <li ng-repeat="contact in settings.contacts">
 *          <select ng-model="contact.type">
 *             <option>phone</option>
 *             <option>email</option>
 *          </select>
 *          <input type="text" ng-model="contact.value"/>
 *          [ <a href="" ng-click="settings.clearContact(contact)">clear</a>
 *          | <a href="" ng-click="settings.removeContact(contact)">X</a> ]
 *        </li>
 *        <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li>
 *     </ul>
 *    </div>
 *   </file>
 *   <file name="app.js">
 *    angular.module('controllerAsExample', [])
 *      .controller('SettingsController1', SettingsController1);
 *
 *    function SettingsController1() {
 *      this.name = "John Smith";
 *      this.contacts = [
 *        {type: 'phone', value: '408 555 1212'},
 *        {type: 'email', value: 'john.smith@example.org'} ];
 *    }
 *
 *    SettingsController1.prototype.greet = function() {
 *      alert(this.name);
 *    };
 *
 *    SettingsController1.prototype.addContact = function() {
 *      this.contacts.push({type: 'email', value: 'yourname@example.org'});
 *    };
 *
 *    SettingsController1.prototype.removeContact = function(contactToRemove) {
 *     var index = this.contacts.indexOf(contactToRemove);
 *      this.contacts.splice(index, 1);
 *    };
 *
 *    SettingsController1.prototype.clearContact = function(contact) {
 *      contact.type = 'phone';
 *      contact.value = '';
 *    };
 *   </file>
 *   <file name="protractor.js" type="protractor">
 *     it('should check controller as', function() {
 *       var container = element(by.id('ctrl-as-exmpl'));
 *         expect(container.element(by.model('settings.name'))
 *           .getAttribute('value')).toBe('John Smith');
 *
 *       var firstRepeat =
 *           container.element(by.repeater('contact in settings.contacts').row(0));
 *       var secondRepeat =
 *           container.element(by.repeater('contact in settings.contacts').row(1));
 *
 *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
 *           .toBe('408 555 1212');
 *
 *       expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
 *           .toBe('john.smith@example.org');
 *
 *       firstRepeat.element(by.linkText('clear')).click();
 *
 *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
 *           .toBe('');
 *
 *       container.element(by.linkText('add')).click();
 *
 *       expect(container.element(by.repeater('contact in settings.contacts').row(2))
 *           .element(by.model('contact.value'))
 *           .getAttribute('value'))
 *           .toBe('yourname@example.org');
 *     });
 *   </file>
 * </example>
 *
 * This example demonstrates the "attach to `$scope`" style of controller.
 *
 * <example name="ngController" module="controllerExample">
 *  <file name="index.html">
 *   <div id="ctrl-exmpl" ng-controller="SettingsController2">
 *     Name: <input type="text" ng-model="name"/>
 *     [ <a href="" ng-click="greet()">greet</a> ]<br/>
 *     Contact:
 *     <ul>
 *       <li ng-repeat="contact in contacts">
 *         <select ng-model="contact.type">
 *            <option>phone</option>
 *            <option>email</option>
 *         </select>
 *         <input type="text" ng-model="contact.value"/>
 *         [ <a href="" ng-click="clearContact(contact)">clear</a>
 *         | <a href="" ng-click="removeContact(contact)">X</a> ]
 *       </li>
 *       <li>[ <a href="" ng-click="addContact()">add</a> ]</li>
 *    </ul>
 *   </div>
 *  </file>
 *  <file name="app.js">
 *   angular.module('controllerExample', [])
 *     .controller('SettingsController2', ['$scope', SettingsController2]);
 *
 *   function SettingsController2($scope) {
 *     $scope.name = "John Smith";
 *     $scope.contacts = [
 *       {type:'phone', value:'408 555 1212'},
 *       {type:'email', value:'john.smith@example.org'} ];
 *
 *     $scope.greet = function() {
 *       alert($scope.name);
 *     };
 *
 *     $scope.addContact = function() {
 *       $scope.contacts.push({type:'email', value:'yourname@example.org'});
 *     };
 *
 *     $scope.removeContact = function(contactToRemove) {
 *       var index = $scope.contacts.indexOf(contactToRemove);
 *       $scope.contacts.splice(index, 1);
 *     };
 *
 *     $scope.clearContact = function(contact) {
 *       contact.type = 'phone';
 *       contact.value = '';
 *     };
 *   }
 *  </file>
 *  <file name="protractor.js" type="protractor">
 *    it('should check controller', function() {
 *      var container = element(by.id('ctrl-exmpl'));
 *
 *      expect(container.element(by.model('name'))
 *          .getAttribute('value')).toBe('John Smith');
 *
 *      var firstRepeat =
 *          container.element(by.repeater('contact in contacts').row(0));
 *      var secondRepeat =
 *          container.element(by.repeater('contact in contacts').row(1));
 *
 *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
 *          .toBe('408 555 1212');
 *      expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
 *          .toBe('john.smith@example.org');
 *
 *      firstRepeat.element(by.linkText('clear')).click();
 *
 *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
 *          .toBe('');
 *
 *      container.element(by.linkText('add')).click();
 *
 *      expect(container.element(by.repeater('contact in contacts').row(2))
 *          .element(by.model('contact.value'))
 *          .getAttribute('value'))
 *          .toBe('yourname@example.org');
 *    });
 *  </file>
 *</example>

 */
var ngControllerDirective = [function() {
  return {
    scope: true,
    controller: '@',
    priority: 500
  };
}];

/**
 * @ngdoc directive
 * @name ngCsp
 *
 * @element html
 * @description
 * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
 *
 * This is necessary when developing things like Google Chrome Extensions.
 *
 * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
 * For Angular to be CSP compatible there are only two things that we need to do differently:
 *
 * - don't use `Function` constructor to generate optimized value getters
 * - don't inject custom stylesheet into the document
 *
 * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`
 * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will
 * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will
 * be raised.
 *
 * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically
 * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).
 * To make those directives work in CSP mode, include the `angular-csp.css` manually.
 *
 * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This
 * autodetection however triggers a CSP error to be logged in the console:
 *
 * ```
 * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of
 * script in the following Content Security Policy directive: "default-src 'self'". Note that
 * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
 * ```
 *
 * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`
 * directive on the root element of the application or on the `angular.js` script tag, whichever
 * appears first in the html document.
 *
 * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*
 *
 * @example
 * This example shows how to apply the `ngCsp` directive to the `html` tag.
   ```html
     <!doctype html>
     <html ng-app ng-csp>
     ...
     ...
     </html>
   ```
 */

// ngCsp is not implemented as a proper directive any more, because we need it be processed while we
// bootstrap the system (before $parse is instantiated), for this reason we just have
// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc

/**
 * @ngdoc directive
 * @name ngClick
 *
 * @description
 * The ngClick directive allows you to specify custom behavior when
 * an element is clicked.
 *
 * @element ANY
 * @priority 0
 * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon
 * click. ({@link guide/expression#-event- Event object is available as `$event`})
 *
 * @example
   <example>
     <file name="index.html">
      <button ng-click="count = count + 1" ng-init="count=0">
        Increment
      </button>
      <span>
        count: {{count}}
      <span>
     </file>
     <file name="protractor.js" type="protractor">
       it('should check ng-click', function() {
         expect(element(by.binding('count')).getText()).toMatch('0');
         element(by.css('button')).click();
         expect(element(by.binding('count')).getText()).toMatch('1');
       });
     </file>
   </example>
 */
/*
 * A collection of directives that allows creation of custom event handlers that are defined as
 * angular expressions and are compiled and executed within the current scope.
 */
var ngEventDirectives = {};

// For events that might fire synchronously during DOM manipulation
// we need to execute their event handlers asynchronously using $evalAsync,
// so that they are not executed in an inconsistent state.
var forceAsyncEvents = {
  'blur': true,
  'focus': true
};
forEach(
  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
  function(eventName) {
    var directiveName = directiveNormalize('ng-' + eventName);
    ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
      return {
        compile: function($element, attr) {
          // We expose the powerful $event object on the scope that provides access to the Window,
          // etc. that isn't protected by the fast paths in $parse.  We explicitly request better
          // checks at the cost of speed since event handler expressions are not executed as
          // frequently as regular change detection.
          var fn = $parse(attr[directiveName], /* expensiveChecks */ true);
          return function ngEventHandler(scope, element) {
            element.on(eventName, function(event) {
              var callback = function() {
                fn(scope, {$event:event});
              };
              if (forceAsyncEvents[eventName] && $rootScope.$$phase) {
                scope.$evalAsync(callback);
              } else {
                scope.$apply(callback);
              }
            });
          };
        }
      };
    }];
  }
);

/**
 * @ngdoc directive
 * @name ngDblclick
 *
 * @description
 * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.
 *
 * @element ANY
 * @priority 0
 * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon
 * a dblclick. (The Event object is available as `$event`)
 *
 * @example
   <example>
     <file name="index.html">
      <button ng-dblclick="count = count + 1" ng-init="count=0">
        Increment (on double click)
      </button>
      count: {{count}}
     </file>
   </example>
 */


/**
 * @ngdoc directive
 * @name ngMousedown
 *
 * @description
 * The ngMousedown directive allows you to specify custom behavior on mousedown event.
 *
 * @element ANY
 * @priority 0
 * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon
 * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})
 *
 * @example
   <example>
     <file name="index.html">
      <button ng-mousedown="count = count + 1" ng-init="count=0">
        Increment (on mouse down)
      </button>
      count: {{count}}
     </file>
   </example>
 */


/**
 * @ngdoc directive
 * @name ngMouseup
 *
 * @description
 * Specify custom behavior on mouseup event.
 *
 * @element ANY
 * @priority 0
 * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon
 * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})
 *
 * @example
   <example>
     <file name="index.html">
      <button ng-mouseup="count = count + 1" ng-init="count=0">
        Increment (on mouse up)
      </button>
      count: {{count}}
     </file>
   </example>
 */

/**
 * @ngdoc directive
 * @name ngMouseover
 *
 * @description
 * Specify custom behavior on mouseover event.
 *
 * @element ANY
 * @priority 0
 * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon
 * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})
 *
 * @example
   <example>
     <file name="index.html">
      <button ng-mouseover="count = count + 1" ng-init="count=0">
        Increment (when mouse is over)
      </button>
      count: {{count}}
     </file>
   </example>
 */


/**
 * @ngdoc directive
 * @name ngMouseenter
 *
 * @description
 * Specify custom behavior on mouseenter event.
 *
 * @element ANY
 * @priority 0
 * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon
 * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})
 *
 * @example
   <example>
     <file name="index.html">
      <button ng-mouseenter="count = count + 1" ng-init="count=0">
        Increment (when mouse enters)
      </button>
      count: {{count}}
     </file>
   </example>
 */


/**
 * @ngdoc directive
 * @name ngMouseleave
 *
 * @description
 * Specify custom behavior on mouseleave event.
 *
 * @element ANY
 * @priority 0
 * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon
 * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})
 *
 * @example
   <example>
     <file name="index.html">
      <button ng-mouseleave="count = count + 1" ng-init="count=0">
        Increment (when mouse leaves)
      </button>
      count: {{count}}
     </file>
   </example>
 */


/**
 * @ngdoc directive
 * @name ngMousemove
 *
 * @description
 * Specify custom behavior on mousemove event.
 *
 * @element ANY
 * @priority 0
 * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon
 * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})
 *
 * @example
   <example>
     <file name="index.html">
      <button ng-mousemove="count = count + 1" ng-init="count=0">
        Increment (when mouse moves)
      </button>
      count: {{count}}
     </file>
   </example>
 */


/**
 * @ngdoc directive
 * @name ngKeydown
 *
 * @description
 * Specify custom behavior on keydown event.
 *
 * @element ANY
 * @priority 0
 * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon
 * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
 *
 * @example
   <example>
     <file name="index.html">
      <input ng-keydown="count = count + 1" ng-init="count=0">
      key down count: {{count}}
     </file>
   </example>
 */


/**
 * @ngdoc directive
 * @name ngKeyup
 *
 * @description
 * Specify custom behavior on keyup event.
 *
 * @element ANY
 * @priority 0
 * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon
 * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
 *
 * @example
   <example>
     <file name="index.html">
       <p>Typing in the input box below updates the key count</p>
       <input ng-keyup="count = count + 1" ng-init="count=0"> key up count: {{count}}

       <p>Typing in the input box below updates the keycode</p>
       <input ng-keyup="event=$event">
       <p>event keyCode: {{ event.keyCode }}</p>
       <p>event altKey: {{ event.altKey }}</p>
     </file>
   </example>
 */


/**
 * @ngdoc directive
 * @name ngKeypress
 *
 * @description
 * Specify custom behavior on keypress event.
 *
 * @element ANY
 * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon
 * keypress. ({@link guide/expression#-event- Event object is available as `$event`}
 * and can be interrogated for keyCode, altKey, etc.)
 *
 * @example
   <example>
     <file name="index.html">
      <input ng-keypress="count = count + 1" ng-init="count=0">
      key press count: {{count}}
     </file>
   </example>
 */


/**
 * @ngdoc directive
 * @name ngSubmit
 *
 * @description
 * Enables binding angular expressions to onsubmit events.
 *
 * Additionally it prevents the default action (which for form means sending the request to the
 * server and reloading the current page), but only if the form does not contain `action`,
 * `data-action`, or `x-action` attributes.
 *
 * <div class="alert alert-warning">
 * **Warning:** Be careful not to cause "double-submission" by using both the `ngClick` and
 * `ngSubmit` handlers together. See the
 * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}
 * for a detailed discussion of when `ngSubmit` may be triggered.
 * </div>
 *
 * @element form
 * @priority 0
 * @param {expression} ngSubmit {@link guide/expression Expression} to eval.
 * ({@link guide/expression#-event- Event object is available as `$event`})
 *
 * @example
   <example module="submitExample">
     <file name="index.html">
      <script>
        angular.module('submitExample', [])
          .controller('ExampleController', ['$scope', function($scope) {
            $scope.list = [];
            $scope.text = 'hello';
            $scope.submit = function() {
              if ($scope.text) {
                $scope.list.push(this.text);
                $scope.text = '';
              }
            };
          }]);
      </script>
      <form ng-submit="submit()" ng-controller="ExampleController">
        Enter text and hit enter:
        <input type="text" ng-model="text" name="text" />
        <input type="submit" id="submit" value="Submit" />
        <pre>list={{list}}</pre>
      </form>
     </file>
     <file name="protractor.js" type="protractor">
       it('should check ng-submit', function() {
         expect(element(by.binding('list')).getText()).toBe('list=[]');
         element(by.css('#submit')).click();
         expect(element(by.binding('list')).getText()).toContain('hello');
         expect(element(by.model('text')).getAttribute('value')).toBe('');
       });
       it('should ignore empty strings', function() {
         expect(element(by.binding('list')).getText()).toBe('list=[]');
         element(by.css('#submit')).click();
         element(by.css('#submit')).click();
         expect(element(by.binding('list')).getText()).toContain('hello');
        });
     </file>
   </example>
 */

/**
 * @ngdoc directive
 * @name ngFocus
 *
 * @description
 * Specify custom behavior on focus event.
 *
 * Note: As the `focus` event is executed synchronously when calling `input.focus()`
 * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
 * during an `$apply` to ensure a consistent state.
 *
 * @element window, input, select, textarea, a
 * @priority 0
 * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon
 * focus. ({@link guide/expression#-event- Event object is available as `$event`})
 *
 * @example
 * See {@link ng.directive:ngClick ngClick}
 */

/**
 * @ngdoc directive
 * @name ngBlur
 *
 * @description
 * Specify custom behavior on blur event.
 *
 * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when
 * an element has lost focus.
 *
 * Note: As the `blur` event is executed synchronously also during DOM manipulations
 * (e.g. removing a focussed input),
 * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
 * during an `$apply` to ensure a consistent state.
 *
 * @element window, input, select, textarea, a
 * @priority 0
 * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon
 * blur. ({@link guide/expression#-event- Event object is available as `$event`})
 *
 * @example
 * See {@link ng.directive:ngClick ngClick}
 */

/**
 * @ngdoc directive
 * @name ngCopy
 *
 * @description
 * Specify custom behavior on copy event.
 *
 * @element window, input, select, textarea, a
 * @priority 0
 * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon
 * copy. ({@link guide/expression#-event- Event object is available as `$event`})
 *
 * @example
   <example>
     <file name="index.html">
      <input ng-copy="copied=true" ng-init="copied=false; value='copy me'" ng-model="value">
      copied: {{copied}}
     </file>
   </example>
 */

/**
 * @ngdoc directive
 * @name ngCut
 *
 * @description
 * Specify custom behavior on cut event.
 *
 * @element window, input, select, textarea, a
 * @priority 0
 * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon
 * cut. ({@link guide/expression#-event- Event object is available as `$event`})
 *
 * @example
   <example>
     <file name="index.html">
      <input ng-cut="cut=true" ng-init="cut=false; value='cut me'" ng-model="value">
      cut: {{cut}}
     </file>
   </example>
 */

/**
 * @ngdoc directive
 * @name ngPaste
 *
 * @description
 * Specify custom behavior on paste event.
 *
 * @element window, input, select, textarea, a
 * @priority 0
 * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon
 * paste. ({@link guide/expression#-event- Event object is available as `$event`})
 *
 * @example
   <example>
     <file name="index.html">
      <input ng-paste="paste=true" ng-init="paste=false" placeholder='paste here'>
      pasted: {{paste}}
     </file>
   </example>
 */

/**
 * @ngdoc directive
 * @name ngIf
 * @restrict A
 *
 * @description
 * The `ngIf` directive removes or recreates a portion of the DOM tree based on an
 * {expression}. If the expression assigned to `ngIf` evaluates to a false
 * value then the element is removed from the DOM, otherwise a clone of the
 * element is reinserted into the DOM.
 *
 * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the
 * element in the DOM rather than changing its visibility via the `display` css property.  A common
 * case when this difference is significant is when using css selectors that rely on an element's
 * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.
 *
 * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope
 * is created when the element is restored.  The scope created within `ngIf` inherits from
 * its parent scope using
 * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance).
 * An important implication of this is if `ngModel` is used within `ngIf` to bind to
 * a javascript primitive defined in the parent scope. In this case any modifications made to the
 * variable within the child scope will override (hide) the value in the parent scope.
 *
 * Also, `ngIf` recreates elements using their compiled state. An example of this behavior
 * is if an element's class attribute is directly modified after it's compiled, using something like
 * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element
 * the added class will be lost because the original compiled state is used to regenerate the element.
 *
 * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`
 * and `leave` effects.
 *
 * @animations
 * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container
 * leave - happens just before the `ngIf` contents are removed from the DOM
 *
 * @element ANY
 * @scope
 * @priority 600
 * @param {expression} ngIf If the {@link guide/expression expression} is falsy then
 *     the element is removed from the DOM tree. If it is truthy a copy of the compiled
 *     element is added to the DOM tree.
 *
 * @example
  <example module="ngAnimate" deps="angular-animate.js" animations="true">
    <file name="index.html">
      Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /><br/>
      Show when checked:
      <span ng-if="checked" class="animate-if">
        I'm removed when the checkbox is unchecked.
      </span>
    </file>
    <file name="animations.css">
      .animate-if {
        background:white;
        border:1px solid black;
        padding:10px;
      }

      .animate-if.ng-enter, .animate-if.ng-leave {
        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
      }

      .animate-if.ng-enter,
      .animate-if.ng-leave.ng-leave-active {
        opacity:0;
      }

      .animate-if.ng-leave,
      .animate-if.ng-enter.ng-enter-active {
        opacity:1;
      }
    </file>
  </example>
 */
var ngIfDirective = ['$animate', function($animate) {
  return {
    transclude: 'element',
    priority: 600,
    terminal: true,
    restrict: 'A',
    $$tlb: true,
    link: function ($scope, $element, $attr, ctrl, $transclude) {
        var block, childScope, previousElements;
        $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {

          if (toBoolean(value)) {
            if (!childScope) {
              childScope = $scope.$new();
              $transclude(childScope, function (clone) {
                clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
                // Note: We only need the first/last node of the cloned nodes.
                // However, we need to keep the reference to the jqlite wrapper as it might be changed later
                // by a directive with templateUrl when its template arrives.
                block = {
                  clone: clone
                };
                $animate.enter(clone, $element.parent(), $element);
              });
            }
          } else {
            if(previousElements) {
              previousElements.remove();
              previousElements = null;
            }
            if(childScope) {
              childScope.$destroy();
              childScope = null;
            }
            if(block) {
              previousElements = getBlockElements(block.clone);
              $animate.leave(previousElements, function() {
                previousElements = null;
              });
              block = null;
            }
          }
        });
    }
  };
}];

/**
 * @ngdoc directive
 * @name ngInclude
 * @restrict ECA
 *
 * @description
 * Fetches, compiles and includes an external HTML fragment.
 *
 * By default, the template URL is restricted to the same domain and protocol as the
 * application document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
 * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols
 * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or
 * [wrap them](ng.$sce#trustAsResourceUrl) as trusted values. Refer to Angular's {@link
 * ng.$sce Strict Contextual Escaping}.
 *
 * In addition, the browser's
 * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
 * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
 * policy may further restrict whether the template is successfully loaded.
 * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`
 * access on some browsers.
 *
 * @animations
 * enter - animation is used to bring new content into the browser.
 * leave - animation is used to animate existing content away.
 *
 * The enter and leave animation occur concurrently.
 *
 * @scope
 * @priority 400
 *
 * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,
 *                 make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`.
 * @param {string=} onload Expression to evaluate when a new partial is loaded.
 *
 * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll
 *                  $anchorScroll} to scroll the viewport after the content is loaded.
 *
 *                  - If the attribute is not set, disable scrolling.
 *                  - If the attribute is set without value, enable scrolling.
 *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.
 *
 * @example
  <example module="includeExample" deps="angular-animate.js" animations="true">
    <file name="index.html">
     <div ng-controller="ExampleController">
       <select ng-model="template" ng-options="t.name for t in templates">
        <option value="">(blank)</option>
       </select>
       url of the template: <tt>{{template.url}}</tt>
       <hr/>
       <div class="slide-animate-container">
         <div class="slide-animate" ng-include="template.url"></div>
       </div>
     </div>
    </file>
    <file name="script.js">
      angular.module('includeExample', ['ngAnimate'])
        .controller('ExampleController', ['$scope', function($scope) {
          $scope.templates =
            [ { name: 'template1.html', url: 'template1.html'},
              { name: 'template2.html', url: 'template2.html'} ];
          $scope.template = $scope.templates[0];
        }]);
     </file>
    <file name="template1.html">
      Content of template1.html
    </file>
    <file name="template2.html">
      Content of template2.html
    </file>
    <file name="animations.css">
      .slide-animate-container {
        position:relative;
        background:white;
        border:1px solid black;
        height:40px;
        overflow:hidden;
      }

      .slide-animate {
        padding:10px;
      }

      .slide-animate.ng-enter, .slide-animate.ng-leave {
        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;

        position:absolute;
        top:0;
        left:0;
        right:0;
        bottom:0;
        display:block;
        padding:10px;
      }

      .slide-animate.ng-enter {
        top:-50px;
      }
      .slide-animate.ng-enter.ng-enter-active {
        top:0;
      }

      .slide-animate.ng-leave {
        top:0;
      }
      .slide-animate.ng-leave.ng-leave-active {
        top:50px;
      }
    </file>
    <file name="protractor.js" type="protractor">
      var templateSelect = element(by.model('template'));
      var includeElem = element(by.css('[ng-include]'));

      it('should load template1.html', function() {
        expect(includeElem.getText()).toMatch(/Content of template1.html/);
      });

      it('should load template2.html', function() {
        if (browser.params.browser == 'firefox') {
          // Firefox can't handle using selects
          // See https://github.com/angular/protractor/issues/480
          return;
        }
        templateSelect.click();
        templateSelect.all(by.css('option')).get(2).click();
        expect(includeElem.getText()).toMatch(/Content of template2.html/);
      });

      it('should change to blank', function() {
        if (browser.params.browser == 'firefox') {
          // Firefox can't handle using selects
          return;
        }
        templateSelect.click();
        templateSelect.all(by.css('option')).get(0).click();
        expect(includeElem.isPresent()).toBe(false);
      });
    </file>
  </example>
 */


/**
 * @ngdoc event
 * @name ngInclude#$includeContentRequested
 * @eventType emit on the scope ngInclude was declared in
 * @description
 * Emitted every time the ngInclude content is requested.
 */


/**
 * @ngdoc event
 * @name ngInclude#$includeContentLoaded
 * @eventType emit on the current ngInclude scope
 * @description
 * Emitted every time the ngInclude content is reloaded.
 */
var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate', '$sce',
                  function($http,   $templateCache,   $anchorScroll,   $animate,   $sce) {
  return {
    restrict: 'ECA',
    priority: 400,
    terminal: true,
    transclude: 'element',
    controller: angular.noop,
    compile: function(element, attr) {
      var srcExp = attr.ngInclude || attr.src,
          onloadExp = attr.onload || '',
          autoScrollExp = attr.autoscroll;

      return function(scope, $element, $attr, ctrl, $transclude) {
        var changeCounter = 0,
            currentScope,
            previousElement,
            currentElement;

        var cleanupLastIncludeContent = function() {
          if(previousElement) {
            previousElement.remove();
            previousElement = null;
          }
          if(currentScope) {
            currentScope.$destroy();
            currentScope = null;
          }
          if(currentElement) {
            $animate.leave(currentElement, function() {
              previousElement = null;
            });
            previousElement = currentElement;
            currentElement = null;
          }
        };

        scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {
          var afterAnimation = function() {
            if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
              $anchorScroll();
            }
          };
          var thisChangeId = ++changeCounter;

          if (src) {
            $http.get(src, {cache: $templateCache}).success(function(response) {
              if (thisChangeId !== changeCounter) return;
              var newScope = scope.$new();
              ctrl.template = response;

              // Note: This will also link all children of ng-include that were contained in the original
              // html. If that content contains controllers, ... they could pollute/change the scope.
              // However, using ng-include on an element with additional content does not make sense...
              // Note: We can't remove them in the cloneAttchFn of $transclude as that
              // function is called before linking the content, which would apply child
              // directives to non existing elements.
              var clone = $transclude(newScope, function(clone) {
                cleanupLastIncludeContent();
                $animate.enter(clone, null, $element, afterAnimation);
              });

              currentScope = newScope;
              currentElement = clone;

              currentScope.$emit('$includeContentLoaded');
              scope.$eval(onloadExp);
            }).error(function() {
              if (thisChangeId === changeCounter) cleanupLastIncludeContent();
            });
            scope.$emit('$includeContentRequested');
          } else {
            cleanupLastIncludeContent();
            ctrl.template = null;
          }
        });
      };
    }
  };
}];

// This directive is called during the $transclude call of the first `ngInclude` directive.
// It will replace and compile the content of the element with the loaded template.
// We need this directive so that the element content is already filled when
// the link function of another directive on the same element as ngInclude
// is called.
var ngIncludeFillContentDirective = ['$compile',
  function($compile) {
    return {
      restrict: 'ECA',
      priority: -400,
      require: 'ngInclude',
      link: function(scope, $element, $attr, ctrl) {
        $element.html(ctrl.template);
        $compile($element.contents())(scope);
      }
    };
  }];

/**
 * @ngdoc directive
 * @name ngInit
 * @restrict AC
 *
 * @description
 * The `ngInit` directive allows you to evaluate an expression in the
 * current scope.
 *
 * <div class="alert alert-error">
 * The only appropriate use of `ngInit` is for aliasing special properties of
 * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you
 * should use {@link guide/controller controllers} rather than `ngInit`
 * to initialize values on a scope.
 * </div>
 * <div class="alert alert-warning">
 * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make
 * sure you have parenthesis for correct precedence:
 * <pre class="prettyprint">
 *   <div ng-init="test1 = (data | orderBy:'name')"></div>
 * </pre>
 * </div>
 *
 * @priority 450
 *
 * @element ANY
 * @param {expression} ngInit {@link guide/expression Expression} to eval.
 *
 * @example
   <example module="initExample">
     <file name="index.html">
   <script>
     angular.module('initExample', [])
       .controller('ExampleController', ['$scope', function($scope) {
         $scope.list = [['a', 'b'], ['c', 'd']];
       }]);
   </script>
   <div ng-controller="ExampleController">
     <div ng-repeat="innerList in list" ng-init="outerIndex = $index">
       <div ng-repeat="value in innerList" ng-init="innerIndex = $index">
          <span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
       </div>
     </div>
   </div>
     </file>
     <file name="protractor.js" type="protractor">
       it('should alias index positions', function() {
         var elements = element.all(by.css('.example-init'));
         expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');
         expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');
         expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');
         expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');
       });
     </file>
   </example>
 */
var ngInitDirective = ngDirective({
  priority: 450,
  compile: function() {
    return {
      pre: function(scope, element, attrs) {
        scope.$eval(attrs.ngInit);
      }
    };
  }
});

/**
 * @ngdoc directive
 * @name ngNonBindable
 * @restrict AC
 * @priority 1000
 *
 * @description
 * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current
 * DOM element. This is useful if the element contains what appears to be Angular directives and
 * bindings but which should be ignored by Angular. This could be the case if you have a site that
 * displays snippets of code, for instance.
 *
 * @element ANY
 *
 * @example
 * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,
 * but the one wrapped in `ngNonBindable` is left alone.
 *
 * @example
    <example>
      <file name="index.html">
        <div>Normal: {{1 + 2}}</div>
        <div ng-non-bindable>Ignored: {{1 + 2}}</div>
      </file>
      <file name="protractor.js" type="protractor">
       it('should check ng-non-bindable', function() {
         expect(element(by.binding('1 + 2')).getText()).toContain('3');
         expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/);
       });
      </file>
    </example>
 */
var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });

/**
 * @ngdoc directive
 * @name ngPluralize
 * @restrict EA
 *
 * @description
 * `ngPluralize` is a directive that displays messages according to en-US localization rules.
 * These rules are bundled with angular.js, but can be overridden
 * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive
 * by specifying the mappings between
 * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
 * and the strings to be displayed.
 *
 * # Plural categories and explicit number rules
 * There are two
 * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
 * in Angular's default en-US locale: "one" and "other".
 *
 * While a plural category may match many numbers (for example, in en-US locale, "other" can match
 * any number that is not 1), an explicit number rule can only match one number. For example, the
 * explicit number rule for "3" matches the number 3. There are examples of plural categories
 * and explicit number rules throughout the rest of this documentation.
 *
 * # Configuring ngPluralize
 * You configure ngPluralize by providing 2 attributes: `count` and `when`.
 * You can also provide an optional attribute, `offset`.
 *
 * The value of the `count` attribute can be either a string or an {@link guide/expression
 * Angular expression}; these are evaluated on the current scope for its bound value.
 *
 * The `when` attribute specifies the mappings between plural categories and the actual
 * string to be displayed. The value of the attribute should be a JSON object.
 *
 * The following example shows how to configure ngPluralize:
 *
 * ```html
 * <ng-pluralize count="personCount"
                 when="{'0': 'Nobody is viewing.',
 *                      'one': '1 person is viewing.',
 *                      'other': '{} people are viewing.'}">
 * </ng-pluralize>
 *```
 *
 * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not
 * specify this rule, 0 would be matched to the "other" category and "0 people are viewing"
 * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for
 * other numbers, for example 12, so that instead of showing "12 people are viewing", you can
 * show "a dozen people are viewing".
 *
 * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted
 * into pluralized strings. In the previous example, Angular will replace `{}` with
 * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder
 * for <span ng-non-bindable>{{numberExpression}}</span>.
 *
 * # Configuring ngPluralize with offset
 * The `offset` attribute allows further customization of pluralized text, which can result in
 * a better user experience. For example, instead of the message "4 people are viewing this document",
 * you might display "John, Kate and 2 others are viewing this document".
 * The offset attribute allows you to offset a number by any desired value.
 * Let's take a look at an example:
 *
 * ```html
 * <ng-pluralize count="personCount" offset=2
 *               when="{'0': 'Nobody is viewing.',
 *                      '1': '{{person1}} is viewing.',
 *                      '2': '{{person1}} and {{person2}} are viewing.',
 *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',
 *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
 * </ng-pluralize>
 * ```
 *
 * Notice that we are still using two plural categories(one, other), but we added
 * three explicit number rules 0, 1 and 2.
 * When one person, perhaps John, views the document, "John is viewing" will be shown.
 * When three people view the document, no explicit number rule is found, so
 * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
 * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
 * is shown.
 *
 * Note that when you specify offsets, you must provide explicit number rules for
 * numbers from 0 up to and including the offset. If you use an offset of 3, for example,
 * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for
 * plural categories "one" and "other".
 *
 * @param {string|expression} count The variable to be bound to.
 * @param {string} when The mapping between plural category to its corresponding strings.
 * @param {number=} offset Offset to deduct from the total number.
 *
 * @example
    <example module="pluralizeExample">
      <file name="index.html">
        <script>
          angular.module('pluralizeExample', [])
            .controller('ExampleController', ['$scope', function($scope) {
              $scope.person1 = 'Igor';
              $scope.person2 = 'Misko';
              $scope.personCount = 1;
            }]);
        </script>
        <div ng-controller="ExampleController">
          Person 1:<input type="text" ng-model="person1" value="Igor" /><br/>
          Person 2:<input type="text" ng-model="person2" value="Misko" /><br/>
          Number of People:<input type="text" ng-model="personCount" value="1" /><br/>

          <!--- Example with simple pluralization rules for en locale --->
          Without Offset:
          <ng-pluralize count="personCount"
                        when="{'0': 'Nobody is viewing.',
                               'one': '1 person is viewing.',
                               'other': '{} people are viewing.'}">
          </ng-pluralize><br>

          <!--- Example with offset --->
          With Offset(2):
          <ng-pluralize count="personCount" offset=2
                        when="{'0': 'Nobody is viewing.',
                               '1': '{{person1}} is viewing.',
                               '2': '{{person1}} and {{person2}} are viewing.',
                               'one': '{{person1}}, {{person2}} and one other person are viewing.',
                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
          </ng-pluralize>
        </div>
      </file>
      <file name="protractor.js" type="protractor">
        it('should show correct pluralized string', function() {
          var withoutOffset = element.all(by.css('ng-pluralize')).get(0);
          var withOffset = element.all(by.css('ng-pluralize')).get(1);
          var countInput = element(by.model('personCount'));

          expect(withoutOffset.getText()).toEqual('1 person is viewing.');
          expect(withOffset.getText()).toEqual('Igor is viewing.');

          countInput.clear();
          countInput.sendKeys('0');

          expect(withoutOffset.getText()).toEqual('Nobody is viewing.');
          expect(withOffset.getText()).toEqual('Nobody is viewing.');

          countInput.clear();
          countInput.sendKeys('2');

          expect(withoutOffset.getText()).toEqual('2 people are viewing.');
          expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');

          countInput.clear();
          countInput.sendKeys('3');

          expect(withoutOffset.getText()).toEqual('3 people are viewing.');
          expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');

          countInput.clear();
          countInput.sendKeys('4');

          expect(withoutOffset.getText()).toEqual('4 people are viewing.');
          expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');
        });
        it('should show data-bound names', function() {
          var withOffset = element.all(by.css('ng-pluralize')).get(1);
          var personCount = element(by.model('personCount'));
          var person1 = element(by.model('person1'));
          var person2 = element(by.model('person2'));
          personCount.clear();
          personCount.sendKeys('4');
          person1.clear();
          person1.sendKeys('Di');
          person2.clear();
          person2.sendKeys('Vojta');
          expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');
        });
      </file>
    </example>
 */
var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {
  var BRACE = /{}/g;
  return {
    restrict: 'EA',
    link: function(scope, element, attr) {
      var numberExp = attr.count,
          whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs
          offset = attr.offset || 0,
          whens = scope.$eval(whenExp) || {},
          whensExpFns = {},
          startSymbol = $interpolate.startSymbol(),
          endSymbol = $interpolate.endSymbol(),
          isWhen = /^when(Minus)?(.+)$/;

      forEach(attr, function(expression, attributeName) {
        if (isWhen.test(attributeName)) {
          whens[lowercase(attributeName.replace('when', '').replace('Minus', '-'))] =
            element.attr(attr.$attr[attributeName]);
        }
      });
      forEach(whens, function(expression, key) {
        whensExpFns[key] =
          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +
            offset + endSymbol));
      });

      scope.$watch(function ngPluralizeWatch() {
        var value = parseFloat(scope.$eval(numberExp));

        if (!isNaN(value)) {
          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,
          //check it against pluralization rules in $locale service
          if (!(value in whens)) value = $locale.pluralCat(value - offset);
           return whensExpFns[value](scope, element, true);
        } else {
          return '';
        }
      }, function ngPluralizeWatchAction(newVal) {
        element.text(newVal);
      });
    }
  };
}];

/**
 * @ngdoc directive
 * @name ngRepeat
 *
 * @description
 * The `ngRepeat` directive instantiates a template once per item from a collection. Each template
 * instance gets its own scope, where the given loop variable is set to the current collection item,
 * and `$index` is set to the item index or key.
 *
 * Special properties are exposed on the local scope of each template instance, including:
 *
 * | Variable  | Type            | Details                                                                     |
 * |-----------|-----------------|-----------------------------------------------------------------------------|
 * | `$index`  | {@type number}  | iterator offset of the repeated element (0..length-1)                       |
 * | `$first`  | {@type boolean} | true if the repeated element is first in the iterator.                      |
 * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |
 * | `$last`   | {@type boolean} | true if the repeated element is last in the iterator.                       |
 * | `$even`   | {@type boolean} | true if the iterator position `$index` is even (otherwise false).           |
 * | `$odd`    | {@type boolean} | true if the iterator position `$index` is odd (otherwise false).            |
 *
 * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
 * This may be useful when, for instance, nesting ngRepeats.
 *
 * # Special repeat start and end points
 * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
 * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
 * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)
 * up to and including the ending HTML tag where **ng-repeat-end** is placed.
 *
 * The example below makes use of this feature:
 * ```html
 *   <header ng-repeat-start="item in items">
 *     Header {{ item }}
 *   </header>
 *   <div class="body">
 *     Body {{ item }}
 *   </div>
 *   <footer ng-repeat-end>
 *     Footer {{ item }}
 *   </footer>
 * ```
 *
 * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:
 * ```html
 *   <header>
 *     Header A
 *   </header>
 *   <div class="body">
 *     Body A
 *   </div>
 *   <footer>
 *     Footer A
 *   </footer>
 *   <header>
 *     Header B
 *   </header>
 *   <div class="body">
 *     Body B
 *   </div>
 *   <footer>
 *     Footer B
 *   </footer>
 * ```
 *
 * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such
 * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).
 *
 * @animations
 * **.enter** - when a new item is added to the list or when an item is revealed after a filter
 *
 * **.leave** - when an item is removed from the list or when an item is filtered out
 *
 * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
 *
 * @element ANY
 * @scope
 * @priority 1000
 * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These
 *   formats are currently supported:
 *
 *   * `variable in expression` – where variable is the user defined loop variable and `expression`
 *     is a scope expression giving the collection to enumerate.
 *
 *     For example: `album in artist.albums`.
 *
 *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,
 *     and `expression` is the scope expression giving the collection to enumerate.
 *
 *     For example: `(name, age) in {'adam':10, 'amalie':12}`.
 *
 *   * `variable in expression track by tracking_expression` – You can also provide an optional tracking function
 *     which can be used to associate the objects in the collection with the DOM elements. If no tracking function
 *     is specified the ng-repeat associates elements by identity in the collection. It is an error to have
 *     more than one tracking function to resolve to the same key. (This would mean that two distinct objects are
 *     mapped to the same DOM element, which is not possible.)  Filters should be applied to the expression,
 *     before specifying a tracking expression.
 *
 *     For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
 *     will be associated by item identity in the array.
 *
 *     For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
 *     `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
 *     with the corresponding item in the array by identity. Moving the same object in array would move the DOM
 *     element in the same way in the DOM.
 *
 *     For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this
 *     case the object identity does not matter. Two objects are considered equivalent as long as their `id`
 *     property is same.
 *
 *     For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter
 *     to items in conjunction with a tracking expression.
 *
 * @example
 * This example initializes the scope to a list of names and
 * then uses `ngRepeat` to display every person:
  <example module="ngAnimate" deps="angular-animate.js" animations="true">
    <file name="index.html">
      <div ng-init="friends = [
        {name:'John', age:25, gender:'boy'},
        {name:'Jessie', age:30, gender:'girl'},
        {name:'Johanna', age:28, gender:'girl'},
        {name:'Joy', age:15, gender:'girl'},
        {name:'Mary', age:28, gender:'girl'},
        {name:'Peter', age:95, gender:'boy'},
        {name:'Sebastian', age:50, gender:'boy'},
        {name:'Erika', age:27, gender:'girl'},
        {name:'Patrick', age:40, gender:'boy'},
        {name:'Samantha', age:60, gender:'girl'}
      ]">
        I have {{friends.length}} friends. They are:
        <input type="search" ng-model="q" placeholder="filter friends..." />
        <ul class="example-animate-container">
          <li class="animate-repeat" ng-repeat="friend in friends | filter:q">
            [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
          </li>
        </ul>
      </div>
    </file>
    <file name="animations.css">
      .example-animate-container {
        background:white;
        border:1px solid black;
        list-style:none;
        margin:0;
        padding:0 10px;
      }

      .animate-repeat {
        line-height:40px;
        list-style:none;
        box-sizing:border-box;
      }

      .animate-repeat.ng-move,
      .animate-repeat.ng-enter,
      .animate-repeat.ng-leave {
        -webkit-transition:all linear 0.5s;
        transition:all linear 0.5s;
      }

      .animate-repeat.ng-leave.ng-leave-active,
      .animate-repeat.ng-move,
      .animate-repeat.ng-enter {
        opacity:0;
        max-height:0;
      }

      .animate-repeat.ng-leave,
      .animate-repeat.ng-move.ng-move-active,
      .animate-repeat.ng-enter.ng-enter-active {
        opacity:1;
        max-height:40px;
      }
    </file>
    <file name="protractor.js" type="protractor">
      var friends = element.all(by.repeater('friend in friends'));

      it('should render initial data set', function() {
        expect(friends.count()).toBe(10);
        expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');
        expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');
        expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');
        expect(element(by.binding('friends.length')).getText())
            .toMatch("I have 10 friends. They are:");
      });

       it('should update repeater when filter predicate changes', function() {
         expect(friends.count()).toBe(10);

         element(by.model('q')).sendKeys('ma');

         expect(friends.count()).toBe(2);
         expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');
         expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');
       });
      </file>
    </example>
 */
var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
  var NG_REMOVED = '$$NG_REMOVED';
  var ngRepeatMinErr = minErr('ngRepeat');
  return {
    transclude: 'element',
    priority: 1000,
    terminal: true,
    $$tlb: true,
    link: function($scope, $element, $attr, ctrl, $transclude){
        var expression = $attr.ngRepeat;
        var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),
          trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,
          lhs, rhs, valueIdentifier, keyIdentifier,
          hashFnLocals = {$id: hashKey};

        if (!match) {
          throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
            expression);
        }

        lhs = match[1];
        rhs = match[2];
        trackByExp = match[3];

        if (trackByExp) {
          trackByExpGetter = $parse(trackByExp);
          trackByIdExpFn = function(key, value, index) {
            // assign key, value, and $index to the locals so that they can be used in hash functions
            if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
            hashFnLocals[valueIdentifier] = value;
            hashFnLocals.$index = index;
            return trackByExpGetter($scope, hashFnLocals);
          };
        } else {
          trackByIdArrayFn = function(key, value) {
            return hashKey(value);
          };
          trackByIdObjFn = function(key) {
            return key;
          };
        }

        match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);
        if (!match) {
          throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
                                                                    lhs);
        }
        valueIdentifier = match[3] || match[1];
        keyIdentifier = match[2];

        // Store a list of elements from previous run. This is a hash where key is the item from the
        // iterator, and the value is objects with following properties.
        //   - scope: bound scope
        //   - element: previous element.
        //   - index: position
        var lastBlockMap = {};

        //watch props
        $scope.$watchCollection(rhs, function ngRepeatAction(collection){
          var index, length,
              previousNode = $element[0],     // current position of the node
              nextNode,
              // Same as lastBlockMap but it has the current state. It will become the
              // lastBlockMap on the next iteration.
              nextBlockMap = {},
              arrayLength,
              childScope,
              key, value, // key/value of iteration
              trackById,
              trackByIdFn,
              collectionKeys,
              block,       // last object information {scope, element, id}
              nextBlockOrder = [],
              elementsToRemove;


          if (isArrayLike(collection)) {
            collectionKeys = collection;
            trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
          } else {
            trackByIdFn = trackByIdExpFn || trackByIdObjFn;
            // if object, extract keys, sort them and use to determine order of iteration over obj props
            collectionKeys = [];
            for (key in collection) {
              if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {
                collectionKeys.push(key);
              }
            }
            collectionKeys.sort();
          }

          arrayLength = collectionKeys.length;

          // locate existing items
          length = nextBlockOrder.length = collectionKeys.length;
          for(index = 0; index < length; index++) {
           key = (collection === collectionKeys) ? index : collectionKeys[index];
           value = collection[key];
           trackById = trackByIdFn(key, value, index);
           assertNotHasOwnProperty(trackById, '`track by` id');
           if(lastBlockMap.hasOwnProperty(trackById)) {
             block = lastBlockMap[trackById];
             delete lastBlockMap[trackById];
             nextBlockMap[trackById] = block;
             nextBlockOrder[index] = block;
           } else if (nextBlockMap.hasOwnProperty(trackById)) {
             // restore lastBlockMap
             forEach(nextBlockOrder, function(block) {
               if (block && block.scope) lastBlockMap[block.id] = block;
             });
             // This is a duplicate and we need to throw an error
             throw ngRepeatMinErr('dupes',
                  "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
                  expression, trackById, toJson(value));
           } else {
             // new never before seen block
             nextBlockOrder[index] = { id: trackById };
             nextBlockMap[trackById] = false;
           }
         }

          // remove existing items
          for (key in lastBlockMap) {
            // lastBlockMap is our own object so we don't need to use special hasOwnPropertyFn
            if (lastBlockMap.hasOwnProperty(key)) {
              block = lastBlockMap[key];
              elementsToRemove = getBlockElements(block.clone);
              $animate.leave(elementsToRemove);
              forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; });
              block.scope.$destroy();
            }
          }

          // we are not using forEach for perf reasons (trying to avoid #call)
          for (index = 0, length = collectionKeys.length; index < length; index++) {
            key = (collection === collectionKeys) ? index : collectionKeys[index];
            value = collection[key];
            block = nextBlockOrder[index];
            if (nextBlockOrder[index - 1]) previousNode = getBlockEnd(nextBlockOrder[index - 1]);

            if (block.scope) {
              // if we have already seen this object, then we need to reuse the
              // associated scope/element
              childScope = block.scope;

              nextNode = previousNode;
              do {
                nextNode = nextNode.nextSibling;
              } while(nextNode && nextNode[NG_REMOVED]);

              if (getBlockStart(block) != nextNode) {
                // existing item which got moved
                $animate.move(getBlockElements(block.clone), null, jqLite(previousNode));
              }
              previousNode = getBlockEnd(block);
            } else {
              // new item which we don't know about
              childScope = $scope.$new();
            }

            childScope[valueIdentifier] = value;
            if (keyIdentifier) childScope[keyIdentifier] = key;
            childScope.$index = index;
            childScope.$first = (index === 0);
            childScope.$last = (index === (arrayLength - 1));
            childScope.$middle = !(childScope.$first || childScope.$last);
            // jshint bitwise: false
            childScope.$odd = !(childScope.$even = (index&1) === 0);
            // jshint bitwise: true

            if (!block.scope) {
              $transclude(childScope, function(clone) {
                clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' ');
                $animate.enter(clone, null, jqLite(previousNode));
                previousNode = clone;
                block.scope = childScope;
                // Note: We only need the first/last node of the cloned nodes.
                // However, we need to keep the reference to the jqlite wrapper as it might be changed later
                // by a directive with templateUrl when its template arrives.
                block.clone = clone;
                nextBlockMap[block.id] = block;
              });
            }
          }
          lastBlockMap = nextBlockMap;
        });
    }
  };

  function getBlockStart(block) {
    return block.clone[0];
  }

  function getBlockEnd(block) {
    return block.clone[block.clone.length - 1];
  }
}];

/**
 * @ngdoc directive
 * @name ngShow
 *
 * @description
 * The `ngShow` directive shows or hides the given HTML element based on the expression
 * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding
 * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
 * in AngularJS and sets the display style to none (using an !important flag).
 * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
 *
 * ```html
 * <!-- when $scope.myValue is truthy (element is visible) -->
 * <div ng-show="myValue"></div>
 *
 * <!-- when $scope.myValue is falsy (element is hidden) -->
 * <div ng-show="myValue" class="ng-hide"></div>
 * ```
 *
 * When the `ngShow` expression evaluates to false then the `.ng-hide` CSS class is added to the class attribute
 * on the element causing it to become hidden. When true, the `.ng-hide` CSS class is removed
 * from the element causing the element not to appear hidden.
 *
 * <div class="alert alert-warning">
 * **Note:** Here is a list of values that ngShow will consider as a falsy value (case insensitive):<br />
 * "f" / "0" / "false" / "no" / "n" / "[]"
 * </div>
 *
 * ## Why is !important used?
 *
 * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
 * can be easily overridden by heavier selectors. For example, something as simple
 * as changing the display style on a HTML list item would make hidden elements appear visible.
 * This also becomes a bigger issue when dealing with CSS frameworks.
 *
 * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
 * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
 * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
 *
 * ### Overriding `.ng-hide`
 *
 * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
 * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
 * class in CSS:
 *
 * ```css
 * .ng-hide {
 *   //this is just another form of hiding an element
 *   display:block!important;
 *   position:absolute;
 *   top:-9999px;
 *   left:-9999px;
 * }
 * ```
 *
 * By default you don't need to override in CSS anything and the animations will work around the display style.
 *
 * ## A note about animations with `ngShow`
 *
 * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
 * is true and false. This system works like the animation system present with ngClass except that
 * you must also include the !important flag to override the display property
 * so that you can perform an animation when the element is hidden during the time of the animation.
 *
 * ```css
 * //
 * //a working example can be found at the bottom of this page
 * //
 * .my-element.ng-hide-add, .my-element.ng-hide-remove {
 *   transition:0.5s linear all;
 * }
 *
 * .my-element.ng-hide-add { ... }
 * .my-element.ng-hide-add.ng-hide-add-active { ... }
 * .my-element.ng-hide-remove { ... }
 * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
 * ```
 *
 * Keep in mind that, as of AngularJS version 1.2.17 (and 1.3.0-beta.11), there is no need to change the display
 * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
 *
 * @animations
 * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible
 * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden
 *
 * @element ANY
 * @param {expression} ngShow If the {@link guide/expression expression} is truthy
 *     then the element is shown or hidden respectively.
 *
 * @example
  <example module="ngAnimate" deps="angular-animate.js" animations="true">
    <file name="index.html">
      Click me: <input type="checkbox" ng-model="checked"><br/>
      <div>
        Show:
        <div class="check-element animate-show" ng-show="checked">
          <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
        </div>
      </div>
      <div>
        Hide:
        <div class="check-element animate-show" ng-hide="checked">
          <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
        </div>
      </div>
    </file>
    <file name="glyphicons.css">
      @import url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css);
    </file>
    <file name="animations.css">
      .animate-show {
        -webkit-transition:all linear 0.5s;
        transition:all linear 0.5s;
        line-height:20px;
        opacity:1;
        padding:10px;
        border:1px solid black;
        background:white;
      }

      .animate-show.ng-hide {
        line-height:0;
        opacity:0;
        padding:0 10px;
      }

      .check-element {
        padding:10px;
        border:1px solid black;
        background:white;
      }
    </file>
    <file name="protractor.js" type="protractor">
      var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
      var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));

      it('should check ng-show / ng-hide', function() {
        expect(thumbsUp.isDisplayed()).toBeFalsy();
        expect(thumbsDown.isDisplayed()).toBeTruthy();

        element(by.model('checked')).click();

        expect(thumbsUp.isDisplayed()).toBeTruthy();
        expect(thumbsDown.isDisplayed()).toBeFalsy();
      });
    </file>
  </example>
 */
var ngShowDirective = ['$animate', function($animate) {
  return function(scope, element, attr) {
    scope.$watch(attr.ngShow, function ngShowWatchAction(value){
      $animate[toBoolean(value) ? 'removeClass' : 'addClass'](element, 'ng-hide');
    });
  };
}];


/**
 * @ngdoc directive
 * @name ngHide
 *
 * @description
 * The `ngHide` directive shows or hides the given HTML element based on the expression
 * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding
 * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
 * in AngularJS and sets the display style to none (using an !important flag).
 * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
 *
 * ```html
 * <!-- when $scope.myValue is truthy (element is hidden) -->
 * <div ng-hide="myValue" class="ng-hide"></div>
 *
 * <!-- when $scope.myValue is falsy (element is visible) -->
 * <div ng-hide="myValue"></div>
 * ```
 *
 * When the `.ngHide` expression evaluates to true then the `.ng-hide` CSS class is added to the class attribute
 * on the element causing it to become hidden. When false, the `.ng-hide` CSS class is removed
 * from the element causing the element not to appear hidden.
 *
 * <div class="alert alert-warning">
 * **Note:** Here is a list of values that ngHide will consider as a falsy value (case insensitive):<br />
 * "f" / "0" / "false" / "no" / "n" / "[]"
 * </div>
 *
 * ## Why is !important used?
 *
 * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
 * can be easily overridden by heavier selectors. For example, something as simple
 * as changing the display style on a HTML list item would make hidden elements appear visible.
 * This also becomes a bigger issue when dealing with CSS frameworks.
 *
 * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
 * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
 * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
 *
 * ### Overriding `.ng-hide`
 *
 * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
 * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
 * class in CSS:
 *
 * ```css
 * .ng-hide {
 *   //this is just another form of hiding an element
 *   display:block!important;
 *   position:absolute;
 *   top:-9999px;
 *   left:-9999px;
 * }
 * ```
 *
 * By default you don't need to override in CSS anything and the animations will work around the display style.
 *
 * ## A note about animations with `ngHide`
 *
 * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
 * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`
 * CSS class is added and removed for you instead of your own CSS class.
 *
 * ```css
 * //
 * //a working example can be found at the bottom of this page
 * //
 * .my-element.ng-hide-add, .my-element.ng-hide-remove {
 *   transition:0.5s linear all;
 * }
 *
 * .my-element.ng-hide-add { ... }
 * .my-element.ng-hide-add.ng-hide-add-active { ... }
 * .my-element.ng-hide-remove { ... }
 * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
 * ```
 *
 * Keep in mind that, as of AngularJS version 1.2.17 (and 1.3.0-beta.11), there is no need to change the display
 * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
 *
 * @animations
 * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden
 * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible
 *
 * @element ANY
 * @param {expression} ngHide If the {@link guide/expression expression} is truthy then
 *     the element is shown or hidden respectively.
 *
 * @example
  <example module="ngAnimate" deps="angular-animate.js" animations="true">
    <file name="index.html">
      Click me: <input type="checkbox" ng-model="checked"><br/>
      <div>
        Show:
        <div class="check-element animate-hide" ng-show="checked">
          <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
        </div>
      </div>
      <div>
        Hide:
        <div class="check-element animate-hide" ng-hide="checked">
          <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
        </div>
      </div>
    </file>
    <file name="glyphicons.css">
      @import url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css);
    </file>
    <file name="animations.css">
      .animate-hide {
        -webkit-transition:all linear 0.5s;
        transition:all linear 0.5s;
        line-height:20px;
        opacity:1;
        padding:10px;
        border:1px solid black;
        background:white;
      }

      .animate-hide.ng-hide {
        line-height:0;
        opacity:0;
        padding:0 10px;
      }

      .check-element {
        padding:10px;
        border:1px solid black;
        background:white;
      }
    </file>
    <file name="protractor.js" type="protractor">
      var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
      var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));

      it('should check ng-show / ng-hide', function() {
        expect(thumbsUp.isDisplayed()).toBeFalsy();
        expect(thumbsDown.isDisplayed()).toBeTruthy();

        element(by.model('checked')).click();

        expect(thumbsUp.isDisplayed()).toBeTruthy();
        expect(thumbsDown.isDisplayed()).toBeFalsy();
      });
    </file>
  </example>
 */
var ngHideDirective = ['$animate', function($animate) {
  return function(scope, element, attr) {
    scope.$watch(attr.ngHide, function ngHideWatchAction(value){
      $animate[toBoolean(value) ? 'addClass' : 'removeClass'](element, 'ng-hide');
    });
  };
}];

/**
 * @ngdoc directive
 * @name ngStyle
 * @restrict AC
 *
 * @description
 * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.
 *
 * @element ANY
 * @param {expression} ngStyle
 *
 * {@link guide/expression Expression} which evals to an
 * object whose keys are CSS style names and values are corresponding values for those CSS
 * keys.
 *
 * Since some CSS style names are not valid keys for an object, they must be quoted.
 * See the 'background-color' style in the example below.
 *
 * @example
   <example>
     <file name="index.html">
        <input type="button" value="set color" ng-click="myStyle={color:'red'}">
        <input type="button" value="set background" ng-click="myStyle={'background-color':'blue'}">
        <input type="button" value="clear" ng-click="myStyle={}">
        <br/>
        <span ng-style="myStyle">Sample Text</span>
        <pre>myStyle={{myStyle}}</pre>
     </file>
     <file name="style.css">
       span {
         color: black;
       }
     </file>
     <file name="protractor.js" type="protractor">
       var colorSpan = element(by.css('span'));

       it('should check ng-style', function() {
         expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
         element(by.css('input[value=\'set color\']')).click();
         expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');
         element(by.css('input[value=clear]')).click();
         expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
       });
     </file>
   </example>
 */
var ngStyleDirective = ngDirective(function(scope, element, attr) {
  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
    if (oldStyles && (newStyles !== oldStyles)) {
      forEach(oldStyles, function(val, style) { element.css(style, '');});
    }
    if (newStyles) element.css(newStyles);
  }, true);
});

/**
 * @ngdoc directive
 * @name ngSwitch
 * @restrict EA
 *
 * @description
 * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.
 * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location
 * as specified in the template.
 *
 * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it
 * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element
 * matches the value obtained from the evaluated expression. In other words, you define a container element
 * (where you place the directive), place an expression on the **`on="..."` attribute**
 * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place
 * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on
 * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default
 * attribute is displayed.
 *
 * <div class="alert alert-info">
 * Be aware that the attribute values to match against cannot be expressions. They are interpreted
 * as literal string values to match against.
 * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the
 * value of the expression `$scope.someVal`.
 * </div>

 * @animations
 * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container
 * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM
 *
 * @usage
 *
 * ```
 * <ANY ng-switch="expression">
 *   <ANY ng-switch-when="matchValue1">...</ANY>
 *   <ANY ng-switch-when="matchValue2">...</ANY>
 *   <ANY ng-switch-default>...</ANY>
 * </ANY>
 * ```
 *
 *
 * @scope
 * @priority 800
 * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.
 * On child elements add:
 *
 * * `ngSwitchWhen`: the case statement to match against. If match then this
 *   case will be displayed. If the same match appears multiple times, all the
 *   elements will be displayed.
 * * `ngSwitchDefault`: the default case when no other case match. If there
 *   are multiple default cases, all of them will be displayed when no other
 *   case match.
 *
 *
 * @example
  <example module="switchExample" deps="angular-animate.js" animations="true">
    <file name="index.html">
      <div ng-controller="ExampleController">
        <select ng-model="selection" ng-options="item for item in items">
        </select>
        <tt>selection={{selection}}</tt>
        <hr/>
        <div class="animate-switch-container"
          ng-switch on="selection">
            <div class="animate-switch" ng-switch-when="settings">Settings Div</div>
            <div class="animate-switch" ng-switch-when="home">Home Span</div>
            <div class="animate-switch" ng-switch-default>default</div>
        </div>
      </div>
    </file>
    <file name="script.js">
      angular.module('switchExample', ['ngAnimate'])
        .controller('ExampleController', ['$scope', function($scope) {
          $scope.items = ['settings', 'home', 'other'];
          $scope.selection = $scope.items[0];
        }]);
    </file>
    <file name="animations.css">
      .animate-switch-container {
        position:relative;
        background:white;
        border:1px solid black;
        height:40px;
        overflow:hidden;
      }

      .animate-switch {
        padding:10px;
      }

      .animate-switch.ng-animate {
        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;

        position:absolute;
        top:0;
        left:0;
        right:0;
        bottom:0;
      }

      .animate-switch.ng-leave.ng-leave-active,
      .animate-switch.ng-enter {
        top:-50px;
      }
      .animate-switch.ng-leave,
      .animate-switch.ng-enter.ng-enter-active {
        top:0;
      }
    </file>
    <file name="protractor.js" type="protractor">
      var switchElem = element(by.css('[ng-switch]'));
      var select = element(by.model('selection'));

      it('should start in settings', function() {
        expect(switchElem.getText()).toMatch(/Settings Div/);
      });
      it('should change to home', function() {
        select.all(by.css('option')).get(1).click();
        expect(switchElem.getText()).toMatch(/Home Span/);
      });
      it('should select default', function() {
        select.all(by.css('option')).get(2).click();
        expect(switchElem.getText()).toMatch(/default/);
      });
    </file>
  </example>
 */
var ngSwitchDirective = ['$animate', function($animate) {
  return {
    restrict: 'EA',
    require: 'ngSwitch',

    // asks for $scope to fool the BC controller module
    controller: ['$scope', function ngSwitchController() {
     this.cases = {};
    }],
    link: function(scope, element, attr, ngSwitchController) {
      var watchExpr = attr.ngSwitch || attr.on,
          selectedTranscludes = [],
          selectedElements = [],
          previousElements = [],
          selectedScopes = [];

      scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
        var i, ii;
        for (i = 0, ii = previousElements.length; i < ii; ++i) {
          previousElements[i].remove();
        }
        previousElements.length = 0;

        for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
          var selected = selectedElements[i];
          selectedScopes[i].$destroy();
          previousElements[i] = selected;
          $animate.leave(selected, function() {
            previousElements.splice(i, 1);
          });
        }

        selectedElements.length = 0;
        selectedScopes.length = 0;

        if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
          scope.$eval(attr.change);
          forEach(selectedTranscludes, function(selectedTransclude) {
            var selectedScope = scope.$new();
            selectedScopes.push(selectedScope);
            selectedTransclude.transclude(selectedScope, function(caseElement) {
              var anchor = selectedTransclude.element;

              selectedElements.push(caseElement);
              $animate.enter(caseElement, anchor.parent(), anchor);
            });
          });
        }
      });
    }
  };
}];

var ngSwitchWhenDirective = ngDirective({
  transclude: 'element',
  priority: 800,
  require: '^ngSwitch',
  link: function(scope, element, attrs, ctrl, $transclude) {
    ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
    ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
  }
});

var ngSwitchDefaultDirective = ngDirective({
  transclude: 'element',
  priority: 800,
  require: '^ngSwitch',
  link: function(scope, element, attr, ctrl, $transclude) {
    ctrl.cases['?'] = (ctrl.cases['?'] || []);
    ctrl.cases['?'].push({ transclude: $transclude, element: element });
   }
});

/**
 * @ngdoc directive
 * @name ngTransclude
 * @restrict AC
 *
 * @description
 * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
 *
 * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.
 *
 * @element ANY
 *
 * @example
   <example module="transcludeExample">
     <file name="index.html">
       <script>
         angular.module('transcludeExample', [])
          .directive('pane', function(){
             return {
               restrict: 'E',
               transclude: true,
               scope: { title:'@' },
               template: '<div style="border: 1px solid black;">' +
                           '<div style="background-color: gray">{{title}}</div>' +
                           '<div ng-transclude></div>' +
                         '</div>'
             };
         })
         .controller('ExampleController', ['$scope', function($scope) {
           $scope.title = 'Lorem Ipsum';
           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
         }]);
       </script>
       <div ng-controller="ExampleController">
         <input ng-model="title"><br>
         <textarea ng-model="text"></textarea> <br/>
         <pane title="{{title}}">{{text}}</pane>
       </div>
     </file>
     <file name="protractor.js" type="protractor">
        it('should have transcluded', function() {
          var titleElement = element(by.model('title'));
          titleElement.clear();
          titleElement.sendKeys('TITLE');
          var textElement = element(by.model('text'));
          textElement.clear();
          textElement.sendKeys('TEXT');
          expect(element(by.binding('title')).getText()).toEqual('TITLE');
          expect(element(by.binding('text')).getText()).toEqual('TEXT');
        });
     </file>
   </example>
 *
 */
var ngTranscludeDirective = ngDirective({
  link: function($scope, $element, $attrs, controller, $transclude) {
    if (!$transclude) {
      throw minErr('ngTransclude')('orphan',
       'Illegal use of ngTransclude directive in the template! ' +
       'No parent directive that requires a transclusion found. ' +
       'Element: {0}',
       startingTag($element));
    }

    $transclude(function(clone) {
      $element.empty();
      $element.append(clone);
    });
  }
});

/**
 * @ngdoc directive
 * @name script
 * @restrict E
 *
 * @description
 * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the
 * template can be used by {@link ng.directive:ngInclude `ngInclude`},
 * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the
 * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be
 * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.
 *
 * @param {string} type Must be set to `'text/ng-template'`.
 * @param {string} id Cache name of the template.
 *
 * @example
  <example>
    <file name="index.html">
      <script type="text/ng-template" id="/tpl.html">
        Content of the template.
      </script>

      <a ng-click="currentTpl='/tpl.html'" id="tpl-link">Load inlined template</a>
      <div id="tpl-content" ng-include src="currentTpl"></div>
    </file>
    <file name="protractor.js" type="protractor">
      it('should load template defined inside script tag', function() {
        element(by.css('#tpl-link')).click();
        expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);
      });
    </file>
  </example>
 */
var scriptDirective = ['$templateCache', function($templateCache) {
  return {
    restrict: 'E',
    terminal: true,
    compile: function(element, attr) {
      if (attr.type == 'text/ng-template') {
        var templateUrl = attr.id,
            text = element[0].text;

        $templateCache.put(templateUrl, text);
      }
    }
  };
}];

var ngOptionsMinErr = minErr('ngOptions');
/**
 * @ngdoc directive
 * @name select
 * @restrict E
 *
 * @description
 * HTML `SELECT` element with angular data-binding.
 *
 * # `ngOptions`
 *
 * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
 * elements for the `<select>` element using the array or object obtained by evaluating the
 * `ngOptions` comprehension_expression.
 *
 * When an item in the `<select>` menu is selected, the array element or object property
 * represented by the selected option will be bound to the model identified by the `ngModel`
 * directive.
 *
 * <div class="alert alert-warning">
 * **Note:** `ngModel` compares by reference, not value. This is important when binding to an
 * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).
 * </div>
 *
 * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
 * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
 * option. See example below for demonstration.
 *
 * <div class="alert alert-warning">
 * **Note:** `ngOptions` provides an iterator facility for the `<option>` element which should be used instead
 * of {@link ng.directive:ngRepeat ngRepeat} when you want the
 * `select` model to be bound to a non-string value. This is because an option element can only
 * be bound to string values at present.
 * </div>
 *
 * @param {string} ngModel Assignable angular expression to data-bind to.
 * @param {string=} name Property name of the form under which the control is published.
 * @param {string=} required The control is considered valid only if value is entered.
 * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
 *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
 *    `required` when you want to data-bind to the `required` attribute.
 * @param {comprehension_expression=} ngOptions in one of the following forms:
 *
 *   * for array data sources:
 *     * `label` **`for`** `value` **`in`** `array`
 *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`
 *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`
 *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
 *   * for object data sources:
 *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
 *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
 *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
 *     * `select` **`as`** `label` **`group by`** `group`
 *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`
 *
 * Where:
 *
 *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.
 *   * `value`: local variable which will refer to each item in the `array` or each property value
 *      of `object` during iteration.
 *   * `key`: local variable which will refer to a property name in `object` during iteration.
 *   * `label`: The result of this expression will be the label for `<option>` element. The
 *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).
 *   * `select`: The result of this expression will be bound to the model of the parent `<select>`
 *      element. If not specified, `select` expression will default to `value`.
 *   * `group`: The result of this expression will be used to group options using the `<optgroup>`
 *      DOM element.
 *   * `trackexpr`: Used when working with an array of objects. The result of this expression will be
 *      used to identify the objects in the array. The `trackexpr` will most likely refer to the
 *     `value` variable (e.g. `value.propertyName`).
 *
 * @example
    <example module="selectExample">
      <file name="index.html">
        <script>
        angular.module('selectExample', [])
          .controller('ExampleController', ['$scope', function($scope) {
            $scope.colors = [
              {name:'black', shade:'dark'},
              {name:'white', shade:'light'},
              {name:'red', shade:'dark'},
              {name:'blue', shade:'dark'},
              {name:'yellow', shade:'light'}
            ];
            $scope.myColor = $scope.colors[2]; // red
          }]);
        </script>
        <div ng-controller="ExampleController">
          <ul>
            <li ng-repeat="color in colors">
              Name: <input ng-model="color.name">
              [<a href ng-click="colors.splice($index, 1)">X</a>]
            </li>
            <li>
              [<a href ng-click="colors.push({})">add</a>]
            </li>
          </ul>
          <hr/>
          Color (null not allowed):
          <select ng-model="myColor" ng-options="color.name for color in colors"></select><br>

          Color (null allowed):
          <span  class="nullable">
            <select ng-model="myColor" ng-options="color.name for color in colors">
              <option value="">-- choose color --</option>
            </select>
          </span><br/>

          Color grouped by shade:
          <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors">
          </select><br/>


          Select <a href ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</a>.<br>
          <hr/>
          Currently selected: {{ {selected_color:myColor}  }}
          <div style="border:solid 1px black; height:20px"
               ng-style="{'background-color':myColor.name}">
          </div>
        </div>
      </file>
      <file name="protractor.js" type="protractor">
         it('should check ng-options', function() {
           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
           element.all(by.model('myColor')).first().click();
           element.all(by.css('select[ng-model="myColor"] option')).first().click();
           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
           element(by.css('.nullable select[ng-model="myColor"]')).click();
           element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click();
           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');
         });
      </file>
    </example>
 */

var ngOptionsDirective = valueFn({ terminal: true });
// jshint maxlen: false
var selectDirective = ['$compile', '$parse', function($compile,   $parse) {
                         //000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888
  var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,
      nullModelCtrl = {$setViewValue: noop};
// jshint maxlen: 100

  return {
    restrict: 'E',
    require: ['select', '?ngModel'],
    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
      var self = this,
          optionsMap = {},
          ngModelCtrl = nullModelCtrl,
          nullOption,
          unknownOption;


      self.databound = $attrs.ngModel;


      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {
        ngModelCtrl = ngModelCtrl_;
        nullOption = nullOption_;
        unknownOption = unknownOption_;
      };


      self.addOption = function(value) {
        assertNotHasOwnProperty(value, '"option value"');
        optionsMap[value] = true;

        if (ngModelCtrl.$viewValue == value) {
          $element.val(value);
          if (unknownOption.parent()) unknownOption.remove();
        }
      };


      self.removeOption = function(value) {
        if (this.hasOption(value)) {
          delete optionsMap[value];
          if (ngModelCtrl.$viewValue == value) {
            this.renderUnknownOption(value);
          }
        }
      };


      self.renderUnknownOption = function(val) {
        var unknownVal = '? ' + hashKey(val) + ' ?';
        unknownOption.val(unknownVal);
        $element.prepend(unknownOption);
        $element.val(unknownVal);
        unknownOption.prop('selected', true); // needed for IE
      };


      self.hasOption = function(value) {
        return optionsMap.hasOwnProperty(value);
      };

      $scope.$on('$destroy', function() {
        // disable unknown option so that we don't do work when the whole select is being destroyed
        self.renderUnknownOption = noop;
      });
    }],

    link: function(scope, element, attr, ctrls) {
      // if ngModel is not defined, we don't need to do anything
      if (!ctrls[1]) return;

      var selectCtrl = ctrls[0],
          ngModelCtrl = ctrls[1],
          multiple = attr.multiple,
          optionsExp = attr.ngOptions,
          nullOption = false, // if false, user will not be able to select it (used by ngOptions)
          emptyOption,
          // we can't just jqLite('<option>') since jqLite is not smart enough
          // to create it in <select> and IE barfs otherwise.
          optionTemplate = jqLite(document.createElement('option')),
          optGroupTemplate =jqLite(document.createElement('optgroup')),
          unknownOption = optionTemplate.clone();

      // find "null" option
      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {
        if (children[i].value === '') {
          emptyOption = nullOption = children.eq(i);
          break;
        }
      }

      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);

      // required validator
      if (multiple) {
        ngModelCtrl.$isEmpty = function(value) {
          return !value || value.length === 0;
        };
      }

      if (optionsExp) setupAsOptions(scope, element, ngModelCtrl);
      else if (multiple) setupAsMultiple(scope, element, ngModelCtrl);
      else setupAsSingle(scope, element, ngModelCtrl, selectCtrl);


      ////////////////////////////



      function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {
        ngModelCtrl.$render = function() {
          var viewValue = ngModelCtrl.$viewValue;

          if (selectCtrl.hasOption(viewValue)) {
            if (unknownOption.parent()) unknownOption.remove();
            selectElement.val(viewValue);
            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy
          } else {
            if (isUndefined(viewValue) && emptyOption) {
              selectElement.val('');
            } else {
              selectCtrl.renderUnknownOption(viewValue);
            }
          }
        };

        selectElement.on('change', function() {
          scope.$apply(function() {
            if (unknownOption.parent()) unknownOption.remove();
            ngModelCtrl.$setViewValue(selectElement.val());
          });
        });
      }

      function setupAsMultiple(scope, selectElement, ctrl) {
        var lastView;
        ctrl.$render = function() {
          var items = new HashMap(ctrl.$viewValue);
          forEach(selectElement.find('option'), function(option) {
            option.selected = isDefined(items.get(option.value));
          });
        };

        // we have to do it on each watch since ngModel watches reference, but
        // we need to work of an array, so we need to see if anything was inserted/removed
        scope.$watch(function selectMultipleWatch() {
          if (!equals(lastView, ctrl.$viewValue)) {
            lastView = shallowCopy(ctrl.$viewValue);
            ctrl.$render();
          }
        });

        selectElement.on('change', function() {
          scope.$apply(function() {
            var array = [];
            forEach(selectElement.find('option'), function(option) {
              if (option.selected) {
                array.push(option.value);
              }
            });
            ctrl.$setViewValue(array);
          });
        });
      }

      function setupAsOptions(scope, selectElement, ctrl) {
        var match;

        if (!(match = optionsExp.match(NG_OPTIONS_REGEXP))) {
          throw ngOptionsMinErr('iexp',
            "Expected expression in form of " +
            "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
            " but got '{0}'. Element: {1}",
            optionsExp, startingTag(selectElement));
        }

        var displayFn = $parse(match[2] || match[1]),
            valueName = match[4] || match[6],
            keyName = match[5],
            groupByFn = $parse(match[3] || ''),
            valueFn = $parse(match[2] ? match[1] : valueName),
            valuesFn = $parse(match[7]),
            track = match[8],
            trackFn = track ? $parse(match[8]) : null,
            // This is an array of array of existing option groups in DOM.
            // We try to reuse these if possible
            // - optionGroupsCache[0] is the options with no option group
            // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element
            optionGroupsCache = [[{element: selectElement, label:''}]];

        if (nullOption) {
          // compile the element since there might be bindings in it
          $compile(nullOption)(scope);

          // remove the class, which is added automatically because we recompile the element and it
          // becomes the compilation root
          nullOption.removeClass('ng-scope');

          // we need to remove it before calling selectElement.empty() because otherwise IE will
          // remove the label from the element. wtf?
          nullOption.remove();
        }

        // clear contents, we'll add what's needed based on the model
        selectElement.empty();

        selectElement.on('change', function() {
          scope.$apply(function() {
            var optionGroup,
                collection = valuesFn(scope) || [],
                locals = {},
                key, value, optionElement, index, groupIndex, length, groupLength, trackIndex;

            if (multiple) {
              value = [];
              for (groupIndex = 0, groupLength = optionGroupsCache.length;
                   groupIndex < groupLength;
                   groupIndex++) {
                // list of options for that group. (first item has the parent)
                optionGroup = optionGroupsCache[groupIndex];

                for(index = 1, length = optionGroup.length; index < length; index++) {
                  if ((optionElement = optionGroup[index].element)[0].selected) {
                    key = optionElement.val();
                    if (keyName) locals[keyName] = key;
                    if (trackFn) {
                      for (trackIndex = 0; trackIndex < collection.length; trackIndex++) {
                        locals[valueName] = collection[trackIndex];
                        if (trackFn(scope, locals) == key) break;
                      }
                    } else {
                      locals[valueName] = collection[key];
                    }
                    value.push(valueFn(scope, locals));
                  }
                }
              }
            } else {
              key = selectElement.val();
              if (key == '?') {
                value = undefined;
              } else if (key === ''){
                value = null;
              } else {
                if (trackFn) {
                  for (trackIndex = 0; trackIndex < collection.length; trackIndex++) {
                    locals[valueName] = collection[trackIndex];
                    if (trackFn(scope, locals) == key) {
                      value = valueFn(scope, locals);
                      break;
                    }
                  }
                } else {
                  locals[valueName] = collection[key];
                  if (keyName) locals[keyName] = key;
                  value = valueFn(scope, locals);
                }
              }
            }
            ctrl.$setViewValue(value);
            render();
          });
        });

        ctrl.$render = render;

        scope.$watchCollection(valuesFn, render);
        scope.$watchCollection(function () {
          var locals = {},
              values = valuesFn(scope);
          if (values) {
            var toDisplay = new Array(values.length);
            for (var i = 0, ii = values.length; i < ii; i++) {
              locals[valueName] = values[i];
              toDisplay[i] = displayFn(scope, locals);
            }
            return toDisplay;
          }
        }, render);

        if ( multiple ) {
          scope.$watchCollection(function() { return ctrl.$modelValue; }, render);
        }

        function getSelectedSet() {
          var selectedSet = false;
          if (multiple) {
            var modelValue = ctrl.$modelValue;
            if (trackFn && isArray(modelValue)) {
              selectedSet = new HashMap([]);
              var locals = {};
              for (var trackIndex = 0; trackIndex < modelValue.length; trackIndex++) {
                locals[valueName] = modelValue[trackIndex];
                selectedSet.put(trackFn(scope, locals), modelValue[trackIndex]);
              }
            } else {
              selectedSet = new HashMap(modelValue);
            }
          }
          return selectedSet;
        }


        function render() {
              // Temporary location for the option groups before we render them
          var optionGroups = {'':[]},
              optionGroupNames = [''],
              optionGroupName,
              optionGroup,
              option,
              existingParent, existingOptions, existingOption,
              modelValue = ctrl.$modelValue,
              values = valuesFn(scope) || [],
              keys = keyName ? sortedKeys(values) : values,
              key,
              groupLength, length,
              groupIndex, index,
              locals = {},
              selected,
              selectedSet = getSelectedSet(),
              lastElement,
              element,
              label;


          // We now build up the list of options we need (we merge later)
          for (index = 0; length = keys.length, index < length; index++) {

            key = index;
            if (keyName) {
              key = keys[index];
              if ( key.charAt(0) === '$' ) continue;
              locals[keyName] = key;
            }

            locals[valueName] = values[key];

            optionGroupName = groupByFn(scope, locals) || '';
            if (!(optionGroup = optionGroups[optionGroupName])) {
              optionGroup = optionGroups[optionGroupName] = [];
              optionGroupNames.push(optionGroupName);
            }
            if (multiple) {
              selected = isDefined(
                selectedSet.remove(trackFn ? trackFn(scope, locals) : valueFn(scope, locals))
              );
            } else {
              if (trackFn) {
                var modelCast = {};
                modelCast[valueName] = modelValue;
                selected = trackFn(scope, modelCast) === trackFn(scope, locals);
              } else {
                selected = modelValue === valueFn(scope, locals);
              }
              selectedSet = selectedSet || selected; // see if at least one item is selected
            }
            label = displayFn(scope, locals); // what will be seen by the user

            // doing displayFn(scope, locals) || '' overwrites zero values
            label = isDefined(label) ? label : '';
            optionGroup.push({
              // either the index into array or key from object
              id: trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index),
              label: label,
              selected: selected                   // determine if we should be selected
            });
          }
          if (!multiple) {
            if (nullOption || modelValue === null) {
              // insert null option if we have a placeholder, or the model is null
              optionGroups[''].unshift({id:'', label:'', selected:!selectedSet});
            } else if (!selectedSet) {
              // option could not be found, we have to insert the undefined item
              optionGroups[''].unshift({id:'?', label:'', selected:true});
            }
          }

          // Now we need to update the list of DOM nodes to match the optionGroups we computed above
          for (groupIndex = 0, groupLength = optionGroupNames.length;
               groupIndex < groupLength;
               groupIndex++) {
            // current option group name or '' if no group
            optionGroupName = optionGroupNames[groupIndex];

            // list of options for that group. (first item has the parent)
            optionGroup = optionGroups[optionGroupName];

            if (optionGroupsCache.length <= groupIndex) {
              // we need to grow the optionGroups
              existingParent = {
                element: optGroupTemplate.clone().attr('label', optionGroupName),
                label: optionGroup.label
              };
              existingOptions = [existingParent];
              optionGroupsCache.push(existingOptions);
              selectElement.append(existingParent.element);
            } else {
              existingOptions = optionGroupsCache[groupIndex];
              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element

              // update the OPTGROUP label if not the same.
              if (existingParent.label != optionGroupName) {
                existingParent.element.attr('label', existingParent.label = optionGroupName);
              }
            }

            lastElement = null;  // start at the beginning
            for(index = 0, length = optionGroup.length; index < length; index++) {
              option = optionGroup[index];
              if ((existingOption = existingOptions[index+1])) {
                // reuse elements
                lastElement = existingOption.element;
                if (existingOption.label !== option.label) {
                  lastElement.text(existingOption.label = option.label);
                  lastElement.prop('label', existingOption.label);
                }
                if (existingOption.id !== option.id) {
                  lastElement.val(existingOption.id = option.id);
                }
                // lastElement.prop('selected') provided by jQuery has side-effects
                if (lastElement[0].selected !== option.selected) {
                  lastElement.prop('selected', (existingOption.selected = option.selected));
                  if (msie) {
                    // See #7692
                    // The selected item wouldn't visually update on IE without this.
                    // Tested on Win7: IE9, IE10 and IE11. Future IEs should be tested as well
                    lastElement.prop('selected', existingOption.selected);
                  }
                }
              } else {
                // grow elements

                // if it's a null option
                if (option.id === '' && nullOption) {
                  // put back the pre-compiled element
                  element = nullOption;
                } else {
                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but
                  // in this version of jQuery on some browser the .text() returns a string
                  // rather then the element.
                  (element = optionTemplate.clone())
                      .val(option.id)
                      .prop('selected', option.selected)
                      .attr('selected', option.selected)
                      .prop('label', option.label)
                      .text(option.label);
                }

                existingOptions.push(existingOption = {
                    element: element,
                    label: option.label,
                    id: option.id,
                    selected: option.selected
                });
                selectCtrl.addOption(option.label, element);
                if (lastElement) {
                  lastElement.after(element);
                } else {
                  existingParent.element.append(element);
                }
                lastElement = element;
              }
            }
            // remove any excessive OPTIONs in a group
            index++; // increment since the existingOptions[0] is parent element not OPTION
            while(existingOptions.length > index) {
              option = existingOptions.pop();
              selectCtrl.removeOption(option.label);
              option.element.remove();
            }
          }
          // remove any excessive OPTGROUPs from select
          while(optionGroupsCache.length > groupIndex) {
            optionGroupsCache.pop()[0].element.remove();
          }
        }
      }
    }
  };
}];

var optionDirective = ['$interpolate', function($interpolate) {
  var nullSelectCtrl = {
    addOption: noop,
    removeOption: noop
  };

  return {
    restrict: 'E',
    priority: 100,
    compile: function(element, attr) {
      if (isUndefined(attr.value)) {
        var interpolateFn = $interpolate(element.text(), true);
        if (!interpolateFn) {
          attr.$set('value', element.text());
        }
      }

      return function (scope, element, attr) {
        var selectCtrlName = '$selectController',
            parent = element.parent(),
            selectCtrl = parent.data(selectCtrlName) ||
              parent.parent().data(selectCtrlName); // in case we are in optgroup

        if (selectCtrl && selectCtrl.databound) {
          // For some reason Opera defaults to true and if not overridden this messes up the repeater.
          // We don't want the view to drive the initialization of the model anyway.
          element.prop('selected', false);
        } else {
          selectCtrl = nullSelectCtrl;
        }

        if (interpolateFn) {
          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
            attr.$set('value', newVal);
            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);
            selectCtrl.addOption(newVal);
          });
        } else {
          selectCtrl.addOption(attr.value);
        }

        element.on('$destroy', function() {
          selectCtrl.removeOption(attr.value);
        });
      };
    }
  };
}];

var styleDirective = valueFn({
  restrict: 'E',
  terminal: true
});

  if (window.angular.bootstrap) {
    //AngularJS is already loaded, so we can return here...
    console.log('WARNING: Tried to load angular more than once.');
    return;
  }

  //try to bind to jquery now so that one can write angular.element().read()
  //but we will rebind on bootstrap again.
  bindJQuery();

  publishExternalAPI(angular);

  jqLite(document).ready(function() {
    angularInit(document, bootstrap);
  });

})(window, document);

!window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}.ng-animate-block-transitions{transition:0s all!important;-webkit-transition:0s all!important;}.ng-hide-add-active,.ng-hide-remove{display:block!important;}</style>');
/**
 * @license AngularJS v1.2.26
 * (c) 2010-2014 Google, Inc. http://angularjs.org
 * License: MIT
 */
(function(window, angular, undefined) {'use strict';

/**
 * @ngdoc module
 * @name ngRoute
 * @description
 *
 * # ngRoute
 *
 * The `ngRoute` module provides routing and deeplinking services and directives for angular apps.
 *
 * ## Example
 * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
 *
 *
 * <div doc-module-components="ngRoute"></div>
 */
 /* global -ngRouteModule */
var ngRouteModule = angular.module('ngRoute', ['ng']).
                        provider('$route', $RouteProvider);

/**
 * @ngdoc provider
 * @name $routeProvider
 * @kind function
 *
 * @description
 *
 * Used for configuring routes.
 *
 * ## Example
 * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
 *
 * ## Dependencies
 * Requires the {@link ngRoute `ngRoute`} module to be installed.
 */
function $RouteProvider(){
  function inherit(parent, extra) {
    return angular.extend(new (angular.extend(function() {}, {prototype:parent}))(), extra);
  }

  var routes = {};

  /**
   * @ngdoc method
   * @name $routeProvider#when
   *
   * @param {string} path Route path (matched against `$location.path`). If `$location.path`
   *    contains redundant trailing slash or is missing one, the route will still match and the
   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the
   *    route definition.
   *
   *    * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up
   *        to the next slash are matched and stored in `$routeParams` under the given `name`
   *        when the route matches.
   *    * `path` can contain named groups starting with a colon and ending with a star:
   *        e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`
   *        when the route matches.
   *    * `path` can contain optional named groups with a question mark: e.g.`:name?`.
   *
   *    For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
   *    `/color/brown/largecode/code/with/slashes/edit` and extract:
   *
   *    * `color: brown`
   *    * `largecode: code/with/slashes`.
   *
   *
   * @param {Object} route Mapping information to be assigned to `$route.current` on route
   *    match.
   *
   *    Object properties:
   *
   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with
   *      newly created scope or the name of a {@link angular.Module#controller registered
   *      controller} if passed as a string.
   *    - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be
   *      published to scope under the `controllerAs` name.
   *    - `template` – `{string=|function()=}` – html template as a string or a function that
   *      returns an html template as a string which should be used by {@link
   *      ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
   *      This property takes precedence over `templateUrl`.
   *
   *      If `template` is a function, it will be called with the following parameters:
   *
   *      - `{Array.<Object>}` - route parameters extracted from the current
   *        `$location.path()` by applying the current route
   *
   *    - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
   *      template that should be used by {@link ngRoute.directive:ngView ngView}.
   *
   *      If `templateUrl` is a function, it will be called with the following parameters:
   *
   *      - `{Array.<Object>}` - route parameters extracted from the current
   *        `$location.path()` by applying the current route
   *
   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
   *      be injected into the controller. If any of these dependencies are promises, the router
   *      will wait for them all to be resolved or one to be rejected before the controller is
   *      instantiated.
   *      If all the promises are resolved successfully, the values of the resolved promises are
   *      injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is
   *      fired. If any of the promises are rejected the
   *      {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object
   *      is:
   *
   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.
   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.
   *        Otherwise if function, then it is {@link auto.$injector#invoke injected}
   *        and the return value is treated as the dependency. If the result is a promise, it is
   *        resolved before its value is injected into the controller. Be aware that
   *        `ngRoute.$routeParams` will still refer to the previous route within these resolve
   *        functions.  Use `$route.current.params` to access the new route parameters, instead.
   *
   *    - `redirectTo` – {(string|function())=} – value to update
   *      {@link ng.$location $location} path with and trigger route redirection.
   *
   *      If `redirectTo` is a function, it will be called with the following parameters:
   *
   *      - `{Object.<string>}` - route parameters extracted from the current
   *        `$location.path()` by applying the current route templateUrl.
   *      - `{string}` - current `$location.path()`
   *      - `{Object}` - current `$location.search()`
   *
   *      The custom `redirectTo` function is expected to return a string which will be used
   *      to update `$location.path()` and `$location.search()`.
   *
   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()`
   *      or `$location.hash()` changes.
   *
   *      If the option is set to `false` and url in the browser changes, then
   *      `$routeUpdate` event is broadcasted on the root scope.
   *
   *    - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive
   *
   *      If the option is set to `true`, then the particular route can be matched without being
   *      case sensitive
   *
   * @returns {Object} self
   *
   * @description
   * Adds a new route definition to the `$route` service.
   */
  this.when = function(path, route) {
    routes[path] = angular.extend(
      {reloadOnSearch: true},
      route,
      path && pathRegExp(path, route)
    );

    // create redirection for trailing slashes
    if (path) {
      var redirectPath = (path[path.length-1] == '/')
            ? path.substr(0, path.length-1)
            : path +'/';

      routes[redirectPath] = angular.extend(
        {redirectTo: path},
        pathRegExp(redirectPath, route)
      );
    }

    return this;
  };

   /**
    * @param path {string} path
    * @param opts {Object} options
    * @return {?Object}
    *
    * @description
    * Normalizes the given path, returning a regular expression
    * and the original path.
    *
    * Inspired by pathRexp in visionmedia/express/lib/utils.js.
    */
  function pathRegExp(path, opts) {
    var insensitive = opts.caseInsensitiveMatch,
        ret = {
          originalPath: path,
          regexp: path
        },
        keys = ret.keys = [];

    path = path
      .replace(/([().])/g, '\\$1')
      .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option){
        var optional = option === '?' ? option : null;
        var star = option === '*' ? option : null;
        keys.push({ name: key, optional: !!optional });
        slash = slash || '';
        return ''
          + (optional ? '' : slash)
          + '(?:'
          + (optional ? slash : '')
          + (star && '(.+?)' || '([^/]+)')
          + (optional || '')
          + ')'
          + (optional || '');
      })
      .replace(/([\/$\*])/g, '\\$1');

    ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');
    return ret;
  }

  /**
   * @ngdoc method
   * @name $routeProvider#otherwise
   *
   * @description
   * Sets route definition that will be used on route change when no other route definition
   * is matched.
   *
   * @param {Object} params Mapping information to be assigned to `$route.current`.
   * @returns {Object} self
   */
  this.otherwise = function(params) {
    this.when(null, params);
    return this;
  };


  this.$get = ['$rootScope',
               '$location',
               '$routeParams',
               '$q',
               '$injector',
               '$http',
               '$templateCache',
               '$sce',
      function($rootScope, $location, $routeParams, $q, $injector, $http, $templateCache, $sce) {

    /**
     * @ngdoc service
     * @name $route
     * @requires $location
     * @requires $routeParams
     *
     * @property {Object} current Reference to the current route definition.
     * The route definition contains:
     *
     *   - `controller`: The controller constructor as define in route definition.
     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for
     *     controller instantiation. The `locals` contain
     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:
     *
     *     - `$scope` - The current route scope.
     *     - `$template` - The current route template HTML.
     *
     * @property {Object} routes Object with all route configuration Objects as its properties.
     *
     * @description
     * `$route` is used for deep-linking URLs to controllers and views (HTML partials).
     * It watches `$location.url()` and tries to map the path to an existing route definition.
     *
     * Requires the {@link ngRoute `ngRoute`} module to be installed.
     *
     * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.
     *
     * The `$route` service is typically used in conjunction with the
     * {@link ngRoute.directive:ngView `ngView`} directive and the
     * {@link ngRoute.$routeParams `$routeParams`} service.
     *
     * @example
     * This example shows how changing the URL hash causes the `$route` to match a route against the
     * URL, and the `ngView` pulls in the partial.
     *
     * <example name="$route-service" module="ngRouteExample"
     *          deps="angular-route.js" fixBase="true">
     *   <file name="index.html">
     *     <div ng-controller="MainController">
     *       Choose:
     *       <a href="Book/Moby">Moby</a> |
     *       <a href="Book/Moby/ch/1">Moby: Ch1</a> |
     *       <a href="Book/Gatsby">Gatsby</a> |
     *       <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
     *       <a href="Book/Scarlet">Scarlet Letter</a><br/>
     *
     *       <div ng-view></div>
     *
     *       <hr />
     *
     *       <pre>$location.path() = {{$location.path()}}</pre>
     *       <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
     *       <pre>$route.current.params = {{$route.current.params}}</pre>
     *       <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
     *       <pre>$routeParams = {{$routeParams}}</pre>
     *     </div>
     *   </file>
     *
     *   <file name="book.html">
     *     controller: {{name}}<br />
     *     Book Id: {{params.bookId}}<br />
     *   </file>
     *
     *   <file name="chapter.html">
     *     controller: {{name}}<br />
     *     Book Id: {{params.bookId}}<br />
     *     Chapter Id: {{params.chapterId}}
     *   </file>
     *
     *   <file name="script.js">
     *     angular.module('ngRouteExample', ['ngRoute'])
     *
     *      .controller('MainController', function($scope, $route, $routeParams, $location) {
     *          $scope.$route = $route;
     *          $scope.$location = $location;
     *          $scope.$routeParams = $routeParams;
     *      })
     *
     *      .controller('BookController', function($scope, $routeParams) {
     *          $scope.name = "BookController";
     *          $scope.params = $routeParams;
     *      })
     *
     *      .controller('ChapterController', function($scope, $routeParams) {
     *          $scope.name = "ChapterController";
     *          $scope.params = $routeParams;
     *      })
     *
     *     .config(function($routeProvider, $locationProvider) {
     *       $routeProvider
     *        .when('/Book/:bookId', {
     *         templateUrl: 'book.html',
     *         controller: 'BookController',
     *         resolve: {
     *           // I will cause a 1 second delay
     *           delay: function($q, $timeout) {
     *             var delay = $q.defer();
     *             $timeout(delay.resolve, 1000);
     *             return delay.promise;
     *           }
     *         }
     *       })
     *       .when('/Book/:bookId/ch/:chapterId', {
     *         templateUrl: 'chapter.html',
     *         controller: 'ChapterController'
     *       });
     *
     *       // configure html5 to get links working on jsfiddle
     *       $locationProvider.html5Mode(true);
     *     });
     *
     *   </file>
     *
     *   <file name="protractor.js" type="protractor">
     *     it('should load and compile correct template', function() {
     *       element(by.linkText('Moby: Ch1')).click();
     *       var content = element(by.css('[ng-view]')).getText();
     *       expect(content).toMatch(/controller\: ChapterController/);
     *       expect(content).toMatch(/Book Id\: Moby/);
     *       expect(content).toMatch(/Chapter Id\: 1/);
     *
     *       element(by.partialLinkText('Scarlet')).click();
     *
     *       content = element(by.css('[ng-view]')).getText();
     *       expect(content).toMatch(/controller\: BookController/);
     *       expect(content).toMatch(/Book Id\: Scarlet/);
     *     });
     *   </file>
     * </example>
     */

    /**
     * @ngdoc event
     * @name $route#$routeChangeStart
     * @eventType broadcast on root scope
     * @description
     * Broadcasted before a route change. At this  point the route services starts
     * resolving all of the dependencies needed for the route change to occur.
     * Typically this involves fetching the view template as well as any dependencies
     * defined in `resolve` route property. Once  all of the dependencies are resolved
     * `$routeChangeSuccess` is fired.
     *
     * @param {Object} angularEvent Synthetic event object.
     * @param {Route} next Future route information.
     * @param {Route} current Current route information.
     */

    /**
     * @ngdoc event
     * @name $route#$routeChangeSuccess
     * @eventType broadcast on root scope
     * @description
     * Broadcasted after a route dependencies are resolved.
     * {@link ngRoute.directive:ngView ngView} listens for the directive
     * to instantiate the controller and render the view.
     *
     * @param {Object} angularEvent Synthetic event object.
     * @param {Route} current Current route information.
     * @param {Route|Undefined} previous Previous route information, or undefined if current is
     * first route entered.
     */

    /**
     * @ngdoc event
     * @name $route#$routeChangeError
     * @eventType broadcast on root scope
     * @description
     * Broadcasted if any of the resolve promises are rejected.
     *
     * @param {Object} angularEvent Synthetic event object
     * @param {Route} current Current route information.
     * @param {Route} previous Previous route information.
     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.
     */

    /**
     * @ngdoc event
     * @name $route#$routeUpdate
     * @eventType broadcast on root scope
     * @description
     *
     * The `reloadOnSearch` property has been set to false, and we are reusing the same
     * instance of the Controller.
     */

    var forceReload = false,
        $route = {
          routes: routes,

          /**
           * @ngdoc method
           * @name $route#reload
           *
           * @description
           * Causes `$route` service to reload the current route even if
           * {@link ng.$location $location} hasn't changed.
           *
           * As a result of that, {@link ngRoute.directive:ngView ngView}
           * creates new scope, reinstantiates the controller.
           */
          reload: function() {
            forceReload = true;
            $rootScope.$evalAsync(updateRoute);
          }
        };

    $rootScope.$on('$locationChangeSuccess', updateRoute);

    return $route;

    /////////////////////////////////////////////////////

    /**
     * @param on {string} current url
     * @param route {Object} route regexp to match the url against
     * @return {?Object}
     *
     * @description
     * Check if the route matches the current url.
     *
     * Inspired by match in
     * visionmedia/express/lib/router/router.js.
     */
    function switchRouteMatcher(on, route) {
      var keys = route.keys,
          params = {};

      if (!route.regexp) return null;

      var m = route.regexp.exec(on);
      if (!m) return null;

      for (var i = 1, len = m.length; i < len; ++i) {
        var key = keys[i - 1];

        var val = m[i];

        if (key && val) {
          params[key.name] = val;
        }
      }
      return params;
    }

    function updateRoute() {
      var next = parseRoute(),
          last = $route.current;

      if (next && last && next.$$route === last.$$route
          && angular.equals(next.pathParams, last.pathParams)
          && !next.reloadOnSearch && !forceReload) {
        last.params = next.params;
        angular.copy(last.params, $routeParams);
        $rootScope.$broadcast('$routeUpdate', last);
      } else if (next || last) {
        forceReload = false;
        $rootScope.$broadcast('$routeChangeStart', next, last);
        $route.current = next;
        if (next) {
          if (next.redirectTo) {
            if (angular.isString(next.redirectTo)) {
              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)
                       .replace();
            } else {
              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))
                       .replace();
            }
          }
        }

        $q.when(next).
          then(function() {
            if (next) {
              var locals = angular.extend({}, next.resolve),
                  template, templateUrl;

              angular.forEach(locals, function(value, key) {
                locals[key] = angular.isString(value) ?
                    $injector.get(value) : $injector.invoke(value);
              });

              if (angular.isDefined(template = next.template)) {
                if (angular.isFunction(template)) {
                  template = template(next.params);
                }
              } else if (angular.isDefined(templateUrl = next.templateUrl)) {
                if (angular.isFunction(templateUrl)) {
                  templateUrl = templateUrl(next.params);
                }
                templateUrl = $sce.getTrustedResourceUrl(templateUrl);
                if (angular.isDefined(templateUrl)) {
                  next.loadedTemplateUrl = templateUrl;
                  template = $http.get(templateUrl, {cache: $templateCache}).
                      then(function(response) { return response.data; });
                }
              }
              if (angular.isDefined(template)) {
                locals['$template'] = template;
              }
              return $q.all(locals);
            }
          }).
          // after route change
          then(function(locals) {
            if (next == $route.current) {
              if (next) {
                next.locals = locals;
                angular.copy(next.params, $routeParams);
              }
              $rootScope.$broadcast('$routeChangeSuccess', next, last);
            }
          }, function(error) {
            if (next == $route.current) {
              $rootScope.$broadcast('$routeChangeError', next, last, error);
            }
          });
      }
    }


    /**
     * @returns {Object} the current active route, by matching it against the URL
     */
    function parseRoute() {
      // Match a route
      var params, match;
      angular.forEach(routes, function(route, path) {
        if (!match && (params = switchRouteMatcher($location.path(), route))) {
          match = inherit(route, {
            params: angular.extend({}, $location.search(), params),
            pathParams: params});
          match.$$route = route;
        }
      });
      // No route matched; fallback to "otherwise" route
      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});
    }

    /**
     * @returns {string} interpolation of the redirect path with the parameters
     */
    function interpolate(string, params) {
      var result = [];
      angular.forEach((string||'').split(':'), function(segment, i) {
        if (i === 0) {
          result.push(segment);
        } else {
          var segmentMatch = segment.match(/(\w+)(.*)/);
          var key = segmentMatch[1];
          result.push(params[key]);
          result.push(segmentMatch[2] || '');
          delete params[key];
        }
      });
      return result.join('');
    }
  }];
}

ngRouteModule.provider('$routeParams', $RouteParamsProvider);


/**
 * @ngdoc service
 * @name $routeParams
 * @requires $route
 *
 * @description
 * The `$routeParams` service allows you to retrieve the current set of route parameters.
 *
 * Requires the {@link ngRoute `ngRoute`} module to be installed.
 *
 * The route parameters are a combination of {@link ng.$location `$location`}'s
 * {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}.
 * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.
 *
 * In case of parameter name collision, `path` params take precedence over `search` params.
 *
 * The service guarantees that the identity of the `$routeParams` object will remain unchanged
 * (but its properties will likely change) even when a route change occurs.
 *
 * Note that the `$routeParams` are only updated *after* a route change completes successfully.
 * This means that you cannot rely on `$routeParams` being correct in route resolve functions.
 * Instead you can use `$route.current.params` to access the new route's parameters.
 *
 * @example
 * ```js
 *  // Given:
 *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
 *  // Route: /Chapter/:chapterId/Section/:sectionId
 *  //
 *  // Then
 *  $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
 * ```
 */
function $RouteParamsProvider() {
  this.$get = function() { return {}; };
}

ngRouteModule.directive('ngView', ngViewFactory);
ngRouteModule.directive('ngView', ngViewFillContentFactory);


/**
 * @ngdoc directive
 * @name ngView
 * @restrict ECA
 *
 * @description
 * # Overview
 * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
 * including the rendered template of the current route into the main layout (`index.html`) file.
 * Every time the current route changes, the included view changes with it according to the
 * configuration of the `$route` service.
 *
 * Requires the {@link ngRoute `ngRoute`} module to be installed.
 *
 * @animations
 * enter - animation is used to bring new content into the browser.
 * leave - animation is used to animate existing content away.
 *
 * The enter and leave animation occur concurrently.
 *
 * @scope
 * @priority 400
 * @param {string=} onload Expression to evaluate whenever the view updates.
 *
 * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll
 *                  $anchorScroll} to scroll the viewport after the view is updated.
 *
 *                  - If the attribute is not set, disable scrolling.
 *                  - If the attribute is set without value, enable scrolling.
 *                  - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated
 *                    as an expression yields a truthy value.
 * @example
    <example name="ngView-directive" module="ngViewExample"
             deps="angular-route.js;angular-animate.js"
             animations="true" fixBase="true">
      <file name="index.html">
        <div ng-controller="MainCtrl as main">
          Choose:
          <a href="Book/Moby">Moby</a> |
          <a href="Book/Moby/ch/1">Moby: Ch1</a> |
          <a href="Book/Gatsby">Gatsby</a> |
          <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
          <a href="Book/Scarlet">Scarlet Letter</a><br/>

          <div class="view-animate-container">
            <div ng-view class="view-animate"></div>
          </div>
          <hr />

          <pre>$location.path() = {{main.$location.path()}}</pre>
          <pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>
          <pre>$route.current.params = {{main.$route.current.params}}</pre>
          <pre>$route.current.scope.name = {{main.$route.current.scope.name}}</pre>
          <pre>$routeParams = {{main.$routeParams}}</pre>
        </div>
      </file>

      <file name="book.html">
        <div>
          controller: {{book.name}}<br />
          Book Id: {{book.params.bookId}}<br />
        </div>
      </file>

      <file name="chapter.html">
        <div>
          controller: {{chapter.name}}<br />
          Book Id: {{chapter.params.bookId}}<br />
          Chapter Id: {{chapter.params.chapterId}}
        </div>
      </file>

      <file name="animations.css">
        .view-animate-container {
          position:relative;
          height:100px!important;
          position:relative;
          background:white;
          border:1px solid black;
          height:40px;
          overflow:hidden;
        }

        .view-animate {
          padding:10px;
        }

        .view-animate.ng-enter, .view-animate.ng-leave {
          -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
          transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;

          display:block;
          width:100%;
          border-left:1px solid black;

          position:absolute;
          top:0;
          left:0;
          right:0;
          bottom:0;
          padding:10px;
        }

        .view-animate.ng-enter {
          left:100%;
        }
        .view-animate.ng-enter.ng-enter-active {
          left:0;
        }
        .view-animate.ng-leave.ng-leave-active {
          left:-100%;
        }
      </file>

      <file name="script.js">
        angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])
          .config(['$routeProvider', '$locationProvider',
            function($routeProvider, $locationProvider) {
              $routeProvider
                .when('/Book/:bookId', {
                  templateUrl: 'book.html',
                  controller: 'BookCtrl',
                  controllerAs: 'book'
                })
                .when('/Book/:bookId/ch/:chapterId', {
                  templateUrl: 'chapter.html',
                  controller: 'ChapterCtrl',
                  controllerAs: 'chapter'
                });

              $locationProvider.html5Mode(true);
          }])
          .controller('MainCtrl', ['$route', '$routeParams', '$location',
            function($route, $routeParams, $location) {
              this.$route = $route;
              this.$location = $location;
              this.$routeParams = $routeParams;
          }])
          .controller('BookCtrl', ['$routeParams', function($routeParams) {
            this.name = "BookCtrl";
            this.params = $routeParams;
          }])
          .controller('ChapterCtrl', ['$routeParams', function($routeParams) {
            this.name = "ChapterCtrl";
            this.params = $routeParams;
          }]);

      </file>

      <file name="protractor.js" type="protractor">
        it('should load and compile correct template', function() {
          element(by.linkText('Moby: Ch1')).click();
          var content = element(by.css('[ng-view]')).getText();
          expect(content).toMatch(/controller\: ChapterCtrl/);
          expect(content).toMatch(/Book Id\: Moby/);
          expect(content).toMatch(/Chapter Id\: 1/);

          element(by.partialLinkText('Scarlet')).click();

          content = element(by.css('[ng-view]')).getText();
          expect(content).toMatch(/controller\: BookCtrl/);
          expect(content).toMatch(/Book Id\: Scarlet/);
        });
      </file>
    </example>
 */


/**
 * @ngdoc event
 * @name ngView#$viewContentLoaded
 * @eventType emit on the current ngView scope
 * @description
 * Emitted every time the ngView content is reloaded.
 */
ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
function ngViewFactory(   $route,   $anchorScroll,   $animate) {
  return {
    restrict: 'ECA',
    terminal: true,
    priority: 400,
    transclude: 'element',
    link: function(scope, $element, attr, ctrl, $transclude) {
        var currentScope,
            currentElement,
            previousElement,
            autoScrollExp = attr.autoscroll,
            onloadExp = attr.onload || '';

        scope.$on('$routeChangeSuccess', update);
        update();

        function cleanupLastView() {
          if(previousElement) {
            previousElement.remove();
            previousElement = null;
          }
          if(currentScope) {
            currentScope.$destroy();
            currentScope = null;
          }
          if(currentElement) {
            $animate.leave(currentElement, function() {
              previousElement = null;
            });
            previousElement = currentElement;
            currentElement = null;
          }
        }

        function update() {
          var locals = $route.current && $route.current.locals,
              template = locals && locals.$template;

          if (angular.isDefined(template)) {
            var newScope = scope.$new();
            var current = $route.current;

            // Note: This will also link all children of ng-view that were contained in the original
            // html. If that content contains controllers, ... they could pollute/change the scope.
            // However, using ng-view on an element with additional content does not make sense...
            // Note: We can't remove them in the cloneAttchFn of $transclude as that
            // function is called before linking the content, which would apply child
            // directives to non existing elements.
            var clone = $transclude(newScope, function(clone) {
              $animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {
                if (angular.isDefined(autoScrollExp)
                  && (!autoScrollExp || scope.$eval(autoScrollExp))) {
                  $anchorScroll();
                }
              });
              cleanupLastView();
            });

            currentElement = clone;
            currentScope = current.scope = newScope;
            currentScope.$emit('$viewContentLoaded');
            currentScope.$eval(onloadExp);
          } else {
            cleanupLastView();
          }
        }
    }
  };
}

// This directive is called during the $transclude call of the first `ngView` directive.
// It will replace and compile the content of the element with the loaded template.
// We need this directive so that the element content is already filled when
// the link function of another directive on the same element as ngView
// is called.
ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
function ngViewFillContentFactory($compile, $controller, $route) {
  return {
    restrict: 'ECA',
    priority: -400,
    link: function(scope, $element) {
      var current = $route.current,
          locals = current.locals;

      $element.html(locals.$template);

      var link = $compile($element.contents());

      if (current.controller) {
        locals.$scope = scope;
        var controller = $controller(current.controller, locals);
        if (current.controllerAs) {
          scope[current.controllerAs] = controller;
        }
        $element.data('$ngControllerController', controller);
        $element.children().data('$ngControllerController', controller);
      }

      link(scope);
    }
  };
}


})(window, window.angular);

;(function(win){
	var store = {},
		doc = win.document,
		localStorageName = 'localStorage',
		scriptTag = 'script',
		storage

	store.disabled = false
	store.set = function(key, value) {}
	store.get = function(key) {}
	store.remove = function(key) {}
	store.clear = function() {}
	store.transact = function(key, defaultVal, transactionFn) {
		var val = store.get(key)
		if (transactionFn == null) {
			transactionFn = defaultVal
			defaultVal = null
		}
		if (typeof val == 'undefined') { val = defaultVal || {} }
		transactionFn(val)
		store.set(key, val)
	}
	store.getAll = function() {}
	store.forEach = function() {}

	store.serialize = function(value) {
		return JSON.stringify(value)
	}
	store.deserialize = function(value) {
		if (typeof value != 'string') { return undefined }
		try { return JSON.parse(value) }
		catch(e) { return value || undefined }
	}

	// Functions to encapsulate questionable FireFox 3.6.13 behavior
	// when about.config::dom.storage.enabled === false
	// See https://github.com/marcuswestin/store.js/issues#issue/13
	function isLocalStorageNameSupported() {
		try { return (localStorageName in win && win[localStorageName]) }
		catch(err) { return false }
	}

	if (isLocalStorageNameSupported()) {
		storage = win[localStorageName]
		store.set = function(key, val) {
			if (val === undefined) { return store.remove(key) }
			storage.setItem(key, store.serialize(val))
			return val
		}
		store.get = function(key) { return store.deserialize(storage.getItem(key)) }
		store.remove = function(key) { storage.removeItem(key) }
		store.clear = function() { storage.clear() }
		store.getAll = function() {
			var ret = {}
			store.forEach(function(key, val) {
				ret[key] = val
			})
			return ret
		}
		store.forEach = function(callback) {
			for (var i=0; i<storage.length; i++) {
				var key = storage.key(i)
				callback(key, store.get(key))
			}
		}
	} else if (doc.documentElement.addBehavior) {
		var storageOwner,
			storageContainer
		// Since #userData storage applies only to specific paths, we need to
		// somehow link our data to a specific path.  We choose /favicon.ico
		// as a pretty safe option, since all browsers already make a request to
		// this URL anyway and being a 404 will not hurt us here.  We wrap an
		// iframe pointing to the favicon in an ActiveXObject(htmlfile) object
		// (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
		// since the iframe access rules appear to allow direct access and
		// manipulation of the document element, even for a 404 page.  This
		// document can be used instead of the current document (which would
		// have been limited to the current path) to perform #userData storage.
		try {
			storageContainer = new ActiveXObject('htmlfile')
			storageContainer.open()
			storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>')
			storageContainer.close()
			storageOwner = storageContainer.w.frames[0].document
			storage = storageOwner.createElement('div')
		} catch(e) {
			// somehow ActiveXObject instantiation failed (perhaps some special
			// security settings or otherwse), fall back to per-path storage
			storage = doc.createElement('div')
			storageOwner = doc.body
		}
		function withIEStorage(storeFunction) {
			return function() {
				var args = Array.prototype.slice.call(arguments, 0)
				args.unshift(storage)
				// See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
				// and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
				storageOwner.appendChild(storage)
				storage.addBehavior('#default#userData')
				storage.load(localStorageName)
				var result = storeFunction.apply(store, args)
				storageOwner.removeChild(storage)
				return result
			}
		}

		// In IE7, keys cannot start with a digit or contain certain chars.
		// See https://github.com/marcuswestin/store.js/issues/40
		// See https://github.com/marcuswestin/store.js/issues/83
		var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g")
		function ieKeyFix(key) {
			return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___')
		}
		store.set = withIEStorage(function(storage, key, val) {
			key = ieKeyFix(key)
			if (val === undefined) { return store.remove(key) }
			storage.setAttribute(key, store.serialize(val))
			storage.save(localStorageName)
			return val
		})
		store.get = withIEStorage(function(storage, key) {
			key = ieKeyFix(key)
			return store.deserialize(storage.getAttribute(key))
		})
		store.remove = withIEStorage(function(storage, key) {
			key = ieKeyFix(key)
			storage.removeAttribute(key)
			storage.save(localStorageName)
		})
		store.clear = withIEStorage(function(storage) {
			var attributes = storage.XMLDocument.documentElement.attributes
			storage.load(localStorageName)
			for (var i=0, attr; attr=attributes[i]; i++) {
				storage.removeAttribute(attr.name)
			}
			storage.save(localStorageName)
		})
		store.getAll = function(storage) {
			var ret = {}
			store.forEach(function(key, val) {
				ret[key] = val
			})
			return ret
		}
		store.forEach = withIEStorage(function(storage, callback) {
			var attributes = storage.XMLDocument.documentElement.attributes
			for (var i=0, attr; attr=attributes[i]; ++i) {
				callback(attr.name, store.deserialize(storage.getAttribute(attr.name)))
			}
		})
	}

	try {
		var testKey = '__storejs__'
		store.set(testKey, testKey)
		if (store.get(testKey) != testKey) { store.disabled = true }
		store.remove(testKey)
	} catch(e) {
		store.disabled = true
	}
	store.enabled = !store.disabled

	if (typeof module != 'undefined' && module.exports && this.module !== module) { module.exports = store }
	else if (typeof define === 'function' && define.amd) { define(store) }
	else { win.store = store }

})(Function('return this')());

var ripple =
/******/ (function(modules) { // webpackBootstrap
/******/ 	
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;
/******/ 		
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};
/******/ 		
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ 		
/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;
/******/ 		
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/******/ 	
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/ 	
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/ 	
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/ 	
/******/ 	
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

	eval("exports.Remote           = __webpack_require__(1).Remote;\nexports.Request          = __webpack_require__(2).Request;\nexports.Amount           = __webpack_require__(3).Amount;\nexports.Account          = __webpack_require__(4).Account;\nexports.Transaction      = __webpack_require__(5).Transaction;\nexports.Currency         = __webpack_require__(6).Currency;\nexports.Base             = __webpack_require__(7).Base;\nexports.UInt160          = __webpack_require__(8).UInt160;\nexports.UInt256          = __webpack_require__(9).UInt256;\nexports.Seed             = __webpack_require__(10).Seed;\nexports.Meta             = __webpack_require__(11).Meta;\nexports.SerializedObject = __webpack_require__(12).SerializedObject;\nexports.RippleError      = __webpack_require__(13).RippleError;\nexports.Message          = __webpack_require__(14).Message;\nexports.VaultClient      = __webpack_require__(15).VaultClient;\nexports.AuthInfo         = __webpack_require__(16).AuthInfo;\nexports.RippleTxt        = __webpack_require__(17).RippleTxt;\nexports.binformat        = __webpack_require__(18);\nexports.utils            = __webpack_require__(19);\nexports.Server           = __webpack_require__(20).Server;\nexports.Wallet           = __webpack_require__(21);\n\n// Important: We do not guarantee any specific version of SJCL or for any\n// specific features to be included. The version and configuration may change at\n// any time without warning.\n//\n// However, for programs that are tied to a specific version of ripple.js like\n// the official client, it makes sense to expose the SJCL instance so we don't\n// have to include it twice.\nexports.sjcl   = __webpack_require__(19).sjcl;\n\nexports.config = __webpack_require__(22);\n\n// camelCase to under_scored API conversion\nfunction attachUnderscored(c) {\n  var o = exports[c];\n\n  Object.keys(o.prototype).forEach(function(key) {\n    var UPPERCASE = /([A-Z]{1})[a-z]+/g;\n\n    if (!UPPERCASE.test(key)) {\n      return;\n    }\n\n    var underscored = key.replace(UPPERCASE, function(c) {\n      return '_' + c.toLowerCase();\n    });\n\n    o.prototype[underscored] = o.prototype[key];\n  });\n};\n\n[ 'Remote',\n  'Request',\n  'Transaction',\n  'Account',\n  'Server'\n].forEach(attachUnderscored);\n\n// vim:sw=2:sts=2:ts=8:et\n\n\n// WEBPACK FOOTER\n// module.id = 0\n// module.readableIdentifier = ./src/js/ripple/index.js\n//@ sourceURL=webpack-module:///./src/js/ripple/index.js");

/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {

	eval("// Remote access to a server.\n// - We never send binary data.\n// - We use the W3C interface for node and browser compatibility:\n//   http://www.w3.org/TR/websockets/#the-websocket-interface\n//\n// This class is intended for both browser and Node.js use.\n//\n// This class is designed to work via peer protocol via either the public or\n// private WebSocket interfaces. The JavaScript class for the peer protocol\n// has not yet been implemented. However, this class has been designed for it\n// to be a very simple drop option.\n//\n// YYY Will later provide js/network.js which will transparently use multiple\n// instances of this class for network access.\n\nvar EventEmitter     = __webpack_require__(37).EventEmitter;\nvar util             = __webpack_require__(38);\nvar assert           = __webpack_require__(39);\nvar LRU              = __webpack_require__(48);\nvar Server           = __webpack_require__(20).Server;\nvar Request          = __webpack_require__(2).Request;\nvar Server           = __webpack_require__(20).Server;\nvar Amount           = __webpack_require__(3).Amount;\nvar Currency         = __webpack_require__(6).Currency;\nvar UInt160          = __webpack_require__(8).UInt160;\nvar UInt256          = __webpack_require__(9).UInt256;\nvar Transaction      = __webpack_require__(5).Transaction;\nvar Account          = __webpack_require__(4).Account;\nvar Meta             = __webpack_require__(11).Meta;\nvar OrderBook        = __webpack_require__(23).OrderBook;\nvar PathFind         = __webpack_require__(24).PathFind;\nvar SerializedObject = __webpack_require__(12).SerializedObject;\nvar RippleError      = __webpack_require__(13).RippleError;\nvar utils            = __webpack_require__(19);\nvar sjcl             = __webpack_require__(19).sjcl;\nvar config           = __webpack_require__(22);\nvar log              = __webpack_require__(25).internal.sub('remote');\n\n/**\n *    Interface to manage the connection to a Ripple server.\n *\n *    This implementation uses WebSockets.\n *\n *    Keys for opts:\n *\n *      trace\n *      max_listeners      : Set maxListeners for remote; prevents EventEmitter warnings\n *      connection_offset  : Connect to remote servers on supplied interval (in seconds)\n *      trusted            : truthy, if remote is trusted\n *      max_fee            : Maximum acceptable transaction fee\n *      fee_cushion        : Extra fee multiplier to account for async fee changes.\n *      servers            : Array of server objects with the following form\n *      canonical_signing  : Signatures should be canonicalized and the \"canonical\" flag set\n *\n *         {\n *              host:    <string>\n *            , port:    <number>\n *            , secure:  <boolean>\n *         }\n *\n *    Events:\n *      'connect'\n *      'disconnect'\n *      'state':\n *      - 'online'        : Connected and subscribed.\n *      - 'offline'       : Not subscribed or not connected.\n *      'subscribed'      : This indicates stand-alone is available.\n *\n *    Server events:\n *      'ledger_closed'   : A good indicate of ready to serve.\n *      'transaction'     : Transactions we receive based on current subscriptions.\n *      'transaction_all' : Listening triggers a subscribe to all transactions\n *                          globally in the network.\n *\n *    @param opts      Connection options.\n *    @param trace\n */\n\nfunction Remote(opts, trace) {\n  EventEmitter.call(this);\n\n  var self = this;\n  var opts = opts || { };\n\n  this.trusted = Boolean(opts.trusted);\n  this.state = 'offline'; // 'online', 'offline'\n  this._server_fatal = false; // True, if we know server exited.\n  this._allow_partial_history = (typeof opts.allow_partial_history === 'boolean') ? opts.allow_partial_history : true;\n\n  this.local_sequence = Boolean(opts.local_sequence); // Locally track sequence numbers\n  this.local_fee = (typeof opts.local_fee === 'boolean') ? opts.local_fee : true;// Locally set fees\n  this.local_signing = (typeof opts.local_signing === 'boolean') ? opts.local_signing : true;\n  this.canonical_signing = (typeof opts.canonical_signing === 'boolean') ? opts.canonical_signing : true;\n\n  this.fee_cushion = (typeof opts.fee_cushion === 'number') ? opts.fee_cushion : 1.2;\n  this.max_fee = (typeof opts.max_fee === 'number') ? opts.max_fee : 1000000; // default max fee is 1 XRP, 10^6 drops\n\n  this.max_attempts = (typeof opts.max_attempts === 'number') ? opts.max_attempts : 10;\n\n  this._ledger_current_index = void(0);\n  this._ledger_hash = void(0);\n  this._ledger_time = void(0);\n\n  this._stand_alone = void(0);\n  this._testnet = void(0);\n  this.trace = Boolean(opts.trace);\n\n  this._transaction_subs = 0;\n  this._connection_count = 0;\n  this._connected = false;\n  this._should_connect = true;\n\n  this._submission_timeout = 1000 * (typeof opts.submission_timeout === 'number' ? opts.submission_timeout : 20);\n\n  this._received_tx = LRU({ max: 100 });\n  this._cur_path_find = null;\n\n  // Local signing implies local fees and sequences\n  if (this.local_signing) {\n    this.local_sequence = true;\n    this.local_fee = true;\n  }\n\n  this._servers = [ ];\n  this._primary_server = void(0);\n\n  // Cache information for accounts.\n  // DEPRECATED, will be removed\n  // Consider sequence numbers stable if you know you're not generating bad transactions.\n  // Otherwise, clear it to have it automatically refreshed from the network.\n  // account : { seq : __ }\n  this.accounts = { };\n\n  // Account objects by AccountId.\n  this._accounts = { };\n\n  // OrderBook objects\n  this._books = { };\n\n  // Secrets that we know about.\n  // Secrets can be set by calling set_secret(account, secret).\n  // account : secret\n  this.secrets = { };\n\n  // Cache for various ledgers.\n  // XXX Clear when ledger advances.\n  this.ledgers = {\n    current : {\n      account_root : { }\n    }\n  };\n\n  if (typeof this._submission_timeout !== 'number') {\n    throw new TypeError('Remote \"submission_timeout\" configuration is not a Number');\n  }\n\n  if (typeof this.max_fee !== 'number') {\n    throw new TypeError('Remote \"max_fee\" configuration is not a Number');\n  }\n\n  if (typeof this.fee_cushion !== 'number') {\n    throw new TypeError('Remote \"fee_cushion\" configuration is not a Number');\n  }\n\n  if (!/^(undefined|boolean)$/.test(typeof opts.trace)) {\n    throw new TypeError('Remote \"trace\" configuration is not a Boolean');\n  }\n\n  if (typeof this.local_signing !== 'boolean') {\n    throw new TypeError('Remote \"local_signing\" configuration is not a Boolean');\n  }\n\n  if (typeof this.local_fee !== 'boolean') {\n    throw new TypeError('Remote \"local_fee\" configuration is not a Boolean');\n  }\n\n  if (typeof this.local_sequence !== 'boolean') {\n    throw new TypeError('Remote \"local_sequence\" configuration is not a Boolean');\n  }\n\n  if (!/^(undefined|number)$/.test(typeof opts.ping)) {\n    throw new TypeError('Remote \"ping\" configuration is not a Number');\n  }\n\n  if (!/^(undefined|object)$/.test(typeof opts.storage)) {\n    throw new TypeError('Remote \"storage\" configuration is not an Object');\n  }\n\n  // Fallback for previous API\n  if (!opts.hasOwnProperty('servers') && opts.hasOwnProperty('websocket_ip')) {\n    opts.servers = [\n      {\n        host:     opts.websocket_ip,\n        port:     opts.websocket_port,\n        secure:   opts.websocket_ssl,\n        trusted:  opts.trusted\n      }\n    ];\n  }\n\n  (opts.servers || []).forEach(function(server) {\n    self.addServer(server);\n  });\n\n  // This is used to remove Node EventEmitter warnings\n  var maxListeners = opts.maxListeners || opts.max_listeners || 0;\n\n  this._servers.concat(this).forEach(function(emitter) {\n    if (emitter instanceof EventEmitter) {\n      emitter.setMaxListeners(maxListeners);\n    }\n  });\n\n  function listenerAdded(type, listener) {\n    if (type === 'transaction_all') {\n      if (!self._transaction_subs && self.isConnected()) {\n        self.request_subscribe('transactions').request();\n      }\n      self._transaction_subs += 1;\n    }\n  };\n\n  this.on('newListener', listenerAdded);\n\n  function listenerRemoved(type, listener) {\n    if (type === 'transaction_all') {\n      self._transaction_subs -= 1;\n      if (!self._transaction_subs && self.isConnected()) {\n        self.request_unsubscribe('transactions').request();\n      }\n    }\n  };\n\n  this.on('removeListener', listenerRemoved);\n\n  if (opts.storage) {\n    this.storage = opts.storage;\n    this.once('connect', this.getPendingTransactions.bind(this));\n  }\n\n  function pingServers() {\n    self._pingInterval = setInterval(function() {\n      var pingRequest = self.requestPing();\n      pingRequest.on('error', function(){});\n      pingRequest.broadcast();\n    }, opts.ping * 1000);\n  };\n\n  if (opts.ping) {\n    this.on('connect', pingServers);\n  }\n\n  function reconnect() {\n    self.reconnect();\n  };\n\n  //if we are using a browser, reconnect\n  //the servers whenever the network comes online\n  if (typeof window !== 'undefined') {\n    if (window.addEventListener) {\n      // W3C DOM\n      window.addEventListener('online', reconnect);\n    } else if (window.attachEvent) {\n      // IE DOM\n      window.attachEvent('ononline', reconnect);\n    }\n  }\n};\n\nutil.inherits(Remote, EventEmitter);\n\n// Flags for ledger entries. In support of account_root().\nRemote.flags = {\n  // Account Root\n  account_root: {\n    PasswordSpent:   0x00010000, // True, if password set fee is spent.\n    RequireDestTag:  0x00020000, // True, to require a DestinationTag for payments.\n    RequireAuth:     0x00040000, // True, to require a authorization to hold IOUs.\n    DisallowXRP:     0x00080000, // True, to disallow sending XRP.\n    DisableMaster:   0x00100000  // True, force regular key.\n  },\n\n  // Offer\n  offer: {\n    Passive:         0x00010000,\n    Sell:            0x00020000  // True, offer was placed as a sell.\n  },\n\n  // Ripple State\n  state: {\n    LowReserve:      0x00010000, // True, if entry counts toward reserve.\n    HighReserve:     0x00020000,\n    LowAuth:         0x00040000,\n    HighAuth:        0x00080000,\n    LowNoRipple:     0x00100000,\n    HighNoRipple:    0x00200000\n  }\n};\n\nRemote.from_config = function(obj, trace) {\n  var serverConfig = (typeof obj === 'string') ? config.servers[obj] : obj;\n  var remote = new Remote(serverConfig, trace);\n\n  function initializeAccount(account) {\n    var accountInfo = config.accounts[account];\n    if (typeof accountInfo === 'object') {\n      if (accountInfo.secret) {\n        // Index by nickname\n        remote.setSecret(account, accountInfo.secret);\n        // Index by account ID\n        remote.setSecret(accountInfo.account, accountInfo.secret);\n      }\n    }\n  };\n\n  if (config.accounts) {\n    Object.keys(config.accounts).forEach(initializeAccount);\n  }\n\n  return remote;\n};\n\n/**\n * Check that server message is valid\n *\n * @param {Object} message\n */\n\nRemote.isValidMessage = function(message) {\n  return (typeof message === 'object')\n      && (typeof message.type === 'string');\n};\n\n/**\n * Check that server message contains valid\n * ledger data\n *\n * @param {Object} message\n */\n\nRemote.isValidLedgerData = function(message) {\n  return (typeof message === 'object')\n    && (typeof message.fee_base === 'number')\n    && (typeof message.fee_ref === 'number')\n    && (typeof message.ledger_hash === 'string')\n    && (typeof message.ledger_index === 'number')\n    && (typeof message.ledger_time === 'number')\n    && (typeof message.reserve_base === 'number')\n    && (typeof message.reserve_inc === 'number');\n};\n\n/**\n * Check that server message contains valid\n * load status data\n *\n * @param {Object} message\n */\n\nRemote.isValidLoadStatus = function(message) {\n  return (typeof message.load_base === 'number')\n      && (typeof message.load_factor === 'number');\n};\n\n/**\n * Set the emitted state: 'online' or 'offline'\n *\n * @param {String} state\n */\n\nRemote.prototype._setState = function(state) {\n  if (this.state !== state) {\n    if (this.trace) {\n      log.info('set_state:', state);\n    }\n\n    this.state = state;\n    this.emit('state', state);\n\n    switch (state) {\n      case 'online':\n        this._online_state = 'open';\n        this._connected = true;\n        this.emit('connect');\n        this.emit('connected');\n        break;\n      case 'offline':\n        this._online_state = 'closed';\n        this._connected = false;\n        this.emit('disconnect');\n        this.emit('disconnected');\n        break;\n    }\n  }\n};\n\n/**\n * Inform remote that the remote server is not comming back.\n */\n\nRemote.prototype.setServerFatal = function() {\n  this._server_fatal = true;\n};\n\n/**\n * Enable debug output\n *\n * @param {Boolean} trace\n */\n\nRemote.prototype.setTrace = function(trace) {\n  this.trace = (trace === void(0) || trace);\n  return this;\n};\n\nRemote.prototype._trace = function() {\n  if (this.trace) {\n    log.info.apply(log, arguments);\n  }\n};\n\n/**\n * Store a secret - allows the Remote to automatically fill \n * out auth information.\n *\n * @param {String} account\n * @param {String} secret\n */\n\nRemote.prototype.setSecret = function(account, secret) {\n  this.secrets[account] = secret;\n};\n\nRemote.prototype.getPendingTransactions = function() {\n  var self = this;\n\n  function resubmitTransaction(tx) {\n    if (typeof tx !== 'object') {\n      return;\n    }\n\n    var transaction = self.transaction();\n    transaction.parseJson(tx.tx_json);\n    transaction.clientID(tx.clientID);\n\n    Object.keys(tx).forEach(function(prop) {\n      switch (prop) {\n        case 'secret':\n        case 'submittedIDs':\n        case 'submitIndex':\n          transaction[prop] = tx[prop];\n          break;\n      }\n    });\n\n    transaction.submit();\n  };\n\n  this.storage.getPendingTransactions(function(err, transactions) {\n    if (!err && Array.isArray(transactions)) {\n      transactions.forEach(resubmitTransaction);\n    }\n  });\n};\n\nRemote.prototype.addServer = function(opts) {\n  var self = this;\n\n  var server = new Server(this, opts);\n\n  function serverMessage(data) {\n    self._handleMessage(data, server);\n  };\n\n  server.on('message', serverMessage);\n\n  function serverConnect() {\n    self._connection_count += 1;\n\n    if (opts.primary) {\n      self._setPrimaryServer(server);\n    }\n    if (self._connection_count === 1) {\n      self._setState('online');\n    }\n    if (self._connection_count === self._servers.length) {\n      self.emit('ready');\n    }\n  };\n\n  server.on('connect', serverConnect);\n\n  function serverDisconnect() {\n    self._connection_count--;\n    if (self._connection_count === 0) {\n      self._setState('offline');\n    }\n  };\n\n  server.on('disconnect', serverDisconnect);\n\n  this._servers.push(server);\n\n  return this;\n};\n\n/**\n * Reconnect to Ripple network\n */\n\nRemote.prototype.reconnect = function() {\n  var self = this;\n\n  if (!this._should_connect) {\n    return;\n  }\n\n  log.info('reconnecting');\n\n  this._servers.forEach(function(server) {\n    server.reconnect();\n  });\n\n  return this;\n};\n\n/**\n * Connect to the Ripple network\n *\n * @param {Function} callback\n * @api public\n */\n\nRemote.prototype.connect = function(online) {\n  if (!this._servers.length) {\n    throw new Error('No servers available.');\n  }\n\n  switch (typeof online) {\n    case 'undefined':\n      break;\n    case 'function':\n      this.once('connect', online);\n      break;\n    default:\n      // Downwards compatibility\n      if (!Boolean(online)) {\n        return this.disconnect();\n      }\n  }\n\n  var self = this;\n\n  this._should_connect = true;\n\n  this._servers.forEach(function(server) {\n    server.connect();\n  });\n\n  return this;\n};\n\n/**\n * Disconnect from the Ripple network.\n *\n * @param {Function} callback\n * @api public\n */\n\nRemote.prototype.disconnect = function(callback) {\n  if (!this._servers.length) {\n    throw new Error('No servers available, not disconnecting');\n  }\n\n  var callback = (typeof callback === 'function') ? callback : function(){};\n\n  if (!this.isConnected()) {\n    callback();\n    return this;\n  }\n\n  this._should_connect = false;\n\n  this.once('disconnect', callback);\n\n  this._servers.forEach(function(server) {\n    server.disconnect();\n  });\n\n  this._set_state('offline');\n\n  return this;\n};\n\n/**\n * Handle server message. Server messages are proxied to\n * the Remote, such that global events can be handled\n *\n * It is possible for messages to be dispatched after the\n * connection is closed.\n *\n * @param {JSON} message\n * @param {Server} server\n */\n\nRemote.prototype._handleMessage = function(message, server) {\n  var self = this;\n\n  try {\n    message = JSON.parse(message);\n  } catch (e) {\n  }\n\n  if (!Remote.isValidMessage(message)) {\n    // Unexpected response from remote.\n    this.emit('error', new RippleError('remoteUnexpected', 'Unexpected response from remote'));\n    return;\n  }\n\n  switch (message.type) {\n    case 'ledgerClosed':\n      this._handleLedgerClosed(message, server);\n      break;\n    case 'serverStatus':\n      this._handleServerStatus(message, server);\n      break;\n    case 'transaction':\n      this._handleTransaction(message, server);\n      break;\n    case 'path_find':\n      this._handlePathFind(message, server);\n      break;\n    default:\n      if (this.trace) {\n        log.info(message.type + ': ', message);\n      }\n      break;\n  }\n};\n\n/**\n * Handle server ledger_closed event\n *\n * @param {Object} message\n */\n\nRemote.prototype._handleLedgerClosed = function(message, server) {\n  var self = this;\n\n  // XXX If not trusted, need to verify we consider ledger closed.\n  // XXX Also need to consider a slow server or out of order response.\n  // XXX Be more defensive fields could be missing or of wrong type.\n  // YYY Might want to do some cache management.\n  if (!Remote.isValidLedgerData(message)) {\n    return;\n  }\n\n  var ledgerAdvanced = message.ledger_index >= this._ledger_current_index;\n\n  if (isNaN(this._ledger_current_index) || ledgerAdvanced) {\n    this._ledger_time = message.ledger_time;\n    this._ledger_hash = message.ledger_hash;\n    this._ledger_current_index = message.ledger_index + 1;\n\n    if (this.isConnected()) {\n      this.emit('ledger_closed', message, server);\n    } else {\n      this.once('connect', function() {\n        // Delay until server is 'online'\n        self.emit('ledger_closed', message, server);\n      });\n    }\n  }\n};\n\n/**\n * Handle server server_status event\n *\n * @param {Object} message\n */\n\nRemote.prototype._handleServerStatus = function(message, server) {\n  this.emit('server_status', message, server);\n};\n\n/**\n * Handle server transaction event\n *\n * @param {Object} message\n */\n\nRemote.prototype._handleTransaction = function(message, server) {\n  var self = this;\n\n  // XXX If not trusted, need proof.\n\n  // De-duplicate transactions\n  var transactionHash = message.transaction.hash;\n\n  if (this._received_tx.get(transactionHash)) {\n    return;\n  }\n\n  if (message.validated) {\n    this._received_tx.set(transactionHash, true);\n  }\n\n  if (this.trace) {\n    log.info('tx:', message);\n  }\n\n  function notify(el) {\n    var item = this[el];\n    if (item && typeof item.notify === 'function') {\n      item.notify(message);\n    }\n  };\n\n  var metadata = message.meta || message.metadata;\n\n  if (metadata) {\n    // Process metadata\n    message.mmeta = new Meta(metadata);\n\n    // Pass the event on to any related Account objects\n    var affectedAccounts = message.mmeta.getAffectedAccounts();\n    affectedAccounts.forEach(notify.bind(this._accounts));\n\n    // Pass the event on to any related OrderBooks\n    var affectedBooks = message.mmeta.getAffectedBooks();\n    affectedBooks.forEach(notify.bind(this._books));\n  } else {\n    // Transaction could be from proposed transaction stream\n    [ 'Account', 'Destination' ].forEach(function(prop) {\n      notify.call(self._accounts, message.transaction[prop]);\n    });\n  }\n\n  this.emit('transaction', message, server);\n  this.emit('transaction_all', message, server);\n};\n\n/**\n * Handle server path_find event\n *\n * @param {Object} message\n */\n\nRemote.prototype._handlePathFind = function(message, server) {\n  var self = this;\n\n  // Pass the event to the currently open PathFind object\n  if (this._cur_path_find) {\n    this._cur_path_find.notify_update(message);\n  }\n\n  this.emit('path_find_all', message, server);\n};\n\n/**\n * Returns the current ledger hash\n *\n * @return {String} ledger hash\n */\n\nRemote.prototype.getLedgerHash = function() {\n  return this._ledger_hash;\n};\n\n/**\n * Set primary server. Primary server will be selected\n * to handle requested regardless of its internally-tracked\n * priority score\n *\n * @param {Server} server\n */\n\nRemote.prototype._setPrimaryServer =\nRemote.prototype.setPrimaryServer = function(server) {\n  if (this._primary_server) {\n    this._primary_server._primary = false;\n  }\n  this._primary_server = server;\n  this._primary_server._primary = true;\n};\n\n/**\n * Get connected state\n *\n * @return {Boolean} connected\n */\n\nRemote.prototype.isConnected = function() {\n  return this._connected;\n};\n\n/**\n * Get array of connected servers\n */\n\nRemote.prototype.getConnectedServers = function() {\n  var servers = [ ];\n  for (var i=0; i<this._servers.length; i++) {\n    if (this._servers[i].isConnected()) {\n      servers.push(this._servers[i]);\n    }\n  }\n  return servers;\n};\n\n/**\n * Select a server to handle a request. Servers are\n * automatically prioritized\n */\n\nRemote.prototype._getServer =\nRemote.prototype.getServer = function() {\n  if (this._primary_server && this._primary_server.isConnected()) {\n    return this._primary_server;\n  }\n\n  if (!this._servers.length) {\n    return null;\n  }\n\n  var connectedServers = this.getConnectedServers();\n  if (connectedServers.length === 0 || !connectedServers[0]) {\n    return null;\n  }\n\n  var server = connectedServers[0];\n  var cScore = server._score + server._fee;\n\n  for (var i=1; i<connectedServers.length; i++) {\n    var _server = connectedServers[i];\n    var bScore = _server._score + _server._fee;\n    if (bScore < cScore) {\n      server = _server;\n      cScore = bScore;\n    }\n  }\n\n  return server;\n};\n\n/**\n * Send a request. This method is called internally by Request\n * objects. Each Request contains a reference to Remote, and\n * Request.request calls Request.remote.request\n *\n * @param {Request} request\n */\n\nRemote.prototype.request = function(request) {\n  if (typeof request === 'string') {\n    if (!/^request_/.test(request)) {\n      request = 'request_' + request;\n    }\n    if (typeof this[request] === 'function') {\n      var args = Array.prototype.slice.call(arguments, 1);\n      return this[request].apply(this, args);\n    } else {\n      throw new Error('Command does not exist: ' + request);\n    }\n  }\n\n  if (!(request instanceof Request)) {\n    throw new Error('Argument is not a Request');\n  }\n\n  if (!this._servers.length) {\n    request.emit('error', new Error('No servers available'));\n  } else if (!this.isConnected()) {\n    this.once('connect', this.request.bind(this, request));\n  } else if (request.server === null) {\n    request.emit('error', new Error('Server does not exist'));\n  } else {\n    var server = request.server || this.getServer();\n    if (server) {\n      server._request(request);\n    } else {\n      request.emit('error', new Error('No servers available'));\n    }\n  }\n};\n\n/**\n * Request ping\n *\n * @param [String] server host\n * @param [Function] callback\n * @return {Request} request\n */\n\nRemote.prototype.ping  =\nRemote.prototype.requestPing = function(host, callback) {\n  var request = new Request(this, 'ping');\n\n  switch (typeof host) {\n    case 'function':\n      callback = host;\n      break;\n    case 'string':\n      request.setServer(host);\n      break;\n  }\n\n  var then = Date.now();\n\n  request.once('success', function() {\n    request.emit('pong', Date.now() - then);\n  });\n\n  request.callback(callback, 'pong');\n\n  return request;\n};\n\n/**\n * Request server_info\n *\n * @param [Function] callback\n * @return {Request} request\n */\n\nRemote.prototype.requestServerInfo = function(callback) {\n  return new Request(this, 'server_info').callback(callback);\n};\n\n/**\n * Request ledger\n *\n * @return {Request} request\n */\n\nRemote.prototype.requestLedger = function(options, callback) {\n  // XXX This is a bad command. Some variants don't scale.\n  // XXX Require the server to be trusted.\n  //utils.assert(this.trusted);\n\n  var request = new Request(this, 'ledger');\n\n  switch (typeof options) {\n    case 'undefined': break;\n    case 'function':\n      callback = options;\n      break;\n\n    case 'object':\n      if (!options) break;\n\n      Object.keys(options).forEach(function(o) {\n        switch (o) {\n          case 'full':\n          case 'expand':\n          case 'transactions':\n          case 'accounts':\n            request.message[o] = true;\n            break;\n          case 'ledger_index':\n          case 'ledger_hash':\n            request.message[o] = options[o];\n            break;\n          case 'closed' :\n          case 'current' :\n          case 'validated' :\n            request.message.ledger_index = o;\n            break;\n        }\n      }, options);\n      break;\n\n    default:\n      request.ledgerSelect(options);\n      break;\n  }\n\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request ledger_closed\n *\n * @param [Function] callback\n * @return {Request} request\n */\n\nRemote.prototype.requestLedgerClosed =\nRemote.prototype.requestLedgerHash = function(callback) {\n  //utils.assert(this.trusted);   // If not trusted, need to check proof.\n  return new Request(this, 'ledger_closed').callback(callback);\n};\n\n/**\n * Request ledger_header\n *\n * @param [Function] callback\n * @return {Request} request\n */\n\nRemote.prototype.requestLedgerHeader = function(callback) {\n  return new Request(this, 'ledger_header').callback(callback);\n};\n\n/**\n * Request ledger_current\n *\n * Get the current proposed ledger entry. May be closed (and revised)\n * at any time (even before returning).\n *\n * Only for unit testing.\n *\n * @param [Function] callback\n * @return {Request} request\n */\n\nRemote.prototype.requestLedgerCurrent = function(callback) {\n  return new Request(this, 'ledger_current').callback(callback);\n};\n\n/**\n * Request ledger_entry\n *\n * @param [String] type\n * @param [Function] callback\n * @return {Request} request\n */\n\nRemote.prototype.requestLedgerEntry = function(type, callback) {\n  //utils.assert(this.trusted);   // If not trusted, need to check proof, maybe talk packet protocol.\n\n  var self = this;\n  var request = new Request(this, 'ledger_entry');\n\n  if (typeof type === 'function') {\n    callback = type;\n  }\n\n  // Transparent caching. When .request() is invoked, look in the Remote object for the result.\n  // If not found, listen, cache result, and emit it.\n  //\n  // Transparent caching:\n  if (type === 'account_root') {\n    request.request_default = request.request;\n\n    request.request = function() {                        // Intercept default request.\n      var bDefault  = true;\n      // .self = Remote\n      // this = Request\n\n      // console.log('request_ledger_entry: caught');\n\n      //if (self._ledger_hash) {\n        // A specific ledger is requested.\n        // XXX Add caching.\n        // else if (req.ledger_index)\n        // else if ('ripple_state' === request.type)         // YYY Could be cached per ledger.\n      //}\n\n      if (!self._ledger_hash && type === 'account_root') {\n        var cache = self.ledgers.current.account_root;\n\n        if (!cache) {\n          cache = self.ledgers.current.account_root = {};\n        }\n\n        var node = self.ledgers.current.account_root[request.message.account_root];\n\n        if (node) {\n          // Emulate fetch of ledger entry.\n          // console.log('request_ledger_entry: emulating');\n          // YYY Missing lots of fields.\n          request.emit('success', { node: node });\n          bDefault  = false;\n        } else { // Was not cached.\n          // XXX Only allow with trusted mode.  Must sync response with advance.\n          switch (type) {\n            case 'account_root':\n              request.once('success', function(message) {\n                // Cache node.\n                // console.log('request_ledger_entry: caching');\n                self.ledgers.current.account_root[message.node.Account] = message.node;\n              });\n              break;\n\n            default:\n              // This type not cached.\n              // console.log('request_ledger_entry: non-cached type');\n          }\n        }\n      }\n\n      if (bDefault) {\n        // console.log('request_ledger_entry: invoking');\n        request.request_default();\n      }\n    };\n  }\n\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request subscribe\n *\n * @param {Array} streams\n * @param [Function] callback\n * @return {Request} request\n */\n\nRemote.prototype.requestSubscribe = function(streams, callback) {\n  var request = new Request(this, 'subscribe');\n\n  if (streams) {\n    request.message.streams = Array.isArray(streams) ? streams : [ streams ];\n  }\n\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request usubscribe\n *\n * @param {Array} streams\n * @param [Function] callback\n * @return {Request} request\n */\n\nRemote.prototype.requestUnsubscribe = function(streams, callback) {\n  var request = new Request(this, 'unsubscribe');\n\n  if (streams) {\n    request.message.streams = Array.isArray(streams) ? streams : [ streams ];\n  }\n\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request transaction_entry\n *\n * @param {String} transaction hash\n * @param {String|Number} ledger hash or sequence\n * @param [Function] callback\n * @return {Request} request\n */\n\nRemote.prototype.requestTransactionEntry = function(hash, ledgerHash, callback) {\n  //// If not trusted, need to check proof, maybe talk packet protocol.\n  //utils.assert(this.trusted);\n  var request = new Request(this, 'transaction_entry');\n\n  request.txHash(hash);\n\n  switch (typeof ledgerHash) {\n    case 'string':\n    case 'number':\n      request.ledgerSelect(ledgerHash);\n      break;\n\n    case 'undefined':\n    case 'function':\n      request.ledgerIndex('validated');\n      callback = ledgerHash;\n      break;\n\n    default:\n      throw new Error('Invalid ledger_hash type');\n  }\n\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request tx\n *\n * @param {String} transaction hash\n * @param [Function] callback\n * @return {Request} request\n */\n\nRemote.prototype.requestTransaction =\nRemote.prototype.requestTx = function(hash, callback) {\n  var request = new Request(this, 'tx');\n\n  request.message.transaction = hash;\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Account Request\n *\n * Optional paging with limit and marker options\n * supported in rippled for 'account_lines' and 'account_offers'\n *\n * The paged responses aren't guaranteed to be reliable between\n * ledger closes. You have to supply a ledger_index or ledger_hash\n * when paging to ensure a complete response\n *\n * @param {String} type - request name, e.g. 'account_lines'\n * @param {String} account - ripple address\n * @param {Object} options - all optional\n *   @param {String} peer - ripple address\n *   @param [String|Number] ledger identifier\n *   @param [Number] limit - max results per response\n *   @param {String} marker - start position in response paging\n * @param [Function] callback\n * @return {Request}\n * @throws {Error} if a marker is provided, but no ledger_index or ledger_hash\n */\nRemote.accountRequest = function(type, options, callback) {\n  var account, ledger, peer, limit, marker;\n\n  if (typeof options === 'object') {\n    account = options.account;\n    ledger = options.ledger;\n    peer = options.peer;\n    limit = options.limit;\n    marker = options.marker;\n  }\n\n  // if a marker is given, we need a ledger\n  // check if a valid ledger_index or ledger_hash is provided\n  if (marker) {\n    if (!(Number(ledger) > 0) && !UInt256.is_valid(ledger)) {\n      throw new Error('A ledger_index or ledger_hash must be provided when using a marker');\n    }\n  }\n\n  var lastArg = arguments[arguments.length - 1];\n\n  if (typeof lastArg === 'function') {\n    callback = lastArg;\n  }\n\n  var request = new Request(this, type);\n\n  if (account) {\n    account = UInt160.json_rewrite(account);\n    request.message.account = account;\n  }\n\n  request.ledgerSelect(ledger);\n\n  if (UInt160.is_valid(peer)) {\n    request.message.peer = UInt160.json_rewrite(peer);\n  }\n\n  if (!isNaN(Number(limit))) {\n    limit = Number(limit);\n\n    // max for 32-bit unsigned int is 4294967295\n    // we'll clamp to 1e9\n    if (limit > 1e9) {\n      limit = 1e9;\n    }\n    // min for 32-bit unsigned int is 0\n    // we'll clamp to 0\n    if (limit < 0) {\n      limit = 0;\n    }\n\n    request.message.limit = limit;\n  }\n\n  if (marker) {\n    request.message.marker = marker;\n  }\n\n  request.callback(callback);\n  return request;\n};\n\n/**\n * Request account_info\n *\n * @param {Object} options\n *   @param {String} account - ripple address\n *   @param {String} peer - ripple address\n *   @param [String|Number] ledger identifier\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestAccountInfo = function(options, callback) {\n  var args = Array.prototype.concat.apply(['account_info'], arguments);\n  return Remote.accountRequest.apply(this, args);\n};\n\n/**\n * Request account_currencies\n *\n * @param {Object} options\n *   @param {String} account - ripple address\n *   @param {String} peer - ripple address\n *   @param [String|Number] ledger identifier\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestAccountCurrencies = function(options, callback) {\n  var args = Array.prototype.concat.apply(['account_currencies'], arguments);\n  return Remote.accountRequest.apply(this, args);\n};\n\n/**\n * Request account_lines\n *\n * Requests for account_lines support paging, provide a limit and marker\n * to page through responses.\n *\n * The paged responses aren't guaranteed to be reliable between\n * ledger closes. You have to supply a ledger_index or ledger_hash\n * when paging to ensure a complete response\n *\n * @param {Object} options\n *   @param {String} account - ripple address\n *   @param {String} peer - ripple address\n *   @param [String|Number] ledger identifier\n *   @param [Number] limit - max results per response\n *   @param {String} marker - start position in response paging\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestAccountLines = function(options, callback) {\n  // XXX Does this require the server to be trusted?\n  //utils.assert(this.trusted);\n  var args = Array.prototype.concat.apply(['account_lines'], arguments);\n  return Remote.accountRequest.apply(this, args);\n};\n\n/**\n * Request account_offers\n *\n * Requests for account_offers support paging, provide a limit and marker\n * to page through responses.\n *\n * The paged responses aren't guaranteed to be reliable between\n * ledger closes. You have to supply a ledger_index or ledger_hash\n * when paging to ensure a complete response\n *\n * @param {Object} options\n *   @param {String} account - ripple address\n *   @param [String|Number] ledger identifier\n *   @param [Number] limit - max results per response\n *   @param {String} marker - start position in response paging\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestAccountOffers = function(options, callback) {\n  var args = Array.prototype.concat.apply(['account_offers'], arguments);\n  return Remote.accountRequest.apply(this, args);\n};\n\n/**\n * Request account_tx\n *\n * @param {Object} options\n *\n *    @param {String} account\n *    @param [Number] ledger_index_min defaults to -1 if ledger_index_max is specified.\n *    @param [Number] ledger_index_max defaults to -1 if ledger_index_min is specified.\n *    @param [Boolean] binary, defaults to false\n *    @param [Boolean] parseBinary, defaults to true\n *    @param [Boolean] count, defaults to false\n *    @param [Boolean] descending, defaults to false\n *    @param [Number] offset, defaults to 0\n *    @param [Number] limit\n *\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestAccountTransactions =\nRemote.prototype.requestAccountTx = function(options, callback) {\n  // XXX Does this require the server to be trusted?\n  //utils.assert(this.trusted);\n\n  var request = new Request(this, 'account_tx');\n\n  if (options.min_ledger !== void(0)) {\n    options.ledger_index_min = options.min_ledger;\n  }\n\n  if (options.max_ledger !== void(0)) {\n    options.ledger_index_max = options.max_ledger;\n  }\n\n  if (options.binary && options.parseBinary === void(0)) {\n    options.parseBinary = true;\n  }\n\n  Object.keys(options).forEach(function(o) {\n    switch (o) {\n      case 'account':\n      case 'ledger_index_min':  //earliest\n      case 'ledger_index_max':  //latest\n      case 'binary':            //false\n      case 'count':             //false\n      case 'descending':        //false\n      case 'offset':            //0\n      case 'limit':\n\n      //extended account_tx\n      case 'forward':           //false\n      case 'marker':\n        request.message[o] = this[o];\n        break;\n    }\n  }, options);\n\n  request.once('success', function(res) {\n    if (options.parseBinary) {\n      res.transactions = res.transactions.map(Remote.parseBinaryTransaction);\n    }\n    request.emit('transactions', res);\n  });\n\n  request.callback(callback, 'transactions');\n\n  return request;\n};\n\n/**\n * @param {Object} transaction\n * @return {Transaction}\n */\n\nRemote.parseBinaryTransaction = function(transaction) {\n  var tx = { validated: transaction.validated };\n  tx.meta = new SerializedObject(transaction.meta).to_json();\n  tx.tx = new SerializedObject(transaction.tx_blob).to_json();\n  tx.tx.ledger_index = transaction.ledger_index;\n  tx.tx.hash = Transaction.from_json(tx.tx).hash();\n  return tx;\n};\n\n/**\n * Request the overall transaction history.\n *\n * Returns a list of transactions that happened recently on the network. The\n * default number of transactions to be returned is 20.\n *\n * @param [Number] start\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestTransactionHistory =\nRemote.prototype.requestTxHistory = function(start, callback) {\n  // XXX Does this require the server to be trusted?\n  //utils.assert(this.trusted);\n\n  var request = new Request(this, 'tx_history');\n\n  request.message.start = start;\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request book_offers\n *\n * @param {Object} gets\n * @param {Object} pays\n * @param {String} taker\n * @param [Function] calback\n * @return {Request}\n */\n\nRemote.prototype.requestBookOffers = function(gets, pays, taker, callback) {\n  var lastArg = arguments[arguments.length - 1];\n\n  if (gets.hasOwnProperty('gets') || gets.hasOwnProperty('taker_gets')) {\n    var options = gets;\n    // This would mutate the `lastArg` in `arguments` to be `null` and is\n    // redundant. Once upon a time, some awkward code was written f(g, null,\n    // null, cb) ...\n    callback = pays;\n    taker = options.taker;\n    pays = options.pays || options.taker_pays;\n    gets = options.gets || options.taker_gets;\n  }\n\n  if (typeof lastArg === 'function') {\n    callback = lastArg;\n  }\n\n  var request = new Request(this, 'book_offers');\n\n  request.message.taker_gets = {\n    currency: Currency.json_rewrite(gets.currency, {force_hex:true})\n  };\n\n  if (!Currency.from_json(request.message.taker_gets.currency).is_native()) {\n    request.message.taker_gets.issuer = UInt160.json_rewrite(gets.issuer);\n  }\n\n  request.message.taker_pays = {\n    currency: Currency.json_rewrite(pays.currency, {force_hex:true})\n  };\n\n  if (!Currency.from_json(request.message.taker_pays.currency).is_native()) {\n    request.message.taker_pays.issuer = UInt160.json_rewrite(pays.issuer);\n  }\n\n  request.message.taker = taker ? taker : UInt160.ACCOUNT_ONE;\n\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request wallet_accounts\n *\n * @param {String} seed\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestWalletAccounts = function(seed, callback) {\n  utils.assert(this.trusted); // Don't send secrets.\n\n  var request = new Request(this, 'wallet_accounts');\n  request.message.seed = seed;\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request sign\n *\n * @param {String} secret\n * @param {Object} tx_json\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestSign = function(secret, tx_json, callback) {\n  utils.assert(this.trusted); // Don't send secrets.\n\n  var request = new Request(this, 'sign');\n  request.message.secret  = secret;\n  request.message.tx_json = tx_json;\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request submit\n *\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestSubmit = function(callback) {\n  return new Request(this, 'submit').callback(callback);\n};\n\n/**\n * Create a subscribe request with current subscriptions.\n *\n * Other classes can add their own subscriptions to this request by listening to\n * the server_subscribe event.\n *\n * This function will create and return the request, but not submit it.\n *\n * @param [Function] callback\n * @api private\n */\n\nRemote.prototype._serverPrepareSubscribe = function(server, callback) {\n  var self  = this;\n  var feeds = [ 'ledger', 'server' ];\n\n  if (typeof server === 'function') {\n    callback = server;\n  }\n\n  if (this._transaction_subs) {\n    feeds.push('transactions');\n  }\n\n  var request = this.requestSubscribe(feeds);\n\n  function serverSubscribed(message) {\n    self._stand_alone = !!message.stand_alone;\n    self._testnet = !!message.testnet;\n\n    if (typeof message.random === 'string') {\n      var rand = message.random.match(/[0-9A-F]{8}/ig);\n\n      while (rand && rand.length) {\n        sjcl.random.addEntropy(parseInt(rand.pop(), 16));\n      }\n\n      self.emit('random', utils.hexToArray(message.random));\n    }\n\n    self._handleLedgerClosed(message, server);\n\n    self.emit('subscribed');\n  };\n\n  request.on('error', function(err) {\n    if (self.trace) {\n      log.info('Initial server subscribe failed', err);\n    }\n  });\n\n  request.once('success', serverSubscribed);\n\n  self.emit('prepare_subscribe', request);\n\n  request.callback(callback, 'subscribed');\n\n  return request;\n};\n\n/**\n * For unit testing: ask the remote to accept the current ledger.\n * To be notified when the ledger is accepted, server_subscribe() then listen to 'ledger_hash' events.\n * A good way to be notified of the result of this is:\n * remote.once('ledger_closed', function(ledger_closed, ledger_index) { ... } );\n *\n * @param [Function] callback\n */\n\nRemote.prototype.ledgerAccept =\nRemote.prototype.requestLedgerAccept = function(callback) {\n  if (!this._stand_alone) {\n    this.emit('error', new RippleError('notStandAlone'));\n    return;\n  }\n\n  var request = new Request(this, 'ledger_accept');\n\n  this.once('ledger_closed', function(ledger) {\n    request.emit('ledger_closed', ledger);\n  });\n\n  request.callback(callback, 'ledger_closed');\n  request.request();\n\n  return request;\n};\n\n/**\n * Account root request abstraction\n *\n * @this Remote\n * @api private\n */\n\nRemote.accountRootRequest = function(type, responseFilter, account, ledger, callback) {\n  if (typeof account === 'object') {\n    callback = ledger;\n    ledger   = account.ledger;\n    account  = account.account;\n  }\n\n  var lastArg = arguments[arguments.length - 1];\n\n  if (typeof lastArg === 'function') {\n    callback = lastArg;\n  }\n\n  var request = this.requestLedgerEntry('account_root');\n\n  request.accountRoot(account);\n  request.ledgerSelect(ledger);\n\n  request.once('success', function(message) {\n    request.emit(type, responseFilter(message));\n  });\n\n  request.callback(callback, type);\n\n  return request;\n};\n\n/**\n * Request account balance\n *\n * @param {String} account\n * @param [String|Number] ledger\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestAccountBalance = function(account, ledger, callback) {\n  function responseFilter(message) {\n    return Amount.from_json(message.node.Balance);\n  };\n\n  var args = Array.prototype.concat.apply(['account_balance', responseFilter], arguments);\n  var request = Remote.accountRootRequest.apply(this, args);\n\n  return request;\n};\n\n/**\n * Request account flags\n *\n * @param {String} account\n * @param [String|Number] ledger\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestAccountFlags = function(account, ledger, callback) {\n  function responseFilter(message) {\n    return message.node.Flags;\n  };\n\n  var args = Array.prototype.concat.apply(['account_flags', responseFilter], arguments);\n  var request = Remote.accountRootRequest.apply(this, args);\n\n  return request;\n};\n\n/**\n * Request owner count\n *\n * @param {String} account\n * @param [String|Number] ledger\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestOwnerCount = function(account, ledger, callback) {\n  function responseFilter(message) {\n    return message.node.OwnerCount;\n  };\n\n  var args = Array.prototype.concat.apply(['owner_count', responseFilter], arguments);\n  var request = Remote.accountRootRequest.apply(this, args);\n\n  return request;\n};\n\n/**\n * Get an account by accountID (address)\n *\n *\n * @param {String} account\n * @return {Account}\n */\n\nRemote.prototype.getAccount = function(accountID) {\n  return this._accounts[UInt160.json_rewrite(accountID)];\n};\n\n/**\n * Add an account by accountID (address)\n *\n * @param {String} account\n * @return {Account}\n */\n\nRemote.prototype.addAccount = function(accountID) {\n  var account = new Account(this, accountID);\n\n  if (account.isValid()) {\n    this._accounts[accountID] = account;\n  }\n\n  return account;\n};\n\n/**\n * Add an account if it does not exist, return the\n * account by accountID (address)\n *\n * @param {String} account\n * @return {Account}\n */\n\nRemote.prototype.account =\nRemote.prototype.findAccount = function(accountID) {\n  var account = this.getAccount(accountID);\n  return account ? account : this.addAccount(accountID);\n};\n\n/**\n * Create a pathfind\n *\n * @param {Object} options\n * @return {PathFind}\n */\n\nRemote.prototype.pathFind =\nRemote.prototype.createPathFind = function(src_account, dst_account, dst_amount, src_currencies) {\n  if (typeof src_account === 'object') {\n    var options = src_account;\n    src_currencies = options.src_currencies;\n    dst_amount     = options.dst_amount;\n    dst_account    = options.dst_account;\n    src_account    = options.src_account;\n  }\n\n  var pathFind = new PathFind(this, src_account, dst_account, dst_amount, src_currencies);\n\n  if (this._cur_path_find) {\n    this._cur_path_find.notify_superceded();\n  }\n\n  pathFind.create();\n\n  this._cur_path_find = pathFind;\n\n  return pathFind;\n};\n\nRemote.prepareTrade = function(currency, issuer) {\n  return currency + (Currency.from_json(currency).is_native() ? '' : ('/' + issuer));\n};\n\n/**\n * Create an OrderBook if it does not exist, return\n * the order book\n *\n * @param {Object} options\n * @return {OrderBook}\n */\n\nRemote.prototype.book =\nRemote.prototype.createOrderBook = function(currency_gets, issuer_gets, currency_pays, issuer_pays) {\n  if (typeof currency_gets === 'object') {\n    var options = currency_gets;\n    issuer_pays   = options.issuer_pays;\n    currency_pays = options.currency_pays;\n    issuer_gets   = options.issuer_gets;\n    currency_gets = options.currency_gets;\n  }\n\n  var gets = Remote.prepareTrade(currency_gets, issuer_gets);\n  var pays = Remote.prepareTrade(currency_pays, issuer_pays);\n  var key = gets + ':' + pays;\n\n  if (this._books.hasOwnProperty(key)) {\n    return this._books[key];\n  }\n\n  var book = new OrderBook(this, currency_gets, issuer_gets, currency_pays, issuer_pays, key);\n\n  if (book.is_valid()) {\n    this._books[key] = book;\n  }\n\n  return book;\n};\n\n/**\n * Return the next account sequence\n *\n * @param {String} account\n * @param {String} sequence modifier (ADVANCE or REWIND)\n * @return {Number} sequence\n */\n\nRemote.prototype.accountSeq =\nRemote.prototype.getAccountSequence = function(account, advance) {\n  var account     = UInt160.json_rewrite(account);\n  var accountInfo = this.accounts[account];\n\n  if (!accountInfo) {\n    return;\n  }\n\n  var seq = accountInfo.seq;\n  var change = { ADVANCE: 1, REWIND: -1 }[advance.toUpperCase()] || 0;\n\n  accountInfo.seq += change;\n\n  return seq;\n};\n\n/**\n * Set account sequence\n *\n * @param {String} account\n * @param {Number} sequence\n */\n\nRemote.prototype.setAccountSequence =\nRemote.prototype.setAccountSeq = function(account, sequence) {\n  var account = UInt160.json_rewrite(account);\n\n  if (!this.accounts.hasOwnProperty(account)) {\n    this.accounts[account] = { };\n  }\n\n  this.accounts[account].seq = sequence;\n};\n\n/**\n * Refresh an account's sequence from server\n *\n * @param {String} account\n * @param [String|Number] ledger\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.accountSeqCache = function(account, ledger, callback) {\n  if (typeof account === 'object') {\n    var options = account;\n    callback = ledger;\n    ledger   = options.ledger;\n    account  = options.account;\n  }\n\n  var self = this;\n\n  if (!this.accounts.hasOwnProperty(account)) {\n    this.accounts[account] = { };\n  }\n\n  var account_info = this.accounts[account];\n  var request      = account_info.caching_seq_request;\n\n  function accountRootSuccess(message) {\n    delete account_info.caching_seq_request;\n\n    var seq = message.node.Sequence;\n    account_info.seq  = seq;\n\n    // console.log('caching: %s %d', account, seq);\n    // If the caller also waits for 'success', they might run before this.\n    request.emit('success_account_seq_cache', message);\n  };\n\n  function accountRootError(message) {\n    // console.log('error: %s', account);\n    delete account_info.caching_seq_request;\n\n    request.emit('error_account_seq_cache', message);\n  };\n\n  if (!request) {\n    // console.log('starting: %s', account);\n    request = this.requestLedgerEntry('account_root');\n    request.accountRoot(account);\n    request.ledgerChoose(ledger);\n    request.once('success', accountRootSuccess);\n    request.once('error', accountRootError);\n\n    account_info.caching_seq_request = request;\n  }\n\n  request.callback(callback, 'success_account_seq_cache', 'error_account_seq_cache');\n\n  return request;\n};\n\n/**\n * Mark an account's root node as dirty.\n *\n * @param {String} account\n */\n\nRemote.prototype.dirtyAccountRoot = function(account) {\n  var account = UInt160.json_rewrite(account);\n  delete this.ledgers.current.account_root[account];\n};\n\n/**\n * Get an account's balance\n *\n * @param {String} account\n * @param [String] issuer\n * @param [String] currency\n * @param [String|Number] ledger\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestRippleBalance = function(account, issuer, currency, ledger, callback) {\n  if (typeof account === 'object') {\n    var options = account;\n    callback = issuer;\n    ledger   = options.ledger;\n    currency = options.currency;\n    issuer   = options.issuer;\n    account  = options.account;\n  }\n\n  var request = this.requestLedgerEntry('ripple_state'); // YYY Could be cached per ledger.\n\n  request.rippleState(account, issuer, currency);\n  request.ledgerChoose(ledger);\n\n  function rippleState(message) {\n    var node = message.node;\n    var lowLimit = Amount.from_json(node.LowLimit);\n    var highLimit = Amount.from_json(node.HighLimit);\n\n    // The amount the low account holds of issuer.\n    var balance = Amount.from_json(node.Balance);\n\n    // accountHigh implies: for account: balance is negated, highLimit is the limit set by account.\n    var accountHigh = UInt160.from_json(account).equals(highLimit.issuer());\n\n    request.emit('ripple_state', {\n      account_balance:      ( accountHigh ? balance.negate() :     balance.clone()).parse_issuer(account),\n      peer_balance:         (!accountHigh ? balance.negate() :     balance.clone()).parse_issuer(issuer),\n      account_limit:        ( accountHigh ? highLimit :            lowLimit).clone().parse_issuer(issuer),\n      peer_limit:           (!accountHigh ? highLimit :            lowLimit).clone().parse_issuer(account),\n      account_quality_in:   ( accountHigh ? node.HighQualityIn :   node.LowQualityIn),\n      peer_quality_in:      (!accountHigh ? node.HighQualityIn :   node.LowQualityIn),\n      account_quality_out:  ( accountHigh ? node.HighQualityOut :  node.LowQualityOut),\n      peer_quality_out:     (!accountHigh ? node.HighQualityOut :  node.LowQualityOut),\n    });\n  };\n\n  request.once('success', rippleState);\n  request.callback(callback, 'ripple_state');\n\n  return request;\n};\n\nRemote.prepareCurrencies = function(currency) {\n  var newCurrency  = { };\n\n  if (currency.hasOwnProperty('issuer')) {\n    newCurrency.issuer = UInt160.json_rewrite(currency.issuer);\n  }\n\n  if (currency.hasOwnProperty('currency')) {\n    newCurrency.currency = Currency.json_rewrite(currency.currency, {force_hex:true});\n  }\n\n  return newCurrency;\n};\n\n/**\n * Request ripple_path_find\n *\n * @param {Object} options\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestRipplePathFind = function(src_account, dst_account, dst_amount, src_currencies, callback) {\n  if (typeof src_account === 'object') {\n    var options = src_account;\n    callback       = dst_account;\n    src_currencies = options.src_currencies;\n    dst_amount     = options.dst_amount;\n    dst_account    = options.dst_account;\n    src_account    = options.src_account;\n  }\n\n  var request = new Request(this, 'ripple_path_find');\n\n  request.message.source_account      = UInt160.json_rewrite(src_account);\n  request.message.destination_account = UInt160.json_rewrite(dst_account);\n  request.message.destination_amount  = Amount.json_rewrite(dst_amount);\n\n  if (src_currencies) {\n    request.message.source_currencies = src_currencies.map(Remote.prepareCurrencies);\n  }\n\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request path_find/create\n *\n * @param {Object} options\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestPathFindCreate = function(src_account, dst_account, dst_amount, src_currencies, callback) {\n  if (typeof src_account === 'object') {\n    var options = src_account;\n    callback       = dst_account;\n    src_currencies = options.src_currencies;\n    dst_amount     = options.dst_amount;\n    dst_account    = options.dst_account;\n    src_account    = options.src_account;\n  }\n\n  var request = new Request(this, 'path_find');\n\n  request.message.subcommand          = 'create';\n  request.message.source_account      = UInt160.json_rewrite(src_account);\n  request.message.destination_account = UInt160.json_rewrite(dst_account);\n  request.message.destination_amount  = Amount.json_rewrite(dst_amount);\n\n  if (src_currencies) {\n    request.message.source_currencies = src_currencies.map(Remote.prepareCurrencies);\n  }\n\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request path_find/close\n *\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestPathFindClose = function(callback) {\n  var request = new Request(this, 'path_find');\n\n  request.message.subcommand = 'close';\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request unl_list\n *\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestUnlList = function(callback) {\n  return new Request(this, 'unl_list').callback(callback);\n};\n\n/**\n * Request unl_add\n *\n * @param {String} address\n * @param {String} comment\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestUnlAdd = function(address, comment, callback) {\n  var request = new Request(this, 'unl_add');\n\n  request.message.node = address;\n\n  if (comment) {\n    // note is not specified anywhere, should remove?\n    request.message.comment = void(0);\n  }\n\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request unl_delete\n *\n * @param {String} node\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestUnlDelete = function(node, callback) {\n  var request = new Request(this, 'unl_delete');\n\n  request.message.node = node;\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Request peers\n *\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestPeers = function(callback) {\n  return new Request(this, 'peers').callback(callback);\n};\n\n/**\n * Request connect\n *\n * @param {String} ip\n * @param {Number} port\n * @param [Function] callback\n * @return {Request}\n */\n\nRemote.prototype.requestConnect = function(ip, port, callback) {\n  var request = new Request(this, 'connect');\n\n  request.message.ip = ip;\n\n  if (port) {\n    request.message.port = port;\n  }\n\n  request.callback(callback);\n\n  return request;\n};\n\n/**\n * Create a Transaction\n *\n * @param {String} TransactionType\n * @param {Object} options\n * @return {Transaction}\n */\n\nRemote.prototype.transaction =\nRemote.prototype.createTransaction = function(type, options) {\n  if (arguments.length === 0) {\n    // Fallback\n    return new Transaction(this);\n  }\n\n  assert.strictEqual(typeof type, 'string', 'TransactionType must be a string');\n  assert.strictEqual(typeof options, 'object', 'Transaction options must be an object');\n\n  var transaction = new Transaction(this);\n\n  var transactionTypes = {\n    payment: 'payment',\n    accountset: 'accountSet',\n    trustset: 'trustSet',\n    offercreate: 'offerCreate',\n    offercancel: 'offerCancel',\n    setregularkey: 'setRegularKey',\n    sign: 'sign'\n  };\n\n  var transactionConstructor = transactionTypes[type.toLowerCase()];\n\n  if (!transactionConstructor) {\n    throw new Error('Invalid transaction type: ' + type);\n  }\n\n  return transaction[transactionConstructor](options);\n};\n\n/**\n * Calculate a transaction fee for a number of tx fee units.\n *\n * This takes into account the last known network and local load fees.\n *\n * @param {Number} fee units\n * @return {Amount} Final fee in XRP for specified number of fee units.\n */\n\nRemote.prototype.feeTx = function(units) {\n  var server = this.getServer();\n\n  if (!server) {\n    throw new Error('No connected servers');\n  }\n\n  return server._feeTx(units);\n};\n\n/**\n * Get the current recommended transaction fee unit.\n *\n * Multiply this value with the number of fee units in order to calculate the\n * recommended fee for the transaction you are trying to submit.\n *\n * @return {Number} Recommended amount for one fee unit as float.\n */\n\nRemote.prototype.feeTxUnit = function() {\n  var server = this.getServer();\n\n  if (!server) {\n    throw new Error('No connected servers');\n  }\n\n  return server._feeTxUnit();\n};\n\n/**\n * Get the current recommended reserve base.\n *\n * Returns the base reserve with load fees and safety margin applied.\n *\n * @param {Number} owner count\n * @return {Amount}\n */\n\nRemote.prototype.reserve = function(owner_count) {\n  var server = this.getServer();\n\n  if (!server) {\n    throw new Error('No connected servers');\n  }\n\n  return server._reserve(owner_count);\n};\n\nexports.Remote = Remote;\n\n// vim:sw=2:sts=2:ts=8:et\n\n\n// WEBPACK FOOTER\n// module.id = 1\n// module.readableIdentifier = ./src/js/ripple/remote.js\n//@ sourceURL=webpack-module:///./src/js/ripple/remote.js");

/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {

	eval("var EventEmitter = __webpack_require__(37).EventEmitter;\nvar util         = __webpack_require__(38);\nvar UInt160      = __webpack_require__(8).UInt160;\nvar Currency     = __webpack_require__(6).Currency;\nvar RippleError  = __webpack_require__(13).RippleError;\nvar Server       = __webpack_require__(20).Server;\n\n// Request events emitted:\n//  'success' : Request successful.\n//  'error'   : Request failed.\n//  'remoteError'\n//  'remoteUnexpected'\n//  'remoteDisconnected'\n\n/**\n * Request\n *\n * @param {Remote} remote\n * @param {String} command\n */\n\nfunction Request(remote, command) {\n  EventEmitter.call(this);\n\n  this.remote = remote;\n  this.requested = false;\n  this.message = {\n    command: command,\n    id: void(0)\n  };\n};\n\nutil.inherits(Request, EventEmitter);\n\nRequest.prototype.broadcast = function() {\n  var connectedServers = this.remote.getConnectedServers();\n  this.request(connectedServers);\n  return connectedServers.length;\n};\n\n// Send the request to a remote.\nRequest.prototype.request = function(servers, callback) {\n  if (this.requested) {\n    return this;\n  }\n\n  if (typeof servers === 'function') {\n    callback = servers;\n  }\n\n  this.requested = true;\n  this.on('error', function(){});\n  this.emit('request', this.remote);\n\n  if (Array.isArray(servers)) {\n    servers.forEach(function(server) {\n      this.setServer(server);\n      this.remote.request(this);\n    }, this);\n  } else {\n    this.remote.request(this);\n  }\n\n  this.callback(callback);\n\n  return this;\n};\n\nRequest.prototype.callback = function(callback, successEvent, errorEvent) {\n  var self = this;\n\n  if (typeof callback !== 'function') {\n    return this;\n  }\n\n  var called = false;\n\n  function requestSuccess(message) {\n    if (!called) {\n      called = true;\n      callback.call(self, null, message);\n    }\n  };\n\n  function requestError(error) {\n    if (!called) {\n      called = true;\n\n      if (!(error instanceof RippleError)) {\n        error = new RippleError(error);\n      }\n\n      callback.call(self, error);\n    }\n  };\n\n  this.once(successEvent || 'success', requestSuccess);\n  this.once(errorEvent   || 'error'  , requestError);\n  this.request();\n\n  return this;\n};\n\nRequest.prototype.timeout = function(duration, callback) {\n  var self = this;\n\n  function requested() {\n    self.timeout(duration, callback);\n  };\n\n  if (!this.requested) {\n    // Defer until requested\n    return this.once('request', requested);\n  }\n\n  var emit = this.emit;\n  var timed_out = false;\n\n  var timeout = setTimeout(function() {\n    timed_out = true;\n\n    if (typeof callback === 'function') {\n      callback();\n    }\n\n    emit.call(self, 'timeout');\n  }, duration);\n\n  this.emit = function() {\n    if (!timed_out) {\n      clearTimeout(timeout);\n      emit.apply(self, arguments);\n    }\n  };\n\n  return this;\n};\n\nRequest.prototype.setServer = function(server) {\n  var selected = null;\n\n  switch (typeof server) {\n    case 'object':\n      selected = server;\n      break;\n\n    case 'string':\n      // Find server by URL\n      var servers = this.remote._servers;\n\n      for (var i=0, s; (s=servers[i]); i++) {\n        if (s._url === server) {\n          selected = s;\n          break;\n        }\n      }\n      break;\n  };\n\n  if (selected instanceof Server) {\n    this.server = selected;\n  }\n\n  return this;\n};\n\nRequest.prototype.buildPath = function(build) {\n  if (this.remote.local_signing) {\n    throw new Error(\n      '`build_path` is completely ignored when doing local signing as '\n      + '`Paths` is a component of the signed blob. The `tx_blob` is signed,'\n      + 'sealed and delivered, and the txn unmodified after' );\n  }\n\n  if (build) {\n    this.message.build_path = true;\n  } else {\n    // ND: rippled currently intreprets the mere presence of `build_path` as the\n    // value being `truthy`\n    delete this.message.build_path;\n  }\n\n  return this;\n};\n\nRequest.prototype.ledgerChoose = function(current) {\n  if (current) {\n    this.message.ledger_index = this.remote._ledger_current_index;\n  } else {\n    this.message.ledger_hash  = this.remote._ledger_hash;\n  }\n\n  return this;\n};\n\n// Set the ledger for a request.\n// - ledger_entry\n// - transaction_entry\nRequest.prototype.ledgerHash = function(hash) {\n  this.message.ledger_hash = hash;\n  return this;\n};\n\n// Set the ledger_index for a request.\n// - ledger_entry\nRequest.prototype.ledgerIndex = function(ledger_index) {\n  this.message.ledger_index = ledger_index;\n  return this;\n};\n\n/**\n * Set either ledger_index or ledger_hash based on heuristic\n *\n * @param {Number|String} ledger identifier\n */\n\nRequest.prototype.selectLedger =\nRequest.prototype.ledgerSelect = function(ledger) {\n  switch (ledger) {\n    case 'current':\n    case 'closed':\n    case 'validated':\n      this.message.ledger_index = ledger;\n      break;\n\n    default:\n      if (Number(ledger)) {\n        this.message.ledger_index = Number(ledger);\n      } else if (/^[A-F0-9]+$/.test(ledger)) {\n        this.message.ledger_hash = ledger;\n      }\n      break;\n  }\n\n  return this;\n};\n\nRequest.prototype.accountRoot = function(account) {\n  this.message.account_root  = UInt160.json_rewrite(account);\n  return this;\n};\n\nRequest.prototype.index = function(index) {\n  this.message.index  = index;\n  return this;\n};\n\n// Provide the information id an offer.\n// --> account\n// --> seq : sequence number of transaction creating offer (integer)\nRequest.prototype.offerId = function(account, sequence) {\n  this.message.offer = {\n    account:  UInt160.json_rewrite(account),\n    seq:      sequence\n  };\n  return this;\n};\n\n// --> index : ledger entry index.\nRequest.prototype.offerIndex = function(index) {\n  this.message.offer = index;\n  return this;\n};\n\nRequest.prototype.secret = function(secret) {\n  if (secret) {\n    this.message.secret = secret;\n  }\n  return this;\n};\n\nRequest.prototype.txHash = function(hash) {\n  this.message.tx_hash = hash;\n  return this;\n};\n\nRequest.prototype.txJson = function(json) {\n  this.message.tx_json = json;\n  return this;\n};\n\nRequest.prototype.txBlob = function(json) {\n  this.message.tx_blob = json;\n  return this;\n};\n\nRequest.prototype.rippleState = function(account, issuer, currency) {\n  this.message.ripple_state = {\n    currency : currency,\n    accounts : [\n      UInt160.json_rewrite(account),\n      UInt160.json_rewrite(issuer)\n    ]\n  };\n  return this;\n};\n\nRequest.prototype.setAccounts =\nRequest.prototype.accounts = function(accounts, proposed) {\n  if (!Array.isArray(accounts)) {\n    accounts = [ accounts ];\n  }\n\n  // Process accounts parameters\n  var processedAccounts = accounts.map(function(account) {\n    return UInt160.json_rewrite(account);\n  });\n\n  if (proposed) {\n    this.message.accounts_proposed = processedAccounts;\n  } else {\n    this.message.accounts = processedAccounts;\n  }\n\n  return this;\n};\n\nRequest.prototype.addAccount = function(account, proposed) {\n  if (Array.isArray(account)) {\n    account.forEach(this.addAccount, this);\n    return this;\n  }\n\n  var processedAccount = UInt160.json_rewrite(account);\n\n  if (proposed === true) {\n    this.message.accounts_proposed = (this.message.accounts_proposed || []).concat(processedAccount);\n  } else {\n    this.message.accounts = (this.message.accounts || []).concat(processedAccount);\n  }\n\n  return this;\n};\n\nRequest.prototype.setAccountsProposed =\nRequest.prototype.rtAccounts =\nRequest.prototype.accountsProposed = function(accounts) {\n  return this.accounts(accounts, true);\n};\n\nRequest.prototype.addAccountProposed = function(account) {\n  if (Array.isArray(account)) {\n    account.forEach(this.addAccountProposed, this);\n    return this;\n  }\n\n  return this.addAccount(account, true);\n};\n\nRequest.prototype.setBooks =\nRequest.prototype.books = function(books, snapshot) {\n  // Reset list of books (this method overwrites the current list)\n  this.message.books = [ ];\n\n  for (var i=0, l=books.length; i<l; i++) {\n    var book = books[i];\n    this.addBook(book, snapshot);\n  }\n\n  return this;\n};\n\nRequest.prototype.addBook = function(book, snapshot) {\n  if (Array.isArray(book)) {\n    book.forEach(this.addBook, this);\n    return this;\n  }\n\n  var json = { };\n\n  function processSide(side) {\n    if (!book[side]) {\n      throw new Error('Missing ' + side);\n    }\n\n    var obj = json[side] = {\n      currency: Currency.json_rewrite(book[side].currency, { force_hex: true })\n    };\n\n    if (!Currency.from_json(obj.currency).is_native()) {\n      obj.issuer = UInt160.json_rewrite(book[side].issuer);\n    }\n  }\n\n  [ 'taker_gets', 'taker_pays' ].forEach(processSide);\n\n  if (typeof snapshot !== 'boolean') {\n    json.snapshot = true;\n  } else if (snapshot) {\n    json.snapshot = true;\n  } else {\n    delete json.snapshot;\n  }\n\n  if (book.both) {\n    json.both = true;\n  }\n\n  this.message.books = (this.message.books || []).concat(json);\n\n  return this;\n};\n\nRequest.prototype.addStream = function(stream, values) {\n  var self = this;\n\n  if (Array.isArray(values)) {\n    switch (stream) {\n      case 'accounts':\n        this.addAccount(values);\n        break;\n      case 'accounts_proposed':\n        this.addAccountProposed(values);\n        break;\n      case 'books':\n        this.addBook(values);\n        break;\n    }\n  } else if (arguments.length > 1) {\n    for (arg in arguments) {\n      this.addStream(arguments[arg]);\n    }\n    return;\n  }\n\n  if (!Array.isArray(this.message.streams)) {\n    this.message.streams = [ ];\n  }\n\n  if (this.message.streams.indexOf(stream) === -1) {\n    this.message.streams.push(stream);\n  }\n\n  return this;\n};\n\nexports.Request = Request;\n\n\n// WEBPACK FOOTER\n// module.id = 2\n// module.readableIdentifier = ./src/js/ripple/request.js\n//@ sourceURL=webpack-module:///./src/js/ripple/request.js");

/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {

	eval("// Represent Ripple amounts and currencies.\n// - Numbers in hex are big-endian.\n\nvar extend = __webpack_require__(44);\nvar utils = __webpack_require__(19);\nvar sjcl  = utils.sjcl;\nvar bn    = sjcl.bn;\n\nvar BigInteger = utils.jsbn.BigInteger;\n\nvar UInt160  = __webpack_require__(8).UInt160;\nvar Seed     = __webpack_require__(10).Seed;\nvar Currency = __webpack_require__(6).Currency;\n\n//\n// Amount class in the style of Java's BigInteger class\n// http://docs.oracle.com/javase/1.3/docs/api/java/math/BigInteger.html\n//\n\nfunction Amount() {\n  // Json format:\n  //  integer : XRP\n  //  { 'value' : ..., 'currency' : ..., 'issuer' : ...}\n\n  this._value       = new BigInteger(); // NaN for bad value. Always positive.\n  this._offset      = 0; // Always 0 for XRP.\n  this._is_native   = true; // Default to XRP. Only valid if value is not NaN.\n  this._is_negative = false;\n  this._currency    = new Currency();\n  this._issuer      = new UInt160();\n};\n\nvar consts = {\n  currency_xns:      0,\n  currency_one:      1,\n  xns_precision:     6,\n\n  // BigInteger values prefixed with bi_.\n  bi_5:              new BigInteger('5'),\n  bi_7:              new BigInteger('7'),\n  bi_10:             new BigInteger('10'),\n  bi_1e14:           new BigInteger(String(1e14)),\n  bi_1e16:           new BigInteger(String(1e16)),\n  bi_1e17:           new BigInteger(String(1e17)),\n  bi_1e32:           new BigInteger('100000000000000000000000000000000'),\n  bi_man_max_value:  new BigInteger('9999999999999999'),\n  bi_man_min_value:  new BigInteger('1000000000000000'),\n  bi_xns_max:        new BigInteger('9000000000000000000'), // Json wire limit.\n  bi_xns_min:        new BigInteger('-9000000000000000000'),// Json wire limit.\n  bi_xns_unit:       new BigInteger('1000000'),\n\n  cMinOffset:        -96,\n  cMaxOffset:        80,\n\n  // Maximum possible amount for non-XRP currencies using the maximum mantissa\n  // with maximum exponent. Corresponds to hex 0xEC6386F26FC0FFFF.\n  max_value:         '9999999999999999e80',\n  // Minimum possible amount for non-XRP currencies.\n  min_value:         '-1000000000000000e-96'\n};\n\n// Add constants to Amount class\nextend(Amount, consts);\n\n// DEPRECATED: Use Amount instead, e.g. Amount.currency_xns\nexports.consts = consts;\n\n// Given '100/USD/mtgox' return the a string with mtgox remapped.\nAmount.text_full_rewrite = function(j) {\n  return Amount.from_json(j).to_text_full();\n};\n\n// Given '100/USD/mtgox' return the json.\nAmount.json_rewrite = function(j) {\n  return Amount.from_json(j).to_json();\n};\n\nAmount.from_number = function(n) {\n  return (new Amount()).parse_number(n);\n};\n\nAmount.from_json = function(j) {\n  return (new Amount()).parse_json(j);\n};\n\nAmount.from_quality = function(quality, currency, issuer, opts) {\n  return (new Amount()).parse_quality(quality, currency, issuer, opts);\n};\n\nAmount.from_human = function(j, opts) {\n  return (new Amount()).parse_human(j, opts);\n};\n\nAmount.is_valid = function(j) {\n  return Amount.from_json(j).is_valid();\n};\n\nAmount.is_valid_full = function(j) {\n  return Amount.from_json(j).is_valid_full();\n};\n\nAmount.NaN = function() {\n  var result = new Amount();\n  result._value = NaN;\n  return result;\n};\n\n// Returns a new value which is the absolute value of this.\nAmount.prototype.abs = function() {\n  return this.clone(this.is_negative());\n};\n\n// Result in terms of this' currency and issuer.\nAmount.prototype.add = function(v) {\n  var result;\n\n  v = Amount.from_json(v);\n\n  if (!this.is_comparable(v)) {\n    result              = Amount.NaN();\n  } else if (v.is_zero()) {\n    result              = this;\n  } else if (this.is_zero()) {\n    result              = v.clone();\n    result._is_native   = this._is_native;\n    result._currency    = this._currency;\n    result._issuer      = this._issuer;\n  } else if (this._is_native) {\n    result              = new Amount();\n\n    var v1  = this._is_negative ? this._value.negate() : this._value;\n    var v2  = v._is_negative ? v._value.negate() : v._value;\n    var s   = v1.add(v2);\n\n    result._is_negative = s.compareTo(BigInteger.ZERO) < 0;\n    result._value       = result._is_negative ? s.negate() : s;\n    result._currency    = this._currency;\n    result._issuer      = this._issuer;\n  } else {\n    var v1  = this._is_negative ? this._value.negate() : this._value;\n    var o1  = this._offset;\n    var v2  = v._is_negative ? v._value.negate() : v._value;\n    var o2  = v._offset;\n\n    while (o1 < o2) {\n      v1  = v1.divide(Amount.bi_10);\n      o1  += 1;\n    }\n\n    while (o2 < o1) {\n      v2  = v2.divide(Amount.bi_10);\n      o2  += 1;\n    }\n\n    result = new Amount();\n    result._is_native = false;\n    result._offset = o1;\n    result._value = v1.add(v2);\n    result._is_negative = result._value.compareTo(BigInteger.ZERO) < 0;\n\n    if (result._is_negative) {\n      result._value = result._value.negate();\n    }\n\n    result._currency = this._currency;\n    result._issuer = this._issuer;\n\n    result.canonicalize();\n  }\n\n  return result;\n};\n\n// Result in terms of this currency and issuer.\nAmount.prototype.subtract = function(v) {\n  // Correctness over speed, less code has less bugs, reuse add code.\n  return this.add(Amount.from_json(v).negate());\n};\n\n// Result in terms of this' currency and issuer.\n// XXX Diverges from cpp.\nAmount.prototype.multiply = function(v) {\n  var result;\n\n  v = Amount.from_json(v);\n\n  if (this.is_zero()) {\n    result = this;\n  } else if (v.is_zero()) {\n    result = this.clone();\n    result._value = BigInteger.ZERO;\n  } else {\n    var v1 = this._value;\n    var o1 = this._offset;\n    var v2 = v._value;\n    var o2 = v._offset;\n\n    if (this.is_native()) {\n      while (v1.compareTo(Amount.bi_man_min_value) < 0) {\n        v1 = v1.multiply(Amount.bi_10);\n        o1 -= 1;\n      }\n    }\n\n    if (v.is_native()) {\n      while (v2.compareTo(Amount.bi_man_min_value) < 0) {\n        v2 = v2.multiply(Amount.bi_10);\n        o2 -= 1;\n      }\n    }\n\n    result              = new Amount();\n    result._offset      = o1 + o2 + 14;\n    result._value       = v1.multiply(v2).divide(Amount.bi_1e14).add(Amount.bi_7);\n    result._is_native   = this._is_native;\n    result._is_negative = this._is_negative !== v._is_negative;\n    result._currency    = this._currency;\n    result._issuer      = this._issuer;\n\n    result.canonicalize();\n  }\n\n  return result;\n};\n\n// Result in terms of this' currency and issuer.\nAmount.prototype.divide = function(d) {\n  var result;\n\n  d = Amount.from_json(d);\n\n  if (d.is_zero()) {\n    throw new Error('divide by zero');\n  }\n\n  if (this.is_zero()) {\n    result = this;\n  } else if (!this.is_valid()) {\n    throw new Error('Invalid dividend');\n  } else if (!d.is_valid()) {\n    throw new Error('Invalid divisor');\n  } else {\n    var _n = this;\n\n    if (_n.is_native()) {\n      _n  = _n.clone();\n\n      while (_n._value.compareTo(Amount.bi_man_min_value) < 0) {\n        _n._value  = _n._value.multiply(Amount.bi_10);\n        _n._offset -= 1;\n      }\n    }\n\n    var _d = d;\n\n    if (_d.is_native()) {\n      _d = _d.clone();\n\n      while (_d._value.compareTo(Amount.bi_man_min_value) < 0) {\n        _d._value  = _d._value.multiply(Amount.bi_10);\n        _d._offset -= 1;\n      }\n    }\n\n    result              = new Amount();\n    result._offset      = _n._offset - _d._offset - 17;\n    result._value       = _n._value.multiply(Amount.bi_1e17).divide(_d._value).add(Amount.bi_5);\n    result._is_native   = _n._is_native;\n    result._is_negative = _n._is_negative !== _d._is_negative;\n    result._currency    = _n._currency;\n    result._issuer      = _n._issuer;\n\n    result.canonicalize();\n  }\n\n  return result;\n};\n\n/**\n * This function calculates a ratio - such as a price - between two Amount\n * objects.\n *\n * The return value will have the same type (currency) as the numerator. This is\n * a simplification, which should be sane in most cases. For example, a USD/XRP\n * price would be rendered as USD.\n *\n * @example\n *   var price = buy_amount.ratio_human(sell_amount);\n *\n * @this {Amount} The numerator (top half) of the fraction.\n * @param {Amount} denominator The denominator (bottom half) of the fraction.\n * @param opts Options for the calculation.\n * @param opts.reference_date {Date|Number} Date based on which demurrage/interest\n *   should be applied. Can be given as JavaScript Date or int for Ripple epoch.\n * @return {Amount} The resulting ratio. Unit will be the same as numerator.\n */\n\nAmount.prototype.ratio_human = function(denominator, opts) {\n  opts = extend({ }, opts);\n\n  var numerator = this;\n\n  if (typeof denominator === 'number' && parseInt(denominator, 10) === denominator) {\n    // Special handling of integer arguments\n    denominator = Amount.from_json(String(denominator) + '.0');\n  } else {\n    denominator = Amount.from_json(denominator);\n  }\n\n  denominator = Amount.from_json(denominator);\n\n  // If either operand is NaN, the result is NaN.\n  if (!numerator.is_valid() || !denominator.is_valid()) {\n    return Amount.NaN();\n  }\n\n  if (denominator.is_zero()) {\n    return Amount.NaN();\n  }\n\n  // Apply interest/demurrage\n  //\n  // We only need to apply it to the second factor, because the currency unit of\n  // the first factor will carry over into the result.\n  if (opts.reference_date) {\n    denominator = denominator.applyInterest(opts.reference_date);\n  }\n\n  // Special case: The denominator is a native (XRP) amount.\n  //\n  // In that case, it's going to be expressed as base units (1 XRP =\n  // 10^xns_precision base units).\n  //\n  // However, the unit of the denominator is lost, so when the resulting ratio\n  // is printed, the ratio is going to be too small by a factor of\n  // 10^xns_precision.\n  //\n  // To compensate, we multiply the numerator by 10^xns_precision.\n  if (denominator._is_native) {\n    numerator = numerator.clone();\n    numerator._value = numerator._value.multiply(Amount.bi_xns_unit);\n    numerator.canonicalize();\n  }\n\n  return numerator.divide(denominator);\n};\n\n/**\n * Calculate a product of two amounts.\n *\n * This function allows you to calculate a product between two amounts which\n * retains XRPs human/external interpretation (i.e. 1 XRP = 1,000,000 base\n * units).\n *\n * Intended use is to calculate something like: 10 USD * 10 XRP/USD = 100 XRP\n *\n * @example\n *   var sell_amount = buy_amount.product_human(price);\n *\n * @see Amount#ratio_human\n *\n * @this {Amount} The first factor of the product.\n * @param {Amount} factor The second factor of the product.\n * @param opts Options for the calculation.\n * @param opts.reference_date {Date|Number} Date based on which demurrage/interest\n *   should be applied. Can be given as JavaScript Date or int for Ripple epoch.\n * @return {Amount} The product. Unit will be the same as the first factor.\n */\nAmount.prototype.product_human = function(factor, opts) {\n  opts = opts || {};\n\n  if (typeof factor === 'number' && parseInt(factor, 10) === factor) {\n    // Special handling of integer arguments\n    factor = Amount.from_json(String(factor) + '.0');\n  } else {\n    factor = Amount.from_json(factor);\n  }\n\n  // If either operand is NaN, the result is NaN.\n  if (!this.is_valid() || !factor.is_valid()) {\n    return Amount.NaN();\n  }\n\n  // Apply interest/demurrage\n  //\n  // We only need to apply it to the second factor, because the currency unit of\n  // the first factor will carry over into the result.\n  if (opts.reference_date) {\n    factor = factor.applyInterest(opts.reference_date);\n  }\n\n  var product = this.multiply(factor);\n\n  // Special case: The second factor is a native (XRP) amount expressed as base\n  // units (1 XRP = 10^xns_precision base units).\n  //\n  // See also Amount#ratio_human.\n  if (factor._is_native) {\n    product._value = product._value.divide(Amount.bi_xns_unit);\n    product.canonicalize();\n  }\n\n  return product;\n};\n\n/**\n * Turn this amount into its inverse.\n *\n * @private\n */\nAmount.prototype._invert = function() {\n  this._value = Amount.bi_1e32.divide(this._value);\n  this._offset = -32 - this._offset;\n  this.canonicalize();\n\n  return this;\n};\n\n/**\n * Return the inverse of this amount.\n *\n * @return {Amount} New Amount object with same currency and issuer, but the\n *   inverse of the value.\n */\nAmount.prototype.invert = function() {\n  return this.copy()._invert();\n};\n\n/**\n * Canonicalize amount value\n *\n * Mirrors rippled's internal Amount representation\n * From https://github.com/ripple/rippled/blob/develop/src/ripple/data/protocol/STAmount.h#L31-L40\n *\n * Internal form:\n * 1: If amount is zero, then value is zero and offset is -100\n * 2: Otherwise:\n *    legal offset range is -96 to +80 inclusive\n *    value range is 10^15 to (10^16 - 1) inclusive\n *    amount = value * [10 ^ offset]\n *\n * -------------------\n *\n * The amount can be epxresses as A x 10^B\n * Where:\n * - A must be an integer between 10^15 and (10^16)-1 inclusive\n * - B must be between -96 and 80 inclusive\n *\n * This results\n * - minumum: 10^15 x 10^-96 -> 10^-81 -> -1e-81\n * - maximum: (10^16)-1 x 10^80 -> 9999999999999999e80\n *\n * @returns {Amount}\n * @throws {Error} if offset exceeds legal ranges, meaning the amount value is bigger than supported\n */\nAmount.prototype.canonicalize = function() {\n  if (!(this._value instanceof BigInteger)) {\n    // NaN.\n    // nothing\n  } else if (this._is_native) {\n    // Native.\n    if (this._value.equals(BigInteger.ZERO)) {\n      this._offset      = 0;\n      this._is_negative = false;\n    } else {\n      // Normalize _offset to 0.\n\n      while (this._offset < 0) {\n        this._value  = this._value.divide(Amount.bi_10);\n        this._offset += 1;\n      }\n\n      while (this._offset > 0) {\n        this._value  = this._value.multiply(Amount.bi_10);\n        this._offset -= 1;\n      }\n    }\n\n  } else if (this.is_zero()) {\n    this._offset      = Amount.cMinOffset;\n    this._is_negative = false;\n  } else {\n    // Normalize mantissa to valid range.\n\n    while (this._value.compareTo(Amount.bi_man_min_value) < 0) {\n      this._value  = this._value.multiply(Amount.bi_10);\n      this._offset -= 1;\n    }\n\n    while (this._value.compareTo(Amount.bi_man_max_value) > 0) {\n      this._value  = this._value.divide(Amount.bi_10);\n      this._offset += 1;\n    }\n  }\n\n  // Make sure not bigger than supported. Throw if so.\n  if (this.is_negative() && this._offset < Amount.cMinOffset) {\n    throw new Error('Exceeding min value of ' + Amount.min_value);\n  }\n\n  // Make sure not smaller than supported. Throw if so.\n  if (!this.is_negative() && this._offset > Amount.cMaxOffset) {\n    throw new Error('Exceeding max value of ' + Amount.max_value);\n  }\n\n  return this;\n};\n\nAmount.prototype.clone = function(negate) {\n  return this.copyTo(new Amount(), negate);\n};\n\nAmount.prototype.compareTo = function(v) {\n  var result;\n\n  v = Amount.from_json(v);\n\n  if (!this.is_comparable(v)) {\n    result  = Amount.NaN();\n  } else if (this._is_negative !== v._is_negative) {\n    // Different sign.\n    result  = this._is_negative ? -1 : 1;\n  } else if (this._value.equals(BigInteger.ZERO)) {\n    // Same sign: positive.\n    result  = v._value.equals(BigInteger.ZERO) ? 0 : -1;\n  } else if (v._value.equals(BigInteger.ZERO)) {\n    // Same sign: positive.\n    result  = 1;\n  } else if (!this._is_native && this._offset > v._offset) {\n    result  = this._is_negative ? -1 : 1;\n  } else if (!this._is_native && this._offset < v._offset) {\n    result  = this._is_negative ? 1 : -1;\n  } else {\n    result  = this._value.compareTo(v._value);\n    if (result > 0) {\n      result  = this._is_negative ? -1 : 1;\n    } else if (result < 0) {\n      result  = this._is_negative ? 1 : -1;\n    }\n  }\n\n  return result;\n};\n\n// Make d a copy of this. Returns d.\n// Modification of objects internally refered to is not allowed.\nAmount.prototype.copyTo = function(d, negate) {\n  if (typeof this._value === 'object') {\n    this._value.copyTo(d._value);\n  } else {\n    d._value   = this._value;\n  }\n\n  d._offset = this._offset;\n  d._is_native = this._is_native;\n  d._is_negative  = negate\n    ? !this._is_negative    // Negating.\n    : this._is_negative;    // Just copying.\n\n  d._currency     = this._currency;\n  d._issuer       = this._issuer;\n\n  // Prevent negative zero\n  if (d.is_zero()) {\n    d._is_negative = false;\n  }\n\n  return d;\n};\n\nAmount.prototype.currency = function() {\n  return this._currency;\n};\n\nAmount.prototype.equals = function(d, ignore_issuer) {\n  if (typeof d === 'string') {\n    return this.equals(Amount.from_json(d));\n  }\n\n  var result = !((!this.is_valid() || !d.is_valid())\n             || (this._is_native !== d._is_native)\n             || (!this._value.equals(d._value) || this._offset !== d._offset)\n             || (this._is_negative !== d._is_negative)\n             || (!this._is_native && (!this._currency.equals(d._currency) || !ignore_issuer && !this._issuer.equals(d._issuer))));\n\n  return result;\n};\n\n// True if Amounts are valid and both native or non-native.\nAmount.prototype.is_comparable = function(v) {\n  return this._value instanceof BigInteger\n    && v._value instanceof BigInteger\n    && this._is_native === v._is_native;\n};\n\nAmount.prototype.is_native = function() {\n  return this._is_native;\n};\n\nAmount.prototype.is_negative = function() {\n  return this._value instanceof BigInteger\n          ? this._is_negative\n          : false;                          // NaN is not negative\n};\n\nAmount.prototype.is_positive = function() {\n  return !this.is_zero() && !this.is_negative();\n};\n\n// Only checks the value. Not the currency and issuer.\nAmount.prototype.is_valid = function() {\n  return this._value instanceof BigInteger;\n};\n\nAmount.prototype.is_valid_full = function() {\n  return this.is_valid() && this._currency.is_valid() && this._issuer.is_valid();\n};\n\nAmount.prototype.is_zero = function() {\n  return this._value instanceof BigInteger ? this._value.equals(BigInteger.ZERO) : false;\n};\n\nAmount.prototype.issuer = function() {\n  return this._issuer;\n};\n\n// Return a new value.\nAmount.prototype.negate = function() {\n  return this.clone('NEGATE');\n};\n\n/**\n * Invert this amount and return the new value.\n *\n * Creates a new Amount object as a copy of the current one (including the same\n * unit (currency & issuer), inverts it (1/x) and returns the result.\n */\nAmount.prototype.invert = function() {\n  var one          = this.clone();\n  one._value       = BigInteger.ONE;\n  one._offset      = 0;\n  one._is_negative = false;\n\n  one.canonicalize();\n\n  return one.ratio_human(this);\n};\n\n/**\n * Tries to correctly interpret an amount as entered by a user.\n *\n * Examples:\n *\n *   XRP 250     => 250000000/XRP\n *   25.2 XRP    => 25200000/XRP\n *   USD 100.40  => 100.4/USD/?\n *   100         => 100000000/XRP\n *\n *\n * The regular expression below matches above cases, broken down for better understanding:\n *\n * ^\\s*                         // start with any amount of whitespace\n * ([A-z]{3}|[0-9]{3})          // either 3 letter alphabetic currency-code or 3 digit numeric currency-code. See ISO 4217\n * \\s*                          // any amount of whitespace\n * (-)?                         // optional dash\n * (\\d+)                        // 1 or more digits\n * (?:\\.(\\d*))?                 // optional . character with any amount of digits\n * \\s*                          // any amount of whitespace\n * ([A-z]{3}|[0-9]{3})?         // either 3 letter alphabetic currency-code or 3 digit numeric currency-code. See ISO 4217\n * \\s*                          // any amount of whitespace\n * $                            // end of string\n *\n */\nAmount.human_RE_hex = /^\\s*(-)?(\\d+)(?:\\.(\\d*))?\\s*([a-fA-F0-9]{40})\\s*$/;\nAmount.human_RE = /^\\s*([A-z]{3}|[0-9]{3})?\\s*(-)?(\\d+)(?:\\.(\\d*))?\\s*([A-z]{3}|[0-9]{3})?\\s*$/;\n\nAmount.prototype.parse_human = function(j, opts) {\n  opts = opts || {};\n\n  var integer;\n  var fraction;\n  var currency;\n  var precision  = null;\n\n  // first check if it's a hex formatted currency\n  var matches = String(j).match(Amount.human_RE_hex);\n  if (matches && matches.length === 5 && matches[4]) {\n    integer  = matches[2];\n    fraction = matches[3] || '';\n    currency = matches[4];\n    this._is_negative = Boolean(matches[1]);\n  }\n\n  if (integer === void(0) && currency === void(0)) {\n    var m = String(j).match(Amount.human_RE);\n    if (m) {\n      currency = m[5] || m[1] || 'XRP';\n      integer = m[5] && m[1] ? m[1] + '' + m[3] : (m[3] || '0');\n      fraction = m[4] || '';\n      this._is_negative = Boolean(m[2]);\n    }\n  }\n\n  if (integer) {\n    currency = currency.toUpperCase();\n\n    this._value = new BigInteger(integer);\n    this.set_currency(currency);\n\n    // XRP have exactly six digits of precision\n    if (currency === 'XRP') {\n      fraction = fraction.slice(0, 6);\n      while (fraction.length < 6) {\n        fraction += '0';\n      }\n      this._is_native = true;\n      this._value     = this._value.multiply(Amount.bi_xns_unit).add(new BigInteger(fraction));\n    } else {\n      // Other currencies have arbitrary precision\n      fraction  = fraction.replace(/0+$/, '');\n      precision = fraction.length;\n\n      this._is_native = false;\n      var multiplier  = Amount.bi_10.clone().pow(precision);\n      this._value     = this._value.multiply(multiplier).add(new BigInteger(fraction));\n      this._offset    = -precision;\n\n      this.canonicalize();\n    }\n\n    // Apply interest/demurrage\n    if (opts.reference_date && this._currency.has_interest()) {\n      var interest = this._currency.get_interest_at(opts.reference_date);\n\n      // XXX Because the Amount parsing routines don't support some of the things\n      //     that JavaScript can output when casting a float to a string, the\n      //     following call sometimes does not produce a valid Amount.\n      //\n      //     The correct way to solve this is probably to switch to a proper\n      //     BigDecimal for our internal representation and then use that across\n      //     the board instead of instantiating these dummy Amount objects.\n      var interestTempAmount = Amount.from_json(''+interest+'/1/1');\n\n      if (interestTempAmount.is_valid()) {\n        var ref = this.divide(interestTempAmount);\n        this._value = ref._value;\n        this._offset = ref._offset;\n      }\n    }\n  } else {\n    this._value = NaN;\n  }\n\n  return this;\n};\n\nAmount.prototype.parse_issuer = function(issuer) {\n  this._issuer  = UInt160.from_json(issuer);\n\n  return this;\n};\n\n/**\n * Decode a price from a BookDirectory index.\n *\n * BookDirectory ledger entries each encode the offer price in their index. This\n * method can decode that information and populate an Amount object with it.\n *\n * It is possible not to provide a currency or issuer, but be aware that Amount\n * objects behave differently based on the currency, so you may get incorrect\n * results.\n *\n * Prices involving demurraging currencies are tricky, since they depend on the\n * base and counter currencies.\n *\n * @param quality {String} 8 hex bytes quality or 32 hex bytes BookDirectory\n *   index.\n * @param counterCurrency {Currency|String} Currency of the resulting Amount\n *   object.\n * @param counterIssuer {Issuer|String} Issuer of the resulting Amount object.\n * @param opts Additional options\n * @param opts.inverse {Boolean} If true, return the inverse of the price\n *   encoded in the quality.\n * @param opts.base_currency {Currency|String} The other currency. This plays a\n *   role with interest-bearing or demurrage currencies. In that case the\n *   demurrage has to be applied when the quality is decoded, otherwise the\n *   price will be false.\n * @param opts.reference_date {Date|Number} Date based on which demurrage/interest\n *   should be applied. Can be given as JavaScript Date or int for Ripple epoch.\n * @param opts.xrp_as_drops {Boolean} Whether XRP amount should be treated as\n *   drops. When the base currency is XRP, the quality is calculated in drops.\n *   For human use however, we want to think of 1000000 drops as 1 XRP and\n *   prices as per-XRP instead of per-drop.\n */\nAmount.prototype.parse_quality = function(quality, counterCurrency, counterIssuer, opts)\n{\n  opts = opts || {};\n\n  var baseCurrency = Currency.from_json(opts.base_currency);\n\n  this._is_negative = false;\n  this._value       = new BigInteger(quality.substring(quality.length-14), 16);\n  this._offset      = parseInt(quality.substring(quality.length-16, quality.length-14), 16)-100;\n  this._currency    = Currency.from_json(counterCurrency);\n  this._issuer      = UInt160.from_json(counterIssuer);\n  this._is_native   = this._currency.is_native();\n\n  // Correct offset if xrp_as_drops option is not set and base currency is XRP\n  if (!opts.xrp_as_drops &&\n      baseCurrency.is_valid() &&\n      baseCurrency.is_native()) {\n    if (opts.inverse) {\n      this._offset -= 6;\n    } else {\n      this._offset += 6;\n    }\n  }\n\n  if (opts.inverse) {\n    this._invert();\n  }\n\n  this.canonicalize();\n\n  if (opts.reference_date && baseCurrency.is_valid() && baseCurrency.has_interest()) {\n    var interest = baseCurrency.get_interest_at(opts.reference_date);\n\n    // XXX If we had better math utilities, we wouldn't need this hack.\n    var interestTempAmount = Amount.from_json(''+interest+'/1/1');\n\n    if (interestTempAmount.is_valid()) {\n      var v = this.divide(interestTempAmount);\n      this._value = v._value;\n      this._offset = v._offset;\n    }\n  }\n\n  return this;\n};\n\nAmount.prototype.parse_number = function(n) {\n  this._is_native   = false;\n  this._currency    = Currency.from_json(1);\n  this._issuer      = UInt160.from_json(1);\n  this._is_negative = n < 0 ? true : false;\n  this._value       = new BigInteger(String(this._is_negative ? -n : n));\n  this._offset      = 0;\n\n  this.canonicalize();\n\n  return this;\n};\n\n// <-> j\nAmount.prototype.parse_json = function(j) {\n  switch (typeof j) {\n    case 'string':\n      // .../.../... notation is not a wire format.  But allowed for easier testing.\n      var m = j.match(/^([^/]+)\\/([^/]+)(?:\\/(.+))?$/);\n\n      if (m) {\n        this._currency  = Currency.from_json(m[2]);\n        if (m[3]) {\n          this._issuer  = UInt160.from_json(m[3]);\n        } else {\n          this._issuer  = UInt160.from_json('1');\n        }\n        this.parse_value(m[1]);\n      } else {\n        this.parse_native(j);\n        this._currency  = Currency.from_json('0');\n        this._issuer    = UInt160.from_json('0');\n      }\n      break;\n\n    case 'number':\n      this.parse_json(String(j));\n      break;\n\n    case 'object':\n      if (j === null) {\n        break;\n      }\n\n      if (j instanceof Amount) {\n        j.copyTo(this);\n      } else if (j.hasOwnProperty('value')) {\n        // Parse the passed value to sanitize and copy it.\n        this._currency.parse_json(j.currency, true); // Never XRP.\n\n        if (typeof j.issuer === 'string') {\n          this._issuer.parse_json(j.issuer);\n        }\n\n        this.parse_value(j.value);\n      }\n      break;\n\n    default:\n      this._value = NaN;\n  }\n\n  return this;\n};\n\n// Parse a XRP value from untrusted input.\n// - integer = raw units\n// - float = with precision 6\n// XXX Improvements: disallow leading zeros.\nAmount.prototype.parse_native = function(j) {\n  var m;\n\n  if (typeof j === 'string') {\n    m = j.match(/^(-?)(\\d*)(\\.\\d{0,6})?$/);\n  }\n\n  if (m) {\n    if (m[3] === void(0)) {\n      // Integer notation\n      this._value = new BigInteger(m[2]);\n    } else {\n      // Float notation : values multiplied by 1,000,000.\n      var int_part      = (new BigInteger(m[2])).multiply(Amount.bi_xns_unit);\n      var fraction_part = (new BigInteger(m[3])).multiply(new BigInteger(String(Math.pow(10, 1+Amount.xns_precision-m[3].length))));\n\n      this._value = int_part.add(fraction_part);\n    }\n\n    this._is_native   = true;\n    this._offset      = 0;\n    this._is_negative = !!m[1] && this._value.compareTo(BigInteger.ZERO) !== 0;\n\n    if (this._value.compareTo(Amount.bi_xns_max) > 0) {\n      this._value = NaN;\n    }\n  } else {\n    this._value = NaN;\n  }\n\n  return this;\n};\n\n// Parse a non-native value for the json wire format.\n// Requires _currency to be set!\nAmount.prototype.parse_value = function(j) {\n  this._is_native    = false;\n\n  switch (typeof j) {\n    case 'number':\n      this._is_negative = j < 0;\n      this._value       = new BigInteger(Math.abs(j));\n      this._offset      = 0;\n\n      this.canonicalize();\n      break;\n\n    case 'string':\n      var i = j.match(/^(-?)(\\d+)$/);\n      var d = !i && j.match(/^(-?)(\\d*)\\.(\\d*)$/);\n      var e = !e && j.match(/^(-?)(\\d*)e(-?\\d+)$/);\n\n      if (e) {\n        // e notation\n        this._value       = new BigInteger(e[2]);\n        this._offset      = parseInt(e[3]);\n        this._is_negative = !!e[1];\n\n        this.canonicalize();\n      } else if (d) {\n        // float notation\n        var integer   = new BigInteger(d[2]);\n        var fraction  = new BigInteger(d[3]);\n        var precision = d[3].length;\n\n        this._value       = integer.multiply(Amount.bi_10.clone().pow(precision)).add(fraction);\n        this._offset      = -precision;\n        this._is_negative = !!d[1];\n\n        this.canonicalize();\n      } else if (i) {\n        // integer notation\n        this._value       = new BigInteger(i[2]);\n        this._offset      = 0;\n        this._is_negative = !!i[1];\n\n        this.canonicalize();\n      } else {\n        this._value = NaN;\n      }\n      break;\n\n    default:\n      this._value = j instanceof BigInteger ? j : NaN;\n  }\n\n  return this;\n};\n\nAmount.prototype.set_currency = function(c) {\n  this._currency  = Currency.from_json(c);\n  this._is_native = this._currency.is_native();\n\n  return this;\n};\n\nAmount.prototype.set_issuer = function(issuer) {\n  if (issuer instanceof UInt160) {\n    this._issuer  = issuer;\n  } else {\n    this._issuer  = UInt160.from_json(issuer);\n  }\n\n  return this;\n};\n\nAmount.prototype.to_number = function(allow_nan) {\n  var s = this.to_text(allow_nan);\n  return typeof s === 'string' ? Number(s) : s;\n};\n\n// Convert only value to JSON wire format.\nAmount.prototype.to_text = function(allow_nan) {\n  var result = NaN;\n\n  if (this._is_native) {\n    if (this.is_valid() && this._value.compareTo(Amount.bi_xns_max) <= 0){\n      result = this._value.toString();\n    }\n  } else if (this.is_zero()) {\n    result = '0';\n  } else if (this._offset && (this._offset < -25 || this._offset > -4)) {\n    // Use e notation.\n    // XXX Clamp output.\n    result = this._value.toString() + 'e' + this._offset;\n  } else {\n    var val    = '000000000000000000000000000' + this._value.toString() + '00000000000000000000000';\n    var pre    = val.substring(0, this._offset + 43);\n    var post   = val.substring(this._offset + 43);\n    var s_pre  = pre.match(/[1-9].*$/);  // Everything but leading zeros.\n    var s_post = post.match(/[1-9]0*$/); // Last non-zero plus trailing zeros.\n\n    result = ''\n      + (s_pre ? s_pre[0] : '0')\n      + (s_post ? '.' + post.substring(0, 1 + post.length - s_post[0].length) : '');\n  }\n\n  if (!allow_nan && typeof result === 'number' && isNaN(result)) {\n    result = '0';\n  } else if (this._is_negative) {\n    result = '-' + result;\n  }\n\n  return result;\n};\n\n/**\n * Calculate present value based on currency and a reference date.\n *\n * This only affects demurraging and interest-bearing currencies.\n *\n * User should not store amount objects after the interest is applied. This is\n * intended by display functions such as toHuman().\n *\n * @param referenceDate {Date|Number} Date based on which demurrage/interest\n *   should be applied. Can be given as JavaScript Date or int for Ripple epoch.\n * @return {Amount} The amount with interest applied.\n */\nAmount.prototype.applyInterest = function(referenceDate) {\n  if (this._currency.has_interest()) {\n    var interest = this._currency.get_interest_at(referenceDate);\n\n    // XXX Because the Amount parsing routines don't support some of the things\n    //     that JavaScript can output when casting a float to a string, the\n    //     following call sometimes does not produce a valid Amount.\n    //\n    //     The correct way to solve this is probably to switch to a proper\n    //     BigDecimal for our internal representation and then use that across\n    //     the board instead of instantiating these dummy Amount objects.\n    var interestTempAmount = Amount.from_json(String(interest) + '/1/1');\n\n    if (interestTempAmount.is_valid()) {\n      return this.multiply(interestTempAmount);\n    }\n  } else {\n    return this;\n  }\n};\n\n/**\n * Format only value in a human-readable format.\n *\n * @example\n *   var pretty = amount.to_human({precision: 2});\n *\n * @param opts Options for formatter.\n * @param opts.precision {Number} Max. number of digits after decimal point.\n * @param opts.min_precision {Number} Min. number of digits after dec. point.\n * @param opts.skip_empty_fraction {Boolean} Don't show fraction if it is zero,\n *   even if min_precision is set.\n * @param opts.max_sig_digits {Number} Maximum number of significant digits.\n *   Will cut fractional part, but never integer part.\n * @param opts.group_sep {Boolean|String} Whether to show a separator every n\n *   digits, if a string, that value will be used as the separator. Default: ','\n * @param opts.group_width {Number} How many numbers will be grouped together,\n *   default: 3.\n * @param opts.signed {Boolean|String} Whether negative numbers will have a\n *   prefix. If String, that string will be used as the prefix. Default: '-'\n * @param opts.reference_date {Date|Number} Date based on which demurrage/interest\n *   should be applied. Can be given as JavaScript Date or int for Ripple epoch.\n */\nAmount.prototype.to_human = function(opts) {\n  opts = opts || {};\n\n  if (!this.is_valid()) {\n    return '';\n  }\n\n  // Default options\n  if (typeof opts.signed === 'undefined') {\n    opts.signed = true;\n  }\n  if (typeof opts.group_sep === 'undefined') {\n    opts.group_sep = true;\n  }\n\n  opts.group_width = opts.group_width || 3;\n\n  // Apply demurrage/interest\n  var ref = this;\n  if (opts.reference_date) {\n    ref = this.applyInterest(opts.reference_date);\n  }\n\n  var order         = ref._is_native ? Amount.xns_precision : -ref._offset;\n  var denominator   = Amount.bi_10.clone().pow(order);\n  var int_part      = ref._value.divide(denominator).toString();\n  var fraction_part = ref._value.mod(denominator).toString();\n\n  // Add leading zeros to fraction\n  while (fraction_part.length < order) {\n    fraction_part = '0' + fraction_part;\n  }\n\n  int_part = int_part.replace(/^0*/, '');\n  fraction_part = fraction_part.replace(/0*$/, '');\n\n  if (fraction_part.length || !opts.skip_empty_fraction) {\n\n    // Enforce the maximum number of decimal digits (precision)\n    if (typeof opts.precision === 'number') {\n      if (opts.precision <= 0) {\n\n        // increment the int_part if the first decimal is 5 or higher\n        if (fraction_part.charCodeAt(0) >= 53) {\n          int_part = (Number(int_part) + 1).toString();\n        }\n        fraction_part = '';\n      } else {\n        var precision = Math.min(opts.precision, fraction_part.length);\n        fraction_part = Math.round(fraction_part / Math.pow(10, fraction_part.length - precision)).toString();\n\n        // because the division above will cut off the leading 0's we have to add them back again\n        // XXX look for a more elegant alternative\n        while (fraction_part.length < precision) {\n          fraction_part = '0' + fraction_part;\n        }\n      }\n    }\n\n    // Limit the number of significant digits (max_sig_digits)\n    if (typeof opts.max_sig_digits === 'number') {\n      // First, we count the significant digits we have.\n      // A zero in the integer part does not count.\n      var int_is_zero = +int_part === 0;\n      var digits = int_is_zero ? 0 : int_part.length;\n\n      // Don't count leading zeros in the fractional part if the integer part is\n      // zero.\n      var sig_frac = int_is_zero ? fraction_part.replace(/^0*/, '') : fraction_part;\n      digits += sig_frac.length;\n\n      // Now we calculate where we are compared to the maximum\n      var rounding = digits - opts.max_sig_digits;\n\n      // If we're under the maximum we want to cut no (=0) digits\n      rounding = Math.max(rounding, 0);\n\n      // If we're over the maximum we still only want to cut digits from the\n      // fractional part, not from the integer part.\n      rounding = Math.min(rounding, fraction_part.length);\n\n      // Now we cut `rounding` digits off the right.\n      if (rounding > 0) {\n        fraction_part = fraction_part.slice(0, -rounding);\n      }\n    }\n\n    // Enforce the minimum number of decimal digits (min_precision)\n    if (typeof opts.min_precision === 'number') {\n      while (fraction_part.length < opts.min_precision) {\n        fraction_part += '0';\n      }\n    }\n  }\n\n  if (opts.group_sep) {\n    if (typeof opts.group_sep !== 'string') {\n      opts.group_sep = ',';\n    }\n    int_part = utils.chunkString(int_part, opts.group_width, true).join(opts.group_sep);\n  }\n\n  var formatted = '';\n  if (opts.signed && this._is_negative) {\n    if (typeof opts.signed !== 'string') {\n      opts.signed = '-';\n    }\n    formatted += opts.signed;\n  }\n\n  formatted += int_part.length ? int_part : '0';\n  formatted += fraction_part.length ? '.' + fraction_part : '';\n\n  return formatted;\n};\n\nAmount.prototype.to_human_full = function(opts) {\n  opts = opts || {};\n  var a = this.to_human(opts);\n  var c = this._currency.to_human();\n  var i = this._issuer.to_json(opts);\n  var o = this.is_native() ?  (o = a + '/' + c) : (o  = a + '/' + c + '/' + i);\n  return o;\n};\n\nAmount.prototype.to_json = function() {\n  var result;\n\n  if (this._is_native) {\n    result = this.to_text();\n  } else {\n    var amount_json = {\n      value : this.to_text(),\n      currency : this._currency.has_interest() ? this._currency.to_hex() : this._currency.to_json()\n    };\n    if (this._issuer.is_valid()) {\n      amount_json.issuer = this._issuer.to_json();\n    }\n    result = amount_json;\n  }\n\n  return result;\n};\n\nAmount.prototype.to_text_full = function(opts) {\n  return this._value instanceof BigInteger\n    ? this._is_native\n      ? this.to_human() + '/XRP'\n      : this.to_text() + '/' + this._currency.to_json() + '/' + this._issuer.to_json(opts)\n    : NaN;\n};\n\n// For debugging.\nAmount.prototype.not_equals_why = function(d, ignore_issuer) {\n  if (typeof d === 'string') {\n    return this.not_equals_why(Amount.from_json(d));\n  }\n\n  if (!(d instanceof Amount)) {\n    return 'Not an Amount';\n  }\n\n  var result = false;\n\n  if (!this.is_valid() || !d.is_valid()) {\n    result = 'Invalid amount.';\n  } else if (this._is_native !== d._is_native) {\n    result = 'Native mismatch.';\n  } else {\n    var type = this._is_native ? 'XRP' : 'Non-XRP';\n\n    if (!this._value.equals(d._value) || this._offset !== d._offset) {\n      result = type + ' value differs.';\n    } else if (this._is_negative !== d._is_negative) {\n      result = type + ' sign differs.';\n    } else if (!this._is_native) {\n      if (!this._currency.equals(d._currency)) {\n        result = 'Non-XRP currency differs.';\n      } else if (!ignore_issuer && !this._issuer.equals(d._issuer)) {\n        result = 'Non-XRP issuer differs: ' + d._issuer.to_json() + '/' + this._issuer.to_json();\n      }\n    }\n  }\n\n  return result;\n};\n\nexports.Amount   = Amount;\n\n// DEPRECATED: Include the corresponding files instead.\nexports.Currency = Currency;\nexports.Seed     = Seed;\nexports.UInt160  = UInt160;\n\n// vim:sw=2:sts=2:ts=8:et\n\n\n// WEBPACK FOOTER\n// module.id = 3\n// module.readableIdentifier = ./src/js/ripple/amount.js\n//@ sourceURL=webpack-module:///./src/js/ripple/amount.js");

/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {

	eval("// Routines for working with an account.\n//\n// You should not instantiate this class yourself, instead use Remote#account.\n//\n// Events:\n//   wallet_clean :  True, iff the wallet has been updated.\n//   wallet_dirty :  True, iff the wallet needs to be updated.\n//   balance:        The current stamp balance.\n//   balance_proposed\n//\n\n// var network = require('./network.js');\nvar async              = __webpack_require__(50);\nvar util               = __webpack_require__(38);\nvar extend             = __webpack_require__(44);\nvar EventEmitter       = __webpack_require__(37).EventEmitter;\nvar Amount             = __webpack_require__(3).Amount;\nvar UInt160            = __webpack_require__(8).UInt160;\nvar TransactionManager = __webpack_require__(26).TransactionManager;\nvar sjcl               = __webpack_require__(19).sjcl;\nvar Base               = __webpack_require__(7).Base;\n\n/**\n * @constructor Account\n * @param {Remote} remote\n * @param {String} account\n */\n\nfunction Account(remote, account) {\n  EventEmitter.call(this);\n\n  var self = this;\n\n  this._remote = remote;\n  this._account = UInt160.from_json(account);\n  this._account_id = this._account.to_json();\n  this._subs = 0;\n\n  // Ledger entry object\n  // Important: This must never be overwritten, only extend()-ed\n  this._entry = { };\n\n  function listenerAdded(type, listener) {\n    if (~Account.subscribeEvents.indexOf(type)) {\n      if (!self._subs && self._remote._connected) {\n        self._remote.request_subscribe()\n        .add_account(self._account_id)\n        .broadcast();\n      }\n      self._subs += 1;\n    }\n  };\n\n  this.on('newListener', listenerAdded);\n\n  function listenerRemoved(type, listener) {\n    if (~Account.subscribeEvents.indexOf(type)) {\n      self._subs -= 1;\n      if (!self._subs && self._remote._connected) {\n        self._remote.request_unsubscribe()\n        .add_account(self._account_id)\n        .broadcast();\n      }\n    }\n  };\n\n  this.on('removeListener', listenerRemoved);\n\n  function attachAccount(request) {\n    if (self._account.is_valid() && self._subs) {\n      request.add_account(self._account_id);\n    }\n  };\n\n  this._remote.on('prepare_subscribe', attachAccount);\n\n  function handleTransaction(transaction) {\n    if (!transaction.mmeta) {\n      return;\n    }\n\n    var changed = false;\n\n    transaction.mmeta.each(function(an) {\n      var isAccount = an.fields.Account === self._account_id;\n      var isAccountRoot = isAccount && (an.entryType === 'AccountRoot');\n\n      if (isAccountRoot) {\n        extend(self._entry, an.fieldsNew, an.fieldsFinal);\n        changed = true;\n      }\n    });\n\n    if (changed) {\n      self.emit('entry', self._entry);\n    }\n  };\n\n  this.on('transaction', handleTransaction);\n\n  this._transactionManager = new TransactionManager(this);\n\n  return this;\n};\n\nutil.inherits(Account, EventEmitter);\n\n/**\n * List of events that require a remote subscription to the account.\n */\n\nAccount.subscribeEvents = [ 'transaction', 'entry' ];\n\nAccount.prototype.toJson = function() {\n  return this._account.to_json();\n};\n\n/**\n * Whether the AccountId is valid.\n *\n * Note: This does not tell you whether the account exists in the ledger.\n */\n\nAccount.prototype.isValid = function() {\n  return this._account.is_valid();\n};\n\n/**\n * Request account info\n *\n * @param {Function} callback\n */\n\nAccount.prototype.getInfo = function(callback) {\n  return this._remote.requestAccountInfo({account: this._account_id}, callback);\n};\n\n/**\n * Retrieve the current AccountRoot entry.\n *\n * To keep up-to-date with changes to the AccountRoot entry, subscribe to the\n * 'entry' event.\n *\n * @param {Function} callback\n */\n\nAccount.prototype.entry = function(callback) {\n  var self = this;\n  var callback = typeof callback === 'function' ? callback : function(){};\n\n  function accountInfo(err, info) {\n    if (err) {\n      callback(err);\n    } else {\n      extend(self._entry, info.account_data);\n      self.emit('entry', self._entry);\n      callback(null, info);\n    }\n  };\n\n  this.getInfo(accountInfo);\n\n  return this;\n};\n\nAccount.prototype.getNextSequence = function(callback) {\n  var callback = typeof callback === 'function' ? callback : function(){};\n\n  function isNotFound(err) {\n    return err && typeof err === 'object'\n    && typeof err.remote === 'object'\n    && err.remote.error === 'actNotFound';\n  };\n\n  function accountInfo(err, info) {\n    if (isNotFound(err)) {\n      // New accounts will start out as sequence one\n      callback(null, 1);\n    } else if (err) {\n      callback(err);\n    } else {\n      callback(null, info.account_data.Sequence);\n    }\n  };\n\n  this.getInfo(accountInfo);\n\n  return this;\n};\n\n/**\n * Retrieve this account's Ripple trust lines.\n *\n * To keep up-to-date with changes to the AccountRoot entry, subscribe to the\n * 'lines' event. (Not yet implemented.)\n *\n * @param {function(err, lines)} callback Called with the result\n */\n\nAccount.prototype.lines = function(callback) {\n  var self = this;\n  var callback = typeof callback === 'function' ? callback : function(){};\n\n  function accountLines(err, res) {\n    if (err) {\n      callback(err);\n    } else {\n      self._lines = res.lines;\n      self.emit('lines', self._lines);\n      callback(null, res);\n    }\n  }\n\n  this._remote.requestAccountLines({account: this._account_id}, accountLines);\n\n  return this;\n};\n\n/**\n * Retrieve this account's single trust line.\n *\n * @param {string} currency Currency\n * @param {string} address Ripple address\n * @param {function(err, line)} callback Called with the result\n * @returns {Account}\n */\n\nAccount.prototype.line = function(currency, address, callback) {\n  var self = this;\n  var callback = typeof callback === 'function' ? callback : function(){};\n\n  self.lines(function(err, data) {\n    if (err) {\n      return callback(err);\n    }\n\n    var line;\n\n    top:\n    for (var i=0; i<data.lines.length; i++) {\n      var l = data.lines[i];\n      if (l.account === address && l.currency === currency) {\n        line = l;\n        break top;\n      }\n    }\n\n    callback(null, line);\n  });\n\n  return this;\n};\n\n/**\n * Notify object of a relevant transaction.\n *\n * This is only meant to be called by the Remote class. You should never have to\n * call this yourself.\n *\n * @param {Object} message\n */\n\nAccount.prototype.notify =\nAccount.prototype.notifyTx = function(transaction) {\n  // Only trigger the event if the account object is actually\n  // subscribed - this prevents some weird phantom events from\n  // occurring.\n  if (!this._subs) {\n    return;\n  }\n\n  this.emit('transaction', transaction);\n\n  var account = transaction.transaction.Account;\n\n  if (!account) {\n    return;\n  }\n\n  var isThisAccount = (account === this._account_id);\n\n  this.emit(isThisAccount ? 'transaction-outbound' : 'transaction-inbound', transaction);\n};\n\n/**\n * Submit a transaction to an account's\n * transaction manager\n *\n * @param {Transaction} transaction\n */\n\nAccount.prototype.submit = function(transaction) {\n  this._transactionManager.submit(transaction);\n};\n\n\n/**\n *  Check whether the given public key is valid for this account\n *\n *  @param {Hex-encoded String|RippleAddress} public_key\n *  @param {Function} callback\n *\n *  @callback\n *  @param {Error} err\n *  @param {Boolean} true if the public key is valid and active, false otherwise\n */\nAccount.prototype.publicKeyIsActive = function(public_key, callback) {\n  var self = this;\n  var public_key_as_uint160;\n\n  try {\n    public_key_as_uint160 = Account._publicKeyToAddress(public_key);\n  } catch (err) {\n    return callback(err);\n  }\n\n  function getAccountInfo(async_callback) {\n    self.getInfo(function(err, account_info_res){\n\n      // If the remote responds with an Account Not Found error then the account\n      // is unfunded and thus we can assume that the master key is active\n      if (err && err.remote && err.remote.error === 'actNotFound') {\n        async_callback(null, null);\n      } else {\n        async_callback(err, account_info_res);\n      }\n    });\n  };\n\n  function publicKeyIsValid(account_info_res, async_callback) {\n    // Catch the case of unfunded accounts\n    if (!account_info_res) {\n\n      if (public_key_as_uint160 === self._account_id) {\n        async_callback(null, true);\n      } else {\n        async_callback(null, false);\n      }\n\n      return;\n    }\n\n    var account_info = account_info_res.account_data;\n\n    // Respond with true if the RegularKey is set and matches the given public key or\n    // if the public key matches the account address and the lsfDisableMaster is not set\n    if (account_info.RegularKey &&\n      account_info.RegularKey === public_key_as_uint160) {\n      async_callback(null, true);\n    } else if (account_info.Account === public_key_as_uint160 &&\n      ((account_info.Flags & 0x00100000) === 0)) {\n      async_callback(null, true);\n    } else {\n      async_callback(null, false);\n    }\n  };\n\n  var steps = [\n    getAccountInfo,\n    publicKeyIsValid\n  ];\n\n  async.waterfall(steps, callback);\n};\n\n/**\n *  Convert a hex-encoded public key to a Ripple Address\n *\n *  @static\n *\n *  @param {Hex-encoded string|RippleAddress} public_key\n *  @returns {RippleAddress}\n */\nAccount._publicKeyToAddress = function(public_key) {\n  // Based on functions in /src/js/ripple/keypair.js\n  function hexToUInt160(public_key) {\n    var bits = sjcl.codec.hex.toBits(public_key);\n    var hash = sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits));\n    var address = UInt160.from_bits(hash);\n    address.set_version(Base.VER_ACCOUNT_ID);\n\n    return address.to_json();\n  };\n\n  if (UInt160.is_valid(public_key)) {\n    return public_key;\n  } else if (/^[0-9a-fA-F]+$/.test(public_key)) {\n    return hexToUInt160(public_key);\n  } else {\n    throw new Error('Public key is invalid. Must be a UInt160 or a hex string');\n  }\n};\n\nexports.Account = Account;\n\n// vim:sw=2:sts=2:ts=8:et\n\n\n// WEBPACK FOOTER\n// module.id = 4\n// module.readableIdentifier = ./src/js/ripple/account.js\n//@ sourceURL=webpack-module:///./src/js/ripple/account.js");

/***/ },
/* 5 */
/***/ function(module, exports, __webpack_require__) {

	eval("// Transactions\n//\n//  Construction:\n//    remote.transaction()  // Build a transaction object.\n//     .offer_create(...)   // Set major parameters.\n//     .set_flags()         // Set optional parameters.\n//     .on()                // Register for events.\n//     .submit();           // Send to network.\n//\n//  Events:\n// 'success' : Transaction submitted without error.\n// 'error' : Error submitting transaction.\n// 'proposed' : Advisory proposed status transaction.\n// - A client should expect 0 to multiple results.\n// - Might not get back. The remote might just forward the transaction.\n// - A success could be reverted in final.\n// - local error: other remotes might like it.\n// - malformed error: local server thought it was malformed.\n// - The client should only trust this when talking to a trusted server.\n// 'final' : Final status of transaction.\n// - Only expect a final from dishonest servers after a tesSUCCESS or ter*.\n// 'lost' : Gave up looking for on ledger_closed.\n// 'pending' : Transaction was not found on ledger_closed.\n// 'state' : Follow the state of a transaction.\n//    'client_submitted'     - Sent to remote\n//     |- 'remoteError'      - Remote rejected transaction.\n//      \\- 'client_proposed' - Remote provisionally accepted transaction.\n//       |- 'client_missing' - Transaction has not appeared in ledger as expected.\n//       | |\\- 'client_lost' - No longer monitoring missing transaction.\n//       |/\n//       |- 'tesSUCCESS'     - Transaction in ledger as expected.\n//       |- 'ter...'         - Transaction failed.\n//       \\- 'tec...'         - Transaction claimed fee only.\n//\n// Notes:\n// - All transactions including those with local and malformed errors may be\n//   forwarded anyway.\n// - A malicous server can:\n//   - give any proposed result.\n//     - it may declare something correct as incorrect or something incorrect as correct.\n//     - it may not communicate with the rest of the network.\n//   - may or may not forward.\n//\n\nvar EventEmitter     = __webpack_require__(37).EventEmitter;\nvar util             = __webpack_require__(38);\nvar utils            = __webpack_require__(19);\nvar sjcl             = __webpack_require__(19).sjcl;\nvar Amount           = __webpack_require__(3).Amount;\nvar Currency         = __webpack_require__(3).Currency;\nvar UInt160          = __webpack_require__(3).UInt160;\nvar Seed             = __webpack_require__(10).Seed;\nvar SerializedObject = __webpack_require__(12).SerializedObject;\nvar RippleError      = __webpack_require__(13).RippleError;\nvar hashprefixes     = __webpack_require__(27);\nvar config           = __webpack_require__(22);\n\nfunction Transaction(remote) {\n  EventEmitter.call(this);\n\n  var self = this;\n\n  var remote = remote || void(0);\n\n  this.remote = remote;\n\n  // Transaction data\n  this.tx_json = { Flags: 0 };\n\n  this._secret = void(0);\n  this._build_path = false;\n  this._maxFee = (typeof remote === 'object') ? this.remote.max_fee : void(0);\n\n  this.state = 'unsubmitted';\n  this.finalized = false;\n  this.previousSigningHash = void(0);\n\n  // Index at which transaction was submitted\n  this.submitIndex = void(0);\n\n  // Canonical signing setting defaults to the Remote's configuration\n  this.canonical = (typeof remote === 'object') ? Boolean(remote.canonical_signing) : true;\n\n  // We aren't clever enough to eschew preventative measures so we keep an array\n  // of all submitted transactionIDs (which can change due to load_factor\n  // effecting the Fee amount). This should be populated with a transactionID\n  // any time it goes on the network\n  this.submittedIDs = [ ];\n\n  this.once('success', function(message) {\n    self.finalize(message);\n    self.setState('validated');\n    self.emit('cleanup', message);\n  });\n\n  this.once('error', function(message) {\n    self.finalize(message);\n    self.setState('failed');\n    self.emit('cleanup', message);\n  });\n\n  this.once('submitted', function() {\n    self.setState('submitted');\n  });\n\n  this.once('proposed', function() {\n    self.setState('pending');\n  });\n};\n\nutil.inherits(Transaction, EventEmitter);\n\n// XXX This needs to be determined from the network.\nTransaction.fee_units = {\n  default: 10\n};\n\nTransaction.flags = {\n  // Universal flags can apply to any transaction type\n  Universal: {\n    FullyCanonicalSig:  0x80000000\n  },\n\n  AccountSet: {\n    RequireDestTag:     0x00010000,\n    OptionalDestTag:    0x00020000,\n    RequireAuth:        0x00040000,\n    OptionalAuth:       0x00080000,\n    DisallowXRP:        0x00100000,\n    AllowXRP:           0x00200000\n  },\n\n  TrustSet: {\n    SetAuth:            0x00010000,\n    NoRipple:           0x00020000,\n    SetNoRipple:        0x00020000,\n    ClearNoRipple:      0x00040000,\n    SetFreeze:          0x00100000,\n    ClearFreeze:        0x00200000\n  },\n\n  OfferCreate: {\n    Passive:            0x00010000,\n    ImmediateOrCancel:  0x00020000,\n    FillOrKill:         0x00040000,\n    Sell:               0x00080000\n  },\n\n  Payment: {\n    NoRippleDirect:     0x00010000,\n    PartialPayment:     0x00020000,\n    LimitQuality:       0x00040000\n  }\n};\n\n// The following are integer (as opposed to bit) flags\n// that can be set for particular transactions in the\n// SetFlag or ClearFlag field\nTransaction.set_clear_flags = {\n  AccountSet: {\n    asfRequireDest:    1,\n    asfRequireAuth:    2,\n    asfDisallowXRP:    3,\n    asfDisableMaster:  4,\n    asfNoFreeze:       6,\n    asfGlobalFreeze:   7\n  }\n};\n\nTransaction.MEMO_TYPES = {\n};\n\nTransaction.formats = __webpack_require__(18).tx;\n\nTransaction.prototype.consts = {\n  telLOCAL_ERROR:  -399,\n  temMALFORMED:    -299,\n  tefFAILURE:      -199,\n  terRETRY:        -99,\n  tesSUCCESS:      0,\n  tecCLAIMED:      100\n};\n\nTransaction.from_json = function(j) {\n  return (new Transaction()).parseJson(j);\n};\n\nTransaction.prototype.parseJson = function(v) {\n  this.tx_json = v;\n  return this;\n};\n\nTransaction.prototype.isTelLocal = function(ter) {\n  return ter >= this.consts.telLOCAL_ERROR && ter < this.consts.temMALFORMED;\n};\n\nTransaction.prototype.isTemMalformed = function(ter) {\n  return ter >= this.consts.temMALFORMED && ter < this.consts.tefFAILURE;\n};\n\nTransaction.prototype.isTefFailure = function(ter) {\n  return ter >= this.consts.tefFAILURE && ter < this.consts.terRETRY;\n};\n\nTransaction.prototype.isTerRetry = function(ter) {\n  return ter >= this.consts.terRETRY && ter < this.consts.tesSUCCESS;\n};\n\nTransaction.prototype.isTepSuccess = function(ter) {\n  return ter >= this.consts.tesSUCCESS;\n};\n\nTransaction.prototype.isTecClaimed = function(ter) {\n  return ter >= this.consts.tecCLAIMED;\n};\n\nTransaction.prototype.isRejected = function(ter) {\n  return this.isTelLocal(ter) || this.isTemMalformed(ter) || this.isTefFailure(ter);\n};\n\nTransaction.prototype.setState = function(state) {\n  if (this.state !== state) {\n    this.state = state;\n    this.emit('state', state);\n    this.emit('save');\n  }\n};\n\nTransaction.prototype.finalize = function(message) {\n  this.finalized = true;\n\n  if (this.result) {\n    this.result.ledger_index = message.ledger_index;\n    this.result.ledger_hash  = message.ledger_hash;\n  } else {\n    this.result = message;\n    this.result.tx_json = this.tx_json;\n  }\n\n  return this;\n};\n\nTransaction.prototype._accountSecret = function(account) {\n  return this.remote ? this.remote.secrets[account] : void(0);\n};\n\n/**\n * Returns the number of fee units this transaction will cost.\n *\n * Each Ripple transaction based on its type and makeup costs a certain number\n * of fee units. The fee units are calculated on a per-server basis based on the\n * current load on both the network and the server.\n *\n * @see https://ripple.com/wiki/Transaction_Fee\n *\n * @return {Number} Number of fee units for this transaction.\n */\n\nTransaction.prototype._getFeeUnits =\nTransaction.prototype.feeUnits = function() {\n  return Transaction.fee_units['default'];\n};\n\n/**\n * Compute median server fee\n */\n\nTransaction.prototype._computeFee = function() {\n  if (!this.remote) {\n    return void(0);\n  }\n\n  var servers = this.remote._servers;\n  var fees = [ ];\n\n  for (var i=0; i<servers.length; i++) {\n    var server = servers[i];\n    if (server._connected) {\n      fees.push(Number(server._computeFee(this._getFeeUnits())));\n    }\n  }\n\n  switch (fees.length) {\n    case 0: return;\n    case 1: return String(fees[0]);\n  }\n\n  fees.sort(function ascending(a, b) {\n    if (a > b) {\n      return 1;\n    } else if (a < b) {\n      return -1;\n    } else {\n      return 0;\n    }\n  });\n\n  var midInd = Math.floor(fees.length / 2);\n\n  var median = fees.length % 2 === 0\n  ? Math.floor(0.5 + (fees[midInd] + fees[midInd - 1]) / 2)\n  : fees[midInd];\n\n  return String(median);\n};\n\n/**\n * Attempts to complete the transaction for submission.\n *\n * This function seeks to fill out certain fields, such as Fee and\n * SigningPubKey, which can be determined by the library based on network\n * information and other fields.\n */\n\nTransaction.prototype.complete = function() {\n  if (this.remote) {\n    if (!this.remote.trusted && !this.remote.local_signing) {\n      this.emit('error', new RippleError('tejServerUntrusted', 'Attempt to give secret to untrusted server'));\n      return false;\n    }\n  }\n\n  // Try to auto-fill the secret\n  if (!this._secret && !(this._secret = this._accountSecret(this.tx_json.Account))) {\n    this.emit('error', new RippleError('tejSecretUnknown', 'Missing secret'));\n    return false;\n  }\n\n  if (typeof this.tx_json.SigningPubKey === 'undefined') {\n    try {\n      var seed = Seed.from_json(this._secret);\n      var key  = seed.get_key(this.tx_json.Account);\n      this.tx_json.SigningPubKey = key.to_hex_pub();\n    } catch(e) {\n      this.emit('error', new RippleError('tejSecretInvalid', 'Invalid secret'));\n      return false;\n    }\n  }\n\n  // If the Fee hasn't been set, one needs to be computed by\n  // an assigned server\n  if (this.remote && typeof this.tx_json.Fee === 'undefined') {\n    if (this.remote.local_fee || !this.remote.trusted) {\n      if (!(this.tx_json.Fee = this._computeFee())) {\n        this.emit('error', new RippleError('tejUnconnected'));\n        return;\n      }\n    }\n  }\n\n  if (Number(this.tx_json.Fee) > this._maxFee) {\n    this.emit('error', new RippleError('tejMaxFeeExceeded', 'Max fee exceeded'));\n    return false;\n  }\n\n  // Set canonical flag - this enables canonicalized signature checking\n  if (this.remote && this.remote.local_signing && this.canonical) {\n    this.tx_json.Flags |= Transaction.flags.Universal.FullyCanonicalSig;\n\n    // JavaScript converts operands to 32-bit signed ints before doing bitwise\n    // operations. We need to convert it back to an unsigned int.\n    this.tx_json.Flags = this.tx_json.Flags >>> 0;\n  }\n\n  return this.tx_json;\n};\n\nTransaction.prototype.serialize = function() {\n  return SerializedObject.from_json(this.tx_json);\n};\n\nTransaction.prototype.signingHash = function() {\n  return this.hash(config.testnet ? 'HASH_TX_SIGN_TESTNET' : 'HASH_TX_SIGN');\n};\n\nTransaction.prototype.hash = function(prefix, as_uint256) {\n  if (typeof prefix === 'string') {\n    if (typeof hashprefixes[prefix] === 'undefined') {\n      throw new Error('Unknown hashing prefix requested.');\n    }\n    prefix = hashprefixes[prefix];\n  } else if (!prefix) {\n    prefix = hashprefixes.HASH_TX_ID;\n  }\n\n  var hash = SerializedObject.from_json(this.tx_json).hash(prefix);\n\n  return as_uint256 ? hash : hash.to_hex();\n};\n\nTransaction.prototype.sign = function(callback) {\n  var callback = typeof callback === 'function' ? callback : function(){};\n  var seed = Seed.from_json(this._secret);\n\n  var prev_sig = this.tx_json.TxnSignature;\n  delete this.tx_json.TxnSignature;\n\n  var hash = this.signingHash();\n\n  // If the hash is the same, we can re-use the previous signature\n  if (prev_sig && hash === this.previousSigningHash) {\n    this.tx_json.TxnSignature = prev_sig;\n    callback();\n    return this;\n  }\n\n  var key = seed.get_key(this.tx_json.Account);\n  var sig = key.sign(hash, 0);\n  var hex = sjcl.codec.hex.fromBits(sig).toUpperCase();\n\n  this.tx_json.TxnSignature = hex;\n  this.previousSigningHash = hash;\n\n  callback();\n\n  return this;\n};\n\n/**\n * Add a ID to list of submitted IDs for this transaction\n */\n\nTransaction.prototype.addId = function(hash) {\n  if (this.submittedIDs.indexOf(hash) === -1) {\n    this.submittedIDs.unshift(hash);\n    this.emit('signed', hash);\n    this.emit('save');\n  }\n};\n\n/**\n * Find ID within list of submitted IDs for this transaction\n */\n\nTransaction.prototype.findId = function(cache) {\n  var result;\n\n  for (var i=0; i<this.submittedIDs.length; i++) {\n    var hash = this.submittedIDs[i];\n    if ((result = cache[hash])) {\n      break;\n    }\n  }\n\n  return result;\n};\n\n//\n// Set options for Transactions\n//\n\n// --> build: true, to have server blindly construct a path.\n//\n// \"blindly\" because the sender has no idea of the actual cost except that is must be less than send max.\nTransaction.prototype.buildPath = function(build) {\n  this._build_path = build;\n  return this;\n};\n\n// tag should be undefined or a 32 bit integer.\n// YYY Add range checking for tag.\nTransaction.prototype.destinationTag = function(tag) {\n  if (tag !== void(0)) {\n    this.tx_json.DestinationTag = tag;\n  }\n  return this;\n};\n\nTransaction.prototype.invoiceID = function(id) {\n  if (typeof id === 'string') {\n    while (id.length < 64) {\n      id += '0';\n    }\n    this.tx_json.InvoiceID = id;\n  }\n  return this;\n};\n\nTransaction.prototype.clientID = function(id) {\n  if (typeof id === 'string') {\n    this._clientID = id;\n  }\n  return this;\n};\n\nTransaction.prototype.lastLedger = function(sequence) {\n  if (typeof sequence === 'number' && isFinite(sequence)) {\n    this._setLastLedger = true;\n    this.tx_json.LastLedgerSequence = sequence;\n  }\n  return this;\n};\n\n/*\n * Set the transaction's proposed fee. No op when fee parameter\n * is not 0 or a positive number\n *\n * @param {Number} fee The proposed fee\n *\n * @returns {Transaction} calling instance for chaining\n */\nTransaction.prototype.maxFee = function(fee) {\n  if (typeof fee === 'number' && fee >= 0) {\n    this._setMaxFee = true;\n    this._maxFee = fee;\n  }\n\n  return this;\n};\n\nTransaction._pathRewrite = function(path) {\n  if (!Array.isArray(path)) {\n    return;\n  }\n\n  var newPath = path.map(function(node) {\n    var newNode = { };\n\n    if (node.hasOwnProperty('account')) {\n      newNode.account = UInt160.json_rewrite(node.account);\n    }\n\n    if (node.hasOwnProperty('issuer')) {\n      newNode.issuer = UInt160.json_rewrite(node.issuer);\n    }\n\n    if (node.hasOwnProperty('currency')) {\n      newNode.currency = Currency.json_rewrite(node.currency);\n    }\n\n    if (node.hasOwnProperty('type_hex')) {\n      newNode.type_hex = node.type_hex;\n    }\n\n    return newNode;\n  });\n\n  return newPath;\n};\n\nTransaction.prototype.pathAdd = function(path) {\n  if (Array.isArray(path)) {\n    this.tx_json.Paths  = this.tx_json.Paths || [];\n    this.tx_json.Paths.push(Transaction._pathRewrite(path));\n  }\n  return this;\n};\n\n// --> paths: undefined or array of path\n// // A path is an array of objects containing some combination of: account, currency, issuer\n\nTransaction.prototype.paths = function(paths) {\n  if (Array.isArray(paths)) {\n    for (var i=0, l=paths.length; i<l; i++) {\n      this.pathAdd(paths[i]);\n    }\n  }\n  return this;\n};\n\n// If the secret is in the config object, it does not need to be provided.\nTransaction.prototype.secret = function(secret) {\n  this._secret = secret;\n  return this;\n};\n\nTransaction.prototype.sendMax = function(send_max) {\n  if (send_max) {\n    this.tx_json.SendMax = Amount.json_rewrite(send_max);\n  }\n  return this;\n};\n\n// tag should be undefined or a 32 bit integer.\n// YYY Add range checking for tag.\nTransaction.prototype.sourceTag = function(tag) {\n  if (tag) {\n    this.tx_json.SourceTag = tag;\n  }\n  return this;\n};\n\n// --> rate: In billionths.\nTransaction.prototype.transferRate = function(rate) {\n  this.tx_json.TransferRate = Number(rate);\n\n  if (this.tx_json.TransferRate < 1e9) {\n    throw new Error('invalidTransferRate');\n  }\n\n  return this;\n};\n\n// Add flags to a transaction.\n// --> flags: undefined, _flag_, or [ _flags_ ]\nTransaction.prototype.setFlags = function(flags) {\n  if (flags === void(0)) {\n    return this;\n  }\n\n  if (typeof flags === 'number') {\n    this.tx_json.Flags = flags;\n    return this;\n  }\n\n  var flag_set = Array.isArray(flags) ? flags : Array.prototype.slice.call(arguments);\n  var transaction_flags = Transaction.flags[this.tx_json.TransactionType] || { };\n\n  for (var i=0, l=flag_set.length; i<l; i++) {\n    var flag = flag_set[i];\n\n    if (transaction_flags.hasOwnProperty(flag)) {\n      this.tx_json.Flags += transaction_flags[flag];\n    } else {\n      return this.emit('error', new RippleError('tejInvalidFlag'));\n    }\n  }\n\n  return this;\n};\n\n/**\n * Add a Memo to transaction. Memos can be used as key-value,\n * using the MemoType as a key\n *\n * @param {String} type\n * @param {String} data\n */\n\nTransaction.prototype.addMemo = function(type, data) {\n  if (!/(undefined|string)/.test(typeof type)) {\n    throw new Error('MemoType must be a string');\n  }\n\n  if (!/(undefined|string)/.test(typeof data)) {\n    throw new Error('MemoData must be a string');\n  }\n\n  function toHex(str) {\n    return sjcl.codec.hex.fromBits(sjcl.codec.utf8String.toBits(str));\n  };\n\n  var memo = { };\n\n  if (type) {\n    if (Transaction.MEMO_TYPES[type]) {\n      //XXX Maybe in the future we want a schema validator for\n      //memo types\n      memo.MemoType = Transaction.MEMO_TYPES[type];\n    } else {\n      memo.MemoType = toHex(type);\n    }\n  }\n\n  if (data) {\n    memo.MemoData = toHex(data);\n  }\n\n  this.tx_json.Memos = (this.tx_json.Memos || []).concat({ Memo: memo });\n\n  return this;\n};\n\n// Options:\n//  .domain()           NYI\n//  .flags()\n//  .message_key()      NYI\n//  .transfer_rate()\n//  .wallet_locator()   NYI\n//  .wallet_size()      NYI\n\n/**\n *  Construct an 'AccountSet' transaction.\n *\n *  Note that bit flags can be set using the .setFlags() method\n *  but for 'AccountSet' transactions there is an additional way to\n *  modify AccountRoot flags. The values available for the SetFlag \n *  and ClearFlag are as follows:\n *\n *  \"asfRequireDest\"\n *    Require a destination tag\n *  \"asfRequireAuth\"\n *    Authorization is required to extend trust\n *  \"asfDisallowXRP\"\n *    XRP should not be sent to this account\n *  \"asfDisableMaster\"\n *    Disallow use of the master key\n */\n\nTransaction.prototype.accountSet = function(src, set_flag, clear_flag) {\n  if (typeof src === 'object') {\n    var options = src;\n    src = options.source || options.from || options.account;\n    set_flag = options.set_flag || options.set;\n    clear_flag = options.clear_flag || options.clear;\n  }\n\n  if (!UInt160.is_valid(src)) {\n    throw new Error('Source address invalid');\n  }\n\n  this.tx_json.TransactionType  = 'AccountSet';\n  this.tx_json.Account          = UInt160.json_rewrite(src);\n\n  var SetClearFlags = Transaction.set_clear_flags.AccountSet;\n\n  function prepareFlag(flag) {\n    return (typeof flag === 'number') ? flag : (SetClearFlags[flag] || SetClearFlags['asf' + flag]);\n  };\n\n  if (set_flag && (set_flag = prepareFlag(set_flag))) {\n    this.tx_json.SetFlag = set_flag;\n  }\n\n  if (clear_flag && (clear_flag = prepareFlag(clear_flag))) {\n    this.tx_json.ClearFlag = clear_flag;\n  }\n\n  return this;\n};\n\nTransaction.prototype.claim = function(src, generator, public_key, signature) {\n  if (typeof src === 'object') {\n    var options = src;\n    signature  = options.signature;\n    public_key = options.public_key;\n    generator  = options.generator;\n    src        = options.source || options.from || options.account;\n  }\n\n  this.tx_json.TransactionType = 'Claim';\n  this.tx_json.Generator       = generator;\n  this.tx_json.PublicKey       = public_key;\n  this.tx_json.Signature       = signature;\n\n  return this;\n};\n\nTransaction.prototype.offerCancel = function(src, sequence) {\n  if (typeof src === 'object') {\n    var options = src;\n    sequence = options.sequence;\n    src      = options.source || options.from || options.account;\n  }\n\n  if (!UInt160.is_valid(src)) {\n    throw new Error('Source address invalid');\n  }\n\n  this.tx_json.TransactionType = 'OfferCancel';\n  this.tx_json.Account         = UInt160.json_rewrite(src);\n  this.tx_json.OfferSequence   = Number(sequence);\n\n  return this;\n};\n\n// Options:\n//  .set_flags()\n// --> expiration : if not undefined, Date or Number\n// --> cancel_sequence : if not undefined, Sequence\nTransaction.prototype.offerCreate = function(src, taker_pays, taker_gets, expiration, cancel_sequence) {\n  if (typeof src === 'object') {\n    var options = src;\n    cancel_sequence = options.cancel_sequence;\n    expiration      = options.expiration;\n    taker_gets      = options.taker_gets || options.sell;\n    taker_pays      = options.taker_pays || options.buy;\n    src             = options.source || options.from || options.account;\n  }\n\n  if (!UInt160.is_valid(src)) {\n    throw new Error('Source address invalid');\n  }\n\n  this.tx_json.TransactionType = 'OfferCreate';\n  this.tx_json.Account         = UInt160.json_rewrite(src);\n  this.tx_json.TakerPays       = Amount.json_rewrite(taker_pays);\n  this.tx_json.TakerGets       = Amount.json_rewrite(taker_gets);\n\n  if (expiration) {\n    this.tx_json.Expiration = utils.time.toRipple(expiration);\n  }\n\n  if (cancel_sequence) {\n    this.tx_json.OfferSequence = Number(cancel_sequence);\n  }\n\n  return this;\n};\n\n/**\n *  Construct a 'SetRegularKey' transaction.\n *  If the RegularKey is set, the private key that corresponds to\n *  it can be used to sign transactions instead of the master key\n *\n *  The RegularKey must be a valid Ripple Address, or a Hash160 of\n *  the public key corresponding to the new private signing key.\n */\n\nTransaction.prototype.setRegularKey = function(src, regular_key) {\n  if (typeof src === 'object') {\n    var options = src;\n    src = options.address || options.account || options.from;\n    regular_key = options.regular_key;\n  }\n\n  if (!UInt160.is_valid(src)) {\n    throw new Error('Source address invalid');\n  }\n\n  if (!UInt160.is_valid(regular_key)) {\n    throw new Error('RegularKey must be a valid Ripple Address (a Hash160 of the public key)');\n  }\n\n  this.tx_json.TransactionType = 'SetRegularKey';\n  this.tx_json.Account = UInt160.json_rewrite(src);\n  this.tx_json.RegularKey = UInt160.json_rewrite(regular_key);\n\n  return this;\n};\n\n// Construct a 'payment' transaction.\n//\n// When a transaction is submitted:\n// - If the connection is reliable and the server is not merely forwarding and is not malicious,\n// --> src : UInt160 or String\n// --> dst : UInt160 or String\n// --> deliver_amount : Amount or String.\n//\n// Options:\n//  .paths()\n//  .build_path()\n//  .destination_tag()\n//  .path_add()\n//  .secret()\n//  .send_max()\n//  .set_flags()\n//  .source_tag()\nTransaction.prototype.payment = function(src, dst, amount) {\n  if (typeof src === 'object') {\n    var options = src;\n    amount = options.amount;\n    dst    = options.destination || options.to;\n    src    = options.source || options.from || options.account;\n  }\n\n  if (!UInt160.is_valid(src)) {\n    throw new Error('Payment source address invalid');\n  }\n\n  if (!UInt160.is_valid(dst)) {\n    throw new Error('Payment destination address invalid');\n  }\n\n  this.tx_json.TransactionType = 'Payment';\n  this.tx_json.Account         = UInt160.json_rewrite(src);\n  this.tx_json.Amount          = Amount.json_rewrite(amount);\n  this.tx_json.Destination     = UInt160.json_rewrite(dst);\n\n  return this;\n};\n\nTransaction.prototype.trustSet =\nTransaction.prototype.rippleLineSet = function(src, limit, quality_in, quality_out) {\n  if (typeof src === 'object') {\n    var options = src;\n    quality_out = options.quality_out;\n    quality_in  = options.quality_in;\n    limit       = options.limit;\n    src         = options.source || options.from || options.account;\n  }\n\n  if (!UInt160.is_valid(src)) {\n    throw new Error('Source address invalid');\n  }\n\n  this.tx_json.TransactionType = 'TrustSet';\n  this.tx_json.Account         = UInt160.json_rewrite(src);\n\n  if (limit !== void(0)) {\n    this.tx_json.LimitAmount = Amount.json_rewrite(limit);\n  }\n\n  if (quality_in) {\n    this.tx_json.QualityIn = quality_in;\n  }\n\n  if (quality_out) {\n    this.tx_json.QualityOut = quality_out;\n  }\n\n  // XXX Throw an error if nothing is set.\n\n  return this;\n};\n\n// Submit a transaction to the network.\nTransaction.prototype.submit = function(callback) {\n  var self = this;\n\n  this.callback = (typeof callback === 'function') ? callback : function(){};\n\n  function transactionError(error, message) {\n    if (!(error instanceof RippleError)) {\n      error = new RippleError(error, message);\n    }\n    self.callback(error);\n  };\n\n  this._errorHandler = transactionError;\n\n  function transactionSuccess(message) {\n    self.callback(null, message);\n  };\n\n  this._successHandler = transactionSuccess;\n\n  this.on('error', function(){});\n\n  var account = this.tx_json.Account;\n\n  if (!this.remote) {\n    return this.emit('error', new Error('No remote found'));\n  }\n\n  if (!UInt160.is_valid(account)) {\n    return this.emit('error', new RippleError('tejInvalidAccount', 'Account is missing or invalid'));\n  }\n\n  // YYY Might check paths for invalid accounts.\n  this.remote.account(account).submit(this);\n\n  return this;\n};\n\nTransaction.prototype.abort = function(callback) {\n  var callback = (typeof callback === 'function') ? callback : function(){};\n  if (!this.finalized) {\n    this.once('final', callback);\n    this.emit('abort');\n  }\n};\n\nTransaction.prototype.summary = function() {\n  return Transaction.summary.call(this);\n};\n\nTransaction.summary = function() {\n  var result = {\n    tx_json:             this.tx_json,\n    clientID:            this._clientID,\n    submittedIDs:        this.submittedIDs,\n    submissionAttempts:  this.attempts,\n    submitIndex:         this.submitIndex,\n    initialSubmitIndex:  this.initialSubmitIndex,\n    lastLedgerSequence:  this.lastLedgerSequence,\n    state:               this.state,\n    server:              this._server ? this._server._opts.url : void(0),\n    finalized:           this.finalized\n  };\n\n  if (this.result) {\n    result.result = {\n      engine_result        : this.result.engine_result,\n      engine_result_message: this.result.engine_result_message,\n      ledger_hash          : this.result.ledger_hash,\n      ledger_index         : this.result.ledger_index,\n      transaction_hash     : this.result.tx_json.hash\n    };\n  }\n\n  return result;\n};\n\nexports.Transaction = Transaction;\n\n// vim:sw=2:sts=2:ts=8:et\n\n\n// WEBPACK FOOTER\n// module.id = 5\n// module.readableIdentifier = ./src/js/ripple/transaction.js\n//@ sourceURL=webpack-module:///./src/js/ripple/transaction.js");

/***/ },
/* 6 */
/***/ function(module, exports, __webpack_require__) {

	eval("var extend    = __webpack_require__(44);\nvar UInt160 = __webpack_require__(8).UInt160;\nvar utils = __webpack_require__(19);\nvar Float = __webpack_require__(28).Float;\n\n//\n// Currency support\n//\n\nvar Currency = extend(function() {\n  // Internal form: 0 = XRP. 3 letter-code.\n  // XXX Internal should be 0 or hex with three letter annotation when valid.\n\n  // Json form:\n  //  '', 'XRP', '0': 0\n  //  3-letter code: ...\n  // XXX Should support hex, C++ doesn't currently allow it.\n\n  this._value  = NaN;\n\n  this._update();\n}, UInt160);\n\nCurrency.prototype = extend({}, UInt160.prototype);\nCurrency.prototype.constructor = Currency;\n\nCurrency.HEX_CURRENCY_BAD = '0000000000000000000000005852500000000000';\n\n/**\n * Tries to correctly interpret a Currency as entered by a user.\n *\n * Examples:\n *\n *  USD                               => currency\n *  USD - Dollar                      => currency with optional full currency name\n *  XAU (-0.5%pa)                     => XAU with 0.5% effective demurrage rate per year\n *  XAU - Gold (-0.5%pa)              => Optionally allowed full currency name\n *  USD (1%pa)                        => US dollars with 1% effective interest per year\n *  INR - Indian Rupees               => Optional full currency name with spaces\n *  TYX - 30-Year Treasuries          => Optional full currency with numbers and a dash\n *  TYX - 30-Year Treasuries (1.5%pa) => Optional full currency with numbers, dash and interest rate\n *\n *  The regular expression below matches above cases, broken down for better understanding:\n *\n *  ^\\s*                      // start with any amount of whitespace\n *  ([a-zA-Z]{3}|[0-9]{3})    // either 3 letter alphabetic currency-code or 3 digit numeric currency-code. See ISO 4217\n *  (\\s*-\\s*[- \\w]+)          // optional full currency name following the dash after currency code,\n *                               full currency code can contain letters, numbers and dashes\n *  (\\s*\\(-?\\d+\\.?\\d*%pa\\))?  // optional demurrage rate, has optional - and . notation (-0.5%pa)\n *  \\s*$                      // end with any amount of whitespace\n *\n */\nCurrency.prototype.human_RE = /^\\s*([a-zA-Z0-9]{3})(\\s*-\\s*[- \\w]+)?(\\s*\\(-?\\d+\\.?\\d*%pa\\))?\\s*$/;\n\nCurrency.from_json = function(j, shouldInterpretXrpAsIou) {\n    return (new Currency()).parse_json(j, shouldInterpretXrpAsIou);\n};\n\nCurrency.from_human = function(j, opts) {\n  return (new Currency().parse_human(j, opts));\n}\n\n// this._value = NaN on error.\nCurrency.prototype.parse_json = function(j, shouldInterpretXrpAsIou) {\n  this._value = NaN;\n\n  switch (typeof j) {\n    case 'string':\n\n      // if an empty string is given, fall back to XRP\n      if (!j || j === '0') {\n        this.parse_hex(shouldInterpretXrpAsIou ? Currency.HEX_CURRENCY_BAD : Currency.HEX_ZERO);\n        break;\n      }\n\n      // match the given string to see if it's in an allowed format\n      var matches = String(j).match(this.human_RE);\n\n      if (matches) {\n\n        var currencyCode = matches[1];\n\n        // for the currency 'XRP' case\n        // we drop everything else that could have been provided\n        // e.g. 'XRP - Ripple'\n        if (!currencyCode || /^(0|XRP)$/.test(currencyCode)) {\n          this.parse_hex(shouldInterpretXrpAsIou ? Currency.HEX_CURRENCY_BAD : Currency.HEX_ZERO);\n\n          // early break, we can't have interest on XRP\n          break;\n        }\n\n        // the full currency is matched as it is part of the valid currency format, but not stored\n        // var full_currency = matches[2] || '';\n        var interest = matches[3] || '';\n\n        // interest is defined as interest per year, per annum (pa)\n        var percentage = interest.match(/(-?\\d+\\.?\\d+)/);\n\n        currencyCode = currencyCode.toUpperCase();\n\n        var currencyData = utils.arraySet(20, 0);\n\n        if (percentage) {\n          /*\n           * 20 byte layout of a interest bearing currency\n           *\n           * 01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __\n           *    CURCODE- DATE------- RATE------------------- RESERVED---\n           */\n\n          // byte 1 for type, use '1' to denote demurrage currency\n          currencyData[0] = 1;\n\n          // byte 2-4 for currency code\n          currencyData[1] = currencyCode.charCodeAt(0) & 0xff;\n          currencyData[2] = currencyCode.charCodeAt(1) & 0xff;\n          currencyData[3] = currencyCode.charCodeAt(2) & 0xff;\n\n          // byte 5-8 are for reference date, but should always be 0 so we won't fill it\n\n          // byte 9-16 are for the interest\n          percentage = parseFloat(percentage[0]);\n\n          // the interest or demurrage is expressed as a yearly (per annum) value\n          var secondsPerYear = 31536000; // 60 * 60 * 24 * 365\n\n          // Calculating the interest e-fold\n          // 0.5% demurrage is expressed 0.995, 0.005 less than 1\n          // 0.5% interest is expressed as 1.005, 0.005 more than 1\n          var interestEfold = secondsPerYear / Math.log(1 + percentage/100);\n          var bytes = Float.toIEEE754Double(interestEfold);\n\n          for (var i=0; i<=bytes.length; i++) {\n            currencyData[8 + i] = bytes[i] & 0xff;\n          }\n\n          // the last 4 bytes are reserved for future use, so we won't fill those\n\n        } else {\n          currencyData[12] = currencyCode.charCodeAt(0) & 0xff;\n          currencyData[13] = currencyCode.charCodeAt(1) & 0xff;\n          currencyData[14] = currencyCode.charCodeAt(2) & 0xff;\n        }\n\n        this.parse_bytes(currencyData);\n      } else {\n        this.parse_hex(j);\n      }\n      break;\n\n    case 'number':\n      if (!isNaN(j)) {\n        this.parse_number(j);\n      }\n      break;\n\n    case 'object':\n      if (j instanceof Currency) {\n        this._value = j.copyTo({})._value;\n        this._update();\n      }\n      break;\n  }\n\n  return this;\n};\n\n\nCurrency.prototype.parse_human = function(j) {\n  return this.parse_json(j);\n};\n\n/**\n * Recalculate internal representation.\n *\n * You should never need to call this.\n */\nCurrency.prototype._update = function() {\n  var bytes = this.to_bytes();\n\n  // is it 0 everywhere except 12, 13, 14?\n  var isZeroExceptInStandardPositions = true;\n\n  if (!bytes) {\n    return 'XRP';\n  }\n\n  this._native = false;\n  this._type = -1;\n  this._interest_start = NaN;\n  this._interest_period = NaN;\n  this._iso_code = '';\n\n  for (var i=0; i<20; i++) {\n    isZeroExceptInStandardPositions = isZeroExceptInStandardPositions && (i===12 || i===13 || i===14 || bytes[i]===0);\n  }\n\n  if (isZeroExceptInStandardPositions) {\n    this._iso_code = String.fromCharCode(bytes[12])\n                   + String.fromCharCode(bytes[13])\n                   + String.fromCharCode(bytes[14]);\n\n    if (this._iso_code === '\\0\\0\\0') {\n      this._native = true;\n      this._iso_code = 'XRP';\n    }\n\n    this._type = 0;\n  } else if (bytes[0] === 0x01) { // Demurrage currency\n    this._iso_code = String.fromCharCode(bytes[1])\n                   + String.fromCharCode(bytes[2])\n                   + String.fromCharCode(bytes[3]);\n\n    this._type = 1;\n    this._interest_start = (bytes[4] << 24) +\n                           (bytes[5] << 16) +\n                           (bytes[6] <<  8) +\n                           (bytes[7]      );\n    this._interest_period = Float.fromIEEE754Double(bytes.slice(8, 16));\n  }\n};\n\n// XXX Probably not needed anymore?\n/*\nCurrency.prototype.parse_bytes = function(byte_array) {\n  if (Array.isArray(byte_array) && byte_array.length === 20) {\n    var result;\n    // is it 0 everywhere except 12, 13, 14?\n    var isZeroExceptInStandardPositions = true;\n\n    for (var i=0; i<20; i++) {\n      isZeroExceptInStandardPositions = isZeroExceptInStandardPositions && (i===12 || i===13 || i===14 || byte_array[0]===0)\n    }\n\n    if (isZeroExceptInStandardPositions) {\n      var currencyCode = String.fromCharCode(byte_array[12])\n      + String.fromCharCode(byte_array[13])\n      + String.fromCharCode(byte_array[14]);\n      if (/^[A-Z0-9]{3}$/.test(currencyCode) && currencyCode !== 'XRP' ) {\n        this._value = currencyCode;\n      } else if (currencyCode === '\\0\\0\\0') {\n        this._value = 0;\n      } else {\n        this._value = NaN;\n      }\n    } else {\n      // XXX Should support non-standard currency codes\n      this._value = NaN;\n    }\n  } else {\n    this._value = NaN;\n  }\n  return this;\n};\n*/\n\nCurrency.prototype.is_native = function() {\n  return this._native;\n};\n\n/**\n * Whether this currency is an interest-bearing/demurring currency.\n */\nCurrency.prototype.has_interest = function() {\n  return this._type === 1 && !isNaN(this._interest_start) && !isNaN(this._interest_period);\n};\n\n/**\n *\n * @param referenceDate - number of seconds since the Ripple Epoch (0:00 on January 1, 2000 UTC)\n *                        used to calculate the interest over provided interval\n *                        pass in one years worth of seconds to ge the yearly interest\n * @returns {number} - interest for provided interval, can be negative for demurred currencies\n */\nCurrency.prototype.get_interest_at = function(referenceDate, decimals) {\n  if (!this.has_interest()) {\n    return 0;\n  }\n\n  // use one year as a default period\n  if (!referenceDate) {\n    referenceDate = this._interest_start + 3600 * 24 * 365;\n  }\n\n  if (referenceDate instanceof Date) {\n    referenceDate = utils.fromTimestamp(referenceDate.getTime());\n  }\n\n  // calculate interest by e-fold number\n  return Math.exp((referenceDate - this._interest_start) / this._interest_period);\n};\n\nCurrency.prototype.get_interest_percentage_at = function(referenceDate, decimals) {\n  var interest = this.get_interest_at(referenceDate, decimals);\n\n  // convert to percentage\n  var interest = (interest*100)-100;\n  var decimalMultiplier = decimals ? Math.pow(10,decimals) : 100;\n\n  // round to two decimals behind the dot\n  return Math.round(interest*decimalMultiplier) / decimalMultiplier;\n};\n\n// XXX Currently we inherit UInt.prototype.is_valid, which is mostly fine.\n//\n//     We could be doing further checks into the internal format of the\n//     currency data, since there are some values that are invalid.\n//\n//Currency.prototype.is_valid = function() {\n//  return this._value instanceof BigInteger && ...;\n//};\n\nCurrency.prototype.to_json = function(opts) {\n  if (!this.is_valid()) {\n    // XXX This is backwards compatible behavior, but probably not very good.\n    return 'XRP';\n  }\n\n  var opts = opts || {};\n\n  var currency;\n  var fullName = opts && opts.full_name ? ' - ' + opts.full_name : '';\n  opts.show_interest = opts.show_interest !== void(0) ? opts.show_interest : this.has_interest();\n\n  if (!opts.force_hex && /^[A-Z0-9]{3}$/.test(this._iso_code)) {\n    currency = this._iso_code + fullName;\n    if (opts.show_interest) {\n      var decimals = !isNaN(opts.decimals) ? opts.decimals : void(0);\n      var interestPercentage = this.has_interest() ? this.get_interest_percentage_at(this._interest_start + 3600 * 24 * 365, decimals) : 0;\n      currency += ' (' + interestPercentage + '%pa)';\n    }\n\n  } else {\n\n    // Fallback to returning the raw currency hex\n    currency = this.to_hex();\n\n    // XXX This is to maintain backwards compatibility, but it is very, very odd\n    //     behavior, so we should deprecate it and get rid of it as soon as\n    //     possible.\n    if (currency === Currency.HEX_ONE) {\n      currency = 1;\n    }\n  }\n\n  return currency;\n};\n\nCurrency.prototype.to_human = function(opts) {\n  // to_human() will always print the human-readable currency code if available.\n  return this.to_json(opts);\n};\n\nCurrency.prototype.get_iso = function() {\n  return this._iso_code;\n};\n\nexports.Currency = Currency;\n\n// vim:sw=2:sts=2:ts=8:et\n\n\n// WEBPACK FOOTER\n// module.id = 6\n// module.readableIdentifier = ./src/js/ripple/currency.js\n//@ sourceURL=webpack-module:///./src/js/ripple/currency.js");

/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {

	eval("var sjcl    = __webpack_require__(19).sjcl;\nvar utils   = __webpack_require__(19);\nvar extend  = __webpack_require__(44);\n\nvar BigInteger = utils.jsbn.BigInteger;\n\nvar Base = {};\n\nvar alphabets = Base.alphabets = {\n  ripple:  'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz',\n  tipple:  'RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz',\n  bitcoin:  '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'\n};\n\nextend(Base, {\n  VER_NONE              : 1,\n  VER_NODE_PUBLIC       : 28,\n  VER_NODE_PRIVATE      : 32,\n  VER_ACCOUNT_ID        : 0,\n  VER_ACCOUNT_PUBLIC    : 35,\n  VER_ACCOUNT_PRIVATE   : 34,\n  VER_FAMILY_GENERATOR  : 41,\n  VER_FAMILY_SEED       : 33\n});\n\nfunction sha256(bytes) {\n  return sjcl.codec.bytes.fromBits(sjcl.hash.sha256.hash(sjcl.codec.bytes.toBits(bytes)));\n};\n\nfunction sha256hash(bytes) {\n  return sha256(sha256(bytes));\n};\n\n// --> input: big-endian array of bytes.\n// <-- string at least as long as input.\nBase.encode = function(input, alpha) {\n  var alphabet = alphabets[alpha || 'ripple'];\n  var bi_base  = new BigInteger(String(alphabet.length));\n  var bi_q     = new BigInteger();\n  var bi_r     = new BigInteger();\n  var bi_value = new BigInteger(input);\n  var buffer   = [];\n\n  while (bi_value.compareTo(BigInteger.ZERO) > 0) {\n    bi_value.divRemTo(bi_base, bi_q, bi_r);\n    bi_q.copyTo(bi_value);\n    buffer.push(alphabet[bi_r.intValue()]);\n  }\n\n  for (var i=0; i !== input.length && !input[i]; i += 1) {\n    buffer.push(alphabet[0]);\n  }\n\n  return buffer.reverse().join('');\n};\n\n// --> input: String\n// <-- array of bytes or undefined.\nBase.decode = function(input, alpha) {\n  if (typeof input !== 'string') {\n    return void(0);\n  }\n\n  var alphabet = alphabets[alpha || 'ripple'];\n  var bi_base  = new BigInteger(String(alphabet.length));\n  var bi_value = new BigInteger();\n  var i;\n\n  for (i = 0; i !== input.length && input[i] === alphabet[0]; i += 1) {\n  }\n\n  for (; i !== input.length; i += 1) {\n    var v = alphabet.indexOf(input[i]);\n\n    if (v < 0) {\n      return void(0);\n    }\n\n    var r = new BigInteger();\n    r.fromInt(v);\n    bi_value  = bi_value.multiply(bi_base).add(r);\n  }\n\n  // toByteArray:\n  // - Returns leading zeros!\n  // - Returns signed bytes!\n  var bytes =  bi_value.toByteArray().map(function(b) { return b ? b < 0 ? 256+b : b : 0; });\n  var extra = 0;\n\n  while (extra !== bytes.length && !bytes[extra]) {\n    extra += 1;\n  }\n\n  if (extra) {\n    bytes = bytes.slice(extra);\n  }\n\n  var zeros = 0;\n\n  while (zeros !== input.length && input[zeros] === alphabet[0]) {\n    zeros += 1;\n  }\n\n  return [].concat(utils.arraySet(zeros, 0), bytes);\n};\n\nBase.verify_checksum = function(bytes) {\n  var computed = sha256hash(bytes.slice(0, -4)).slice(0, 4);\n  var checksum = bytes.slice(-4);\n  var result = true;\n\n  for (var i=0; i<4; i++) {\n    if (computed[i] !== checksum[i]) {\n      result = false;\n      break;\n    }\n  }\n\n  return result;\n};\n\n// --> input: Array\n// <-- String\nBase.encode_check = function(version, input, alphabet) {\n  var buffer = [].concat(version, input);\n  var check  = sha256(sha256(buffer)).slice(0, 4);\n\n  return Base.encode([].concat(buffer, check), alphabet);\n};\n\n// --> input : String\n// <-- NaN || BigInteger\nBase.decode_check = function(version, input, alphabet) {\n  var buffer = Base.decode(input, alphabet);\n\n  if (!buffer || buffer.length < 5) {\n    return NaN;\n  }\n\n  // Single valid version\n  if (typeof version === 'number' && buffer[0] !== version) {\n    return NaN;\n  }\n\n  // Multiple allowed versions\n  if (Array.isArray(version)) {\n    var match = false;\n\n    for (var i=0, l=version.length; i<l; i++) {\n      match |= version[i] === buffer[0];\n    }\n\n    if (!match) {\n      return NaN;\n    }\n  }\n\n  if (!Base.verify_checksum(buffer)) {\n    return NaN;\n  }\n\n  // We'll use the version byte to add a leading zero, this ensures JSBN doesn't\n  // intrepret the value as a negative number\n  buffer[0] = 0;\n\n  return new BigInteger(buffer.slice(0, -4), 256);\n};\n\nexports.Base = Base;\n\n\n// WEBPACK FOOTER\n// module.id = 7\n// module.readableIdentifier = ./src/js/ripple/base.js\n//@ sourceURL=webpack-module:///./src/js/ripple/base.js");

/***/ },
/* 8 */
/***/ function(module, exports, __webpack_require__) {

	eval("var utils   = __webpack_require__(19);\nvar config  = __webpack_require__(22);\nvar extend  = __webpack_require__(44);\n\nvar BigInteger = utils.jsbn.BigInteger;\n\nvar UInt = __webpack_require__(29).UInt;\nvar Base = __webpack_require__(7).Base;\n\n//\n// UInt160 support\n//\n\nvar UInt160 = extend(function() {\n  // Internal form: NaN or BigInteger\n  this._value  = NaN;\n  this._version_byte = void(0);\n  this._update();\n}, UInt);\n\nUInt160.width = 20;\nUInt160.prototype = extend({}, UInt.prototype);\nUInt160.prototype.constructor = UInt160;\n\nvar ACCOUNT_ZERO = UInt160.ACCOUNT_ZERO = 'rrrrrrrrrrrrrrrrrrrrrhoLvTp';\nvar ACCOUNT_ONE  = UInt160.ACCOUNT_ONE  = 'rrrrrrrrrrrrrrrrrrrrBZbvji';\nvar HEX_ZERO     = UInt160.HEX_ZERO     = '0000000000000000000000000000000000000000';\nvar HEX_ONE      = UInt160.HEX_ONE      = '0000000000000000000000000000000000000001';\nvar STR_ZERO     = UInt160.STR_ZERO     = utils.hexToString(HEX_ZERO);\nvar STR_ONE      = UInt160.STR_ONE      = utils.hexToString(HEX_ONE);\n\nUInt160.prototype.set_version = function(j) {\n  this._version_byte = j;\n  return this;\n};\n\nUInt160.prototype.get_version = function() {\n  return this._version_byte;\n};\n\n// value = NaN on error.\nUInt160.prototype.parse_json = function(j) {\n  // Canonicalize and validate\n  if (config.accounts && (j in config.accounts)) {\n    j = config.accounts[j].account;\n  }\n\n  if (typeof j === 'number' && !isNaN(j)) {\n    // Allow raw numbers - DEPRECATED\n    // This is used mostly by the test suite and is supported\n    // as a legacy feature only. DO NOT RELY ON THIS BEHAVIOR.\n    this._value = new BigInteger(String(j));\n    this._version_byte = Base.VER_ACCOUNT_ID;\n  } else if (typeof j !== 'string') {\n    this._value = NaN;\n  } else if (j[0] === 'r') {\n    this._value = Base.decode_check(Base.VER_ACCOUNT_ID, j);\n    this._version_byte = Base.VER_ACCOUNT_ID;\n  } else {\n    this.parse_hex(j);\n  }\n\n  this._update();\n\n  return this;\n};\n\nUInt160.prototype.parse_generic = function(j) {\n  UInt.prototype.parse_generic.call(this, j);\n\n  if (isNaN(this._value)) {\n    if ((typeof j === 'string') && j[0] === 'r') {\n      this._value = Base.decode_check(Base.VER_ACCOUNT_ID, j);\n    }\n  }\n\n  this._update();\n\n  return this;\n};\n\n// XXX Json form should allow 0 and 1, C++ doesn't currently allow it.\nUInt160.prototype.to_json = function(opts) {\n  opts  = opts || {};\n\n  if (this._value instanceof BigInteger) {\n    // If this value has a type, return a Base58 encoded string.\n    if (typeof this._version_byte === 'number') {\n      var output = Base.encode_check(this._version_byte, this.to_bytes());\n\n      if (opts.gateways && output in opts.gateways) {\n        output = opts.gateways[output];\n      }\n\n      return output;\n    } else {\n      return this.to_hex();\n    }\n  }\n  return NaN;\n};\n\nexports.UInt160 = UInt160;\n\n// vim:sw=2:sts=2:ts=8:et\n\n\n// WEBPACK FOOTER\n// module.id = 8\n// module.readableIdentifier = ./src/js/ripple/uint160.js\n//@ sourceURL=webpack-module:///./src/js/ripple/uint160.js");

/***/ },
/* 9 */
/***/ function(module, exports, __webpack_require__) {

	eval("var utils  = __webpack_require__(19);\nvar extend = __webpack_require__(44);\nvar UInt   = __webpack_require__(29).UInt;\n\n//\n// UInt256 support\n//\n\nvar UInt256 = extend(function() {\n  // Internal form: NaN or BigInteger\n  this._value = NaN;\n}, UInt);\n\nUInt256.width = 32;\nUInt256.prototype = extend({}, UInt.prototype);\nUInt256.prototype.constructor = UInt256;\n\nvar HEX_ZERO = UInt256.HEX_ZERO = '00000000000000000000000000000000' + '00000000000000000000000000000000';\nvar HEX_ONE  = UInt256.HEX_ONE  = '00000000000000000000000000000000' + '00000000000000000000000000000001';\nvar STR_ZERO = UInt256.STR_ZERO = utils.hexToString(HEX_ZERO);\nvar STR_ONE  = UInt256.STR_ONE  = utils.hexToString(HEX_ONE);\n\nexports.UInt256 = UInt256;\n\n\n// WEBPACK FOOTER\n// module.id = 9\n// module.readableIdentifier = ./src/js/ripple/uint256.js\n//@ sourceURL=webpack-module:///./src/js/ripple/uint256.js");

/***/ },
/* 10 */
/***/ function(module, exports, __webpack_require__) {

	eval("//\n// Seed support\n//\n\nvar extend = __webpack_require__(44);\nvar utils  = __webpack_require__(19);\nvar sjcl   = utils.sjcl;\n\nvar BigInteger = utils.jsbn.BigInteger;\n\nvar Base    = __webpack_require__(7).Base;\nvar UInt    = __webpack_require__(29).UInt;\nvar UInt256 = __webpack_require__(9).UInt256;\nvar UInt160 = __webpack_require__(8).UInt160;\nvar KeyPair = __webpack_require__(30).KeyPair;\n\nvar Seed = extend(function () {\n  // Internal form: NaN or BigInteger\n  this._curve = sjcl.ecc.curves.c256;\n  this._value = NaN;\n}, UInt);\n\nSeed.width = 16;\nSeed.prototype = extend({}, UInt.prototype);\nSeed.prototype.constructor = Seed;\n\n// value = NaN on error.\n// One day this will support rfc1751 too.\nSeed.prototype.parse_json = function (j) {\n  if (typeof j === 'string') {\n    if (!j.length) {\n      this._value = NaN;\n    // XXX Should actually always try and continue if it failed.\n    } else if (j[0] === 's') {\n      this._value = Base.decode_check(Base.VER_FAMILY_SEED, j);\n    } else if (/^[0-9a-fA-f]{32}$/.test(j)) {\n      this.parse_hex(j);\n    // XXX Should also try 1751\n    } else {\n      this.parse_passphrase(j);\n    }\n  } else {\n    this._value = NaN;\n  }\n\n  return this;\n};\n\nSeed.prototype.parse_passphrase = function (j) {\n  if (typeof j !== 'string') {\n    throw new Error('Passphrase must be a string');\n  }\n\n  var hash = sjcl.hash.sha512.hash(sjcl.codec.utf8String.toBits(j));\n  var bits = sjcl.bitArray.bitSlice(hash, 0, 128);\n\n  this.parse_bits(bits);\n\n  return this;\n};\n\nSeed.prototype.to_json = function () {\n  if (!(this._value instanceof BigInteger)) {\n    return NaN;\n  }\n\n  var output = Base.encode_check(Base.VER_FAMILY_SEED, this.to_bytes());\n\n  return output;\n};\n\nfunction append_int(a, i) {\n  return [].concat(a, i >> 24, (i >> 16) & 0xff, (i >> 8) & 0xff, i & 0xff);\n};\n\nfunction firstHalfOfSHA512(bytes) {\n  return sjcl.bitArray.bitSlice(\n    sjcl.hash.sha512.hash(sjcl.codec.bytes.toBits(bytes)),\n    0, 256\n  );\n};\n\nfunction SHA256_RIPEMD160(bits) {\n  return sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits));\n};\n\n/**\n* @param account\n*        {undefined}                 take first, default, KeyPair\n*\n*        {Number}                    specifies the account number of the KeyPair\n*                                    desired.\n*\n*        {Uint160} (from_json able), specifies the address matching the KeyPair\n*                                    that is desired.\n*\n* @param maxLoops (optional)\n*        {Number}                    specifies the amount of attempts taken to generate\n*                                    a matching KeyPair\n*/\nSeed.prototype.get_key = function (account, maxLoops) {\n  var account_number = 0, address;\n  var max_loops = maxLoops || 1;\n\n  if (!this.is_valid()) {\n    throw new Error('Cannot generate keys from invalid seed!');\n  }\n  if (account) {\n    if (typeof account === 'number') {\n      account_number = account;\n      max_loops = account_number+1;\n    } else {\n      address = UInt160.from_json(account);\n    }\n  }\n\n  var private_gen, public_gen;\n  var curve = this._curve;\n  var i = 0;\n\n  do {\n    private_gen = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(this.to_bytes(), i)));\n    i++;\n  } while (!curve.r.greaterEquals(private_gen));\n\n  public_gen = curve.G.mult(private_gen);\n\n  var sec;\n  var key_pair;\n\n  do {\n\n    i = 0;\n\n    do {\n      sec = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(append_int(public_gen.toBytesCompressed(), account_number), i)));\n      i++;\n    } while (!curve.r.greaterEquals(sec));\n\n    account_number++;\n    sec = sec.add(private_gen).mod(curve.r);\n    key_pair = KeyPair.from_bn_secret(sec);\n\n    if (max_loops-- <= 0) {\n      // We are almost certainly looking for an account that would take same\n      // value of $too_long {forever, ...}\n      throw new Error('Too many loops looking for KeyPair yielding '+\n                      address.to_json() +' from ' + this.to_json());\n    }\n\n  } while (address && !key_pair.get_address().equals(address));\n    return key_pair;\n};\n\nexports.Seed = Seed;\n\n\n// WEBPACK FOOTER\n// module.id = 10\n// module.readableIdentifier = ./src/js/ripple/seed.js\n//@ sourceURL=webpack-module:///./src/js/ripple/seed.js");

/***/ },
/* 11 */
/***/ function(module, exports, __webpack_require__) {

	eval("var extend  = __webpack_require__(44);\nvar utils   = __webpack_require__(19);\nvar UInt160 = __webpack_require__(8).UInt160;\nvar Amount  = __webpack_require__(3).Amount;\n\n/**\n * Meta data processing facility\n *\n * @constructor\n * @param {Object} transaction metadata\n */\n\nfunction Meta(data) {\n  var self = this;\n\n  this.nodes = [ ];\n\n  if (typeof data !== 'object') {\n    throw new TypeError('Missing metadata');\n  }\n\n  if (!Array.isArray(data.AffectedNodes)) {\n    throw new TypeError('Metadata missing AffectedNodes');\n  }\n\n  data.AffectedNodes.forEach(this.addNode, this);\n};\n\nMeta.nodeTypes = [\n  'CreatedNode',\n  'ModifiedNode',\n  'DeletedNode'\n];\n\nMeta.amountFieldsAffectingIssuer = [\n  'LowLimit',\n  'HighLimit',\n  'TakerPays',\n  'TakerGets'\n];\n\n/**\n * @api private\n */\n\nMeta.prototype.getNodeType = function(node) {\n  var result = null;\n\n  for (var i=0; i<Meta.nodeTypes.length; i++) {\n    var type = Meta.nodeTypes[i];\n    if (node.hasOwnProperty(type)) {\n      result = type;\n      break;\n    }\n  }\n\n  return result;\n};\n\n/**\n * Add node to metadata\n *\n * @param {Object} node\n * @api private\n */\n\nMeta.prototype.addNode = function(node) {\n  this._affectedAccounts = void(0);\n  this._affectedBooks = void(0);\n\n  var result = { };\n\n  if ((result.nodeType = this.getNodeType(node))) {\n    node = node[result.nodeType];\n\n    result.diffType    = result.nodeType;\n    result.entryType   = node.LedgerEntryType;\n    result.ledgerIndex = node.LedgerIndex;\n    result.fields      = extend({ }, node.PreviousFields, node.NewFields, node.FinalFields);\n    result.fieldsPrev  = node.PreviousFields || { };\n    result.fieldsNew   = node.NewFields || { };\n    result.fieldsFinal = node.FinalFields || { };\n\n    // getAffectedBooks will set this\n    // result.bookKey   = undefined;\n\n    this.nodes.push(result);\n  }\n};\n\n/**\n * Get affected nodes array\n *\n * @param {Object} filter options\n * @return {Array} nodes\n */\n\nMeta.prototype.getNodes = function(options) {\n  if (typeof options === 'object') {\n    return this.nodes.filter(function(node) {\n      if (options.nodeType && options.nodeType !== node.nodeType) {\n        return false;\n      }\n      if (options.entryType && options.entryType !== node.entryType) {\n        return false;\n      }\n      if (options.bookKey && options.bookKey !== node.bookKey) {\n        return false;\n      }\n      return true;\n    });\n  } else {\n    return this.nodes;\n  }\n};\n\n/**\n * Execute a function on each affected node.\n *\n * The callback is passed two parameters. The first is a node object which looks\n * like this:\n *\n *   {\n *     // Type of diff, e.g. CreatedNode, ModifiedNode\n *     nodeType: 'CreatedNode'\n *\n *     // Type of node affected, e.g. RippleState, AccountRoot\n *     entryType: 'RippleState',\n *\n *     // Index of the ledger this change occurred in\n *     ledgerIndex: '01AB01AB...',\n *\n *     // Contains all fields with later versions taking precedence\n *     //\n *     // This is a shorthand for doing things like checking which account\n *     // this affected without having to check the nodeType.\n *     fields: {...},\n *\n *     // Old fields (before the change)\n *     fieldsPrev: {...},\n *\n *     // New fields (that have been added)\n *     fieldsNew: {...},\n *\n *     // Changed fields\n *     fieldsFinal: {...}\n *   }\n *\n * The second parameter to the callback is the index of the node in the metadata\n * (first entry is index 0).\n */\n\n[\n 'forEach',\n 'map',\n 'filter',\n 'every',\n 'some',\n 'reduce'\n].forEach(function(fn) {\n  Meta.prototype[fn] = function() {\n    return Array.prototype[fn].apply(this.nodes, arguments);\n  };\n});\n\nMeta.prototype.each = Meta.prototype.forEach;\n\nMeta.prototype.getAffectedAccounts = function(from) {\n  if (this._affectedAccounts) {\n    return this._affectedAccounts;\n  }\n\n  var accounts = [ ];\n\n  // This code should match the behavior of the C++ method:\n  // TransactionMetaSet::getAffectedAccounts\n  for (var i=0; i<this.nodes.length; i++) {\n    var node = this.nodes[i];\n    var fields = (node.nodeType === 'CreatedNode') ? node.fieldsNew : node.fieldsFinal;\n    for (var fieldName in fields) {\n      var field = fields[fieldName];\n      if (typeof field === 'string' && UInt160.is_valid(field)) {\n        accounts.push(field);\n      } else if (~Meta.amountFieldsAffectingIssuer.indexOf(fieldName)) {\n        var amount = Amount.from_json(field);\n        var issuer = amount.issuer();\n        if (issuer.is_valid() && !issuer.is_zero()) {\n          accounts.push(issuer.to_json());\n        }\n      }\n    }\n  }\n\n  this._affectedAccounts = utils.arrayUnique(accounts);\n\n  return  this._affectedAccounts;\n};\n\nMeta.prototype.getAffectedBooks = function() {\n  if (this._affectedBooks) {\n    return this._affectedBooks;\n  }\n\n  var books = [ ];\n\n  for (var i=0; i<this.nodes.length; i++) {\n    var node = this.nodes[i];\n\n    if (node.entryType !== 'Offer') {\n      continue;\n    }\n\n    var gets = Amount.from_json(node.fields.TakerGets);\n    var pays = Amount.from_json(node.fields.TakerPays);\n    var getsKey = gets.currency().to_json();\n    var paysKey = pays.currency().to_json();\n\n    if (getsKey !== 'XRP') {\n      getsKey += '/' + gets.issuer().to_json();\n    }\n\n    if (paysKey !== 'XRP') {\n      paysKey += '/' + pays.issuer().to_json();\n    }\n\n    var key = getsKey + ':' + paysKey;\n\n    // Hell of a lot of work, so we are going to cache this. We can use this\n    // later to good effect in OrderBook.notify to make sure we only process\n    // pertinent offers.\n    node.bookKey = key;\n\n    books.push(key);\n  }\n\n  this._affectedBooks = utils.arrayUnique(books);\n\n  return this._affectedBooks;\n};\n\nexports.Meta = Meta;\n\n\n// WEBPACK FOOTER\n// module.id = 11\n// module.readableIdentifier = ./src/js/ripple/meta.js\n//@ sourceURL=webpack-module:///./src/js/ripple/meta.js");

/***/ },
/* 12 */
/***/ function(module, exports, __webpack_require__) {

	eval("/* WEBPACK VAR INJECTION */(function(Buffer) {var assert    = __webpack_require__(39);\nvar extend    = __webpack_require__(44);\nvar binformat = __webpack_require__(18);\nvar stypes    = __webpack_require__(31);\nvar UInt256   = __webpack_require__(9).UInt256;\nvar Crypt     = __webpack_require__(32).Crypt;\nvar utils     = __webpack_require__(19);\n\nvar sjcl = utils.sjcl;\nvar BigInteger = utils.jsbn.BigInteger;\n\nvar TRANSACTION_TYPES = { };\n\nObject.keys(binformat.tx).forEach(function(key) {\n  TRANSACTION_TYPES[binformat.tx[key][0]] = key;\n});\n\nvar LEDGER_ENTRY_TYPES = {};\n\nObject.keys(binformat.ledger).forEach(function(key) {\n  LEDGER_ENTRY_TYPES[binformat.ledger[key][0]] = key;\n});\n\nvar TRANSACTION_RESULTS = {};\n\nObject.keys(binformat.ter).forEach(function(key) {\n  TRANSACTION_RESULTS[binformat.ter[key]] = key;\n});\n\nfunction SerializedObject(buf) {\n  if (Array.isArray(buf) || (Buffer && Buffer.isBuffer(buf)) ) {\n    this.buffer = buf;\n  } else if (typeof buf === 'string') {\n    this.buffer = sjcl.codec.bytes.fromBits(sjcl.codec.hex.toBits(buf));\n  } else if (!buf) {\n    this.buffer = [];\n  } else {\n    throw new Error('Invalid buffer passed.');\n  }\n  this.pointer = 0;\n};\n\nSerializedObject.from_json = function(obj) {\n  // Create a copy of the object so we don't modify it\n  var obj = extend({}, obj);\n  var so  = new SerializedObject();\n  var typedef;\n\n  if (typeof obj.TransactionType === 'number') {\n    obj.TransactionType = SerializedObject.lookup_type_tx(obj.TransactionType);\n    if (!obj.TransactionType) {\n      throw new Error('Transaction type ID is invalid.');\n    }\n  }\n\n  if (typeof obj.LedgerEntryType === 'number') {\n    obj.LedgerEntryType = SerializedObject.lookup_type_le(obj.LedgerEntryType);\n\n    if (!obj.LedgerEntryType) {\n      throw new Error('LedgerEntryType ID is invalid.');\n    }\n  }\n\n  if (typeof obj.TransactionType === 'string') {\n    typedef = binformat.tx[obj.TransactionType];\n    if (!Array.isArray(typedef)) {\n      throw new Error('Transaction type is invalid');\n    }\n\n    typedef = typedef.slice();\n    obj.TransactionType = typedef.shift();\n  } else if (typeof obj.LedgerEntryType === 'string') {\n    typedef = binformat.ledger[obj.LedgerEntryType];\n\n    if (!Array.isArray(typedef)) {\n      throw new Error('LedgerEntryType is invalid');\n    }\n\n    typedef = typedef.slice();\n    obj.LedgerEntryType = typedef.shift();\n\n  } else if (typeof obj.AffectedNodes === 'object') {\n    typedef = binformat.metadata;\n  } else {\n    throw new Error('Object to be serialized must contain either' +\n                    ' TransactionType, LedgerEntryType or AffectedNodes.');\n  }\n\n  // ND: This from_*json* seems a reasonable place to put validation of `json`\n  SerializedObject.check_no_missing_fields(typedef, obj);\n  so.serialize(typedef, obj);\n\n  return so;\n};\n\nSerializedObject.check_no_missing_fields = function(typedef, obj) {\n  var missing_fields = [];\n\n  for (var i = typedef.length - 1; i >= 0; i--) {\n    var spec = typedef[i];\n    var field = spec[0];\n    var requirement = spec[1];\n\n    if (binformat.REQUIRED === requirement && obj[field] === void(0)) {\n      missing_fields.push(field);\n    };\n  };\n\n  if (missing_fields.length > 0) {\n    var object_name;\n\n    if (obj.TransactionType !== void(0)) {\n      object_name = SerializedObject.lookup_type_tx(obj.TransactionType);\n    } else if (obj.LedgerEntryType != null){\n      object_name = SerializedObject.lookup_type_le(obj.LedgerEntryType);\n    } else {\n      object_name = \"TransactionMetaData\";\n    }\n\n    throw new Error(object_name + \" is missing fields: \" +\n                    JSON.stringify(missing_fields));\n  };\n};\n\nSerializedObject.prototype.append = function(bytes) {\n  if (bytes instanceof SerializedObject) {\n    bytes = bytes.buffer;\n  }\n\n  this.buffer = this.buffer.concat(bytes);\n  this.pointer += bytes.length;\n};\n\nSerializedObject.prototype.resetPointer = function() {\n  this.pointer = 0;\n};\n\nfunction readOrPeek(advance) {\n  return function(bytes) {\n    var start = this.pointer;\n    var end = start + bytes;\n\n    if (end > this.buffer.length) {\n      throw new Error('Buffer length exceeded');\n    }\n\n    var result = this.buffer.slice(start, end);\n\n    if (advance) {\n      this.pointer = end;\n    }\n\n    return result;\n  };\n};\n\nSerializedObject.prototype.read = readOrPeek(true);\n\nSerializedObject.prototype.peek = readOrPeek(false);\n\nSerializedObject.prototype.to_bits = function() {\n  return sjcl.codec.bytes.toBits(this.buffer);\n};\n\nSerializedObject.prototype.to_hex = function() {\n  return sjcl.codec.hex.fromBits(this.to_bits()).toUpperCase();\n};\n\nSerializedObject.prototype.to_json = function() {\n  var old_pointer = this.pointer;\n  this.resetPointer();\n  var output = { };\n\n  while (this.pointer < this.buffer.length) {\n    var key_and_value = stypes.parse(this);\n    var key = key_and_value[0];\n    var value = key_and_value[1];\n    output[key] = SerializedObject.jsonify_structure(value, key);\n  }\n\n  this.pointer = old_pointer;\n\n  return output;\n};\n\nSerializedObject.jsonify_structure = function(structure, field_name) {\n  var output;\n\n  switch (typeof structure) {\n    case 'number':\n      switch (field_name) {\n        case 'LedgerEntryType':\n          output = LEDGER_ENTRY_TYPES[structure];\n          break;\n        case 'TransactionResult':\n          output = TRANSACTION_RESULTS[structure];\n          break;\n        case 'TransactionType':\n          output = TRANSACTION_TYPES[structure];\n          break;\n        default:\n          output = structure;\n      }\n      break;\n    case 'object':\n      if (structure === null) {\n        break;\n      }\n\n      if (typeof structure.to_json === 'function') {\n        output = structure.to_json();\n      } else if (structure instanceof BigInteger) {\n        output = structure.toString(16).toUpperCase();\n      } else {\n        //new Array or Object\n        output = new structure.constructor();\n\n        var keys = Object.keys(structure);\n\n        for (var i=0, l=keys.length; i<l; i++) {\n          var key = keys[i];\n          output[key] = SerializedObject.jsonify_structure(structure[key], key);\n        }\n      }\n      break;\n    default:\n      output = structure;\n  }\n\n  return output;\n};\n\nSerializedObject.prototype.serialize = function(typedef, obj) {\n  // Serialize object without end marker\n  stypes.Object.serialize(this, obj, true);\n\n  // ST: Old serialization\n  /*\n  // Ensure canonical order\n  typedef = SerializedObject.sort_typedef(typedef);\n\n  // Serialize fields\n  for (var i=0, l=typedef.length; i<l; i++) {\n    this.serialize_field(typedef[i], obj);\n  }\n  */\n};\n\nSerializedObject.prototype.hash = function(prefix) {\n  var sign_buffer = new SerializedObject();\n  \n  // Add hashing prefix\n  if (\"undefined\" !== typeof prefix) {\n    stypes.Int32.serialize(sign_buffer, prefix);\n  }\n\n  // Copy buffer to temporary buffer\n  sign_buffer.append(this.buffer);\n  \n  // XXX We need a proper Buffer class then Crypt could accept that\n  var bits = sjcl.codec.bytes.toBits(sign_buffer.buffer);\n  return Crypt.hashSha512Half(bits);\n};\n\n// DEPRECATED\nSerializedObject.prototype.signing_hash = SerializedObject.prototype.hash;\n\nSerializedObject.prototype.serialize_field = function(spec, obj) {\n  var name     = spec[0];\n  var presence = spec[1];\n  var field_id = spec[2];\n  var Type     = stypes[spec[3]];\n\n  if (typeof obj[name] !== 'undefined') {\n    // ST: Old serialization code\n    //this.append(SerializedObject.get_field_header(Type.id, field_id));\n    try {\n      // ST: Old serialization code\n      //Type.serialize(this, obj[name]);\n      stypes.serialize(this, name, obj[name]);\n    } catch (e) {\n      // Add field name to message and rethrow\n      e.message = 'Error serializing \"' + name + '\": ' + e.message;\n      throw e;\n    }\n  } else if (presence === binformat.REQUIRED) {\n    throw new Error('Missing required field ' + name);\n  }\n};\n\nSerializedObject.get_field_header = function(type_id, field_id) {\n  var buffer = [ 0 ];\n\n  if (type_id > 0xF) {\n    buffer.push(type_id & 0xFF);\n  } else {\n    buffer[0] += (type_id & 0xF) << 4;\n  }\n\n  if (field_id > 0xF) {\n    buffer.push(field_id & 0xFF);\n  } else {\n    buffer[0] += field_id & 0xF;\n  }\n\n  return buffer;\n};\n\nSerializedObject.sort_typedef = function(typedef) {\n  assert(Array.isArray(typedef));\n\n  function sort_field_compare(a, b) {\n    // Sort by type id first, then by field id\n    return a[3] !== b[3] ? stypes[a[3]].id - stypes[b[3]].id : a[2] - b[2];\n  };\n\n  return typedef.sort(sort_field_compare);\n};\n\nSerializedObject.lookup_type_tx = function(id) {\n  assert.strictEqual(typeof id, 'number');\n  return TRANSACTION_TYPES[id];\n};\n\nSerializedObject.lookup_type_le = function (id) {\n  assert(typeof id === 'number');\n  return LEDGER_ENTRY_TYPES[id];\n};\n\nexports.SerializedObject = SerializedObject;\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(41).Buffer))\n\n// WEBPACK FOOTER\n// module.id = 12\n// module.readableIdentifier = ./src/js/ripple/serializedobject.js\n//@ sourceURL=webpack-module:///./src/js/ripple/serializedobject.js");

/***/ },
/* 13 */
/***/ function(module, exports, __webpack_require__) {

	eval("var util   = __webpack_require__(38);\nvar extend = __webpack_require__(44);\n\nfunction RippleError(code, message) {\n  switch (typeof code) {\n    case 'object':\n      extend(this, code);\n      break;\n\n    case 'string':\n      this.result = code;\n      this.result_message = message;\n      break;\n  }\n\n  this.engine_result = this.result = (this.result || this.engine_result || this.error || 'Error');\n  this.engine_result_message = this.result_message = (this.result_message || this.engine_result_message || this.error_message || 'Error');\n  this.result_message = this.message = (this.result_message);\n\n  var stack;\n\n  if (!!Error.captureStackTrace) {\n    Error.captureStackTrace(this, code || this);\n  } else if ((stack = new Error().stack)) {\n    this.stack = stack;\n  }\n};\n\nutil.inherits(RippleError, Error);\n\nRippleError.prototype.name = 'RippleError';\n\nexports.RippleError = RippleError;\n\n\n// WEBPACK FOOTER\n// module.id = 13\n// module.readableIdentifier = ./src/js/ripple/rippleerror.js\n//@ sourceURL=webpack-module:///./src/js/ripple/rippleerror.js");

/***/ },
/* 14 */
/***/ function(module, exports, __webpack_require__) {

	eval("var async              = __webpack_require__(50);\nvar crypto             = __webpack_require__(42);\nvar sjcl               = __webpack_require__(19).sjcl;\nvar Remote             = __webpack_require__(1).Remote;\nvar Seed               = __webpack_require__(10).Seed;\nvar KeyPair            = __webpack_require__(30).KeyPair;\nvar Account            = __webpack_require__(4).Account;\nvar UInt160            = __webpack_require__(8).UInt160;\n\n// Message class (static)\nvar Message = {};\n\nMessage.HASH_FUNCTION  = sjcl.hash.sha512.hash;\nMessage.MAGIC_BYTES    = 'Ripple Signed Message:\\n';\n\nvar REGEX_HEX = /^[0-9a-fA-F]+$/;\nvar REGEX_BASE64 = /^([A-Za-z0-9\\+]{4})*([A-Za-z0-9\\+]{2}==)|([A-Za-z0-9\\+]{3}=)?$/;\n\n/**\n *  Produce a Base64-encoded signature on the given message with\n *  the string 'Ripple Signed Message:\\n' prepended.\n *\n *  Note that this signature uses the signing function that includes\n *  a recovery_factor to be able to extract the public key from the signature\n *  without having to pass the public key along with the signature.\n *\n *  @static\n *\n *  @param {String} message\n *  @param {sjcl.ecc.ecdsa.secretKey|Any format accepted by Seed.from_json} secret_key\n *  @param {RippleAddress} [The first key] account Field to specify the signing account. \n *    If this is omitted the first account produced by the secret generator will be used.\n *  @returns {Base64-encoded String} signature\n */\nMessage.signMessage = function(message, secret_key, account) {\n\n  return Message.signHash(Message.HASH_FUNCTION(Message.MAGIC_BYTES + message), secret_key, account);\n\n};\n\n/**\n *  Produce a Base64-encoded signature on the given hex-encoded hash.\n *\n *  Note that this signature uses the signing function that includes\n *  a recovery_factor to be able to extract the public key from the signature\n *  without having to pass the public key along with the signature.\n *\n *  @static\n *\n *  @param {bitArray|Hex-encoded String} hash\n *  @param {sjcl.ecc.ecdsa.secretKey|Any format accepted by Seed.from_json} secret_key\n *  @param {RippleAddress} [The first key] account Field to specify the signing account. \n *    If this is omitted the first account produced by the secret generator will be used.\n *  @returns {Base64-encoded String} signature\n */\nMessage.signHash = function(hash, secret_key, account) {\n\n  if (typeof hash === 'string' && /^[0-9a-fA-F]+$/.test(hash)) {\n    hash = sjcl.codec.hex.toBits(hash);\n  }\n\n  if (typeof hash !== 'object' || hash.length <= 0 || typeof hash[0] !== 'number') {\n    throw new Error('Hash must be a bitArray or hex-encoded string');\n  }\n\n  if (!(secret_key instanceof sjcl.ecc.ecdsa.secretKey)) {\n    secret_key = Seed.from_json(secret_key).get_key(account)._secret;\n  }\n\n  var signature_bits = secret_key.signWithRecoverablePublicKey(hash);\n  var signature_base64 = sjcl.codec.base64.fromBits(signature_bits);\n\n  return signature_base64;\n\n};\n\n\n/**\n *  Verify the signature on a given message.\n *\n *  Note that this function is asynchronous. \n *  The ripple-lib remote is used to check that the public\n *  key extracted from the signature corresponds to one that is currently\n *  active for the given account.\n *\n *  @static\n *\n *  @param {String} data.message\n *  @param {RippleAddress} data.account\n *  @param {Base64-encoded String} data.signature\n *  @param {ripple-lib Remote} remote\n *  @param {Function} callback\n *\n *  @callback callback\n *  @param {Error} error\n *  @param {boolean} is_valid true if the signature is valid, false otherwise\n */\nMessage.verifyMessageSignature = function(data, remote, callback) {\n\n  if (typeof data.message === 'string') {\n    data.hash = Message.HASH_FUNCTION(Message.MAGIC_BYTES + data.message);\n  } else {\n    return callback(new Error('Data object must contain message field to verify signature'));\n  }\n\n  return Message.verifyHashSignature(data, remote, callback);\n\n};\n\n\n/**\n *  Verify the signature on a given hash.\n *\n *  Note that this function is asynchronous. \n *  The ripple-lib remote is used to check that the public\n *  key extracted from the signature corresponds to one that is currently\n *  active for the given account.\n *\n *  @static\n *\n *  @param {bitArray|Hex-encoded String} data.hash\n *  @param {RippleAddress} data.account\n *  @param {Base64-encoded String} data.signature\n *  @param {ripple-lib Remote} remote\n *  @param {Function} callback\n *\n *  @callback callback\n *  @param {Error} error\n *  @param {boolean} is_valid true if the signature is valid, false otherwise\n */\nMessage.verifyHashSignature = function(data, remote, callback) {\n\n  var hash,\n    account,\n    signature;\n\n  if(typeof callback !== 'function') {\n    throw new Error('Must supply callback function');\n  }\n\n  hash = data.hash;\n  if (hash && typeof hash === 'string' && REGEX_HEX.test(hash)) {\n    hash = sjcl.codec.hex.toBits(hash);\n  }\n\n  if (typeof hash !== 'object' || hash.length <= 0 || typeof hash[0] !== 'number') {\n    return callback(new Error('Hash must be a bitArray or hex-encoded string'));\n  }\n\n  account = data.account || data.address;\n  if (!account || !UInt160.from_json(account).is_valid()) {\n    return callback(new Error('Account must be a valid ripple address'));\n  }\n\n  signature = data.signature;\n  if (typeof signature !== 'string' || !REGEX_BASE64.test(signature)) {\n    return callback(new Error('Signature must be a Base64-encoded string'));\n  }\n  signature = sjcl.codec.base64.toBits(signature);\n\n  if (!(remote instanceof Remote) || remote.state !== 'online') {\n    return callback(new Error('Must supply connected Remote to verify signature'));\n  }\n\n  function recoverPublicKey (async_callback) {\n\n    var public_key;\n    try {\n      public_key = sjcl.ecc.ecdsa.publicKey.recoverFromSignature(hash, signature);\n    } catch (err) {\n      return async_callback(err);\n    }\n\n    if (public_key) {\n      async_callback(null, public_key);\n    } else {\n      async_callback(new Error('Could not recover public key from signature'));\n    }\n\n  };\n\n  function checkPublicKeyIsValid (public_key, async_callback) {\n\n    // Get hex-encoded public key\n    var key_pair = new KeyPair();\n    key_pair._pubkey = public_key;\n    var public_key_hex = key_pair.to_hex_pub();\n\n    var account_class_instance = new Account(remote, account);\n    account_class_instance.publicKeyIsActive(public_key_hex, async_callback);\n\n  };\n\n  var steps = [\n    recoverPublicKey,\n    checkPublicKeyIsValid\n  ];\n\n  async.waterfall(steps, callback);\n\n};\n\nexports.Message = Message;\n\n\n// WEBPACK FOOTER\n// module.id = 14\n// module.readableIdentifier = ./src/js/ripple/message.js\n//@ sourceURL=webpack-module:///./src/js/ripple/message.js");

/***/ },
/* 15 */
/***/ function(module, exports, __webpack_require__) {

	eval("var async      = __webpack_require__(50);\nvar blobClient = __webpack_require__(33).BlobClient;\nvar AuthInfo   = __webpack_require__(16).AuthInfo;\nvar crypt      = __webpack_require__(32).Crypt;\nvar log        = __webpack_require__(25).sub('vault');\nfunction VaultClient(opts) {\n  \n  var self = this;\n  \n  if (!opts) {\n    opts = { };\n  }\n\n  if (typeof opts === 'string') {\n    opts = { domain: opts };\n  }\n\n  this.domain   = opts.domain || 'ripple.com';\n  this.infos    = { };\n};\n\n/**\n * getAuthInfo\n * gets auth info for a username. returns authinfo\n * even if user does not exists (with exist set to false)\n * @param {string} username\n * @param {function} callback\n */\nVaultClient.prototype.getAuthInfo = function (username, callback) {\n\n  AuthInfo.get(this.domain, username, function(err, authInfo) {\n    if (err) {\n      return callback(err);\n    }\n\n    if (authInfo.version !== 3) {\n      return callback(new Error('This wallet is incompatible with this version of the vault-client.'));\n    }\n\n    if (!authInfo.pakdf) {\n      return callback(new Error('No settings for PAKDF in auth packet.'));\n    }\n\n    if (typeof authInfo.blobvault !== 'string') {\n      return callback(new Error('No blobvault specified in the authinfo.'));\n    }\n\n    callback(null, authInfo);\n  });  \n};\n\n/**\n * _deriveLoginKeys\n * method designed for asnyc waterfall\n */\n\nVaultClient.prototype._deriveLoginKeys = function (authInfo, password, callback) {\n  var normalizedUsername = authInfo.username.toLowerCase().replace(/-/g, '');\n  \n  //derive login keys\n  crypt.derive(authInfo.pakdf, 'login', normalizedUsername, password, function(err, keys) {\n    if (err) {\n      callback(err);\n    } else {\n      callback(null, authInfo, password, keys);\n    }\n  });\n};\n\n\n\n/**\n * _deriveUnlockKey\n * method designed for asnyc waterfall\n */\n\nVaultClient.prototype._deriveUnlockKey = function (authInfo, password, keys, callback) {\n  var normalizedUsername = authInfo.username.toLowerCase().replace(/-/g, '');\n  \n  //derive unlock key\n  crypt.derive(authInfo.pakdf, 'unlock', normalizedUsername, password, function(err, unlock) {\n    if (err) {\n      log.error('derive:', err);\n      return callback(err);\n    }\n\n    if (!keys) {\n      keys = { };\n    }\n    \n    keys.unlock = unlock.unlock;\n    callback(null, authInfo, keys);\n  });\n};\n  \n/**\n * Get a ripple name from a given account address, if it has one\n * @param {string} address - Account address to query\n * @param {string} url     - Url of blob vault\n */\n\nVaultClient.prototype.getRippleName = function(address, url, callback) {\n  //use the url from previously retrieved authInfo, if necessary\n  if (!url) {\n    callback(new Error('Blob vault URL is required'));\n  } else {\n    blobClient.getRippleName(url, address, callback);\n  }\n};\n\n/**\n * Check blobvault for existance of username\n *\n * @param {string}    username\n * @param {function}  fn - Callback function\n */\n\nVaultClient.prototype.exists = function(username, callback) {\n  AuthInfo.get(this.domain, username.toLowerCase(), function(err, authInfo) {\n    if (err) {\n      callback(err);\n    } else {\n      callback(null, !!authInfo.exists);\n    }\n  });\n};\n\n/**\n * Authenticate and retrieve a decrypted blob using a ripple name and password\n *\n * @param {string}    username\n * @param {string}    password\n * @param {function}  fn - Callback function\n */\n\nVaultClient.prototype.login = function(username, password, device_id, callback) {\n  var self = this;\n  \n  var steps = [\n    getAuthInfo,\n    self._deriveLoginKeys,\n    getBlob\n  ];\n\n  async.waterfall(steps, callback);\n    \n  function getAuthInfo(callback) {\n    self.getAuthInfo(username, function(err, authInfo){\n      \n      if (authInfo && !authInfo.exists) {\n        return callback(new Error('User does not exist.'));\n      }\n            \n      return callback (err, authInfo, password);\n    });  \n  }\n  \n  function getBlob(authInfo, password, keys, callback) {\n    var options = {\n      url       : authInfo.blobvault,\n      blob_id   : keys.id,\n      key       : keys.crypt,\n      device_id : device_id\n    };\n    \n    blobClient.get(options, function(err, blob) {\n      if (err) {\n        return callback(err);\n      }\n\n      //save for relogin\n      self.infos[keys.id] = authInfo;\n\n      //migrate missing fields\n      if (blob.missing_fields) {\n        if (blob.missing_fields.encrypted_blobdecrypt_key) {     \n          log.info('migration: saving encrypted blob decrypt key');\n          authInfo.blob = blob;\n          //get the key to unlock the secret, then update the blob keys          \n          self._deriveUnlockKey(authInfo, password, keys, updateKeys);\n        }\n      }\n         \n      callback(null, {\n        blob      : blob,\n        username  : authInfo.username,\n        verified  : authInfo.emailVerified\n      });\n    });\n  };\n  \n  function updateKeys (err, params, keys) {\n    if (err || !keys.unlock) {\n      return; //unable to unlock\n    }\n    \n    var secret;\n    try {\n      secret = crypt.decrypt(keys.unlock, params.blob.encrypted_secret);\n    } catch (error) {\n      return log.error('decrypt:', error);\n    } \n    \n    options = {\n      username  : params.username,\n      blob      : params.blob,\n      masterkey : secret,\n      keys      : keys\n    };\n    \n    blobClient.updateKeys(options, function(err, resp){\n      if (err) {\n        log.error('updateKeys:', err);\n      }\n    });     \n  } \n};\n\n/**\n * Retreive and decrypt blob using a blob url, id and crypt derived previously.\n *\n * @param {string}   url - Blob vault url\n * @param {string}   id  - Blob id from previously retreived blob\n * @param {string}   key - Blob decryption key\n * @param {function} fn  - Callback function\n */\n\nVaultClient.prototype.relogin = function(url, id, key, device_id, callback) {\n  //use the url from previously retrieved authInfo, if necessary\n  if (!url && this.infos[id]) {\n    url = this.infos[id].blobvault;\n  }\n\n  if (!url) {\n    return callback(new Error('Blob vault URL is required'));\n  }\n\n  var options = {\n    url       : url,\n    blob_id   : id,\n    key       : key,\n    device_id : device_id\n  };\n    \n  blobClient.get(options, function(err, blob) {\n    if (err) {\n      callback(err);\n    } else {\n      callback (null, { blob: blob });\n    }\n  });\n};\n\n/**\n * Decrypt the secret key using a username and password\n *\n * @param {string}    username\n * @param {string}    password\n * @param {string}    encryptSecret\n * @param {function}  fn - Callback function\n */\n\nVaultClient.prototype.unlock = function(username, password, encryptSecret, fn) {\n  var self = this;\n  \n  var steps = [\n    getAuthInfo,\n    self._deriveUnlockKey,\n    unlockSecret\n  ];\n\n  async.waterfall(steps, fn);\n  \n  function getAuthInfo(callback) {\n    self.getAuthInfo(username, function(err, authInfo){\n      \n      if (authInfo && !authInfo.exists) {\n        return callback(new Error('User does not exist.'));\n      }\n            \n      return callback (err, authInfo, password, {});\n    });  \n  }\n  \n  function unlockSecret (authinfo, keys, callback) {\n\n    var secret;\n    try {\n      secret = crypt.decrypt(keys.unlock, encryptSecret);\n    } catch (error) {\n      return callback(error);\n    }  \n    \n    callback(null, {\n      keys   : keys,\n      secret : secret\n    });      \n  }\n};\n\n/**\n * Retrieve the decrypted blob and secret key in one step using\n * the username and password\n *\n * @param {string}    username\n * @param {string}    password\n * @param {function}  fn - Callback function\n */\n\nVaultClient.prototype.loginAndUnlock = function(username, password, device_id, fn) {\n  var self = this;\n\n  var steps = [\n    login,\n    deriveUnlockKey,\n    unlockSecret\n  ];\n\n  async.waterfall(steps, fn);  \n  \n  function login (callback) {\n    self.login(username, password, device_id, function(err, resp) {\n\n      if (err) {\n        return callback(err);\n      }\n  \n      if (!resp.blob || !resp.blob.encrypted_secret) {\n        return callback(new Error('Unable to retrieve blob and secret.'));\n      }\n  \n      if (!resp.blob.id || !resp.blob.key) {\n        return callback(new Error('Unable to retrieve keys.'));\n      }\n  \n      //get authInfo via id - would have been saved from login\n      var authInfo = self.infos[resp.blob.id];\n  \n      if (!authInfo) {\n        return callback(new Error('Unable to find authInfo'));\n      }\n    \n      callback(null, authInfo, password, resp.blob);\n    });    \n  };\n\n  function deriveUnlockKey (authInfo, password, blob, callback) {\n    self._deriveUnlockKey(authInfo, password, null, function(err, authInfo, keys){\n      callback(err, keys.unlock, authInfo, blob);\n    });\n  };\n  \n  function unlockSecret (unlock, authInfo, blob, callback) {\n    var secret;\n    try {\n      secret = crypt.decrypt(unlock, blob.encrypted_secret);\n    } catch (error) {\n      return callback(error);\n    }     \n    \n    callback(null, {\n      blob      : blob,\n      unlock    : unlock,\n      secret    : secret,\n      username  : authInfo.username,\n      verified  : authInfo.emailVerified\n    });    \n  };  \n};\n\n/**\n * Verify an email address for an existing user\n *\n * @param {string}    username\n * @param {string}    token - Verification token\n * @param {function}  fn - Callback function\n */\n\nVaultClient.prototype.verify = function(username, token, callback) {\n  var self = this;\n\n  self.getAuthInfo(username, function (err, authInfo){\n    if (err) {\n      return callback(err);\n    }\n    \n    blobClient.verify(authInfo.blobvault, username.toLowerCase(), token, callback);     \n  });\n};\n\n/*\n * changePassword\n * @param {object} options\n * @param {string} options.username\n * @param {string} options.password\n * @param {string} options.masterkey\n * @param {object} options.blob\n */\n\nVaultClient.prototype.changePassword = function (options, fn) {\n  var self     = this;\n  var password = String(options.password).trim();\n  \n  var steps = [\n    getAuthInfo,\n    self._deriveLoginKeys,\n    self._deriveUnlockKey,\n    changePassword\n  ];\n  \n  async.waterfall(steps, fn);\n    \n  function getAuthInfo(callback) {\n    self.getAuthInfo(options.username, function(err, authInfo) { \n      return callback (err, authInfo, password);      \n    });\n  };\n  \n  function changePassword (authInfo, keys, callback) {\n    options.keys = keys;\n    blobClient.updateKeys(options, callback); \n  };\n};\n\n/**\n * rename\n * rename a ripple account\n * @param {object} options\n * @param {string} options.username\n * @param {string} options.new_username\n * @param {string} options.password\n * @param {string} options.masterkey\n * @param {object} options.blob\n * @param {function} fn\n */\n\nVaultClient.prototype.rename = function (options, fn) {\n  var self         = this;\n  var new_username = String(options.new_username).trim();\n  var password     = String(options.password).trim();\n  \n  var steps = [\n    getAuthInfo,\n    self._deriveLoginKeys,\n    self._deriveUnlockKey,\n    renameBlob\n  ];\n\n  async.waterfall(steps, fn);\n    \n  function getAuthInfo(callback) {\n    self.getAuthInfo(new_username, function(err, authInfo){\n      \n      if (authInfo && authInfo.exists) {\n        return callback(new Error('username already taken.'));\n      } else {\n        authInfo.username = new_username;\n      }\n            \n      return callback (err, authInfo, password);\n    });  \n  };\n  \n  function renameBlob (authInfo, keys, callback) {\n    options.keys = keys;\n    blobClient.rename(options, callback);    \n  };\n};\n\n/**\n * Register a new user and save to the blob vault\n *\n * @param {object} options\n * @param {string} options.username\n * @param {string} options.password\n * @param {string} options.masterkey   //optional, will create if absent\n * @param {string} options.email\n * @param {string} options.activateLink\n * @param {object} options.oldUserBlob //optional\n * @param {function} fn\n */\n\nVaultClient.prototype.register = function(options, fn) {\n  var self     = this;\n  var username = String(options.username).trim();\n  var password = String(options.password).trim();\n  var result   = self.validateUsername(username);\n  \n  if (!result.valid) {\n    return fn(new Error('invalid username.'));  \n  }\n  \n  var steps = [\n    getAuthInfo,\n    self._deriveLoginKeys,\n    self._deriveUnlockKey,\n    create\n  ];\n  \n  async.waterfall(steps, fn);\n  \n  function getAuthInfo(callback) {\n    self.getAuthInfo(username, function(err, authInfo){      \n      return callback (err, authInfo, password);\n    });  \n  };\n\n  function create(authInfo, keys, callback) {\n    var params = {\n      url          : authInfo.blobvault,\n      id           : keys.id,\n      crypt        : keys.crypt,\n      unlock       : keys.unlock,\n      username     : username,\n      email        : options.email,\n      masterkey    : options.masterkey || crypt.createMaster(),\n      activateLink : options.activateLink,\n      oldUserBlob  : options.oldUserBlob,\n      domain       : options.domain\n    };\n        \n    blobClient.create(params, function(err, blob) {\n      if (err) {\n        callback(err);\n      } else {\n        callback(null, {\n          blob     : blob, \n          username : username\n        });\n      }\n    });\n  };\n};\n\n/**\n * validateUsername\n * check username for validity \n */\n\nVaultClient.prototype.validateUsername = function (username) {\n  username   = String(username).trim();\n  var result = {\n    valid  : false,\n    reason : ''\n  };\n  \n  if (username.length < 2) {\n    result.reason = 'tooshort';\n  } else if (username.length > 20) {\n    result.reason = 'toolong'; \n  } else if (!/^[a-zA-Z0-9\\-]+$/.exec(username)) {\n    result.reason = 'charset'; \n  } else if (/^-/.exec(username)) {\n    result.reason = 'starthyphen'; \n  } else if (/-$/.exec(username)) {\n    result.reason = 'endhyphen'; \n  } else if (/--/.exec(username)) {\n    result.reason = 'multhyphen'; \n  } else {\n    result.valid = true;\n  }\n  \n  return result;\n};\n\n/**\n * generateDeviceID\n * create a new random device ID for 2FA\n */\nVaultClient.prototype.generateDeviceID = function () {\n  return crypt.createSecret(4);\n};\n\n/*** pass thru some blob client function ***/\n\nVaultClient.prototype.resendEmail   = blobClient.resendEmail;\n\nVaultClient.prototype.recoverBlob   = blobClient.recoverBlob;\n\nVaultClient.prototype.deleteBlob    = blobClient.deleteBlob;\n\nVaultClient.prototype.requestToken  = blobClient.requestToken;\n\nVaultClient.prototype.verifyToken   = blobClient.verifyToken;\n\nVaultClient.prototype.getAttestation = blobClient.getAttestation;\n\nVaultClient.prototype.updateAttestation = blobClient.updateAttestation;\n\nVaultClient.prototype.getAttestationSummary = blobClient.getAttestationSummary;\n\n//export by name\nexports.VaultClient = VaultClient;\n\n\n// WEBPACK FOOTER\n// module.id = 15\n// module.readableIdentifier = ./src/js/ripple/vaultclient.js\n//@ sourceURL=webpack-module:///./src/js/ripple/vaultclient.js");

/***/ },
/* 16 */
/***/ function(module, exports, __webpack_require__) {

	eval("var async      = __webpack_require__(50);\nvar superagent = __webpack_require__(51);\nvar RippleTxt  = __webpack_require__(17).RippleTxt;\n\nvar AuthInfo = { };\n\nAuthInfo._getRippleTxt = function(domain, callback) {\n  RippleTxt.get(domain, callback);\n};\n\nAuthInfo._getUser = function(url, callback) {\n  superagent.get(url, callback);\n};\n\n\n/**\n * Get auth info for a given username\n *\n * @param {string}    domain - Domain which hosts the user's info\n * @param {string}    username - Username who's info we are retreiving\n * @param {function}  fn - Callback function\n */\n\nAuthInfo.get = function(domain, username, callback) {\n  var self = this;\n  username = username.toLowerCase();\n  \n  function getRippleTxt(callback) {\n    self._getRippleTxt(domain, function(err, txt) {\n      if (err) {\n        return callback(err);\n      }\n\n      if (!txt.authinfo_url) {\n        return callback(new Error('Authentication is not supported on ' + domain));\n      }\n\n      var url = Array.isArray(txt.authinfo_url) ? txt.authinfo_url[0] : txt.authinfo_url;\n\n      url += '?domain=' + domain + '&username=' + username;\n\n      callback(null, url);\n    });\n  };\n\n  function getUser(url, callback) {\n    self._getUser(url, function(err, res) {\n      if (err || res.error) {\n        callback(new Error('Authentication info server unreachable'));\n      } else {\n        callback(null, res.body);\n      }\n    });\n  };\n\n  async.waterfall([ getRippleTxt, getUser ], callback);\n};\n\nexports.AuthInfo = AuthInfo;\n\n\n// WEBPACK FOOTER\n// module.id = 16\n// module.readableIdentifier = ./src/js/ripple/authinfo.js\n//@ sourceURL=webpack-module:///./src/js/ripple/authinfo.js");

/***/ },
/* 17 */
/***/ function(module, exports, __webpack_require__) {

	eval("var request   = __webpack_require__(51);\nvar Currency  = __webpack_require__(6).Currency;\n\nvar RippleTxt = {\n  txts : { }\n};\n\nRippleTxt.urlTemplates = [\n  'https://{{domain}}/ripple.txt',\n  'https://www.{{domain}}/ripple.txt',\n  'https://ripple.{{domain}}/ripple.txt',\n  'http://{{domain}}/ripple.txt',\n  'http://www.{{domain}}/ripple.txt',\n  'http://ripple.{{domain}}/ripple.txt'\n];\n\n/**\n * Gets the ripple.txt file for the given domain\n * @param {string}    domain - Domain to retrieve file from\n * @param {function}  fn - Callback function\n */\n\nRippleTxt.get = function(domain, fn) {\n  var self = this;\n\n  if (self.txts[domain]) {\n    return fn(null, self.txts[domain]);\n  }\n\n  ;(function nextUrl(i) {\n    var url = RippleTxt.urlTemplates[i];\n    \n    if (!url) {\n      return fn(new Error('No ripple.txt found'));\n    }\n\n    url = url.replace('{{domain}}', domain);\n    \n    request.get(url, function(err, resp) {\n      if (err || !resp.text) {\n        return nextUrl(++i);\n      }\n\n      var sections = self.parse(resp.text);\n      self.txts[domain] = sections;\n\n      fn(null, sections);\n    });\n  })(0);\n};\n\n/**\n * Parse a ripple.txt file\n * @param {string}  txt - Unparsed ripple.txt data\n */\n\nRippleTxt.parse = function(txt) {\n  var currentSection = '';\n  var sections = { };\n  \n  txt = txt.replace(/\\r?\\n/g, '\\n').split('\\n');\n\n  for (var i = 0, l = txt.length; i < l; i++) {\n    var line = txt[i];\n\n    if (!line.length || line[0] === '#') {\n      continue;\n    }\n\n    if (line[0] === '[' && line[line.length - 1] === ']') {\n      currentSection = line.slice(1, line.length - 1);\n      sections[currentSection] = [];\n    } else {\n      line = line.replace(/^\\s+|\\s+$/g, '');\n      if (sections[currentSection]) {\n        sections[currentSection].push(line);\n      }\n    }\n  }\n\n  return sections;\n};\n\n/**\n * extractDomain\n * attempt to extract the domain from a given url\n * returns the url if unsuccessful\n * @param {Object} url\n */\n\nRippleTxt.extractDomain = function (url) {\n  match = /[^.]*\\.[^.]{2,3}(?:\\.[^.]{2,3})?([^.\\?][^\\?.]+?)?$/.exec(url);\n  return match && match[0] ? match[0] : url;\n};\n\n/**\n * getCurrencies\n * returns domain, issuer account and currency object\n * for each currency found in the domain's ripple.txt file\n * @param {Object} domain\n * @param {Object} fn\n */\n\nRippleTxt.getCurrencies = function(domain, fn) {\n  domain = RippleTxt.extractDomain(domain);\n  this.get(domain, function(err, txt) {\n    if (err) {\n      return fn(err);  \n    }\n    \n    if (err || !txt.currencies || !txt.accounts) {\n      return fn(null, []);\n    }\n    \n    //NOTE: this won't be accurate if there are\n    //multiple issuer accounts with different \n    //currencies associated with each.\n    var issuer     = txt.accounts[0];\n    var currencies = [];\n    \n    txt.currencies.forEach(function(currency) {\n      currencies.push({\n        issuer   : issuer,\n        currency : Currency.from_json(currency),\n        domain   : domain\n      });\n    });\n    \n    fn(null, currencies);\n  });\n}; \n\nexports.RippleTxt = RippleTxt;\n\n\n// WEBPACK FOOTER\n// module.id = 17\n// module.readableIdentifier = ./src/js/ripple/rippletxt.js\n//@ sourceURL=webpack-module:///./src/js/ripple/rippletxt.js");

/***/ },
/* 18 */
/***/ function(module, exports, __webpack_require__) {

	eval("/**\n * Data type map.\n *\n * Mapping of type ids to data types. The type id is specified by the high\n */\nvar TYPES_MAP = exports.types = [\n  void(0),\n\n  // Common\n  'Int16',    // 1\n  'Int32',    // 2\n  'Int64',    // 3\n  'Hash128',  // 4\n  'Hash256',  // 5\n  'Amount',   // 6\n  'VL',       // 7\n  'Account',  // 8\n\n  // 9-13 reserved\n  void(0),    // 9\n  void(0),    // 10\n  void(0),    // 11\n  void(0),    // 12\n  void(0),    // 13\n\n  'Object',   // 14\n  'Array',    // 15\n\n  // Uncommon\n  'Int8',     // 16\n  'Hash160',  // 17\n  'PathSet',  // 18\n  'Vector256' // 19\n];\n\n/**\n * Field type map.\n *\n * Mapping of field type id to field type name.\n */\n\nvar FIELDS_MAP = exports.fields = {\n  // Common types\n  1: { // Int16\n    1: 'LedgerEntryType',\n    2: 'TransactionType'\n  },\n  2: { // Int32\n    2: 'Flags',\n    3: 'SourceTag',\n    4: 'Sequence',\n    5: 'PreviousTxnLgrSeq',\n    6: 'LedgerSequence',\n    7: 'CloseTime',\n    8: 'ParentCloseTime',\n    9: 'SigningTime',\n    10: 'Expiration',\n    11: 'TransferRate',\n    12: 'WalletSize',\n    13: 'OwnerCount',\n    14: 'DestinationTag',\n    // Skip 15\n    16: 'HighQualityIn',\n    17: 'HighQualityOut',\n    18: 'LowQualityIn',\n    19: 'LowQualityOut',\n    20: 'QualityIn',\n    21: 'QualityOut',\n    22: 'StampEscrow',\n    23: 'BondAmount',\n    24: 'LoadFee',\n    25: 'OfferSequence',\n    26: 'FirstLedgerSequence',\n    27: 'LastLedgerSequence',\n    28: 'TransactionIndex',\n    29: 'OperationLimit',\n    30: 'ReferenceFeeUnits',\n    31: 'ReserveBase',\n    32: 'ReserveIncrement',\n    33: 'SetFlag',\n    34: 'ClearFlag'\n  },\n  3: { // Int64\n    1: 'IndexNext',\n    2: 'IndexPrevious',\n    3: 'BookNode',\n    4: 'OwnerNode',\n    5: 'BaseFee',\n    6: 'ExchangeRate',\n    7: 'LowNode',\n    8: 'HighNode'\n  },\n  4: { // Hash128\n    1: 'EmailHash'\n  },\n  5: { // Hash256\n    1: 'LedgerHash',\n    2: 'ParentHash',\n    3: 'TransactionHash',\n    4: 'AccountHash',\n    5: 'PreviousTxnID',\n    6: 'LedgerIndex',\n    7: 'WalletLocator',\n    8: 'RootIndex',\n    9: 'AccountTxnID',\n    16: 'BookDirectory',\n    17: 'InvoiceID',\n    18: 'Nickname',\n    19: 'Amendment',\n    20: 'TicketID'\n  },\n  6: { // Amount\n    1: 'Amount',\n    2: 'Balance',\n    3: 'LimitAmount',\n    4: 'TakerPays',\n    5: 'TakerGets',\n    6: 'LowLimit',\n    7: 'HighLimit',\n    8: 'Fee',\n    9: 'SendMax',\n    16: 'MinimumOffer',\n    17: 'RippleEscrow',\n    18: 'DeliveredAmount'\n  },\n  7: { // VL\n    1: 'PublicKey',\n    2: 'MessageKey',\n    3: 'SigningPubKey',\n    4: 'TxnSignature',\n    5: 'Generator',\n    6: 'Signature',\n    7: 'Domain',\n    8: 'FundCode',\n    9: 'RemoveCode',\n    10: 'ExpireCode',\n    11: 'CreateCode',\n    12: 'MemoType',\n    13: 'MemoData',\n    14: 'MemoFormat'\n  },\n  8: { // Account\n    1: 'Account',\n    2: 'Owner',\n    3: 'Destination',\n    4: 'Issuer',\n    7: 'Target',\n    8: 'RegularKey'\n  },\n  14: { // Object\n    1: void(0),  //end of Object\n    2: 'TransactionMetaData',\n    3: 'CreatedNode',\n    4: 'DeletedNode',\n    5: 'ModifiedNode',\n    6: 'PreviousFields',\n    7: 'FinalFields',\n    8: 'NewFields',\n    9: 'TemplateEntry',\n    10: 'Memo'\n  },\n  15: { // Array\n    1: void(0),  //end of Array\n    2: 'SigningAccounts',\n    3: 'TxnSignatures',\n    4: 'Signatures',\n    5: 'Template',\n    6: 'Necessary',\n    7: 'Sufficient',\n    8: 'AffectedNodes',\n    9: 'Memos'\n  },\n\n  // Uncommon types\n  16: { // Int8\n    1: 'CloseResolution',\n    2: 'TemplateEntryType',\n    3: 'TransactionResult'\n  },\n  17: { // Hash160\n    1: 'TakerPaysCurrency',\n    2: 'TakerPaysIssuer',\n    3: 'TakerGetsCurrency',\n    4: 'TakerGetsIssuer'\n  },\n  18: { // PathSet\n    1: 'Paths'\n  },\n  19: { // Vector256\n    1: 'Indexes',\n    2: 'Hashes',\n    3: 'Amendments'\n  }\n};\n\nvar INVERSE_FIELDS_MAP = exports.fieldsInverseMap = { };\n\nObject.keys(FIELDS_MAP).forEach(function(k1) {\n  Object.keys(FIELDS_MAP[k1]).forEach(function(k2) {\n    INVERSE_FIELDS_MAP[FIELDS_MAP[k1][k2]] = [ Number(k1), Number(k2) ];\n  });\n});\n\n\nvar REQUIRED = exports.REQUIRED = 0,\n    OPTIONAL = exports.OPTIONAL = 1,\n    DEFAULT  = exports.DEFAULT  = 2;\n\nvar base = [\n  [ 'TransactionType'    , REQUIRED ],\n  [ 'Flags'              , OPTIONAL ],\n  [ 'SourceTag'          , OPTIONAL ],\n  [ 'LastLedgerSequence' , OPTIONAL ],\n  [ 'Account'            , REQUIRED ],\n  [ 'Sequence'           , REQUIRED ],\n  [ 'Fee'                , REQUIRED ],\n  [ 'OperationLimit'     , OPTIONAL ],\n  [ 'SigningPubKey'      , REQUIRED ],\n  [ 'TxnSignature'       , OPTIONAL ]\n];\n\nexports.tx = {\n  AccountSet: [3].concat(base, [\n    [ 'EmailHash'          , OPTIONAL ],\n    [ 'WalletLocator'      , OPTIONAL ],\n    [ 'WalletSize'         , OPTIONAL ],\n    [ 'MessageKey'         , OPTIONAL ],\n    [ 'Domain'             , OPTIONAL ],\n    [ 'TransferRate'       , OPTIONAL ]\n  ]),\n  TrustSet: [20].concat(base, [\n    [ 'LimitAmount'        , OPTIONAL ],\n    [ 'QualityIn'          , OPTIONAL ],\n    [ 'QualityOut'         , OPTIONAL ]\n  ]),\n  OfferCreate: [7].concat(base, [\n    [ 'TakerPays'          , REQUIRED ],\n    [ 'TakerGets'          , REQUIRED ],\n    [ 'Expiration'         , OPTIONAL ]\n  ]),\n  OfferCancel: [8].concat(base, [\n    [ 'OfferSequence'      , REQUIRED ]\n  ]),\n  SetRegularKey: [5].concat(base, [\n    [ 'RegularKey'         , REQUIRED ]\n  ]),\n  Payment: [0].concat(base, [\n    [ 'Destination'        , REQUIRED ],\n    [ 'Amount'             , REQUIRED ],\n    [ 'SendMax'            , OPTIONAL ],\n    [ 'Paths'              , DEFAULT  ],\n    [ 'InvoiceID'          , OPTIONAL ],\n    [ 'DestinationTag'     , OPTIONAL ]\n  ]),\n  Contract: [9].concat(base, [\n    [ 'Expiration'         , REQUIRED ],\n    [ 'BondAmount'         , REQUIRED ],\n    [ 'StampEscrow'        , REQUIRED ],\n    [ 'RippleEscrow'       , REQUIRED ],\n    [ 'CreateCode'         , OPTIONAL ],\n    [ 'FundCode'           , OPTIONAL ],\n    [ 'RemoveCode'         , OPTIONAL ],\n    [ 'ExpireCode'         , OPTIONAL ]\n  ]),\n  RemoveContract: [10].concat(base, [\n    [ 'Target'             , REQUIRED ]\n  ]),\n  EnableFeature: [100].concat(base, [\n    [ 'Feature'            , REQUIRED ]\n  ]),\n  SetFee: [101].concat(base, [\n    [ 'Features'           , REQUIRED ],\n    [ 'BaseFee'            , REQUIRED ],\n    [ 'ReferenceFeeUnits'  , REQUIRED ],\n    [ 'ReserveBase'        , REQUIRED ],\n    [ 'ReserveIncrement'   , REQUIRED ]\n  ])\n};\n\nvar sleBase = [\n  ['LedgerIndex',          OPTIONAL],\n  ['LedgerEntryType',      REQUIRED],\n  ['Flags',                REQUIRED]\n];\n\nexports.ledger = {\n  AccountRoot: [97].concat(sleBase,[\n    ['Sequence',           REQUIRED],\n    ['PreviousTxnLgrSeq',  REQUIRED],\n    ['TransferRate',       OPTIONAL],\n    ['WalletSize',         OPTIONAL],\n    ['OwnerCount',         REQUIRED],\n    ['EmailHash',          OPTIONAL],\n    ['PreviousTxnID',      REQUIRED],\n    ['AccountTxnID',       OPTIONAL],\n    ['WalletLocator',      OPTIONAL],\n    ['Balance',            REQUIRED],\n    ['MessageKey',         OPTIONAL],\n    ['Domain',             OPTIONAL],\n    ['Account',            REQUIRED],\n    ['RegularKey',         OPTIONAL]]),\n  Contract: [99].concat(sleBase,[\n    ['PreviousTxnLgrSeq',  REQUIRED],\n    ['Expiration',         REQUIRED],\n    ['BondAmount',         REQUIRED],\n    ['PreviousTxnID',      REQUIRED],\n    ['Balance',            REQUIRED],\n    ['FundCode',           OPTIONAL],\n    ['RemoveCode',         OPTIONAL],\n    ['ExpireCode',         OPTIONAL],\n    ['CreateCode',         OPTIONAL],\n    ['Account',            REQUIRED],\n    ['Owner',              REQUIRED],\n    ['Issuer',             REQUIRED]]),\n  DirectoryNode: [100].concat(sleBase,[\n    ['IndexNext',          OPTIONAL],\n    ['IndexPrevious',      OPTIONAL],\n    ['ExchangeRate',       OPTIONAL],\n    ['RootIndex',          REQUIRED],\n    ['Owner',              OPTIONAL],\n    ['TakerPaysCurrency',  OPTIONAL],\n    ['TakerPaysIssuer',    OPTIONAL],\n    ['TakerGetsCurrency',  OPTIONAL],\n    ['TakerGetsIssuer',    OPTIONAL],\n    ['Indexes',            REQUIRED]]),\n  EnabledFeatures: [102].concat(sleBase,[\n    ['Features',           REQUIRED]]),\n  FeeSettings: [115].concat(sleBase,[\n    ['ReferenceFeeUnits',  REQUIRED],\n    ['ReserveBase',        REQUIRED],\n    ['ReserveIncrement',   REQUIRED],\n    ['BaseFee',            REQUIRED],\n    ['LedgerIndex',        OPTIONAL]]),\n  GeneratorMap: [103].concat(sleBase,[\n    ['Generator',          REQUIRED]]),\n  LedgerHashes: [104].concat(sleBase,[\n    ['LedgerEntryType',      REQUIRED],\n    ['Flags',                REQUIRED],\n    ['FirstLedgerSequence',  OPTIONAL],\n    ['LastLedgerSequence',   OPTIONAL],\n    ['LedgerIndex',          OPTIONAL],\n    ['Hashes',               REQUIRED]]),\n  Nickname: [110].concat(sleBase,[\n    ['LedgerEntryType',     REQUIRED],\n    ['Flags',               REQUIRED],\n    ['LedgerIndex',         OPTIONAL],\n    ['MinimumOffer',        OPTIONAL],\n    ['Account',             REQUIRED]]),\n  Offer: [111].concat(sleBase,[\n    ['LedgerEntryType',     REQUIRED],\n    ['Flags',               REQUIRED],\n    ['Sequence',            REQUIRED],\n    ['PreviousTxnLgrSeq',   REQUIRED],\n    ['Expiration',          OPTIONAL],\n    ['BookNode',            REQUIRED],\n    ['OwnerNode',           REQUIRED],\n    ['PreviousTxnID',       REQUIRED],\n    ['LedgerIndex',         OPTIONAL],\n    ['BookDirectory',       REQUIRED],\n    ['TakerPays',           REQUIRED],\n    ['TakerGets',           REQUIRED],\n    ['Account',             REQUIRED]]),\n  RippleState: [114].concat(sleBase,[\n    ['LedgerEntryType',     REQUIRED],\n    ['Flags',               REQUIRED],\n    ['PreviousTxnLgrSeq',   REQUIRED],\n    ['HighQualityIn',       OPTIONAL],\n    ['HighQualityOut',      OPTIONAL],\n    ['LowQualityIn',        OPTIONAL],\n    ['LowQualityOut',       OPTIONAL],\n    ['LowNode',             OPTIONAL],\n    ['HighNode',            OPTIONAL],\n    ['PreviousTxnID',       REQUIRED],\n    ['LedgerIndex',         OPTIONAL],\n    ['Balance',             REQUIRED],\n    ['LowLimit',            REQUIRED],\n    ['HighLimit',           REQUIRED]])\n}\n\nexports.metadata = [\n  [ 'TransactionIndex'     , REQUIRED ],\n  [ 'TransactionResult'    , REQUIRED ],\n  [ 'AffectedNodes'        , REQUIRED ]\n];\n\nexports.ter = {\n  tesSUCCESS               : 0,\n  tecCLAIM                 : 100,\n  tecPATH_PARTIAL          : 101,\n  tecUNFUNDED_ADD          : 102,\n  tecUNFUNDED_OFFER        : 103,\n  tecUNFUNDED_PAYMENT      : 104,\n  tecFAILED_PROCESSING     : 105,\n  tecDIR_FULL              : 121,\n  tecINSUF_RESERVE_LINE    : 122,\n  tecINSUF_RESERVE_OFFER   : 123,\n  tecNO_DST                : 124,\n  tecNO_DST_INSUF_XRP      : 125,\n  tecNO_LINE_INSUF_RESERVE : 126,\n  tecNO_LINE_REDUNDANT     : 127,\n  tecPATH_DRY              : 128,\n  tecUNFUNDED              : 129,  // Deprecated, old ambiguous unfunded.\n  tecMASTER_DISABLED       : 130,\n  tecNO_REGULAR_KEY        : 131,\n  tecOWNERS                : 132,\n  tecNO_ISSUER             : 133,\n  tecNO_AUTH               : 134,\n  tecNO_LINE               : 135,\n  tecINSUFF_FEE            : 136,\n  tecFROZEN                : 137,\n  tecNO_TARGET             : 138,\n  tecNO_PERMISSION         : 139,\n  tecNO_ENTRY              : 140,\n  tecINSUFFICIENT_RESERVE  : 141\n};\n\n\n// WEBPACK FOOTER\n// module.id = 18\n// module.readableIdentifier = ./src/js/ripple/binformat.js\n//@ sourceURL=webpack-module:///./src/js/ripple/binformat.js");

/***/ },
/* 19 */
/***/ function(module, exports, __webpack_require__) {

	eval("function filterErr(code, done) {\n  return function(e) {\n    done(e.code !== code ? e : void(0));\n  };\n};\n\nfunction throwErr(done) {\n  return function(e) {\n    if (e) {\n      throw e;\n    }\n    done();\n  };\n};\n\nfunction trace(comment, func) {\n  return function() {\n    console.log('%s: %s', trace, arguments.toString);\n    func(arguments);\n  };\n};\n\nfunction arraySet(count, value) {\n  var a = new Array(count);\n\n  for (var i=0; i<count; i++) {\n    a[i] = value;\n  }\n\n  return a;\n};\n\nfunction hexToString(h) {\n  var a = [];\n  var i = 0;\n\n  if (h.length % 2) {\n    a.push(String.fromCharCode(parseInt(h.substring(0, 1), 16)));\n    i = 1;\n  }\n\n  for (; i<h.length; i+=2) {\n    a.push(String.fromCharCode(parseInt(h.substring(i, i+2), 16)));\n  }\n\n  return a.join('');\n};\n\nfunction stringToHex(s) {\n  var result = '';\n  for (var i=0; i<s.length; i++) {\n    var b = s.charCodeAt(i);\n    result += b < 16 ? '0' + b.toString(16) : b.toString(16);\n  }\n  return result;\n};\n\nfunction stringToArray(s) {\n  var a = new Array(s.length);\n\n  for (var i=0; i<a.length; i+=1) {\n    a[i] = s.charCodeAt(i);\n  }\n\n  return a;\n};\n\nfunction hexToArray(h) {\n  return stringToArray(hexToString(h));\n};\n\nfunction chunkString(str, n, leftAlign) {\n  var ret = [];\n  var i=0, len=str.length;\n\n  if (leftAlign) {\n    i = str.length % n;\n    if (i) {\n      ret.push(str.slice(0, i));\n    }\n  }\n\n  for(; i<len; i+=n) {\n    ret.push(str.slice(i, n + i));\n  }\n\n  return ret;\n};\n\nfunction assert(assertion, msg) {\n  if (!assertion) {\n    throw new Error('Assertion failed' + (msg ? ': ' + msg : '.'));\n  }\n};\n\n/**\n * Return unique values in array.\n */\nfunction arrayUnique(arr) {\n  var u = {}, a = [];\n\n  for (var i=0, l=arr.length; i<l; i++){\n    var k = arr[i];\n    if (u[k]) {\n      continue;\n    }\n    a.push(k);\n    u[k] = true;\n  }\n\n  return a;\n};\n\n/**\n * Convert a ripple epoch to a JavaScript timestamp.\n *\n * JavaScript timestamps are unix epoch in milliseconds.\n */\nfunction toTimestamp(rpepoch) {\n  return (rpepoch + 0x386D4380) * 1000;\n};\n\n/**\n * Convert a JavaScript timestamp or Date to a Ripple epoch.\n *\n * JavaScript timestamps are unix epoch in milliseconds.\n */\nfunction fromTimestamp(rpepoch) {\n  if (rpepoch instanceof Date) {\n    rpepoch = rpepoch.getTime();\n  }\n\n  return Math.round(rpepoch / 1000) - 0x386D4380;\n};\n\nexports.time = {\n  fromRipple: toTimestamp,\n  toRipple: fromTimestamp\n};\n\nexports.trace         = trace;\nexports.arraySet      = arraySet;\nexports.hexToString   = hexToString;\nexports.hexToArray    = hexToArray;\nexports.stringToArray = stringToArray;\nexports.stringToHex   = stringToHex;\nexports.chunkString   = chunkString;\nexports.assert        = assert;\nexports.arrayUnique   = arrayUnique;\nexports.toTimestamp   = toTimestamp;\nexports.fromTimestamp = fromTimestamp;\n\n// Going up three levels is needed to escape the src-cov folder used for the\n// test coverage stuff.\nexports.sjcl = __webpack_require__(34);\nexports.jsbn = __webpack_require__(35);\n\n// vim:sw=2:sts=2:ts=8:et\n\n\n// WEBPACK FOOTER\n// module.id = 19\n// module.readableIdentifier = ./src/js/ripple/utils.js\n//@ sourceURL=webpack-module:///./src/js/ripple/utils.js");

/***/ },
/* 20 */
/***/ function(module, exports, __webpack_require__) {

	eval("var util         = __webpack_require__(38);\nvar url          = __webpack_require__(43);\nvar EventEmitter = __webpack_require__(37).EventEmitter;\nvar Amount       = __webpack_require__(3).Amount;\nvar log          = __webpack_require__(25).internal.sub('server');\n\n/**\n *  @constructor Server\n *\n *  @param {Remote} Reference to a Remote object\n *  @param {Object} Options\n *    @param {String} host\n *    @param {Number|String} port\n *    @param [Boolean] securec\n */\n\nfunction Server(remote, opts) {\n  EventEmitter.call(this);\n\n  var self = this;\n\n  if (typeof opts === 'string') {\n    var parsedUrl = url.parse(opts);\n    opts = {\n      host: parsedUrl.hostname,\n      port: parsedUrl.port,\n      secure: (parsedUrl.protocol === 'ws:') ? false : true\n    };\n  }\n\n  if (typeof opts !== 'object') {\n    throw new TypeError('Server configuration is not an Object');\n  }\n\n  if (!Server.domainRE.test(opts.host)) {\n    throw new Error('Server host is malformed, use \"host\" and \"port\" server configuration');\n  }\n\n  // We want to allow integer strings as valid port numbers for backward compatibility\n  if (!(opts.port = Number(opts.port))) {\n    throw new TypeError('Server port must be a number');\n  }\n\n  if (opts.port < 1 || opts.port > 65535) {\n    throw new TypeError('Server \"port\" must be an integer in range 1-65535');\n  }\n\n  if (typeof opts.secure !== 'boolean') {\n    opts.secure = true;\n  }\n\n  this._remote = remote;\n  this._opts = opts;\n  this._ws = void(0);\n\n  this._connected = false;\n  this._shouldConnect = false;\n  this._state = 'offline';\n\n  this._id = 0; // request ID\n  this._retry = 0;\n  this._requests = { };\n\n  this._load_base = 256;\n  this._load_factor = 256;\n\n  this._fee = 10;\n  this._fee_ref = 10;\n  this._fee_base = 10;\n  this._reserve_base = void(0);\n  this._reserve_inc = void(0);\n  this._fee_cushion = this._remote.fee_cushion;\n\n  this._lastLedgerIndex = NaN;\n  this._lastLedgerClose = NaN;\n\n  this._score = 0;\n  this._scoreWeights = {\n    ledgerclose: 5,\n    response: 1\n  };\n\n  this._pubkey_node = '';\n\n  this._url = this._opts.url = (this._opts.secure ? 'wss://' : 'ws://')\n      + this._opts.host + ':' + this._opts.port;\n\n  this.on('message', function onMessage(message) {\n    self._handleMessage(message);\n  });\n\n  this.on('response_subscribe', function onSubscribe(message) {\n    self._handleResponseSubscribe(message);\n  });\n\n  function setActivityInterval() {\n    var interval = self._checkActivity.bind(self);\n    self._activityInterval = setInterval(interval, 1000);\n  };\n\n  this.on('disconnect', function onDisconnect() {\n    clearInterval(self._activityInterval);\n    self.once('ledger_closed', setActivityInterval);\n  });\n\n  this.once('ledger_closed', setActivityInterval);\n\n  this._remote.on('ledger_closed', function onRemoteLedgerClose(ledger) {\n    self._updateScore('ledgerclose', ledger);\n  });\n\n  this.on('response_ping', function onPingResponse(message, request) {\n    self._updateScore('response', request);\n  });\n\n  this.on('load_changed', function onLoadChange(load) {\n    self._updateScore('loadchange', load);\n  });\n\n  // If server is not up-to-date, request server_info\n  // for getting pubkey_node & hostid information.\n  // Otherwise this information is available on the\n  // initial server subscribe response\n  this.on('connect', function requestServerID() {\n    if (self._pubkey_node) {\n      return;\n    }\n\n    self.on('response_server_info', function setServerID(message) {\n      try {\n        self._pubkey_node = message.info.pubkey_node;\n      } catch (e) {\n      }\n    });\n\n    var serverInfoRequest = self._remote.requestServerInfo();\n    serverInfoRequest.on('error', function() { });\n    self._request(serverInfoRequest);\n  });\n};\n\nutil.inherits(Server, EventEmitter);\n\nServer.domainRE = /^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|[-_]){0,61}[0-9A-Za-z])?(?:\\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|[-_]){0,61}[0-9A-Za-z])?)*\\.?$/;\n\n/**\n * Server states that we will treat as the server being online.\n *\n * Our requirements are that the server can process transactions and notify\n * us of changes.\n */\n\nServer.onlineStates = [\n  'syncing',\n  'tracking',\n  'proposing',\n  'validating',\n  'full'\n];\n\n/**\n * This is the final interface between client code and a socket connection to a\n * `rippled` server. As such, this is a decent hook point to allow a WebSocket\n * interface conforming object to be used as a basis to mock rippled. This\n * avoids the need to bind a websocket server to a port and allows a more\n * synchronous style of code to represent a client <-> server message sequence.\n * We can also use this to log a message sequence to a buffer.\n *\n * @api private\n */\n\nServer.websocketConstructor = function() {\n  // We require this late, because websocket shims may be loaded after\n  // ripple-lib in the browser\n  return __webpack_require__(36);\n};\n\n/**\n * Set server state\n *\n * @param {String} state\n * @api private\n */\n\nServer.prototype._setState = function(state) {\n  if (state !== this._state) {\n    if (this._remote.trace) {\n      log.info(this.getServerID(), 'set_state:', state);\n    }\n\n    this._state = state;\n    this.emit('state', state);\n\n    switch (state) {\n      case 'online':\n        this._connected = true;\n        this._retry = 0;\n        this.emit('connect');\n        break;\n      case 'offline':\n        this._connected = false;\n        this.emit('disconnect');\n        break;\n    }\n  }\n};\n\n/**\n * Check that server is still active.\n *\n * Server activity is determined by ledger_closed events.\n * Maximum delay to receive a ledger_closed event is 20s.\n *\n * If server is inactive, reconnect\n *\n * @api private\n */\n\nServer.prototype._checkActivity = function() {\n  if (!this.isConnected()) {\n    return;\n  }\n\n  if (isNaN(this._lastLedgerClose)) {\n    return;\n  }\n\n  var delta = (Date.now() - this._lastLedgerClose);\n\n  if (delta > (1000 * 25)) {\n    if (this._remote.trace) {\n      log.info(this.getServerID(), 'reconnect: activity delta:', delta);\n    }\n    this.reconnect();\n  }\n};\n\n/**\n * Server maintains a score for request prioritization.\n *\n * The score is determined by various data including\n * this server's lag to receive ledger_closed events,\n * ping response time, and load(fee) change\n *\n * @param {String} type\n * @param {Object} data\n * @api private\n */\n\nServer.prototype._updateScore = function(type, data) {\n  if (!this.isConnected()) {\n    return;\n  }\n\n  var weight = this._scoreWeights[type] || 1;\n\n  switch (type) {\n    case 'ledgerclose':\n      // Ledger lag\n      var delta = data.ledger_index - this._lastLedgerIndex;\n      if (delta > 0) {\n        this._score += weight * delta;\n      }\n      break;\n    case 'response':\n      // Ping lag\n      var delta = Math.floor((Date.now() - data.time) / 200);\n      this._score += weight * delta;\n      break;\n    case 'loadchange':\n      // Load/fee change\n      this._fee = Number(this._computeFee(10));\n      break;\n  }\n\n  if (this._score > 1e3) {\n    if (this._remote.trace) {\n      log.info(this.getServerID(), 'reconnect: score:', this._score);\n    }\n    this.reconnect();\n  }\n};\n\n/**\n * Get the server's remote address\n *\n * Incompatible with ripple-lib client build\n */\n\nServer.prototype.getRemoteAddress =\nServer.prototype._remoteAddress = function() {\n  var address;\n  try {\n    address = this._ws._socket.remoteAddress;\n  } catch (e) {\n  }\n  return address;\n};\n\n/**\n * Get the server's hostid\n */\n\nServer.prototype.getHostID =\nServer.prototype.getServerID = function() {\n  return this._url + ' (' + (this._pubkey_node ? this._pubkey_node : '') + ')';\n};\n\n/**\n * Disconnect from rippled WebSocket server\n *\n * @api public\n */\n\nServer.prototype.disconnect = function() {\n  var self = this;\n\n  if (!this.isConnected()) {\n    this.once('socket_open', function() {\n      self.disconnect();\n    });\n    return;\n  }\n\n  //these need to be reset so that updateScore \n  //and checkActivity do not trigger reconnect\n  this._lastLedgerIndex = NaN;\n  this._lastLedgerClose = NaN;\n  this._score = 0;\n  this._shouldConnect = false;\n  this._setState('offline');\n\n  if (this._ws) {\n    this._ws.close();\n  }\n};\n\n/**\n * Reconnect to rippled WebSocket server\n *\n * @api public\n */\n\nServer.prototype.reconnect = function() {\n  var self = this;\n\n  function reconnect() {\n    self._shouldConnect = true;\n    self._retry = 0;\n    self.connect();\n  };\n\n  if (this._ws && this._shouldConnect) {\n    if (this.isConnected()) {\n      this.once('disconnect', reconnect);\n      this.disconnect();\n    } else {\n      reconnect();\n    }\n  }\n};\n\n/**\n * Connect to rippled WebSocket server and subscribe to events that are\n * internally requisite. Automatically retry connections with a gradual\n * back-off\n *\n * @api public\n */\n\nServer.prototype.connect = function() {\n  var self = this;\n\n  var WebSocket = Server.websocketConstructor();\n\n  if (!WebSocket) {\n    throw new Error('No websocket support detected!');\n  }\n\n  // We don't connect if we believe we're already connected. This means we have\n  // recently received a message from the server and the WebSocket has not\n  // reported any issues either. If we do fail to ping or the connection drops,\n  // we will automatically reconnect.\n  if (this.isConnected()) {\n    return;\n  }\n\n  // Ensure any existing socket is given the command to close first.\n  if (this._ws) {\n    this._ws.close();\n  }\n\n  if (this._remote.trace) {\n    log.info(this.getServerID(), 'connect');\n  }\n\n  var ws = this._ws = new WebSocket(this._opts.url);\n\n  this._shouldConnect = true;\n\n  self.emit('connecting');\n\n  ws.onmessage = function onMessage(msg) {\n    self.emit('message', msg.data);\n  };\n\n  ws.onopen = function onOpen() {\n    if (ws === self._ws) {\n      self.emit('socket_open');\n      // Subscribe to events\n      self._request(self._remote._serverPrepareSubscribe(self));\n    }\n  };\n\n  ws.onerror = function onError(e) {\n    if (ws === self._ws) {\n      self.emit('socket_error');\n\n      if (self._remote.trace) {\n        log.info(self.getServerID(), 'onerror:',  e.data || e);\n      }\n\n      // Most connection errors for WebSockets are conveyed as 'close' events with\n      // code 1006. This is done for security purposes and therefore unlikely to\n      // ever change.\n\n      // This means that this handler is hardly ever called in practice. If it is,\n      // it probably means the server's WebSocket implementation is corrupt, or\n      // the connection is somehow producing corrupt data.\n\n      // Most WebSocket applications simply log and ignore this error. Once we\n      // support for multiple servers, we may consider doing something like\n      // lowering this server's quality score.\n\n      // However, in Node.js this event may be triggered instead of the close\n      // event, so we need to handle it.\n      self._handleClose();\n    }\n  };\n\n  ws.onclose = function onClose() {\n    if (ws === self._ws) {\n      if (self._remote.trace) {\n        log.info(self.getServerID(), 'onclose:', ws.readyState);\n      }\n      self._handleClose();\n    }\n  };\n};\n\n/**\n * Retry connection to rippled server\n *\n * @api private\n */\n\nServer.prototype._retryConnect = function() {\n  var self = this;\n\n  this._retry += 1;\n\n  var retryTimeout = (this._retry < 40)\n  // First, for 2 seconds: 20 times per second\n  ? (1000 / 20)\n  : (this._retry < 40 + 60)\n  // Then, for 1 minute: once per second\n  ? (1000)\n  : (this._retry < 40 + 60 + 60)\n  // Then, for 10 minutes: once every 10 seconds\n  ? (10 * 1000)\n  // Then: once every 30 seconds\n  : (30 * 1000);\n\n  function connectionRetry() {\n    if (self._shouldConnect) {\n      if (self._remote.trace) {\n        log.info(self.getServerID(), 'retry', self._retry);\n      }\n      self.connect();\n    }\n  };\n\n  this._retryTimer = setTimeout(connectionRetry, retryTimeout);\n};\n\n/**\n * Handle connection closes\n *\n * @api private\n */\n\nServer.prototype._handleClose = function() {\n  var self = this;\n  var ws = this._ws;\n\n  function noOp(){};\n\n  // Prevent additional events from this socket\n  ws.onopen = ws.onerror = ws.onclose = ws.onmessage = noOp;\n\n  this.emit('socket_close');\n  this._setState('offline');\n\n  if (this._shouldConnect) {\n    this._retryConnect();\n  }\n};\n\n/**\n * Handle incoming messages from rippled WebSocket server\n *\n * @param {JSON-parseable} message\n * @api private\n */\n\nServer.prototype._handleMessage = function(message) {\n  var self = this;\n\n  try {\n    message = JSON.parse(message);\n  } catch(e) {\n  }\n\n  if (!Server.isValidMessage(message)) {\n    this.emit('unexpected', message);\n    return;\n  }\n\n  switch (message.type) {\n    case 'ledgerClosed':\n      this._handleLedgerClosed(message);\n      break;\n    case 'serverStatus':\n      this._handleServerStatus(message);\n      break;\n    case 'response':\n      this._handleResponse(message);\n      break;\n    case 'path_find':\n      this._handlePathFind(message);\n      break;\n  }\n};\n\nServer.prototype._handleLedgerClosed = function(message) {\n  this._lastLedgerIndex = message.ledger_index;\n  this._lastLedgerClose = Date.now();\n  this.emit('ledger_closed', message);\n};\n\nServer.prototype._handleServerStatus = function(message) {\n  // This message is only received when online.\n  // As we are connected, it is the definitive final state.\n  var isOnline = ~Server.onlineStates.indexOf(message.server_status);\n\n  this._setState(isOnline ? 'online' : 'offline');\n\n  if (!Server.isLoadStatus(message)) {\n    return;\n  }\n\n  this.emit('load', message, this);\n  this._remote.emit('load', message, this);\n\n  var loadChanged = message.load_base !== this._load_base\n  || message.load_factor !== this._load_factor;\n\n  if (loadChanged) {\n    this._load_base = message.load_base;\n    this._load_factor = message.load_factor;\n    this.emit('load_changed', message, this);\n    this._remote.emit('load_changed', message, this);\n  }\n};\n\nServer.prototype._handleResponse = function(message) {\n  // A response to a request.\n  var request = this._requests[message.id];\n\n  delete this._requests[message.id];\n\n  if (!request) {\n    if (this._remote.trace) {\n      log.info(this.getServerID(), 'UNEXPECTED:', message);\n    }\n    return;\n  }\n\n  if (message.status === 'success') {\n    if (this._remote.trace) {\n      log.info(this.getServerID(), 'response:', message);\n    }\n\n    var command = request.message.command;\n    var result = message.result;\n    var responseEvent = 'response_' + command;\n\n    request.emit('success', result);\n\n    [ this, this._remote ].forEach(function(emitter) {\n      emitter.emit(responseEvent, result, request, message);\n    });\n  } else if (message.error) {\n    if (this._remote.trace) {\n      log.info(this.getServerID(), 'error:', message);\n    }\n\n    request.emit('error', {\n      error: 'remoteError',\n      error_message: 'Remote reported an error.',\n      remote: message\n    });\n  }\n};\n\nServer.prototype._handlePathFind = function(message) {\n  if (this._remote.trace) {\n    log.info(this.getServerID(), 'path_find:', message);\n  }\n};\n\n/**\n * Handle subscription response messages. Subscription response\n * messages indicate that a connection to the server is ready\n *\n * @param {Object} message\n * @api private\n */\n\nServer.prototype._handleResponseSubscribe = function(message) {\n  if (!this._remote._allow_partial_history\n      && !Server.hasFullLedgerHistory(message)) {\n    // Server has partial history and Remote has been configured to disallow\n    // servers with incomplete history\n    return this.reconnect();\n  }\n  if (message.pubkey_node) {\n    // pubkey_node is used to identify the server\n    this._pubkey_node = message.pubkey_node;\n  }\n  if (Server.isLoadStatus(message)) {\n    this._load_base = message.load_base || 256;\n    this._load_factor = message.load_factor || 256;\n    this._fee_ref = message.fee_ref || 10;\n    this._fee_base = message.fee_base || 10;\n    this._reserve_base = message.reserve_base;\n    this._reserve_inc = message.reserve_inc;\n  }\n  if (~Server.onlineStates.indexOf(message.server_status)) {\n    this._setState('online');\n  }\n};\n\n/**\n * Check that server message indicates that server has complete ledger history\n *\n * @param {Object} message\n * @return {Boolean}\n */\n\nServer.hasFullLedgerHistory = function(message) {\n  return (typeof message === 'object')\n  && (message.server_status === 'full')\n  && (typeof message.validated_ledgers === 'string')\n  && (message.validated_ledgers.split('-').length === 2);\n};\n\n/**\n * Check that received message from rippled is valid\n *\n * @param {Object} message\n * @return {Boolean}\n */\n\nServer.isValidMessage = function(message) {\n  return (typeof message === 'object')\n      && (typeof message.type === 'string');\n};\n\n/**\n * Check that received serverStatus message contains load status information\n *\n * @param {Object} message\n * @return {Boolean}\n */\n\nServer.isLoadStatus = function(message) {\n  return (typeof message === 'object')\n      && (typeof message.load_base === 'number')\n      && (typeof message.load_factor === 'number');\n};\n\n/**\n * Send JSON message to rippled WebSocket server\n *\n * @param {JSON-Stringifiable} message\n * @api private\n */\n\nServer.prototype._sendMessage = function(message) {\n  if (this._ws) {\n    if (this._remote.trace) {\n      log.info(this.getServerID(), 'request:', message);\n    }\n    this._ws.send(JSON.stringify(message));\n  }\n};\n\n/**\n * Submit a Request object\n *\n * Requests are indexed by message ID, which is repeated in the response from\n * rippled WebSocket server\n *\n * @param {Request} request\n * @api private\n */\n\nServer.prototype._request = function(request) {\n  var self  = this;\n\n  // Only bother if we are still connected.\n  if (!this._ws) {\n    if (this._remote.trace) {\n      log.info(this.getServerID(), 'request: DROPPING:', request.message);\n    }\n    return;\n  }\n\n  request.server = this;\n  request.message.id = this._id;\n  request.time = Date.now();\n\n  this._requests[request.message.id] = request;\n\n  // Advance message ID\n  this._id++;\n\n  function sendRequest() {\n    self._sendMessage(request.message);\n  };\n\n  var isOpen = this._ws.readyState === 1;\n  var isSubscribeRequest = request && request.message.command === 'subscribe';\n\n  if (this.isConnected() || (isOpen && isSubscribeRequest)) {\n    sendRequest();\n  } else {\n    this.once('connect', sendRequest);\n  }\n};\n\nServer.prototype.isConnected =\nServer.prototype._isConnected = function() {\n  return this._connected;\n};\n\n/**\n * Calculate transaction fee\n *\n * @param {Transaction|Number} Fee units for a provided transaction\n * @return {String} Final fee in XRP for specified number of fee units\n * @api private\n */\n\nServer.prototype._computeFee = function(feeUnits) {\n  if (isNaN(feeUnits)) {\n    throw new Error('Invalid argument');\n  }\n\n  return this._feeTx(Number(feeUnits)).to_json();\n};\n\n/**\n * Calculate a transaction fee for a number of tx fee units.\n *\n * This takes into account the last known network and local load fees.\n *\n * @param {Number} Fee units for a provided transaction\n * @return {Amount} Final fee in XRP for specified number of fee units.\n */\n\nServer.prototype._feeTx = function(units) {\n  var fee_unit = this._feeTxUnit();\n  return Amount.from_json(String(Math.ceil(units * fee_unit)));\n};\n\n/**\n * Get the current recommended transaction fee unit.\n *\n * Multiply this value with the number of fee units in order to calculate the\n * recommended fee for the transaction you are trying to submit.\n *\n * @return {Number} Recommended amount for one fee unit as float.\n */\n\nServer.prototype._feeTxUnit = function() {\n  var fee_unit = this._fee_base / this._fee_ref;\n\n  // Apply load fees\n  fee_unit *= this._load_factor / this._load_base;\n\n  // Apply fee cushion (a safety margin in case fees rise since we were last updated)\n  fee_unit *= this._fee_cushion;\n\n  return fee_unit;\n};\n\n/**\n * Get the current recommended reserve base.\n *\n * Returns the base reserve with load fees and safety margin applied.\n */\n\nServer.prototype._reserve = function(ownerCount) {\n  var reserve_base = Amount.from_json(String(this._reserve_base));\n  var reserve_inc  = Amount.from_json(String(this._reserve_inc));\n  var owner_count  = ownerCount || 0;\n\n  if (owner_count < 0) {\n    throw new Error('Owner count must not be negative.');\n  }\n\n  return reserve_base.add(reserve_inc.product_human(owner_count));\n};\n\nexports.Server = Server;\n\n// vim:sw=2:sts=2:ts=8:et\n\n\n// WEBPACK FOOTER\n// module.id = 20\n// module.readableIdentifier = ./src/js/ripple/server.js\n//@ sourceURL=webpack-module:///./src/js/ripple/server.js");

/***/ },
/* 21 */
/***/ function(module, exports, __webpack_require__) {

	eval("var sjcl = __webpack_require__(19).sjcl;\n\nvar WalletGenerator = __webpack_require__(49)({\n  sjcl: sjcl\n});\n\nmodule.exports = WalletGenerator;\n\n\n\n// WEBPACK FOOTER\n// module.id = 21\n// module.readableIdentifier = ./src/js/ripple/wallet.js\n//@ sourceURL=webpack-module:///./src/js/ripple/wallet.js");

/***/ },
/* 22 */
/***/ function(module, exports, __webpack_require__) {

	eval("// This object serves as a singleton to store config options\n\nvar extend = __webpack_require__(44);\n\nvar config = module.exports = {\n  load: function (newOpts) {\n    extend(config, newOpts);\n    return config;\n  }\n};\n\n\n// WEBPACK FOOTER\n// module.id = 22\n// module.readableIdentifier = ./src/js/ripple/config.js\n//@ sourceURL=webpack-module:///./src/js/ripple/config.js");

/***/ },
/* 23 */
/***/ function(module, exports, __webpack_require__) {

	eval("// Routines for working with an orderbook.\n//\n// One OrderBook object represents one half of an order book. (i.e. bids OR\n// asks) Which one depends on the ordering of the parameters.\n//\n// Events:\n//  - model\n//  - trade\n//  - transaction\n\nvar util         = __webpack_require__(38);\nvar extend       = __webpack_require__(44);\nvar assert       = __webpack_require__(39);\nvar async        = __webpack_require__(50);\nvar EventEmitter = __webpack_require__(37).EventEmitter;\nvar Amount       = __webpack_require__(3).Amount;\nvar UInt160      = __webpack_require__(8).UInt160;\nvar Currency     = __webpack_require__(6).Currency;\nvar log          = __webpack_require__(25).internal.sub('orderbook');\n\n/**\n * @constructor OrderBook\n * @param {Remote} remote\n * @param {String} ask currency\n * @param {String} ask issuer\n * @param {String} bid currency\n * @param {String} bid issuer\n * @param {String} orderbook key\n */\n\nfunction OrderBook(remote, getsC, getsI, paysC, paysI, key) {\n  EventEmitter.call(this);\n\n  var self = this;\n\n  this._remote = remote;\n  this._currencyGets = Currency.from_json(getsC);\n  this._issuerGets = getsI;\n  this._currencyPays = Currency.from_json(paysC);\n  this._issuerPays = paysI;\n  this._key = key;\n  this._subscribed = false;\n  this._shouldSubscribe = true;\n  this._listeners = 0;\n  this._offers = [ ];\n  this._ownerFunds = { };\n  this._offerCounts = { };\n\n  // We consider ourselves synchronized if we have a current\n  // copy of the offers, we are online and subscribed to updates.\n  this._synchronized = false;\n\n  function listenersModified(action, event) {\n    // Automatically subscribe and unsubscribe to orderbook\n    // on the basis of existing event listeners\n    if (~OrderBook.EVENTS.indexOf(event)) {\n      switch (action) {\n        case 'add':\n          if (++self._listeners === 1) {\n            self.subscribe();\n          }\n          break;\n        case 'remove':\n          if (--self._listeners === 0) {\n            self.unsubscribe();\n          }\n          break;\n      }\n    }\n  };\n\n  this.on('newListener', function(event) {\n    listenersModified('add', event);\n  });\n\n  this.on('removeListener', function(event) {\n    listenersModified('remove', event);\n  });\n\n  this.on('unsubscribe', function() {\n    self.resetCache();\n    self._remote.removeListener('transaction', updateFundedAmounts);\n    self._remote.removeListener('transaction', updateTransferRate);\n  });\n\n  this._remote.once('prepare_subscribe', function() {\n    self.subscribe();\n  });\n\n  this._remote.on('disconnect', function() {\n    self.resetCache();\n    self._remote.once('prepare_subscribe', function() {\n      self.subscribe();\n    });\n  });\n\n  function updateFundedAmounts(message) {\n    self.updateFundedAmounts(message);\n  };\n\n  this._remote.on('transaction', updateFundedAmounts);\n\n  function updateTransferRate(message) {\n    self.updateTransferRate(message);\n  };\n\n  this._remote.on('transaction', updateTransferRate);\n\n  return this;\n};\n\nutil.inherits(OrderBook, EventEmitter);\n\n/**\n * Events emitted from OrderBook\n */\n\nOrderBook.EVENTS = [ 'transaction', 'model', 'trade', 'offer' ];\n\nOrderBook.DEFAULT_TRANSFER_RATE = 1000000000;\n\n/**\n * Whether the OrderBook is valid.\n *\n * Note: This only checks whether the parameters (currencies and issuer) are\n *       syntactically valid. It does not check anything against the ledger.\n *\n * @return {Boolean} is valid\n */\n\nOrderBook.prototype.isValid =\nOrderBook.prototype.is_valid = function() {\n  // XXX Should check for same currency (non-native) && same issuer\n  return (\n    this._currencyPays && this._currencyPays.is_valid() &&\n    (this._currencyPays.is_native() || UInt160.is_valid(this._issuerPays)) &&\n    this._currencyGets && this._currencyGets.is_valid() &&\n    (this._currencyGets.is_native() || UInt160.is_valid(this._issuerGets)) &&\n    !(this._currencyPays.is_native() && this._currencyGets.is_native())\n  );\n};\n\n/**\n * Initialize orderbook. Get orderbook offers and subscribe to transactions\n */\n\nOrderBook.prototype.subscribe = function() {\n  var self = this;\n\n  if (!this._shouldSubscribe) {\n    return;\n  }\n\n  if (this._remote.trace) {\n    log.info('subscribing', this._key);\n  }\n\n  var steps = [\n    function(callback) {\n      self.requestTransferRate(callback);\n    },\n    function(callback) {\n      self.requestOffers(callback);\n    },\n    function(callback) {\n      self.subscribeTransactions(callback);\n    }\n  ];\n\n  async.series(steps, function(err) {\n    //XXX What now?\n  });\n};\n\n/**\n * Unhook event listeners and prevent ripple-lib from further work on this\n * orderbook. There is no more orderbook stream, so \"unsubscribe\" is nominal\n */\n\nOrderBook.prototype.unsubscribe = function() {\n  var self = this;\n\n  if (this._remote.trace) {\n    log.info('unsubscribing', this._key);\n  }\n\n  this._subscribed = false;\n  this._shouldSubscribe = false;\n\n  OrderBook.EVENTS.forEach(function(event) {\n    if (self.listeners(event).length > 0) {\n      self.removeAllListeners(event);\n    }\n  });\n\n  this.emit('unsubscribe');\n};\n\n/**\n * Reset cached owner funds, offer counts\n */\n\nOrderBook.prototype.resetCache = function() {\n  this._ownerFunds = { };\n  this._offerCounts = { };\n  this._synchronized = false;\n};\n\n/**\n * Check that the funds for offer owner have been cached\n *\n * @param {String} account address\n */\n\nOrderBook.prototype.hasCachedFunds = function(account) {\n  assert(UInt160.is_valid(account), 'Account is invalid');\n  return this._ownerFunds[account] !== void(0);\n};\n\n/**\n * Add cached offer owner funds\n *\n * @param {String} account address\n * @param {String} funded amount\n */\n\nOrderBook.prototype.addCachedFunds = function(account, fundedAmount) {\n  assert(UInt160.is_valid(account), 'Account is invalid');\n  assert(!isNaN(fundedAmount), 'Funded amount is invalid');\n  this._ownerFunds[account] = fundedAmount;\n};\n\n/**\n * Get cached offer owner funds\n *\n * @param {String} account address\n */\n\nOrderBook.prototype.getCachedFunds = function(account) {\n  assert(UInt160.is_valid(account), 'Account is invalid');\n  return this._ownerFunds[account];\n};\n\n/**\n * Remove cached offer owner funds\n *\n * @param {String} account address\n */\n\nOrderBook.prototype.removeCachedFunds = function(account) {\n  assert(UInt160.is_valid(account), 'Account is invalid');\n  this._ownerFunds[account] = void(0);\n};\n\n/**\n * Get offer count for offer owner\n */\n\nOrderBook.prototype.getOfferCount = function(account) {\n  assert(UInt160.is_valid(account), 'Account is invalid');\n  return this._offerCounts[account] || 0;\n};\n\n/**\n * Increment offer count for offer owner\n */\n\nOrderBook.prototype.incrementOfferCount = function(account) {\n  assert(UInt160.is_valid(account), 'Account is invalid');\n  var result = (this._offerCounts[account] || 0) + 1;\n  this._offerCounts[account] = result;\n  return result;\n};\n\n/**\n * Decrement offer count for offer owner\n */\n\nOrderBook.prototype.decrementOfferCount = function(account) {\n  assert(UInt160.is_valid(account), 'Account is invalid');\n  var result = (this._offerCounts[account] || 1) - 1;\n  this._offerCounts[account] = result;\n  return result;\n};\n\n/**\n * Compute funded amount for a balance/transferRate\n *\n * @param {String} balance\n * @param [String] transferRate\n * @return {Amount} funded amount\n */\n\nOrderBook.prototype.applyTransferRate = function(balance, transferRate) {\n  assert(!isNaN(balance), 'Balance is invalid');\n\n  if (this._currencyGets.is_native()) {\n    return balance;\n  }\n\n  if (transferRate === void(0)) {\n    transferRate = this._issuerTransferRate;\n  }\n\n  assert(!isNaN(transferRate), 'Transfer rate is invalid');\n\n  if (transferRate === OrderBook.DEFAULT_TRANSFER_RATE) {\n    return balance;\n  }\n\n  var iouSuffix = '/USD/rrrrrrrrrrrrrrrrrrrrBZbvji';\n  var adjustedBalance = Amount.from_json(balance + iouSuffix)\n  .divide(transferRate)\n  .multiply(Amount.from_json(OrderBook.DEFAULT_TRANSFER_RATE))\n  .to_json()\n  .value;\n\n  return adjustedBalance;\n};\n\n/**\n * Request transfer rate for this orderbook's issuer\n *\n * @param [Function] calback\n */\n\nOrderBook.prototype.requestTransferRate = function(callback) {\n  var self = this;\n  var issuer = this._issuerGets;\n\n  this.once('transfer_rate', function(rate) {\n    if (typeof callback === 'function') {\n      callback(null, rate);\n    }\n  });\n\n  if (this._currencyGets.is_native()) {\n    // Transfer rate is default\n    return this.emit('transfer_rate', OrderBook.DEFAULT_TRANSFER_RATE);\n  }\n\n  if (this._issuerTransferRate) {\n    // Transfer rate has been cached\n    return this.emit('transfer_rate', this._issuerTransferRate);\n  }\n\n  this._remote.requestAccountInfo({account: issuer}, function(err, info) {\n    if (err) {\n      // XXX What now?\n      return callback(err);\n    }\n\n    var transferRate = info.account_data.TransferRate\n    || OrderBook.DEFAULT_TRANSFER_RATE;\n\n    self._issuerTransferRate = transferRate;\n    self.emit('transfer_rate', transferRate);\n  });\n};\n\n/**\n * Set funded amount on offer. All offers have taker_gets_funded property,\n * which reflects the amount this account can afford to offer. All offers have\n * is_fully_funded property, indicating whether these funds are sufficient for\n * the offer placed.\n *\n * @param {Object} offer\n * @param {String} funds\n * @return offer\n */\n\nOrderBook.prototype.setFundedAmount = function(offer, fundedAmount) {\n  assert.strictEqual(typeof offer, 'object', 'Offer is invalid');\n  assert(!isNaN(fundedAmount), 'Funds is invalid');\n\n  if (fundedAmount === '0') {\n    offer.taker_gets_funded = '0';\n    offer.taker_pays_funded = '0';\n    offer.is_fully_funded = false;\n    return offer;\n  }\n\n  var iouSuffix = '/' + this._currencyGets.to_json()\n                + '/' + this._issuerGets;\n\n  offer.is_fully_funded = Amount.from_json(\n    this._currencyGets.is_native() ? fundedAmount : fundedAmount + iouSuffix\n  ).compareTo(Amount.from_json(offer.TakerGets)) >= 0;\n\n  if (offer.is_fully_funded) {\n    offer.taker_gets_funded = Amount.from_json(offer.TakerGets).to_text();\n    offer.taker_pays_funded = Amount.from_json(offer.TakerPays).to_text();\n    return offer;\n  }\n\n  offer.taker_gets_funded = fundedAmount;\n\n  var takerPaysValue = typeof offer.TakerPays === 'object'\n  ? offer.TakerPays.value\n  : offer.TakerPays;\n\n  var takerGetsValue = typeof offer.TakerGets === 'object'\n  ? offer.TakerGets.value\n  : offer.TakerGets;\n\n  var takerPays = Amount.from_json(\n    takerPaysValue + '/000/rrrrrrrrrrrrrrrrrrrrBZbvji'\n  );\n\n  var takerGets = Amount.from_json(\n    takerGetsValue + '/000/rrrrrrrrrrrrrrrrrrrrBZbvji'\n  );\n\n  var fundedPays = Amount.from_json(\n    fundedAmount + '/000/rrrrrrrrrrrrrrrrrrrrBZbvji'\n  );\n\n  var rate = takerPays.divide(takerGets);\n\n  fundedPays = fundedPays.multiply(rate);\n\n  if (fundedPays.compareTo(takerPays) < 0) {\n    offer.taker_pays_funded = fundedPays.to_json().value;\n  } else {\n    offer.taker_pays_funded = takerPays.to_json().value;\n  }\n\n  return offer;\n};\n\n/**\n * Determine what an account is funded to offer for orderbook's\n * currency/issuer\n *\n * @param {String} account\n * @param {Function} callback\n */\n\nOrderBook.prototype.requestFundedAmount = function(account, callback) {\n  assert(UInt160.is_valid(account), 'Account is invalid');\n  assert.strictEqual(typeof callback, 'function', 'Callback is invalid');\n\n  var self = this;\n\n  if (self._remote.trace) {\n    log.info('requesting funds', account);\n  }\n\n  function requestNativeBalance(callback) {\n    self._remote.requestAccountInfo({account: account}, function(err, info) {\n      if (err) {\n        callback(err);\n      } else {\n        callback(null, String(info.account_data.Balance));\n      }\n    });\n  };\n\n  function requestLineBalance(callback) {\n    var request = self._remote.requestAccountLines(\n      {\n        account: account,\n        ledger: 'validated',\n        peer: self._issuerGets\n      }\n    );\n\n    request.request(function(err, res) {\n      if (err) {\n        return callback(err);\n      }\n\n      var currency = self._currencyGets.to_json();\n      var balance = '0';\n\n      for (var i=0, line; (line=res.lines[i]); i++) {\n        if (line.currency === currency) {\n          balance = line.balance;\n          break;\n        }\n      }\n\n      callback(null, balance);\n    });\n  };\n\n  function computeFundedAmount(err, results) {\n    if (err) {\n      if (self._remote.trace) {\n        log.info('failed to request funds', err);\n      }\n      //XXX What now?\n      return callback(err);\n    }\n\n    if (self._remote.trace) {\n      log.info('requested funds', account, results);\n    }\n\n    var balance;\n    var fundedAmount;\n\n    if (self._currencyGets.is_native()) {\n      balance = results[0];\n      fundedAmount = balance;\n    } else {\n      balance = results[1];\n      fundedAmount = self.applyTransferRate(balance, results[0]);\n    }\n\n    callback(null, fundedAmount);\n  };\n\n  var steps = [ ];\n\n  if (this._currencyGets.is_native()) {\n    steps.push(requestNativeBalance);\n  } else {\n    steps.push(this.requestTransferRate.bind(this));\n    steps.push(requestLineBalance);\n  }\n\n  async.parallel(steps, computeFundedAmount);\n};\n\n/**\n * Get changed balance of an affected node\n *\n * @param {Object} RippleState or AccountRoot node\n * @return {Object} { account, balance }\n */\n\nOrderBook.prototype.getBalanceChange = function(node) {\n  var result = {\n    account: void(0),\n    balance: void(0)\n  };\n\n  switch (node.entryType) {\n    case 'AccountRoot':\n      result.account = node.fields.Account;\n      result.balance = node.fieldsFinal.Balance;\n      break;\n\n    case 'RippleState':\n      if (node.fields.HighLimit.issuer === this._issuerGets) {\n        result.account = node.fields.LowLimit.issuer;\n        result.balance = node.fieldsFinal.Balance.value;\n      } else if (node.fields.LowLimit.issuer === this._issuerGets) {\n        // Negate balance\n        result.account = node.fields.HighLimit.issuer;\n        result.balance = Amount.from_json(\n          node.fieldsFinal.Balance\n        ).negate().to_json().value;\n      }\n      break;\n  }\n\n  result.isValid = !isNaN(result.balance)\n                && UInt160.is_valid(result.account);\n\n  return result;\n};\n\n/**\n * Check that affected node represents a balance change\n *\n * @param {Object} RippleState or AccountRoot node\n * @return {Boolean}\n */\n\nOrderBook.prototype.isBalanceChange = function(node) {\n  // Check balance change\n  if (!(node.fields && node.fields.Balance\n  && node.fieldsPrev && node.fieldsFinal\n  && node.fieldsPrev.Balance && node.fieldsFinal.Balance)) {\n    return false;\n  }\n\n  // Check currency\n  if (this._currencyGets.is_native()) {\n    return !isNaN(node.fields.Balance);\n  }\n\n  if (node.fields.Balance.currency !== this._currencyGets.to_json()) {\n    return false;\n  }\n\n  // Check issuer\n  if (!(node.fields.HighLimit.issuer === this._issuerGets\n     || node.fields.LowLimit.issuer === this._issuerGets)) {\n     return false;\n   }\n\n   return true;\n};\n\n/**\n * Update funded amounts for offers in the orderbook as new transactions are\n * streamed from server\n *\n * @param {Object} transaction\n */\n\nOrderBook.prototype.updateFundedAmounts = function(message) {\n  var self = this;\n\n  var affectedAccounts = message.mmeta.getAffectedAccounts();\n\n  var isOwnerAffected = affectedAccounts.some(function(account) {\n    return self.hasCachedFunds(account);\n  });\n\n  if (!isOwnerAffected) {\n    return;\n  }\n\n  if (!this._currencyGets.is_native() && !this._issuerTransferRate) {\n    // Defer until transfer rate is requested\n    if (self._remote.trace) {\n      log.info('waiting for transfer rate');\n    }\n\n    this.once('transfer_rate', function() {\n      self.updateFundedAmounts(message);\n    });\n\n    this.requestTransferRate();\n    return;\n  }\n\n  var nodes = message.mmeta.getNodes({\n    nodeType: 'ModifiedNode',\n    entryType: this._currencyGets.is_native() ? 'AccountRoot' : 'RippleState'\n  });\n\n  for (var i=0; i<nodes.length; i++) {\n    var node = nodes[i];\n\n    if (!this.isBalanceChange(node)) {\n      continue;\n    }\n\n    var result = this.getBalanceChange(node);\n\n    if (result.isValid) {\n      if (this.hasCachedFunds(result.account)) {\n        this.updateOfferFunds(result.account, result.balance);\n      }\n    }\n  }\n};\n\n/**\n * Update issuer's TransferRate as it changes\n *\n * @param {Object} transaction\n */\n\nOrderBook.prototype.updateTransferRate = function(message) {\n  var self = this;\n\n  var affectedAccounts = message.mmeta.getAffectedAccounts();\n\n  var isIssuerAffected = affectedAccounts.some(function(account) {\n    return account === self._issuerGets;\n  });\n\n  if (!isIssuerAffected) {\n    return;\n  }\n\n  // XXX Update transfer rate\n  //\n  //  var nodes = message.mmeta.getNodes({\n  //    nodeType: 'ModifiedNode',\n  //    entryType: 'AccountRoot'\n  //  });\n};\n\n/**\n * Request orderbook entries from server\n */\n\nOrderBook.prototype.requestOffers = function(callback) {\n  var self = this;\n\n  if (typeof callback !== 'function') {\n    callback = function(){};\n  }\n\n  if (!this._shouldSubscribe) {\n    return callback(new Error('Should not request offers'));\n  }\n\n  if (this._remote.trace) {\n    log.info('requesting offers', this._key);\n  }\n\n  function handleOffers(res) {\n    if (!Array.isArray(res.offers)) {\n      // XXX What now?\n      return callback(new Error('Invalid response'));\n    }\n\n    if (self._remote.trace) {\n      log.info('requested offers', self._key, 'offers: ' + res.offers.length);\n    }\n\n    // Reset offers\n    self._offers = [ ];\n\n    for (var i=0, l=res.offers.length; i<l; i++) {\n      var offer = res.offers[i];\n      var fundedAmount;\n\n      if (self.hasCachedFunds(offer.Account)) {\n        fundedAmount = self.getCachedFunds(offer.Account);\n      } else if (offer.hasOwnProperty('owner_funds')) {\n        fundedAmount = self.applyTransferRate(offer.owner_funds);\n        self.addCachedFunds(offer.Account, fundedAmount);\n      }\n\n      self.setFundedAmount(offer, fundedAmount);\n      self.incrementOfferCount(offer.Account);\n      self._offers.push(offer);\n    }\n\n    self._synchronized = true;\n\n    self.emit('model', self._offers);\n\n    callback(null, self._offers);\n  };\n\n  function handleError(err) {\n    // XXX What now?\n    if (self._remote.trace) {\n      log.info('failed to request offers', self._key, err);\n    }\n\n    callback(err);\n  };\n\n  var request = this._remote.requestBookOffers(this.toJSON());\n  request.once('success', handleOffers);\n  request.once('error', handleError);\n  request.request();\n\n  return request;\n};\n\n/**\n * Subscribe to transactions stream\n */\n\nOrderBook.prototype.subscribeTransactions = function(callback) {\n  var self = this;\n\n  if (typeof callback !== 'function') {\n    callback = function(){};\n  }\n\n  if (!this._shouldSubscribe) {\n    return callback('Should not subscribe');\n  }\n\n  if (this._remote.trace) {\n    log.info('subscribing to transactions');\n  }\n\n  function handleSubscribed(res) {\n    if (self._remote.trace) {\n      log.info('subscribed to transactions');\n    }\n\n    self._subscribed = true;\n\n    callback(null, res);\n  };\n\n  function handleError(err) {\n    if (self._remote.trace) {\n      log.info('failed to subscribe to transactions', self._key, err);\n    }\n\n    callback(err);\n  };\n\n  var request = this._remote.requestSubscribe();\n  request.addStream('transactions');\n  request.once('success', handleSubscribed);\n  request.once('error', handleError);\n  request.request();\n\n  return request;\n};\n\n/**\n * Get offers model asynchronously.\n *\n * This function takes a callback and calls it with an array containing the\n * current set of offers in this order book.\n *\n * If the data is available immediately, the callback may be called\n * synchronously.\n *\n * @param {Function} callback\n */\n\nOrderBook.prototype.offers =\nOrderBook.prototype.getOffers = function(callback) {\n  assert.strictEqual(typeof callback, 'function', 'Callback missing');\n\n  var self = this;\n\n  if (this._synchronized) {\n    callback(null, this._offers);\n  } else {\n    this.once('model', function(m) {\n      callback(null, m);\n    });\n  }\n\n  return this;\n};\n\n/**\n * Return latest known offers\n *\n * Usually, this will just be an empty array if the order book hasn't been\n * loaded yet. But this accessor may be convenient in some circumstances.\n *\n * @return {Array} offers\n */\n\nOrderBook.prototype.offersSync =\nOrderBook.prototype.getOffersSync = function() {\n  return this._offers;\n};\n\n/**\n * Insert an offer into the orderbook\n *\n * @param {Object} node\n */\n\nOrderBook.prototype.insertOffer = function(node, fundedAmount) {\n  if (this._remote.trace) {\n    log.info('inserting offer', this._key, node.fields);\n  }\n\n  var nodeFields = node.fields;\n\n  nodeFields.index = node.ledgerIndex;\n\n  if (!isNaN(fundedAmount)) {\n    this.setFundedAmount(nodeFields, fundedAmount);\n    this.addCachedFunds(nodeFields.Account, fundedAmount);\n  }\n\n  var DATE_REF = {\n    reference_date: new Date()\n  };\n\n  // XXX Should use Amount#from_quality\n  var price = Amount.from_json(\n    nodeFields.TakerPays\n  ).ratio_human(node.fields.TakerGets, DATE_REF);\n\n  for (var i=0, l=this._offers.length; i<l; i++) {\n    var offer = this._offers[i];\n\n    var priceItem = Amount.from_json(\n      offer.TakerPays\n    ).ratio_human(offer.TakerGets, DATE_REF);\n\n    if (price.compareTo(priceItem) <= 0) {\n      this._offers.splice(i, 0, nodeFields);\n      break;\n    } else if (i === (l - 1)) {\n      this._offers.push(nodeFields);\n    }\n  }\n\n  this.emit('offer_added', nodeFields);\n};\n\n/**\n * Modify an existing offer in the orderbook\n *\n * @param {Object} node\n * @param {Boolean} isDeletedNode\n */\n\nOrderBook.prototype.modifyOffer = function(node, isDeletedNode) {\n  if (this._remote.trace) {\n    if (isDeletedNode) {\n      log.info('deleting offer', this._key, node.fields);\n    } else {\n      log.info('modifying offer', this._key, node.fields);\n    }\n  }\n\n  for (var i=0; i<this._offers.length; i++) {\n    var offer = this._offers[i];\n    if (offer.index === node.ledgerIndex) {\n      if (isDeletedNode) {\n        // Multiple offers same account?\n        this._offers.splice(i, 1);\n        this.emit('offer_removed', offer);\n      } else {\n        // TODO: This assumes no fields are deleted, which is\n        // probably a safe assumption, but should be checked.\n        var previousOffer = extend({}, offer);\n        extend(offer, node.fieldsFinal);\n        this.emit('offer_changed', previousOffer, offer);\n      }\n      break;\n    }\n  }\n};\n\n/**\n * Update funded status on offers whose account's balance has changed\n *\n * Update cached account funds\n *\n * @param {String} account address\n * @param {String|Object} offer funds\n */\n\nOrderBook.prototype.updateOfferFunds = function(account, balance) {\n  assert(UInt160.is_valid(account), 'Account is invalid');\n  assert(!isNaN(balance), 'Funded amount is invalid');\n\n  if (this._remote.trace) {\n    log.info('updating offer funds', this._key, account, fundedAmount);\n  }\n\n  var fundedAmount = this.applyTransferRate(balance);\n\n  // Update cached account funds\n  this.addCachedFunds(account, fundedAmount);\n\n  for (var i=0; i<this._offers.length; i++) {\n    var offer = this._offers[i];\n\n    if (offer.Account !== account) {\n      continue;\n    }\n\n    var suffix = '/USD/rrrrrrrrrrrrrrrrrrrrBZbvji';\n    var previousOffer = extend({}, offer);\n    var previousFundedGets = Amount.from_json(offer.taker_gets_funded + suffix);\n\n    offer.owner_funds = balance;\n    this.setFundedAmount(offer, fundedAmount);\n\n    var hasChangedFunds = !previousFundedGets.equals(\n      Amount.from_json(offer.taker_gets_funded + suffix)\n    );\n\n    if (hasChangedFunds) {\n      this.emit('offer_changed', previousOffer, offer);\n      this.emit(\n        'offer_funds_changed', offer,\n        previousOffer.taker_gets_funded,\n        offer.taker_gets_funded\n      );\n    }\n  }\n};\n\n/**\n * Notify orderbook of a relevant transaction\n *\n * @param {Object} transaction\n * @api private\n */\n\nOrderBook.prototype.notify = function(message) {\n  var self = this;\n\n  // Unsubscribed from OrderBook\n  if (!this._subscribed) {\n    return;\n  }\n\n  var affectedNodes = message.mmeta.getNodes({\n    entryType: 'Offer',\n    bookKey: this._key\n  });\n\n  if (affectedNodes.length < 1) {\n    return;\n  }\n\n  if (this._remote.trace) {\n    log.info('notifying', this._key, message.transaction.hash);\n  }\n\n  var tradeGets = Amount.from_json(\n    '0' + ((Currency.from_json(this._currencyGets).is_native())\n           ? ''\n           : ('/' + this._currencyGets + '/' + this._issuerGets))\n  );\n\n  var tradePays = Amount.from_json(\n    '0' + ((Currency.from_json(this._currencyPays).is_native())\n           ? ''\n           : ('/' + this._currencyPays + '/' + this._issuerPays))\n  );\n\n  function handleNode(node, callback) {\n    var isDeletedNode = node.nodeType === 'DeletedNode';\n    var isOfferCancel = message.transaction.TransactionType === 'OfferCancel';\n\n    switch (node.nodeType) {\n      case 'DeletedNode':\n      case 'ModifiedNode':\n         self.modifyOffer(node, isDeletedNode);\n\n        // We don't want to count an OfferCancel as a trade\n        if (!isOfferCancel) {\n          tradeGets = tradeGets.add(node.fieldsPrev.TakerGets);\n          tradePays = tradePays.add(node.fieldsPrev.TakerPays);\n\n          if (isDeletedNode) {\n            if (self.decrementOfferCount(node.fields.Account) < 1) {\n              self.removeCachedFunds(node.fields.Account);\n            }\n          } else {\n            tradeGets = tradeGets.subtract(node.fieldsFinal.TakerGets);\n            tradePays = tradePays.subtract(node.fieldsFinal.TakerPays);\n          }\n        }\n        callback();\n        break;\n\n      case 'CreatedNode':\n        self.incrementOfferCount(node.fields.Account);\n\n        var fundedAmount = message.transaction.owner_funds;\n\n        if (!isNaN(fundedAmount)) {\n          self.insertOffer(node, fundedAmount);\n          return callback();\n        }\n\n        // Get the offer account's balance from server\n        self.requestFundedAmount(\n          node.fields.Account, function(err, fundedAmount) {\n          if (err) {\n            // XXX Now what?\n          } else {\n            self.insertOffer(node, fundedAmount);\n          }\n          callback();\n        });\n        break;\n    }\n  };\n\n  async.eachSeries(affectedNodes, handleNode, function() {\n    self.emit('transaction', message);\n    self.emit('model', self._offers);\n    if (!tradeGets.is_zero()) {\n      self.emit('trade', tradePays, tradeGets);\n    }\n  });\n};\n\n/**\n * Get request-representation of orderbook\n *\n * @return {Object} json\n */\n\nOrderBook.prototype.toJSON =\nOrderBook.prototype.to_json = function() {\n  var json = {\n    taker_gets: {\n      currency: this._currencyGets.to_hex()\n    },\n    taker_pays: {\n      currency: this._currencyPays.to_hex()\n    }\n  };\n\n  if (!this._currencyGets.is_native()) {\n    json.taker_gets.issuer = this._issuerGets;\n  }\n\n  if (!this._currencyPays.is_native()) {\n    json.taker_pays.issuer = this._issuerPays;\n  }\n\n  return json;\n};\n\nexports.OrderBook = OrderBook;\n\n// vim:sw=2:sts=2:ts=8:et\n\n\n// WEBPACK FOOTER\n// module.id = 23\n// module.readableIdentifier = ./src/js/ripple/orderbook.js\n//@ sourceURL=webpack-module:///./src/js/ripple/orderbook.js");

/***/ },
/* 24 */
/***/ function(module, exports, __webpack_require__) {

	eval("var EventEmitter = __webpack_require__(37).EventEmitter;\nvar util         = __webpack_require__(38);\nvar Amount       = __webpack_require__(3).Amount;\nvar extend       = __webpack_require__(44);\n\n/**\n * Represents a persistent path finding request.\n *\n * Only one path find request is allowed per connection, so when another path\n * find request is triggered it will supercede the existing one, making it emit\n * the 'end' and 'superceded' events.\n */\nfunction PathFind(remote, src_account, dst_account, dst_amount, src_currencies) {\n  EventEmitter.call(this);\n\n  this.remote = remote;\n\n  this.src_account    = src_account;\n  this.dst_account    = dst_account;\n  this.dst_amount     = dst_amount;\n  this.src_currencies = src_currencies;\n};\n\nutil.inherits(PathFind, EventEmitter);\n\n/**\n * Submits a path_find_create request to the network.\n *\n * This starts a path find request, superceding all previous path finds.\n *\n * This will be called automatically by Remote when this object is instantiated,\n * so you should only have to call it if the path find was closed or superceded\n * and you wish to restart it.\n */\nPathFind.prototype.create = function () {\n  var self = this;\n\n  var req = this.remote.request_path_find_create(this.src_account,\n                                                 this.dst_account,\n                                                 this.dst_amount,\n                                                 this.src_currencies,\n                                                 handleInitialPath);\n\n  function handleInitialPath(err, msg) {\n    if (err) {\n      self.emit('error', err);\n    } else {\n      self.notify_update(msg);\n    }\n  }\n\n  // XXX We should add ourselves to prepare_subscribe or a similar mechanism so\n  // that we can resubscribe after a reconnection.\n\n  req.request();\n};\n\nPathFind.prototype.close = function () {\n  this.remote.request_path_find_close().request();\n  this.emit('end');\n  this.emit('close');\n};\n\nPathFind.prototype.notify_update = function (message) {\n  var src_account = message.source_account;\n  var dst_account = message.destination_account;\n  var dst_amount  = Amount.from_json(message.destination_amount);\n\n  // Only pass the event along if this path find response matches what we were\n  // looking for.\n  if (this.src_account === src_account &&\n      this.dst_account === dst_account &&\n      this.dst_amount.equals(dst_amount)) {\n    this.emit('update', message);\n  }\n};\n\nPathFind.prototype.notify_superceded = function () {\n  // XXX If we're set to re-subscribe whenever we connect to a new server, then\n  // we should cancel that behavior here. See PathFind#create.\n\n  this.emit('end');\n  this.emit('superceded');\n};\n\nexports.PathFind = PathFind;\n\n\n// WEBPACK FOOTER\n// module.id = 24\n// module.readableIdentifier = ./src/js/ripple/pathfind.js\n//@ sourceURL=webpack-module:///./src/js/ripple/pathfind.js");

/***/ },
/* 25 */
/***/ function(module, exports, __webpack_require__) {

	eval("var exports = module.exports = __webpack_require__(40);\n\n/**\n * Log engine for browser consoles.\n *\n * Browsers tend to have better consoles that support nicely formatted\n * JavaScript objects. This connector passes objects through to the logging\n * function without any stringification.\n */\nvar InteractiveLogEngine = {\n  logObject: function (msg, obj) {\n    var args = Array.prototype.slice.call(arguments, 1);\n\n    args = args.map(function(arg) {\n      if (/MSIE/.test(navigator.userAgent)) {\n        return JSON.stringify(arg, null, 2);\n      } else {\n        return arg;\n      }\n    });\n\n    args.unshift(msg);\n    args.unshift('[' + new Date().toISOString() + ']');\n\n    console.log.apply(console, args);\n  }\n};\n\nif (window.console && window.console.log) {\n  exports.Log.engine = InteractiveLogEngine;\n}\n\n\n// WEBPACK FOOTER\n// module.id = 25\n// module.readableIdentifier = ./src/js/ripple/log.web.js\n//@ sourceURL=webpack-module:///./src/js/ripple/log.web.js");

/***/ },
/* 26 */
/***/ function(module, exports, __webpack_require__) {

	eval("var util         = __webpack_require__(38);\nvar EventEmitter = __webpack_require__(37).EventEmitter;\nvar Transaction  = __webpack_require__(5).Transaction;\nvar RippleError  = __webpack_require__(13).RippleError;\nvar PendingQueue = __webpack_require__(45).TransactionQueue;\nvar log          = __webpack_require__(25).internal.sub('transactionmanager');\n\n/**\n * @constructor TransactionManager\n * @param {Account} account\n */\n\nfunction TransactionManager(account) {\n  EventEmitter.call(this);\n\n  var self = this;\n\n  this._account           = account;\n  this._accountID         = account._account_id;\n  this._remote            = account._remote;\n  this._nextSequence      = void(0);\n  this._maxFee            = this._remote.max_fee;\n  this._maxAttempts       = this._remote.max_attempts;\n  this._submissionTimeout = this._remote._submission_timeout;\n  this._pending           = new PendingQueue();\n\n  // Query remote server for next account sequence number\n  this._loadSequence();\n\n  function transactionReceived(res) {\n    var transaction = TransactionManager.normalizeTransaction(res);\n    var sequence    = transaction.tx_json.Sequence;\n    var hash        = transaction.tx_json.hash;\n\n    if (!transaction.validated) {\n      return;\n    }\n\n    self._pending.addReceivedSequence(sequence);\n\n    // ND: we need to check against all submissions IDs\n    var submission = self._pending.getSubmission(hash);\n\n    if (self._remote.trace) {\n      log.info('transaction received:', transaction.tx_json);\n    }\n\n    if (submission instanceof Transaction) {\n\n      // ND: A `success` handler will `finalize` this later\n      switch (transaction.engine_result) {\n        case 'tesSUCCESS':\n          submission.emit('success', transaction);\n          break;\n        default:\n          submission.emit('error', transaction);\n      }\n\n    } else {\n      self._pending.addReceivedId(hash, transaction);\n    }\n  };\n\n  this._account.on('transaction-outbound', transactionReceived);\n\n  this._remote.on('load_changed', this._adjustFees.bind(this));\n\n  function updatePendingStatus(ledger) {\n    self._pending.forEach(function(pending) {\n      switch (ledger.ledger_index - pending.submitIndex) {\n        case 8:\n          pending.emit('lost', ledger);\n          break;\n        case 4:\n          pending.emit('missing', ledger);\n          break;\n      }\n    });\n  };\n\n  this._remote.on('ledger_closed', updatePendingStatus);\n\n  function remoteReconnected(callback) {\n    var callback = (typeof callback === 'function') ? callback : function(){};\n\n    if (!self._pending.length) {\n      return callback();\n    }\n\n    //Load account transaction history\n    var options = {\n      account: self._accountID,\n      ledger_index_min: -1,\n      ledger_index_max: -1,\n      binary: true,\n      parseBinary: true,\n      limit: 100,\n      filter: 'outbound'\n    };\n\n    function accountTx(err, transactions) {\n      if (!err && Array.isArray(transactions.transactions)) {\n        transactions.transactions.forEach(transactionReceived);\n      }\n\n      self._remote.on('ledger_closed', updatePendingStatus);\n\n      //Load next transaction sequence\n      self._loadSequence(self._resubmit.bind(self));\n\n      callback();\n    };\n\n    self._remote.requestAccountTx(options, accountTx);\n\n    self.emit('reconnect');\n  };\n\n  function remoteDisconnected() {\n    self._remote.once('connect', remoteReconnected);\n    self._remote.removeListener('ledger_closed', updatePendingStatus);\n  };\n\n  this._remote.on('disconnect', remoteDisconnected);\n\n  function saveTransaction(transaction) {\n    self._remote.storage.saveTransaction(transaction.summary());\n  };\n\n  if (this._remote.storage) {\n    this.on('save', saveTransaction);\n  }\n};\n\nutil.inherits(TransactionManager, EventEmitter);\n\n//Normalize transactions received from account\n//transaction stream and account_tx\nTransactionManager.normalizeTransaction = function(tx) {\n  var transaction = { };\n\n  Object.keys(tx).forEach(function(key) {\n    transaction[key] = tx[key];\n  });\n\n  if (!tx.engine_result) {\n    // account_tx\n    transaction = {\n      engine_result:  tx.meta.TransactionResult,\n      tx_json:        tx.tx,\n      hash:           tx.tx.hash,\n      ledger_index:   tx.tx.ledger_index,\n      meta:           tx.meta,\n      type:           'transaction',\n      validated:      true\n    };\n\n    transaction.result = transaction.engine_result;\n    transaction.result_message = transaction.engine_result_message;\n  }\n\n  if (!transaction.metadata) {\n    transaction.metadata = transaction.meta;\n  }\n\n  if (!transaction.tx_json) {\n    transaction.tx_json = transaction.transaction;\n  }\n\n  delete transaction.transaction;\n  delete transaction.mmeta;\n  delete transaction.meta;\n\n  return transaction;\n};\n\n// Transaction fees are adjusted in real-time\nTransactionManager.prototype._adjustFees = function(loadData) {\n  // ND: note, that `Fee` is a component of a transactionID\n  var self = this;\n\n  if (!this._remote.local_fee) {\n    return;\n  }\n\n  this._pending.forEach(function(pending) {\n    var oldFee = pending.tx_json.Fee;\n    var newFee = pending._computeFee();\n\n    function maxFeeExceeded() {\n      pending.once('presubmit', function() {\n        pending.emit('error', 'tejMaxFeeExceeded');\n      });\n    };\n\n    if (Number(newFee) > self._maxFee) {\n      return maxFeeExceeded();\n    }\n\n    pending.tx_json.Fee = newFee;\n    pending.emit('fee_adjusted', oldFee, newFee);\n\n    if (self._remote.trace) {\n      log.info('fee adjusted:', pending.tx_json, oldFee, newFee);\n    }\n  });\n};\n\n//Fill an account transaction sequence\nTransactionManager.prototype._fillSequence = function(tx, callback) {\n  var self = this;\n\n  function submitFill(sequence, callback) {\n    var fill = self._remote.transaction();\n    fill.account_set(self._accountID);\n    fill.tx_json.Sequence = sequence;\n    fill.once('submitted', callback);\n\n    // Secrets may be set on a per-transaction basis\n    if (tx._secret) {\n      fill.secret(tx._secret);\n    }\n\n    fill.submit();\n  };\n\n  function sequenceLoaded(err, sequence) {\n    if (typeof sequence !== 'number') {\n      return callback(new Error('Failed to fetch account transaction sequence'));\n    }\n\n    var sequenceDif = tx.tx_json.Sequence - sequence;\n    var submitted = 0;\n\n    ;(function nextFill(sequence) {\n      if (sequence >= tx.tx_json.Sequence) {\n        return;\n      }\n\n      submitFill(sequence, function() {\n        if (++submitted === sequenceDif) {\n          callback();\n        } else {\n          nextFill(sequence + 1);\n        }\n      });\n    })(sequence);\n  };\n\n  this._loadSequence(sequenceLoaded);\n};\n\nTransactionManager.prototype._loadSequence = function(callback) {\n  var self = this;\n\n  function sequenceLoaded(err, sequence) {\n    if (typeof sequence === 'number') {\n      self._nextSequence = sequence;\n      self.emit('sequence_loaded', sequence);\n      if (typeof callback === 'function') {\n        callback(err, sequence);\n      }\n    } else {\n      setTimeout(function() {\n        self._loadSequence(callback);\n      }, 1000 * 3);\n    }\n  };\n\n  this._account.getNextSequence(sequenceLoaded);\n};\n\nTransactionManager.prototype._resubmit = function(ledgers, pending) {\n  var self = this;\n  var pending = pending ? [ pending ] : this._pending;\n  var ledgers = Number(ledgers) || 0;\n\n  function resubmitTransaction(pending) {\n    if (!pending || pending.finalized) {\n      // Transaction has been finalized, nothing to do\n      return;\n    }\n\n    var hashCached = pending.findId(self._pending._idCache);\n\n    if (self._remote.trace) {\n      log.info('resubmit:', pending.tx_json);\n    }\n\n    if (hashCached) {\n      return pending.emit('success', hashCached);\n    }\n\n    while (self._pending.hasSequence(pending.tx_json.Sequence)) {\n      //Sequence number has been consumed by another transaction\n      pending.tx_json.Sequence += 1;\n\n      if (self._remote.trace) {\n        log.info('incrementing sequence:', pending.tx_json);\n      }\n    }\n\n    self._request(pending);\n  };\n\n  function resubmitTransactions() {\n    ;(function nextTransaction(i) {\n      var transaction = pending[i];\n\n      if (!(transaction instanceof Transaction)) {\n        return;\n      }\n\n      transaction.once('submitted', function(m) {\n        transaction.emit('resubmitted', m);\n\n        self._loadSequence();\n\n        if (++i < pending.length) {\n          nextTransaction(i);\n        }\n      });\n\n      resubmitTransaction(transaction);\n    })(0);\n  };\n\n  this._waitLedgers(ledgers, resubmitTransactions);\n};\n\nTransactionManager.prototype._waitLedgers = function(ledgers, callback) {\n  if (ledgers < 1) {\n    return callback();\n  }\n\n  var self = this;\n  var closes = 0;\n\n  function ledgerClosed() {\n    if (++closes < ledgers) {\n      return;\n    }\n\n    self._remote.removeListener('ledger_closed', ledgerClosed);\n\n    callback();\n  };\n\n  this._remote.on('ledger_closed', ledgerClosed);\n};\n\nTransactionManager.prototype._request = function(tx) {\n  var self   = this;\n  var remote = this._remote;\n\n  if (tx.attempts > this._maxAttempts) {\n    return tx.emit('error', new RippleError('tejAttemptsExceeded'));\n  }\n\n  if (tx.attempts > 0 && !remote.local_signing) {\n    var message = ''\n    + 'It is not possible to resubmit transactions automatically safely without '\n    + 'synthesizing the transactionID locally. See `local_signing` config option';\n\n    return tx.emit('error', new RippleError('tejLocalSigningRequired', message));\n  }\n\n  if (tx.finalized) {\n    return;\n  }\n\n  if (remote.trace) {\n    log.info('submit transaction:', tx.tx_json);\n  }\n\n  function transactionProposed(message) {\n    if (tx.finalized) {\n      return;\n    }\n\n    // If server is honest, don't expect a final if rejected.\n    message.rejected = tx.isRejected(message.engine_result_code);\n\n    tx.emit('proposed', message);\n  };\n\n  function transactionFailed(message) {\n    if (tx.finalized) {\n      return;\n    }\n\n    switch (message.engine_result) {\n      case 'tefPAST_SEQ':\n        self._resubmit(1, tx);\n        break;\n      case 'tefALREADY':\n        if (tx.responses === tx.submissions) {\n          tx.emit('error', message);\n        } else {\n          submitRequest.once('success', submitted);\n        }\n        break;\n      default:\n        tx.emit('error', message);\n    }\n  };\n\n  function transactionRetry(message) {\n    if (tx.finalized) {\n      return;\n    }\n\n    self._fillSequence(tx, function() {\n      self._resubmit(1, tx);\n    });\n  };\n\n  function transactionFeeClaimed(message) {\n    if (tx.finalized) {\n      return;\n    }\n  };\n\n  function transactionFailedLocal(message) {\n    if (tx.finalized) {\n      return;\n    }\n\n    if (self._remote.local_fee && (message.engine_result === 'telINSUF_FEE_P')) {\n      self._resubmit(2, tx);\n    } else {\n      submissionError(message);\n    }\n  };\n\n  function submissionError(error) {\n    // Finalized (e.g. aborted) transactions must stop all activity\n    if (tx.finalized) {\n      return;\n    }\n\n    if (TransactionManager._isTooBusy(error)) {\n      self._resubmit(1, tx);\n    } else {\n      self._nextSequence--;\n      tx.emit('error', error);\n    }\n  };\n\n  function submitted(message) {\n    // Finalized (e.g. aborted) transactions must stop all activity\n    if (tx.finalized) {\n      return;\n    }\n\n    // ND: If for some unknown reason our hash wasn't computed correctly this is\n    // an extra measure.\n    if (message.tx_json && message.tx_json.hash) {\n      tx.addId(message.tx_json.hash);\n    }\n\n    message.result = message.engine_result || '';\n\n    tx.result = message;\n    tx.responses += 1;\n\n    if (remote.trace) {\n      log.info('submit response:', message);\n    }\n\n    tx.emit('submitted', message);\n\n    switch (message.result.slice(0, 3)) {\n      case 'tes':\n        transactionProposed(message);\n        break;\n      case 'tec':\n        transactionFeeClaimed(message);\n        break;\n      case 'ter':\n        transactionRetry(message);\n        break;\n      case 'tef':\n        transactionFailed(message);\n        break;\n      case 'tel':\n        transactionFailedLocal(message);\n        break;\n      default:\n        // tem\n        submissionError(message);\n    }\n  };\n\n  var submitRequest = remote.requestSubmit();\n\n  submitRequest.once('error', submitted);\n  submitRequest.once('success', submitted);\n\n  function prepareSubmit() {\n    if (remote.local_signing) {\n      // TODO: We are serializing twice, when we could/should be feeding the\n      // tx_blob to `tx.hash()` which rebuilds it to sign it.\n      submitRequest.tx_blob(tx.serialize().to_hex());\n\n      // ND: ecdsa produces a random `TxnSignature` field value, a component of\n      // the hash. Attempting to identify a transaction via a hash synthesized\n      // locally while using remote signing is inherently flawed.\n      tx.addId(tx.hash());\n    } else {\n      // ND: `build_path` is completely ignored when doing local signing as\n      // `Paths` is a component of the signed blob, the `tx_blob` is signed,\n      // sealed and delivered, and the txn unmodified.\n      // TODO: perhaps an exception should be raised if build_path is attempted\n      // while local signing\n      submitRequest.build_path(tx._build_path);\n      submitRequest.secret(tx._secret);\n      submitRequest.tx_json(tx.tx_json);\n    }\n\n    if (tx._server) {\n      submitRequest.server = tx._server;\n    }\n\n    submitTransaction();\n  };\n\n  function requestTimeout() {\n    // ND: What if the response is just slow and we get a response that\n    // `submitted` above will cause to have concurrent resubmit logic streams?\n    // It's simpler to just mute handlers and look out for finalized\n    // `transaction` messages.\n\n    // ND: We should audit the code for other potential multiple resubmit\n    // streams. Connection/reconnection could be one? That's why it's imperative\n    // that ALL transactionIDs sent over network are tracked.\n\n    // Finalized (e.g. aborted) transactions must stop all activity\n    if (tx.finalized) {\n      return;\n    }\n\n    tx.emit('timeout');\n\n    if (remote._connected) {\n      if (remote.trace) {\n        log.info('timeout:', tx.tx_json);\n      }\n      self._resubmit(3, tx);\n    }\n  };\n\n  function submitTransaction() {\n    if (tx.finalized) {\n      return;\n    }\n\n    tx.emit('presubmit');\n\n    submitRequest.timeout(self._submissionTimeout, requestTimeout);\n\n    tx.submissions = submitRequest.broadcast();\n    tx.attempts++;\n    tx.emit('postsubmit');\n  };\n\n  tx.submitIndex = this._remote._ledger_current_index;\n\n  if (tx.attempts === 0) {\n    tx.initialSubmitIndex = tx.submitIndex;\n  }\n\n  if (!tx._setLastLedger) {\n    // Honor LastLedgerSequence set by user of API. If\n    // left unset by API, bump LastLedgerSequence\n    tx.tx_json.LastLedgerSequence = tx.submitIndex + 8;\n  }\n\n  tx.lastLedgerSequence = tx.tx_json.LastLedgerSequence;\n\n  if (remote.local_signing) {\n    tx.sign(prepareSubmit);\n  } else {\n    prepareSubmit();\n  }\n\n  return submitRequest;\n};\n\nTransactionManager._isNoOp = function(transaction) {\n  return (typeof transaction === 'object')\n      && (typeof transaction.tx_json === 'object')\n      && (transaction.tx_json.TransactionType === 'AccountSet')\n      && (transaction.tx_json.Flags === 0);\n};\n\nTransactionManager._isRemoteError = function(error) {\n  return (typeof error === 'object')\n      && (error.error === 'remoteError')\n      && (typeof error.remote === 'object');\n};\n\nTransactionManager._isNotFound = function(error) {\n  return TransactionManager._isRemoteError(error)\n      && /^(txnNotFound|transactionNotFound)$/.test(error.remote.error);\n};\n\nTransactionManager._isTooBusy = function(error) {\n  return TransactionManager._isRemoteError(error)\n      && (error.remote.error === 'tooBusy');\n};\n\n/**\n * Entry point for TransactionManager submission\n *\n * @param {Transaction} tx\n */\n\nTransactionManager.prototype.submit = function(tx) {\n  var self = this;\n  var remote = this._remote;\n\n  // If sequence number is not yet known, defer until it is.\n  if (typeof this._nextSequence !== 'number') {\n    this.once('sequence_loaded', this.submit.bind(this, tx));\n    return;\n  }\n\n  // Finalized (e.g. aborted) transactions must stop all activity\n  if (tx.finalized) {\n    return;\n  }\n\n  function cleanup(message) {\n    // ND: We can just remove this `tx` by identity\n    self._pending.remove(tx);\n    tx.emit('final', message);\n    if (remote.trace) {\n      log.info('transaction finalized:', tx.tx_json, self._pending.getLength());\n    }\n  };\n\n  tx.once('cleanup', cleanup);\n\n  tx.on('save', function() {\n    self.emit('save', tx);\n  });\n\n  tx.once('error', function(message) {\n    tx._errorHandler(message);\n  });\n\n  tx.once('success', function(message) {\n    tx._successHandler(message);\n  });\n\n  tx.once('abort', function() {\n    tx.emit('error', new RippleError('tejAbort', 'Transaction aborted'));\n  });\n\n  if (typeof tx.tx_json.Sequence !== 'number') {\n    tx.tx_json.Sequence = this._nextSequence++;\n  }\n\n  // Attach secret, associate transaction with a server, attach fee.\n  // If the transaction can't complete, decrement sequence so that\n  // subsequent transactions\n  if (!tx.complete()) {\n    this._nextSequence--;\n    return;\n  }\n\n  tx.attempts = 0;\n  tx.submissions = 0;\n  tx.responses = 0;\n\n  // ND: this is the ONLY place we put the tx into the queue. The\n  // TransactionQueue queue is merely a list, so any mutations to tx._hash\n  // will cause subsequent look ups (eg. inside 'transaction-outbound'\n  // validated transaction clearing) to fail.\n  this._pending.push(tx);\n  this._request(tx);\n};\n\nexports.TransactionManager = TransactionManager;\n\n\n// WEBPACK FOOTER\n// module.id = 26\n// module.readableIdentifier = ./src/js/ripple/transactionmanager.js\n//@ sourceURL=webpack-module:///./src/js/ripple/transactionmanager.js");

/***/ },
/* 27 */
/***/ function(module, exports, __webpack_require__) {

	eval("/**\n * Prefix for hashing functions.\n *\n * These prefixes are inserted before the source material used to\n * generate various hashes. This is done to put each hash in its own\n * \"space.\" This way, two different types of objects with the\n * same binary data will produce different hashes.\n *\n * Each prefix is a 4-byte value with the last byte set to zero\n * and the first three bytes formed from the ASCII equivalent of\n * some arbitrary string. For example \"TXN\".\n */\n\n// transaction plus signature to give transaction ID\nexports.HASH_TX_ID           = 0x54584E00; // 'TXN'\n// transaction plus metadata\nexports.HASH_TX_NODE         = 0x534E4400; // 'TND'\n// inner node in tree\nexports.HASH_INNER_NODE      = 0x4D494E00; // 'MIN'\n// leaf node in tree\nexports.HASH_LEAF_NODE       = 0x4D4C4E00; // 'MLN'\n// inner transaction to sign\nexports.HASH_TX_SIGN         = 0x53545800; // 'STX'\n// inner transaction to sign (TESTNET)\nexports.HASH_TX_SIGN_TESTNET = 0x73747800; // 'stx'\n\n\n// WEBPACK FOOTER\n// module.id = 27\n// module.readableIdentifier = ./src/js/ripple/hashprefixes.js\n//@ sourceURL=webpack-module:///./src/js/ripple/hashprefixes.js");

/***/ },
/* 28 */
/***/ function(module, exports, __webpack_require__) {

	eval("// Convert a JavaScript number to IEEE-754 Double Precision\n// value represented as an array of 8 bytes (octets)\n//\n// Based on:\n// http://cautionsingularityahead.blogspot.com/2010/04/javascript-and-ieee754-redux.html\n//\n// Found and modified from:\n// https://gist.github.com/bartaz/1119041\n\nvar Float = exports.Float = {};\n\nFloat.toIEEE754 = function(v, ebits, fbits) {\n\n  var bias = (1 << (ebits - 1)) - 1;\n\n  // Compute sign, exponent, fraction\n  var s, e, f;\n  if (isNaN(v)) {\n    e = (1 << bias) - 1; f = 1; s = 0;\n  }\n  else if (v === Infinity || v === -Infinity) {\n    e = (1 << bias) - 1; f = 0; s = (v < 0) ? 1 : 0;\n  }\n  else if (v === 0) {\n    e = 0; f = 0; s = (1 / v === -Infinity) ? 1 : 0;\n  }\n  else {\n    s = v < 0;\n    v = Math.abs(v);\n\n    if (v >= Math.pow(2, 1 - bias)) {\n      var ln = Math.min(Math.floor(Math.log(v) / Math.LN2), bias);\n      e = ln + bias;\n      f = v * Math.pow(2, fbits - ln) - Math.pow(2, fbits);\n    }\n    else {\n      e = 0;\n      f = v / Math.pow(2, 1 - bias - fbits);\n    }\n  }\n\n  // Pack sign, exponent, fraction\n  var i, bits = [];\n  for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = Math.floor(f / 2); }\n  for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = Math.floor(e / 2); }\n  bits.push(s ? 1 : 0);\n  bits.reverse();\n  var str = bits.join('');\n\n  // Bits to bytes\n  var bytes = [];\n  while (str.length) {\n    bytes.push(parseInt(str.substring(0, 8), 2));\n    str = str.substring(8);\n  }\n  return bytes;\n}\n\nFloat.fromIEEE754 = function(bytes, ebits, fbits) {\n\n  // Bytes to bits\n  var bits = [];\n  for (var i = bytes.length; i; i -= 1) {\n    var byte = bytes[i - 1];\n    for (var j = 8; j; j -= 1) {\n      bits.push(byte % 2 ? 1 : 0); byte = byte >> 1;\n    }\n  }\n  bits.reverse();\n  var str = bits.join('');\n\n  // Unpack sign, exponent, fraction\n  var bias = (1 << (ebits - 1)) - 1;\n  var s = parseInt(str.substring(0, 1), 2) ? -1 : 1;\n  var e = parseInt(str.substring(1, 1 + ebits), 2);\n  var f = parseInt(str.substring(1 + ebits), 2);\n\n  // Produce number\n  if (e === (1 << ebits) - 1) {\n    return f !== 0 ? NaN : s * Infinity;\n  }\n  else if (e > 0) {\n    return s * Math.pow(2, e - bias) * (1 + f / Math.pow(2, fbits));\n  }\n  else if (f !== 0) {\n    return s * Math.pow(2, -(bias-1)) * (f / Math.pow(2, fbits));\n  }\n  else {\n    return s * 0;\n  }\n}\n\nFloat.fromIEEE754Double = function(b) { return Float.fromIEEE754(b, 11, 52); }\nFloat.toIEEE754Double = function(v) { return   Float.toIEEE754(v, 11, 52); }\nFloat.fromIEEE754Single = function(b) { return Float.fromIEEE754(b,  8, 23); }\nFloat.toIEEE754Single = function(v) { return   Float.toIEEE754(v,  8, 23); }\n\n\n// Convert array of octets to string binary representation\n// by bartaz\n\nFloat.toIEEE754DoubleString = function(v) {\n  return exports.toIEEE754Double(v)\n    .map(function(n){ for(n = n.toString(2);n.length < 8;n=\"0\"+n); return n })\n    .join('')\n    .replace(/(.)(.{11})(.{52})/, \"$1 $2 $3\")\n}\n\n// WEBPACK FOOTER\n// module.id = 28\n// module.readableIdentifier = ./src/js/ripple/ieee754.js\n//@ sourceURL=webpack-module:///./src/js/ripple/ieee754.js");

/***/ },
/* 29 */
/***/ function(module, exports, __webpack_require__) {

	eval("var utils   = __webpack_require__(19);\nvar sjcl    = utils.sjcl;\nvar config  = __webpack_require__(22);\n\nvar BigInteger = utils.jsbn.BigInteger;\n\n//\n// Abstract UInt class\n//\n// Base class for UInt classes\n//\n\nvar UInt = function() {\n  // Internal form: NaN or BigInteger\n  this._value  = NaN;\n\n  this._update();\n};\n\nUInt.json_rewrite = function(j, opts) {\n  return this.from_json(j).to_json(opts);\n};\n\n// Return a new UInt from j.\nUInt.from_generic = function(j) {\n  if (j instanceof this) {\n    return j.clone();\n  } else {\n    return (new this()).parse_generic(j);\n  }\n};\n\n// Return a new UInt from j.\nUInt.from_hex = function(j) {\n  if (j instanceof this) {\n    return j.clone();\n  } else {\n    return (new this()).parse_hex(j);\n  }\n};\n\n// Return a new UInt from j.\nUInt.from_json = function(j) {\n  if (j instanceof this) {\n    return j.clone();\n  } else {\n    return (new this()).parse_json(j);\n  }\n};\n\n// Return a new UInt from j.\nUInt.from_bits = function(j) {\n  if (j instanceof this) {\n    return j.clone();\n  } else {\n    return (new this()).parse_bits(j);\n  }\n};\n\n// Return a new UInt from j.\nUInt.from_bytes = function(j) {\n  if (j instanceof this) {\n    return j.clone();\n  } else {\n    return (new this()).parse_bytes(j);\n  }\n};\n\n// Return a new UInt from j.\nUInt.from_bn = function(j) {\n  if (j instanceof this) {\n    return j.clone();\n  } else {\n    return (new this()).parse_bn(j);\n  }\n};\n\n// Return a new UInt from j.\nUInt.from_number = function(j) {\n  if (j instanceof this) {\n    return j.clone();\n  } else {\n    return (new this()).parse_number(j);\n  }\n};\n\nUInt.is_valid = function(j) {\n  return this.from_json(j).is_valid();\n};\n\nUInt.prototype.clone = function() {\n  return this.copyTo(new this.constructor());\n};\n\n// Returns copy.\nUInt.prototype.copyTo = function(d) {\n  d._value = this._value;\n\n  if (typeof d._update === 'function') {\n    d._update();\n  }\n\n  return d;\n};\n\nUInt.prototype.equals = function(d) {\n  return this._value instanceof BigInteger && d._value instanceof BigInteger && this._value.equals(d._value);\n};\n\nUInt.prototype.is_valid = function() {\n  return this._value instanceof BigInteger;\n};\n\nUInt.prototype.is_zero = function() {\n  return this._value.equals(BigInteger.ZERO);\n};\n\n/**\n * Update any derivative values.\n *\n * This allows subclasses to maintain caches of any data that they derive from\n * the main _value. For example, the Currency class keeps the currency type, the\n * currency code and other information about the currency cached.\n *\n * The reason for keeping this mechanism in this class is so every subclass can\n * call it whenever it modifies the internal state.\n */\nUInt.prototype._update = function() {\n  // Nothing to do by default. Subclasses will override this.\n};\n\n// value = NaN on error.\nUInt.prototype.parse_generic = function(j) {\n  // Canonicalize and validate\n  if (config.accounts && (j in config.accounts)) {\n    j = config.accounts[j].account;\n  }\n\n  switch (j) {\n    case undefined:\n      case '0':\n      case this.constructor.STR_ZERO:\n      case this.constructor.ACCOUNT_ZERO:\n      case this.constructor.HEX_ZERO:\n      this._value  = BigInteger.valueOf();\n      break;\n\n    case '1':\n      case this.constructor.STR_ONE:\n      case this.constructor.ACCOUNT_ONE:\n      case this.constructor.HEX_ONE:\n      this._value  = new BigInteger([1]);\n      break;\n\n    default:\n        if (typeof j !== 'string') {\n          this._value  = NaN;\n        } else if (this.constructor.width === j.length) {\n          this._value  = new BigInteger(utils.stringToArray(j), 256);\n        } else if ((this.constructor.width * 2) === j.length) {\n          // XXX Check char set!\n          this._value  = new BigInteger(j, 16);\n        } else {\n          this._value  = NaN;\n        }\n  }\n\n  this._update();\n\n  return this;\n};\n\nUInt.prototype.parse_hex = function(j) {\n  if (typeof j === 'string' && j.length === (this.constructor.width * 2)) {\n    this._value = new BigInteger(j, 16);\n  } else {\n    this._value = NaN;\n  }\n\n  this._update();\n\n  return this;\n};\n\nUInt.prototype.parse_bits = function(j) {\n  if (sjcl.bitArray.bitLength(j) !== this.constructor.width * 8) {\n    this._value = NaN;\n  } else {\n    var bytes = sjcl.codec.bytes.fromBits(j);\n    this.parse_bytes(bytes);\n  }\n\n  this._update();\n\n  return this;\n};\n\n\nUInt.prototype.parse_bytes = function(j) {\n  if (!Array.isArray(j) || j.length !== this.constructor.width) {\n    this._value = NaN;\n  } else {\n    this._value  = new BigInteger([0].concat(j), 256);\n  }\n\n  this._update();\n\n  return this;\n};\n\n\nUInt.prototype.parse_json = UInt.prototype.parse_hex;\n\nUInt.prototype.parse_bn = function(j) {\n  if ((j instanceof sjcl.bn) && j.bitLength() <= this.constructor.width * 8) {\n    var bytes = sjcl.codec.bytes.fromBits(j.toBits());\n    this._value  = new BigInteger(bytes, 256);\n  } else {\n    this._value = NaN;\n  }\n\n  this._update();\n\n  return this;\n};\n\nUInt.prototype.parse_number = function(j) {\n  this._value = NaN;\n\n  if (typeof j === 'number' && isFinite(j) && j >= 0) {\n    this._value = new BigInteger(String(j));\n  }\n\n  this._update();\n\n  return this;\n};\n\n// Convert from internal form.\nUInt.prototype.to_bytes = function() {\n  if (!(this._value instanceof BigInteger)) {\n    return null;\n  }\n\n  var bytes  = this._value.toByteArray();\n\n  bytes = bytes.map(function(b) {\n    return (b + 256) % 256;\n  });\n\n  var target = this.constructor.width;\n\n  // XXX Make sure only trim off leading zeros.\n  bytes = bytes.slice(-target);\n\n  while (bytes.length < target) {\n    bytes.unshift(0);\n  }\n\n  return bytes;\n};\n\nUInt.prototype.to_hex = function() {\n  if (!(this._value instanceof BigInteger)) {\n    return null;\n  }\n\n  var bytes = this.to_bytes();\n  return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(bytes)).toUpperCase();\n};\n\nUInt.prototype.to_json = UInt.prototype.to_hex;\n\nUInt.prototype.to_bits = function() {\n  if (!(this._value instanceof BigInteger)) {\n    return null;\n  }\n\n  var bytes = this.to_bytes();\n\n  return sjcl.codec.bytes.toBits(bytes);\n};\n\nUInt.prototype.to_bn = function() {\n  if (!(this._value instanceof BigInteger)) {\n    return null;\n  }\n\n  var bits = this.to_bits();\n\n  return sjcl.bn.fromBits(bits);\n};\n\nexports.UInt = UInt;\n\n// vim:sw=2:sts=2:ts=8:et\n\n\n// WEBPACK FOOTER\n// module.id = 29\n// module.readableIdentifier = ./src/js/ripple/uint.js\n//@ sourceURL=webpack-module:///./src/js/ripple/uint.js");

/***/ },
/* 30 */
/***/ function(module, exports, __webpack_require__) {

	eval("var sjcl    = __webpack_require__(19).sjcl;\n\nvar UInt160 = __webpack_require__(8).UInt160;\nvar UInt256 = __webpack_require__(9).UInt256;\nvar Base    = __webpack_require__(7).Base;\n\nfunction KeyPair() {\n  this._curve  = sjcl.ecc.curves.c256;\n  this._secret = null;\n  this._pubkey = null;\n};\n\nKeyPair.from_bn_secret = function(j) {\n  return (j instanceof this) ? j.clone() : (new this()).parse_bn_secret(j);\n};\n\nKeyPair.prototype.parse_bn_secret = function(j) {\n  this._secret = new sjcl.ecc.ecdsa.secretKey(sjcl.ecc.curves.c256, j);\n  return this;\n};\n\n/**\n * Returns public key as sjcl public key.\n *\n * @private\n */\nKeyPair.prototype._pub = function() {\n  var curve = this._curve;\n\n  if (!this._pubkey && this._secret) {\n    var exponent = this._secret._exponent;\n    this._pubkey = new sjcl.ecc.ecdsa.publicKey(curve, curve.G.mult(exponent));\n  }\n\n  return this._pubkey;\n};\n\n/**\n * Returns public key in compressed format as bit array.\n *\n * @private\n */\nKeyPair.prototype._pub_bits = function() {\n  var pub = this._pub();\n\n  if (!pub) {\n    return null;\n  }\n\n  var point = pub._point, y_even = point.y.mod(2).equals(0);\n\n  return sjcl.bitArray.concat(\n    [sjcl.bitArray.partial(8, y_even ? 0x02 : 0x03)],\n    point.x.toBits(this._curve.r.bitLength())\n  );\n};\n\n/**\n * Returns public key as hex.\n *\n * Key will be returned as a compressed pubkey - 33 bytes converted to hex.\n */\nKeyPair.prototype.to_hex_pub = function() {\n  var bits = this._pub_bits();\n\n  if (!bits) {\n    return null;\n  }\n\n  return sjcl.codec.hex.fromBits(bits).toUpperCase();\n};\n\nfunction SHA256_RIPEMD160(bits) {\n  return sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits));\n}\n\nKeyPair.prototype.get_address = function() {\n  var bits = this._pub_bits();\n\n  if (!bits) {\n    return null;\n  }\n\n  var hash = SHA256_RIPEMD160(bits);\n\n  var address = UInt160.from_bits(hash);\n  address.set_version(Base.VER_ACCOUNT_ID);\n  return address;\n};\n\nKeyPair.prototype.sign = function(hash) {\n  hash = UInt256.from_json(hash);\n  var sig = this._secret.sign(hash.to_bits(), 0);\n  sig = this._secret.canonicalizeSignature(sig);\n  return this._secret.encodeDER(sig);\n};\n\nexports.KeyPair = KeyPair;\n\n\n// WEBPACK FOOTER\n// module.id = 30\n// module.readableIdentifier = ./src/js/ripple/keypair.js\n//@ sourceURL=webpack-module:///./src/js/ripple/keypair.js");

/***/ },
/* 31 */
/***/ function(module, exports, __webpack_require__) {

	eval("/**\n * Type definitions for binary format.\n *\n * This file should not be included directly. Instead, find the format you're\n * trying to parse or serialize in binformat.js and pass that to\n * SerializedObject.parse() or SerializedObject.serialize().\n */\n\nvar assert    = __webpack_require__(39);\nvar extend    = __webpack_require__(44);\nvar binformat = __webpack_require__(18);\nvar utils     = __webpack_require__(19);\nvar sjcl      = utils.sjcl;\n\nvar UInt128   = __webpack_require__(46).UInt128;\nvar UInt160   = __webpack_require__(8).UInt160;\nvar UInt256   = __webpack_require__(9).UInt256;\nvar Base      = __webpack_require__(7).Base;\n\nvar amount    = __webpack_require__(3);\nvar Amount    = amount.Amount;\nvar Currency  = amount.Currency;\n\n// Shortcuts\nvar hex = sjcl.codec.hex;\nvar bytes = sjcl.codec.bytes;\n\nvar BigInteger = utils.jsbn.BigInteger;\n\n\nvar SerializedType = function (methods) {\n  extend(this, methods);\n};\n\nfunction isNumber(val) {\n  return typeof val === 'number' && isFinite(val);\n};\n\nfunction isString(val) {\n  return typeof val === 'string';\n};\n\nfunction isHexInt64String(val) {\n  return isString(val) && /^[0-9A-F]{0,16}$/i.test(val);\n};\n\nfunction isCurrencyString(val) {\n  return isString(val) && /^[A-Z0-9]{3}$/.test(val);\n};\n\nfunction isBigInteger(val) {\n  return val instanceof BigInteger;\n};\n\nfunction serialize_hex(so, hexData, noLength) {\n  var byteData = bytes.fromBits(hex.toBits(hexData));\n  if (!noLength) {\n    SerializedType.serialize_varint(so, byteData.length);\n  }\n  so.append(byteData);\n};\n\n/**\n * parses bytes as hex\n */\nfunction convert_bytes_to_hex (byte_array) {\n  return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(byte_array)).toUpperCase();\n};\n\nSerializedType.serialize_varint = function (so, val) {\n  if (val < 0) {\n    throw new Error('Variable integers are unsigned.');\n  }\n\n  if (val <= 192) {\n    so.append([val]);\n  } else if (val <= 12480) {\n    val -= 193;\n    so.append([193 + (val >>> 8), val & 0xff]);\n  } else if (val <= 918744) {\n    val -= 12481;\n    so.append([ 241 + (val >>> 16), val >>> 8 & 0xff, val & 0xff ]);\n  } else {\n    throw new Error('Variable integer overflow.');\n  }\n};\n\nSerializedType.prototype.parse_varint = function (so) {\n  var b1 = so.read(1)[0], b2, b3;\n  var result;\n\n  if (b1 > 254) {\n    throw new Error('Invalid varint length indicator');\n  }\n\n  if (b1 <= 192) {\n    result = b1;\n  } else if (b1 <= 240) {\n    b2 = so.read(1)[0];\n    result = 193 + (b1 - 193) * 256 + b2;\n  } else if (b1 <= 254) {\n    b2 = so.read(1)[0];\n    b3 = so.read(1)[0];\n    result = 12481 + (b1 - 241) * 65536 + b2 * 256 + b3;\n  }\n\n  return result;\n};\n\n// In the following, we assume that the inputs are in the proper range. Is this correct?\n// Helper functions for 1-, 2-, and 4-byte integers.\n\n/**\n * Convert an integer value into an array of bytes.\n *\n * The result is appended to the serialized object ('so').\n */\nfunction append_byte_array(so, val, bytes) {\n  if (!isNumber(val)) {\n    throw new Error('Value is not a number', bytes);\n  }\n\n  if (val < 0 || val >= Math.pow(256, bytes)) {\n    throw new Error('Value out of bounds');\n  }\n\n  var newBytes = [ ];\n\n  for (var i=0; i<bytes; i++) {\n    newBytes.unshift(val >>> (i * 8) & 0xff);\n  }\n\n  so.append(newBytes);\n};\n\n// Convert a certain number of bytes from the serialized object ('so') into an integer.\nfunction readAndSum(so, bytes) {\n  var sum = 0;\n\n  if (bytes > 4) {\n    throw new Error('This function only supports up to four bytes.');\n  }\n\n  for (var i=0; i<bytes; i++) {\n    var byte = so.read(1)[0];\n    sum += (byte << (8 * (bytes - i - 1)));\n  }\n\n  // Convert to unsigned integer\n  return sum >>> 0;\n};\n\nvar STInt8 = exports.Int8 = new SerializedType({\n  serialize: function (so, val) {\n    append_byte_array(so, val, 1);\n  },\n  parse: function (so) {\n    return readAndSum(so, 1);\n  }\n});\n\nSTInt8.id = 16;\n\nvar STInt16 = exports.Int16 = new SerializedType({\n  serialize: function (so, val) {\n    append_byte_array(so, val, 2);\n  },\n  parse: function (so) {\n    return readAndSum(so, 2);\n  }\n});\n\nSTInt16.id = 1;\n\nvar STInt32 = exports.Int32 = new SerializedType({\n  serialize: function (so, val) {\n    append_byte_array(so, val, 4);\n  },\n  parse: function (so) {\n    return readAndSum(so, 4);\n  }\n});\n\nSTInt32.id = 2;\n\nvar STInt64 = exports.Int64 = new SerializedType({\n  serialize: function (so, val) {\n    var bigNumObject;\n\n    if (isNumber(val)) {\n      val = Math.floor(val);\n      if (val < 0) {\n        throw new Error('Negative value for unsigned Int64 is invalid.');\n      }\n      bigNumObject = new BigInteger(String(val), 10);\n    } else if (isString(val)) {\n      if (!isHexInt64String(val)) {\n        throw new Error('Not a valid hex Int64.');\n      }\n      bigNumObject = new BigInteger(val, 16);\n    } else if (isBigInteger(val)) {\n      if (val.compareTo(BigInteger.ZERO) < 0) {\n        throw new Error('Negative value for unsigned Int64 is invalid.');\n      }\n      bigNumObject = val;\n    } else {\n      throw new Error('Invalid type for Int64');\n    }\n\n    var hex = bigNumObject.toString(16);\n\n    if (hex.length > 16) {\n      throw new Error('Int64 is too large');\n    }\n\n    while (hex.length < 16) {\n      hex = '0' + hex;\n    }\n\n    serialize_hex(so, hex, true); //noLength = true\n  },\n  parse: function (so) {\n    var bytes = so.read(8);\n    // We need to add a 0, so if the high bit is set it won't think it's a\n    // pessimistic numeric fraek. What doth lief?\n    var result = new BigInteger([0].concat(bytes), 256);\n    assert(result instanceof BigInteger);\n    return result;\n  }\n});\n\nSTInt64.id = 3;\n\nvar STHash128 = exports.Hash128 = new SerializedType({\n  serialize: function (so, val) {\n    var hash = UInt128.from_json(val);\n    if (!hash.is_valid()) {\n      throw new Error('Invalid Hash128');\n    }\n    serialize_hex(so, hash.to_hex(), true); //noLength = true\n  },\n  parse: function (so) {\n    return UInt128.from_bytes(so.read(16));\n  }\n});\n\nSTHash128.id = 4;\n\nvar STHash256 = exports.Hash256 = new SerializedType({\n  serialize: function (so, val) {\n    var hash = UInt256.from_json(val);\n    if (!hash.is_valid()) {\n      throw new Error('Invalid Hash256');\n    }\n    serialize_hex(so, hash.to_hex(), true); //noLength = true\n  },\n  parse: function (so) {\n    return UInt256.from_bytes(so.read(32));\n  }\n});\n\nSTHash256.id = 5;\n\nvar STHash160 = exports.Hash160 = new SerializedType({\n  serialize: function (so, val) {\n    var hash = UInt160.from_json(val);\n    if (!hash.is_valid()) {\n      throw new Error('Invalid Hash160');\n    }\n    serialize_hex(so, hash.to_hex(), true); //noLength = true\n  },\n  parse: function (so) {\n    return UInt160.from_bytes(so.read(20));\n  }\n});\n\nSTHash160.id = 17;\n\n// Internal\nvar STCurrency = new SerializedType({\n  serialize: function (so, val, xrp_as_ascii) {\n    var currencyData = val.to_bytes();\n\n    if (!currencyData) {\n      throw new Error('Tried to serialize invalid/unimplemented currency type.');\n    }\n\n    so.append(currencyData);\n  },\n  parse: function (so) {\n    var bytes = so.read(20);\n    var currency = Currency.from_bytes(bytes);\n    // XXX Disabled check. Theoretically, the Currency class should support any\n    //     UInt160 value and consider it valid. But it doesn't, so for the\n    //     deserialization to be usable, we need to allow invalid results for now.\n    //if (!currency.is_valid()) {\n    //  throw new Error('Invalid currency: '+convert_bytes_to_hex(bytes));\n    //}\n    return currency;\n  }\n});\n\nvar STAmount = exports.Amount = new SerializedType({\n  serialize: function (so, val) {\n    var amount = Amount.from_json(val);\n    if (!amount.is_valid()) {\n      throw new Error('Not a valid Amount object.');\n    }\n\n    // Amount (64-bit integer)\n    var valueBytes = utils.arraySet(8, 0);\n\n    if (amount.is_native()) {\n      var valueHex = amount._value.toString(16);\n\n      // Enforce correct length (64 bits)\n      if (valueHex.length > 16) {\n        throw new Error('Value out of bounds');\n      }\n\n      while (valueHex.length < 16) {\n        valueHex = '0' + valueHex;\n      }\n\n      valueBytes = bytes.fromBits(hex.toBits(valueHex));\n      // Clear most significant two bits - these bits should already be 0 if\n      // Amount enforces the range correctly, but we'll clear them anyway just\n      // so this code can make certain guarantees about the encoded value.\n      valueBytes[0] &= 0x3f;\n\n      if (!amount.is_negative()) {\n        valueBytes[0] |= 0x40;\n      }\n    } else {\n      var hi = 0, lo = 0;\n\n      // First bit: non-native\n      hi |= 1 << 31;\n\n      if (!amount.is_zero()) {\n        // Second bit: non-negative?\n        if (!amount.is_negative()) {\n          hi |= 1 << 30;\n        }\n\n        // Next eight bits: offset/exponent\n        hi |= ((97 + amount._offset) & 0xff) << 22;\n        // Remaining 54 bits: mantissa\n        hi |= amount._value.shiftRight(32).intValue() & 0x3fffff;\n        lo = amount._value.intValue() & 0xffffffff;\n      }\n\n      valueBytes = sjcl.codec.bytes.fromBits([hi, lo]);\n    }\n\n    so.append(valueBytes);\n\n    if (!amount.is_native()) {\n      // Currency (160-bit hash)\n      var currency = amount.currency();\n      STCurrency.serialize(so, currency, true);\n\n      // Issuer (160-bit hash)\n      so.append(amount.issuer().to_bytes());\n    }\n  },\n  parse: function (so) {\n    var amount = new Amount();\n    var value_bytes = so.read(8);\n    var is_zero = !(value_bytes[0] & 0x7f);\n\n    for (var i=1; i<8; i++) {\n      is_zero = is_zero && !value_bytes[i];\n    }\n\n    if (value_bytes[0] & 0x80) {\n      //non-native\n      var currency = STCurrency.parse(so);\n      var issuer_bytes = so.read(20);\n      var issuer = UInt160.from_bytes(issuer_bytes);\n      issuer.set_version(Base.VER_ACCOUNT_ID);\n      var offset = ((value_bytes[0] & 0x3f) << 2) + (value_bytes[1] >>> 6) - 97;\n      var mantissa_bytes = value_bytes.slice(1);\n      mantissa_bytes[0] &= 0x3f;\n      var value = new BigInteger(mantissa_bytes, 256);\n\n      if (value.equals(BigInteger.ZERO) && !is_zero ) {\n        throw new Error('Invalid zero representation');\n      }\n\n      amount._value = value;\n      amount._offset = offset;\n      amount._currency    = currency;\n      amount._issuer      = issuer;\n      amount._is_native   = false;\n    } else {\n      //native\n      var integer_bytes = value_bytes.slice();\n      integer_bytes[0] &= 0x3f;\n      amount._value = new BigInteger(integer_bytes, 256);\n      amount._is_native   = true;\n    }\n    amount._is_negative = !is_zero && !(value_bytes[0] & 0x40);\n    return amount;\n  }\n});\n\nSTAmount.id = 6;\n\nvar STVL = exports.VariableLength = exports.VL = new SerializedType({\n  serialize: function (so, val) {\n    if (typeof val === 'string') {\n      serialize_hex(so, val);\n    } else {\n      throw new Error('Unknown datatype.');\n    }\n  },\n  parse: function (so) {\n    var len = this.parse_varint(so);\n    return convert_bytes_to_hex(so.read(len));\n  }\n});\n\nSTVL.id = 7;\n\nvar STAccount = exports.Account = new SerializedType({\n  serialize: function (so, val) {\n    var account = UInt160.from_json(val);\n    if (!account.is_valid()) {\n      throw new Error('Invalid account!');\n    }\n    serialize_hex(so, account.to_hex());\n  },\n  parse: function (so) {\n    var len = this.parse_varint(so);\n\n    if (len !== 20) {\n      throw new Error('Non-standard-length account ID');\n    }\n\n    var result = UInt160.from_bytes(so.read(len));\n    result.set_version(Base.VER_ACCOUNT_ID);\n\n    //console.log('PARSED 160:', result.to_json());\n    if (false) {\n      throw new Error('Invalid Account');\n    }\n\n    return result;\n  }\n});\n\nSTAccount.id = 8;\n\nvar STPathSet = exports.PathSet = new SerializedType({\n  typeBoundary:  0xff,\n  typeEnd:       0x00,\n  typeAccount:   0x01,\n  typeCurrency:  0x10,\n  typeIssuer:    0x20,\n  serialize: function (so, val) {\n    for (var i=0, l=val.length; i<l; i++) {\n      // Boundary\n      if (i) {\n        STInt8.serialize(so, this.typeBoundary);\n      }\n\n      for (var j=0, l2=val[i].length; j<l2; j++) {\n        var entry = val[i][j];\n        //if (entry.hasOwnProperty('_value')) {entry = entry._value;}\n        var type = 0;\n\n        if (entry.account) {\n          type |= this.typeAccount;\n        }\n        if (entry.currency) {\n          type |= this.typeCurrency;\n        }\n        if (entry.issuer) {\n          type |= this.typeIssuer;\n        }\n\n        STInt8.serialize(so, type);\n\n        if (entry.account) {\n          so.append(UInt160.from_json(entry.account).to_bytes());\n        }\n\n        if (entry.currency) {\n          var currency = Currency.from_json(entry.currency, entry.non_native);\n          STCurrency.serialize(so, currency);\n        }\n\n        if (entry.issuer) {\n          so.append(UInt160.from_json(entry.issuer).to_bytes());\n        }\n      }\n    }\n\n    STInt8.serialize(so, this.typeEnd);\n  },\n  parse: function (so) {\n    // should return a list of lists:\n    /*\n       [\n       [entry, entry],\n       [entry, entry, entry],\n       [entry],\n       []\n       ]\n\n       each entry has one or more of the following attributes: amount, currency, issuer.\n       */\n\n    var path_list    = [];\n    var current_path = [];\n    var tag_byte;\n\n    while ((tag_byte = so.read(1)[0]) !== this.typeEnd) {\n      //TODO: try/catch this loop, and catch when we run out of data without reaching the end of the data structure.\n      //Now determine: is this an end, boundary, or entry-begin-tag?\n      //console.log('Tag byte:', tag_byte);\n      if (tag_byte === this.typeBoundary) {\n        //console.log('Boundary');\n        if (current_path) { //close the current path, if there is one,\n          path_list.push(current_path);\n        }\n        current_path = [ ]; //and start a new one.\n        continue;\n      }\n\n      //It's an entry-begin tag.\n      //console.log('It's an entry-begin tag.');\n      var entry = {};\n\n      if (tag_byte & this.typeAccount) {\n        //console.log('entry.account');\n        /*var bta = so.read(20);\n          console.log('BTA:', bta);*/\n        entry.account = STHash160.parse(so);\n        entry.account.set_version(Base.VER_ACCOUNT_ID);\n      }\n      if (tag_byte & this.typeCurrency) {\n        //console.log('entry.currency');\n        entry.currency = STCurrency.parse(so);\n        if (entry.currency.to_json() === 'XRP' && !entry.currency.is_native()) {\n          entry.non_native = true;\n        }\n      }\n      if (tag_byte & this.typeIssuer) {\n        //console.log('entry.issuer');\n        entry.issuer = STHash160.parse(so);\n        // Enable and set correct type of base-58 encoding\n        entry.issuer.set_version(Base.VER_ACCOUNT_ID);\n        //console.log('DONE WITH ISSUER!');\n      }\n\n      if (entry.account || entry.currency || entry.issuer) {\n        current_path.push(entry);\n      } else {\n        throw new Error('Invalid path entry'); //It must have at least something in it.\n      }\n    }\n\n    if (current_path) {\n      //close the current path, if there is one,\n      path_list.push(current_path);\n    }\n\n    return path_list;\n  }\n});\n\nSTPathSet.id = 18;\n\nvar STVector256 = exports.Vector256 = new SerializedType({\n  serialize: function (so, val) { //Assume val is an array of STHash256 objects.\n    var length_as_varint = SerializedType.serialize_varint(so, val.length * 32);\n    for (var i=0, l=val.length; i<l; i++) {\n      STHash256.serialize(so, val[i]);\n    }\n  },\n  parse: function (so) {\n    var length = this.parse_varint(so);\n    var output = [];\n    // length is number of bytes not number of Hash256\n    for (var i=0; i<length / 32; i++) {\n      output.push(STHash256.parse(so));\n    }\n    return output;\n  }\n});\n\nSTVector256.id = 19;\n\nexports.serialize = exports.serialize_whatever = serialize;\n\nfunction serialize(so, field_name, value) {\n  //so: a byte-stream to serialize into.\n  //field_name: a string for the field name ('LedgerEntryType' etc.)\n  //value: the value of that field.\n  var field_coordinates = binformat.fieldsInverseMap[field_name];\n  var type_bits         = field_coordinates[0];\n  var field_bits        = field_coordinates[1];\n  var tag_byte          = (type_bits < 16 ? type_bits << 4 : 0) | (field_bits < 16 ? field_bits : 0);\n\n  if (field_name === 'LedgerEntryType' && 'string' === typeof value) {\n    value = binformat.ledger[value][0];\n  }\n\n  if (field_name === 'TransactionResult' && 'string' === typeof value) {\n    value = binformat.ter[value];\n  }\n\n  STInt8.serialize(so, tag_byte);\n\n  if (type_bits >= 16) {\n    STInt8.serialize(so, type_bits);\n  }\n\n  if (field_bits >= 16) {\n    STInt8.serialize(so, field_bits);\n  }\n\n  // Get the serializer class (ST...) for a field based on the type bits.\n  var serialized_object_type = exports[binformat.types[type_bits]];\n  //do something with val[keys] and val[keys[i]];\n\n  try {\n    serialized_object_type.serialize(so, value);\n  } catch (e) {\n    e.message += ' (' + field_name + ')';\n    throw e;\n  }\n}\n\n//Take the serialized object, figure out what type/field it is, and return the parsing of that.\nexports.parse = exports.parse_whatever = parse;\n\nfunction parse(so) {\n  var tag_byte   = so.read(1)[0];\n  var type_bits  = tag_byte >> 4;\n\n  if (type_bits === 0) {\n    type_bits = so.read(1)[0];\n  }\n\n  // Get the parser class (ST...) for a field based on the type bits.\n  var type = exports[binformat.types[type_bits]];\n\n  assert(type, 'Unknown type - header byte is 0x' + tag_byte.toString(16));\n\n  var field_bits = tag_byte & 0x0f;\n  var field_name = (field_bits === 0)\n  ? field_name = binformat.fields[type_bits][so.read(1)[0]]\n  : field_name = binformat.fields[type_bits][field_bits];\n\n  assert(field_name, 'Unknown field - header byte is 0x' + tag_byte.toString(16));\n\n  return [ field_name, type.parse(so) ]; //key, value\n};\n\nfunction sort_fields(keys) {\n  function sort_field_compare(a, b) {\n    var a_field_coordinates = binformat.fieldsInverseMap[a];\n    var a_type_bits         = a_field_coordinates[0];\n    var a_field_bits        = a_field_coordinates[1];\n    var b_field_coordinates = binformat.fieldsInverseMap[b];\n    var b_type_bits         = b_field_coordinates[0];\n    var b_field_bits        = b_field_coordinates[1];\n\n    // Sort by type id first, then by field id\n    return a_type_bits !== b_type_bits ? a_type_bits - b_type_bits : a_field_bits - b_field_bits;\n  };\n\n  return keys.sort(sort_field_compare);\n}\n\nvar STObject = exports.Object = new SerializedType({\n  serialize: function (so, val, no_marker) {\n    var keys = Object.keys(val);\n\n    // Ignore lowercase field names - they're non-serializable fields by\n    // convention.\n    keys = keys.filter(function (key) {\n      return key[0] !== key[0].toLowerCase();\n    });\n\n    keys.forEach(function (key) {\n      if (typeof binformat.fieldsInverseMap[key] === 'undefined') {\n        throw new Error('JSON contains unknown field: \"' + key + '\"');\n      }\n    });\n\n    // Sort fields\n    keys = sort_fields(keys);\n\n    for (var i=0; i<keys.length; i++) {\n      serialize(so, keys[i], val[keys[i]]);\n    }\n\n    if (!no_marker) {\n      //Object ending marker\n      STInt8.serialize(so, 0xe1);\n    }\n  },\n\n  parse: function (so) {\n    var output = {};\n    while (so.peek(1)[0] !== 0xe1) {\n      var keyval = parse(so);\n      output[keyval[0]] = keyval[1];\n    }\n    so.read(1);\n    return output;\n  }\n});\n\nSTObject.id = 14;\n\nvar STArray = exports.Array = new SerializedType({\n  serialize: function (so, val) {\n    for (var i=0, l=val.length; i<l; i++) {\n      var keys = Object.keys(val[i]);\n\n      if (keys.length !== 1) {\n        throw Error('Cannot serialize an array containing non-single-key objects');\n      }\n\n      var field_name = keys[0];\n      var value = val[i][field_name];\n      serialize(so, field_name, value);\n    }\n\n    //Array ending marker\n    STInt8.serialize(so, 0xf1);\n  },\n\n  parse: function (so) {\n    var output = [ ];\n\n    while (so.peek(1)[0] !== 0xf1) {\n      var keyval = parse(so);\n      var obj = { };\n      obj[keyval[0]] = keyval[1];\n      output.push(obj);\n    }\n\n    so.read(1);\n\n    return output;\n  }\n});\n\nSTArray.id = 15;\n\n\n// WEBPACK FOOTER\n// module.id = 31\n// module.readableIdentifier = ./src/js/ripple/serializedtypes.js\n//@ sourceURL=webpack-module:///./src/js/ripple/serializedtypes.js");

/***/ },
/* 32 */
/***/ function(module, exports, __webpack_require__) {

	eval("var sjcl        = __webpack_require__(19).sjcl;\nvar base        = __webpack_require__(7).Base;\nvar Seed        = __webpack_require__(10).Seed;\nvar UInt160     = __webpack_require__(8).UInt160;\nvar UInt256     = __webpack_require__(9).UInt256;\nvar request     = __webpack_require__(51);\nvar querystring = __webpack_require__(52);\nvar extend      = __webpack_require__(44);\nvar parser      = __webpack_require__(43);\nvar Crypt       = { };\n\nvar cryptConfig = {\n  cipher : 'aes',\n  mode   : 'ccm',\n  ts     : 64,   // tag length\n  ks     : 256,  // key size\n  iter   : 1000  // iterations (key derivation)\n};\n\n/**\n * Full domain hash based on SHA512\n */\n\nfunction fdh(data, bytelen) {\n  var bitlen = bytelen << 3;\n\n  if (typeof data === 'string') {\n    data = sjcl.codec.utf8String.toBits(data);\n  }\n\n  // Add hashing rounds until we exceed desired length in bits\n  var counter = 0, output = [];\n\n  while (sjcl.bitArray.bitLength(output) < bitlen) {\n    var hash = sjcl.hash.sha512.hash(sjcl.bitArray.concat([counter], data));\n    output = sjcl.bitArray.concat(output, hash);\n    counter++;\n  }\n\n  // Truncate to desired length\n  output = sjcl.bitArray.clamp(output, bitlen);\n\n  return output;\n};\n\n/**\n * This is a function to derive different hashes from the same key. \n * Each hash is derived as HMAC-SHA512HALF(key, token).\n *\n * @param {string} key\n * @param {string} hash\n */\n\nfunction keyHash(key, token) {\n  var hmac = new sjcl.misc.hmac(key, sjcl.hash.sha512);\n  return sjcl.codec.hex.fromBits(sjcl.bitArray.bitSlice(hmac.encrypt(token), 0, 256));\n};\n\n/**\n * add entropy at each call to get random words\n * @param {number} nWords\n */\nfunction randomWords (nWords) {\n  for (var i = 0; i < 8; i++) {\n    sjcl.random.addEntropy(Math.random(), 32, \"Math.random()\");\n  }  \n  \n  return sjcl.random.randomWords(nWords);  \n}\n\n/****** exposed functions ******/\n\n/**\n * KEY DERIVATION FUNCTION\n *\n * This service takes care of the key derivation, i.e. converting low-entropy\n * secret into higher entropy secret via either computationally expensive\n * processes or peer-assisted key derivation (PAKDF).\n *\n * @param {object}    opts\n * @param {string}    purpose - Key type/purpose\n * @param {string}    username\n * @param {string}    secret - Also known as passphrase/password\n * @param {function}  fn\n */\n\nCrypt.derive = function(opts, purpose, username, secret, fn) {\n  var tokens;\n\n  if (purpose === 'login') {\n    tokens = ['id', 'crypt'];\n  } else {\n    tokens = ['unlock'];\n  }\n\n  var iExponent = new sjcl.bn(String(opts.exponent));\n  var iModulus  = new sjcl.bn(String(opts.modulus));\n  var iAlpha    = new sjcl.bn(String(opts.alpha));\n\n  var publicInfo = [ 'PAKDF_1_0_0', opts.host.length, opts.host, username.length, username, purpose.length, purpose ].join(':') + ':';\n  var publicSize = Math.ceil(Math.min((7 + iModulus.bitLength()) >>> 3, 256) / 8);\n  var publicHash = fdh(publicInfo, publicSize);\n  var publicHex  = sjcl.codec.hex.fromBits(publicHash);\n  var iPublic    = new sjcl.bn(String(publicHex)).setBitM(0);\n  var secretInfo = [ publicInfo, secret.length, secret ].join(':') + ':';\n  var secretSize = (7 + iModulus.bitLength()) >>> 3;\n  var secretHash = fdh(secretInfo, secretSize);\n  var secretHex  = sjcl.codec.hex.fromBits(secretHash);\n  var iSecret    = new sjcl.bn(String(secretHex)).mod(iModulus);\n\n  if (iSecret.jacobi(iModulus) !== 1) {\n    iSecret = iSecret.mul(iAlpha).mod(iModulus);\n  }\n\n  var iRandom;\n\n  for (;;) {\n    iRandom = sjcl.bn.random(iModulus, 0);\n    if (iRandom.jacobi(iModulus) === 1) {\n      break;\n    }\n  }\n\n  var iBlind   = iRandom.powermodMontgomery(iPublic.mul(iExponent), iModulus);\n  var iSignreq = iSecret.mulmod(iBlind, iModulus);\n  var signreq  = sjcl.codec.hex.fromBits(iSignreq.toBits());\n\n  request.post(opts.url)\n    .send({ info: publicInfo, signreq: signreq })\n    .end(function(err, resp) {\n      if (err || !resp) {\n        return fn(new Error('Could not query PAKDF server ' + opts.host));\n      }\n\n      var data = resp.body || resp.text ? JSON.parse(resp.text) : {};\n\n      if (data.result !== 'success') {\n        return fn(new Error('Could not query PAKDF server '+opts.host));\n      }\n\n      var iSignres = new sjcl.bn(String(data.signres));\n      var iRandomInv = iRandom.inverseMod(iModulus);\n      var iSigned    = iSignres.mulmod(iRandomInv, iModulus);\n      var key        = iSigned.toBits();\n      var result     = { };\n\n      tokens.forEach(function(token) {\n        result[token] = keyHash(key, token);\n      });\n\n      fn(null, result);\n    });\n};\n\n/**\n * Imported from ripple-client\n */\n\n\n\n/**\n * Encrypt data\n *\n * @param {string} key\n * @param {string} data\n */\n\nCrypt.encrypt = function(key, data) {\n  key = sjcl.codec.hex.toBits(key);\n\n  var opts = extend(true, {}, cryptConfig);\n\n  var encryptedObj = JSON.parse(sjcl.encrypt(key, data, opts));\n  var version = [sjcl.bitArray.partial(8, 0)];\n  var initVector = sjcl.codec.base64.toBits(encryptedObj.iv);\n  var ciphertext = sjcl.codec.base64.toBits(encryptedObj.ct);\n\n  var encryptedBits = sjcl.bitArray.concat(version, initVector);\n  encryptedBits = sjcl.bitArray.concat(encryptedBits, ciphertext);\n\n  return sjcl.codec.base64.fromBits(encryptedBits);\n};\n\n/**\n * Decrypt data\n *\n * @param {string} key\n * @param {string} data\n */\n\nCrypt.decrypt = function (key, data) {\n  \n  key = sjcl.codec.hex.toBits(key);\n  var encryptedBits = sjcl.codec.base64.toBits(data);\n\n  var version = sjcl.bitArray.extract(encryptedBits, 0, 8);\n\n  if (version !== 0) {\n    throw new Error('Unsupported encryption version: '+version);\n  }\n\n  var encrypted = extend(true, {}, cryptConfig, {\n    iv: sjcl.codec.base64.fromBits(sjcl.bitArray.bitSlice(encryptedBits, 8, 8+128)),\n    ct: sjcl.codec.base64.fromBits(sjcl.bitArray.bitSlice(encryptedBits, 8+128))\n  });\n\n  return sjcl.decrypt(key, JSON.stringify(encrypted));\n};\n\n\n/**\n * Validate a ripple address\n *\n * @param {string} address\n */\n\nCrypt.isValidAddress = function (address) {\n  return UInt160.is_valid(address);\n};\n\n/**\n * Create an encryption key\n *\n * @param {integer} nWords - number of words\n */\n\nCrypt.createSecret = function (nWords) {\n  return sjcl.codec.hex.fromBits(randomWords(nWords));\n};\n\n/**\n * Create a new master key\n */\n\nCrypt.createMaster = function () {\n  return base.encode_check(33, sjcl.codec.bytes.fromBits(randomWords(4)));\n};\n\n\n/**\n * Create a ripple address from a master key\n *\n * @param {string} masterkey\n */\n\nCrypt.getAddress = function (masterkey) {\n  return Seed.from_json(masterkey).get_key().get_address().to_json();\n};\n\n/**\n * Hash data using SHA-512.\n *\n * @param {string|bitArray} data\n * @return {string} Hash of the data\n */\n\nCrypt.hashSha512 = function (data) {\n  // XXX Should return a UInt512\n  return sjcl.codec.hex.fromBits(sjcl.hash.sha512.hash(data)); \n};\n\n/**\n * Hash data using SHA-512 and return the first 256 bits.\n *\n * @param {string|bitArray} data\n * @return {UInt256} Hash of the data\n */\nCrypt.hashSha512Half = function (data) {\n  return UInt256.from_hex(Crypt.hashSha512(data).substr(0, 64));\n};\n\n\n/**\n * Sign a data string with a secret key\n *\n * @param {string} secret\n * @param {string} data\n */\n\nCrypt.signString = function(secret, data) {\n  var hmac = new sjcl.misc.hmac(sjcl.codec.hex.toBits(secret), sjcl.hash.sha512);\n  return sjcl.codec.hex.fromBits(hmac.mac(data));\n};\n\n/**\n * Create an an accout recovery key\n *\n * @param {string} secret\n */\n\nCrypt.deriveRecoveryEncryptionKeyFromSecret = function(secret) {\n  var seed = Seed.from_json(secret).to_bits();\n  var hmac = new sjcl.misc.hmac(seed, sjcl.hash.sha512);\n  var key  = hmac.mac('ripple/hmac/recovery_encryption_key/v1');\n  key      = sjcl.bitArray.bitSlice(key, 0, 256);\n  return sjcl.codec.hex.fromBits(key);\n};\n\n/**\n * Convert base64 encoded data into base64url encoded data.\n *\n * @param {String} base64 Data\n */\n\nCrypt.base64ToBase64Url = function(encodedData) {\n  return encodedData.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/[=]+$/, '');\n};\n\n/**\n * Convert base64url encoded data into base64 encoded data.\n *\n * @param {String} base64 Data\n */\n\nCrypt.base64UrlToBase64 = function(encodedData) {\n  encodedData = encodedData.replace(/-/g, '+').replace(/_/g, '/');\n\n  while (encodedData.length % 4) {\n    encodedData += '=';\n  }\n\n  return encodedData;\n};\n\n/**\n * base64 to UTF8\n */\n\nCrypt.decodeBase64 = function (data) {\n  return sjcl.codec.utf8String.fromBits(sjcl.codec.base64.toBits(data));\n}\n\nexports.Crypt = Crypt;\n\n\n// WEBPACK FOOTER\n// module.id = 32\n// module.readableIdentifier = ./src/js/ripple/crypt.js\n//@ sourceURL=webpack-module:///./src/js/ripple/crypt.js");

/***/ },
/* 33 */
/***/ function(module, exports, __webpack_require__) {

	eval("var crypt   = __webpack_require__(32).Crypt;\nvar SignedRequest = __webpack_require__(47).SignedRequest;\nvar request = __webpack_require__(51);\nvar extend  = __webpack_require__(44);\nvar async   = __webpack_require__(50);\nvar log     = __webpack_require__(25).sub('blob');\nvar BlobClient = {};\n\n//Blob object class\nfunction BlobObj(options) {\n  if (!options) options = { };\n  \n  this.device_id = options.device_id;\n  this.url       = options.url;\n  this.id        = options.blob_id;\n  this.key       = options.key; \n  this.identity  = new Identity(this);\n  this.data      = { };\n};\n\n// Blob operations\n// Do NOT change the mapping of existing ops\nBlobObj.ops = {\n  // Special\n  noop: 0,\n\n  // Simple ops\n  set: 16,\n  unset: 17,\n  extend: 18,\n\n  // Meta ops\n  push: 32,\n  pop: 33,\n  shift: 34,\n  unshift: 35,\n  filter: 36\n};\n\n\nBlobObj.opsReverseMap = [ ];\nfor (var name in BlobObj.ops) {\n  BlobObj.opsReverseMap[BlobObj.ops[name]] = name;\n}\n\n//Identity fields\nvar identityRoot   = 'identityVault';\nvar identityFields = [\n  'name',\n  'entityType',\n  'email',\n  'phone',\n  'address',\n  'nationalID',\n  'birthday',\n  'birthplace'\n];\n\nvar entityTypes = [\n  'individual',\n  'organization',\n  'corporation'\n];\n\nvar addressFields = [\n  'contact',\n  'line1',\n  'line2',\n  'city',\n  'region',  //state/province/region\n  'postalCode',\n  'country'\n];\n\nvar nationalIDFields = [\n  'number',\n  'type',\n  'country',\n];\n\nvar idTypeFields = [\n  'ssn',\n  'taxID',\n  'passport',\n  'driversLicense',\n  'other'\n];\n\n/**\n * Initialize a new blob object\n *\n * @param {function} fn - Callback function\n */\n\nBlobObj.prototype.init = function(fn) {\n  var self = this, url;\n\n  if (self.url.indexOf('://') === -1) {\n    self.url = 'http://' + url;\n  }\n\n  url  = self.url + '/v1/blob/' + self.id;\n  if (this.device_id) url += '?device_id=' + this.device_id;\n  \n  request.get(url, function(err, resp) {\n    if (err) {\n      return fn(new Error(err.message || 'Could not retrieve blob'));\n    } else if (!resp.body) {\n      return fn(new Error('Could not retrieve blob'));\n    } else if (resp.body.twofactor) {\n      resp.body.twofactor.blob_id   = self.id;\n      resp.body.twofactor.blob_url  = self.url;\n      resp.body.twofactor.device_id = self.device_id;\n      resp.body.twofactor.blob_key  = self.key\n      return fn(resp.body);\n    } else if (resp.body.result !== 'success') {\n      return fn(new Error('Incorrect username or password'));\n    }\n    \n    self.revision         = resp.body.revision;\n    self.encrypted_secret = resp.body.encrypted_secret;\n    self.identity_id      = resp.body.identity_id;\n    self.missing_fields   = resp.body.missing_fields;\n    //self.attestations     = resp.body.attestation_summary;\n    \n    if (!self.decrypt(resp.body.blob)) {\n      return fn(new Error('Error while decrypting blob'));\n    }\n\n    //Apply patches\n    if (resp.body.patches && resp.body.patches.length) {\n      var successful = true;\n      resp.body.patches.forEach(function(patch) {\n        successful = successful && self.applyEncryptedPatch(patch);\n      });\n\n      if (successful) {\n        self.consolidate();\n      }\n    }\n\n    //return with newly decrypted blob\n    fn(null, self);\n  }).timeout(8000);\n};\n\n/**\n * Consolidate -\n * Consolidate patches as a new revision\n *\n * @param {function} fn - Callback function\n */\n\nBlobObj.prototype.consolidate = function(fn) {\n  // Callback is optional\n  if (typeof fn !== 'function') {\n    fn = function(){};\n  }\n\n  //console.log('client: blob: consolidation at revision', this.revision);\n  var encrypted = this.encrypt();\n\n  var config = {\n    method: 'POST',\n    url: this.url + '/v1/blob/consolidate',\n    dataType: 'json',\n    data: {\n      blob_id: this.id,\n      data: encrypted,\n      revision: this.revision\n    },\n  };\n\n  var signedRequest = new SignedRequest(config);\n\n  var signed = signedRequest.signHmac(this.data.auth_secret, this.id);\n\n  request.post(signed.url)\n    .send(signed.data)\n    .end(function(err, resp) {\n      // XXX Add better error information to exception\n      if (err) {\n        fn(new Error('Failed to consolidate blob - XHR error'));\n      } else if (resp.body && resp.body.result === 'success') {\n        fn(null, resp.body);\n      } else {\n        fn(new Error('Failed to consolidate blob'));\n      }\n  });\n};\n\n/**\n * ApplyEncryptedPatch -\n * save changes from a downloaded patch to the blob\n *\n * @param {string} patch - encrypted patch string\n */\n\nBlobObj.prototype.applyEncryptedPatch = function(patch) {\n  try {\n    var args = JSON.parse(crypt.decrypt(this.key, patch));\n    var op   = args.shift();\n    var path = args.shift();\n\n    this.applyUpdate(op, path, args);\n    this.revision++;\n\n    return true;\n  } catch (err) {\n    //console.log('client: blob: failed to apply patch:', err.toString());\n    //console.log(err.stack);\n    return false;\n  }\n};\n\n/**\n * Encrypt secret with unlock key\n *\n * @param {string} secretUnlockkey\n */\nBlobObj.prototype.encryptSecret = function (secretUnlockKey, secret) {\n  return crypt.encrypt(secretUnlockKey, secret);\n};\n\n/**\n * Decrypt secret with unlock key\n *\n * @param {string} secretUnlockkey\n */\n\nBlobObj.prototype.decryptSecret = function(secretUnlockKey) {\n  return crypt.decrypt(secretUnlockKey, this.encrypted_secret);\n};\n\n/**\n * Decrypt blob with crypt key\n *\n * @param {string} data - encrypted blob data\n */\n\nBlobObj.prototype.decrypt = function(data) {\n  try {\n    this.data = JSON.parse(crypt.decrypt(this.key, data));\n    return this;\n  } catch (e) {\n    //console.log('client: blob: decryption failed', e.toString());\n    //console.log(e.stack);\n    return false;\n  }\n};\n\n/**\n * Encrypt blob with crypt key\n */\n\nBlobObj.prototype.encrypt = function() {\n// Filter Angular metadata before encryption\n//  if ('object' === typeof this.data &&\n//      'object' === typeof this.data.contacts)\n//    this.data.contacts = angular.fromJson(angular.toJson(this.data.contacts));\n\n  return crypt.encrypt(this.key, JSON.stringify(this.data));\n};\n\n/**\n * Encrypt recovery key\n *\n * @param {string} secret\n * @param {string} blobDecryptKey\n */\n\nBlobObj.prototype.encryptBlobCrypt = function(secret, blobDecryptKey) {\n  var recoveryEncryptionKey = crypt.deriveRecoveryEncryptionKeyFromSecret(secret);\n  return crypt.encrypt(recoveryEncryptionKey, blobDecryptKey);\n};\n\n/**\n * Decrypt recovery key\n *\n * @param {string} secret\n * @param {string} encryptedKey\n */\n\nfunction decryptBlobCrypt (secret, encryptedKey) {\n  var recoveryEncryptionKey = crypt.deriveRecoveryEncryptionKeyFromSecret(secret);\n  return crypt.decrypt(recoveryEncryptionKey, encryptedKey);\n};\n\n/**** Blob updating functions ****/\n\n/**\n * Set blob element\n */\n\nBlobObj.prototype.set = function(pointer, value, fn) {\n  if (pointer == \"/\" + identityRoot && this.data[identityRoot]) {\n    return fn(new Error('Cannot overwrite Identity Vault')); \n  }\n    \n  this.applyUpdate('set', pointer, [value]);\n  this.postUpdate('set', pointer, [value], fn);\n};\n\n/**\n * Remove blob element\n */\n\nBlobObj.prototype.unset = function(pointer, fn) {\n  if (pointer == \"/\" + identityRoot) {\n    return fn(new Error('Cannot remove Identity Vault')); \n  }\n  \n  this.applyUpdate('unset', pointer, []);\n  this.postUpdate('unset', pointer, [], fn);\n};\n\n/**\n * Extend blob object\n */\n\nBlobObj.prototype.extend = function(pointer, value, fn) {\n  this.applyUpdate('extend', pointer, [value]);\n  this.postUpdate('extend', pointer, [value], fn);\n};\n\n/**\n * Prepend blob array\n */\n\nBlobObj.prototype.unshift = function(pointer, value, fn) {    \n  this.applyUpdate('unshift', pointer, [value]);\n  this.postUpdate('unshift', pointer, [value], fn);\n};\n\n/**\n * Filter the row(s) from an array.\n *\n * This method will find any entries from the array stored under `pointer` and\n * apply the `subcommands` to each of them.\n *\n * The subcommands can be any commands with the pointer parameter left out.\n */\n\nBlobObj.prototype.filter = function(pointer, field, value, subcommands, callback) {\n  var args = Array.prototype.slice.apply(arguments);\n\n  if (typeof args[args.length - 1] === 'function') {\n    callback = args.pop();\n  }\n\n  args.shift();\n\n  // Normalize subcommands to minimize the patch size\n  args = args.slice(0, 2).concat(normalizeSubcommands(args.slice(2), true));\n\n  this.applyUpdate('filter', pointer, args);\n  this.postUpdate('filter', pointer, args, callback);\n};\n\n/**\n * Apply udpdate to the blob\n */\n\nBlobObj.prototype.applyUpdate = function(op, path, params) {\n  // Exchange from numeric op code to string\n  if (typeof op === 'number') {\n    op = BlobObj.opsReverseMap[op];\n  }\n\n  if (typeof op !== 'string') {\n    throw new Error('Blob update op code must be a number or a valid op id string');\n  }\n\n  // Separate each step in the 'pointer'\n  var pointer = path.split('/');\n  var first = pointer.shift();\n\n  if (first !== '') {\n    throw new Error('Invalid JSON pointer: '+path);\n  }\n\n  this._traverse(this.data, pointer, path, op, params);\n};\n\n//for applyUpdate function\nBlobObj.prototype._traverse = function(context, pointer, originalPointer, op, params) {\n  var _this = this;\n  var part = _this.unescapeToken(pointer.shift());\n\n  if (Array.isArray(context)) {\n    if (part === '-') {\n      part = context.length;\n    } else if (part % 1 !== 0 && part >= 0) {\n      throw new Error('Invalid pointer, array element segments must be a positive integer, zero or '-'');\n    }\n  } else if (typeof context !== 'object') {\n    return null;\n  } else if (!context.hasOwnProperty(part)) {\n    // Some opcodes create the path as they're going along\n    if (op === 'set') {\n      context[part] = {};\n    } else if (op === 'unshift') {\n      context[part] = [];\n    } else {\n      return null;\n    }\n  }\n\n  if (pointer.length !== 0) {\n    return this._traverse(context[part], pointer, originalPointer, op, params);\n  }\n\n  switch (op) {\n    case 'set':\n      context[part] = params[0];\n      break;\n    case 'unset':\n      if (Array.isArray(context)) {\n        context.splice(part, 1);\n      } else {\n        delete context[part];\n      }\n      break;\n    case 'extend':\n      if (typeof context[part] !== 'object') {\n        throw new Error('Tried to extend a non-object');\n      }\n      extend(true, context[part], params[0]);\n      break;\n    case 'unshift':\n      if (typeof context[part] === 'undefined') {\n        context[part] = [ ];\n      } else if (!Array.isArray(context[part])) {\n        throw new Error('Operator \"unshift\" must be applied to an array.');\n      }\n      context[part].unshift(params[0]);\n      break;\n    case 'filter':\n      if (Array.isArray(context[part])) {\n        context[part].forEach(function(element, i) {\n          if (typeof element === 'object' && element.hasOwnProperty(params[0]) && element[params[0]] === params[1]) {\n            var subpointer = originalPointer + '/' + i;\n            var subcommands = normalizeSubcommands(params.slice(2));\n\n            subcommands.forEach(function(subcommand) {\n              var op = subcommand[0];\n              var pointer = subpointer + subcommand[1];\n              _this.applyUpdate(op, pointer, subcommand.slice(2));\n            });\n          }\n        });\n      }\n      break;\n    default:\n      throw new Error('Unsupported op '+op);\n  }\n};\n\nBlobObj.prototype.escapeToken = function(token) {\n  return token.replace(/[~\\/]/g, function(key) {\n    return key === '~' ? '~0' : '~1';\n  });\n};\n\nBlobObj.prototype.unescapeToken = function(str) {\n  return str.replace(/~./g, function(m) {\n    switch (m) {\n      case '~0':\n        return '~';\n      case '~1':\n        return '/';\n    }\n    throw new Error('Invalid tilde escape: ' + m);\n  });\n};\n\n/**\n * Sumbit update to blob vault\n */\n\nBlobObj.prototype.postUpdate = function(op, pointer, params, fn) {\n  // Callback is optional\n  if (typeof fn !== 'function') {\n    fn = function(){};\n  }\n\n  if (typeof op === 'string') {\n    op = BlobObj.ops[op];\n  }\n\n  if (typeof op !== 'number') {\n    throw new Error('Blob update op code must be a number or a valid op id string');\n  }\n\n  if (op < 0 || op > 255) {\n    throw new Error('Blob update op code out of bounds');\n  }\n\n  //console.log('client: blob: submitting update', BlobObj.opsReverseMap[op], pointer, params);\n\n  params.unshift(pointer);\n  params.unshift(op);\n\n  var config = {\n    method: 'POST',\n    url: this.url + '/v1/blob/patch',\n    dataType: 'json',\n    data: {\n      blob_id: this.id,\n      patch: crypt.encrypt(this.key, JSON.stringify(params))\n    }\n  };\n\n\n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signHmac(this.data.auth_secret, this.id);\n\n  request.post(signed.url)\n  .send(signed.data)\n  .end(function(err, resp) {\n    if (err) {\n      fn(new Error('Patch could not be saved - XHR error'));\n    } else if (!resp.body || resp.body.result !== 'success') {\n      fn(new Error('Patch could not be saved - bad result')); \n    } else {\n      fn(null, resp.body);\n    }\n  });\n};\n\n/**\n * get2FA - HMAC signed request\n */\n\nBlobObj.prototype.get2FA = function (fn) {\n  var config = {\n    method : 'GET',\n    url    : this.url + '/v1/blob/' + this.id + '/2FA?device_id=' + this.device_id,\n  };\n  \n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signHmac(this.data.auth_secret, this.id);  \n\n  request.get(signed.url)\n    .end(function(err, resp) { \n      if (err) {\n        fn(err);\n      } else if (resp.body && resp.body.result === 'success') {\n        fn(null, resp.body);\n      } else if (resp.body && resp.body.result === 'error') {\n        fn(new Error(resp.body.message)); \n      } else {\n        fn(new Error('Unable to retrieve settings.'));\n      }\n    });   \n}\n\n/**\n * set2FA\n * modify 2 factor auth settings\n * @params {object}  options\n * @params {string}  options.masterkey\n * @params {boolean} options.enabled\n * @params {string}  options.phone\n * @params {string}  options.country_code\n */\n\nBlobObj.prototype.set2FA = function(options, fn) {\n  \n  var config = {\n    method : 'POST',\n    url    : this.url + '/v1/blob/' + this.id + '/2FA',\n    data   : {\n      enabled      : options.enabled,\n      phone        : options.phone,\n      country_code : options.country_code\n    }\n  };\n\n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signAsymmetric(options.masterkey, this.data.account_id, this.id);\n\n  request.post(signed.url)\n    .send(signed.data)\n    .end(function(err, resp) { \n      if (err) {\n        fn(err);\n      } else if (resp.body && resp.body.result === 'success') {\n        fn(null, resp.body);\n      } else if (resp.body && resp.body.result === 'error') {\n        fn(resp.body); \n      } else {\n        fn(new Error('Unable to update settings.'));\n      }\n    }); \n};\n\n/***** helper functions *****/\n\nfunction normalizeSubcommands(subcommands, compress) {\n  // Normalize parameter structure\n  if (/(number|string)/.test(typeof subcommands[0])) {\n    // Case 1: Single subcommand inline\n    subcommands = [subcommands];\n  } else if (subcommands.length === 1 && Array.isArray(subcommands[0]) && /(number|string)/.test(typeof subcommands[0][0])) {\n    // Case 2: Single subcommand as array\n    // (nothing to do)\n  } else if (Array.isArray(subcommands[0])) {\n    // Case 3: Multiple subcommands as array of arrays\n    subcommands = subcommands[0];\n  }\n\n  // Normalize op name and convert strings to numeric codes\n  subcommands = subcommands.map(function(subcommand) {\n    if (typeof subcommand[0] === 'string') {\n      subcommand[0] = BlobObj.ops[subcommand[0]];\n    }\n\n    if (typeof subcommand[0] !== 'number') {\n      throw new Error('Invalid op in subcommand');\n    }\n\n    if (typeof subcommand[1] !== 'string') {\n      throw new Error('Invalid path in subcommand');\n    }\n\n    return subcommand;\n  });\n\n  if (compress) {\n    // Convert to the minimal possible format\n    if (subcommands.length === 1) {\n      return subcommands[0];\n    } else {\n      return [subcommands];\n    }\n  } else {\n    return subcommands;\n  }\n}\n\n\n/***** identity ****/\n\n/** \n * Identity class\n * \n */\n\nvar Identity = function (blob) {\n  this._getBlob = function() {\n    return blob;\n  };\n}; \n\n/**\n * getFullAddress\n * returns the address formed into a text string\n * @param {string} key - Encryption key\n */\n\nIdentity.prototype.getFullAddress = function (key) {\n  var blob = this._getBlob();\n  if (!blob || \n      !blob.data || \n      !blob.data[identityRoot] ||\n      !blob.data[identityRoot].address) {\n    return \"\";\n  }     \n  \n  var address = this.get('address', key);\n  var text    = \"\";\n  \n  if (address.value.contact)    text += address.value.contact;\n  if (address.value.line1)      text += \" \" + address.value.line1;\n  if (address.value.line2)      text += \" \" + address.value.line2;\n  if (address.value.city)       text += \" \" + address.value.city;\n  if (address.value.region)     text += \" \" + address.value.region;\n  if (address.value.postalCode) text += \" \" + address.value.postalCode;\n  if (address.value.country)    text += \" \" + address.value.country;\n  return text;\n};\n\n/**\n * getAll\n * get and decrypt all identity fields\n * @param {string} key  - Encryption key\n * @param {function} fn - Callback function\n */\n\nIdentity.prototype.getAll = function (key) {\n  var blob = this._getBlob();\n  if (!blob || !blob.data || !blob.data[identityRoot]) {\n    return {};\n  }   \n  \n  var result = {}, identity = blob.data[identityRoot];\n  for (var i in identity) {\n    result[i] = this.get(i, key);\n  }\n  \n  return result;\n};\n\n/**\n * get\n * get and decrypt a single identity field\n * @param {string} pointer - Field to retrieve\n * @param {string} key     - Encryption key\n */\n\nIdentity.prototype.get = function (pointer, key) {\n  var blob = this._getBlob();\n  if (!blob || !blob.data || !blob.data[identityRoot]) {\n    return null;\n  }\n  \n  var data = blob.data[identityRoot][pointer];\n  if (data && data.encrypted) {\n    return decrypt(key, data);\n    \n  } else if (data) {\n    return data;\n    \n  } else {\n    return null;\n  }\n  \n  function decrypt (key, data) {\n    var value;\n    var result = {encrypted : true};\n    \n    try {\n      value = crypt.decrypt(key, data.value);\n    } catch (e) {\n      result.value  = data.value;\n      result.error  = e; \n      return result;\n    }\n    \n    try {\n      result.value = JSON.parse(value);\n    } catch (e) {\n      result.value = value;\n    }\n    \n    return result;\n  }\n};\n\n/**\n * set\n * set and encrypt a single identity field.\n * @param {string} pointer - Field to set\n * @param {string} key     - Encryption key\n * @param {string} value   - Unencrypted data\n * @param {function} fn    - Callback function\n */\n\nIdentity.prototype.set = function (pointer, key, value, fn) {\n  var self = this, blob = this._getBlob();\n  \n  if (!fn) fn = function(){ };\n  \n  //check fields for validity\n  if (identityFields.indexOf(pointer) === -1) {\n    return fn(new Error(\"invalid identity field\"));   \n  \n  //validate address fields  \n  } else if (pointer === 'address') {\n    if (typeof value !== 'object') {\n      return fn(new Error(\"address must be an object\"));   \n    }\n    \n    for (var addressField in value) {\n      if (addressFields.indexOf(addressField) === -1) {\n        return fn(new Error(\"invalid address field\"));   \n      }\n    }\n  \n  //validate nationalID fields  \n  } else if (pointer === 'nationalID') {\n    if (typeof value !== 'object') {\n      return fn(new Error(\"nationalID must be an object\"));   \n    }\n    \n    for (var idField in value) {\n      if (nationalIDFields.indexOf(idField) === -1) {\n        return fn(new Error(\"invalid nationalID field\"));   \n      }\n      \n      if (idField === 'type') {\n        if (idTypeFields.indexOf(value[idField]) === -1) {\n          return fn(new Error(\"invalid nationalID type\"));   \n        }      \n      }\n    }   \n    \n  //validate entity type   \n  } else if (pointer === 'entityType') {\n    if (entityTypes.indexOf(value) === -1) {\n      return fn(new Error(\"invalid entity type\"));   \n    }     \n  }\n\n  async.waterfall([ validate, set ], fn);\n    \n  //make sure the identity setup is valid\n  function validate (callback) {\n   \n    if (!blob) return fn(new Error(\"Identity must be associated with a blob\"));\n    else if (!blob.data) return fn(new Error(\"Invalid Blob\"));  \n    else if (!blob.data[identityRoot]) {\n      blob.set(\"/\" + identityRoot, {}, function(err, res){\n        if (err) return callback (err);\n        else     return callback (null);\n      }); \n    } else return callback (null);\n  };\n    \n  function set (callback) {\n\n    //NOTE: currently we will overwrite if it already exists\n    //the other option would be to require decrypting with the\n    //existing key as a form of authorization\n    //var current = self.get(pointer, key);  \n    //if (current && current.error) {\n    //  return fn ? fn(current.error) : undefined;\n    //}\n    \n    var data = {};\n    data[pointer] = {\n      encrypted : key ? true : false,\n      value     : key ? encrypt(key, value) : value  \n    };\n    \n    self._getBlob().extend(\"/\" + identityRoot, data, callback);\n  };\n  \n  function encrypt (key, value) {\n    if (typeof value === 'object') value = JSON.stringify(value);\n    return crypt.encrypt(key, value);\n  }\n};\n\n/**\n * unset\n * remove a single identity field - will only be removed\n * with a valid decryption key\n * @param {string} pointer - Field to remove\n * @param {string} key     - Encryption key\n * @param {function} fn    - Callback function\n */\n\nIdentity.prototype.unset = function (pointer, key, fn) {\n  \n  if (!fn) fn = function(){ };\n  \n  //NOTE: this is rather useless since you can overwrite\n  //without an encryption key\n  var data = this.get(pointer, key);\n  if (data && data.error) {\n    return fn(data.error);\n  }\n  \n  this._getBlob().unset(\"/\" + identityRoot+\"/\" + pointer, fn);\n};\n\n/***** blob client methods ****/\n\n/**\n * Blob object class\n */ \n \nexports.Blob = BlobObj;\n\n/**\n * Get ripple name for a given address\n */\n\nBlobClient.getRippleName = function(url, address, fn) {\n  if (!crypt.isValidAddress(address)) {\n    return fn (new Error('Invalid ripple address'));\n  }\n\n  if (!crypt.isValidAddress(address)) return fn (new Error(\"Invalid ripple address\"));\n  request.get(url + '/v1/user/' + address, function(err, resp){\n    if (err) {\n      fn(new Error('Unable to access vault sever'));\n    } else if (resp.body && resp.body.username) {\n      fn(null, resp.body.username);\n    } else if (resp.body && resp.body.exists === false) {\n      fn (new Error('No ripple name for this address'));\n    } else {\n      fn(new Error('Unable to determine if ripple name exists'));\n    }\n  });\n};\n\n/**\n * Retrive a blob with url, id and key\n * @params {object} options\n * @params {string} options.url\n * @params {string} options.blob_id\n * @params {string} options.key\n * @params {string} options.device_id //optional\n */\n\nBlobClient.get = function (options, fn) {\n  var blob = new BlobObj(options);\n  blob.init(fn);\n};\n\n/**\n * requestToken\n * request new token to be sent for 2FA\n * @param {string} url\n * @param {string} id\n * @param {string} force_sms\n */\n\nBlobClient.requestToken = function (url, id, force_sms, fn) {\n  var config = {\n    method : 'GET',\n    url    : url + '/v1/blob/' + id + '/2FA/requestToken'\n  };\n  \n  \n  if (force_sms && force_sms instanceof Function) {\n    fn = force_sms;\n  } else if (force_sms) {\n    config.url += \"?force_sms=true\";\n  }\n  \n  request.get(config.url)\n    .end(function(err, resp) { \n      if (err) {\n        fn(err);\n      } else if (resp.body && resp.body.result === 'success') {\n        fn(null, resp.body);\n      } else if (resp.body && resp.body.result === 'error') {\n        fn(new Error(resp.body.message)); \n      } else {\n        fn(new Error('Unable to request authentication token.'));\n      }\n    }); \n}; \n\n/**\n * verifyToken\n * verify a device token for 2FA  \n * @param {object} options\n * @param {string} options.url\n * @param {string} options.id \n * @param {string} options.device_id \n * @param {string} options.token\n * @param {boolean} options.remember_me\n */\n\nBlobClient.verifyToken = function (options, fn) {\n  var config = {\n    method : 'POST',\n    url    : options.url + '/v1/blob/' + options.id + '/2FA/verifyToken',\n    data   : {\n      device_id   : options.device_id,\n      token       : options.token,\n      remember_me : options.remember_me\n    }\n  };\n  \n  request.post(config.url)\n    .send(config.data)\n    .end(function(err, resp) { \n      if (err) {\n        fn(err);\n      } else if (resp.body && resp.body.result === 'success') {\n        fn(null, resp.body);\n      } else if (resp.body && resp.body.result === 'error') {\n        fn(new Error(resp.body.message)); \n      } else {\n        fn(new Error('Unable to verify authentication token.'));\n      }\n    });   \n};\n\n/**\n * Verify email address\n */\n\nBlobClient.verify = function(url, username, token, fn) {\n  url += '/v1/user/' + username + '/verify/' + token;\n  request.get(url, function(err, resp) {\n    if (err) {    \n      fn(new Error(\"Failed to verify the account - XHR error\"));\n    } else if (resp.body && resp.body.result === 'success') {\n      fn(null, resp.body);\n    } else {\n      fn(new Error('Failed to verify the account'));\n    }\n  });\n};\n\n/**\n * resendEmail\n * send a new verification email\n * @param {object}   opts\n * @param {string}   opts.id\n * @param {string}   opts.username\n * @param {string}   opts.account_id\n * @param {string}   opts.email\n * @param {string}   opts.activateLink\n * @param {function} fn - Callback\n */\n\nBlobClient.resendEmail = function (opts, fn) {\n  var config = {\n    method : 'POST',\n    url    : opts.url + '/v1/user/email',\n    data   : {\n      blob_id  : opts.id,\n      username : opts.username,\n      email    : opts.email,\n      hostlink : opts.activateLink\n    }\n  };\n\n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signAsymmetric(opts.masterkey, opts.account_id, opts.id);\n\n  request.post(signed.url)\n    .send(signed.data)\n    .end(function(err, resp) {\n      if (err) {\n        log.error(\"resendEmail:\", err);\n        fn(new Error(\"Failed to resend the token\"));\n      } else if (resp.body && resp.body.result === 'success') {\n        fn(null, resp.body);\n      } else if (resp.body && resp.body.result === 'error') {\n        log.error(\"resendEmail:\", resp.body.message);\n        fn(new Error(\"Failed to resend the token\"));\n      } else {\n        fn(new Error(\"Failed to resend the token\")); \n      }\n    });\n};\n\n/**\n * RecoverBlob\n * recover a blob using the account secret\n * @param {object} opts\n * @param {string} opts.url\n * @param {string} opts.username\n * @param {string} opts.masterkey\n * @param {function} fn\n */\n\nBlobClient.recoverBlob = function (opts, fn) {\n  var username = String(opts.username).trim();\n  var config   = {\n    method : 'GET',\n    url    : opts.url + '/v1/user/recov/' + username,\n  };\n\n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signAsymmetricRecovery(opts.masterkey, username);  \n\n  request.get(signed.url)\n    .end(function(err, resp) {\n      if (err) {\n        fn(err);\n      } else if (resp.body && resp.body.result === 'success') {\n        if (!resp.body.encrypted_blobdecrypt_key) {\n          fn(new Error('Missing encrypted blob decrypt key.'));      \n        } else {\n          handleRecovery(resp);  \n        }       \n      } else if (resp.body && resp.body.result === 'error') {\n        fn(new Error(resp.body.message)); \n      } else {\n        fn(new Error('Could not recover blob'));\n      }\n    });\n    \n  function handleRecovery (resp) {\n\n    var params = {\n      url     : opts.url,\n      blob_id : resp.body.blob_id,\n      key     : decryptBlobCrypt(opts.masterkey, resp.body.encrypted_blobdecrypt_key)\n    }\n    \n    var blob  = new BlobObj(params);\n    \n    blob.revision = resp.body.revision;\n    blob.encrypted_secret = resp.body.encrypted_secret;\n\n    if (!blob.decrypt(resp.body.blob)) {\n      return fn(new Error('Error while decrypting blob'));\n    }\n\n    //Apply patches\n    if (resp.body.patches && resp.body.patches.length) {\n      var successful = true;\n      resp.body.patches.forEach(function(patch) {\n        successful = successful && blob.applyEncryptedPatch(patch);\n      });\n\n      if (successful) {\n        blob.consolidate();\n      }\n    }\n\n    //return with newly decrypted blob\n    fn(null, blob);\n  };\n};\n\n\n/**\n * updateKeys\n * Change the blob encryption keys\n * @param {object} opts\n * @param {string} opts.username\n * @param {object} opts.keys\n * @param {object} opts.blob\n * @param {string} masterkey\n */\n\nBlobClient.updateKeys = function (opts, fn) {\n  var old_id    = opts.blob.id;\n  opts.blob.id  = opts.keys.id;\n  opts.blob.key = opts.keys.crypt;\n  opts.blob.encrypted_secret = opts.blob.encryptSecret(opts.keys.unlock, opts.masterkey);\n  \n  var config = {\n    method : 'POST',\n    url    : opts.blob.url + '/v1/user/' + opts.username + '/updatekeys',\n    data   : {\n      blob_id  : opts.blob.id,\n      data     : opts.blob.encrypt(),\n      revision : opts.blob.revision,\n      encrypted_secret : opts.blob.encrypted_secret,\n      encrypted_blobdecrypt_key : opts.blob.encryptBlobCrypt(opts.masterkey, opts.keys.crypt),\n    }\n  };\n\n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signAsymmetric(opts.masterkey, opts.blob.data.account_id, old_id); \n\n  request.post(signed.url)\n    .send(signed.data)\n    .end(function(err, resp) {\n      if (err) {\n        log.error(\"updateKeys:\", err);\n        fn(new Error('Failed to update blob - XHR error'));\n      } else if (!resp.body || resp.body.result !== 'success') {\n        log.error(\"updateKeys:\", resp.body ? resp.body.message : null);\n        fn(new Error('Failed to update blob - bad result')); \n      } else {\n        fn(null, resp.body);\n      }\n    });     \n}; \n \n/**\n * rename\n * Change the username\n * @param {object} opts\n * @param {string} opts.username\n * @param {string} opts.new_username\n * @param {object} opts.keys\n * @param {object} opts.blob\n * @param {string} masterkey\n */\n\nBlobClient.rename = function (opts, fn) {\n  var old_id    = opts.blob.id;\n  opts.blob.id  = opts.keys.id;\n  opts.blob.key = opts.keys.crypt;\n  opts.blob.encryptedSecret = opts.blob.encryptSecret(opts.keys.unlock, opts.masterkey);\n\n  var config = {\n    method: 'POST',\n    url: opts.blob.url + '/v1/user/' + opts.username + '/rename',\n    data: {\n      blob_id  : opts.blob.id,\n      username : opts.new_username,\n      data     : opts.blob.encrypt(),\n      revision : opts.blob.revision,\n      encrypted_secret : opts.blob.encryptedSecret,\n      encrypted_blobdecrypt_key : opts.blob.encryptBlobCrypt(opts.masterkey, opts.keys.crypt)\n    }\n  };\n\n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signAsymmetric(opts.masterkey, opts.blob.data.account_id, old_id);\n\n  request.post(signed.url)\n    .send(signed.data)\n    .end(function(err, resp) {\n      if (err) {\n        log.error(\"rename:\", err);\n        fn(new Error(\"Failed to rename\"));\n      } else if (resp.body && resp.body.result === 'success') {\n        fn(null, resp.body);\n      } else if (resp.body && resp.body.result === 'error') {\n        log.error(\"rename:\", resp.body.message);\n        fn(new Error(\"Failed to rename\"));\n      } else {\n        fn(new Error(\"Failed to rename\"));\n      }\n    });\n};\n\n/**\n * Create a blob object\n *\n * @param {object} options\n * @param {string} options.url\n * @param {string} options.id\n * @param {string} options.crypt\n * @param {string} options.unlock\n * @param {string} options.username\n * @param {string} options.masterkey\n * @param {object} options.oldUserBlob\n * @param {function} fn\n */\n\nBlobClient.create = function(options, fn) {\n  var params = {\n    url     : options.url,\n    blob_id : options.id,\n    key     : options.crypt\n  }\n  var blob = new BlobObj(params);\n\n  blob.revision = 0;\n\n  blob.data = {\n    auth_secret : crypt.createSecret(8),\n    account_id  : crypt.getAddress(options.masterkey),\n    email       : options.email,\n    contacts    : [],\n    created     : (new Date()).toJSON()\n  };\n\n  blob.encrypted_secret = blob.encryptSecret(options.unlock, options.masterkey);\n\n  // Migration\n  if (options.oldUserBlob) {\n    blob.data.contacts = options.oldUserBlob.data.contacts;\n  }\n\n  //post to the blob vault to create\n  var config = {\n    method : 'POST',\n    url    : options.url + '/v1/user',\n    data   : {\n      blob_id     : options.id,\n      username    : options.username,\n      address     : blob.data.account_id,\n      auth_secret : blob.data.auth_secret,\n      data        : blob.encrypt(),\n      email       : options.email,\n      hostlink    : options.activateLink,\n      domain      : options.domain,\n      encrypted_blobdecrypt_key : blob.encryptBlobCrypt(options.masterkey, options.crypt),\n      encrypted_secret : blob.encrypted_secret\n    }\n  };\n\n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signAsymmetric(options.masterkey, blob.data.account_id, options.id);\n\n  request.post(signed.url)\n    .send(signed.data)\n    .end(function(err, resp) {\n      if (err) {\n        fn(err);\n      } else if (resp.body && resp.body.result === 'success') {\n        blob.identity_id = resp.body.identity_id;\n        fn(null, blob, resp.body);\n      } else if (resp.body && resp.body.result === 'error') {\n        fn(new Error(resp.body.message)); \n      } else {\n        fn(new Error('Could not create blob'));\n      }\n    });\n};\n\n/**\n * deleteBlob\n * @param {object} options\n * @param {string} options.url\n * @param {string} options.username\n * @param {string} options.blob_id\n * @param {string} options.account_id\n * @param {string} options.masterkey \n */\n\nBlobClient.deleteBlob = function(options, fn) {\n  \n  var config = {\n    method : 'DELETE',\n    url    : options.url + '/v1/user/' + options.username,\n  };\n\n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signAsymmetric(options.masterkey, options.account_id, options.blob_id);\n\n  request.del(signed.url)\n    .end(function(err, resp) {\n      if (err) {\n        fn(err);\n      } else if (resp.body && resp.body.result === 'success') {\n        fn(null, resp.body);\n      } else if (resp.body && resp.body.result === 'error') {\n        fn(new Error(resp.body.message)); \n      } else {\n        fn(new Error('Could not delete blob'));\n      }\n    });  \n};\n\n/*** identity related functions ***/\n\n/**\n * updateProfile\n * update information stored outside the blob - HMAC signed\n * @param {object}\n * @param {string} opts.url\n * @param {string} opts.auth_secret\n * @param {srring} opts.blob_id\n * @param {object} opts.profile \n * @param {array}  opts.profile.attributes (optional, array of attribute objects)\n * @param {array}  opts.profile.addresses (optional, array of address objects)\n * \n * @param {string} attribute.id ... id of existing attribute\n * @param {string} attribute.name ... attribute name i.e. ripple_address\n * @param {string} attribute.type ... optional, sub-type of attribute\n * @param {string} attribute.value ... value of attribute\n * @param {string} attribute.domain ... corresponding domain\n * @param {string} attribute.status ... “current”, “removed”, etc.\n * @param {string} attribute.visibitlity ... “public”, ”private”\n */\n\nBlobClient.updateProfile = function (opts, fn) {\n  var config = {\n    method: 'POST',\n    url: opts.url + '/v1/profile/',\n    dataType: 'json',\n    data: opts.profile\n  };\n\n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signHmac(opts.auth_secret, opts.blob_id);  \n  \n  request.post(signed.url)\n    .send(signed.data)\n    .end(function(err, resp) {\n      \n      if (err) {\n        log.error('updateProfile:', err);\n        fn(new Error('Failed to update profile - XHR error'));\n      } else if (resp.body && resp.body.result === 'success') {\n        fn(null, resp.body);\n      } else if (resp.body) {\n        log.error('updateProfile:', resp.body);\n        fn(new Error('Failed to update profile'));\n      } else {\n        fn(new Error('Failed to update profile'));\n      } \n    });\n};\n\n/**\n * getProfile\n * @param {Object} opts\n * @param {string} opts.url\n * @param {string} opts.auth_secret\n * @param {srring} opts.blob_id\n */\n\nBlobClient.getProfile = function (opts, fn) {\n  var config = {\n    method: 'GET',\n    url: opts.url + '/v1/profile/'\n  };\n\n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signHmac(opts.auth_secret, opts.blob_id);  \n  \n  request.get(signed.url)\n    .send(signed.data)\n    .end(function(err, resp) {\n      \n      if (err) {\n        log.error('getProfile:', err);\n        fn(new Error('Failed to get profile - XHR error'));\n      } else if (resp.body && resp.body.result === 'success') {\n        fn(null, resp.body);\n      } else if (resp.body) {\n        log.error('getProfile:', resp.body);\n        fn(new Error('Failed to get profile'));\n      } else {\n        fn(new Error('Failed to get profile'));\n      } \n    });\n};\n\n/**\n * getAttestation\n * @param {Object} opts\n * @param {string} opts.url\n * @param {string} opts.auth_secret\n * @param {string} opts.blob_id\n * @param {string} opts.type (email,phone,basic_identity)\n * @param {object} opts.phone (required for type 'phone')\n * @param {string} opts.email (required for type 'email')\n */\n\nBlobClient.getAttestation = function (opts, fn) {\n  var params = { };\n  \n  if (opts.phone) params.phone = opts.phone;\n  if (opts.email) params.email = opts.email;\n      \n  var config = {\n    method: 'POST',\n    url: opts.url + '/v1/attestation/' + opts.type,\n    dataType: 'json',\n    data: params\n  };\n  \n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signHmac(opts.auth_secret, opts.blob_id);  \n  \n  request.post(signed.url)\n    .send(signed.data)\n    .end(function(err, resp) {\n      \n      if (err) {\n        log.error('attest:', err);\n        fn(new Error('attestation error - XHR error'));\n      } else if (resp.body && resp.body.result === 'success') {\n        if (resp.body.attestation) {\n          resp.body.decoded = BlobClient.parseAttestation(resp.body.attestation);\n        }\n        \n        fn(null, resp.body);\n      } else if (resp.body) {\n        log.error('attestation:', resp.body);\n        fn(new Error('attestation error: ' + resp.body.message || \"\"));\n      } else {\n        fn(new Error('attestation error'));\n      } \n    });\n};  \n\n/**\n * getAttestationSummary\n * @param {Object} opts\n * @param {string} opts.url\n * @param {string} opts.auth_secret\n * @param {string} opts.blob_id\n */\n\nBlobClient.getAttestationSummary = function (opts, fn) {\n\n\n  var config = {\n    method: 'GET',\n    url: opts.url + '/v1/attestation/summary',\n    dataType: 'json'\n  };\n  \n  if (opts.full) config.url += '?full=true';\n  \n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signHmac(opts.auth_secret, opts.blob_id);  \n  \n  request.get(signed.url)\n    .send(signed.data)\n    .end(function(err, resp) {\n      \n      if (err) {\n        log.error('attest:', err);\n        fn(new Error('attestation error - XHR error'));\n      } else if (resp.body && resp.body.result === 'success') {\n        if (resp.body.attestation) {\n          resp.body.decoded = BlobClient.parseAttestation(resp.body.attestation);\n        }\n        \n        fn(null, resp.body);\n      } else if (resp.body) {\n        log.error('attestation:', resp.body);\n        fn(new Error('attestation error: ' + resp.body.message || \"\"));\n      } else {\n        fn(new Error('attestation error'));\n      } \n    });\n};  \n\n/**\n * updateAttestation\n * @param {Object} opts\n * @param {string} opts.url\n * @param {string} opts.auth_secret\n * @param {string} opts.blob_id\n * @param {string} opts.type (email,phone,profile,identity)\n * @param {object} opts.phone (required for type 'phone')\n * @param {object} opts.profile (required for type 'profile')\n * @param {string} opts.email (required for type 'email')\n * @param {string} opts.answers (required for type 'identity')\n * @param {string} opts.token (required for completing email or phone attestations)\n */\n\nBlobClient.updateAttestation = function (opts, fn) {\n\n  var params = { };\n  \n  if (opts.phone)    params.phone   = opts.phone;\n  if (opts.profile)  params.profile = opts.profile;\n  if (opts.email)    params.email   = opts.email;\n  if (opts.token)    params.token   = opts.token;\n  if (opts.answers)  params.answers = opts.answers;\n      \n  var config = {\n    method: 'POST',\n    url: opts.url + '/v1/attestation/' + opts.type + '/update',\n    dataType: 'json',\n    data: params\n  };\n\n  var signedRequest = new SignedRequest(config);\n  var signed = signedRequest.signHmac(opts.auth_secret, opts.blob_id);  \n  \n  request.post(signed.url)\n    .send(signed.data)\n    .end(function(err, resp) {\n      \n      if (err) {\n        log.error('attest:', err);\n        fn(new Error('attestation error - XHR error'));\n      } else if (resp.body && resp.body.result === 'success') {\n        if (resp.body.attestation) {\n          resp.body.decoded = BlobClient.parseAttestation(resp.body.attestation);\n        }\n        \n        fn(null, resp.body);\n      } else if (resp.body) {\n        log.error('attestation:', resp.body);\n        fn(new Error('attestation error: ' + resp.body.message || \"\"));\n      } else {\n        fn(new Error('attestation error'));\n      } \n    });\n};\n\n/**\n * parseAttestation\n * @param {Object} attestation\n */\n\nBlobClient.parseAttestation = function (attestation) {\n  var segments =  decodeURIComponent(attestation).split('.');\n  var decoded;\n  \n  // base64 decode and parse JSON\n  try {\n    decoded = {\n      header    : JSON.parse(crypt.decodeBase64(segments[0])),\n      payload   : JSON.parse(crypt.decodeBase64(segments[1])),\n      signature : segments[2]\n    }; \n    \n  } catch (e) {\n    console.log(\"invalid attestation:\", e);\n  }\n  \n  return decoded;\n};\n\nexports.BlobClient = BlobClient;\n\n\n// WEBPACK FOOTER\n// module.id = 33\n// module.readableIdentifier = ./src/js/ripple/blob.js\n//@ sourceURL=webpack-module:///./src/js/ripple/blob.js");

/***/ },
/* 34 */
/***/ function(module, exports, __webpack_require__) {

	eval("/** @fileOverview Javascript cryptography implementation.\n *\n * Crush to remove comments, shorten variable names and\n * generally reduce transmission size.\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n */\n\n\"use strict\";\n/*jslint indent: 2, bitwise: false, nomen: false, plusplus: false, white: false, regexp: false */\n/*global document, window, escape, unescape */\n\n/** @namespace The Stanford Javascript Crypto Library, top-level namespace. */\nvar sjcl = {\n  /** @namespace Symmetric ciphers. */\n  cipher: {},\n\n  /** @namespace Hash functions.  Right now only SHA256 is implemented. */\n  hash: {},\n\n  /** @namespace Key exchange functions.  Right now only SRP is implemented. */\n  keyexchange: {},\n  \n  /** @namespace Block cipher modes of operation. */\n  mode: {},\n\n  /** @namespace Miscellaneous.  HMAC and PBKDF2. */\n  misc: {},\n  \n  /**\n   * @namespace Bit array encoders and decoders.\n   *\n   * @description\n   * The members of this namespace are functions which translate between\n   * SJCL's bitArrays and other objects (usually strings).  Because it\n   * isn't always clear which direction is encoding and which is decoding,\n   * the method names are \"fromBits\" and \"toBits\".\n   */\n  codec: {},\n  \n  /** @namespace Exceptions. */\n  exception: {\n    /** @constructor Ciphertext is corrupt. */\n    corrupt: function(message) {\n      this.toString = function() { return \"CORRUPT: \"+this.message; };\n      this.message = message;\n    },\n    \n    /** @constructor Invalid parameter. */\n    invalid: function(message) {\n      this.toString = function() { return \"INVALID: \"+this.message; };\n      this.message = message;\n    },\n    \n    /** @constructor Bug or missing feature in SJCL. @constructor */\n    bug: function(message) {\n      this.toString = function() { return \"BUG: \"+this.message; };\n      this.message = message;\n    },\n\n    /** @constructor Something isn't ready. */\n    notReady: function(message) {\n      this.toString = function() { return \"NOT READY: \"+this.message; };\n      this.message = message;\n    }\n  }\n};\n\nif(typeof module != 'undefined' && module.exports){\n  module.exports = sjcl;\n}\n\n/** @fileOverview Low-level AES implementation.\n *\n * This file contains a low-level implementation of AES, optimized for\n * size and for efficiency on several browsers.  It is based on\n * OpenSSL's aes_core.c, a public-domain implementation by Vincent\n * Rijmen, Antoon Bosselaers and Paulo Barreto.\n *\n * An older version of this implementation is available in the public\n * domain, but this one is (c) Emily Stark, Mike Hamburg, Dan Boneh,\n * Stanford University 2008-2010 and BSD-licensed for liability\n * reasons.\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n */\n\n/**\n * Schedule out an AES key for both encryption and decryption.  This\n * is a low-level class.  Use a cipher mode to do bulk encryption.\n *\n * @constructor\n * @param {Array} key The key as an array of 4, 6 or 8 words.\n *\n * @class Advanced Encryption Standard (low-level interface)\n */\nsjcl.cipher.aes = function (key) {\n  if (!this._tables[0][0][0]) {\n    this._precompute();\n  }\n  \n  var i, j, tmp,\n    encKey, decKey,\n    sbox = this._tables[0][4], decTable = this._tables[1],\n    keyLen = key.length, rcon = 1;\n  \n  if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {\n    throw new sjcl.exception.invalid(\"invalid aes key size\");\n  }\n  \n  this._key = [encKey = key.slice(0), decKey = []];\n  \n  // schedule encryption keys\n  for (i = keyLen; i < 4 * keyLen + 28; i++) {\n    tmp = encKey[i-1];\n    \n    // apply sbox\n    if (i%keyLen === 0 || (keyLen === 8 && i%keyLen === 4)) {\n      tmp = sbox[tmp>>>24]<<24 ^ sbox[tmp>>16&255]<<16 ^ sbox[tmp>>8&255]<<8 ^ sbox[tmp&255];\n      \n      // shift rows and add rcon\n      if (i%keyLen === 0) {\n        tmp = tmp<<8 ^ tmp>>>24 ^ rcon<<24;\n        rcon = rcon<<1 ^ (rcon>>7)*283;\n      }\n    }\n    \n    encKey[i] = encKey[i-keyLen] ^ tmp;\n  }\n  \n  // schedule decryption keys\n  for (j = 0; i; j++, i--) {\n    tmp = encKey[j&3 ? i : i - 4];\n    if (i<=4 || j<4) {\n      decKey[j] = tmp;\n    } else {\n      decKey[j] = decTable[0][sbox[tmp>>>24      ]] ^\n                  decTable[1][sbox[tmp>>16  & 255]] ^\n                  decTable[2][sbox[tmp>>8   & 255]] ^\n                  decTable[3][sbox[tmp      & 255]];\n    }\n  }\n};\n\nsjcl.cipher.aes.prototype = {\n  // public\n  /* Something like this might appear here eventually\n  name: \"AES\",\n  blockSize: 4,\n  keySizes: [4,6,8],\n  */\n  \n  /**\n   * Encrypt an array of 4 big-endian words.\n   * @param {Array} data The plaintext.\n   * @return {Array} The ciphertext.\n   */\n  encrypt:function (data) { return this._crypt(data,0); },\n  \n  /**\n   * Decrypt an array of 4 big-endian words.\n   * @param {Array} data The ciphertext.\n   * @return {Array} The plaintext.\n   */\n  decrypt:function (data) { return this._crypt(data,1); },\n  \n  /**\n   * The expanded S-box and inverse S-box tables.  These will be computed\n   * on the client so that we don't have to send them down the wire.\n   *\n   * There are two tables, _tables[0] is for encryption and\n   * _tables[1] is for decryption.\n   *\n   * The first 4 sub-tables are the expanded S-box with MixColumns.  The\n   * last (_tables[01][4]) is the S-box itself.\n   *\n   * @private\n   */\n  _tables: [[[],[],[],[],[]],[[],[],[],[],[]]],\n\n  /**\n   * Expand the S-box tables.\n   *\n   * @private\n   */\n  _precompute: function () {\n   var encTable = this._tables[0], decTable = this._tables[1],\n       sbox = encTable[4], sboxInv = decTable[4],\n       i, x, xInv, d=[], th=[], x2, x4, x8, s, tEnc, tDec;\n\n    // Compute double and third tables\n   for (i = 0; i < 256; i++) {\n     th[( d[i] = i<<1 ^ (i>>7)*283 )^i]=i;\n   }\n   \n   for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {\n     // Compute sbox\n     s = xInv ^ xInv<<1 ^ xInv<<2 ^ xInv<<3 ^ xInv<<4;\n     s = s>>8 ^ s&255 ^ 99;\n     sbox[x] = s;\n     sboxInv[s] = x;\n     \n     // Compute MixColumns\n     x8 = d[x4 = d[x2 = d[x]]];\n     tDec = x8*0x1010101 ^ x4*0x10001 ^ x2*0x101 ^ x*0x1010100;\n     tEnc = d[s]*0x101 ^ s*0x1010100;\n     \n     for (i = 0; i < 4; i++) {\n       encTable[i][x] = tEnc = tEnc<<24 ^ tEnc>>>8;\n       decTable[i][s] = tDec = tDec<<24 ^ tDec>>>8;\n     }\n   }\n   \n   // Compactify.  Considerable speedup on Firefox.\n   for (i = 0; i < 5; i++) {\n     encTable[i] = encTable[i].slice(0);\n     decTable[i] = decTable[i].slice(0);\n   }\n  },\n  \n  /**\n   * Encryption and decryption core.\n   * @param {Array} input Four words to be encrypted or decrypted.\n   * @param dir The direction, 0 for encrypt and 1 for decrypt.\n   * @return {Array} The four encrypted or decrypted words.\n   * @private\n   */\n  _crypt:function (input, dir) {\n    if (input.length !== 4) {\n      throw new sjcl.exception.invalid(\"invalid aes block size\");\n    }\n    \n    var key = this._key[dir],\n        // state variables a,b,c,d are loaded with pre-whitened data\n        a = input[0]           ^ key[0],\n        b = input[dir ? 3 : 1] ^ key[1],\n        c = input[2]           ^ key[2],\n        d = input[dir ? 1 : 3] ^ key[3],\n        a2, b2, c2,\n        \n        nInnerRounds = key.length/4 - 2,\n        i,\n        kIndex = 4,\n        out = [0,0,0,0],\n        table = this._tables[dir],\n        \n        // load up the tables\n        t0    = table[0],\n        t1    = table[1],\n        t2    = table[2],\n        t3    = table[3],\n        sbox  = table[4];\n \n    // Inner rounds.  Cribbed from OpenSSL.\n    for (i = 0; i < nInnerRounds; i++) {\n      a2 = t0[a>>>24] ^ t1[b>>16 & 255] ^ t2[c>>8 & 255] ^ t3[d & 255] ^ key[kIndex];\n      b2 = t0[b>>>24] ^ t1[c>>16 & 255] ^ t2[d>>8 & 255] ^ t3[a & 255] ^ key[kIndex + 1];\n      c2 = t0[c>>>24] ^ t1[d>>16 & 255] ^ t2[a>>8 & 255] ^ t3[b & 255] ^ key[kIndex + 2];\n      d  = t0[d>>>24] ^ t1[a>>16 & 255] ^ t2[b>>8 & 255] ^ t3[c & 255] ^ key[kIndex + 3];\n      kIndex += 4;\n      a=a2; b=b2; c=c2;\n    }\n        \n    // Last round.\n    for (i = 0; i < 4; i++) {\n      out[dir ? 3&-i : i] =\n        sbox[a>>>24      ]<<24 ^ \n        sbox[b>>16  & 255]<<16 ^\n        sbox[c>>8   & 255]<<8  ^\n        sbox[d      & 255]     ^\n        key[kIndex++];\n      a2=a; a=b; b=c; c=d; d=a2;\n    }\n    \n    return out;\n  }\n};\n\n\n/** @fileOverview Arrays of bits, encoded as arrays of Numbers.\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n */\n\n/** @namespace Arrays of bits, encoded as arrays of Numbers.\n *\n * @description\n * <p>\n * These objects are the currency accepted by SJCL's crypto functions.\n * </p>\n *\n * <p>\n * Most of our crypto primitives operate on arrays of 4-byte words internally,\n * but many of them can take arguments that are not a multiple of 4 bytes.\n * This library encodes arrays of bits (whose size need not be a multiple of 8\n * bits) as arrays of 32-bit words.  The bits are packed, big-endian, into an\n * array of words, 32 bits at a time.  Since the words are double-precision\n * floating point numbers, they fit some extra data.  We use this (in a private,\n * possibly-changing manner) to encode the number of bits actually  present\n * in the last word of the array.\n * </p>\n *\n * <p>\n * Because bitwise ops clear this out-of-band data, these arrays can be passed\n * to ciphers like AES which want arrays of words.\n * </p>\n */\nsjcl.bitArray = {\n  /**\n   * Array slices in units of bits.\n   * @param {bitArray} a The array to slice.\n   * @param {Number} bstart The offset to the start of the slice, in bits.\n   * @param {Number} bend The offset to the end of the slice, in bits.  If this is undefined,\n   * slice until the end of the array.\n   * @return {bitArray} The requested slice.\n   */\n  bitSlice: function (a, bstart, bend) {\n    a = sjcl.bitArray._shiftRight(a.slice(bstart/32), 32 - (bstart & 31)).slice(1);\n    return (bend === undefined) ? a : sjcl.bitArray.clamp(a, bend-bstart);\n  },\n\n  /**\n   * Extract a number packed into a bit array.\n   * @param {bitArray} a The array to slice.\n   * @param {Number} bstart The offset to the start of the slice, in bits.\n   * @param {Number} length The length of the number to extract.\n   * @return {Number} The requested slice.\n   */\n  extract: function(a, bstart, blength) {\n    // FIXME: this Math.floor is not necessary at all, but for some reason\n    // seems to suppress a bug in the Chromium JIT.\n    var x, sh = Math.floor((-bstart-blength) & 31);\n    if ((bstart + blength - 1 ^ bstart) & -32) {\n      // it crosses a boundary\n      x = (a[bstart/32|0] << (32 - sh)) ^ (a[bstart/32+1|0] >>> sh);\n    } else {\n      // within a single word\n      x = a[bstart/32|0] >>> sh;\n    }\n    return x & ((1<<blength) - 1);\n  },\n\n  /**\n   * Concatenate two bit arrays.\n   * @param {bitArray} a1 The first array.\n   * @param {bitArray} a2 The second array.\n   * @return {bitArray} The concatenation of a1 and a2.\n   */\n  concat: function (a1, a2) {\n    if (a1.length === 0 || a2.length === 0) {\n      return a1.concat(a2);\n    }\n    \n    var out, i, last = a1[a1.length-1], shift = sjcl.bitArray.getPartial(last);\n    if (shift === 32) {\n      return a1.concat(a2);\n    } else {\n      return sjcl.bitArray._shiftRight(a2, shift, last|0, a1.slice(0,a1.length-1));\n    }\n  },\n\n  /**\n   * Find the length of an array of bits.\n   * @param {bitArray} a The array.\n   * @return {Number} The length of a, in bits.\n   */\n  bitLength: function (a) {\n    var l = a.length, x;\n    if (l === 0) { return 0; }\n    x = a[l - 1];\n    return (l-1) * 32 + sjcl.bitArray.getPartial(x);\n  },\n\n  /**\n   * Truncate an array.\n   * @param {bitArray} a The array.\n   * @param {Number} len The length to truncate to, in bits.\n   * @return {bitArray} A new array, truncated to len bits.\n   */\n  clamp: function (a, len) {\n    if (a.length * 32 < len) { return a; }\n    a = a.slice(0, Math.ceil(len / 32));\n    var l = a.length;\n    len = len & 31;\n    if (l > 0 && len) {\n      a[l-1] = sjcl.bitArray.partial(len, a[l-1] & 0x80000000 >> (len-1), 1);\n    }\n    return a;\n  },\n\n  /**\n   * Make a partial word for a bit array.\n   * @param {Number} len The number of bits in the word.\n   * @param {Number} x The bits.\n   * @param {Number} [0] _end Pass 1 if x has already been shifted to the high side.\n   * @return {Number} The partial word.\n   */\n  partial: function (len, x, _end) {\n    if (len === 32) { return x; }\n    return (_end ? x|0 : x << (32-len)) + len * 0x10000000000;\n  },\n\n  /**\n   * Get the number of bits used by a partial word.\n   * @param {Number} x The partial word.\n   * @return {Number} The number of bits used by the partial word.\n   */\n  getPartial: function (x) {\n    return Math.round(x/0x10000000000) || 32;\n  },\n\n  /**\n   * Compare two arrays for equality in a predictable amount of time.\n   * @param {bitArray} a The first array.\n   * @param {bitArray} b The second array.\n   * @return {boolean} true if a == b; false otherwise.\n   */\n  equal: function (a, b) {\n    if (sjcl.bitArray.bitLength(a) !== sjcl.bitArray.bitLength(b)) {\n      return false;\n    }\n    var x = 0, i;\n    for (i=0; i<a.length; i++) {\n      x |= a[i]^b[i];\n    }\n    return (x === 0);\n  },\n\n  /** Shift an array right.\n   * @param {bitArray} a The array to shift.\n   * @param {Number} shift The number of bits to shift.\n   * @param {Number} [carry=0] A byte to carry in\n   * @param {bitArray} [out=[]] An array to prepend to the output.\n   * @private\n   */\n  _shiftRight: function (a, shift, carry, out) {\n    var i, last2=0, shift2;\n    if (out === undefined) { out = []; }\n    \n    for (; shift >= 32; shift -= 32) {\n      out.push(carry);\n      carry = 0;\n    }\n    if (shift === 0) {\n      return out.concat(a);\n    }\n    \n    for (i=0; i<a.length; i++) {\n      out.push(carry | a[i]>>>shift);\n      carry = a[i] << (32-shift);\n    }\n    last2 = a.length ? a[a.length-1] : 0;\n    shift2 = sjcl.bitArray.getPartial(last2);\n    out.push(sjcl.bitArray.partial(shift+shift2 & 31, (shift + shift2 > 32) ? carry : out.pop(),1));\n    return out;\n  },\n  \n  /** xor a block of 4 words together.\n   * @private\n   */\n  _xor4: function(x,y) {\n    return [x[0]^y[0],x[1]^y[1],x[2]^y[2],x[3]^y[3]];\n  }\n};\n\n/** @fileOverview Bit array codec implementations.\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n */\n \n/** @namespace UTF-8 strings */\nsjcl.codec.utf8String = {\n  /** Convert from a bitArray to a UTF-8 string. */\n  fromBits: function (arr) {\n    var out = \"\", bl = sjcl.bitArray.bitLength(arr), i, tmp;\n    for (i=0; i<bl/8; i++) {\n      if ((i&3) === 0) {\n        tmp = arr[i/4];\n      }\n      out += String.fromCharCode(tmp >>> 24);\n      tmp <<= 8;\n    }\n    return decodeURIComponent(escape(out));\n  },\n  \n  /** Convert from a UTF-8 string to a bitArray. */\n  toBits: function (str) {\n    str = unescape(encodeURIComponent(str));\n    var out = [], i, tmp=0;\n    for (i=0; i<str.length; i++) {\n      tmp = tmp << 8 | str.charCodeAt(i);\n      if ((i&3) === 3) {\n        out.push(tmp);\n        tmp = 0;\n      }\n    }\n    if (i&3) {\n      out.push(sjcl.bitArray.partial(8*(i&3), tmp));\n    }\n    return out;\n  }\n};\n\n/** @fileOverview Bit array codec implementations.\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n */\n\n/** @namespace Hexadecimal */\nsjcl.codec.hex = {\n  /** Convert from a bitArray to a hex string. */\n  fromBits: function (arr) {\n    var out = \"\", i, x;\n    for (i=0; i<arr.length; i++) {\n      out += ((arr[i]|0)+0xF00000000000).toString(16).substr(4);\n    }\n    return out.substr(0, sjcl.bitArray.bitLength(arr)/4);//.replace(/(.{8})/g, \"$1 \");\n  },\n  /** Convert from a hex string to a bitArray. */\n  toBits: function (str) {\n    var i, out=[], len;\n    str = str.replace(/\\s|0x/g, \"\");\n    len = str.length;\n    str = str + \"00000000\";\n    for (i=0; i<str.length; i+=8) {\n      out.push(parseInt(str.substr(i,8),16)^0);\n    }\n    return sjcl.bitArray.clamp(out, len*4);\n  }\n};\n\n\n/** @fileOverview Bit array codec implementations.\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n */\n\n/** @namespace Base64 encoding/decoding */\nsjcl.codec.base64 = {\n  /** The base64 alphabet.\n   * @private\n   */\n  _chars: \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",\n  \n  /** Convert from a bitArray to a base64 string. */\n  fromBits: function (arr, _noEquals, _url) {\n    var out = \"\", i, bits=0, c = sjcl.codec.base64._chars, ta=0, bl = sjcl.bitArray.bitLength(arr);\n    if (_url) c = c.substr(0,62) + '-_';\n    for (i=0; out.length * 6 < bl; ) {\n      out += c.charAt((ta ^ arr[i]>>>bits) >>> 26);\n      if (bits < 6) {\n        ta = arr[i] << (6-bits);\n        bits += 26;\n        i++;\n      } else {\n        ta <<= 6;\n        bits -= 6;\n      }\n    }\n    while ((out.length & 3) && !_noEquals) { out += \"=\"; }\n    return out;\n  },\n  \n  /** Convert from a base64 string to a bitArray */\n  toBits: function(str, _url) {\n    str = str.replace(/\\s|=/g,'');\n    var out = [], i, bits=0, c = sjcl.codec.base64._chars, ta=0, x;\n    if (_url) c = c.substr(0,62) + '-_';\n    for (i=0; i<str.length; i++) {\n      x = c.indexOf(str.charAt(i));\n      if (x < 0) {\n        throw new sjcl.exception.invalid(\"this isn't base64!\");\n      }\n      if (bits > 26) {\n        bits -= 26;\n        out.push(ta ^ x>>>bits);\n        ta  = x << (32-bits);\n      } else {\n        bits += 6;\n        ta ^= x << (32-bits);\n      }\n    }\n    if (bits&56) {\n      out.push(sjcl.bitArray.partial(bits&56, ta, 1));\n    }\n    return out;\n  }\n};\n\nsjcl.codec.base64url = {\n  fromBits: function (arr) { return sjcl.codec.base64.fromBits(arr,1,1); },\n  toBits: function (str) { return sjcl.codec.base64.toBits(str,1); }\n};\n\n/** @fileOverview Bit array codec implementations.\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n */\n\n/** @namespace Arrays of bytes */\nsjcl.codec.bytes = {\n  /** Convert from a bitArray to an array of bytes. */\n  fromBits: function (arr) {\n    var out = [], bl = sjcl.bitArray.bitLength(arr), i, tmp;\n    for (i=0; i<bl/8; i++) {\n      if ((i&3) === 0) {\n        tmp = arr[i/4];\n      }\n      out.push(tmp >>> 24);\n      tmp <<= 8;\n    }\n    return out;\n  },\n  /** Convert from an array of bytes to a bitArray. */\n  toBits: function (bytes) {\n    var out = [], i, tmp=0;\n    for (i=0; i<bytes.length; i++) {\n      tmp = tmp << 8 | bytes[i];\n      if ((i&3) === 3) {\n        out.push(tmp);\n        tmp = 0;\n      }\n    }\n    if (i&3) {\n      out.push(sjcl.bitArray.partial(8*(i&3), tmp));\n    }\n    return out;\n  }\n};\n\n/** @fileOverview Javascript SHA-256 implementation.\n *\n * An older version of this implementation is available in the public\n * domain, but this one is (c) Emily Stark, Mike Hamburg, Dan Boneh,\n * Stanford University 2008-2010 and BSD-licensed for liability\n * reasons.\n *\n * Special thanks to Aldo Cortesi for pointing out several bugs in\n * this code.\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n */\n\n/**\n * Context for a SHA-256 operation in progress.\n * @constructor\n * @class Secure Hash Algorithm, 256 bits.\n */\nsjcl.hash.sha256 = function (hash) {\n  if (!this._key[0]) { this._precompute(); }\n  if (hash) {\n    this._h = hash._h.slice(0);\n    this._buffer = hash._buffer.slice(0);\n    this._length = hash._length;\n  } else {\n    this.reset();\n  }\n};\n\n/**\n * Hash a string or an array of words.\n * @static\n * @param {bitArray|String} data the data to hash.\n * @return {bitArray} The hash value, an array of 16 big-endian words.\n */\nsjcl.hash.sha256.hash = function (data) {\n  return (new sjcl.hash.sha256()).update(data).finalize();\n};\n\nsjcl.hash.sha256.prototype = {\n  /**\n   * The hash's block size, in bits.\n   * @constant\n   */\n  blockSize: 512,\n   \n  /**\n   * Reset the hash state.\n   * @return this\n   */\n  reset:function () {\n    this._h = this._init.slice(0);\n    this._buffer = [];\n    this._length = 0;\n    return this;\n  },\n  \n  /**\n   * Input several words to the hash.\n   * @param {bitArray|String} data the data to hash.\n   * @return this\n   */\n  update: function (data) {\n    if (typeof data === \"string\") {\n      data = sjcl.codec.utf8String.toBits(data);\n    }\n    var i, b = this._buffer = sjcl.bitArray.concat(this._buffer, data),\n        ol = this._length,\n        nl = this._length = ol + sjcl.bitArray.bitLength(data);\n    for (i = 512+ol & -512; i <= nl; i+= 512) {\n      this._block(b.splice(0,16));\n    }\n    return this;\n  },\n  \n  /**\n   * Complete hashing and output the hash value.\n   * @return {bitArray} The hash value, an array of 8 big-endian words.\n   */\n  finalize:function () {\n    var i, b = this._buffer, h = this._h;\n\n    // Round out and push the buffer\n    b = sjcl.bitArray.concat(b, [sjcl.bitArray.partial(1,1)]);\n    \n    // Round out the buffer to a multiple of 16 words, less the 2 length words.\n    for (i = b.length + 2; i & 15; i++) {\n      b.push(0);\n    }\n    \n    // append the length\n    b.push(Math.floor(this._length / 0x100000000));\n    b.push(this._length | 0);\n\n    while (b.length) {\n      this._block(b.splice(0,16));\n    }\n\n    this.reset();\n    return h;\n  },\n\n  /**\n   * The SHA-256 initialization vector, to be precomputed.\n   * @private\n   */\n  _init:[],\n  /*\n  _init:[0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19],\n  */\n  \n  /**\n   * The SHA-256 hash key, to be precomputed.\n   * @private\n   */\n  _key:[],\n  /*\n  _key:\n    [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n     0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n     0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n     0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n     0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n     0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n     0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n     0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2],\n  */\n\n\n  /**\n   * Function to precompute _init and _key.\n   * @private\n   */\n  _precompute: function () {\n    var i = 0, prime = 2, factor;\n\n    function frac(x) { return (x-Math.floor(x)) * 0x100000000 | 0; }\n\n    outer: for (; i<64; prime++) {\n      for (factor=2; factor*factor <= prime; factor++) {\n        if (prime % factor === 0) {\n          // not a prime\n          continue outer;\n        }\n      }\n      \n      if (i<8) {\n        this._init[i] = frac(Math.pow(prime, 1/2));\n      }\n      this._key[i] = frac(Math.pow(prime, 1/3));\n      i++;\n    }\n  },\n  \n  /**\n   * Perform one cycle of SHA-256.\n   * @param {bitArray} words one block of words.\n   * @private\n   */\n  _block:function (words) {  \n    var i, tmp, a, b,\n      w = words.slice(0),\n      h = this._h,\n      k = this._key,\n      h0 = h[0], h1 = h[1], h2 = h[2], h3 = h[3],\n      h4 = h[4], h5 = h[5], h6 = h[6], h7 = h[7];\n\n    /* Rationale for placement of |0 :\n     * If a value can overflow is original 32 bits by a factor of more than a few\n     * million (2^23 ish), there is a possibility that it might overflow the\n     * 53-bit mantissa and lose precision.\n     *\n     * To avoid this, we clamp back to 32 bits by |'ing with 0 on any value that\n     * propagates around the loop, and on the hash state h[].  I don't believe\n     * that the clamps on h4 and on h0 are strictly necessary, but it's close\n     * (for h4 anyway), and better safe than sorry.\n     *\n     * The clamps on h[] are necessary for the output to be correct even in the\n     * common case and for short inputs.\n     */\n    for (i=0; i<64; i++) {\n      // load up the input word for this round\n      if (i<16) {\n        tmp = w[i];\n      } else {\n        a   = w[(i+1 ) & 15];\n        b   = w[(i+14) & 15];\n        tmp = w[i&15] = ((a>>>7  ^ a>>>18 ^ a>>>3  ^ a<<25 ^ a<<14) + \n                         (b>>>17 ^ b>>>19 ^ b>>>10 ^ b<<15 ^ b<<13) +\n                         w[i&15] + w[(i+9) & 15]) | 0;\n      }\n      \n      tmp = (tmp + h7 + (h4>>>6 ^ h4>>>11 ^ h4>>>25 ^ h4<<26 ^ h4<<21 ^ h4<<7) +  (h6 ^ h4&(h5^h6)) + k[i]); // | 0;\n      \n      // shift register\n      h7 = h6; h6 = h5; h5 = h4;\n      h4 = h3 + tmp | 0;\n      h3 = h2; h2 = h1; h1 = h0;\n\n      h0 = (tmp +  ((h1&h2) ^ (h3&(h1^h2))) + (h1>>>2 ^ h1>>>13 ^ h1>>>22 ^ h1<<30 ^ h1<<19 ^ h1<<10)) | 0;\n    }\n\n    h[0] = h[0]+h0 | 0;\n    h[1] = h[1]+h1 | 0;\n    h[2] = h[2]+h2 | 0;\n    h[3] = h[3]+h3 | 0;\n    h[4] = h[4]+h4 | 0;\n    h[5] = h[5]+h5 | 0;\n    h[6] = h[6]+h6 | 0;\n    h[7] = h[7]+h7 | 0;\n  }\n};\n\n\n\n/** @fileOverview Javascript SHA-512 implementation.\n *\n * This implementation was written for CryptoJS by Jeff Mott and adapted for\n * SJCL by Stefan Thomas.\n *\n * CryptoJS (c) 2009–2012 by Jeff Mott. All rights reserved.\n * Released with New BSD License\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n * @author Jeff Mott\n * @author Stefan Thomas\n */\n\n/**\n * Context for a SHA-512 operation in progress.\n * @constructor\n * @class Secure Hash Algorithm, 512 bits.\n */\nsjcl.hash.sha512 = function (hash) {\n  if (!this._key[0]) { this._precompute(); }\n  if (hash) {\n    this._h = hash._h.slice(0);\n    this._buffer = hash._buffer.slice(0);\n    this._length = hash._length;\n  } else {\n    this.reset();\n  }\n};\n\n/**\n * Hash a string or an array of words.\n * @static\n * @param {bitArray|String} data the data to hash.\n * @return {bitArray} The hash value, an array of 16 big-endian words.\n */\nsjcl.hash.sha512.hash = function (data) {\n  return (new sjcl.hash.sha512()).update(data).finalize();\n};\n\nsjcl.hash.sha512.prototype = {\n  /**\n   * The hash's block size, in bits.\n   * @constant\n   */\n  blockSize: 1024,\n   \n  /**\n   * Reset the hash state.\n   * @return this\n   */\n  reset:function () {\n    this._h = this._init.slice(0);\n    this._buffer = [];\n    this._length = 0;\n    return this;\n  },\n  \n  /**\n   * Input several words to the hash.\n   * @param {bitArray|String} data the data to hash.\n   * @return this\n   */\n  update: function (data) {\n    if (typeof data === \"string\") {\n      data = sjcl.codec.utf8String.toBits(data);\n    }\n    var i, b = this._buffer = sjcl.bitArray.concat(this._buffer, data),\n        ol = this._length,\n        nl = this._length = ol + sjcl.bitArray.bitLength(data);\n    for (i = 1024+ol & -1024; i <= nl; i+= 1024) {\n      this._block(b.splice(0,32));\n    }\n    return this;\n  },\n  \n  /**\n   * Complete hashing and output the hash value.\n   * @return {bitArray} The hash value, an array of 16 big-endian words.\n   */\n  finalize:function () {\n    var i, b = this._buffer, h = this._h;\n\n    // Round out and push the buffer\n    b = sjcl.bitArray.concat(b, [sjcl.bitArray.partial(1,1)]);\n\n    // Round out the buffer to a multiple of 32 words, less the 4 length words.\n    for (i = b.length + 4; i & 31; i++) {\n      b.push(0);\n    }\n\n    // append the length\n    b.push(0);\n    b.push(0);\n    b.push(Math.floor(this._length / 0x100000000));\n    b.push(this._length | 0);\n\n    while (b.length) {\n      this._block(b.splice(0,32));\n    }\n\n    this.reset();\n    return h;\n  },\n\n  /**\n   * The SHA-512 initialization vector, to be precomputed.\n   * @private\n   */\n  _init:[],\n\n  /**\n   * Least significant 24 bits of SHA512 initialization values.\n   *\n   * Javascript only has 53 bits of precision, so we compute the 40 most\n   * significant bits and add the remaining 24 bits as constants.\n   *\n   * @private\n   */\n  _initr: [ 0xbcc908, 0xcaa73b, 0x94f82b, 0x1d36f1, 0xe682d1, 0x3e6c1f, 0x41bd6b, 0x7e2179 ],\n\n  /*\n  _init:\n  [0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b, 0x3c6ef372, 0xfe94f82b, 0xa54ff53a, 0x5f1d36f1,\n   0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f, 0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179],\n  */\n\n  /**\n   * The SHA-512 hash key, to be precomputed.\n   * @private\n   */\n  _key:[],\n\n  /**\n   * Least significant 24 bits of SHA512 key values.\n   * @private\n   */\n  _keyr:\n  [0x28ae22, 0xef65cd, 0x4d3b2f, 0x89dbbc, 0x48b538, 0x05d019, 0x194f9b, 0x6d8118,\n   0x030242, 0x706fbe, 0xe4b28c, 0xffb4e2, 0x7b896f, 0x1696b1, 0xc71235, 0x692694,\n   0xf14ad2, 0x4f25e3, 0x8cd5b5, 0xac9c65, 0x2b0275, 0xa6e483, 0x41fbd4, 0x1153b5,\n   0x66dfab, 0xb43210, 0xfb213f, 0xef0ee4, 0xa88fc2, 0x0aa725, 0x03826f, 0x0e6e70,\n   0xd22ffc, 0x26c926, 0xc42aed, 0x95b3df, 0xaf63de, 0x77b2a8, 0xedaee6, 0x82353b,\n   0xf10364, 0x423001, 0xf89791, 0x54be30, 0xef5218, 0x65a910, 0x71202a, 0xbbd1b8,\n   0xd2d0c8, 0x41ab53, 0x8eeb99, 0x9b48a8, 0xc95a63, 0x418acb, 0x63e373, 0xb2b8a3,\n   0xefb2fc, 0x172f60, 0xf0ab72, 0x6439ec, 0x631e28, 0x82bde9, 0xc67915, 0x72532b,\n   0x26619c, 0xc0c207, 0xe0eb1e, 0x6ed178, 0x176fba, 0xc898a6, 0xf90dae, 0x1c471b,\n   0x047d84, 0xc72493, 0xc9bebc, 0x100d4c, 0x3e42b6, 0x657e2a, 0xd6faec, 0x475817],\n\n  /*\n  _key:\n  [0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,\n   0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,\n   0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,\n   0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,\n   0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,\n   0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,\n   0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,\n   0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,\n   0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,\n   0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,\n   0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,\n   0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,\n   0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,\n   0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,\n   0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,\n   0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,\n   0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,\n   0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,\n   0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,\n   0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817],\n  */\n\n  /**\n   * Function to precompute _init and _key.\n   * @private\n   */\n  _precompute: function () {\n    // XXX: This code is for precomputing the SHA256 constants, change for\n    //      SHA512 and re-enable.\n    var i = 0, prime = 2, factor;\n\n    function frac(x)  { return (x-Math.floor(x)) * 0x100000000 | 0; }\n    function frac2(x) { return (x-Math.floor(x)) * 0x10000000000 & 0xff; }\n\n    outer: for (; i<80; prime++) {\n      for (factor=2; factor*factor <= prime; factor++) {\n        if (prime % factor === 0) {\n          // not a prime\n          continue outer;\n        }\n      }\n\n      if (i<8) {\n        this._init[i*2] = frac(Math.pow(prime, 1/2));\n        this._init[i*2+1] = (frac2(Math.pow(prime, 1/2)) << 24) | this._initr[i];\n      }\n      this._key[i*2] = frac(Math.pow(prime, 1/3));\n      this._key[i*2+1] = (frac2(Math.pow(prime, 1/3)) << 24) | this._keyr[i];\n      i++;\n    }\n  },\n\n  /**\n   * Perform one cycle of SHA-512.\n   * @param {bitArray} words one block of words.\n   * @private\n   */\n  _block:function (words) {\n    var i, wrh, wrl,\n        w = words.slice(0),\n        h = this._h,\n        k = this._key,\n        h0h = h[ 0], h0l = h[ 1], h1h = h[ 2], h1l = h[ 3],\n        h2h = h[ 4], h2l = h[ 5], h3h = h[ 6], h3l = h[ 7],\n        h4h = h[ 8], h4l = h[ 9], h5h = h[10], h5l = h[11],\n        h6h = h[12], h6l = h[13], h7h = h[14], h7l = h[15];\n\n    // Working variables\n    var ah = h0h, al = h0l, bh = h1h, bl = h1l,\n        ch = h2h, cl = h2l, dh = h3h, dl = h3l,\n        eh = h4h, el = h4l, fh = h5h, fl = h5l,\n        gh = h6h, gl = h6l, hh = h7h, hl = h7l;\n\n    for (i=0; i<80; i++) {\n      // load up the input word for this round\n      if (i<16) {\n        wrh = w[i * 2];\n        wrl = w[i * 2 + 1];\n      } else {\n        // Gamma0\n        var gamma0xh = w[(i-15) * 2];\n        var gamma0xl = w[(i-15) * 2 + 1];\n        var gamma0h =\n          ((gamma0xl << 31) | (gamma0xh >>> 1)) ^\n          ((gamma0xl << 24) | (gamma0xh >>> 8)) ^\n           (gamma0xh >>> 7);\n        var gamma0l =\n          ((gamma0xh << 31) | (gamma0xl >>> 1)) ^\n          ((gamma0xh << 24) | (gamma0xl >>> 8)) ^\n          ((gamma0xh << 25) | (gamma0xl >>> 7));\n\n        // Gamma1\n        var gamma1xh = w[(i-2) * 2];\n        var gamma1xl = w[(i-2) * 2 + 1];\n        var gamma1h =\n          ((gamma1xl << 13) | (gamma1xh >>> 19)) ^\n          ((gamma1xh << 3)  | (gamma1xl >>> 29)) ^\n           (gamma1xh >>> 6);\n        var gamma1l =\n          ((gamma1xh << 13) | (gamma1xl >>> 19)) ^\n          ((gamma1xl << 3)  | (gamma1xh >>> 29)) ^\n          ((gamma1xh << 26) | (gamma1xl >>> 6));\n\n        // Shortcuts\n        var wr7h = w[(i-7) * 2];\n        var wr7l = w[(i-7) * 2 + 1];\n\n        var wr16h = w[(i-16) * 2];\n        var wr16l = w[(i-16) * 2 + 1];\n\n        // W(round) = gamma0 + W(round - 7) + gamma1 + W(round - 16)\n        wrl = gamma0l + wr7l;\n        wrh = gamma0h + wr7h + ((wrl >>> 0) < (gamma0l >>> 0) ? 1 : 0);\n        wrl += gamma1l;\n        wrh += gamma1h + ((wrl >>> 0) < (gamma1l >>> 0) ? 1 : 0);\n        wrl += wr16l;\n        wrh += wr16h + ((wrl >>> 0) < (wr16l >>> 0) ? 1 : 0);\n      }\n\n      w[i*2]     = wrh |= 0;\n      w[i*2 + 1] = wrl |= 0;\n\n      // Ch\n      var chh = (eh & fh) ^ (~eh & gh);\n      var chl = (el & fl) ^ (~el & gl);\n\n      // Maj\n      var majh = (ah & bh) ^ (ah & ch) ^ (bh & ch);\n      var majl = (al & bl) ^ (al & cl) ^ (bl & cl);\n\n      // Sigma0\n      var sigma0h = ((al << 4) | (ah >>> 28)) ^ ((ah << 30) | (al >>> 2)) ^ ((ah << 25) | (al >>> 7));\n      var sigma0l = ((ah << 4) | (al >>> 28)) ^ ((al << 30) | (ah >>> 2)) ^ ((al << 25) | (ah >>> 7));\n\n      // Sigma1\n      var sigma1h = ((el << 18) | (eh >>> 14)) ^ ((el << 14) | (eh >>> 18)) ^ ((eh << 23) | (el >>> 9));\n      var sigma1l = ((eh << 18) | (el >>> 14)) ^ ((eh << 14) | (el >>> 18)) ^ ((el << 23) | (eh >>> 9));\n\n      // K(round)\n      var krh = k[i*2];\n      var krl = k[i*2+1];\n\n      // t1 = h + sigma1 + ch + K(round) + W(round)\n      var t1l = hl + sigma1l;\n      var t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0);\n      t1l += chl;\n      t1h += chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0);\n      t1l += krl;\n      t1h += krh + ((t1l >>> 0) < (krl >>> 0) ? 1 : 0);\n      t1l += wrl;\n      t1h += wrh + ((t1l >>> 0) < (wrl >>> 0) ? 1 : 0);\n\n      // t2 = sigma0 + maj\n      var t2l = sigma0l + majl;\n      var t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0);\n\n      // Update working variables\n      hh = gh;\n      hl = gl;\n      gh = fh;\n      gl = fl;\n      fh = eh;\n      fl = el;\n      el = (dl + t1l) | 0;\n      eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0;\n      dh = ch;\n      dl = cl;\n      ch = bh;\n      cl = bl;\n      bh = ah;\n      bl = al;\n      al = (t1l + t2l) | 0;\n      ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0;\n    }\n\n    // Intermediate hash\n    h0l = h[1] = (h0l + al) | 0;\n    h[0] = (h0h + ah + ((h0l >>> 0) < (al >>> 0) ? 1 : 0)) | 0;\n    h1l = h[3] = (h1l + bl) | 0;\n    h[2] = (h1h + bh + ((h1l >>> 0) < (bl >>> 0) ? 1 : 0)) | 0;\n    h2l = h[5] = (h2l + cl) | 0;\n    h[4] = (h2h + ch + ((h2l >>> 0) < (cl >>> 0) ? 1 : 0)) | 0;\n    h3l = h[7] = (h3l + dl) | 0;\n    h[6] = (h3h + dh + ((h3l >>> 0) < (dl >>> 0) ? 1 : 0)) | 0;\n    h4l = h[9] = (h4l + el) | 0;\n    h[8] = (h4h + eh + ((h4l >>> 0) < (el >>> 0) ? 1 : 0)) | 0;\n    h5l = h[11] = (h5l + fl) | 0;\n    h[10] = (h5h + fh + ((h5l >>> 0) < (fl >>> 0) ? 1 : 0)) | 0;\n    h6l = h[13] = (h6l + gl) | 0;\n    h[12] = (h6h + gh + ((h6l >>> 0) < (gl >>> 0) ? 1 : 0)) | 0;\n    h7l = h[15] = (h7l + hl) | 0;\n    h[14] = (h7h + hh + ((h7l >>> 0) < (hl >>> 0) ? 1 : 0)) | 0;\n  }\n};\n\n\n\n/** @fileOverview Javascript SHA-1 implementation.\n *\n * Based on the implementation in RFC 3174, method 1, and on the SJCL\n * SHA-256 implementation.\n *\n * @author Quinn Slack\n */\n\n/**\n * Context for a SHA-1 operation in progress.\n * @constructor\n * @class Secure Hash Algorithm, 160 bits.\n */\nsjcl.hash.sha1 = function (hash) {\n  if (hash) {\n    this._h = hash._h.slice(0);\n    this._buffer = hash._buffer.slice(0);\n    this._length = hash._length;\n  } else {\n    this.reset();\n  }\n};\n\n/**\n * Hash a string or an array of words.\n * @static\n * @param {bitArray|String} data the data to hash.\n * @return {bitArray} The hash value, an array of 5 big-endian words.\n */\nsjcl.hash.sha1.hash = function (data) {\n  return (new sjcl.hash.sha1()).update(data).finalize();\n};\n\nsjcl.hash.sha1.prototype = {\n  /**\n   * The hash's block size, in bits.\n   * @constant\n   */\n  blockSize: 512,\n   \n  /**\n   * Reset the hash state.\n   * @return this\n   */\n  reset:function () {\n    this._h = this._init.slice(0);\n    this._buffer = [];\n    this._length = 0;\n    return this;\n  },\n  \n  /**\n   * Input several words to the hash.\n   * @param {bitArray|String} data the data to hash.\n   * @return this\n   */\n  update: function (data) {\n    if (typeof data === \"string\") {\n      data = sjcl.codec.utf8String.toBits(data);\n    }\n    var i, b = this._buffer = sjcl.bitArray.concat(this._buffer, data),\n        ol = this._length,\n        nl = this._length = ol + sjcl.bitArray.bitLength(data);\n    for (i = this.blockSize+ol & -this.blockSize; i <= nl;\n         i+= this.blockSize) {\n      this._block(b.splice(0,16));\n    }\n    return this;\n  },\n  \n  /**\n   * Complete hashing and output the hash value.\n   * @return {bitArray} The hash value, an array of 5 big-endian words. TODO\n   */\n  finalize:function () {\n    var i, b = this._buffer, h = this._h;\n\n    // Round out and push the buffer\n    b = sjcl.bitArray.concat(b, [sjcl.bitArray.partial(1,1)]);\n    // Round out the buffer to a multiple of 16 words, less the 2 length words.\n    for (i = b.length + 2; i & 15; i++) {\n      b.push(0);\n    }\n\n    // append the length\n    b.push(Math.floor(this._length / 0x100000000));\n    b.push(this._length | 0);\n\n    while (b.length) {\n      this._block(b.splice(0,16));\n    }\n\n    this.reset();\n    return h;\n  },\n\n  /**\n   * The SHA-1 initialization vector.\n   * @private\n   */\n  _init:[0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0],\n\n  /**\n   * The SHA-1 hash key.\n   * @private\n   */\n  _key:[0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6],\n\n  /**\n   * The SHA-1 logical functions f(0), f(1), ..., f(79).\n   * @private\n   */\n  _f:function(t, b, c, d) {\n    if (t <= 19) {\n      return (b & c) | (~b & d);\n    } else if (t <= 39) {\n      return b ^ c ^ d;\n    } else if (t <= 59) {\n      return (b & c) | (b & d) | (c & d);\n    } else if (t <= 79) {\n      return b ^ c ^ d;\n    }\n  },\n\n  /**\n   * Circular left-shift operator.\n   * @private\n   */\n  _S:function(n, x) {\n    return (x << n) | (x >>> 32-n);\n  },\n  \n  /**\n   * Perform one cycle of SHA-1.\n   * @param {bitArray} words one block of words.\n   * @private\n   */\n  _block:function (words) {  \n    var t, tmp, a, b, c, d, e,\n    w = words.slice(0),\n    h = this._h,\n    k = this._key;\n   \n    a = h[0]; b = h[1]; c = h[2]; d = h[3]; e = h[4]; \n\n    for (t=0; t<=79; t++) {\n      if (t >= 16) {\n        w[t] = this._S(1, w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16]);\n      }\n      tmp = (this._S(5, a) + this._f(t, b, c, d) + e + w[t] +\n             this._key[Math.floor(t/20)]) | 0;\n      e = d;\n      d = c;\n      c = this._S(30, b);\n      b = a;\n      a = tmp;\n   }\n\n   h[0] = (h[0]+a) |0;\n   h[1] = (h[1]+b) |0;\n   h[2] = (h[2]+c) |0;\n   h[3] = (h[3]+d) |0;\n   h[4] = (h[4]+e) |0;\n  }\n};\n\n/** @fileOverview CCM mode implementation.\n *\n * Special thanks to Roy Nicholson for pointing out a bug in our\n * implementation.\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n */\n\n/** @namespace CTR mode with CBC MAC. */\nsjcl.mode.ccm = {\n  /** The name of the mode.\n   * @constant\n   */\n  name: \"ccm\",\n  \n  /** Encrypt in CCM mode.\n   * @static\n   * @param {Object} prf The pseudorandom function.  It must have a block size of 16 bytes.\n   * @param {bitArray} plaintext The plaintext data.\n   * @param {bitArray} iv The initialization value.\n   * @param {bitArray} [adata=[]] The authenticated data.\n   * @param {Number} [tlen=64] the desired tag length, in bits.\n   * @return {bitArray} The encrypted data, an array of bytes.\n   */\n  encrypt: function(prf, plaintext, iv, adata, tlen) {\n    var L, i, out = plaintext.slice(0), tag, w=sjcl.bitArray, ivl = w.bitLength(iv) / 8, ol = w.bitLength(out) / 8;\n    tlen = tlen || 64;\n    adata = adata || [];\n    \n    if (ivl < 7) {\n      throw new sjcl.exception.invalid(\"ccm: iv must be at least 7 bytes\");\n    }\n    \n    // compute the length of the length\n    for (L=2; L<4 && ol >>> 8*L; L++) {}\n    if (L < 15 - ivl) { L = 15-ivl; }\n    iv = w.clamp(iv,8*(15-L));\n    \n    // compute the tag\n    tag = sjcl.mode.ccm._computeTag(prf, plaintext, iv, adata, tlen, L);\n    \n    // encrypt\n    out = sjcl.mode.ccm._ctrMode(prf, out, iv, tag, tlen, L);\n    \n    return w.concat(out.data, out.tag);\n  },\n  \n  /** Decrypt in CCM mode.\n   * @static\n   * @param {Object} prf The pseudorandom function.  It must have a block size of 16 bytes.\n   * @param {bitArray} ciphertext The ciphertext data.\n   * @param {bitArray} iv The initialization value.\n   * @param {bitArray} [[]] adata The authenticated data.\n   * @param {Number} [64] tlen the desired tag length, in bits.\n   * @return {bitArray} The decrypted data.\n   */\n  decrypt: function(prf, ciphertext, iv, adata, tlen) {\n    tlen = tlen || 64;\n    adata = adata || [];\n    var L, i, \n        w=sjcl.bitArray,\n        ivl = w.bitLength(iv) / 8,\n        ol = w.bitLength(ciphertext), \n        out = w.clamp(ciphertext, ol - tlen),\n        tag = w.bitSlice(ciphertext, ol - tlen), tag2;\n    \n\n    ol = (ol - tlen) / 8;\n        \n    if (ivl < 7) {\n      throw new sjcl.exception.invalid(\"ccm: iv must be at least 7 bytes\");\n    }\n    \n    // compute the length of the length\n    for (L=2; L<4 && ol >>> 8*L; L++) {}\n    if (L < 15 - ivl) { L = 15-ivl; }\n    iv = w.clamp(iv,8*(15-L));\n    \n    // decrypt\n    out = sjcl.mode.ccm._ctrMode(prf, out, iv, tag, tlen, L);\n    \n    // check the tag\n    tag2 = sjcl.mode.ccm._computeTag(prf, out.data, iv, adata, tlen, L);\n    if (!w.equal(out.tag, tag2)) {\n      throw new sjcl.exception.corrupt(\"ccm: tag doesn't match\");\n    }\n    \n    return out.data;\n  },\n\n  /* Compute the (unencrypted) authentication tag, according to the CCM specification\n   * @param {Object} prf The pseudorandom function.\n   * @param {bitArray} plaintext The plaintext data.\n   * @param {bitArray} iv The initialization value.\n   * @param {bitArray} adata The authenticated data.\n   * @param {Number} tlen the desired tag length, in bits.\n   * @return {bitArray} The tag, but not yet encrypted.\n   * @private\n   */\n  _computeTag: function(prf, plaintext, iv, adata, tlen, L) {\n    // compute B[0]\n    var q, mac, field = 0, offset = 24, tmp, i, macData = [], w=sjcl.bitArray, xor = w._xor4;\n\n    tlen /= 8;\n  \n    // check tag length and message length\n    if (tlen % 2 || tlen < 4 || tlen > 16) {\n      throw new sjcl.exception.invalid(\"ccm: invalid tag length\");\n    }\n  \n    if (adata.length > 0xFFFFFFFF || plaintext.length > 0xFFFFFFFF) {\n      // I don't want to deal with extracting high words from doubles.\n      throw new sjcl.exception.bug(\"ccm: can't deal with 4GiB or more data\");\n    }\n\n    // mac the flags\n    mac = [w.partial(8, (adata.length ? 1<<6 : 0) | (tlen-2) << 2 | L-1)];\n\n    // mac the iv and length\n    mac = w.concat(mac, iv);\n    mac[3] |= w.bitLength(plaintext)/8;\n    mac = prf.encrypt(mac);\n    \n  \n    if (adata.length) {\n      // mac the associated data.  start with its length...\n      tmp = w.bitLength(adata)/8;\n      if (tmp <= 0xFEFF) {\n        macData = [w.partial(16, tmp)];\n      } else if (tmp <= 0xFFFFFFFF) {\n        macData = w.concat([w.partial(16,0xFFFE)], [tmp]);\n      } // else ...\n    \n      // mac the data itself\n      macData = w.concat(macData, adata);\n      for (i=0; i<macData.length; i += 4) {\n        mac = prf.encrypt(xor(mac, macData.slice(i,i+4).concat([0,0,0])));\n      }\n    }\n  \n    // mac the plaintext\n    for (i=0; i<plaintext.length; i+=4) {\n      mac = prf.encrypt(xor(mac, plaintext.slice(i,i+4).concat([0,0,0])));\n    }\n\n    return w.clamp(mac, tlen * 8);\n  },\n\n  /** CCM CTR mode.\n   * Encrypt or decrypt data and tag with the prf in CCM-style CTR mode.\n   * May mutate its arguments.\n   * @param {Object} prf The PRF.\n   * @param {bitArray} data The data to be encrypted or decrypted.\n   * @param {bitArray} iv The initialization vector.\n   * @param {bitArray} tag The authentication tag.\n   * @param {Number} tlen The length of th etag, in bits.\n   * @param {Number} L The CCM L value.\n   * @return {Object} An object with data and tag, the en/decryption of data and tag values.\n   * @private\n   */\n  _ctrMode: function(prf, data, iv, tag, tlen, L) {\n    var enc, i, w=sjcl.bitArray, xor = w._xor4, ctr, b, l = data.length, bl=w.bitLength(data);\n\n    // start the ctr\n    ctr = w.concat([w.partial(8,L-1)],iv).concat([0,0,0]).slice(0,4);\n    \n    // en/decrypt the tag\n    tag = w.bitSlice(xor(tag,prf.encrypt(ctr)), 0, tlen);\n  \n    // en/decrypt the data\n    if (!l) { return {tag:tag, data:[]}; }\n    \n    for (i=0; i<l; i+=4) {\n      ctr[3]++;\n      enc = prf.encrypt(ctr);\n      data[i]   ^= enc[0];\n      data[i+1] ^= enc[1];\n      data[i+2] ^= enc[2];\n      data[i+3] ^= enc[3];\n    }\n    return { tag:tag, data:w.clamp(data,bl) };\n  }\n};\n\n/** @fileOverview HMAC implementation.\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n */\n\n/** HMAC with the specified hash function.\n * @constructor\n * @param {bitArray} key the key for HMAC.\n * @param {Object} [hash=sjcl.hash.sha256] The hash function to use.\n */\nsjcl.misc.hmac = function (key, Hash) {\n  this._hash = Hash = Hash || sjcl.hash.sha256;\n  var exKey = [[],[]], i,\n      bs = Hash.prototype.blockSize / 32;\n  this._baseHash = [new Hash(), new Hash()];\n\n  if (key.length > bs) {\n    key = Hash.hash(key);\n  }\n  \n  for (i=0; i<bs; i++) {\n    exKey[0][i] = key[i]^0x36363636;\n    exKey[1][i] = key[i]^0x5C5C5C5C;\n  }\n  \n  this._baseHash[0].update(exKey[0]);\n  this._baseHash[1].update(exKey[1]);\n};\n\n/** HMAC with the specified hash function.  Also called encrypt since it's a prf.\n * @param {bitArray|String} data The data to mac.\n */\nsjcl.misc.hmac.prototype.encrypt = sjcl.misc.hmac.prototype.mac = function (data) {\n  var w = new (this._hash)(this._baseHash[0]).update(data).finalize();\n  return new (this._hash)(this._baseHash[1]).update(w).finalize();\n};\n\n\n/** @fileOverview Password-based key-derivation function, version 2.0.\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n */\n\n/** Password-Based Key-Derivation Function, version 2.0.\n *\n * Generate keys from passwords using PBKDF2-HMAC-SHA256.\n *\n * This is the method specified by RSA's PKCS #5 standard.\n *\n * @param {bitArray|String} password  The password.\n * @param {bitArray} salt The salt.  Should have lots of entropy.\n * @param {Number} [count=1000] The number of iterations.  Higher numbers make the function slower but more secure.\n * @param {Number} [length] The length of the derived key.  Defaults to the\n                            output size of the hash function.\n * @param {Object} [Prff=sjcl.misc.hmac] The pseudorandom function family.\n * @return {bitArray} the derived key.\n */\nsjcl.misc.pbkdf2 = function (password, salt, count, length, Prff) {\n  count = count || 1000;\n  \n  if (length < 0 || count < 0) {\n    throw sjcl.exception.invalid(\"invalid params to pbkdf2\");\n  }\n  \n  if (typeof password === \"string\") {\n    password = sjcl.codec.utf8String.toBits(password);\n  }\n  \n  Prff = Prff || sjcl.misc.hmac;\n  \n  var prf = new Prff(password),\n      u, ui, i, j, k, out = [], b = sjcl.bitArray;\n\n  for (k = 1; 32 * out.length < (length || 1); k++) {\n    u = ui = prf.encrypt(b.concat(salt,[k]));\n    \n    for (i=1; i<count; i++) {\n      ui = prf.encrypt(ui);\n      for (j=0; j<ui.length; j++) {\n        u[j] ^= ui[j];\n      }\n    }\n    \n    out = out.concat(u);\n  }\n\n  if (length) { out = b.clamp(out, length); }\n\n  return out;\n};\n\n/** @fileOverview Random number generator.\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n */\n\n/** @constructor\n * @class Random number generator\n *\n * @description\n * <p>\n * This random number generator is a derivative of Ferguson and Schneier's\n * generator Fortuna.  It collects entropy from various events into several\n * pools, implemented by streaming SHA-256 instances.  It differs from\n * ordinary Fortuna in a few ways, though.\n * </p>\n *\n * <p>\n * Most importantly, it has an entropy estimator.  This is present because\n * there is a strong conflict here between making the generator available\n * as soon as possible, and making sure that it doesn't \"run on empty\".\n * In Fortuna, there is a saved state file, and the system is likely to have\n * time to warm up.\n * </p>\n *\n * <p>\n * Second, because users are unlikely to stay on the page for very long,\n * and to speed startup time, the number of pools increases logarithmically:\n * a new pool is created when the previous one is actually used for a reseed.\n * This gives the same asymptotic guarantees as Fortuna, but gives more\n * entropy to early reseeds.\n * </p>\n *\n * <p>\n * The entire mechanism here feels pretty klunky.  Furthermore, there are\n * several improvements that should be made, including support for\n * dedicated cryptographic functions that may be present in some browsers;\n * state files in local storage; cookies containing randomness; etc.  So\n * look for improvements in future versions.\n * </p>\n */\nsjcl.prng = function(defaultParanoia) {\n  \n  /* private */\n  this._pools                   = [new sjcl.hash.sha256()];\n  this._poolEntropy             = [0];\n  this._reseedCount             = 0;\n  this._robins                  = {};\n  this._eventId                 = 0;\n  \n  this._collectorIds            = {};\n  this._collectorIdNext         = 0;\n  \n  this._strength                = 0;\n  this._poolStrength            = 0;\n  this._nextReseed              = 0;\n  this._key                     = [0,0,0,0,0,0,0,0];\n  this._counter                 = [0,0,0,0];\n  this._cipher                  = undefined;\n  this._defaultParanoia         = defaultParanoia;\n  \n  /* event listener stuff */\n  this._collectorsStarted       = false;\n  this._callbacks               = {progress: {}, seeded: {}};\n  this._callbackI               = 0;\n  \n  /* constants */\n  this._NOT_READY               = 0;\n  this._READY                   = 1;\n  this._REQUIRES_RESEED         = 2;\n\n  this._MAX_WORDS_PER_BURST     = 65536;\n  this._PARANOIA_LEVELS         = [0,48,64,96,128,192,256,384,512,768,1024];\n  this._MILLISECONDS_PER_RESEED = 30000;\n  this._BITS_PER_RESEED         = 80;\n}\n \nsjcl.prng.prototype = {\n  /** Generate several random words, and return them in an array\n   * @param {Number} nwords The number of words to generate.\n   */\n  randomWords: function (nwords, paranoia) {\n    var out = [], i, readiness = this.isReady(paranoia), g;\n  \n    if (readiness === this._NOT_READY) {\n      throw new sjcl.exception.notReady(\"generator isn't seeded\");\n    } else if (readiness & this._REQUIRES_RESEED) {\n      this._reseedFromPools(!(readiness & this._READY));\n    }\n  \n    for (i=0; i<nwords; i+= 4) {\n      if ((i+1) % this._MAX_WORDS_PER_BURST === 0) {\n        this._gate();\n      }\n   \n      g = this._gen4words();\n      out.push(g[0],g[1],g[2],g[3]);\n    }\n    this._gate();\n  \n    return out.slice(0,nwords);\n  },\n  \n  setDefaultParanoia: function (paranoia) {\n    this._defaultParanoia = paranoia;\n  },\n  \n  /**\n   * Add entropy to the pools.\n   * @param data The entropic value.  Should be a 32-bit integer, array of 32-bit integers, or string\n   * @param {Number} estimatedEntropy The estimated entropy of data, in bits\n   * @param {String} source The source of the entropy, eg \"mouse\"\n   */\n  addEntropy: function (data, estimatedEntropy, source) {\n    source = source || \"user\";\n  \n    var id,\n      i, tmp,\n      t = (new Date()).valueOf(),\n      robin = this._robins[source],\n      oldReady = this.isReady(), err = 0;\n      \n    id = this._collectorIds[source];\n    if (id === undefined) { id = this._collectorIds[source] = this._collectorIdNext ++; }\n      \n    if (robin === undefined) { robin = this._robins[source] = 0; }\n    this._robins[source] = ( this._robins[source] + 1 ) % this._pools.length;\n  \n    switch(typeof(data)) {\n      \n    case \"number\":\n      if (estimatedEntropy === undefined) {\n        estimatedEntropy = 1;\n      }\n      this._pools[robin].update([id,this._eventId++,1,estimatedEntropy,t,1,data|0]);\n      break;\n      \n    case \"object\":\n      var objName = Object.prototype.toString.call(data);\n      if (objName === \"[object Uint32Array]\") {\n        tmp = [];\n        for (i = 0; i < data.length; i++) {\n          tmp.push(data[i]);\n        }\n        data = tmp;\n      } else {\n        if (objName !== \"[object Array]\") {\n          err = 1;\n        }\n        for (i=0; i<data.length && !err; i++) {\n          if (typeof(data[i]) != \"number\") {\n            err = 1;\n          }\n        }\n      }\n      if (!err) {\n        if (estimatedEntropy === undefined) {\n          /* horrible entropy estimator */\n          estimatedEntropy = 0;\n          for (i=0; i<data.length; i++) {\n            tmp= data[i];\n            while (tmp>0) {\n              estimatedEntropy++;\n              tmp = tmp >>> 1;\n            }\n          }\n        }\n        this._pools[robin].update([id,this._eventId++,2,estimatedEntropy,t,data.length].concat(data));\n      }\n      break;\n      \n    case \"string\":\n      if (estimatedEntropy === undefined) {\n       /* English text has just over 1 bit per character of entropy.\n        * But this might be HTML or something, and have far less\n        * entropy than English...  Oh well, let's just say one bit.\n        */\n       estimatedEntropy = data.length;\n      }\n      this._pools[robin].update([id,this._eventId++,3,estimatedEntropy,t,data.length]);\n      this._pools[robin].update(data);\n      break;\n      \n    default:\n      err=1;\n    }\n    if (err) {\n      throw new sjcl.exception.bug(\"random: addEntropy only supports number, array of numbers or string\");\n    }\n  \n    /* record the new strength */\n    this._poolEntropy[robin] += estimatedEntropy;\n    this._poolStrength += estimatedEntropy;\n  \n    /* fire off events */\n    if (oldReady === this._NOT_READY) {\n      if (this.isReady() !== this._NOT_READY) {\n        this._fireEvent(\"seeded\", Math.max(this._strength, this._poolStrength));\n      }\n      this._fireEvent(\"progress\", this.getProgress());\n    }\n  },\n  \n  /** Is the generator ready? */\n  isReady: function (paranoia) {\n    var entropyRequired = this._PARANOIA_LEVELS[ (paranoia !== undefined) ? paranoia : this._defaultParanoia ];\n  \n    if (this._strength && this._strength >= entropyRequired) {\n      return (this._poolEntropy[0] > this._BITS_PER_RESEED && (new Date()).valueOf() > this._nextReseed) ?\n        this._REQUIRES_RESEED | this._READY :\n        this._READY;\n    } else {\n      return (this._poolStrength >= entropyRequired) ?\n        this._REQUIRES_RESEED | this._NOT_READY :\n        this._NOT_READY;\n    }\n  },\n  \n  /** Get the generator's progress toward readiness, as a fraction */\n  getProgress: function (paranoia) {\n    var entropyRequired = this._PARANOIA_LEVELS[ paranoia ? paranoia : this._defaultParanoia ];\n  \n    if (this._strength >= entropyRequired) {\n      return 1.0;\n    } else {\n      return (this._poolStrength > entropyRequired) ?\n        1.0 :\n        this._poolStrength / entropyRequired;\n    }\n  },\n  \n  /** start the built-in entropy collectors */\n  startCollectors: function () {\n    if (this._collectorsStarted) { return; }\n  \n    if (window.addEventListener) {\n      window.addEventListener(\"load\", this._loadTimeCollector, false);\n      window.addEventListener(\"mousemove\", this._mouseCollector, false);\n    } else if (document.attachEvent) {\n      document.attachEvent(\"onload\", this._loadTimeCollector);\n      document.attachEvent(\"onmousemove\", this._mouseCollector);\n    }\n    else {\n      throw new sjcl.exception.bug(\"can't attach event\");\n    }\n  \n    this._collectorsStarted = true;\n  },\n  \n  /** stop the built-in entropy collectors */\n  stopCollectors: function () {\n    if (!this._collectorsStarted) { return; }\n  \n    if (window.removeEventListener) {\n      window.removeEventListener(\"load\", this._loadTimeCollector, false);\n      window.removeEventListener(\"mousemove\", this._mouseCollector, false);\n    } else if (window.detachEvent) {\n      window.detachEvent(\"onload\", this._loadTimeCollector);\n      window.detachEvent(\"onmousemove\", this._mouseCollector);\n    }\n    this._collectorsStarted = false;\n  },\n  \n  /* use a cookie to store entropy.\n  useCookie: function (all_cookies) {\n      throw new sjcl.exception.bug(\"random: useCookie is unimplemented\");\n  },*/\n  \n  /** add an event listener for progress or seeded-ness. */\n  addEventListener: function (name, callback) {\n    this._callbacks[name][this._callbackI++] = callback;\n  },\n  \n  /** remove an event listener for progress or seeded-ness */\n  removeEventListener: function (name, cb) {\n    var i, j, cbs=this._callbacks[name], jsTemp=[];\n  \n    /* I'm not sure if this is necessary; in C++, iterating over a\n     * collection and modifying it at the same time is a no-no.\n     */\n  \n    for (j in cbs) {\n\tif (cbs.hasOwnProperty(j) && cbs[j] === cb) {\n        jsTemp.push(j);\n      }\n    }\n  \n    for (i=0; i<jsTemp.length; i++) {\n      j = jsTemp[i];\n      delete cbs[j];\n    }\n  },\n  \n  /** Generate 4 random words, no reseed, no gate.\n   * @private\n   */\n  _gen4words: function () {\n    for (var i=0; i<4; i++) {\n      this._counter[i] = this._counter[i]+1 | 0;\n      if (this._counter[i]) { break; }\n    }\n    return this._cipher.encrypt(this._counter);\n  },\n  \n  /* Rekey the AES instance with itself after a request, or every _MAX_WORDS_PER_BURST words.\n   * @private\n   */\n  _gate: function () {\n    this._key = this._gen4words().concat(this._gen4words());\n    this._cipher = new sjcl.cipher.aes(this._key);\n  },\n  \n  /** Reseed the generator with the given words\n   * @private\n   */\n  _reseed: function (seedWords) {\n    this._key = sjcl.hash.sha256.hash(this._key.concat(seedWords));\n    this._cipher = new sjcl.cipher.aes(this._key);\n    for (var i=0; i<4; i++) {\n      this._counter[i] = this._counter[i]+1 | 0;\n      if (this._counter[i]) { break; }\n    }\n  },\n  \n  /** reseed the data from the entropy pools\n   * @param full If set, use all the entropy pools in the reseed.\n   */\n  _reseedFromPools: function (full) {\n    var reseedData = [], strength = 0, i;\n  \n    this._nextReseed = reseedData[0] =\n      (new Date()).valueOf() + this._MILLISECONDS_PER_RESEED;\n    \n    for (i=0; i<16; i++) {\n      /* On some browsers, this is cryptographically random.  So we might\n       * as well toss it in the pot and stir...\n       */\n      reseedData.push(Math.random()*0x100000000|0);\n    }\n    \n    for (i=0; i<this._pools.length; i++) {\n     reseedData = reseedData.concat(this._pools[i].finalize());\n     strength += this._poolEntropy[i];\n     this._poolEntropy[i] = 0;\n   \n     if (!full && (this._reseedCount & (1<<i))) { break; }\n    }\n  \n    /* if we used the last pool, push a new one onto the stack */\n    if (this._reseedCount >= 1 << this._pools.length) {\n     this._pools.push(new sjcl.hash.sha256());\n     this._poolEntropy.push(0);\n    }\n  \n    /* how strong was this reseed? */\n    this._poolStrength -= strength;\n    if (strength > this._strength) {\n      this._strength = strength;\n    }\n  \n    this._reseedCount ++;\n    this._reseed(reseedData);\n  },\n  \n  _mouseCollector: function (ev) {\n    var x = ev.x || ev.clientX || ev.offsetX || 0, y = ev.y || ev.clientY || ev.offsetY || 0;\n    sjcl.random.addEntropy([x,y], 2, \"mouse\");\n  },\n  \n  _loadTimeCollector: function (ev) {\n    sjcl.random.addEntropy((new Date()).valueOf(), 2, \"loadtime\");\n  },\n  \n  _fireEvent: function (name, arg) {\n    var j, cbs=sjcl.random._callbacks[name], cbsTemp=[];\n    /* TODO: there is a race condition between removing collectors and firing them */ \n\n    /* I'm not sure if this is necessary; in C++, iterating over a\n     * collection and modifying it at the same time is a no-no.\n     */\n  \n    for (j in cbs) {\n     if (cbs.hasOwnProperty(j)) {\n        cbsTemp.push(cbs[j]);\n     }\n    }\n  \n    for (j=0; j<cbsTemp.length; j++) {\n     cbsTemp[j](arg);\n    }\n  }\n};\n\nsjcl.random = new sjcl.prng(6);\n\n(function(){\n  try {\n    // get cryptographically strong entropy in Webkit\n    var ab = new Uint32Array(32);\n    crypto.getRandomValues(ab);\n    sjcl.random.addEntropy(ab, 1024, \"crypto.getRandomValues\");\n  } catch (e) {\n    // no getRandomValues :-(\n  }\n})();\n\n/** @fileOverview Convenince functions centered around JSON encapsulation.\n *\n * @author Emily Stark\n * @author Mike Hamburg\n * @author Dan Boneh\n */\n \n /** @namespace JSON encapsulation */\n sjcl.json = {\n  /** Default values for encryption */\n  defaults: { v:1, iter:1000, ks:128, ts:64, mode:\"ccm\", adata:\"\", cipher:\"aes\" },\n\n  /** Simple encryption function.\n   * @param {String|bitArray} password The password or key.\n   * @param {String} plaintext The data to encrypt.\n   * @param {Object} [params] The parameters including tag, iv and salt.\n   * @param {Object} [rp] A returned version with filled-in parameters.\n   * @return {String} The ciphertext.\n   * @throws {sjcl.exception.invalid} if a parameter is invalid.\n   */\n  encrypt: function (password, plaintext, params, rp) {\n    params = params || {};\n    rp = rp || {};\n    \n    var j = sjcl.json, p = j._add({ iv: sjcl.random.randomWords(4,0) },\n                                  j.defaults), tmp, prp, adata;\n    j._add(p, params);\n    adata = p.adata;\n    if (typeof p.salt === \"string\") {\n      p.salt = sjcl.codec.base64.toBits(p.salt);\n    }\n    if (typeof p.iv === \"string\") {\n      p.iv = sjcl.codec.base64.toBits(p.iv);\n    }\n    \n    if (!sjcl.mode[p.mode] ||\n        !sjcl.cipher[p.cipher] ||\n        (typeof password === \"string\" && p.iter <= 100) ||\n        (p.ts !== 64 && p.ts !== 96 && p.ts !== 128) ||\n        (p.ks !== 128 && p.ks !== 192 && p.ks !== 256) ||\n        (p.iv.length < 2 || p.iv.length > 4)) {\n      throw new sjcl.exception.invalid(\"json encrypt: invalid parameters\");\n    }\n    \n    if (typeof password === \"string\") {\n      tmp = sjcl.misc.cachedPbkdf2(password, p);\n      password = tmp.key.slice(0,p.ks/32);\n      p.salt = tmp.salt;\n    } else if (sjcl.ecc && password instanceof sjcl.ecc.elGamal.publicKey) {\n      tmp = password.kem();\n      p.kemtag = tmp.tag;\n      password = tmp.key.slice(0,p.ks/32);\n    }\n    if (typeof plaintext === \"string\") {\n      plaintext = sjcl.codec.utf8String.toBits(plaintext);\n    }\n    if (typeof adata === \"string\") {\n      adata = sjcl.codec.utf8String.toBits(adata);\n    }\n    prp = new sjcl.cipher[p.cipher](password);\n    \n    /* return the json data */\n    j._add(rp, p);\n    rp.key = password;\n    \n    /* do the encryption */\n    p.ct = sjcl.mode[p.mode].encrypt(prp, plaintext, p.iv, adata, p.ts);\n    \n    //return j.encode(j._subtract(p, j.defaults));\n    return j.encode(p);\n  },\n  \n  /** Simple decryption function.\n   * @param {String|bitArray} password The password or key.\n   * @param {String} ciphertext The ciphertext to decrypt.\n   * @param {Object} [params] Additional non-default parameters.\n   * @param {Object} [rp] A returned object with filled parameters.\n   * @return {String} The plaintext.\n   * @throws {sjcl.exception.invalid} if a parameter is invalid.\n   * @throws {sjcl.exception.corrupt} if the ciphertext is corrupt.\n   */\n  decrypt: function (password, ciphertext, params, rp) {\n    params = params || {};\n    rp = rp || {};\n    \n    var j = sjcl.json, p = j._add(j._add(j._add({},j.defaults),j.decode(ciphertext)), params, true), ct, tmp, prp, adata=p.adata;\n    if (typeof p.salt === \"string\") {\n      p.salt = sjcl.codec.base64.toBits(p.salt);\n    }\n    if (typeof p.iv === \"string\") {\n      p.iv = sjcl.codec.base64.toBits(p.iv);\n    }\n    \n    if (!sjcl.mode[p.mode] ||\n        !sjcl.cipher[p.cipher] ||\n        (typeof password === \"string\" && p.iter <= 100) ||\n        (p.ts !== 64 && p.ts !== 96 && p.ts !== 128) ||\n        (p.ks !== 128 && p.ks !== 192 && p.ks !== 256) ||\n        (!p.iv) ||\n        (p.iv.length < 2 || p.iv.length > 4)) {\n      throw new sjcl.exception.invalid(\"json decrypt: invalid parameters\");\n    }\n    \n    if (typeof password === \"string\") {\n      tmp = sjcl.misc.cachedPbkdf2(password, p);\n      password = tmp.key.slice(0,p.ks/32);\n      p.salt  = tmp.salt;\n    } else if (sjcl.ecc && password instanceof sjcl.ecc.elGamal.secretKey) {\n      password = password.unkem(sjcl.codec.base64.toBits(p.kemtag)).slice(0,p.ks/32);\n    }\n    if (typeof adata === \"string\") {\n      adata = sjcl.codec.utf8String.toBits(adata);\n    }\n    prp = new sjcl.cipher[p.cipher](password);\n    \n    /* do the decryption */\n    ct = sjcl.mode[p.mode].decrypt(prp, p.ct, p.iv, adata, p.ts);\n    \n    /* return the json data */\n    j._add(rp, p);\n    rp.key = password;\n    \n    return sjcl.codec.utf8String.fromBits(ct);\n  },\n  \n  /** Encode a flat structure into a JSON string.\n   * @param {Object} obj The structure to encode.\n   * @return {String} A JSON string.\n   * @throws {sjcl.exception.invalid} if obj has a non-alphanumeric property.\n   * @throws {sjcl.exception.bug} if a parameter has an unsupported type.\n   */\n  encode: function (obj) {\n    var i, out='{', comma='';\n    for (i in obj) {\n      if (obj.hasOwnProperty(i)) {\n        if (!i.match(/^[a-z0-9]+$/i)) {\n          throw new sjcl.exception.invalid(\"json encode: invalid property name\");\n        }\n        out += comma + '\"' + i + '\":';\n        comma = ',';\n        \n        switch (typeof obj[i]) {\n        case 'number':\n        case 'boolean':\n          out += obj[i];\n          break;\n          \n        case 'string':\n          out += '\"' + escape(obj[i]) + '\"';\n          break;\n        \n        case 'object':\n          out += '\"' + sjcl.codec.base64.fromBits(obj[i],0) + '\"';\n          break;\n        \n        default:\n          throw new sjcl.exception.bug(\"json encode: unsupported type\");\n        }\n      }\n    }\n    return out+'}';\n  },\n  \n  /** Decode a simple (flat) JSON string into a structure.  The ciphertext,\n   * adata, salt and iv will be base64-decoded.\n   * @param {String} str The string.\n   * @return {Object} The decoded structure.\n   * @throws {sjcl.exception.invalid} if str isn't (simple) JSON.\n   */\n  decode: function (str) {\n    str = str.replace(/\\s/g,'');\n    if (!str.match(/^\\{.*\\}$/)) { \n      throw new sjcl.exception.invalid(\"json decode: this isn't json!\");\n    }\n    var a = str.replace(/^\\{|\\}$/g, '').split(/,/), out={}, i, m;\n    for (i=0; i<a.length; i++) {\n      if (!(m=a[i].match(/^(?:([\"']?)([a-z][a-z0-9]*)\\1):(?:(\\d+)|\"([a-z0-9+\\/%*_.@=\\-]*)\")$/i))) {\n        throw new sjcl.exception.invalid(\"json decode: this isn't json!\");\n      }\n      if (m[3]) {\n        out[m[2]] = parseInt(m[3],10);\n      } else {\n        out[m[2]] = m[2].match(/^(ct|salt|iv)$/) ? sjcl.codec.base64.toBits(m[4]) : unescape(m[4]);\n      }\n    }\n    return out;\n  },\n  \n  /** Insert all elements of src into target, modifying and returning target.\n   * @param {Object} target The object to be modified.\n   * @param {Object} src The object to pull data from.\n   * @param {boolean} [requireSame=false] If true, throw an exception if any field of target differs from corresponding field of src.\n   * @return {Object} target.\n   * @private\n   */\n  _add: function (target, src, requireSame) {\n    if (target === undefined) { target = {}; }\n    if (src === undefined) { return target; }\n    var i;\n    for (i in src) {\n      if (src.hasOwnProperty(i)) {\n        if (requireSame && target[i] !== undefined && target[i] !== src[i]) {\n          throw new sjcl.exception.invalid(\"required parameter overridden\");\n        }\n        target[i] = src[i];\n      }\n    }\n    return target;\n  },\n  \n  /** Remove all elements of minus from plus.  Does not modify plus.\n   * @private\n   */\n  _subtract: function (plus, minus) {\n    var out = {}, i;\n    \n    for (i in plus) {\n      if (plus.hasOwnProperty(i) && plus[i] !== minus[i]) {\n        out[i] = plus[i];\n      }\n    }\n    \n    return out;\n  },\n  \n  /** Return only the specified elements of src.\n   * @private\n   */\n  _filter: function (src, filter) {\n    var out = {}, i;\n    for (i=0; i<filter.length; i++) {\n      if (src[filter[i]] !== undefined) {\n        out[filter[i]] = src[filter[i]];\n      }\n    }\n    return out;\n  }\n};\n\n/** Simple encryption function; convenient shorthand for sjcl.json.encrypt.\n * @param {String|bitArray} password The password or key.\n * @param {String} plaintext The data to encrypt.\n * @param {Object} [params] The parameters including tag, iv and salt.\n * @param {Object} [rp] A returned version with filled-in parameters.\n * @return {String} The ciphertext.\n */\nsjcl.encrypt = sjcl.json.encrypt;\n\n/** Simple decryption function; convenient shorthand for sjcl.json.decrypt.\n * @param {String|bitArray} password The password or key.\n * @param {String} ciphertext The ciphertext to decrypt.\n * @param {Object} [params] Additional non-default parameters.\n * @param {Object} [rp] A returned object with filled parameters.\n * @return {String} The plaintext.\n */\nsjcl.decrypt = sjcl.json.decrypt;\n\n/** The cache for cachedPbkdf2.\n * @private\n */\nsjcl.misc._pbkdf2Cache = {};\n\n/** Cached PBKDF2 key derivation.\n * @param {String} password The password.\n * @param {Object} [params] The derivation params (iteration count and optional salt).\n * @return {Object} The derived data in key, the salt in salt.\n */\nsjcl.misc.cachedPbkdf2 = function (password, obj) {\n  var cache = sjcl.misc._pbkdf2Cache, c, cp, str, salt, iter;\n  \n  obj = obj || {};\n  iter = obj.iter || 1000;\n  \n  /* open the cache for this password and iteration count */\n  cp = cache[password] = cache[password] || {};\n  c = cp[iter] = cp[iter] || { firstSalt: (obj.salt && obj.salt.length) ?\n                     obj.salt.slice(0) : sjcl.random.randomWords(2,0) };\n          \n  salt = (obj.salt === undefined) ? c.firstSalt : obj.salt;\n  \n  c[salt] = c[salt] || sjcl.misc.pbkdf2(password, salt, obj.iter);\n  return { key: c[salt].slice(0), salt:salt.slice(0) };\n};\n\n\n\n/**\n * @constructor\n * Constructs a new bignum from another bignum, a number or a hex string.\n */\nsjcl.bn = function(it) {\n  this.initWith(it);\n};\n\nsjcl.bn.prototype = {\n  radix: 24,\n  maxMul: 8,\n  _class: sjcl.bn,\n  \n  copy: function() {\n    return new this._class(this);\n  },\n\n  /**\n   * Initializes this with it, either as a bn, a number, or a hex string.\n   */\n  initWith: function(it) {\n    var i=0, k, n, l;\n    switch(typeof it) {\n    case \"object\":\n      this.limbs = it.limbs.slice(0);\n      break;\n      \n    case \"number\":\n      this.limbs = [it];\n      this.normalize();\n      break;\n      \n    case \"string\":\n      it = it.replace(/^0x/, '');\n      this.limbs = [];\n      // hack\n      k = this.radix / 4;\n      for (i=0; i < it.length; i+=k) {\n        this.limbs.push(parseInt(it.substring(Math.max(it.length - i - k, 0), it.length - i),16));\n      }\n      break;\n\n    default:\n      this.limbs = [0];\n    }\n    return this;\n  },\n\n  /**\n   * Returns true if \"this\" and \"that\" are equal.  Calls fullReduce().\n   * Equality test is in constant time.\n   */\n  equals: function(that) {\n    if (typeof that === \"number\") { that = new this._class(that); }\n    var difference = 0, i;\n    this.fullReduce();\n    that.fullReduce();\n    for (i = 0; i < this.limbs.length || i < that.limbs.length; i++) {\n      difference |= this.getLimb(i) ^ that.getLimb(i);\n    }\n    return (difference === 0);\n  },\n  \n  /**\n   * Get the i'th limb of this, zero if i is too large.\n   */\n  getLimb: function(i) {\n    return (i >= this.limbs.length) ? 0 : this.limbs[i];\n  },\n  \n  /**\n   * Constant time comparison function.\n   * Returns 1 if this >= that, or zero otherwise.\n   */\n  greaterEquals: function(that) {\n    if (typeof that === \"number\") { that = new this._class(that); }\n    var less = 0, greater = 0, i, a, b;\n    i = Math.max(this.limbs.length, that.limbs.length) - 1;\n    for (; i>= 0; i--) {\n      a = this.getLimb(i);\n      b = that.getLimb(i);\n      greater |= (b - a) & ~less;\n      less |= (a - b) & ~greater;\n    }\n    return (greater | ~less) >>> 31;\n  },\n  \n  /**\n   * Convert to a hex string.\n   */\n  toString: function() {\n    this.fullReduce();\n    var out=\"\", i, s, l = this.limbs;\n    for (i=0; i < this.limbs.length; i++) {\n      s = l[i].toString(16);\n      while (i < this.limbs.length - 1 && s.length < 6) {\n        s = \"0\" + s;\n      }\n      out = s + out;\n    }\n    return \"0x\"+out;\n  },\n  \n  /** this += that.  Does not normalize. */\n  addM: function(that) {\n    if (typeof(that) !== \"object\") { that = new this._class(that); }\n    var i, l=this.limbs, ll=that.limbs;\n    for (i=l.length; i<ll.length; i++) {\n      l[i] = 0;\n    }\n    for (i=0; i<ll.length; i++) {\n      l[i] += ll[i];\n    }\n    return this;\n  },\n  \n  /** this *= 2.  Requires normalized; ends up normalized. */\n  doubleM: function() {\n    var i, carry=0, tmp, r=this.radix, m=this.radixMask, l=this.limbs;\n    for (i=0; i<l.length; i++) {\n      tmp = l[i];\n      tmp = tmp+tmp+carry;\n      l[i] = tmp & m;\n      carry = tmp >> r;\n    }\n    if (carry) {\n      l.push(carry);\n    }\n    return this;\n  },\n  \n  /** this /= 2, rounded down.  Requires normalized; ends up normalized. */\n  halveM: function() {\n    var i, carry=0, tmp, r=this.radix, l=this.limbs;\n    for (i=l.length-1; i>=0; i--) {\n      tmp = l[i];\n      l[i] = (tmp+carry)>>1;\n      carry = (tmp&1) << r;\n    }\n    if (!l[l.length-1]) {\n      l.pop();\n    }\n    return this;\n  },\n\n  /** this -= that.  Does not normalize. */\n  subM: function(that) {\n    if (typeof(that) !== \"object\") { that = new this._class(that); }\n    var i, l=this.limbs, ll=that.limbs;\n    for (i=l.length; i<ll.length; i++) {\n      l[i] = 0;\n    }\n    for (i=0; i<ll.length; i++) {\n      l[i] -= ll[i];\n    }\n    return this;\n  },\n  \n  mod: function(that) {\n    var neg = !this.greaterEquals(new sjcl.bn(0));\n    \n    that = new sjcl.bn(that).normalize(); // copy before we begin\n    var out = new sjcl.bn(this).normalize(), ci=0;\n    \n    if (neg) out = (new sjcl.bn(0)).subM(out).normalize();\n    \n    for (; out.greaterEquals(that); ci++) {\n      that.doubleM();\n    }\n    \n    if (neg) out = that.sub(out).normalize();\n    \n    for (; ci > 0; ci--) {\n      that.halveM();\n      if (out.greaterEquals(that)) {\n        out.subM(that).normalize();\n      }\n    }\n    return out.trim();\n  },\n  \n  /** return inverse mod prime p.  p must be odd. Binary extended Euclidean algorithm mod p. */\n  inverseMod: function(p) {\n    var a = new sjcl.bn(1), b = new sjcl.bn(0), x = new sjcl.bn(this), y = new sjcl.bn(p), tmp, i, nz=1;\n    \n    if (!(p.limbs[0] & 1)) {\n      throw (new sjcl.exception.invalid(\"inverseMod: p must be odd\"));\n    }\n    \n    // invariant: y is odd\n    do {\n      if (x.limbs[0] & 1) {\n        if (!x.greaterEquals(y)) {\n          // x < y; swap everything\n          tmp = x; x = y; y = tmp;\n          tmp = a; a = b; b = tmp;\n        }\n        x.subM(y);\n        x.normalize();\n        \n        if (!a.greaterEquals(b)) {\n          a.addM(p);\n        }\n        a.subM(b);\n      }\n      \n      // cut everything in half\n      x.halveM();\n      if (a.limbs[0] & 1) {\n        a.addM(p);\n      }\n      a.normalize();\n      a.halveM();\n      \n      // check for termination: x ?= 0\n      for (i=nz=0; i<x.limbs.length; i++) {\n        nz |= x.limbs[i];\n      }\n    } while(nz);\n    \n    if (!y.equals(1)) {\n      throw (new sjcl.exception.invalid(\"inverseMod: p and x must be relatively prime\"));\n    }\n    \n    return b;\n  },\n  \n  /** this + that.  Does not normalize. */\n  add: function(that) {\n    return this.copy().addM(that);\n  },\n\n  /** this - that.  Does not normalize. */\n  sub: function(that) {\n    return this.copy().subM(that);\n  },\n  \n  /** this * that.  Normalizes and reduces. */\n  mul: function(that) {\n    if (typeof(that) === \"number\") { that = new this._class(that); }\n    var i, j, a = this.limbs, b = that.limbs, al = a.length, bl = b.length, out = new this._class(), c = out.limbs, ai, ii=this.maxMul;\n\n    for (i=0; i < this.limbs.length + that.limbs.length + 1; i++) {\n      c[i] = 0;\n    }\n    for (i=0; i<al; i++) {\n      ai = a[i];\n      for (j=0; j<bl; j++) {\n        c[i+j] += ai * b[j];\n      }\n     \n      if (!--ii) {\n        ii = this.maxMul;\n        out.cnormalize();\n      }\n    }\n    return out.cnormalize().reduce();\n  },\n\n  /** this ^ 2.  Normalizes and reduces. */\n  square: function() {\n    return this.mul(this);\n  },\n\n  /** this ^ n.  Uses square-and-multiply.  Normalizes and reduces. */\n  power: function(l) {\n    if (typeof(l) === \"number\") {\n      l = [l];\n    } else if (l.limbs !== undefined) {\n      l = l.normalize().limbs;\n    }\n    var i, j, out = new this._class(1), pow = this;\n\n    for (i=0; i<l.length; i++) {\n      for (j=0; j<this.radix; j++) {\n        if (l[i] & (1<<j)) {\n          out = out.mul(pow);\n        }\n        pow = pow.square();\n      }\n    }\n    \n    return out;\n  },\n\n  /** this * that mod N */\n  mulmod: function(that, N) {\n    return this.mod(N).mul(that.mod(N)).mod(N);\n  },\n\n  /** this ^ x mod N */\n  powermod: function(x, N) {\n    var result = new sjcl.bn(1), a = new sjcl.bn(this), k = new sjcl.bn(x);\n    while (true) {\n      if (k.limbs[0] & 1) { result = result.mulmod(a, N); }\n      k.halveM();\n      if (k.equals(0)) { break; }\n      a = a.mulmod(a, N);\n    }\n    return result.normalize().reduce();\n  },\n\n  trim: function() {\n    var l = this.limbs, p;\n    do {\n      p = l.pop();\n    } while (l.length && p === 0);\n    l.push(p);\n    return this;\n  },\n  \n  /** Reduce mod a modulus.  Stubbed for subclassing. */\n  reduce: function() {\n    return this;\n  },\n\n  /** Reduce and normalize. */\n  fullReduce: function() {\n    return this.normalize();\n  },\n  \n  /** Propagate carries. */\n  normalize: function() {\n    var carry=0, i, pv = this.placeVal, ipv = this.ipv, l, m, limbs = this.limbs, ll = limbs.length, mask = this.radixMask;\n    for (i=0; i < ll || (carry !== 0 && carry !== -1); i++) {\n      l = (limbs[i]||0) + carry;\n      m = limbs[i] = l & mask;\n      carry = (l-m)*ipv;\n    }\n    if (carry === -1) {\n      limbs[i-1] -= this.placeVal;\n    }\n    return this;\n  },\n\n  /** Constant-time normalize. Does not allocate additional space. */\n  cnormalize: function() {\n    var carry=0, i, ipv = this.ipv, l, m, limbs = this.limbs, ll = limbs.length, mask = this.radixMask;\n    for (i=0; i < ll-1; i++) {\n      l = limbs[i] + carry;\n      m = limbs[i] = l & mask;\n      carry = (l-m)*ipv;\n    }\n    limbs[i] += carry;\n    return this;\n  },\n  \n  /** Serialize to a bit array */\n  toBits: function(len) {\n    this.fullReduce();\n    len = len || this.exponent || this.bitLength();\n    var i = Math.floor((len-1)/24), w=sjcl.bitArray, e = (len + 7 & -8) % this.radix || this.radix,\n        out = [w.partial(e, this.getLimb(i))];\n    for (i--; i >= 0; i--) {\n      out = w.concat(out, [w.partial(Math.min(this.radix,len), this.getLimb(i))]);\n      len -= this.radix;\n    }\n    return out;\n  },\n  \n  /** Return the length in bits, rounded up to the nearest byte. */\n  bitLength: function() {\n    this.fullReduce();\n    var out = this.radix * (this.limbs.length - 1),\n        b = this.limbs[this.limbs.length - 1];\n    for (; b; b >>>= 1) {\n      out ++;\n    }\n    return out+7 & -8;\n  }\n};\n\n/** @this { sjcl.bn } */\nsjcl.bn.fromBits = function(bits) {\n  var Class = this, out = new Class(), words=[], w=sjcl.bitArray, t = this.prototype,\n      l = Math.min(this.bitLength || 0x100000000, w.bitLength(bits)), e = l % t.radix || t.radix;\n  \n  words[0] = w.extract(bits, 0, e);\n  for (; e < l; e += t.radix) {\n    words.unshift(w.extract(bits, e, t.radix));\n  }\n\n  out.limbs = words;\n  return out;\n};\n\n\n\nsjcl.bn.prototype.ipv = 1 / (sjcl.bn.prototype.placeVal = Math.pow(2,sjcl.bn.prototype.radix));\nsjcl.bn.prototype.radixMask = (1 << sjcl.bn.prototype.radix) - 1;\n\n/**\n * Creates a new subclass of bn, based on reduction modulo a pseudo-Mersenne prime,\n * i.e. a prime of the form 2^e + sum(a * 2^b),where the sum is negative and sparse.\n */\nsjcl.bn.pseudoMersennePrime = function(exponent, coeff) {\n  /** @constructor */\n  function p(it) {\n    this.initWith(it);\n    /*if (this.limbs[this.modOffset]) {\n      this.reduce();\n    }*/\n  }\n\n  var ppr = p.prototype = new sjcl.bn(), i, tmp, mo;\n  mo = ppr.modOffset = Math.ceil(tmp = exponent / ppr.radix);\n  ppr.exponent = exponent;\n  ppr.offset = [];\n  ppr.factor = [];\n  ppr.minOffset = mo;\n  ppr.fullMask = 0;\n  ppr.fullOffset = [];\n  ppr.fullFactor = [];\n  ppr.modulus = p.modulus = new sjcl.bn(Math.pow(2,exponent));\n  \n  ppr.fullMask = 0|-Math.pow(2, exponent % ppr.radix);\n\n  for (i=0; i<coeff.length; i++) {\n    ppr.offset[i] = Math.floor(coeff[i][0] / ppr.radix - tmp);\n    ppr.fullOffset[i] = Math.ceil(coeff[i][0] / ppr.radix - tmp);\n    ppr.factor[i] = coeff[i][1] * Math.pow(1/2, exponent - coeff[i][0] + ppr.offset[i] * ppr.radix);\n    ppr.fullFactor[i] = coeff[i][1] * Math.pow(1/2, exponent - coeff[i][0] + ppr.fullOffset[i] * ppr.radix);\n    ppr.modulus.addM(new sjcl.bn(Math.pow(2,coeff[i][0])*coeff[i][1]));\n    ppr.minOffset = Math.min(ppr.minOffset, -ppr.offset[i]); // conservative\n  }\n  ppr._class = p;\n  ppr.modulus.cnormalize();\n\n  /** Approximate reduction mod p.  May leave a number which is negative or slightly larger than p.\n   * @this {sjcl.bn}\n   */\n  ppr.reduce = function() {\n    var i, k, l, mo = this.modOffset, limbs = this.limbs, aff, off = this.offset, ol = this.offset.length, fac = this.factor, ll;\n\n    i = this.minOffset;\n    while (limbs.length > mo) {\n      l = limbs.pop();\n      ll = limbs.length;\n      for (k=0; k<ol; k++) {\n        limbs[ll+off[k]] -= fac[k] * l;\n      }\n      \n      i--;\n      if (!i) {\n        limbs.push(0);\n        this.cnormalize();\n        i = this.minOffset;\n      }\n    }\n    this.cnormalize();\n\n    return this;\n  };\n  \n  /** @this {sjcl.bn} */\n  ppr._strongReduce = (ppr.fullMask === -1) ? ppr.reduce : function() {\n    var limbs = this.limbs, i = limbs.length - 1, k, l;\n    this.reduce();\n    if (i === this.modOffset - 1) {\n      l = limbs[i] & this.fullMask;\n      limbs[i] -= l;\n      for (k=0; k<this.fullOffset.length; k++) {\n        limbs[i+this.fullOffset[k]] -= this.fullFactor[k] * l;\n      }\n      this.normalize();\n    }\n  };\n\n  /** mostly constant-time, very expensive full reduction.\n   * @this {sjcl.bn}\n   */\n  ppr.fullReduce = function() {\n    var greater, i;\n    // massively above the modulus, may be negative\n    \n    this._strongReduce();\n    // less than twice the modulus, may be negative\n\n    this.addM(this.modulus);\n    this.addM(this.modulus);\n    this.normalize();\n    // probably 2-3x the modulus\n    \n    this._strongReduce();\n    // less than the power of 2.  still may be more than\n    // the modulus\n\n    // HACK: pad out to this length\n    for (i=this.limbs.length; i<this.modOffset; i++) {\n      this.limbs[i] = 0;\n    }\n    \n    // constant-time subtract modulus\n    greater = this.greaterEquals(this.modulus);\n    for (i=0; i<this.limbs.length; i++) {\n      this.limbs[i] -= this.modulus.limbs[i] * greater;\n    }\n    this.cnormalize();\n\n    return this;\n  };\n\n\n  /** @this {sjcl.bn} */\n  ppr.inverse = function() {\n    return (this.power(this.modulus.sub(2)));\n  };\n\n  p.fromBits = sjcl.bn.fromBits;\n\n  return p;\n};\n\n// a small Mersenne prime\nsjcl.bn.prime = {\n  p127: sjcl.bn.pseudoMersennePrime(127, [[0,-1]]),\n\n  // Bernstein's prime for Curve25519\n  p25519: sjcl.bn.pseudoMersennePrime(255, [[0,-19]]),\n\n  // NIST primes\n  p192: sjcl.bn.pseudoMersennePrime(192, [[0,-1],[64,-1]]),\n  p224: sjcl.bn.pseudoMersennePrime(224, [[0,1],[96,-1]]),\n  p256: sjcl.bn.pseudoMersennePrime(256, [[0,-1],[96,1],[192,1],[224,-1]]),\n  p384: sjcl.bn.pseudoMersennePrime(384, [[0,-1],[32,1],[96,-1],[128,-1]]),\n  p521: sjcl.bn.pseudoMersennePrime(521, [[0,-1]])\n};\n\nsjcl.bn.random = function(modulus, paranoia) {\n  if (typeof modulus !== \"object\") { modulus = new sjcl.bn(modulus); }\n  var words, i, l = modulus.limbs.length, m = modulus.limbs[l-1]+1, out = new sjcl.bn();\n  while (true) {\n    // get a sequence whose first digits make sense\n    do {\n      words = sjcl.random.randomWords(l, paranoia);\n      if (words[l-1] < 0) { words[l-1] += 0x100000000; }\n    } while (Math.floor(words[l-1] / m) === Math.floor(0x100000000 / m));\n    words[l-1] %= m;\n\n    // mask off all the limbs\n    for (i=0; i<l-1; i++) {\n      words[i] &= modulus.radixMask;\n    }\n\n    // check the rest of the digitssj\n    out.limbs = words;\n    if (!out.greaterEquals(modulus)) {\n      return out;\n    }\n  }\n};\n\n\nsjcl.ecc = {};\n\n/**\n * Represents a point on a curve in affine coordinates.\n * @constructor\n * @param {sjcl.ecc.curve} curve The curve that this point lies on.\n * @param {bigInt} x The x coordinate.\n * @param {bigInt} y The y coordinate.\n */\nsjcl.ecc.point = function(curve,x,y) {\n  if (x === undefined) {\n    this.isIdentity = true;\n  } else {\n    if (x instanceof sjcl.bn) {\n      x = new curve.field(x);\n    }\n    if (y instanceof sjcl.bn) {\n      y = new curve.field(y);\n    }\n\n    this.x = x;\n    this.y = y;\n\n    this.isIdentity = false;\n  }\n  this.curve = curve;\n};\n\n\n\nsjcl.ecc.point.prototype = {\n  toJac: function() {\n    return new sjcl.ecc.pointJac(this.curve, this.x, this.y, new this.curve.field(1));\n  },\n\n  mult: function(k) {\n    return this.toJac().mult(k, this).toAffine();\n  },\n  \n  /**\n   * Multiply this point by k, added to affine2*k2, and return the answer in Jacobian coordinates.\n   * @param {bigInt} k The coefficient to multiply this by.\n   * @param {bigInt} k2 The coefficient to multiply affine2 this by.\n   * @param {sjcl.ecc.point} affine The other point in affine coordinates.\n   * @return {sjcl.ecc.pointJac} The result of the multiplication and addition, in Jacobian coordinates.\n   */\n  mult2: function(k, k2, affine2) {\n    return this.toJac().mult2(k, this, k2, affine2).toAffine();\n  },\n  \n  multiples: function() {\n    var m, i, j;\n    if (this._multiples === undefined) {\n      j = this.toJac().doubl();\n      m = this._multiples = [new sjcl.ecc.point(this.curve), this, j.toAffine()];\n      for (i=3; i<16; i++) {\n        j = j.add(this);\n        m.push(j.toAffine());\n      }\n    }\n    return this._multiples;\n  },\n\n  isValid: function() {\n    return this.y.square().equals(this.curve.b.add(this.x.mul(this.curve.a.add(this.x.square()))));\n  },\n\n  toBits: function() {\n    return sjcl.bitArray.concat(this.x.toBits(), this.y.toBits());\n  }\n};\n\n/**\n * Represents a point on a curve in Jacobian coordinates. Coordinates can be specified as bigInts or strings (which\n * will be converted to bigInts).\n *\n * @constructor\n * @param {bigInt/string} x The x coordinate.\n * @param {bigInt/string} y The y coordinate.\n * @param {bigInt/string} z The z coordinate.\n * @param {sjcl.ecc.curve} curve The curve that this point lies on.\n */\nsjcl.ecc.pointJac = function(curve, x, y, z) {\n  if (x === undefined) {\n    this.isIdentity = true;\n  } else {\n    this.x = x;\n    this.y = y;\n    this.z = z;\n    this.isIdentity = false;\n  }\n  this.curve = curve;\n};\n\nsjcl.ecc.pointJac.prototype = {\n  /**\n   * Adds S and T and returns the result in Jacobian coordinates. Note that S must be in Jacobian coordinates and T must be in affine coordinates.\n   * @param {sjcl.ecc.pointJac} S One of the points to add, in Jacobian coordinates.\n   * @param {sjcl.ecc.point} T The other point to add, in affine coordinates.\n   * @return {sjcl.ecc.pointJac} The sum of the two points, in Jacobian coordinates. \n   */\n  add: function(T) {\n    var S = this, sz2, c, d, c2, x1, x2, x, y1, y2, y, z;\n    if (S.curve !== T.curve) {\n      throw(\"sjcl.ecc.add(): Points must be on the same curve to add them!\");\n    }\n\n    if (S.isIdentity) {\n      return T.toJac();\n    } else if (T.isIdentity) {\n      return S;\n    }\n\n    sz2 = S.z.square();\n    c = T.x.mul(sz2).subM(S.x);\n\n    if (c.equals(0)) {\n      if (S.y.equals(T.y.mul(sz2.mul(S.z)))) {\n        // same point\n        return S.doubl();\n      } else {\n        // inverses\n        return new sjcl.ecc.pointJac(S.curve);\n      }\n    }\n    \n    d = T.y.mul(sz2.mul(S.z)).subM(S.y);\n    c2 = c.square();\n\n    x1 = d.square();\n    x2 = c.square().mul(c).addM( S.x.add(S.x).mul(c2) );\n    x  = x1.subM(x2);\n\n    y1 = S.x.mul(c2).subM(x).mul(d);\n    y2 = S.y.mul(c.square().mul(c));\n    y  = y1.subM(y2);\n\n    z  = S.z.mul(c);\n\n    return new sjcl.ecc.pointJac(this.curve,x,y,z);\n  },\n  \n  /**\n   * doubles this point.\n   * @return {sjcl.ecc.pointJac} The doubled point.\n   */\n  doubl: function() {\n    if (this.isIdentity) { return this; }\n\n    var\n      y2 = this.y.square(),\n      a  = y2.mul(this.x.mul(4)),\n      b  = y2.square().mul(8),\n      z2 = this.z.square(),\n      c  = this.x.sub(z2).mul(3).mul(this.x.add(z2)),\n      x  = c.square().subM(a).subM(a),\n      y  = a.sub(x).mul(c).subM(b),\n      z  = this.y.add(this.y).mul(this.z);\n    return new sjcl.ecc.pointJac(this.curve, x, y, z);\n  },\n\n  /**\n   * Returns a copy of this point converted to affine coordinates.\n   * @return {sjcl.ecc.point} The converted point.\n   */  \n  toAffine: function() {\n    if (this.isIdentity || this.z.equals(0)) {\n      return new sjcl.ecc.point(this.curve);\n    }\n    var zi = this.z.inverse(), zi2 = zi.square();\n    return new sjcl.ecc.point(this.curve, this.x.mul(zi2).fullReduce(), this.y.mul(zi2.mul(zi)).fullReduce());\n  },\n  \n  /**\n   * Multiply this point by k and return the answer in Jacobian coordinates.\n   * @param {bigInt} k The coefficient to multiply by.\n   * @param {sjcl.ecc.point} affine This point in affine coordinates.\n   * @return {sjcl.ecc.pointJac} The result of the multiplication, in Jacobian coordinates.\n   */\n  mult: function(k, affine) {\n    if (typeof(k) === \"number\") {\n      k = [k];\n    } else if (k.limbs !== undefined) {\n      k = k.normalize().limbs;\n    }\n    \n    var i, j, out = new sjcl.ecc.point(this.curve).toJac(), multiples = affine.multiples();\n\n    for (i=k.length-1; i>=0; i--) {\n      for (j=sjcl.bn.prototype.radix-4; j>=0; j-=4) {\n        out = out.doubl().doubl().doubl().doubl().add(multiples[k[i]>>j & 0xF]);\n      }\n    }\n    \n    return out;\n  },\n  \n  /**\n   * Multiply this point by k, added to affine2*k2, and return the answer in Jacobian coordinates.\n   * @param {bigInt} k The coefficient to multiply this by.\n   * @param {sjcl.ecc.point} affine This point in affine coordinates.\n   * @param {bigInt} k2 The coefficient to multiply affine2 this by.\n   * @param {sjcl.ecc.point} affine The other point in affine coordinates.\n   * @return {sjcl.ecc.pointJac} The result of the multiplication and addition, in Jacobian coordinates.\n   */\n  mult2: function(k1, affine, k2, affine2) {\n    if (typeof(k1) === \"number\") {\n      k1 = [k1];\n    } else if (k1.limbs !== undefined) {\n      k1 = k1.normalize().limbs;\n    }\n    \n    if (typeof(k2) === \"number\") {\n      k2 = [k2];\n    } else if (k2.limbs !== undefined) {\n      k2 = k2.normalize().limbs;\n    }\n    \n    var i, j, out = new sjcl.ecc.point(this.curve).toJac(), m1 = affine.multiples(),\n        m2 = affine2.multiples(), l1, l2;\n\n    for (i=Math.max(k1.length,k2.length)-1; i>=0; i--) {\n      l1 = k1[i] | 0;\n      l2 = k2[i] | 0;\n      for (j=sjcl.bn.prototype.radix-4; j>=0; j-=4) {\n        out = out.doubl().doubl().doubl().doubl().add(m1[l1>>j & 0xF]).add(m2[l2>>j & 0xF]);\n      }\n    }\n    \n    return out;\n  },\n\n  isValid: function() {\n    var z2 = this.z.square(), z4 = z2.square(), z6 = z4.mul(z2);\n    return this.y.square().equals(\n             this.curve.b.mul(z6).add(this.x.mul(\n               this.curve.a.mul(z4).add(this.x.square()))));\n  }\n};\n\n/**\n * Construct an elliptic curve. Most users will not use this and instead start with one of the NIST curves defined below.\n *\n * @constructor\n * @param {bigInt} p The prime modulus.\n * @param {bigInt} r The prime order of the curve.\n * @param {bigInt} a The constant a in the equation of the curve y^2 = x^3 + ax + b (for NIST curves, a is always -3).\n * @param {bigInt} x The x coordinate of a base point of the curve.\n * @param {bigInt} y The y coordinate of a base point of the curve.\n */\nsjcl.ecc.curve = function(Field, r, a, b, x, y) {\n  this.field = Field;\n  this.r = Field.prototype.modulus.sub(r);\n  this.a = new Field(a);\n  this.b = new Field(b);\n  this.G = new sjcl.ecc.point(this, new Field(x), new Field(y));\n};\n\nsjcl.ecc.curve.prototype.fromBits = function (bits) {\n  var w = sjcl.bitArray, l = this.field.prototype.exponent + 7 & -8,\n      p = new sjcl.ecc.point(this, this.field.fromBits(w.bitSlice(bits, 0, l)),\n                             this.field.fromBits(w.bitSlice(bits, l, 2*l)));\n  if (!p.isValid()) {\n    throw new sjcl.exception.corrupt(\"not on the curve!\");\n  }\n  return p;\n};\n\nsjcl.ecc.curves = {\n  c192: new sjcl.ecc.curve(\n    sjcl.bn.prime.p192,\n    \"0x662107c8eb94364e4b2dd7ce\",\n    -3,\n    \"0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1\",\n    \"0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012\",\n    \"0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811\"),\n\n  c224: new sjcl.ecc.curve(\n    sjcl.bn.prime.p224,\n    \"0xe95c1f470fc1ec22d6baa3a3d5c4\",\n    -3,\n    \"0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4\",\n    \"0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21\",\n    \"0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34\"),\n\n  c256: new sjcl.ecc.curve(\n    sjcl.bn.prime.p256,\n    \"0x4319055358e8617b0c46353d039cdaae\",\n    -3,\n    \"0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b\",\n    \"0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296\",\n    \"0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5\"),\n\n  c384: new sjcl.ecc.curve(\n    sjcl.bn.prime.p384,\n    \"0x389cb27e0bc8d21fa7e5f24cb74f58851313e696333ad68c\",\n    -3,\n    \"0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef\",\n    \"0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7\",\n    \"0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f\")\n};\n\n\n/* Diffie-Hellman-like public-key system */\nsjcl.ecc._dh = function(cn) {\n  sjcl.ecc[cn] = {\n    /** @constructor */\n    publicKey: function(curve, point) {\n      this._curve = curve;\n      this._curveBitLength = curve.r.bitLength();\n      if (point instanceof Array) {\n        this._point = curve.fromBits(point);\n      } else {\n        this._point = point;\n      }\n\n      this.get = function() {\n        var pointbits = this._point.toBits();\n        var len = sjcl.bitArray.bitLength(pointbits);\n        var x = sjcl.bitArray.bitSlice(pointbits, 0, len/2);\n        var y = sjcl.bitArray.bitSlice(pointbits, len/2);\n        return { x: x, y: y };\n      }\n    },\n\n    /** @constructor */\n    secretKey: function(curve, exponent) {\n      this._curve = curve;\n      this._curveBitLength = curve.r.bitLength();\n      this._exponent = exponent;\n\n      this.get = function() {\n        return this._exponent.toBits();\n      }\n    },\n\n    /** @constructor */\n    generateKeys: function(curve, paranoia, sec) {\n      if (curve === undefined) {\n        curve = 256;\n      }\n      if (typeof curve === \"number\") {\n        curve = sjcl.ecc.curves['c'+curve];\n        if (curve === undefined) {\n          throw new sjcl.exception.invalid(\"no such curve\");\n        }\n      }\n      if (sec === undefined) {\n        var sec = sjcl.bn.random(curve.r, paranoia);\n      }\n      var pub = curve.G.mult(sec);\n      return { pub: new sjcl.ecc[cn].publicKey(curve, pub),\n               sec: new sjcl.ecc[cn].secretKey(curve, sec) };\n    }\n  }; \n};\n\nsjcl.ecc._dh(\"elGamal\");\n\nsjcl.ecc.elGamal.publicKey.prototype = {\n  kem: function(paranoia) {\n    var sec = sjcl.bn.random(this._curve.r, paranoia),\n        tag = this._curve.G.mult(sec).toBits(),\n        key = sjcl.hash.sha256.hash(this._point.mult(sec).toBits());\n    return { key: key, tag: tag };\n  }\n};\n\nsjcl.ecc.elGamal.secretKey.prototype = {\n  unkem: function(tag) {\n    return sjcl.hash.sha256.hash(this._curve.fromBits(tag).mult(this._exponent).toBits());\n  },\n\n  dh: function(pk) {\n    return sjcl.hash.sha256.hash(pk._point.mult(this._exponent).toBits());\n  }\n};\n\nsjcl.ecc._dh(\"ecdsa\");\n\nsjcl.ecc.ecdsa.secretKey.prototype = {\n  sign: function(hash, paranoia, fakeLegacyVersion, fixedKForTesting) {\n    if (sjcl.bitArray.bitLength(hash) > this._curveBitLength) {\n      hash = sjcl.bitArray.clamp(hash, this._curveBitLength);\n    }\n    var R  = this._curve.r,\n        l  = R.bitLength(),\n        k  = fixedKForTesting || sjcl.bn.random(R.sub(1), paranoia).add(1),\n        r  = this._curve.G.mult(k).x.mod(R),\n        ss = sjcl.bn.fromBits(hash).add(r.mul(this._exponent)),\n        s  = fakeLegacyVersion ? ss.inverseMod(R).mul(k).mod(R)\n             : ss.mul(k.inverseMod(R)).mod(R);\n    return sjcl.bitArray.concat(r.toBits(l), s.toBits(l));\n  }\n};\n\nsjcl.ecc.ecdsa.publicKey.prototype = {\n  verify: function(hash, rs, fakeLegacyVersion) {\n    if (sjcl.bitArray.bitLength(hash) > this._curveBitLength) {\n      hash = sjcl.bitArray.clamp(hash, this._curveBitLength);\n    }\n    var w = sjcl.bitArray,\n        R = this._curve.r,\n        l = this._curveBitLength,\n        r = sjcl.bn.fromBits(w.bitSlice(rs,0,l)),\n        ss = sjcl.bn.fromBits(w.bitSlice(rs,l,2*l)),\n        s = fakeLegacyVersion ? ss : ss.inverseMod(R),\n        hG = sjcl.bn.fromBits(hash).mul(s).mod(R),\n        hA = r.mul(s).mod(R),\n        r2 = this._curve.G.mult2(hG, hA, this._point).x;\n    if (r.equals(0) || ss.equals(0) || r.greaterEquals(R) || ss.greaterEquals(R) || !r2.equals(r)) {\n      if (fakeLegacyVersion === undefined) {\n        return this.verify(hash, rs, true);\n      } else {\n        throw (new sjcl.exception.corrupt(\"signature didn't check out\"));\n      }\n    }\n    return true;\n  }\n};\n\n/** @fileOverview Javascript SRP implementation.\n *\n * This file contains a partial implementation of the SRP (Secure Remote\n * Password) password-authenticated key exchange protocol. Given a user\n * identity, salt, and SRP group, it generates the SRP verifier that may\n * be sent to a remote server to establish and SRP account.\n *\n * For more information, see http://srp.stanford.edu/.\n *\n * @author Quinn Slack\n */\n\n/**\n * Compute the SRP verifier from the username, password, salt, and group.\n * @class SRP\n */\nsjcl.keyexchange.srp = {\n  /**\n   * Calculates SRP v, the verifier. \n   *   v = g^x mod N [RFC 5054]\n   * @param {String} I The username.\n   * @param {String} P The password.\n   * @param {Object} s A bitArray of the salt.\n   * @param {Object} group The SRP group. Use sjcl.keyexchange.srp.knownGroup\n                           to obtain this object.\n   * @return {Object} A bitArray of SRP v.\n   */\n  makeVerifier: function(I, P, s, group) {\n    var x;\n    x = sjcl.keyexchange.srp.makeX(I, P, s);\n    x = sjcl.bn.fromBits(x);\n    return group.g.powermod(x, group.N);\n  },\n\n  /**\n   * Calculates SRP x.\n   *   x = SHA1(<salt> | SHA(<username> | \":\" | <raw password>)) [RFC 2945]\n   * @param {String} I The username.\n   * @param {String} P The password.\n   * @param {Object} s A bitArray of the salt.\n   * @return {Object} A bitArray of SRP x.\n   */\n  makeX: function(I, P, s) {\n    var inner = sjcl.hash.sha1.hash(I + ':' + P);\n    return sjcl.hash.sha1.hash(sjcl.bitArray.concat(s, inner));\n  },\n\n  /**\n   * Returns the known SRP group with the given size (in bits).\n   * @param {String} i The size of the known SRP group.\n   * @return {Object} An object with \"N\" and \"g\" properties.\n   */\n  knownGroup:function(i) {\n    if (typeof i !== \"string\") { i = i.toString(); }\n    if (!sjcl.keyexchange.srp._didInitKnownGroups) { sjcl.keyexchange.srp._initKnownGroups(); }\n    return sjcl.keyexchange.srp._knownGroups[i];\n  },\n\n  /**\n   * Initializes bignum objects for known group parameters.\n   * @private\n   */\n  _didInitKnownGroups: false,\n  _initKnownGroups:function() {\n    var i, size, group;\n    for (i=0; i < sjcl.keyexchange.srp._knownGroupSizes.length; i++) {\n      size = sjcl.keyexchange.srp._knownGroupSizes[i].toString();\n      group = sjcl.keyexchange.srp._knownGroups[size];\n      group.N = new sjcl.bn(group.N);\n      group.g = new sjcl.bn(group.g);\n    }\n    sjcl.keyexchange.srp._didInitKnownGroups = true;\n  },\n\n  _knownGroupSizes: [1024, 1536, 2048],\n  _knownGroups: {\n    1024: {\n      N: \"EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C\" +\n         \"9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4\" +\n         \"8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29\" +\n         \"7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A\" +\n         \"FD5138FE8376435B9FC61D2FC0EB06E3\",\n      g:2\n    },\n\n    1536: {\n      N: \"9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA961\" +\n         \"4B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F843\" +\n         \"80B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0B\" +\n         \"E3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF5\" +\n         \"6EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734A\" +\n         \"F7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E\" +\n         \"8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB\",\n      g: 2\n    },\n\n    2048: {\n      N: \"AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC319294\" +\n         \"3DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310D\" +\n         \"CD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FB\" +\n         \"D5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF74\" +\n         \"7359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A\" +\n         \"436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D\" +\n         \"5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E73\" +\n         \"03CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB6\" +\n         \"94B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F\" +\n         \"9E4AFF73\",\n      g: 2\n    }\n  }\n\n};\n\n\n/**\n *  Check that the point is valid based on the method described in\n *  SEC 1: Elliptic Curve Cryptography, section 3.2.2.1: \n *  Elliptic Curve Public Key Validation Primitive\n *  http://www.secg.org/download/aid-780/sec1-v2.pdf\n *\n *  @returns {Boolean}\n */\nsjcl.ecc.point.prototype.isValidPoint = function() {\n\n  var self = this;\n\n  var field_modulus = self.curve.field.modulus;\n\n  if (self.isIdentity) {\n    return false;\n  }\n\n  // Check that coordinatres are in bounds\n  // Return false if x < 1 or x > (field_modulus - 1)\n  if (((new sjcl.bn(1).greaterEquals(self.x)) &&\n    !self.x.equals(1)) ||\n    (self.x.greaterEquals(field_modulus.sub(1))) &&\n    !self.x.equals(1)) {\n\n    return false;\n  }\n\n  // Return false if y < 1 or y > (field_modulus - 1)\n  if (((new sjcl.bn(1).greaterEquals(self.y)) &&\n    !self.y.equals(1)) ||\n    (self.y.greaterEquals(field_modulus.sub(1))) &&\n    !self.y.equals(1)) {\n\n    return false;\n  }\n\n  if (!self.isOnCurve()) {\n    return false;\n  }\n\n  // TODO check to make sure point is a scalar multiple of base_point\n\n  return true;\n\n};\n\n/**\n *  Check that the point is on the curve\n *\n *  @returns {Boolean}\n */\nsjcl.ecc.point.prototype.isOnCurve = function() {\n\n  var self = this;\n\n  var field_order = self.curve.r;\n  var component_a = self.curve.a;\n  var component_b = self.curve.b;\n  var field_modulus = self.curve.field.modulus;\n\n  var left_hand_side = self.y.mul(self.y).mod(field_modulus);\n  var right_hand_side = self.x.mul(self.x).mul(self.x).add(component_a.mul(self.x)).add(component_b).mod(field_modulus);\n\n  return left_hand_side.equals(right_hand_side);\n\n};\n\n\nsjcl.ecc.point.prototype.toString = function() {\n  return '(' + \n    this.x.toString() + ', ' +\n    this.y.toString() +\n    ')';\n};\n\nsjcl.ecc.pointJac.prototype.toString = function() {\n  return '(' + \n    this.x.toString() + ', ' +\n    this.y.toString() + ', ' +\n    this.z.toString() +\n    ')';\n};\n\n// ----- for secp256k1 ------\n\n// Overwrite NIST-P256 with secp256k1\nsjcl.ecc.curves.c256 = new sjcl.ecc.curve(\n    sjcl.bn.pseudoMersennePrime(256, [[0,-1],[4,-1],[6,-1],[7,-1],[8,-1],[9,-1],[32,-1]]),\n    \"0x14551231950b75fc4402da1722fc9baee\",\n    0,\n    7,\n    \"0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\",\n    \"0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8\"\n);\n\n// Replace point addition and doubling algorithms\n// NIST-P256 is a=-3, we need algorithms for a=0\nsjcl.ecc.pointJac.prototype.add = function(T) {\n  var S = this;\n  if (S.curve !== T.curve) {\n    throw(\"sjcl.ecc.add(): Points must be on the same curve to add them!\");\n  }\n\n  if (S.isIdentity) {\n    return T.toJac();\n  } else if (T.isIdentity) {\n    return S;\n  }\n\n  var z1z1 = S.z.square();\n  var h = T.x.mul(z1z1).subM(S.x);\n  var s2 = T.y.mul(S.z).mul(z1z1);\n\n  if (h.equals(0)) {\n    if (S.y.equals(T.y.mul(z1z1.mul(S.z)))) {\n      // same point\n      return S.doubl();\n    } else {\n      // inverses\n      return new sjcl.ecc.pointJac(S.curve);\n    }\n  }\n\n  var hh = h.square();\n  var i = hh.copy().doubleM().doubleM();\n  var j = h.mul(i);\n  var r = s2.sub(S.y).doubleM();\n  var v = S.x.mul(i);\n  \n  var x = r.square().subM(j).subM(v.copy().doubleM());\n  var y = r.mul(v.sub(x)).subM(S.y.mul(j).doubleM());\n  var z = S.z.add(h).square().subM(z1z1).subM(hh);\n\n  return new sjcl.ecc.pointJac(this.curve,x,y,z);\n};\n\nsjcl.ecc.pointJac.prototype.doubl = function () {\n  if (this.isIdentity) { return this; }\n\n  var a = this.x.square();\n  var b = this.y.square();\n  var c = b.square();\n  var d = this.x.add(b).square().subM(a).subM(c).doubleM();\n  var e = a.mul(3);\n  var f = e.square();\n  var x = f.sub(d.copy().doubleM());\n  var y = e.mul(d.sub(x)).subM(c.doubleM().doubleM().doubleM());\n  var z = this.z.mul(this.y).doubleM();\n  return new sjcl.ecc.pointJac(this.curve, x, y, z);\n};\n\nsjcl.ecc.point.prototype.toBytesCompressed = function () {\n  var header = this.y.mod(2).toString() == \"0x0\" ? 0x02 : 0x03;\n  return [header].concat(sjcl.codec.bytes.fromBits(this.x.toBits()))\n};\n\n/** @fileOverview Javascript RIPEMD-160 implementation.\n *\n * @author Artem S Vybornov <vybornov@gmail.com>\n */\n(function() {\n\n/**\n * Context for a RIPEMD-160 operation in progress.\n * @constructor\n * @class RIPEMD, 160 bits.\n */\nsjcl.hash.ripemd160 = function (hash) {\n    if (hash) {\n        this._h = hash._h.slice(0);\n        this._buffer = hash._buffer.slice(0);\n        this._length = hash._length;\n    } else {\n        this.reset();\n    }\n};\n\n/**\n * Hash a string or an array of words.\n * @static\n * @param {bitArray|String} data the data to hash.\n * @return {bitArray} The hash value, an array of 5 big-endian words.\n */\nsjcl.hash.ripemd160.hash = function (data) {\n  return (new sjcl.hash.ripemd160()).update(data).finalize();\n};\n\nsjcl.hash.ripemd160.prototype = {\n    /**\n     * Reset the hash state.\n     * @return this\n     */\n    reset: function () {\n        this._h = _h0.slice(0);\n        this._buffer = [];\n        this._length = 0;\n        return this;\n    },\n\n    /**\n     * Reset the hash state.\n     * @param {bitArray|String} data the data to hash.\n     * @return this\n     */\n    update: function (data) {\n        if ( typeof data === \"string\" )\n            data = sjcl.codec.utf8String.toBits(data);\n\n        var i, b = this._buffer = sjcl.bitArray.concat(this._buffer, data),\n            ol = this._length,\n            nl = this._length = ol + sjcl.bitArray.bitLength(data);\n        for (i = 512+ol & -512; i <= nl; i+= 512) {\n            var words = b.splice(0,16);\n            for ( var w = 0; w < 16; ++w )\n                words[w] = _cvt(words[w]);\n\n            _block.call( this, words );\n        }\n\n        return this;\n    },\n\n    /**\n     * Complete hashing and output the hash value.\n     * @return {bitArray} The hash value, an array of 5 big-endian words.\n     */\n    finalize: function () {\n        var b = sjcl.bitArray.concat( this._buffer, [ sjcl.bitArray.partial(1,1) ] ),\n            l = ( this._length + 1 ) % 512,\n            z = ( l > 448 ? 512 : 448 ) - l % 448,\n            zp = z % 32;\n\n        if ( zp > 0 )\n            b = sjcl.bitArray.concat( b, [ sjcl.bitArray.partial(zp,0) ] )\n        for ( ; z >= 32; z -= 32 )\n            b.push(0);\n\n        b.push( _cvt( this._length | 0 ) );\n        b.push( _cvt( Math.floor(this._length / 0x100000000) ) );\n\n        while ( b.length ) {\n            var words = b.splice(0,16);\n            for ( var w = 0; w < 16; ++w )\n                words[w] = _cvt(words[w]);\n\n            _block.call( this, words );\n        }\n\n        var h = this._h;\n        this.reset();\n\n        for ( var w = 0; w < 5; ++w )\n            h[w] = _cvt(h[w]);\n\n        return h;\n    }\n};\n\nvar _h0 = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ];\n\nvar _k1 = [ 0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e ];\nvar _k2 = [ 0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000 ];\nfor ( var i = 4; i >= 0; --i ) {\n    for ( var j = 1; j < 16; ++j ) {\n        _k1.splice(i,0,_k1[i]);\n        _k2.splice(i,0,_k2[i]);\n    }\n}\n\nvar _r1 = [  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,\n             7,  4, 13,  1, 10,  6, 15,  3, 12,  0,  9,  5,  2, 14, 11,  8,\n             3, 10, 14,  4,  9, 15,  8,  1,  2,  7,  0,  6, 13, 11,  5, 12,\n             1,  9, 11, 10,  0,  8, 12,  4, 13,  3,  7, 15, 14,  5,  6,  2,\n             4,  0,  5,  9,  7, 12,  2, 10, 14,  1,  3,  8, 11,  6, 15, 13 ];\nvar _r2 = [  5, 14,  7,  0,  9,  2, 11,  4, 13,  6, 15,  8,  1, 10,  3, 12,\n             6, 11,  3,  7,  0, 13,  5, 10, 14, 15,  8, 12,  4,  9,  1,  2,\n            15,  5,  1,  3,  7, 14,  6,  9, 11,  8, 12,  2, 10,  0,  4, 13,\n             8,  6,  4,  1,  3, 11, 15,  0,  5, 12,  2, 13,  9,  7, 10, 14,\n            12, 15, 10,  4,  1,  5,  8,  7,  6,  2, 13, 14,  0,  3,  9, 11 ];\n\nvar _s1 = [ 11, 14, 15, 12,  5,  8,  7,  9, 11, 13, 14, 15,  6,  7,  9,  8,\n             7,  6,  8, 13, 11,  9,  7, 15,  7, 12, 15,  9, 11,  7, 13, 12,\n            11, 13,  6,  7, 14,  9, 13, 15, 14,  8, 13,  6,  5, 12,  7,  5,\n            11, 12, 14, 15, 14, 15,  9,  8,  9, 14,  5,  6,  8,  6,  5, 12,\n             9, 15,  5, 11,  6,  8, 13, 12,  5, 12, 13, 14, 11,  8,  5,  6 ];\nvar _s2 = [  8,  9,  9, 11, 13, 15, 15,  5,  7,  7,  8, 11, 14, 14, 12,  6,\n             9, 13, 15,  7, 12,  8,  9, 11,  7,  7, 12,  7,  6, 15, 13, 11,\n             9,  7, 15, 11,  8,  6,  6, 14, 12, 13,  5, 14, 13, 13,  7,  5,\n            15,  5,  8, 11, 14, 14,  6, 14,  6,  9, 12,  9, 12,  5, 15,  8,\n             8,  5, 12,  9, 12,  5, 14,  6,  8, 13,  6,  5, 15, 13, 11, 11 ];\n\nfunction _f0(x,y,z) {\n    return x ^ y ^ z;\n};\n\nfunction _f1(x,y,z) {\n    return (x & y) | (~x & z);\n};\n\nfunction _f2(x,y,z) {\n    return (x | ~y) ^ z;\n};\n\nfunction _f3(x,y,z) {\n    return (x & z) | (y & ~z);\n};\n\nfunction _f4(x,y,z) {\n    return x ^ (y | ~z);\n};\n\nfunction _rol(n,l) {\n    return (n << l) | (n >>> (32-l));\n}\n\nfunction _cvt(n) {\n    return ( (n & 0xff <<  0) <<  24 )\n         | ( (n & 0xff <<  8) <<   8 )\n         | ( (n & 0xff << 16) >>>  8 )\n         | ( (n & 0xff << 24) >>> 24 );\n}\n\nfunction _block(X) {\n    var A1 = this._h[0], B1 = this._h[1], C1 = this._h[2], D1 = this._h[3], E1 = this._h[4],\n        A2 = this._h[0], B2 = this._h[1], C2 = this._h[2], D2 = this._h[3], E2 = this._h[4];\n\n    var j = 0, T;\n\n    for ( ; j < 16; ++j ) {\n        T = _rol( A1 + _f0(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1;\n        A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T;\n        T = _rol( A2 + _f4(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2;\n        A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; }\n    for ( ; j < 32; ++j ) {\n        T = _rol( A1 + _f1(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1;\n        A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T;\n        T = _rol( A2 + _f3(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2;\n        A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; }\n    for ( ; j < 48; ++j ) {\n        T = _rol( A1 + _f2(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1;\n        A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T;\n        T = _rol( A2 + _f2(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2;\n        A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; }\n    for ( ; j < 64; ++j ) {\n        T = _rol( A1 + _f3(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1;\n        A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T;\n        T = _rol( A2 + _f1(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2;\n        A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; }\n    for ( ; j < 80; ++j ) {\n        T = _rol( A1 + _f4(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1;\n        A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T;\n        T = _rol( A2 + _f0(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2;\n        A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; }\n\n    T = this._h[1] + C1 + D2;\n    this._h[1] = this._h[2] + D1 + E2;\n    this._h[2] = this._h[3] + E1 + A2;\n    this._h[3] = this._h[4] + A1 + B2;\n    this._h[4] = this._h[0] + B1 + C2;\n    this._h[0] = T;\n}\n\n})();\n\nsjcl.bn.ZERO = new sjcl.bn(0);\n\n/** [ this / that , this % that ] */\nsjcl.bn.prototype.divRem = function (that) {\n  if (typeof(that) !== \"object\") { that = new this._class(that); }\n  var thisa = this.abs(), thata = that.abs(), quot = new this._class(0),\n      ci = 0;\n  if (!thisa.greaterEquals(thata)) {\n    return [new sjcl.bn(0), this.copy()];\n  } else if (thisa.equals(thata)) {\n    return [new sjcl.bn(1), new sjcl.bn(0)];\n  }\n\n  for (; thisa.greaterEquals(thata); ci++) {\n    thata.doubleM();\n  }\n  for (; ci > 0; ci--) {\n    quot.doubleM();\n    thata.halveM();\n    if (thisa.greaterEquals(thata)) {\n      quot.addM(1);\n      thisa.subM(that).normalize();\n    }\n  }\n  return [quot, thisa];\n};\n\n/** this /= that (rounded to nearest int) */\nsjcl.bn.prototype.divRound = function (that) {\n  var dr = this.divRem(that), quot = dr[0], rem = dr[1];\n\n  if (rem.doubleM().greaterEquals(that)) {\n    quot.addM(1);\n  }\n\n  return quot;\n};\n\n/** this /= that (rounded down) */\nsjcl.bn.prototype.div = function (that) {\n  var dr = this.divRem(that);\n  return dr[0];\n};\n\nsjcl.bn.prototype.sign = function () {\n  return this.greaterEquals(sjcl.bn.ZERO) ? 1 : -1;\n};\n\n/** -this */\nsjcl.bn.prototype.neg = function () {\n  return sjcl.bn.ZERO.sub(this);\n};\n\n/** |this| */\nsjcl.bn.prototype.abs = function () {\n  if (this.sign() === -1) {\n    return this.neg();\n  } else return this;\n};\n\n/** this >> that */\nsjcl.bn.prototype.shiftRight = function (that) {\n  if (\"number\" !== typeof that) {\n    throw new Error(\"shiftRight expects a number\");\n  }\n\n  that = +that;\n\n  if (that < 0) {\n    return this.shiftLeft(that);\n  }\n\n  var a = new sjcl.bn(this);\n\n  while (that >= this.radix) {\n    a.limbs.shift();\n    that -= this.radix;\n  }\n\n  while (that--) {\n    a.halveM();\n  }\n\n  return a;\n};\n\n/** this >> that */\nsjcl.bn.prototype.shiftLeft = function (that) {\n  if (\"number\" !== typeof that) {\n    throw new Error(\"shiftLeft expects a number\");\n  }\n\n  that = +that;\n\n  if (that < 0) {\n    return this.shiftRight(that);\n  }\n\n  var a = new sjcl.bn(this);\n\n  while (that >= this.radix) {\n    a.limbs.unshift(0);\n    that -= this.radix;\n  }\n\n  while (that--) {\n    a.doubleM();\n  }\n\n  return a;\n};\n\n/** (int)this */\n// NOTE Truncates to 32-bit integer\nsjcl.bn.prototype.toNumber = function () {\n  return this.limbs[0] | 0;\n};\n\n/** find n-th bit, 0 = LSB */\nsjcl.bn.prototype.testBit = function (bitIndex) {\n  var limbIndex = Math.floor(bitIndex / this.radix);\n  var bitIndexInLimb = bitIndex % this.radix;\n\n  if (limbIndex >= this.limbs.length) return 0;\n\n  return (this.limbs[limbIndex] >>> bitIndexInLimb) & 1;\n};\n\n/** set n-th bit, 0 = LSB */\nsjcl.bn.prototype.setBitM = function (bitIndex) {\n  var limbIndex = Math.floor(bitIndex / this.radix);\n  var bitIndexInLimb = bitIndex % this.radix;\n\n  while (limbIndex >= this.limbs.length) this.limbs.push(0);\n\n  this.limbs[limbIndex] |= 1 << bitIndexInLimb;\n\n  this.cnormalize();\n\n  return this;\n};\n\nsjcl.bn.prototype.modInt = function (n) {\n  return this.toNumber() % n;\n};\n\nsjcl.bn.prototype.invDigit = function ()\n{\n  var radixMod = 1 + this.radixMask;\n\n  if (this.limbs.length < 1) return 0;\n  var x = this.limbs[0];\n  if ((x&1) == 0) return 0;\n  var y = x&3;\t\t// y == 1/x mod 2^2\n  y = (y*(2-(x&0xf)*y))&0xf;\t// y == 1/x mod 2^4\n  y = (y*(2-(x&0xff)*y))&0xff;\t// y == 1/x mod 2^8\n  y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;\t// y == 1/x mod 2^16\n  // last step - calculate inverse mod DV directly;\n  // assumes 16 < radixMod <= 32 and assumes ability to handle 48-bit ints\n  y = (y*(2-x*y%radixMod))%radixMod;\t\t// y == 1/x mod 2^dbits\n  // we really want the negative inverse, and -DV < y < DV\n  return (y>0)?radixMod-y:-y;\n};\n\n// returns bit length of the integer x\nfunction nbits(x) {\n  var r = 1, t;\n  if((t=x>>>16) != 0) { x = t; r += 16; }\n  if((t=x>>8) != 0) { x = t; r += 8; }\n  if((t=x>>4) != 0) { x = t; r += 4; }\n  if((t=x>>2) != 0) { x = t; r += 2; }\n  if((t=x>>1) != 0) { x = t; r += 1; }\n  return r;\n}\n\n// JSBN-style add and multiply for SJCL w/ 24 bit radix\nsjcl.bn.prototype.am = function (i,x,w,j,c,n) {\n  var xl = x&0xfff, xh = x>>12;\n  while (--n >= 0) {\n    var l = this.limbs[i]&0xfff;\n    var h = this.limbs[i++]>>12;\n    var m = xh*l+h*xl;\n    l = xl*l+((m&0xfff)<<12)+w.limbs[j]+c;\n    c = (l>>24)+(m>>12)+xh*h;\n    w.limbs[j++] = l&0xffffff;\n  }\n  return c;\n}\n\nvar Montgomery = function (m)\n{\n  this.m = m;\n  this.mt = m.limbs.length;\n  this.mt2 = this.mt * 2;\n  this.mp = m.invDigit();\n  this.mpl = this.mp&0x7fff;\n  this.mph = this.mp>>15;\n  this.um = (1<<(m.radix-15))-1;\n};\n\nMontgomery.prototype.reduce = function (x)\n{\n  var radixMod = x.radixMask + 1;\n  while (x.limbs.length <= this.mt2)\t// pad x so am has enough room later\n    x.limbs[x.limbs.length] = 0;\n  for (var i = 0; i < this.mt; ++i) {\n    // faster way of calculating u0 = x[i]*mp mod 2^radix\n    var j = x.limbs[i]&0x7fff;\n    var u0 = (j*this.mpl+(((j*this.mph+(x.limbs[i]>>15)*this.mpl)&this.um)<<15))&x.radixMask;\n    // use am to combine the multiply-shift-add into one call\n    j = i+this.mt;\n    x.limbs[j] += this.m.am(0,u0,x,i,0,this.mt);\n    // propagate carry\n    while (x.limbs[j] >= radixMod) { x.limbs[j] -= radixMod; x.limbs[++j]++; }\n  }\n  x.trim();\n  x = x.shiftRight(this.mt * this.m.radix);\n  if (x.greaterEquals(this.m)) x = x.sub(this.m);\n  return x.trim().normalize().reduce();\n};\n\nMontgomery.prototype.square = function (x)\n{\n  return this.reduce(x.square());\n};\n\nMontgomery.prototype.multiply = function (x, y)\n{\n  return this.reduce(x.mul(y));\n};\n\nMontgomery.prototype.convert = function (x)\n{\n  return x.abs().shiftLeft(this.mt * this.m.radix).mod(this.m);\n};\n\nMontgomery.prototype.revert = function (x)\n{\n  return this.reduce(x.copy());\n};\n\nsjcl.bn.prototype.powermodMontgomery = function (e, m)\n{\n  var i = e.bitLength(), k, r = new this._class(1);\n\n  if (i <= 0) return r;\n  else if (i < 18) k = 1;\n  else if (i < 48) k = 3;\n  else if (i < 144) k = 4;\n  else if (i < 768) k = 5;\n  else k = 6;\n\n  if (i < 8 || !m.testBit(0)) {\n    // For small exponents and even moduli, use a simple square-and-multiply\n    // algorithm.\n    return this.powermod(e, m);\n  }\n\n  var z = new Montgomery(m);\n\n  e.trim().normalize();\n\n  // precomputation\n  var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;\n  g[1] = z.convert(this);\n  if (k > 1) {\n    var g2 = z.square(g[1]);\n\n    while (n <= km) {\n      g[n] = z.multiply(g2, g[n-2]);\n      n += 2;\n    }\n  }\n\n  var j = e.limbs.length-1, w, is1 = true, r2 = new this._class(), t;\n  i = nbits(e.limbs[j])-1;\n  while (j >= 0) {\n    if (i >= k1) w = (e.limbs[j]>>(i-k1))&km;\n    else {\n      w = (e.limbs[j]&((1<<(i+1))-1))<<(k1-i);\n      if (j > 0) w |= e.limbs[j-1]>>(this.radix+i-k1);\n    }\n\n    n = k;\n    while ((w&1) == 0) { w >>= 1; --n; }\n    if ((i -= n) < 0) { i += this.radix; --j; }\n    if (is1) {\t// ret == 1, don't bother squaring or multiplying it\n      r = g[w].copy();\n      is1 = false;\n    } else {\n      while (n > 1) { r2 = z.square(r); r = z.square(r2); n -= 2; }\n      if (n > 0) r2 = z.square(r); else { t = r; r = r2; r2 = t; }\n      r = z.multiply(r2,g[w]);\n    }\n\n    while (j >= 0 && (e.limbs[j]&(1<<i)) == 0) {\n      r2 = z.square(r); t = r; r = r2; r2 = t;\n      if (--i < 0) { i = this.radix-1; --j; }\n    }\n  }\n  return z.revert(r);\n}\n\nsjcl.ecc.ecdsa.secretKey.prototype.sign = function(hash, paranoia, k_for_testing) {\n  var R = this._curve.r,\n      l = R.bitLength();\n\n  // k_for_testing should ONLY BE SPECIFIED FOR TESTING\n  // specifying it will make the signature INSECURE\n  var k;\n  if (typeof k_for_testing === 'object' && k_for_testing.length > 0 && typeof k_for_testing[0] === 'number') {\n    k = k_for_testing;\n  } else if (typeof k_for_testing === 'string' && /^[0-9a-fA-F]+$/.test(k_for_testing)) {\n    k = sjcl.bn.fromBits(sjcl.codec.hex.toBits(k_for_testing));        \n  } else {\n    // This is the only option that should be used in production\n    k = sjcl.bn.random(R.sub(1), paranoia).add(1);\n  }\n\n  var r = this._curve.G.mult(k).x.mod(R);\n  var s = sjcl.bn.fromBits(hash).add(r.mul(this._exponent)).mul(k.inverseMod(R)).mod(R);\n\n  return sjcl.bitArray.concat(r.toBits(l), s.toBits(l));\n};\n\nsjcl.ecc.ecdsa.publicKey.prototype.verify = function(hash, rs) {\n  var w = sjcl.bitArray,\n      R = this._curve.r,\n      l = R.bitLength(),\n      r = sjcl.bn.fromBits(w.bitSlice(rs,0,l)),\n      s = sjcl.bn.fromBits(w.bitSlice(rs,l,2*l)),\n      sInv = s.inverseMod(R),\n      hG = sjcl.bn.fromBits(hash).mul(sInv).mod(R),\n      hA = r.mul(sInv).mod(R),\n      r2 = this._curve.G.mult2(hG, hA, this._point).x;\n\n  if (r.equals(0) || s.equals(0) || r.greaterEquals(R) || s.greaterEquals(R) || !r2.equals(r)) {\n    throw (new sjcl.exception.corrupt(\"signature didn't check out\"));\n  }\n  return true;\n};\n\nsjcl.ecc.ecdsa.secretKey.prototype.canonicalizeSignature = function(rs) {\n  var w = sjcl.bitArray,\n      R = this._curve.r,\n      l = R.bitLength();\n\n  var r = sjcl.bn.fromBits(w.bitSlice(rs,0,l)),\n      s = sjcl.bn.fromBits(w.bitSlice(rs,l,2*l));\n\n  // For a canonical signature we want the lower of two possible values for s\n  // 0 < s <= n/2\n  if (!R.copy().halveM().greaterEquals(s)) {\n    s = R.sub(s);\n  }\n\n  return w.concat(r.toBits(l), s.toBits(l));\n};\n\n\nsjcl.ecc.ecdsa.secretKey.prototype.signDER = function(hash, paranoia) {\n  return this.encodeDER(this.sign(hash, paranoia));\n};\n\nsjcl.ecc.ecdsa.secretKey.prototype.encodeDER = function(rs) {\n  var w = sjcl.bitArray,\n      R = this._curve.r,\n      l = R.bitLength();\n\n  var rb = sjcl.codec.bytes.fromBits(w.bitSlice(rs,0,l)),\n      sb = sjcl.codec.bytes.fromBits(w.bitSlice(rs,l,2*l));\n\n  // Drop empty leading bytes\n  while (!rb[0] && rb.length) rb.shift();\n  while (!sb[0] && sb.length) sb.shift();\n\n  // If high bit is set, prepend an extra zero byte (DER signed integer)\n  if (rb[0] & 0x80) rb.unshift(0);\n  if (sb[0] & 0x80) sb.unshift(0);\n\n  var buffer = [].concat(\n    0x30,\n    4 + rb.length + sb.length,\n    0x02,\n    rb.length,\n    rb,\n    0x02,\n    sb.length,\n    sb\n  );\n\n  return sjcl.codec.bytes.toBits(buffer);\n};\n\n\n/**\n *  This module uses the public key recovery method\n *  described in SEC 1: Elliptic Curve Cryptography,\n *  section 4.1.6, \"Public Key Recovery Operation\".\n *  http://www.secg.org/download/aid-780/sec1-v2.pdf\n *\n *  Implementation based on:\n *  https://github.com/bitcoinjs/bitcoinjs-lib/blob/89cf731ac7309b4f98994e3b4b67b7226020181f/src/ecdsa.js\n */\n\n// Defined here so that this value only needs to be calculated once\nvar FIELD_MODULUS_PLUS_ONE_DIVIDED_BY_FOUR;\n\n/**\n *  Sign the given hash such that the public key, prepending an extra byte \n *  so that the public key will be recoverable from the signature\n *\n *  @param {bitArray} hash\n *  @param {Number} paranoia\n *  @returns {bitArray} Signature formatted as bitArray\n */\nsjcl.ecc.ecdsa.secretKey.prototype.signWithRecoverablePublicKey = function(hash, paranoia, k_for_testing) {\n\n  var self = this;\n\n  // Convert hash to bits and determine encoding for output\n  var hash_bits;\n  if (typeof hash === 'object' && hash.length > 0 && typeof hash[0] === 'number') {\n    hash_bits = hash;\n  } else {\n    throw new sjcl.exception.invalid('hash. Must be a bitArray');\n  }\n\n  // Sign hash with standard, canonicalized method\n  var standard_signature = self.sign(hash_bits, paranoia, k_for_testing);\n  var canonical_signature = self.canonicalizeSignature(standard_signature);\n\n  // Extract r and s signature components from canonical signature\n  var r_and_s = getRandSFromSignature(self._curve, canonical_signature);\n\n  // Rederive public key\n  var public_key = self._curve.G.mult(sjcl.bn.fromBits(self.get()));\n\n  // Determine recovery factor based on which possible value\n  // returns the correct public key\n  var recovery_factor = calculateRecoveryFactor(self._curve, r_and_s.r, r_and_s.s, hash_bits, public_key);\n\n  // Prepend recovery_factor to signature and encode in DER\n  // The value_to_prepend should be 4 bytes total\n  var value_to_prepend = recovery_factor + 27;\n\n  var final_signature_bits = sjcl.bitArray.concat([value_to_prepend], canonical_signature);\n\n  // Return value in bits\n  return final_signature_bits;\n\n};\n\n\n/**\n *  Recover the public key from a signature created with the\n *  signWithRecoverablePublicKey method in this module\n *\n *  @static\n *\n *  @param {bitArray} hash\n *  @param {bitArray} signature\n *  @param {sjcl.ecc.curve} [sjcl.ecc.curves['c256']] curve\n *  @returns {sjcl.ecc.ecdsa.publicKey} Public key\n */\nsjcl.ecc.ecdsa.publicKey.recoverFromSignature = function(hash, signature, curve) {\n\n  if (!signature || signature instanceof sjcl.ecc.curve) {\n    throw new sjcl.exception.invalid('must supply hash and signature to recover public key');\n  }\n\n  if (!curve) {\n    curve = sjcl.ecc.curves['c256'];\n  }\n\n  // Convert hash to bits and determine encoding for output\n  var hash_bits;\n  if (typeof hash === 'object' && hash.length > 0 && typeof hash[0] === 'number') {\n    hash_bits = hash;\n  } else {\n    throw new sjcl.exception.invalid('hash. Must be a bitArray');\n  }\n\n  var signature_bits;\n  if (typeof signature === 'object' && signature.length > 0 && typeof signature[0] === 'number') {\n    signature_bits = signature;\n  } else {\n    throw new sjcl.exception.invalid('signature. Must be a bitArray');\n  }\n\n  // Extract recovery_factor from first 4 bytes\n  var recovery_factor = signature_bits[0] - 27;\n\n  if (recovery_factor < 0 || recovery_factor > 3) {\n    throw new sjcl.exception.invalid('signature. Signature must be generated with algorithm ' +\n      'that prepends the recovery factor in order to recover the public key');\n  }\n\n  // Separate r and s values\n  var r_and_s = getRandSFromSignature(curve, signature_bits.slice(1));\n  var signature_r = r_and_s.r;\n  var signature_s = r_and_s.s;\n\n  // Recover public key using recovery_factor\n  var recovered_public_key_point = recoverPublicKeyPointFromSignature(curve, signature_r, signature_s, hash_bits, recovery_factor);\n  var recovered_public_key = new sjcl.ecc.ecdsa.publicKey(curve, recovered_public_key_point);\n\n  return recovered_public_key;\n\n};\n\n\n/**\n *  Retrieve the r and s components of a signature  \n *\n *  @param {sjcl.ecc.curve} curve\n *  @param {bitArray} signature\n *  @returns {Object} Object with 'r' and 's' fields each as an sjcl.bn\n */\nfunction getRandSFromSignature(curve, signature) {\n\n  var r_length = curve.r.bitLength();\n\n  return {\n    r: sjcl.bn.fromBits(sjcl.bitArray.bitSlice(signature, 0, r_length)),\n    s: sjcl.bn.fromBits(sjcl.bitArray.bitSlice(signature, r_length, sjcl.bitArray.bitLength(signature)))\n  };\n};\n\n\n/**\n *  Determine the recovery factor by trying all four\n *  possibilities and figuring out which results in the\n *  correct public key\n *\n *  @param {sjcl.ecc.curve} curve\n *  @param {sjcl.bn} r\n *  @param {sjcl.bn} s\n *  @param {bitArray} hash_bits\n *  @param {sjcl.ecc.point} original_public_key_point\n *  @returns {Number, 0-3} Recovery factor\n */\nfunction calculateRecoveryFactor(curve, r, s, hash_bits, original_public_key_point) {\n\n  var original_public_key_point_bits = original_public_key_point.toBits();\n\n  // TODO: verify that it is possible for the recovery_factor to be 2 or 3,\n  // we may only need 1 bit because the canonical signature might remove the\n  // possibility of us needing to \"use the second candidate key\"\n  for (var possible_factor = 0; possible_factor < 4; possible_factor++) {\n\n    var resulting_public_key_point;\n    try {\n      resulting_public_key_point = recoverPublicKeyPointFromSignature(curve, r, s, hash_bits, possible_factor);\n    } catch (err) {\n      // console.log(err, err.stack);\n      continue;\n    }\n\n    if (sjcl.bitArray.equal(resulting_public_key_point.toBits(), original_public_key_point_bits)) {\n      return possible_factor;\n    }\n\n  }\n\n  throw new sjcl.exception.bug('unable to calculate recovery factor from signature');\n\n};\n\n\n/**\n *  Recover the public key from the signature.\n *\n *  @param {sjcl.ecc.curve} curve\n *  @param {sjcl.bn} r\n *  @param {sjcl.bn} s\n *  @param {bitArray} hash_bits\n *  @param {Number, 0-3} recovery_factor\n *  @returns {sjcl.point} Public key corresponding to signature\n */\nfunction recoverPublicKeyPointFromSignature(curve, signature_r, signature_s, hash_bits, recovery_factor) {\n\n  var field_order = curve.r;\n  var field_modulus = curve.field.modulus;\n\n  // Reduce the recovery_factor to the two bits used\n  recovery_factor = recovery_factor & 3;\n\n  // The less significant bit specifies whether the y coordinate\n  // of the compressed point is even or not.\n  var compressed_point_y_coord_is_even = recovery_factor & 1;\n\n  // The more significant bit specifies whether we should use the\n  // first or second candidate key.\n  var use_second_candidate_key = recovery_factor >> 1;\n\n  // Calculate (field_order + 1) / 4\n  if (!FIELD_MODULUS_PLUS_ONE_DIVIDED_BY_FOUR) {\n    FIELD_MODULUS_PLUS_ONE_DIVIDED_BY_FOUR = field_modulus.add(1).div(4);\n  }\n\n  // In the paper they write \"1. For j from 0 to h do the following...\"\n  // That is not necessary here because we are given the recovery_factor\n  // step 1.1 Let x = r + jn\n  // Here \"j\" is either 0 or 1\n  var x;\n  if (use_second_candidate_key) {\n    x = signature_r.add(field_order);\n  } else {\n    x = signature_r;\n  }\n\n  // step 1.2 and 1.3  convert x to an elliptic curve point\n  // Following formula in section 2.3.4 Octet-String-to-Elliptic-Curve-Point Conversion\n  var alpha = x.mul(x).mul(x).add(curve.a.mul(x)).add(curve.b).mod(field_modulus);\n  var beta = alpha.powermodMontgomery(FIELD_MODULUS_PLUS_ONE_DIVIDED_BY_FOUR, field_modulus);\n\n  // If beta is even but y isn't or\n  // if beta is odd and y is even\n  // then subtract beta from the field_modulus\n  var y;\n  var beta_is_even = beta.mod(2).equals(0);\n  if (beta_is_even && !compressed_point_y_coord_is_even ||\n    !beta_is_even && compressed_point_y_coord_is_even) {\n    y = beta;\n  } else {\n    y = field_modulus.sub(beta);\n  }\n\n  // generated_point_R is the point generated from x and y\n  var generated_point_R = new sjcl.ecc.point(curve, x, y);\n\n  // step 1.4  check that R is valid and R x field_order !== infinity\n  // TODO: add check for R x field_order === infinity\n  if (!generated_point_R.isValidPoint()) {\n    throw new sjcl.exception.corrupt('point R. Not a valid point on the curve. Cannot recover public key');\n  }\n\n  // step 1.5  Compute e from M\n  var message_e = sjcl.bn.fromBits(hash_bits);\n  var message_e_neg = new sjcl.bn(0).sub(message_e).mod(field_order);\n\n  // step 1.6  Compute Q = r^-1 (sR - eG)\n  // console.log('r: ', signature_r);\n  var signature_r_inv = signature_r.inverseMod(field_order);\n  var public_key_point = generated_point_R.mult2(signature_s, message_e_neg, curve.G).mult(signature_r_inv);\n\n  // Validate public key point\n  if (!public_key_point.isValidPoint()) {\n    throw new sjcl.exception.corrupt('public_key_point. Not a valid point on the curve. Cannot recover public key');\n  }\n\n  // Verify that this public key matches the signature\n  if (!verify_raw(curve, message_e, signature_r, signature_s, public_key_point)) {\n    throw new sjcl.exception.corrupt('cannot recover public key');\n  }\n\n  return public_key_point;\n\n};\n\n\n/**\n *  Verify a signature given the raw components\n *  using method defined in section 4.1.5:\n *  \"Alternative Verifying Operation\"\n *\n *  @param {sjcl.ecc.curve} curve\n *  @param {sjcl.bn} e\n *  @param {sjcl.bn} r\n *  @param {sjcl.bn} s\n *  @param {sjcl.ecc.point} public_key_point\n *  @returns {Boolean} \n */\nfunction verify_raw(curve, e, r, s, public_key_point) {\n\n  var field_order = curve.r;\n\n  // Return false if r is out of bounds\n  if ((new sjcl.bn(1)).greaterEquals(r) || r.greaterEquals(new sjcl.bn(field_order))) {\n    return false;\n  }\n\n  // Return false if s is out of bounds\n  if ((new sjcl.bn(1)).greaterEquals(s) || s.greaterEquals(new sjcl.bn(field_order))) {\n    return false;\n  }\n\n  // Check that r = (u1 + u2)G\n  // u1 = e x s^-1 (mod field_order)\n  // u2 = r x s^-1 (mod field_order)\n  var s_mod_inverse_field_order = s.inverseMod(field_order);\n  var u1 = e.mul(s_mod_inverse_field_order).mod(field_order);\n  var u2 = r.mul(s_mod_inverse_field_order).mod(field_order);\n\n  var point_computed = curve.G.mult2(u1, u2, public_key_point);\n\n  return r.equals(point_computed.x.mod(field_order));\n\n};\n\n\nsjcl.bn.prototype.jacobi = function (that) {\n  var a = this;\n  that = new sjcl.bn(that);\n\n  if (that.sign() === -1) return;\n\n  // 1. If a = 0 then return(0).\n  if (a.equals(0)) { return 0; }\n\n  // 2. If a = 1 then return(1).\n  if (a.equals(1)) { return 1; }\n\n  var s = 0;\n\n  // 3. Write a = 2^e * a1, where a1 is odd.\n  var e = 0;\n  while (!a.testBit(e)) e++;\n  var a1 = a.shiftRight(e);\n\n  // 4. If e is even then set s ← 1.\n  if ((e & 1) === 0) {\n    s = 1;\n  } else {\n    var residue = that.modInt(8);\n\n    if (residue === 1 || residue === 7) {\n      // Otherwise set s ← 1 if n ≡ 1 or 7 (mod 8)\n      s = 1;\n    } else if (residue === 3 || residue === 5) {\n      // Or set s ← −1 if n ≡ 3 or 5 (mod 8).\n      s = -1;\n    }\n  }\n\n  // 5. If n ≡ 3 (mod 4) and a1 ≡ 3 (mod 4) then set s ← −s.\n  if (that.modInt(4) === 3 && a1.modInt(4) === 3) {\n    s = -s;\n  }\n\n  if (a1.equals(1)) {\n    return s;\n  } else {\n    return s * that.mod(a1).jacobi(a1);\n  }\n};\n\n\n// WEBPACK FOOTER\n// module.id = 34\n// module.readableIdentifier = ./build/sjcl.js\n//@ sourceURL=webpack-module:///./build/sjcl.js");

/***/ },
/* 35 */
/***/ function(module, exports, __webpack_require__) {

	eval("// Copyright (c) 2005  Tom Wu\n// All Rights Reserved.\n// See \"LICENSE\" for details.\n\n// Basic JavaScript BN library - subset useful for RSA encryption.\n\n// Bits per digit\nvar dbits;\n\n// JavaScript engine analysis\nvar canary = 0xdeadbeefcafe;\nvar j_lm = ((canary&0xffffff)==0xefcafe);\n\n// (public) Constructor\nfunction BigInteger(a,b,c) {\n  if(a != null)\n    if(\"number\" == typeof a) this.fromNumber(a,b,c);\n    else if(b == null && \"string\" != typeof a) this.fromString(a,256);\n    else this.fromString(a,b);\n}\n\n// return new, unset BigInteger\nfunction nbi() { return new BigInteger(null); }\n\n// am: Compute w_j += (x*this_i), propagate carries,\n// c is initial carry, returns final carry.\n// c < 3*dvalue, x < 2*dvalue, this_i < dvalue\n// We need to select the fastest one that works in this environment.\n\n// am1: use a single mult and divide to get the high bits,\n// max digit bits should be 26 because\n// max internal value = 2*dvalue^2-2*dvalue (< 2^53)\nfunction am1(i,x,w,j,c,n) {\n  while(--n >= 0) {\n    var v = x*this[i++]+w[j]+c;\n    c = Math.floor(v/0x4000000);\n    w[j++] = v&0x3ffffff;\n  }\n  return c;\n}\n// am2 avoids a big mult-and-extract completely.\n// Max digit bits should be <= 30 because we do bitwise ops\n// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)\nfunction am2(i,x,w,j,c,n) {\n  var xl = x&0x7fff, xh = x>>15;\n  while(--n >= 0) {\n    var l = this[i]&0x7fff;\n    var h = this[i++]>>15;\n    var m = xh*l+h*xl;\n    l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);\n    c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);\n    w[j++] = l&0x3fffffff;\n  }\n  return c;\n}\n// Alternately, set max digit bits to 28 since some\n// browsers slow down when dealing with 32-bit numbers.\nfunction am3(i,x,w,j,c,n) {\n  var xl = x&0x3fff, xh = x>>14;\n  while(--n >= 0) {\n    var l = this[i]&0x3fff;\n    var h = this[i++]>>14;\n    var m = xh*l+h*xl;\n    l = xl*l+((m&0x3fff)<<14)+w[j]+c;\n    c = (l>>28)+(m>>14)+xh*h;\n    w[j++] = l&0xfffffff;\n  }\n  return c;\n}\nif(j_lm && 'undefined' !== typeof navigator && (navigator.appName == \"Microsoft Internet Explorer\")) {\n  BigInteger.prototype.am = am2;\n  dbits = 30;\n}\nelse if(j_lm && 'undefined' !== typeof navigator && (navigator.appName != \"Netscape\")) {\n  BigInteger.prototype.am = am1;\n  dbits = 26;\n}\nelse { // Mozilla/Netscape seems to prefer am3\n  BigInteger.prototype.am = am3;\n  dbits = 28;\n}\n\nBigInteger.prototype.DB = dbits;\nBigInteger.prototype.DM = ((1<<dbits)-1);\nBigInteger.prototype.DV = (1<<dbits);\n\nvar BI_FP = 52;\nBigInteger.prototype.FV = Math.pow(2,BI_FP);\nBigInteger.prototype.F1 = BI_FP-dbits;\nBigInteger.prototype.F2 = 2*dbits-BI_FP;\n\n// Digit conversions\nvar BI_RM = \"0123456789abcdefghijklmnopqrstuvwxyz\";\nvar BI_RC = new Array();\nvar rr,vv;\nrr = \"0\".charCodeAt(0);\nfor(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;\nrr = \"a\".charCodeAt(0);\nfor(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;\nrr = \"A\".charCodeAt(0);\nfor(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;\n\nfunction int2char(n) { return BI_RM.charAt(n); }\nfunction intAt(s,i) {\n  var c = BI_RC[s.charCodeAt(i)];\n  return (c==null)?-1:c;\n}\n\n// (protected) copy this to r\nfunction bnpCopyTo(r) {\n  for(var i = this.t-1; i >= 0; --i) r[i] = this[i];\n  r.t = this.t;\n  r.s = this.s;\n}\n\n// (protected) set from integer value x, -DV <= x < DV\nfunction bnpFromInt(x) {\n  this.t = 1;\n  this.s = (x<0)?-1:0;\n  if(x > 0) this[0] = x;\n  else if(x < -1) this[0] = x+this.DV;\n  else this.t = 0;\n}\n\n// return bigint initialized to value\nfunction nbv(i) { var r = nbi(); r.fromInt(i); return r; }\n\n// (protected) set from string and radix\nfunction bnpFromString(s,b) {\n  var k;\n  if(b == 16) k = 4;\n  else if(b == 8) k = 3;\n  else if(b == 256) k = 8; // byte array\n  else if(b == 2) k = 1;\n  else if(b == 32) k = 5;\n  else if(b == 4) k = 2;\n  else { this.fromRadix(s,b); return; }\n  this.t = 0;\n  this.s = 0;\n  var i = s.length, mi = false, sh = 0;\n  while(--i >= 0) {\n    var x = (k==8)?s[i]&0xff:intAt(s,i);\n    if(x < 0) {\n      if(s.charAt(i) == \"-\") mi = true;\n      continue;\n    }\n    mi = false;\n    if(sh == 0)\n      this[this.t++] = x;\n    else if(sh+k > this.DB) {\n      this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;\n      this[this.t++] = (x>>(this.DB-sh));\n    }\n    else\n      this[this.t-1] |= x<<sh;\n    sh += k;\n    if(sh >= this.DB) sh -= this.DB;\n  }\n  if(k == 8 && (s[0]&0x80) != 0) {\n    this.s = -1;\n    if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;\n  }\n  this.clamp();\n  if(mi) BigInteger.ZERO.subTo(this,this);\n}\n\n// (protected) clamp off excess high words\nfunction bnpClamp() {\n  var c = this.s&this.DM;\n  while(this.t > 0 && this[this.t-1] == c) --this.t;\n}\n\n// (public) return string representation in given radix\nfunction bnToString(b) {\n  if(this.s < 0) return \"-\"+this.negate().toString(b);\n  var k;\n  if(b == 16) k = 4;\n  else if(b == 8) k = 3;\n  else if(b == 2) k = 1;\n  else if(b == 32) k = 5;\n  else if(b == 4) k = 2;\n  else return this.toRadix(b);\n  var km = (1<<k)-1, d, m = false, r = \"\", i = this.t;\n  var p = this.DB-(i*this.DB)%k;\n  if(i-- > 0) {\n    if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }\n    while(i >= 0) {\n      if(p < k) {\n        d = (this[i]&((1<<p)-1))<<(k-p);\n        d |= this[--i]>>(p+=this.DB-k);\n      }\n      else {\n        d = (this[i]>>(p-=k))&km;\n        if(p <= 0) { p += this.DB; --i; }\n      }\n      if(d > 0) m = true;\n      if(m) r += int2char(d);\n    }\n  }\n  return m?r:\"0\";\n}\n\n// (public) -this\nfunction bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }\n\n// (public) |this|\nfunction bnAbs() { return (this.s<0)?this.negate():this; }\n\n// (public) return + if this > a, - if this < a, 0 if equal\nfunction bnCompareTo(a) {\n  var r = this.s-a.s;\n  if(r != 0) return r;\n  var i = this.t;\n  r = i-a.t;\n  if(r != 0) return (this.s<0)?-r:r;\n  while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;\n  return 0;\n}\n\n// returns bit length of the integer x\nfunction nbits(x) {\n  var r = 1, t;\n  if((t=x>>>16) != 0) { x = t; r += 16; }\n  if((t=x>>8) != 0) { x = t; r += 8; }\n  if((t=x>>4) != 0) { x = t; r += 4; }\n  if((t=x>>2) != 0) { x = t; r += 2; }\n  if((t=x>>1) != 0) { x = t; r += 1; }\n  return r;\n}\n\n// (public) return the number of bits in \"this\"\nfunction bnBitLength() {\n  if(this.t <= 0) return 0;\n  return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));\n}\n\n// (protected) r = this << n*DB\nfunction bnpDLShiftTo(n,r) {\n  var i;\n  for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];\n  for(i = n-1; i >= 0; --i) r[i] = 0;\n  r.t = this.t+n;\n  r.s = this.s;\n}\n\n// (protected) r = this >> n*DB\nfunction bnpDRShiftTo(n,r) {\n  for(var i = n; i < this.t; ++i) r[i-n] = this[i];\n  r.t = Math.max(this.t-n,0);\n  r.s = this.s;\n}\n\n// (protected) r = this << n\nfunction bnpLShiftTo(n,r) {\n  var bs = n%this.DB;\n  var cbs = this.DB-bs;\n  var bm = (1<<cbs)-1;\n  var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;\n  for(i = this.t-1; i >= 0; --i) {\n    r[i+ds+1] = (this[i]>>cbs)|c;\n    c = (this[i]&bm)<<bs;\n  }\n  for(i = ds-1; i >= 0; --i) r[i] = 0;\n  r[ds] = c;\n  r.t = this.t+ds+1;\n  r.s = this.s;\n  r.clamp();\n}\n\n// (protected) r = this >> n\nfunction bnpRShiftTo(n,r) {\n  r.s = this.s;\n  var ds = Math.floor(n/this.DB);\n  if(ds >= this.t) { r.t = 0; return; }\n  var bs = n%this.DB;\n  var cbs = this.DB-bs;\n  var bm = (1<<bs)-1;\n  r[0] = this[ds]>>bs;\n  for(var i = ds+1; i < this.t; ++i) {\n    r[i-ds-1] |= (this[i]&bm)<<cbs;\n    r[i-ds] = this[i]>>bs;\n  }\n  if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;\n  r.t = this.t-ds;\n  r.clamp();\n}\n\n// (protected) r = this - a\nfunction bnpSubTo(a,r) {\n  var i = 0, c = 0, m = Math.min(a.t,this.t);\n  while(i < m) {\n    c += this[i]-a[i];\n    r[i++] = c&this.DM;\n    c >>= this.DB;\n  }\n  if(a.t < this.t) {\n    c -= a.s;\n    while(i < this.t) {\n      c += this[i];\n      r[i++] = c&this.DM;\n      c >>= this.DB;\n    }\n    c += this.s;\n  }\n  else {\n    c += this.s;\n    while(i < a.t) {\n      c -= a[i];\n      r[i++] = c&this.DM;\n      c >>= this.DB;\n    }\n    c -= a.s;\n  }\n  r.s = (c<0)?-1:0;\n  if(c < -1) r[i++] = this.DV+c;\n  else if(c > 0) r[i++] = c;\n  r.t = i;\n  r.clamp();\n}\n\n// (protected) r = this * a, r != this,a (HAC 14.12)\n// \"this\" should be the larger one if appropriate.\nfunction bnpMultiplyTo(a,r) {\n  var x = this.abs(), y = a.abs();\n  var i = x.t;\n  r.t = i+y.t;\n  while(--i >= 0) r[i] = 0;\n  for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);\n  r.s = 0;\n  r.clamp();\n  if(this.s != a.s) BigInteger.ZERO.subTo(r,r);\n}\n\n// (protected) r = this^2, r != this (HAC 14.16)\nfunction bnpSquareTo(r) {\n  var x = this.abs();\n  var i = r.t = 2*x.t;\n  while(--i >= 0) r[i] = 0;\n  for(i = 0; i < x.t-1; ++i) {\n    var c = x.am(i,x[i],r,2*i,0,1);\n    if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {\n      r[i+x.t] -= x.DV;\n      r[i+x.t+1] = 1;\n    }\n  }\n  if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);\n  r.s = 0;\n  r.clamp();\n}\n\n// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)\n// r != q, this != m.  q or r may be null.\nfunction bnpDivRemTo(m,q,r) {\n  var pm = m.abs();\n  if(pm.t <= 0) return;\n  var pt = this.abs();\n  if(pt.t < pm.t) {\n    if(q != null) q.fromInt(0);\n    if(r != null) this.copyTo(r);\n    return;\n  }\n  if(r == null) r = nbi();\n  var y = nbi(), ts = this.s, ms = m.s;\n  var nsh = this.DB-nbits(pm[pm.t-1]);\t// normalize modulus\n  if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }\n  else { pm.copyTo(y); pt.copyTo(r); }\n  var ys = y.t;\n  var y0 = y[ys-1];\n  if(y0 == 0) return;\n  var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);\n  var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;\n  var i = r.t, j = i-ys, t = (q==null)?nbi():q;\n  y.dlShiftTo(j,t);\n  if(r.compareTo(t) >= 0) {\n    r[r.t++] = 1;\n    r.subTo(t,r);\n  }\n  BigInteger.ONE.dlShiftTo(ys,t);\n  t.subTo(y,y);\t// \"negative\" y so we can replace sub with am later\n  while(y.t < ys) y[y.t++] = 0;\n  while(--j >= 0) {\n    // Estimate quotient digit\n    var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);\n    if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) {\t// Try it out\n      y.dlShiftTo(j,t);\n      r.subTo(t,r);\n      while(r[i] < --qd) r.subTo(t,r);\n    }\n  }\n  if(q != null) {\n    r.drShiftTo(ys,q);\n    if(ts != ms) BigInteger.ZERO.subTo(q,q);\n  }\n  r.t = ys;\n  r.clamp();\n  if(nsh > 0) r.rShiftTo(nsh,r);\t// Denormalize remainder\n  if(ts < 0) BigInteger.ZERO.subTo(r,r);\n}\n\n// (public) this mod a\nfunction bnMod(a) {\n  var r = nbi();\n  this.abs().divRemTo(a,null,r);\n  if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);\n  return r;\n}\n\n// Modular reduction using \"classic\" algorithm\nfunction Classic(m) { this.m = m; }\nfunction cConvert(x) {\n  if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);\n  else return x;\n}\nfunction cRevert(x) { return x; }\nfunction cReduce(x) { x.divRemTo(this.m,null,x); }\nfunction cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }\nfunction cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }\n\nClassic.prototype.convert = cConvert;\nClassic.prototype.revert = cRevert;\nClassic.prototype.reduce = cReduce;\nClassic.prototype.mulTo = cMulTo;\nClassic.prototype.sqrTo = cSqrTo;\n\n// (protected) return \"-1/this % 2^DB\"; useful for Mont. reduction\n// justification:\n//         xy == 1 (mod m)\n//         xy =  1+km\n//   xy(2-xy) = (1+km)(1-km)\n// x[y(2-xy)] = 1-k^2m^2\n// x[y(2-xy)] == 1 (mod m^2)\n// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2\n// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.\n// JS multiply \"overflows\" differently from C/C++, so care is needed here.\nfunction bnpInvDigit() {\n  if(this.t < 1) return 0;\n  var x = this[0];\n  if((x&1) == 0) return 0;\n  var y = x&3;\t\t// y == 1/x mod 2^2\n  y = (y*(2-(x&0xf)*y))&0xf;\t// y == 1/x mod 2^4\n  y = (y*(2-(x&0xff)*y))&0xff;\t// y == 1/x mod 2^8\n  y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;\t// y == 1/x mod 2^16\n  // last step - calculate inverse mod DV directly;\n  // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints\n  y = (y*(2-x*y%this.DV))%this.DV;\t\t// y == 1/x mod 2^dbits\n  // we really want the negative inverse, and -DV < y < DV\n  return (y>0)?this.DV-y:-y;\n}\n\n// Montgomery reduction\nfunction Montgomery(m) {\n  this.m = m;\n  this.mp = m.invDigit();\n  this.mpl = this.mp&0x7fff;\n  this.mph = this.mp>>15;\n  this.um = (1<<(m.DB-15))-1;\n  this.mt2 = 2*m.t;\n}\n\n// xR mod m\nfunction montConvert(x) {\n  var r = nbi();\n  x.abs().dlShiftTo(this.m.t,r);\n  r.divRemTo(this.m,null,r);\n  if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);\n  return r;\n}\n\n// x/R mod m\nfunction montRevert(x) {\n  var r = nbi();\n  x.copyTo(r);\n  this.reduce(r);\n  return r;\n}\n\n// x = x/R mod m (HAC 14.32)\nfunction montReduce(x) {\n  while(x.t <= this.mt2)\t// pad x so am has enough room later\n    x[x.t++] = 0;\n  for(var i = 0; i < this.m.t; ++i) {\n    // faster way of calculating u0 = x[i]*mp mod DV\n    var j = x[i]&0x7fff;\n    var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;\n    // use am to combine the multiply-shift-add into one call\n    j = i+this.m.t;\n    x[j] += this.m.am(0,u0,x,i,0,this.m.t);\n    // propagate carry\n    while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }\n  }\n  x.clamp();\n  x.drShiftTo(this.m.t,x);\n  if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);\n}\n\n// r = \"x^2/R mod m\"; x != r\nfunction montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }\n\n// r = \"xy/R mod m\"; x,y != r\nfunction montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }\n\nMontgomery.prototype.convert = montConvert;\nMontgomery.prototype.revert = montRevert;\nMontgomery.prototype.reduce = montReduce;\nMontgomery.prototype.mulTo = montMulTo;\nMontgomery.prototype.sqrTo = montSqrTo;\n\n// (protected) true iff this is even\nfunction bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }\n\n// (protected) this^e, e < 2^32, doing sqr and mul with \"r\" (HAC 14.79)\nfunction bnpExp(e,z) {\n  if(e > 0xffffffff || e < 1) return BigInteger.ONE;\n  var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;\n  g.copyTo(r);\n  while(--i >= 0) {\n    z.sqrTo(r,r2);\n    if((e&(1<<i)) > 0) z.mulTo(r2,g,r);\n    else { var t = r; r = r2; r2 = t; }\n  }\n  return z.revert(r);\n}\n\n// (public) this^e % m, 0 <= e < 2^32\nfunction bnModPowInt(e,m) {\n  var z;\n  if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);\n  return this.exp(e,z);\n}\n\n// (public)\nfunction bnClone() { var r = nbi(); this.copyTo(r); return r; }\n\n// (public) return value as integer\nfunction bnIntValue() {\n  if(this.s < 0) {\n    if(this.t == 1) return this[0]-this.DV;\n    else if(this.t == 0) return -1;\n  }\n  else if(this.t == 1) return this[0];\n  else if(this.t == 0) return 0;\n  // assumes 16 < DB < 32\n  return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];\n}\n\n// (public) return value as byte\nfunction bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }\n\n// (public) return value as short (assumes DB>=16)\nfunction bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }\n\n// (protected) return x s.t. r^x < DV\nfunction bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }\n\n// (public) 0 if this == 0, 1 if this > 0\nfunction bnSigNum() {\n  if(this.s < 0) return -1;\n  else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;\n  else return 1;\n}\n\n// (protected) convert to radix string\nfunction bnpToRadix(b) {\n  if(b == null) b = 10;\n  if(this.signum() == 0 || b < 2 || b > 36) return \"0\";\n  var cs = this.chunkSize(b);\n  var a = Math.pow(b,cs);\n  var d = nbv(a), y = nbi(), z = nbi(), r = \"\";\n  this.divRemTo(d,y,z);\n  while(y.signum() > 0) {\n    r = (a+z.intValue()).toString(b).substr(1) + r;\n    y.divRemTo(d,y,z);\n  }\n  return z.intValue().toString(b) + r;\n}\n\n// (protected) convert from radix string\nfunction bnpFromRadix(s,b) {\n  this.fromInt(0);\n  if(b == null) b = 10;\n  var cs = this.chunkSize(b);\n  var d = Math.pow(b,cs), mi = false, j = 0, w = 0;\n  for(var i = 0; i < s.length; ++i) {\n    var x = intAt(s,i);\n    if(x < 0) {\n      if(s.charAt(i) == \"-\" && this.signum() == 0) mi = true;\n      continue;\n    }\n    w = b*w+x;\n    if(++j >= cs) {\n      this.dMultiply(d);\n      this.dAddOffset(w,0);\n      j = 0;\n      w = 0;\n    }\n  }\n  if(j > 0) {\n    this.dMultiply(Math.pow(b,j));\n    this.dAddOffset(w,0);\n  }\n  if(mi) BigInteger.ZERO.subTo(this,this);\n}\n\n// (protected) alternate constructor\nfunction bnpFromNumber(a,b,c) {\n  if(\"number\" == typeof b) {\n    // new BigInteger(int,int,RNG)\n    if(a < 2) this.fromInt(1);\n    else {\n      this.fromNumber(a,c);\n      if(!this.testBit(a-1))\t// force MSB set\n        this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);\n      if(this.isEven()) this.dAddOffset(1,0); // force odd\n      while(!this.isProbablePrime(b)) {\n        this.dAddOffset(2,0);\n        if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);\n      }\n    }\n  }\n  else {\n    // new BigInteger(int,RNG)\n    var x = new Array(), t = a&7;\n    x.length = (a>>3)+1;\n    b.nextBytes(x);\n    if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;\n    this.fromString(x,256);\n  }\n}\n\n// (public) convert to bigendian byte array\nfunction bnToByteArray() {\n  var i = this.t, r = new Array();\n  r[0] = this.s;\n  var p = this.DB-(i*this.DB)%8, d, k = 0;\n  if(i-- > 0) {\n    if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)\n      r[k++] = d|(this.s<<(this.DB-p));\n    while(i >= 0) {\n      if(p < 8) {\n        d = (this[i]&((1<<p)-1))<<(8-p);\n        d |= this[--i]>>(p+=this.DB-8);\n      }\n      else {\n        d = (this[i]>>(p-=8))&0xff;\n        if(p <= 0) { p += this.DB; --i; }\n      }\n      if((d&0x80) != 0) d |= -256;\n      if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;\n      if(k > 0 || d != this.s) r[k++] = d;\n    }\n  }\n  return r;\n}\n\nfunction bnEquals(a) { return(this.compareTo(a)==0); }\nfunction bnMin(a) { return(this.compareTo(a)<0)?this:a; }\nfunction bnMax(a) { return(this.compareTo(a)>0)?this:a; }\n\n// (protected) r = this op a (bitwise)\nfunction bnpBitwiseTo(a,op,r) {\n  var i, f, m = Math.min(a.t,this.t);\n  for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);\n  if(a.t < this.t) {\n    f = a.s&this.DM;\n    for(i = m; i < this.t; ++i) r[i] = op(this[i],f);\n    r.t = this.t;\n  }\n  else {\n    f = this.s&this.DM;\n    for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);\n    r.t = a.t;\n  }\n  r.s = op(this.s,a.s);\n  r.clamp();\n}\n\n// (public) this & a\nfunction op_and(x,y) { return x&y; }\nfunction bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }\n\n// (public) this | a\nfunction op_or(x,y) { return x|y; }\nfunction bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }\n\n// (public) this ^ a\nfunction op_xor(x,y) { return x^y; }\nfunction bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }\n\n// (public) this & ~a\nfunction op_andnot(x,y) { return x&~y; }\nfunction bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }\n\n// (public) ~this\nfunction bnNot() {\n  var r = nbi();\n  for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];\n  r.t = this.t;\n  r.s = ~this.s;\n  return r;\n}\n\n// (public) this << n\nfunction bnShiftLeft(n) {\n  var r = nbi();\n  if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);\n  return r;\n}\n\n// (public) this >> n\nfunction bnShiftRight(n) {\n  var r = nbi();\n  if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);\n  return r;\n}\n\n// return index of lowest 1-bit in x, x < 2^31\nfunction lbit(x) {\n  if(x == 0) return -1;\n  var r = 0;\n  if((x&0xffff) == 0) { x >>= 16; r += 16; }\n  if((x&0xff) == 0) { x >>= 8; r += 8; }\n  if((x&0xf) == 0) { x >>= 4; r += 4; }\n  if((x&3) == 0) { x >>= 2; r += 2; }\n  if((x&1) == 0) ++r;\n  return r;\n}\n\n// (public) returns index of lowest 1-bit (or -1 if none)\nfunction bnGetLowestSetBit() {\n  for(var i = 0; i < this.t; ++i)\n    if(this[i] != 0) return i*this.DB+lbit(this[i]);\n  if(this.s < 0) return this.t*this.DB;\n  return -1;\n}\n\n// return number of 1 bits in x\nfunction cbit(x) {\n  var r = 0;\n  while(x != 0) { x &= x-1; ++r; }\n  return r;\n}\n\n// (public) return number of set bits\nfunction bnBitCount() {\n  var r = 0, x = this.s&this.DM;\n  for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);\n  return r;\n}\n\n// (public) true iff nth bit is set\nfunction bnTestBit(n) {\n  var j = Math.floor(n/this.DB);\n  if(j >= this.t) return(this.s!=0);\n  return((this[j]&(1<<(n%this.DB)))!=0);\n}\n\n// (protected) this op (1<<n)\nfunction bnpChangeBit(n,op) {\n  var r = BigInteger.ONE.shiftLeft(n);\n  this.bitwiseTo(r,op,r);\n  return r;\n}\n\n// (public) this | (1<<n)\nfunction bnSetBit(n) { return this.changeBit(n,op_or); }\n\n// (public) this & ~(1<<n)\nfunction bnClearBit(n) { return this.changeBit(n,op_andnot); }\n\n// (public) this ^ (1<<n)\nfunction bnFlipBit(n) { return this.changeBit(n,op_xor); }\n\n// (protected) r = this + a\nfunction bnpAddTo(a,r) {\n  var i = 0, c = 0, m = Math.min(a.t,this.t);\n  while(i < m) {\n    c += this[i]+a[i];\n    r[i++] = c&this.DM;\n    c >>= this.DB;\n  }\n  if(a.t < this.t) {\n    c += a.s;\n    while(i < this.t) {\n      c += this[i];\n      r[i++] = c&this.DM;\n      c >>= this.DB;\n    }\n    c += this.s;\n  }\n  else {\n    c += this.s;\n    while(i < a.t) {\n      c += a[i];\n      r[i++] = c&this.DM;\n      c >>= this.DB;\n    }\n    c += a.s;\n  }\n  r.s = (c<0)?-1:0;\n  if(c > 0) r[i++] = c;\n  else if(c < -1) r[i++] = this.DV+c;\n  r.t = i;\n  r.clamp();\n}\n\n// (public) this + a\nfunction bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }\n\n// (public) this - a\nfunction bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }\n\n// (public) this * a\nfunction bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }\n\n// (public) this^2\nfunction bnSquare() { var r = nbi(); this.squareTo(r); return r; }\n\n// (public) this / a\nfunction bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }\n\n// (public) this % a\nfunction bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }\n\n// (public) [this/a,this%a]\nfunction bnDivideAndRemainder(a) {\n  var q = nbi(), r = nbi();\n  this.divRemTo(a,q,r);\n  return new Array(q,r);\n}\n\n// (protected) this *= n, this >= 0, 1 < n < DV\nfunction bnpDMultiply(n) {\n  this[this.t] = this.am(0,n-1,this,0,0,this.t);\n  ++this.t;\n  this.clamp();\n}\n\n// (protected) this += n << w words, this >= 0\nfunction bnpDAddOffset(n,w) {\n  if(n == 0) return;\n  while(this.t <= w) this[this.t++] = 0;\n  this[w] += n;\n  while(this[w] >= this.DV) {\n    this[w] -= this.DV;\n    if(++w >= this.t) this[this.t++] = 0;\n    ++this[w];\n  }\n}\n\n// A \"null\" reducer\nfunction NullExp() {}\nfunction nNop(x) { return x; }\nfunction nMulTo(x,y,r) { x.multiplyTo(y,r); }\nfunction nSqrTo(x,r) { x.squareTo(r); }\n\nNullExp.prototype.convert = nNop;\nNullExp.prototype.revert = nNop;\nNullExp.prototype.mulTo = nMulTo;\nNullExp.prototype.sqrTo = nSqrTo;\n\n// (public) this^e\nfunction bnPow(e) { return this.exp(e,new NullExp()); }\n\n// (protected) r = lower n words of \"this * a\", a.t <= n\n// \"this\" should be the larger one if appropriate.\nfunction bnpMultiplyLowerTo(a,n,r) {\n  var i = Math.min(this.t+a.t,n);\n  r.s = 0; // assumes a,this >= 0\n  r.t = i;\n  while(i > 0) r[--i] = 0;\n  var j;\n  for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);\n  for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);\n  r.clamp();\n}\n\n// (protected) r = \"this * a\" without lower n words, n > 0\n// \"this\" should be the larger one if appropriate.\nfunction bnpMultiplyUpperTo(a,n,r) {\n  --n;\n  var i = r.t = this.t+a.t-n;\n  r.s = 0; // assumes a,this >= 0\n  while(--i >= 0) r[i] = 0;\n  for(i = Math.max(n-this.t,0); i < a.t; ++i)\n    r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);\n  r.clamp();\n  r.drShiftTo(1,r);\n}\n\n// Barrett modular reduction\nfunction Barrett(m) {\n  // setup Barrett\n  this.r2 = nbi();\n  this.q3 = nbi();\n  BigInteger.ONE.dlShiftTo(2*m.t,this.r2);\n  this.mu = this.r2.divide(m);\n  this.m = m;\n}\n\nfunction barrettConvert(x) {\n  if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);\n  else if(x.compareTo(this.m) < 0) return x;\n  else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }\n}\n\nfunction barrettRevert(x) { return x; }\n\n// x = x mod m (HAC 14.42)\nfunction barrettReduce(x) {\n  x.drShiftTo(this.m.t-1,this.r2);\n  if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }\n  this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);\n  this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);\n  while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);\n  x.subTo(this.r2,x);\n  while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);\n}\n\n// r = x^2 mod m; x != r\nfunction barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }\n\n// r = x*y mod m; x,y != r\nfunction barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }\n\nBarrett.prototype.convert = barrettConvert;\nBarrett.prototype.revert = barrettRevert;\nBarrett.prototype.reduce = barrettReduce;\nBarrett.prototype.mulTo = barrettMulTo;\nBarrett.prototype.sqrTo = barrettSqrTo;\n\n// (public) this^e % m (HAC 14.85)\nfunction bnModPow(e,m) {\n  var i = e.bitLength(), k, r = nbv(1), z;\n  if(i <= 0) return r;\n  else if(i < 18) k = 1;\n  else if(i < 48) k = 3;\n  else if(i < 144) k = 4;\n  else if(i < 768) k = 5;\n  else k = 6;\n  if(i < 8)\n    z = new Classic(m);\n  else if(m.isEven())\n    z = new Barrett(m);\n  else\n    z = new Montgomery(m);\n\n  // precomputation\n  var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;\n  g[1] = z.convert(this);\n  if(k > 1) {\n    var g2 = nbi();\n    z.sqrTo(g[1],g2);\n    while(n <= km) {\n      g[n] = nbi();\n      z.mulTo(g2,g[n-2],g[n]);\n      n += 2;\n    }\n  }\n\n  var j = e.t-1, w, is1 = true, r2 = nbi(), t;\n  i = nbits(e[j])-1;\n  while(j >= 0) {\n    if(i >= k1) w = (e[j]>>(i-k1))&km;\n    else {\n      w = (e[j]&((1<<(i+1))-1))<<(k1-i);\n      if(j > 0) w |= e[j-1]>>(this.DB+i-k1);\n    }\n\n    n = k;\n    while((w&1) == 0) { w >>= 1; --n; }\n    if((i -= n) < 0) { i += this.DB; --j; }\n    if(is1) {\t// ret == 1, don't bother squaring or multiplying it\n      g[w].copyTo(r);\n      is1 = false;\n    }\n    else {\n      while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }\n      if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }\n      z.mulTo(r2,g[w],r);\n    }\n\n    while(j >= 0 && (e[j]&(1<<i)) == 0) {\n      z.sqrTo(r,r2); t = r; r = r2; r2 = t;\n      if(--i < 0) { i = this.DB-1; --j; }\n    }\n  }\n  return z.revert(r);\n}\n\n// (public) gcd(this,a) (HAC 14.54)\nfunction bnGCD(a) {\n  var x = (this.s<0)?this.negate():this.clone();\n  var y = (a.s<0)?a.negate():a.clone();\n  if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }\n  var i = x.getLowestSetBit(), g = y.getLowestSetBit();\n  if(g < 0) return x;\n  if(i < g) g = i;\n  if(g > 0) {\n    x.rShiftTo(g,x);\n    y.rShiftTo(g,y);\n  }\n  while(x.signum() > 0) {\n    if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);\n    if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);\n    if(x.compareTo(y) >= 0) {\n      x.subTo(y,x);\n      x.rShiftTo(1,x);\n    }\n    else {\n      y.subTo(x,y);\n      y.rShiftTo(1,y);\n    }\n  }\n  if(g > 0) y.lShiftTo(g,y);\n  return y;\n}\n\n// (protected) this % n, n < 2^26\nfunction bnpModInt(n) {\n  if(n <= 0) return 0;\n  var d = this.DV%n, r = (this.s<0)?n-1:0;\n  if(this.t > 0)\n    if(d == 0) r = this[0]%n;\n    else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;\n  return r;\n}\n\n// (public) 1/this % m (HAC 14.61)\nfunction bnModInverse(m) {\n  var ac = m.isEven();\n  if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;\n  var u = m.clone(), v = this.clone();\n  var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);\n  while(u.signum() != 0) {\n    while(u.isEven()) {\n      u.rShiftTo(1,u);\n      if(ac) {\n        if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }\n        a.rShiftTo(1,a);\n      }\n      else if(!b.isEven()) b.subTo(m,b);\n      b.rShiftTo(1,b);\n    }\n    while(v.isEven()) {\n      v.rShiftTo(1,v);\n      if(ac) {\n        if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }\n        c.rShiftTo(1,c);\n      }\n      else if(!d.isEven()) d.subTo(m,d);\n      d.rShiftTo(1,d);\n    }\n    if(u.compareTo(v) >= 0) {\n      u.subTo(v,u);\n      if(ac) a.subTo(c,a);\n      b.subTo(d,b);\n    }\n    else {\n      v.subTo(u,v);\n      if(ac) c.subTo(a,c);\n      d.subTo(b,d);\n    }\n  }\n  if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;\n  if(d.compareTo(m) >= 0) return d.subtract(m);\n  if(d.signum() < 0) d.addTo(m,d); else return d;\n  if(d.signum() < 0) return d.add(m); else return d;\n}\n\nvar lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];\nvar lplim = (1<<26)/lowprimes[lowprimes.length-1];\n\n// (public) test primality with certainty >= 1-.5^t\nfunction bnIsProbablePrime(t) {\n  var i, x = this.abs();\n  if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {\n    for(i = 0; i < lowprimes.length; ++i)\n      if(x[0] == lowprimes[i]) return true;\n    return false;\n  }\n  if(x.isEven()) return false;\n  i = 1;\n  while(i < lowprimes.length) {\n    var m = lowprimes[i], j = i+1;\n    while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];\n    m = x.modInt(m);\n    while(i < j) if(m%lowprimes[i++] == 0) return false;\n  }\n  return x.millerRabin(t);\n}\n\n// (protected) true if probably prime (HAC 4.24, Miller-Rabin)\nfunction bnpMillerRabin(t) {\n  var n1 = this.subtract(BigInteger.ONE);\n  var k = n1.getLowestSetBit();\n  if(k <= 0) return false;\n  var r = n1.shiftRight(k);\n  t = (t+1)>>1;\n  if(t > lowprimes.length) t = lowprimes.length;\n  var a = nbi();\n  for(var i = 0; i < t; ++i) {\n    //Pick bases at random, instead of starting at 2\n    a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);\n    var y = a.modPow(r,this);\n    if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {\n      var j = 1;\n      while(j++ < k && y.compareTo(n1) != 0) {\n        y = y.modPowInt(2,this);\n        if(y.compareTo(BigInteger.ONE) == 0) return false;\n      }\n      if(y.compareTo(n1) != 0) return false;\n    }\n  }\n  return true;\n}\n\n\n// protected\nBigInteger.prototype.chunkSize = bnpChunkSize;\nBigInteger.prototype.toRadix = bnpToRadix;\nBigInteger.prototype.fromRadix = bnpFromRadix;\nBigInteger.prototype.fromNumber = bnpFromNumber;\nBigInteger.prototype.bitwiseTo = bnpBitwiseTo;\nBigInteger.prototype.changeBit = bnpChangeBit;\nBigInteger.prototype.addTo = bnpAddTo;\nBigInteger.prototype.dMultiply = bnpDMultiply;\nBigInteger.prototype.dAddOffset = bnpDAddOffset;\nBigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;\nBigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;\nBigInteger.prototype.modInt = bnpModInt;\nBigInteger.prototype.millerRabin = bnpMillerRabin;\n\nBigInteger.prototype.copyTo = bnpCopyTo;\nBigInteger.prototype.fromInt = bnpFromInt;\nBigInteger.prototype.fromString = bnpFromString;\nBigInteger.prototype.clamp = bnpClamp;\nBigInteger.prototype.dlShiftTo = bnpDLShiftTo;\nBigInteger.prototype.drShiftTo = bnpDRShiftTo;\nBigInteger.prototype.lShiftTo = bnpLShiftTo;\nBigInteger.prototype.rShiftTo = bnpRShiftTo;\nBigInteger.prototype.subTo = bnpSubTo;\nBigInteger.prototype.multiplyTo = bnpMultiplyTo;\nBigInteger.prototype.squareTo = bnpSquareTo;\nBigInteger.prototype.divRemTo = bnpDivRemTo;\nBigInteger.prototype.invDigit = bnpInvDigit;\nBigInteger.prototype.isEven = bnpIsEven;\nBigInteger.prototype.exp = bnpExp;\n\n// public\nBigInteger.prototype.toString = bnToString;\nBigInteger.prototype.negate = bnNegate;\nBigInteger.prototype.abs = bnAbs;\nBigInteger.prototype.compareTo = bnCompareTo;\nBigInteger.prototype.bitLength = bnBitLength;\nBigInteger.prototype.mod = bnMod;\nBigInteger.prototype.modPowInt = bnModPowInt;\n\nBigInteger.prototype.clone = bnClone;\nBigInteger.prototype.intValue = bnIntValue;\nBigInteger.prototype.byteValue = bnByteValue;\nBigInteger.prototype.shortValue = bnShortValue;\nBigInteger.prototype.signum = bnSigNum;\nBigInteger.prototype.toByteArray = bnToByteArray;\nBigInteger.prototype.equals = bnEquals;\nBigInteger.prototype.min = bnMin;\nBigInteger.prototype.max = bnMax;\nBigInteger.prototype.and = bnAnd;\nBigInteger.prototype.or = bnOr;\nBigInteger.prototype.xor = bnXor;\nBigInteger.prototype.andNot = bnAndNot;\nBigInteger.prototype.not = bnNot;\nBigInteger.prototype.shiftLeft = bnShiftLeft;\nBigInteger.prototype.shiftRight = bnShiftRight;\nBigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;\nBigInteger.prototype.bitCount = bnBitCount;\nBigInteger.prototype.testBit = bnTestBit;\nBigInteger.prototype.setBit = bnSetBit;\nBigInteger.prototype.clearBit = bnClearBit;\nBigInteger.prototype.flipBit = bnFlipBit;\nBigInteger.prototype.add = bnAdd;\nBigInteger.prototype.subtract = bnSubtract;\nBigInteger.prototype.multiply = bnMultiply;\nBigInteger.prototype.divide = bnDivide;\nBigInteger.prototype.remainder = bnRemainder;\nBigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;\nBigInteger.prototype.modPow = bnModPow;\nBigInteger.prototype.modInverse = bnModInverse;\nBigInteger.prototype.pow = bnPow;\nBigInteger.prototype.gcd = bnGCD;\nBigInteger.prototype.isProbablePrime = bnIsProbablePrime;\n\n// JSBN-specific extension\nBigInteger.prototype.square = bnSquare;\n\n// \"constants\"\nBigInteger.ZERO = nbv(0);\nBigInteger.ONE = nbv(1);\n\n// BigInteger interfaces not implemented in jsbn:\n\n// BigInteger(int signum, byte[] magnitude)\n// double doubleValue()\n// float floatValue()\n// int hashCode()\n// long longValue()\n// static BigInteger valueOf(long val)\n\nBigInteger.valueOf = nbi;\n\nexports.BigInteger = BigInteger;\n\n\n// WEBPACK FOOTER\n// module.id = 35\n// module.readableIdentifier = ./src/js/jsbn/jsbn.js\n//@ sourceURL=webpack-module:///./src/js/jsbn/jsbn.js");

/***/ },
/* 36 */
/***/ function(module, exports, __webpack_require__) {

	eval("// If there is no WebSocket, try MozWebSocket (support for some old browsers)\ntry {\n  module.exports = WebSocket;\n} catch(err) {\n  module.exports = MozWebSocket;\n}\n\n// Some versions of Safari Mac 5 and Safari iOS 4 seem to support websockets,\n// but can't communicate with websocketpp, which is what rippled uses.\n//\n// Note that we check for both the WebSocket protocol version the browser seems\n// to implement as well as the user agent etc. The reason is that we want to err\n// on the side of trying to connect since we don't want to accidentally disable\n// a browser that would normally work fine.\nvar match, versionRegexp = /Version\\/(\\d+)\\.(\\d+)(?:\\.(\\d+))?.*Safari\\//;\nif (\n  // Is browser\n  \"object\" === typeof navigator &&\n  \"string\" === typeof navigator.userAgent &&\n  // Is Safari\n  (match = versionRegexp.exec(navigator.userAgent)) &&\n  // And uses the old websocket protocol\n  2 === window.WebSocket.CLOSED\n) {\n  // Is iOS\n  if (/iP(hone|od|ad)/.test(navigator.platform)) {\n    // Below version 5 is broken\n    if (+match[1] < 5) {\n      module.exports = void(0);\n    }\n  // Is any other Mac OS\n  // If you want to refactor this code, be careful, iOS user agents contain the\n  // string \"like Mac OS X\".\n  } else if (navigator.appVersion.indexOf(\"Mac\") !== -1) {\n    // Below version 6 is broken\n    if (+match[1] < 6) {\n      module.exports = void(0);\n    }\n  }\n}\n\n\n// WEBPACK FOOTER\n// module.id = 36\n// module.readableIdentifier = ./web_modules/ws.js\n//@ sourceURL=webpack-module:///./web_modules/ws.js");

/***/ },
/* 37 */
/***/ function(module, exports, __webpack_require__) {

	eval("// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nfunction EventEmitter() {\n  this._events = this._events || {};\n  this._maxListeners = this._maxListeners || undefined;\n}\nmodule.exports = EventEmitter;\n\n// Backwards-compat with node 0.10.x\nEventEmitter.EventEmitter = EventEmitter;\n\nEventEmitter.prototype._events = undefined;\nEventEmitter.prototype._maxListeners = undefined;\n\n// By default EventEmitters will print a warning if more than 10 listeners are\n// added to it. This is a useful default which helps finding memory leaks.\nEventEmitter.defaultMaxListeners = 10;\n\n// Obviously not all Emitters should be limited to 10. This function allows\n// that to be increased. Set to zero for unlimited.\nEventEmitter.prototype.setMaxListeners = function(n) {\n  if (!isNumber(n) || n < 0 || isNaN(n))\n    throw TypeError('n must be a positive number');\n  this._maxListeners = n;\n  return this;\n};\n\nEventEmitter.prototype.emit = function(type) {\n  var er, handler, len, args, i, listeners;\n\n  if (!this._events)\n    this._events = {};\n\n  // If there is no 'error' event listener then throw.\n  if (type === 'error') {\n    if (!this._events.error ||\n        (isObject(this._events.error) && !this._events.error.length)) {\n      er = arguments[1];\n      if (er instanceof Error) {\n        throw er; // Unhandled 'error' event\n      }\n      throw TypeError('Uncaught, unspecified \"error\" event.');\n    }\n  }\n\n  handler = this._events[type];\n\n  if (isUndefined(handler))\n    return false;\n\n  if (isFunction(handler)) {\n    switch (arguments.length) {\n      // fast cases\n      case 1:\n        handler.call(this);\n        break;\n      case 2:\n        handler.call(this, arguments[1]);\n        break;\n      case 3:\n        handler.call(this, arguments[1], arguments[2]);\n        break;\n      // slower\n      default:\n        len = arguments.length;\n        args = new Array(len - 1);\n        for (i = 1; i < len; i++)\n          args[i - 1] = arguments[i];\n        handler.apply(this, args);\n    }\n  } else if (isObject(handler)) {\n    len = arguments.length;\n    args = new Array(len - 1);\n    for (i = 1; i < len; i++)\n      args[i - 1] = arguments[i];\n\n    listeners = handler.slice();\n    len = listeners.length;\n    for (i = 0; i < len; i++)\n      listeners[i].apply(this, args);\n  }\n\n  return true;\n};\n\nEventEmitter.prototype.addListener = function(type, listener) {\n  var m;\n\n  if (!isFunction(listener))\n    throw TypeError('listener must be a function');\n\n  if (!this._events)\n    this._events = {};\n\n  // To avoid recursion in the case that type === \"newListener\"! Before\n  // adding it to the listeners, first emit \"newListener\".\n  if (this._events.newListener)\n    this.emit('newListener', type,\n              isFunction(listener.listener) ?\n              listener.listener : listener);\n\n  if (!this._events[type])\n    // Optimize the case of one listener. Don't need the extra array object.\n    this._events[type] = listener;\n  else if (isObject(this._events[type]))\n    // If we've already got an array, just append.\n    this._events[type].push(listener);\n  else\n    // Adding the second element, need to change to array.\n    this._events[type] = [this._events[type], listener];\n\n  // Check for listener leak\n  if (isObject(this._events[type]) && !this._events[type].warned) {\n    var m;\n    if (!isUndefined(this._maxListeners)) {\n      m = this._maxListeners;\n    } else {\n      m = EventEmitter.defaultMaxListeners;\n    }\n\n    if (m && m > 0 && this._events[type].length > m) {\n      this._events[type].warned = true;\n      console.error('(node) warning: possible EventEmitter memory ' +\n                    'leak detected. %d listeners added. ' +\n                    'Use emitter.setMaxListeners() to increase limit.',\n                    this._events[type].length);\n      if (typeof console.trace === 'function') {\n        // not supported in IE 10\n        console.trace();\n      }\n    }\n  }\n\n  return this;\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.once = function(type, listener) {\n  if (!isFunction(listener))\n    throw TypeError('listener must be a function');\n\n  var fired = false;\n\n  function g() {\n    this.removeListener(type, g);\n\n    if (!fired) {\n      fired = true;\n      listener.apply(this, arguments);\n    }\n  }\n\n  g.listener = listener;\n  this.on(type, g);\n\n  return this;\n};\n\n// emits a 'removeListener' event iff the listener was removed\nEventEmitter.prototype.removeListener = function(type, listener) {\n  var list, position, length, i;\n\n  if (!isFunction(listener))\n    throw TypeError('listener must be a function');\n\n  if (!this._events || !this._events[type])\n    return this;\n\n  list = this._events[type];\n  length = list.length;\n  position = -1;\n\n  if (list === listener ||\n      (isFunction(list.listener) && list.listener === listener)) {\n    delete this._events[type];\n    if (this._events.removeListener)\n      this.emit('removeListener', type, listener);\n\n  } else if (isObject(list)) {\n    for (i = length; i-- > 0;) {\n      if (list[i] === listener ||\n          (list[i].listener && list[i].listener === listener)) {\n        position = i;\n        break;\n      }\n    }\n\n    if (position < 0)\n      return this;\n\n    if (list.length === 1) {\n      list.length = 0;\n      delete this._events[type];\n    } else {\n      list.splice(position, 1);\n    }\n\n    if (this._events.removeListener)\n      this.emit('removeListener', type, listener);\n  }\n\n  return this;\n};\n\nEventEmitter.prototype.removeAllListeners = function(type) {\n  var key, listeners;\n\n  if (!this._events)\n    return this;\n\n  // not listening for removeListener, no need to emit\n  if (!this._events.removeListener) {\n    if (arguments.length === 0)\n      this._events = {};\n    else if (this._events[type])\n      delete this._events[type];\n    return this;\n  }\n\n  // emit removeListener for all listeners on all events\n  if (arguments.length === 0) {\n    for (key in this._events) {\n      if (key === 'removeListener') continue;\n      this.removeAllListeners(key);\n    }\n    this.removeAllListeners('removeListener');\n    this._events = {};\n    return this;\n  }\n\n  listeners = this._events[type];\n\n  if (isFunction(listeners)) {\n    this.removeListener(type, listeners);\n  } else {\n    // LIFO order\n    while (listeners.length)\n      this.removeListener(type, listeners[listeners.length - 1]);\n  }\n  delete this._events[type];\n\n  return this;\n};\n\nEventEmitter.prototype.listeners = function(type) {\n  var ret;\n  if (!this._events || !this._events[type])\n    ret = [];\n  else if (isFunction(this._events[type]))\n    ret = [this._events[type]];\n  else\n    ret = this._events[type].slice();\n  return ret;\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n  var ret;\n  if (!emitter._events || !emitter._events[type])\n    ret = 0;\n  else if (isFunction(emitter._events[type]))\n    ret = 1;\n  else\n    ret = emitter._events[type].length;\n  return ret;\n};\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg !== null;\n}\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\n\n\n// WEBPACK FOOTER\n// module.id = 37\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/events/events.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/events/events.js");

/***/ },
/* 38 */
/***/ function(module, exports, __webpack_require__) {

	eval("/* WEBPACK VAR INJECTION */(function(global, process) {// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n\n// Mark that a method should not be used.\n// Returns a modified function which warns once by default.\n// If --no-deprecation is set, then it is a no-op.\nexports.deprecate = function(fn, msg) {\n  // Allow for deprecating things in the process of starting up.\n  if (isUndefined(global.process)) {\n    return function() {\n      return exports.deprecate(fn, msg).apply(this, arguments);\n    };\n  }\n\n  if (process.noDeprecation === true) {\n    return fn;\n  }\n\n  var warned = false;\n  function deprecated() {\n    if (!warned) {\n      if (process.throwDeprecation) {\n        throw new Error(msg);\n      } else if (process.traceDeprecation) {\n        console.trace(msg);\n      } else {\n        console.error(msg);\n      }\n      warned = true;\n    }\n    return fn.apply(this, arguments);\n  }\n\n  return deprecated;\n};\n\n\nvar debugs = {};\nvar debugEnviron;\nexports.debuglog = function(set) {\n  if (isUndefined(debugEnviron))\n    debugEnviron = process.env.NODE_DEBUG || '';\n  set = set.toUpperCase();\n  if (!debugs[set]) {\n    if (new RegExp('\\\\b' + set + '\\\\b', 'i').test(debugEnviron)) {\n      var pid = process.pid;\n      debugs[set] = function() {\n        var msg = exports.format.apply(exports, arguments);\n        console.error('%s %d: %s', set, pid, msg);\n      };\n    } else {\n      debugs[set] = function() {};\n    }\n  }\n  return debugs[set];\n};\n\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  array.forEach(function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes, ctx);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = Object.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = Object.getOwnPropertyNames(value);\n  }\n\n  // IE doesn't make error fields non-enumerable\n  // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx\n  if (isError(value)\n      && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {\n    return formatError(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n  keys.forEach(function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (ctx.seen.indexOf(desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = output.reduce(function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return Array.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg !== null;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) &&\n      (objectToString(e) === '[object Error]' || e instanceof Error);\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nexports.isBuffer = __webpack_require__(57);\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = __webpack_require__(67);\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = Object.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(62)))\n\n// WEBPACK FOOTER\n// module.id = 38\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/util/util.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/util/util.js");

/***/ },
/* 39 */
/***/ function(module, exports, __webpack_require__) {

	eval("// http://wiki.commonjs.org/wiki/Unit_Testing/1.0\n//\n// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!\n//\n// Originally from narwhal.js (http://narwhaljs.org)\n// Copyright (c) 2009 Thomas Robinson <280north.com>\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the 'Software'), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// when used in node, this will actually load the util module we depend on\n// versus loading the builtin util module as happens otherwise\n// this is a bug in node module loading as far as I am concerned\nvar util = __webpack_require__(38);\n\nvar pSlice = Array.prototype.slice;\nvar hasOwn = Object.prototype.hasOwnProperty;\n\n// 1. The assert module provides functions that throw\n// AssertionError's when particular conditions are not met. The\n// assert module must conform to the following interface.\n\nvar assert = module.exports = ok;\n\n// 2. The AssertionError is defined in assert.\n// new assert.AssertionError({ message: message,\n//                             actual: actual,\n//                             expected: expected })\n\nassert.AssertionError = function AssertionError(options) {\n  this.name = 'AssertionError';\n  this.actual = options.actual;\n  this.expected = options.expected;\n  this.operator = options.operator;\n  if (options.message) {\n    this.message = options.message;\n    this.generatedMessage = false;\n  } else {\n    this.message = getMessage(this);\n    this.generatedMessage = true;\n  }\n  var stackStartFunction = options.stackStartFunction || fail;\n\n  if (Error.captureStackTrace) {\n    Error.captureStackTrace(this, stackStartFunction);\n  }\n  else {\n    // non v8 browsers so we can have a stacktrace\n    var err = new Error();\n    if (err.stack) {\n      var out = err.stack;\n\n      // try to strip useless frames\n      var fn_name = stackStartFunction.name;\n      var idx = out.indexOf('\\n' + fn_name);\n      if (idx >= 0) {\n        // once we have located the function frame\n        // we need to strip out everything before it (and its line)\n        var next_line = out.indexOf('\\n', idx + 1);\n        out = out.substring(next_line + 1);\n      }\n\n      this.stack = out;\n    }\n  }\n};\n\n// assert.AssertionError instanceof Error\nutil.inherits(assert.AssertionError, Error);\n\nfunction replacer(key, value) {\n  if (util.isUndefined(value)) {\n    return '' + value;\n  }\n  if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) {\n    return value.toString();\n  }\n  if (util.isFunction(value) || util.isRegExp(value)) {\n    return value.toString();\n  }\n  return value;\n}\n\nfunction truncate(s, n) {\n  if (util.isString(s)) {\n    return s.length < n ? s : s.slice(0, n);\n  } else {\n    return s;\n  }\n}\n\nfunction getMessage(self) {\n  return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +\n         self.operator + ' ' +\n         truncate(JSON.stringify(self.expected, replacer), 128);\n}\n\n// At present only the three keys mentioned above are used and\n// understood by the spec. Implementations or sub modules can pass\n// other keys to the AssertionError's constructor - they will be\n// ignored.\n\n// 3. All of the following functions must throw an AssertionError\n// when a corresponding condition is not met, with a message that\n// may be undefined if not provided.  All assertion methods provide\n// both the actual and expected values to the assertion error for\n// display purposes.\n\nfunction fail(actual, expected, message, operator, stackStartFunction) {\n  throw new assert.AssertionError({\n    message: message,\n    actual: actual,\n    expected: expected,\n    operator: operator,\n    stackStartFunction: stackStartFunction\n  });\n}\n\n// EXTENSION! allows for well behaved errors defined elsewhere.\nassert.fail = fail;\n\n// 4. Pure assertion tests whether a value is truthy, as determined\n// by !!guard.\n// assert.ok(guard, message_opt);\n// This statement is equivalent to assert.equal(true, !!guard,\n// message_opt);. To test strictly for the value true, use\n// assert.strictEqual(true, guard, message_opt);.\n\nfunction ok(value, message) {\n  if (!value) fail(value, true, message, '==', assert.ok);\n}\nassert.ok = ok;\n\n// 5. The equality assertion tests shallow, coercive equality with\n// ==.\n// assert.equal(actual, expected, message_opt);\n\nassert.equal = function equal(actual, expected, message) {\n  if (actual != expected) fail(actual, expected, message, '==', assert.equal);\n};\n\n// 6. The non-equality assertion tests for whether two objects are not equal\n// with != assert.notEqual(actual, expected, message_opt);\n\nassert.notEqual = function notEqual(actual, expected, message) {\n  if (actual == expected) {\n    fail(actual, expected, message, '!=', assert.notEqual);\n  }\n};\n\n// 7. The equivalence assertion tests a deep equality relation.\n// assert.deepEqual(actual, expected, message_opt);\n\nassert.deepEqual = function deepEqual(actual, expected, message) {\n  if (!_deepEqual(actual, expected)) {\n    fail(actual, expected, message, 'deepEqual', assert.deepEqual);\n  }\n};\n\nfunction _deepEqual(actual, expected) {\n  // 7.1. All identical values are equivalent, as determined by ===.\n  if (actual === expected) {\n    return true;\n\n  } else if (util.isBuffer(actual) && util.isBuffer(expected)) {\n    if (actual.length != expected.length) return false;\n\n    for (var i = 0; i < actual.length; i++) {\n      if (actual[i] !== expected[i]) return false;\n    }\n\n    return true;\n\n  // 7.2. If the expected value is a Date object, the actual value is\n  // equivalent if it is also a Date object that refers to the same time.\n  } else if (util.isDate(actual) && util.isDate(expected)) {\n    return actual.getTime() === expected.getTime();\n\n  // 7.3 If the expected value is a RegExp object, the actual value is\n  // equivalent if it is also a RegExp object with the same source and\n  // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).\n  } else if (util.isRegExp(actual) && util.isRegExp(expected)) {\n    return actual.source === expected.source &&\n           actual.global === expected.global &&\n           actual.multiline === expected.multiline &&\n           actual.lastIndex === expected.lastIndex &&\n           actual.ignoreCase === expected.ignoreCase;\n\n  // 7.4. Other pairs that do not both pass typeof value == 'object',\n  // equivalence is determined by ==.\n  } else if (!util.isObject(actual) && !util.isObject(expected)) {\n    return actual == expected;\n\n  // 7.5 For all other Object pairs, including Array objects, equivalence is\n  // determined by having the same number of owned properties (as verified\n  // with Object.prototype.hasOwnProperty.call), the same set of keys\n  // (although not necessarily the same order), equivalent values for every\n  // corresponding key, and an identical 'prototype' property. Note: this\n  // accounts for both named and indexed properties on Arrays.\n  } else {\n    return objEquiv(actual, expected);\n  }\n}\n\nfunction isArguments(object) {\n  return Object.prototype.toString.call(object) == '[object Arguments]';\n}\n\nfunction objEquiv(a, b) {\n  if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))\n    return false;\n  // an identical 'prototype' property.\n  if (a.prototype !== b.prototype) return false;\n  //~~~I've managed to break Object.keys through screwy arguments passing.\n  //   Converting to array solves the problem.\n  if (isArguments(a)) {\n    if (!isArguments(b)) {\n      return false;\n    }\n    a = pSlice.call(a);\n    b = pSlice.call(b);\n    return _deepEqual(a, b);\n  }\n  try {\n    var ka = objectKeys(a),\n        kb = objectKeys(b),\n        key, i;\n  } catch (e) {//happens when one is a string literal and the other isn't\n    return false;\n  }\n  // having the same number of owned properties (keys incorporates\n  // hasOwnProperty)\n  if (ka.length != kb.length)\n    return false;\n  //the same set of keys (although not necessarily the same order),\n  ka.sort();\n  kb.sort();\n  //~~~cheap key test\n  for (i = ka.length - 1; i >= 0; i--) {\n    if (ka[i] != kb[i])\n      return false;\n  }\n  //equivalent values for every corresponding key, and\n  //~~~possibly expensive deep test\n  for (i = ka.length - 1; i >= 0; i--) {\n    key = ka[i];\n    if (!_deepEqual(a[key], b[key])) return false;\n  }\n  return true;\n}\n\n// 8. The non-equivalence assertion tests for any deep inequality.\n// assert.notDeepEqual(actual, expected, message_opt);\n\nassert.notDeepEqual = function notDeepEqual(actual, expected, message) {\n  if (_deepEqual(actual, expected)) {\n    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);\n  }\n};\n\n// 9. The strict equality assertion tests strict equality, as determined by ===.\n// assert.strictEqual(actual, expected, message_opt);\n\nassert.strictEqual = function strictEqual(actual, expected, message) {\n  if (actual !== expected) {\n    fail(actual, expected, message, '===', assert.strictEqual);\n  }\n};\n\n// 10. The strict non-equality assertion tests for strict inequality, as\n// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);\n\nassert.notStrictEqual = function notStrictEqual(actual, expected, message) {\n  if (actual === expected) {\n    fail(actual, expected, message, '!==', assert.notStrictEqual);\n  }\n};\n\nfunction expectedException(actual, expected) {\n  if (!actual || !expected) {\n    return false;\n  }\n\n  if (Object.prototype.toString.call(expected) == '[object RegExp]') {\n    return expected.test(actual);\n  } else if (actual instanceof expected) {\n    return true;\n  } else if (expected.call({}, actual) === true) {\n    return true;\n  }\n\n  return false;\n}\n\nfunction _throws(shouldThrow, block, expected, message) {\n  var actual;\n\n  if (util.isString(expected)) {\n    message = expected;\n    expected = null;\n  }\n\n  try {\n    block();\n  } catch (e) {\n    actual = e;\n  }\n\n  message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +\n            (message ? ' ' + message : '.');\n\n  if (shouldThrow && !actual) {\n    fail(actual, expected, 'Missing expected exception' + message);\n  }\n\n  if (!shouldThrow && expectedException(actual, expected)) {\n    fail(actual, expected, 'Got unwanted exception' + message);\n  }\n\n  if ((shouldThrow && actual && expected &&\n      !expectedException(actual, expected)) || (!shouldThrow && actual)) {\n    throw actual;\n  }\n}\n\n// 11. Expected to throw an error:\n// assert.throws(block, Error_opt, message_opt);\n\nassert.throws = function(block, /*optional*/error, /*optional*/message) {\n  _throws.apply(this, [true].concat(pSlice.call(arguments)));\n};\n\n// EXTENSION! This is annoying to write outside this module.\nassert.doesNotThrow = function(block, /*optional*/message) {\n  _throws.apply(this, [false].concat(pSlice.call(arguments)));\n};\n\nassert.ifError = function(err) { if (err) {throw err;}};\n\nvar objectKeys = Object.keys || function (obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (hasOwn.call(obj, key)) keys.push(key);\n  }\n  return keys;\n};\n\n\n// WEBPACK FOOTER\n// module.id = 39\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/assert/assert.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/assert/assert.js");

/***/ },
/* 40 */
/***/ function(module, exports, __webpack_require__) {

	eval("/**\n * Logging functionality for ripple-lib and any applications built on it.\n */\nfunction Log(namespace) {\n  if (!namespace) {\n    this._namespace = [];\n  } else if (Array.isArray(namespace)) {\n    this._namespace = namespace;\n  } else {\n    this._namespace = [''+namespace];\n  }\n\n  this._prefix = this._namespace.concat(['']).join(': ');\n};\n\n/**\n * Create a sub-logger.\n *\n * You can have a hierarchy of loggers.\n *\n * @example\n *\n *   var log = require('ripple').log.sub('server');\n *\n *   log.info('connection successful');\n *   // prints: 'server: connection successful'\n */\nLog.prototype.sub = function(namespace) {\n  var subNamespace = this._namespace.slice();\n\n  if (namespace && typeof namespace === 'string') {\n    subNamespace.push(namespace);\n  }\n\n  var subLogger = new Log(subNamespace);\n  subLogger._setParent(this);\n  return subLogger;\n};\n\nLog.prototype._setParent = function(parentLogger) {\n  this._parent = parentLogger;\n};\n\nLog.makeLevel = function(level) {\n  return function() {\n    var args = Array.prototype.slice.call(arguments);\n    args[0] = this._prefix + args[0];\n    Log.engine.logObject.apply(Log, args);\n  };\n};\n\nLog.prototype.debug = Log.makeLevel(1);\nLog.prototype.info  = Log.makeLevel(2);\nLog.prototype.warn  = Log.makeLevel(3);\nLog.prototype.error = Log.makeLevel(4);\n\n/**\n * Basic logging connector.\n *\n * This engine has no formatting and works with the most basic of 'console.log'\n * implementations. This is the logging engine used in Node.js.\n */\nvar BasicLogEngine = {\n  logObject: function logObject(msg) {\n    var args = Array.prototype.slice.call(arguments, 1);\n\n    args = args.map(function(arg) {\n      return JSON.stringify(arg, null, 2);\n    });\n\n    args.unshift(msg);\n    args.unshift('[' + new Date().toISOString() + ']');\n\n    console.log.apply(console, args);\n  }\n};\n\n/**\n * Null logging connector.\n *\n * This engine simply swallows all messages. Used when console.log is not\n * available.\n */\nvar NullLogEngine = {\n  logObject: function() {}\n};\n\nLog.engine = NullLogEngine;\n\nif (console && console.log) {\n  Log.engine = BasicLogEngine;\n}\n\n/**\n * Provide a root logger as our main export.\n *\n * This means you can use the logger easily on the fly:\n *     ripple.log.debug('My object is', myObj);\n */\nmodule.exports = new Log();\n\n/**\n * This is the logger for ripple-lib internally.\n */\nmodule.exports.internal = module.exports.sub();\n\n/**\n * Expose the class as well.\n */\nmodule.exports.Log = Log;\n\n\n// WEBPACK FOOTER\n// module.id = 40\n// module.readableIdentifier = ./src/js/ripple/log.js\n//@ sourceURL=webpack-module:///./src/js/ripple/log.js");

/***/ },
/* 41 */
/***/ function(module, exports, __webpack_require__) {

	eval("/* WEBPACK VAR INJECTION */(function(Buffer) {/*!\n * The buffer module from node.js, for the browser.\n *\n * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>\n * @license  MIT\n */\n\nvar base64 = __webpack_require__(70)\nvar ieee754 = __webpack_require__(65)\n\nexports.Buffer = Buffer\nexports.SlowBuffer = Buffer\nexports.INSPECT_MAX_BYTES = 50\nBuffer.poolSize = 8192\n\n/**\n * If `Buffer._useTypedArrays`:\n *   === true    Use Uint8Array implementation (fastest)\n *   === false   Use Object implementation (compatible down to IE6)\n */\nBuffer._useTypedArrays = (function () {\n  // Detect if browser supports Typed Arrays. Supported browsers are IE 10+, Firefox 4+,\n  // Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. If the browser does not support adding\n  // properties to `Uint8Array` instances, then that's the same as no `Uint8Array` support\n  // because we need to be able to add all the node Buffer API methods. This is an issue\n  // in Firefox 4-29. Now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438\n  try {\n    var buf = new ArrayBuffer(0)\n    var arr = new Uint8Array(buf)\n    arr.foo = function () { return 42 }\n    return 42 === arr.foo() &&\n        typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray`\n  } catch (e) {\n    return false\n  }\n})()\n\n/**\n * Class: Buffer\n * =============\n *\n * The Buffer constructor returns instances of `Uint8Array` that are augmented\n * with function properties for all the node `Buffer` API functions. We use\n * `Uint8Array` so that square bracket notation works as expected -- it returns\n * a single octet.\n *\n * By augmenting the instances, we can avoid modifying the `Uint8Array`\n * prototype.\n */\nfunction Buffer (subject, encoding, noZero) {\n  if (!(this instanceof Buffer))\n    return new Buffer(subject, encoding, noZero)\n\n  var type = typeof subject\n\n  // Workaround: node's base64 implementation allows for non-padded strings\n  // while base64-js does not.\n  if (encoding === 'base64' && type === 'string') {\n    subject = stringtrim(subject)\n    while (subject.length % 4 !== 0) {\n      subject = subject + '='\n    }\n  }\n\n  // Find the length\n  var length\n  if (type === 'number')\n    length = coerce(subject)\n  else if (type === 'string')\n    length = Buffer.byteLength(subject, encoding)\n  else if (type === 'object')\n    length = coerce(subject.length) // assume that object is array-like\n  else\n    throw new Error('First argument needs to be a number, array or string.')\n\n  var buf\n  if (Buffer._useTypedArrays) {\n    // Preferred: Return an augmented `Uint8Array` instance for best performance\n    buf = Buffer._augment(new Uint8Array(length))\n  } else {\n    // Fallback: Return THIS instance of Buffer (created by `new`)\n    buf = this\n    buf.length = length\n    buf._isBuffer = true\n  }\n\n  var i\n  if (Buffer._useTypedArrays && typeof subject.byteLength === 'number') {\n    // Speed optimization -- use set if we're copying from a typed array\n    buf._set(subject)\n  } else if (isArrayish(subject)) {\n    // Treat array-ish objects as a byte array\n    for (i = 0; i < length; i++) {\n      if (Buffer.isBuffer(subject))\n        buf[i] = subject.readUInt8(i)\n      else\n        buf[i] = subject[i]\n    }\n  } else if (type === 'string') {\n    buf.write(subject, 0, encoding)\n  } else if (type === 'number' && !Buffer._useTypedArrays && !noZero) {\n    for (i = 0; i < length; i++) {\n      buf[i] = 0\n    }\n  }\n\n  return buf\n}\n\n// STATIC METHODS\n// ==============\n\nBuffer.isEncoding = function (encoding) {\n  switch (String(encoding).toLowerCase()) {\n    case 'hex':\n    case 'utf8':\n    case 'utf-8':\n    case 'ascii':\n    case 'binary':\n    case 'base64':\n    case 'raw':\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      return true\n    default:\n      return false\n  }\n}\n\nBuffer.isBuffer = function (b) {\n  return !!(b !== null && b !== undefined && b._isBuffer)\n}\n\nBuffer.byteLength = function (str, encoding) {\n  var ret\n  str = str + ''\n  switch (encoding || 'utf8') {\n    case 'hex':\n      ret = str.length / 2\n      break\n    case 'utf8':\n    case 'utf-8':\n      ret = utf8ToBytes(str).length\n      break\n    case 'ascii':\n    case 'binary':\n    case 'raw':\n      ret = str.length\n      break\n    case 'base64':\n      ret = base64ToBytes(str).length\n      break\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      ret = str.length * 2\n      break\n    default:\n      throw new Error('Unknown encoding')\n  }\n  return ret\n}\n\nBuffer.concat = function (list, totalLength) {\n  assert(isArray(list), 'Usage: Buffer.concat(list, [totalLength])\\n' +\n      'list should be an Array.')\n\n  if (list.length === 0) {\n    return new Buffer(0)\n  } else if (list.length === 1) {\n    return list[0]\n  }\n\n  var i\n  if (typeof totalLength !== 'number') {\n    totalLength = 0\n    for (i = 0; i < list.length; i++) {\n      totalLength += list[i].length\n    }\n  }\n\n  var buf = new Buffer(totalLength)\n  var pos = 0\n  for (i = 0; i < list.length; i++) {\n    var item = list[i]\n    item.copy(buf, pos)\n    pos += item.length\n  }\n  return buf\n}\n\n// BUFFER INSTANCE METHODS\n// =======================\n\nfunction _hexWrite (buf, string, offset, length) {\n  offset = Number(offset) || 0\n  var remaining = buf.length - offset\n  if (!length) {\n    length = remaining\n  } else {\n    length = Number(length)\n    if (length > remaining) {\n      length = remaining\n    }\n  }\n\n  // must be an even number of digits\n  var strLen = string.length\n  assert(strLen % 2 === 0, 'Invalid hex string')\n\n  if (length > strLen / 2) {\n    length = strLen / 2\n  }\n  for (var i = 0; i < length; i++) {\n    var byte = parseInt(string.substr(i * 2, 2), 16)\n    assert(!isNaN(byte), 'Invalid hex string')\n    buf[offset + i] = byte\n  }\n  Buffer._charsWritten = i * 2\n  return i\n}\n\nfunction _utf8Write (buf, string, offset, length) {\n  var charsWritten = Buffer._charsWritten =\n    blitBuffer(utf8ToBytes(string), buf, offset, length)\n  return charsWritten\n}\n\nfunction _asciiWrite (buf, string, offset, length) {\n  var charsWritten = Buffer._charsWritten =\n    blitBuffer(asciiToBytes(string), buf, offset, length)\n  return charsWritten\n}\n\nfunction _binaryWrite (buf, string, offset, length) {\n  return _asciiWrite(buf, string, offset, length)\n}\n\nfunction _base64Write (buf, string, offset, length) {\n  var charsWritten = Buffer._charsWritten =\n    blitBuffer(base64ToBytes(string), buf, offset, length)\n  return charsWritten\n}\n\nfunction _utf16leWrite (buf, string, offset, length) {\n  var charsWritten = Buffer._charsWritten =\n    blitBuffer(utf16leToBytes(string), buf, offset, length)\n  return charsWritten\n}\n\nBuffer.prototype.write = function (string, offset, length, encoding) {\n  // Support both (string, offset, length, encoding)\n  // and the legacy (string, encoding, offset, length)\n  if (isFinite(offset)) {\n    if (!isFinite(length)) {\n      encoding = length\n      length = undefined\n    }\n  } else {  // legacy\n    var swap = encoding\n    encoding = offset\n    offset = length\n    length = swap\n  }\n\n  offset = Number(offset) || 0\n  var remaining = this.length - offset\n  if (!length) {\n    length = remaining\n  } else {\n    length = Number(length)\n    if (length > remaining) {\n      length = remaining\n    }\n  }\n  encoding = String(encoding || 'utf8').toLowerCase()\n\n  var ret\n  switch (encoding) {\n    case 'hex':\n      ret = _hexWrite(this, string, offset, length)\n      break\n    case 'utf8':\n    case 'utf-8':\n      ret = _utf8Write(this, string, offset, length)\n      break\n    case 'ascii':\n      ret = _asciiWrite(this, string, offset, length)\n      break\n    case 'binary':\n      ret = _binaryWrite(this, string, offset, length)\n      break\n    case 'base64':\n      ret = _base64Write(this, string, offset, length)\n      break\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      ret = _utf16leWrite(this, string, offset, length)\n      break\n    default:\n      throw new Error('Unknown encoding')\n  }\n  return ret\n}\n\nBuffer.prototype.toString = function (encoding, start, end) {\n  var self = this\n\n  encoding = String(encoding || 'utf8').toLowerCase()\n  start = Number(start) || 0\n  end = (end !== undefined)\n    ? Number(end)\n    : end = self.length\n\n  // Fastpath empty strings\n  if (end === start)\n    return ''\n\n  var ret\n  switch (encoding) {\n    case 'hex':\n      ret = _hexSlice(self, start, end)\n      break\n    case 'utf8':\n    case 'utf-8':\n      ret = _utf8Slice(self, start, end)\n      break\n    case 'ascii':\n      ret = _asciiSlice(self, start, end)\n      break\n    case 'binary':\n      ret = _binarySlice(self, start, end)\n      break\n    case 'base64':\n      ret = _base64Slice(self, start, end)\n      break\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      ret = _utf16leSlice(self, start, end)\n      break\n    default:\n      throw new Error('Unknown encoding')\n  }\n  return ret\n}\n\nBuffer.prototype.toJSON = function () {\n  return {\n    type: 'Buffer',\n    data: Array.prototype.slice.call(this._arr || this, 0)\n  }\n}\n\n// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)\nBuffer.prototype.copy = function (target, target_start, start, end) {\n  var source = this\n\n  if (!start) start = 0\n  if (!end && end !== 0) end = this.length\n  if (!target_start) target_start = 0\n\n  // Copy 0 bytes; we're done\n  if (end === start) return\n  if (target.length === 0 || source.length === 0) return\n\n  // Fatal error conditions\n  assert(end >= start, 'sourceEnd < sourceStart')\n  assert(target_start >= 0 && target_start < target.length,\n      'targetStart out of bounds')\n  assert(start >= 0 && start < source.length, 'sourceStart out of bounds')\n  assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds')\n\n  // Are we oob?\n  if (end > this.length)\n    end = this.length\n  if (target.length - target_start < end - start)\n    end = target.length - target_start + start\n\n  var len = end - start\n\n  if (len < 100 || !Buffer._useTypedArrays) {\n    for (var i = 0; i < len; i++)\n      target[i + target_start] = this[i + start]\n  } else {\n    target._set(this.subarray(start, start + len), target_start)\n  }\n}\n\nfunction _base64Slice (buf, start, end) {\n  if (start === 0 && end === buf.length) {\n    return base64.fromByteArray(buf)\n  } else {\n    return base64.fromByteArray(buf.slice(start, end))\n  }\n}\n\nfunction _utf8Slice (buf, start, end) {\n  var res = ''\n  var tmp = ''\n  end = Math.min(buf.length, end)\n\n  for (var i = start; i < end; i++) {\n    if (buf[i] <= 0x7F) {\n      res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i])\n      tmp = ''\n    } else {\n      tmp += '%' + buf[i].toString(16)\n    }\n  }\n\n  return res + decodeUtf8Char(tmp)\n}\n\nfunction _asciiSlice (buf, start, end) {\n  var ret = ''\n  end = Math.min(buf.length, end)\n\n  for (var i = start; i < end; i++)\n    ret += String.fromCharCode(buf[i])\n  return ret\n}\n\nfunction _binarySlice (buf, start, end) {\n  return _asciiSlice(buf, start, end)\n}\n\nfunction _hexSlice (buf, start, end) {\n  var len = buf.length\n\n  if (!start || start < 0) start = 0\n  if (!end || end < 0 || end > len) end = len\n\n  var out = ''\n  for (var i = start; i < end; i++) {\n    out += toHex(buf[i])\n  }\n  return out\n}\n\nfunction _utf16leSlice (buf, start, end) {\n  var bytes = buf.slice(start, end)\n  var res = ''\n  for (var i = 0; i < bytes.length; i += 2) {\n    res += String.fromCharCode(bytes[i] + bytes[i+1] * 256)\n  }\n  return res\n}\n\nBuffer.prototype.slice = function (start, end) {\n  var len = this.length\n  start = clamp(start, len, 0)\n  end = clamp(end, len, len)\n\n  if (Buffer._useTypedArrays) {\n    return Buffer._augment(this.subarray(start, end))\n  } else {\n    var sliceLen = end - start\n    var newBuf = new Buffer(sliceLen, undefined, true)\n    for (var i = 0; i < sliceLen; i++) {\n      newBuf[i] = this[i + start]\n    }\n    return newBuf\n  }\n}\n\n// `get` will be removed in Node 0.13+\nBuffer.prototype.get = function (offset) {\n  console.log('.get() is deprecated. Access using array indexes instead.')\n  return this.readUInt8(offset)\n}\n\n// `set` will be removed in Node 0.13+\nBuffer.prototype.set = function (v, offset) {\n  console.log('.set() is deprecated. Access using array indexes instead.')\n  return this.writeUInt8(v, offset)\n}\n\nBuffer.prototype.readUInt8 = function (offset, noAssert) {\n  if (!noAssert) {\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset < this.length, 'Trying to read beyond buffer length')\n  }\n\n  if (offset >= this.length)\n    return\n\n  return this[offset]\n}\n\nfunction _readUInt16 (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  var val\n  if (littleEndian) {\n    val = buf[offset]\n    if (offset + 1 < len)\n      val |= buf[offset + 1] << 8\n  } else {\n    val = buf[offset] << 8\n    if (offset + 1 < len)\n      val |= buf[offset + 1]\n  }\n  return val\n}\n\nBuffer.prototype.readUInt16LE = function (offset, noAssert) {\n  return _readUInt16(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readUInt16BE = function (offset, noAssert) {\n  return _readUInt16(this, offset, false, noAssert)\n}\n\nfunction _readUInt32 (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  var val\n  if (littleEndian) {\n    if (offset + 2 < len)\n      val = buf[offset + 2] << 16\n    if (offset + 1 < len)\n      val |= buf[offset + 1] << 8\n    val |= buf[offset]\n    if (offset + 3 < len)\n      val = val + (buf[offset + 3] << 24 >>> 0)\n  } else {\n    if (offset + 1 < len)\n      val = buf[offset + 1] << 16\n    if (offset + 2 < len)\n      val |= buf[offset + 2] << 8\n    if (offset + 3 < len)\n      val |= buf[offset + 3]\n    val = val + (buf[offset] << 24 >>> 0)\n  }\n  return val\n}\n\nBuffer.prototype.readUInt32LE = function (offset, noAssert) {\n  return _readUInt32(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readUInt32BE = function (offset, noAssert) {\n  return _readUInt32(this, offset, false, noAssert)\n}\n\nBuffer.prototype.readInt8 = function (offset, noAssert) {\n  if (!noAssert) {\n    assert(offset !== undefined && offset !== null,\n        'missing offset')\n    assert(offset < this.length, 'Trying to read beyond buffer length')\n  }\n\n  if (offset >= this.length)\n    return\n\n  var neg = this[offset] & 0x80\n  if (neg)\n    return (0xff - this[offset] + 1) * -1\n  else\n    return this[offset]\n}\n\nfunction _readInt16 (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  var val = _readUInt16(buf, offset, littleEndian, true)\n  var neg = val & 0x8000\n  if (neg)\n    return (0xffff - val + 1) * -1\n  else\n    return val\n}\n\nBuffer.prototype.readInt16LE = function (offset, noAssert) {\n  return _readInt16(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readInt16BE = function (offset, noAssert) {\n  return _readInt16(this, offset, false, noAssert)\n}\n\nfunction _readInt32 (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  var val = _readUInt32(buf, offset, littleEndian, true)\n  var neg = val & 0x80000000\n  if (neg)\n    return (0xffffffff - val + 1) * -1\n  else\n    return val\n}\n\nBuffer.prototype.readInt32LE = function (offset, noAssert) {\n  return _readInt32(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readInt32BE = function (offset, noAssert) {\n  return _readInt32(this, offset, false, noAssert)\n}\n\nfunction _readFloat (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  return ieee754.read(buf, offset, littleEndian, 23, 4)\n}\n\nBuffer.prototype.readFloatLE = function (offset, noAssert) {\n  return _readFloat(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readFloatBE = function (offset, noAssert) {\n  return _readFloat(this, offset, false, noAssert)\n}\n\nfunction _readDouble (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset + 7 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  return ieee754.read(buf, offset, littleEndian, 52, 8)\n}\n\nBuffer.prototype.readDoubleLE = function (offset, noAssert) {\n  return _readDouble(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readDoubleBE = function (offset, noAssert) {\n  return _readDouble(this, offset, false, noAssert)\n}\n\nBuffer.prototype.writeUInt8 = function (value, offset, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset < this.length, 'trying to write beyond buffer length')\n    verifuint(value, 0xff)\n  }\n\n  if (offset >= this.length) return\n\n  this[offset] = value\n}\n\nfunction _writeUInt16 (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 1 < buf.length, 'trying to write beyond buffer length')\n    verifuint(value, 0xffff)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) {\n    buf[offset + i] =\n        (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>\n            (littleEndian ? i : 1 - i) * 8\n  }\n}\n\nBuffer.prototype.writeUInt16LE = function (value, offset, noAssert) {\n  _writeUInt16(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeUInt16BE = function (value, offset, noAssert) {\n  _writeUInt16(this, value, offset, false, noAssert)\n}\n\nfunction _writeUInt32 (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'trying to write beyond buffer length')\n    verifuint(value, 0xffffffff)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) {\n    buf[offset + i] =\n        (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff\n  }\n}\n\nBuffer.prototype.writeUInt32LE = function (value, offset, noAssert) {\n  _writeUInt32(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeUInt32BE = function (value, offset, noAssert) {\n  _writeUInt32(this, value, offset, false, noAssert)\n}\n\nBuffer.prototype.writeInt8 = function (value, offset, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset < this.length, 'Trying to write beyond buffer length')\n    verifsint(value, 0x7f, -0x80)\n  }\n\n  if (offset >= this.length)\n    return\n\n  if (value >= 0)\n    this.writeUInt8(value, offset, noAssert)\n  else\n    this.writeUInt8(0xff + value + 1, offset, noAssert)\n}\n\nfunction _writeInt16 (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 1 < buf.length, 'Trying to write beyond buffer length')\n    verifsint(value, 0x7fff, -0x8000)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  if (value >= 0)\n    _writeUInt16(buf, value, offset, littleEndian, noAssert)\n  else\n    _writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert)\n}\n\nBuffer.prototype.writeInt16LE = function (value, offset, noAssert) {\n  _writeInt16(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeInt16BE = function (value, offset, noAssert) {\n  _writeInt16(this, value, offset, false, noAssert)\n}\n\nfunction _writeInt32 (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')\n    verifsint(value, 0x7fffffff, -0x80000000)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  if (value >= 0)\n    _writeUInt32(buf, value, offset, littleEndian, noAssert)\n  else\n    _writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert)\n}\n\nBuffer.prototype.writeInt32LE = function (value, offset, noAssert) {\n  _writeInt32(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeInt32BE = function (value, offset, noAssert) {\n  _writeInt32(this, value, offset, false, noAssert)\n}\n\nfunction _writeFloat (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')\n    verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  ieee754.write(buf, value, offset, littleEndian, 23, 4)\n}\n\nBuffer.prototype.writeFloatLE = function (value, offset, noAssert) {\n  _writeFloat(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeFloatBE = function (value, offset, noAssert) {\n  _writeFloat(this, value, offset, false, noAssert)\n}\n\nfunction _writeDouble (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 7 < buf.length,\n        'Trying to write beyond buffer length')\n    verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  ieee754.write(buf, value, offset, littleEndian, 52, 8)\n}\n\nBuffer.prototype.writeDoubleLE = function (value, offset, noAssert) {\n  _writeDouble(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeDoubleBE = function (value, offset, noAssert) {\n  _writeDouble(this, value, offset, false, noAssert)\n}\n\n// fill(value, start=0, end=buffer.length)\nBuffer.prototype.fill = function (value, start, end) {\n  if (!value) value = 0\n  if (!start) start = 0\n  if (!end) end = this.length\n\n  if (typeof value === 'string') {\n    value = value.charCodeAt(0)\n  }\n\n  assert(typeof value === 'number' && !isNaN(value), 'value is not a number')\n  assert(end >= start, 'end < start')\n\n  // Fill 0 bytes; we're done\n  if (end === start) return\n  if (this.length === 0) return\n\n  assert(start >= 0 && start < this.length, 'start out of bounds')\n  assert(end >= 0 && end <= this.length, 'end out of bounds')\n\n  for (var i = start; i < end; i++) {\n    this[i] = value\n  }\n}\n\nBuffer.prototype.inspect = function () {\n  var out = []\n  var len = this.length\n  for (var i = 0; i < len; i++) {\n    out[i] = toHex(this[i])\n    if (i === exports.INSPECT_MAX_BYTES) {\n      out[i + 1] = '...'\n      break\n    }\n  }\n  return '<Buffer ' + out.join(' ') + '>'\n}\n\n/**\n * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.\n * Added in Node 0.12. Only available in browsers that support ArrayBuffer.\n */\nBuffer.prototype.toArrayBuffer = function () {\n  if (typeof Uint8Array !== 'undefined') {\n    if (Buffer._useTypedArrays) {\n      return (new Buffer(this)).buffer\n    } else {\n      var buf = new Uint8Array(this.length)\n      for (var i = 0, len = buf.length; i < len; i += 1)\n        buf[i] = this[i]\n      return buf.buffer\n    }\n  } else {\n    throw new Error('Buffer.toArrayBuffer not supported in this browser')\n  }\n}\n\n// HELPER FUNCTIONS\n// ================\n\nfunction stringtrim (str) {\n  if (str.trim) return str.trim()\n  return str.replace(/^\\s+|\\s+$/g, '')\n}\n\nvar BP = Buffer.prototype\n\n/**\n * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods\n */\nBuffer._augment = function (arr) {\n  arr._isBuffer = true\n\n  // save reference to original Uint8Array get/set methods before overwriting\n  arr._get = arr.get\n  arr._set = arr.set\n\n  // deprecated, will be removed in node 0.13+\n  arr.get = BP.get\n  arr.set = BP.set\n\n  arr.write = BP.write\n  arr.toString = BP.toString\n  arr.toLocaleString = BP.toString\n  arr.toJSON = BP.toJSON\n  arr.copy = BP.copy\n  arr.slice = BP.slice\n  arr.readUInt8 = BP.readUInt8\n  arr.readUInt16LE = BP.readUInt16LE\n  arr.readUInt16BE = BP.readUInt16BE\n  arr.readUInt32LE = BP.readUInt32LE\n  arr.readUInt32BE = BP.readUInt32BE\n  arr.readInt8 = BP.readInt8\n  arr.readInt16LE = BP.readInt16LE\n  arr.readInt16BE = BP.readInt16BE\n  arr.readInt32LE = BP.readInt32LE\n  arr.readInt32BE = BP.readInt32BE\n  arr.readFloatLE = BP.readFloatLE\n  arr.readFloatBE = BP.readFloatBE\n  arr.readDoubleLE = BP.readDoubleLE\n  arr.readDoubleBE = BP.readDoubleBE\n  arr.writeUInt8 = BP.writeUInt8\n  arr.writeUInt16LE = BP.writeUInt16LE\n  arr.writeUInt16BE = BP.writeUInt16BE\n  arr.writeUInt32LE = BP.writeUInt32LE\n  arr.writeUInt32BE = BP.writeUInt32BE\n  arr.writeInt8 = BP.writeInt8\n  arr.writeInt16LE = BP.writeInt16LE\n  arr.writeInt16BE = BP.writeInt16BE\n  arr.writeInt32LE = BP.writeInt32LE\n  arr.writeInt32BE = BP.writeInt32BE\n  arr.writeFloatLE = BP.writeFloatLE\n  arr.writeFloatBE = BP.writeFloatBE\n  arr.writeDoubleLE = BP.writeDoubleLE\n  arr.writeDoubleBE = BP.writeDoubleBE\n  arr.fill = BP.fill\n  arr.inspect = BP.inspect\n  arr.toArrayBuffer = BP.toArrayBuffer\n\n  return arr\n}\n\n// slice(start, end)\nfunction clamp (index, len, defaultValue) {\n  if (typeof index !== 'number') return defaultValue\n  index = ~~index;  // Coerce to integer.\n  if (index >= len) return len\n  if (index >= 0) return index\n  index += len\n  if (index >= 0) return index\n  return 0\n}\n\nfunction coerce (length) {\n  // Coerce length to a number (possibly NaN), round up\n  // in case it's fractional (e.g. 123.456) then do a\n  // double negate to coerce a NaN to 0. Easy, right?\n  length = ~~Math.ceil(+length)\n  return length < 0 ? 0 : length\n}\n\nfunction isArray (subject) {\n  return (Array.isArray || function (subject) {\n    return Object.prototype.toString.call(subject) === '[object Array]'\n  })(subject)\n}\n\nfunction isArrayish (subject) {\n  return isArray(subject) || Buffer.isBuffer(subject) ||\n      subject && typeof subject === 'object' &&\n      typeof subject.length === 'number'\n}\n\nfunction toHex (n) {\n  if (n < 16) return '0' + n.toString(16)\n  return n.toString(16)\n}\n\nfunction utf8ToBytes (str) {\n  var byteArray = []\n  for (var i = 0; i < str.length; i++) {\n    var b = str.charCodeAt(i)\n    if (b <= 0x7F)\n      byteArray.push(str.charCodeAt(i))\n    else {\n      var start = i\n      if (b >= 0xD800 && b <= 0xDFFF) i++\n      var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%')\n      for (var j = 0; j < h.length; j++)\n        byteArray.push(parseInt(h[j], 16))\n    }\n  }\n  return byteArray\n}\n\nfunction asciiToBytes (str) {\n  var byteArray = []\n  for (var i = 0; i < str.length; i++) {\n    // Node's code seems to be doing this and not & 0x7F..\n    byteArray.push(str.charCodeAt(i) & 0xFF)\n  }\n  return byteArray\n}\n\nfunction utf16leToBytes (str) {\n  var c, hi, lo\n  var byteArray = []\n  for (var i = 0; i < str.length; i++) {\n    c = str.charCodeAt(i)\n    hi = c >> 8\n    lo = c % 256\n    byteArray.push(lo)\n    byteArray.push(hi)\n  }\n\n  return byteArray\n}\n\nfunction base64ToBytes (str) {\n  return base64.toByteArray(str)\n}\n\nfunction blitBuffer (src, dst, offset, length) {\n  var pos\n  for (var i = 0; i < length; i++) {\n    if ((i + offset >= dst.length) || (i >= src.length))\n      break\n    dst[i + offset] = src[i]\n  }\n  return i\n}\n\nfunction decodeUtf8Char (str) {\n  try {\n    return decodeURIComponent(str)\n  } catch (err) {\n    return String.fromCharCode(0xFFFD) // UTF 8 invalid char\n  }\n}\n\n/*\n * We have to make sure that the value is a valid integer. This means that it\n * is non-negative. It has no fractional component and that it does not\n * exceed the maximum allowed value.\n */\nfunction verifuint (value, max) {\n  assert(typeof value === 'number', 'cannot write a non-number as a number')\n  assert(value >= 0, 'specified a negative value for writing an unsigned value')\n  assert(value <= max, 'value is larger than maximum value for type')\n  assert(Math.floor(value) === value, 'value has a fractional component')\n}\n\nfunction verifsint (value, max, min) {\n  assert(typeof value === 'number', 'cannot write a non-number as a number')\n  assert(value <= max, 'value larger than maximum allowed value')\n  assert(value >= min, 'value smaller than minimum allowed value')\n  assert(Math.floor(value) === value, 'value has a fractional component')\n}\n\nfunction verifIEEE754 (value, max, min) {\n  assert(typeof value === 'number', 'cannot write a non-number as a number')\n  assert(value <= max, 'value larger than maximum allowed value')\n  assert(value >= min, 'value smaller than minimum allowed value')\n}\n\nfunction assert (test, message) {\n  if (!test) throw new Error(message || 'Failed assertion')\n}\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(41).Buffer))\n\n// WEBPACK FOOTER\n// module.id = 41\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/buffer/index.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/buffer/index.js");

/***/ },
/* 42 */
/***/ function(module, exports, __webpack_require__) {

	eval("/* WEBPACK VAR INJECTION */(function(Buffer) {var rng = __webpack_require__(53)\n\nfunction error () {\n  var m = [].slice.call(arguments).join(' ')\n  throw new Error([\n    m,\n    'we accept pull requests',\n    'http://github.com/dominictarr/crypto-browserify'\n    ].join('\\n'))\n}\n\nexports.createHash = __webpack_require__(54)\n\nexports.createHmac = __webpack_require__(55)\n\nexports.randomBytes = function(size, callback) {\n  if (callback && callback.call) {\n    try {\n      callback.call(this, undefined, new Buffer(rng(size)))\n    } catch (err) { callback(err) }\n  } else {\n    return new Buffer(rng(size))\n  }\n}\n\nfunction each(a, f) {\n  for(var i in a)\n    f(a[i], i)\n}\n\nexports.getHashes = function () {\n  return ['sha1', 'sha256', 'md5', 'rmd160']\n\n}\n\nvar p = __webpack_require__(56)(exports.createHmac)\nexports.pbkdf2 = p.pbkdf2\nexports.pbkdf2Sync = p.pbkdf2Sync\n\n\n// the least I can do is make error messages for the rest of the node.js/crypto api.\neach(['createCredentials'\n, 'createCipher'\n, 'createCipheriv'\n, 'createDecipher'\n, 'createDecipheriv'\n, 'createSign'\n, 'createVerify'\n, 'createDiffieHellman'\n], function (name) {\n  exports[name] = function () {\n    error('sorry,', name, 'is not implemented yet')\n  }\n})\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(41).Buffer))\n\n// WEBPACK FOOTER\n// module.id = 42\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/index.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/index.js");

/***/ },
/* 43 */
/***/ function(module, exports, __webpack_require__) {

	eval("/*jshint strict:true node:true es5:true onevar:true laxcomma:true laxbreak:true eqeqeq:true immed:true latedef:true*/\n(function () {\n  \"use strict\";\n\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar punycode = __webpack_require__(69);\n\nexports.parse = urlParse;\nexports.resolve = urlResolve;\nexports.resolveObject = urlResolveObject;\nexports.format = urlFormat;\n\n// Reference: RFC 3986, RFC 1808, RFC 2396\n\n// define these here so at least they only have to be\n// compiled once on the first module load.\nvar protocolPattern = /^([a-z0-9.+-]+:)/i,\n    portPattern = /:[0-9]*$/,\n\n    // RFC 2396: characters reserved for delimiting URLs.\n    // We actually just auto-escape these.\n    delims = ['<', '>', '\"', '`', ' ', '\\r', '\\n', '\\t'],\n\n    // RFC 2396: characters not allowed for various reasons.\n    unwise = ['{', '}', '|', '\\\\', '^', '~', '`'].concat(delims),\n\n    // Allowed by RFCs, but cause of XSS attacks.  Always escape these.\n    autoEscape = ['\\''].concat(delims),\n    // Characters that are never ever allowed in a hostname.\n    // Note that any invalid chars are also handled, but these\n    // are the ones that are *expected* to be seen, so we fast-path\n    // them.\n    nonHostChars = ['%', '/', '?', ';', '#']\n      .concat(unwise).concat(autoEscape),\n    nonAuthChars = ['/', '@', '?', '#'].concat(delims),\n    hostnameMaxLen = 255,\n    hostnamePartPattern = /^[a-zA-Z0-9][a-z0-9A-Z_-]{0,62}$/,\n    hostnamePartStart = /^([a-zA-Z0-9][a-z0-9A-Z_-]{0,62})(.*)$/,\n    // protocols that can allow \"unsafe\" and \"unwise\" chars.\n    unsafeProtocol = {\n      'javascript': true,\n      'javascript:': true\n    },\n    // protocols that never have a hostname.\n    hostlessProtocol = {\n      'javascript': true,\n      'javascript:': true\n    },\n    // protocols that always have a path component.\n    pathedProtocol = {\n      'http': true,\n      'https': true,\n      'ftp': true,\n      'gopher': true,\n      'file': true,\n      'http:': true,\n      'ftp:': true,\n      'gopher:': true,\n      'file:': true\n    },\n    // protocols that always contain a // bit.\n    slashedProtocol = {\n      'http': true,\n      'https': true,\n      'ftp': true,\n      'gopher': true,\n      'file': true,\n      'http:': true,\n      'https:': true,\n      'ftp:': true,\n      'gopher:': true,\n      'file:': true\n    },\n    querystring = __webpack_require__(68);\n\nfunction urlParse(url, parseQueryString, slashesDenoteHost) {\n  if (url && typeof(url) === 'object' && url.href) return url;\n\n  if (typeof url !== 'string') {\n    throw new TypeError(\"Parameter 'url' must be a string, not \" + typeof url);\n  }\n\n  var out = {},\n      rest = url;\n\n  // trim before proceeding.\n  // This is to support parse stuff like \"  http://foo.com  \\n\"\n  rest = rest.trim();\n\n  var proto = protocolPattern.exec(rest);\n  if (proto) {\n    proto = proto[0];\n    var lowerProto = proto.toLowerCase();\n    out.protocol = lowerProto;\n    rest = rest.substr(proto.length);\n  }\n\n  // figure out if it's got a host\n  // user@server is *always* interpreted as a hostname, and url\n  // resolution will treat //foo/bar as host=foo,path=bar because that's\n  // how the browser resolves relative URLs.\n  if (slashesDenoteHost || proto || rest.match(/^\\/\\/[^@\\/]+@[^@\\/]+/)) {\n    var slashes = rest.substr(0, 2) === '//';\n    if (slashes && !(proto && hostlessProtocol[proto])) {\n      rest = rest.substr(2);\n      out.slashes = true;\n    }\n  }\n\n  if (!hostlessProtocol[proto] &&\n      (slashes || (proto && !slashedProtocol[proto]))) {\n    // there's a hostname.\n    // the first instance of /, ?, ;, or # ends the host.\n    // don't enforce full RFC correctness, just be unstupid about it.\n\n    // If there is an @ in the hostname, then non-host chars *are* allowed\n    // to the left of the first @ sign, unless some non-auth character\n    // comes *before* the @-sign.\n    // URLs are obnoxious.\n    var atSign = rest.indexOf('@');\n    if (atSign !== -1) {\n      var auth = rest.slice(0, atSign);\n\n      // there *may be* an auth\n      var hasAuth = true;\n      for (var i = 0, l = nonAuthChars.length; i < l; i++) {\n        if (auth.indexOf(nonAuthChars[i]) !== -1) {\n          // not a valid auth.  Something like http://foo.com/bar@baz/\n          hasAuth = false;\n          break;\n        }\n      }\n\n      if (hasAuth) {\n        // pluck off the auth portion.\n        out.auth = decodeURIComponent(auth);\n        rest = rest.substr(atSign + 1);\n      }\n    }\n\n    var firstNonHost = -1;\n    for (var i = 0, l = nonHostChars.length; i < l; i++) {\n      var index = rest.indexOf(nonHostChars[i]);\n      if (index !== -1 &&\n          (firstNonHost < 0 || index < firstNonHost)) firstNonHost = index;\n    }\n\n    if (firstNonHost !== -1) {\n      out.host = rest.substr(0, firstNonHost);\n      rest = rest.substr(firstNonHost);\n    } else {\n      out.host = rest;\n      rest = '';\n    }\n\n    // pull out port.\n    var p = parseHost(out.host);\n    var keys = Object.keys(p);\n    for (var i = 0, l = keys.length; i < l; i++) {\n      var key = keys[i];\n      out[key] = p[key];\n    }\n\n    // we've indicated that there is a hostname,\n    // so even if it's empty, it has to be present.\n    out.hostname = out.hostname || '';\n\n    // if hostname begins with [ and ends with ]\n    // assume that it's an IPv6 address.\n    var ipv6Hostname = out.hostname[0] === '[' &&\n        out.hostname[out.hostname.length - 1] === ']';\n\n    // validate a little.\n    if (out.hostname.length > hostnameMaxLen) {\n      out.hostname = '';\n    } else if (!ipv6Hostname) {\n      var hostparts = out.hostname.split(/\\./);\n      for (var i = 0, l = hostparts.length; i < l; i++) {\n        var part = hostparts[i];\n        if (!part) continue;\n        if (!part.match(hostnamePartPattern)) {\n          var newpart = '';\n          for (var j = 0, k = part.length; j < k; j++) {\n            if (part.charCodeAt(j) > 127) {\n              // we replace non-ASCII char with a temporary placeholder\n              // we need this to make sure size of hostname is not\n              // broken by replacing non-ASCII by nothing\n              newpart += 'x';\n            } else {\n              newpart += part[j];\n            }\n          }\n          // we test again with ASCII char only\n          if (!newpart.match(hostnamePartPattern)) {\n            var validParts = hostparts.slice(0, i);\n            var notHost = hostparts.slice(i + 1);\n            var bit = part.match(hostnamePartStart);\n            if (bit) {\n              validParts.push(bit[1]);\n              notHost.unshift(bit[2]);\n            }\n            if (notHost.length) {\n              rest = '/' + notHost.join('.') + rest;\n            }\n            out.hostname = validParts.join('.');\n            break;\n          }\n        }\n      }\n    }\n\n    // hostnames are always lower case.\n    out.hostname = out.hostname.toLowerCase();\n\n    if (!ipv6Hostname) {\n      // IDNA Support: Returns a puny coded representation of \"domain\".\n      // It only converts the part of the domain name that\n      // has non ASCII characters. I.e. it dosent matter if\n      // you call it with a domain that already is in ASCII.\n      var domainArray = out.hostname.split('.');\n      var newOut = [];\n      for (var i = 0; i < domainArray.length; ++i) {\n        var s = domainArray[i];\n        newOut.push(s.match(/[^A-Za-z0-9_-]/) ?\n            'xn--' + punycode.encode(s) : s);\n      }\n      out.hostname = newOut.join('.');\n    }\n\n    out.host = (out.hostname || '') +\n        ((out.port) ? ':' + out.port : '');\n    out.href += out.host;\n\n    // strip [ and ] from the hostname\n    if (ipv6Hostname) {\n      out.hostname = out.hostname.substr(1, out.hostname.length - 2);\n      if (rest[0] !== '/') {\n        rest = '/' + rest;\n      }\n    }\n  }\n\n  // now rest is set to the post-host stuff.\n  // chop off any delim chars.\n  if (!unsafeProtocol[lowerProto]) {\n\n    // First, make 100% sure that any \"autoEscape\" chars get\n    // escaped, even if encodeURIComponent doesn't think they\n    // need to be.\n    for (var i = 0, l = autoEscape.length; i < l; i++) {\n      var ae = autoEscape[i];\n      var esc = encodeURIComponent(ae);\n      if (esc === ae) {\n        esc = escape(ae);\n      }\n      rest = rest.split(ae).join(esc);\n    }\n  }\n\n\n  // chop off from the tail first.\n  var hash = rest.indexOf('#');\n  if (hash !== -1) {\n    // got a fragment string.\n    out.hash = rest.substr(hash);\n    rest = rest.slice(0, hash);\n  }\n  var qm = rest.indexOf('?');\n  if (qm !== -1) {\n    out.search = rest.substr(qm);\n    out.query = rest.substr(qm + 1);\n    if (parseQueryString) {\n      out.query = querystring.parse(out.query);\n    }\n    rest = rest.slice(0, qm);\n  } else if (parseQueryString) {\n    // no query string, but parseQueryString still requested\n    out.search = '';\n    out.query = {};\n  }\n  if (rest) out.pathname = rest;\n  if (slashedProtocol[proto] &&\n      out.hostname && !out.pathname) {\n    out.pathname = '/';\n  }\n\n  //to support http.request\n  if (out.pathname || out.search) {\n    out.path = (out.pathname ? out.pathname : '') +\n               (out.search ? out.search : '');\n  }\n\n  // finally, reconstruct the href based on what has been validated.\n  out.href = urlFormat(out);\n  return out;\n}\n\n// format a parsed object into a url string\nfunction urlFormat(obj) {\n  // ensure it's an object, and not a string url.\n  // If it's an obj, this is a no-op.\n  // this way, you can call url_format() on strings\n  // to clean up potentially wonky urls.\n  if (typeof(obj) === 'string') obj = urlParse(obj);\n\n  var auth = obj.auth || '';\n  if (auth) {\n    auth = encodeURIComponent(auth);\n    auth = auth.replace(/%3A/i, ':');\n    auth += '@';\n  }\n\n  var protocol = obj.protocol || '',\n      pathname = obj.pathname || '',\n      hash = obj.hash || '',\n      host = false,\n      query = '';\n\n  if (obj.host !== undefined) {\n    host = auth + obj.host;\n  } else if (obj.hostname !== undefined) {\n    host = auth + (obj.hostname.indexOf(':') === -1 ?\n        obj.hostname :\n        '[' + obj.hostname + ']');\n    if (obj.port) {\n      host += ':' + obj.port;\n    }\n  }\n\n  if (obj.query && typeof obj.query === 'object' &&\n      Object.keys(obj.query).length) {\n    query = querystring.stringify(obj.query);\n  }\n\n  var search = obj.search || (query && ('?' + query)) || '';\n\n  if (protocol && protocol.substr(-1) !== ':') protocol += ':';\n\n  // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.\n  // unless they had them to begin with.\n  if (obj.slashes ||\n      (!protocol || slashedProtocol[protocol]) && host !== false) {\n    host = '//' + (host || '');\n    if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;\n  } else if (!host) {\n    host = '';\n  }\n\n  if (hash && hash.charAt(0) !== '#') hash = '#' + hash;\n  if (search && search.charAt(0) !== '?') search = '?' + search;\n\n  return protocol + host + pathname + search + hash;\n}\n\nfunction urlResolve(source, relative) {\n  return urlFormat(urlResolveObject(source, relative));\n}\n\nfunction urlResolveObject(source, relative) {\n  if (!source) return relative;\n\n  source = urlParse(urlFormat(source), false, true);\n  relative = urlParse(urlFormat(relative), false, true);\n\n  // hash is always overridden, no matter what.\n  source.hash = relative.hash;\n\n  if (relative.href === '') {\n    source.href = urlFormat(source);\n    return source;\n  }\n\n  // hrefs like //foo/bar always cut to the protocol.\n  if (relative.slashes && !relative.protocol) {\n    relative.protocol = source.protocol;\n    //urlParse appends trailing / to urls like http://www.example.com\n    if (slashedProtocol[relative.protocol] &&\n        relative.hostname && !relative.pathname) {\n      relative.path = relative.pathname = '/';\n    }\n    relative.href = urlFormat(relative);\n    return relative;\n  }\n\n  if (relative.protocol && relative.protocol !== source.protocol) {\n    // if it's a known url protocol, then changing\n    // the protocol does weird things\n    // first, if it's not file:, then we MUST have a host,\n    // and if there was a path\n    // to begin with, then we MUST have a path.\n    // if it is file:, then the host is dropped,\n    // because that's known to be hostless.\n    // anything else is assumed to be absolute.\n    if (!slashedProtocol[relative.protocol]) {\n      relative.href = urlFormat(relative);\n      return relative;\n    }\n    source.protocol = relative.protocol;\n    if (!relative.host && !hostlessProtocol[relative.protocol]) {\n      var relPath = (relative.pathname || '').split('/');\n      while (relPath.length && !(relative.host = relPath.shift()));\n      if (!relative.host) relative.host = '';\n      if (!relative.hostname) relative.hostname = '';\n      if (relPath[0] !== '') relPath.unshift('');\n      if (relPath.length < 2) relPath.unshift('');\n      relative.pathname = relPath.join('/');\n    }\n    source.pathname = relative.pathname;\n    source.search = relative.search;\n    source.query = relative.query;\n    source.host = relative.host || '';\n    source.auth = relative.auth;\n    source.hostname = relative.hostname || relative.host;\n    source.port = relative.port;\n    //to support http.request\n    if (source.pathname !== undefined || source.search !== undefined) {\n      source.path = (source.pathname ? source.pathname : '') +\n                    (source.search ? source.search : '');\n    }\n    source.slashes = source.slashes || relative.slashes;\n    source.href = urlFormat(source);\n    return source;\n  }\n\n  var isSourceAbs = (source.pathname && source.pathname.charAt(0) === '/'),\n      isRelAbs = (\n          relative.host !== undefined ||\n          relative.pathname && relative.pathname.charAt(0) === '/'\n      ),\n      mustEndAbs = (isRelAbs || isSourceAbs ||\n                    (source.host && relative.pathname)),\n      removeAllDots = mustEndAbs,\n      srcPath = source.pathname && source.pathname.split('/') || [],\n      relPath = relative.pathname && relative.pathname.split('/') || [],\n      psychotic = source.protocol &&\n          !slashedProtocol[source.protocol];\n\n  // if the url is a non-slashed url, then relative\n  // links like ../.. should be able\n  // to crawl up to the hostname, as well.  This is strange.\n  // source.protocol has already been set by now.\n  // Later on, put the first path part into the host field.\n  if (psychotic) {\n\n    delete source.hostname;\n    delete source.port;\n    if (source.host) {\n      if (srcPath[0] === '') srcPath[0] = source.host;\n      else srcPath.unshift(source.host);\n    }\n    delete source.host;\n    if (relative.protocol) {\n      delete relative.hostname;\n      delete relative.port;\n      if (relative.host) {\n        if (relPath[0] === '') relPath[0] = relative.host;\n        else relPath.unshift(relative.host);\n      }\n      delete relative.host;\n    }\n    mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');\n  }\n\n  if (isRelAbs) {\n    // it's absolute.\n    source.host = (relative.host || relative.host === '') ?\n                      relative.host : source.host;\n    source.hostname = (relative.hostname || relative.hostname === '') ?\n                      relative.hostname : source.hostname;\n    source.search = relative.search;\n    source.query = relative.query;\n    srcPath = relPath;\n    // fall through to the dot-handling below.\n  } else if (relPath.length) {\n    // it's relative\n    // throw away the existing file, and take the new path instead.\n    if (!srcPath) srcPath = [];\n    srcPath.pop();\n    srcPath = srcPath.concat(relPath);\n    source.search = relative.search;\n    source.query = relative.query;\n  } else if ('search' in relative) {\n    // just pull out the search.\n    // like href='?foo'.\n    // Put this after the other two cases because it simplifies the booleans\n    if (psychotic) {\n      source.hostname = source.host = srcPath.shift();\n      //occationaly the auth can get stuck only in host\n      //this especialy happens in cases like\n      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')\n      var authInHost = source.host && source.host.indexOf('@') > 0 ?\n                       source.host.split('@') : false;\n      if (authInHost) {\n        source.auth = authInHost.shift();\n        source.host = source.hostname = authInHost.shift();\n      }\n    }\n    source.search = relative.search;\n    source.query = relative.query;\n    //to support http.request\n    if (source.pathname !== undefined || source.search !== undefined) {\n      source.path = (source.pathname ? source.pathname : '') +\n                    (source.search ? source.search : '');\n    }\n    source.href = urlFormat(source);\n    return source;\n  }\n  if (!srcPath.length) {\n    // no path at all.  easy.\n    // we've already handled the other stuff above.\n    delete source.pathname;\n    //to support http.request\n    if (!source.search) {\n      source.path = '/' + source.search;\n    } else {\n      delete source.path;\n    }\n    source.href = urlFormat(source);\n    return source;\n  }\n  // if a url ENDs in . or .., then it must get a trailing slash.\n  // however, if it ends in anything else non-slashy,\n  // then it must NOT get a trailing slash.\n  var last = srcPath.slice(-1)[0];\n  var hasTrailingSlash = (\n      (source.host || relative.host) && (last === '.' || last === '..') ||\n      last === '');\n\n  // strip single dots, resolve double dots to parent dir\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = srcPath.length; i >= 0; i--) {\n    last = srcPath[i];\n    if (last == '.') {\n      srcPath.splice(i, 1);\n    } else if (last === '..') {\n      srcPath.splice(i, 1);\n      up++;\n    } else if (up) {\n      srcPath.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (!mustEndAbs && !removeAllDots) {\n    for (; up--; up) {\n      srcPath.unshift('..');\n    }\n  }\n\n  if (mustEndAbs && srcPath[0] !== '' &&\n      (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {\n    srcPath.unshift('');\n  }\n\n  if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {\n    srcPath.push('');\n  }\n\n  var isAbsolute = srcPath[0] === '' ||\n      (srcPath[0] && srcPath[0].charAt(0) === '/');\n\n  // put the host back\n  if (psychotic) {\n    source.hostname = source.host = isAbsolute ? '' :\n                                    srcPath.length ? srcPath.shift() : '';\n    //occationaly the auth can get stuck only in host\n    //this especialy happens in cases like\n    //url.resolveObject('mailto:local1@domain1', 'local2@domain2')\n    var authInHost = source.host && source.host.indexOf('@') > 0 ?\n                     source.host.split('@') : false;\n    if (authInHost) {\n      source.auth = authInHost.shift();\n      source.host = source.hostname = authInHost.shift();\n    }\n  }\n\n  mustEndAbs = mustEndAbs || (source.host && srcPath.length);\n\n  if (mustEndAbs && !isAbsolute) {\n    srcPath.unshift('');\n  }\n\n  source.pathname = srcPath.join('/');\n  //to support request.http\n  if (source.pathname !== undefined || source.search !== undefined) {\n    source.path = (source.pathname ? source.pathname : '') +\n                  (source.search ? source.search : '');\n  }\n  source.auth = relative.auth || source.auth;\n  source.slashes = source.slashes || relative.slashes;\n  source.href = urlFormat(source);\n  return source;\n}\n\nfunction parseHost(host) {\n  var out = {};\n  var port = portPattern.exec(host);\n  if (port) {\n    port = port[0];\n    if (port !== ':') {\n      out.port = port.substr(1);\n    }\n    host = host.substr(0, host.length - port.length);\n  }\n  if (host) out.hostname = host;\n  return out;\n}\n\n}());\n\n\n// WEBPACK FOOTER\n// module.id = 43\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/url/url.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/url/url.js");

/***/ },
/* 44 */
/***/ function(module, exports, __webpack_require__) {

	eval("var hasOwn = Object.prototype.hasOwnProperty;\nvar toString = Object.prototype.toString;\n\nfunction isPlainObject(obj) {\n\tif (!obj || toString.call(obj) !== '[object Object]' || obj.nodeType || obj.setInterval)\n\t\treturn false;\n\n\tvar has_own_constructor = hasOwn.call(obj, 'constructor');\n\tvar has_is_property_of_method = hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');\n\t// Not own constructor property must be Object\n\tif (obj.constructor && !has_own_constructor && !has_is_property_of_method)\n\t\treturn false;\n\n\t// Own properties are enumerated firstly, so to speed up,\n\t// if last one is own, then all properties are own.\n\tvar key;\n\tfor ( key in obj ) {}\n\n\treturn key === undefined || hasOwn.call( obj, key );\n};\n\nmodule.exports = function extend() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t    target = arguments[0] || {},\n\t    i = 1,\n\t    length = arguments.length,\n\t    deep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && typeof target !== \"function\") {\n\t\ttarget = {};\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( isPlainObject(copy) || (copyIsArray = Array.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && Array.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\n\n// WEBPACK FOOTER\n// module.id = 44\n// module.readableIdentifier = ./~/extend/index.js\n//@ sourceURL=webpack-module:///./~/extend/index.js");

/***/ },
/* 45 */
/***/ function(module, exports, __webpack_require__) {

	eval("\n/**\n * Manager for pending transactions\n */\n\nvar LRU = __webpack_require__(48);\nvar Transaction = __webpack_require__(5).Transaction;\n\nfunction TransactionQueue() {\n  this._queue = [ ];\n  this._idCache = LRU();\n  this._sequenceCache = LRU();\n};\n\n/**\n * Store received (validated) sequence\n */\n\nTransactionQueue.prototype.addReceivedSequence = function(sequence) {\n  this._sequenceCache.set(String(sequence), true);\n};\n\n/**\n * Check that sequence number has been consumed by a validated\n * transaction\n */\n\nTransactionQueue.prototype.hasSequence = function(sequence) {\n  return this._sequenceCache.has(String(sequence));\n};\n\n/**\n * Store received (validated) ID transaction\n */\n\nTransactionQueue.prototype.addReceivedId = function(id, transaction) {\n  this._idCache.set(id, transaction);\n};\n\n/**\n * Get received (validated) transaction by ID\n */\n\nTransactionQueue.prototype.getReceived = function(id) {\n  return this._idCache.get(id);\n};\n\n/**\n * Get a submitted transaction by ID. Transactions\n * may have multiple associated IDs.\n */\n\nTransactionQueue.prototype.getSubmission = function(id) {\n  var result = void(0);\n\n  for (var i=0, tx; (tx=this._queue[i]); i++) {\n    if (~tx.submittedIDs.indexOf(id)) {\n      result = tx;\n      break;\n    }\n  }\n\n  return result;\n};\n\n/**\n * Remove a transaction from the queue\n */\n\nTransactionQueue.prototype.remove = function(tx) {\n  // ND: We are just removing the Transaction by identity\n  var i = this._queue.length;\n\n  if (typeof tx === 'string') {\n    tx = this.getSubmission(tx);\n  }\n\n  if (!(tx instanceof Transaction)) {\n    return;\n  }\n\n  while (i--) {\n    if (this._queue[i] === tx) {\n      this._queue.splice(i, 1);\n      break;\n    }\n  }\n};\n\nTransactionQueue.prototype.push = function(tx) {\n  this._queue.push(tx);\n};\n\nTransactionQueue.prototype.forEach = function(fn) {\n  this._queue.forEach(fn);\n};\n\nTransactionQueue.prototype.length =\nTransactionQueue.prototype.getLength = function() {\n  return this._queue.length;\n};\n\nexports.TransactionQueue = TransactionQueue;\n\n\n// WEBPACK FOOTER\n// module.id = 45\n// module.readableIdentifier = ./src/js/ripple/transactionqueue.js\n//@ sourceURL=webpack-module:///./src/js/ripple/transactionqueue.js");

/***/ },
/* 46 */
/***/ function(module, exports, __webpack_require__) {

	eval("var utils  = __webpack_require__(19);\nvar extend = __webpack_require__(44);\nvar UInt   = __webpack_require__(29).UInt;\n\n//\n// UInt128 support\n//\n\nvar UInt128 = extend(function () {\n  // Internal form: NaN or BigInteger\n  this._value  = NaN;\n}, UInt);\n\nUInt128.width = 16;\nUInt128.prototype = extend({}, UInt.prototype);\nUInt128.prototype.constructor = UInt128;\n\nvar HEX_ZERO = UInt128.HEX_ZERO = '00000000000000000000000000000000';\nvar HEX_ONE  = UInt128.HEX_ONE  = '00000000000000000000000000000000';\nvar STR_ZERO = UInt128.STR_ZERO = utils.hexToString(HEX_ZERO);\nvar STR_ONE  = UInt128.STR_ONE  = utils.hexToString(HEX_ONE);\n\nexports.UInt128 = UInt128;\n\n\n// WEBPACK FOOTER\n// module.id = 46\n// module.readableIdentifier = ./src/js/ripple/uint128.js\n//@ sourceURL=webpack-module:///./src/js/ripple/uint128.js");

/***/ },
/* 47 */
/***/ function(module, exports, __webpack_require__) {

	eval("var Crypt = __webpack_require__(32).Crypt;\nvar Message = __webpack_require__(14).Message;\nvar parser  = __webpack_require__(43);\nvar querystring = __webpack_require__(52);\nvar extend = __webpack_require__(44);\n\nvar SignedRequest = function (config) {\n  // XXX Constructor should be generalized and constructing from an Angular.js\n  //     $http config should be a SignedRequest.from... utility method.\n  this.config = extend(true, {}, config);\n  if (!this.config.data) this.config.data = {};\n};\n\n\n\n/**\n * Create a string from request parameters that\n * will be used to sign a request\n * @param {Object} parsed - parsed url\n * @param {Object} date \n * @param {Object} mechanism - type of signing\n */\nSignedRequest.prototype.getStringToSign = function (parsed, date, mechanism) {\n  // XXX This method doesn't handle signing GET requests correctly. The data\n  //     field will be merged into the search string, not the request body.\n\n  // Sort the properties of the JSON object into canonical form\n  var canonicalData = JSON.stringify(copyObjectWithSortedKeys(this.config.data));\n\n  // Canonical request using Amazon's v4 signature format\n  // See: http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html\n  var canonicalRequest = [\n    this.config.method || 'GET',\n    parsed.pathname || '',\n    parsed.search || '',\n    // XXX Headers signing not supported\n    '',\n    '',\n    Crypt.hashSha512(canonicalData).toLowerCase()\n  ].join('\\n');\n\n  // String to sign inspired by Amazon's v4 signature format\n  // See: http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html\n  //\n  // We don't have a credential scope, so we skip it.\n  //\n  // But that modifies the format, so the format ID is RIPPLE1, instead of AWS4.\n  return [\n    mechanism,\n    date,\n    Crypt.hashSha512(canonicalRequest).toLowerCase()\n  ].join('\\n');\n};\n\n//prepare for signing\nfunction copyObjectWithSortedKeys(object) {\n  if (isPlainObject(object)) {\n    var newObj = {};\n    var keysSorted = Object.keys(object).sort();\n    var key;\n    for (var i in keysSorted) {\n      key = keysSorted[i];\n      if (Object.prototype.hasOwnProperty.call(object, key)) {\n        newObj[key] = copyObjectWithSortedKeys(object[key]);\n      }\n    }\n    return newObj;\n  } else if (Array.isArray(object)) {\n    return object.map(copyObjectWithSortedKeys);\n  } else {\n    return object;\n  }\n}\n\n//from npm extend\nfunction isPlainObject(obj) {\n  var hasOwn = Object.prototype.hasOwnProperty;\n  var toString = Object.prototype.toString;\n\n  if (!obj || toString.call(obj) !== '[object Object]' || obj.nodeType || obj.setInterval)\n    return false;\n\n  var has_own_constructor = hasOwn.call(obj, 'constructor');\n  var has_is_property_of_method = hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');\n  // Not own constructor property must be Object\n  if (obj.constructor && !has_own_constructor && !has_is_property_of_method)\n    return false;\n\n  // Own properties are enumerated firstly, so to speed up,\n  // if last one is own, then all properties are own.\n  var key;\n  for ( key in obj ) {}\n\n  return key === undefined || hasOwn.call( obj, key );\n};\n\n/**\n * HMAC signed request\n * @param {Object} config\n * @param {Object} auth_secret\n * @param {Object} blob_id\n */\nSignedRequest.prototype.signHmac = function (auth_secret, blob_id) {\n  var config = extend(true, {}, this.config);\n\n  // Parse URL\n  var parsed        = parser.parse(config.url);\n  var date          = dateAsIso8601();\n  var signatureType = 'RIPPLE1-HMAC-SHA512';\n  var stringToSign  = this.getStringToSign(parsed, date, signatureType);\n  var signature     = Crypt.signString(auth_secret, stringToSign);\n\n  var query = querystring.stringify({\n    signature: Crypt.base64ToBase64Url(signature),\n    signature_date: date,\n    signature_blob_id: blob_id,\n    signature_type: signatureType\n  });\n\n  config.url += (parsed.search ? '&' : '?') + query;\n  return config;\n};\n\n/**\n * Asymmetric signed request\n * @param {Object} config\n * @param {Object} secretKey\n * @param {Object} account\n * @param {Object} blob_id\n */\nSignedRequest.prototype.signAsymmetric = function (secretKey, account, blob_id) {\n  var config = extend(true, {}, this.config);\n\n  // Parse URL\n  var parsed        = parser.parse(config.url);\n  var date          = dateAsIso8601();\n  var signatureType = 'RIPPLE1-ECDSA-SHA512';\n  var stringToSign  = this.getStringToSign(parsed, date, signatureType);\n  var signature     = Message.signMessage(stringToSign, secretKey);\n \n  var query = querystring.stringify({\n    signature: Crypt.base64ToBase64Url(signature),\n    signature_date: date,\n    signature_blob_id: blob_id,\n    signature_account: account,\n    signature_type: signatureType\n  });\n\n  config.url += (parsed.search ? '&' : '?') + query;\n\n  return config;\n};\n\n/**\n * Asymmetric signed request for vault recovery\n * @param {Object} config\n * @param {Object} secretKey\n * @param {Object} username\n */\nSignedRequest.prototype.signAsymmetricRecovery = function (secretKey, username) {\n  var config = extend(true, {}, this.config);\n\n  // Parse URL\n  var parsed        = parser.parse(config.url);\n  var date          = dateAsIso8601();\n  var signatureType = 'RIPPLE1-ECDSA-SHA512';\n  var stringToSign  = this.getStringToSign(parsed, date, signatureType);\n  var signature     = Message.signMessage(stringToSign, secretKey);\n \n  var query = querystring.stringify({\n    signature: Crypt.base64ToBase64Url(signature),\n    signature_date: date,\n    signature_username: username,\n    signature_type: signatureType\n  });\n\n  config.url += (parsed.search ? '&' : '?') + query;\n\n  return config;\n};\n\nvar dateAsIso8601 = (function () {\n  function pad(n) {\n    return (n < 0 || n > 9 ? \"\" : \"0\") + n;\n  }\n\n  return function dateAsIso8601() {\n    var date = new Date();\n    return date.getUTCFullYear() + \"-\" +\n      pad(date.getUTCMonth()     + 1)  + \"-\" +\n      pad(date.getUTCDate())     + \"T\" +\n      pad(date.getUTCHours())    + \":\" +\n      pad(date.getUTCMinutes())  + \":\" +\n      pad(date.getUTCSeconds())  + \".000Z\";\n  };\n})();\n\n// XXX Add methods for verifying requests\n// SignedRequest.prototype.verifySignatureHmac\n// SignedRequest.prototype.verifySignatureAsymetric\n\nexports.SignedRequest = SignedRequest;\n\n\n\n// WEBPACK FOOTER\n// module.id = 47\n// module.readableIdentifier = ./src/js/ripple/signedrequest.js\n//@ sourceURL=webpack-module:///./src/js/ripple/signedrequest.js");

/***/ },
/* 48 */
/***/ function(module, exports, __webpack_require__) {

	eval(";(function () { // closure for web browsers\n\nif (typeof module === 'object' && module.exports) {\n  module.exports = LRUCache\n} else {\n  // just set the global for non-node platforms.\n  this.LRUCache = LRUCache\n}\n\nfunction hOP (obj, key) {\n  return Object.prototype.hasOwnProperty.call(obj, key)\n}\n\nfunction naiveLength () { return 1 }\n\nfunction LRUCache (options) {\n  if (!(this instanceof LRUCache))\n    return new LRUCache(options)\n\n  if (typeof options === 'number')\n    options = { max: options }\n\n  if (!options)\n    options = {}\n\n  this._max = options.max\n  // Kind of weird to have a default max of Infinity, but oh well.\n  if (!this._max || !(typeof this._max === \"number\") || this._max <= 0 )\n    this._max = Infinity\n\n  this._lengthCalculator = options.length || naiveLength\n  if (typeof this._lengthCalculator !== \"function\")\n    this._lengthCalculator = naiveLength\n\n  this._allowStale = options.stale || false\n  this._maxAge = options.maxAge || null\n  this._dispose = options.dispose\n  this.reset()\n}\n\n// resize the cache when the max changes.\nObject.defineProperty(LRUCache.prototype, \"max\",\n  { set : function (mL) {\n      if (!mL || !(typeof mL === \"number\") || mL <= 0 ) mL = Infinity\n      this._max = mL\n      if (this._length > this._max) trim(this)\n    }\n  , get : function () { return this._max }\n  , enumerable : true\n  })\n\n// resize the cache when the lengthCalculator changes.\nObject.defineProperty(LRUCache.prototype, \"lengthCalculator\",\n  { set : function (lC) {\n      if (typeof lC !== \"function\") {\n        this._lengthCalculator = naiveLength\n        this._length = this._itemCount\n        for (var key in this._cache) {\n          this._cache[key].length = 1\n        }\n      } else {\n        this._lengthCalculator = lC\n        this._length = 0\n        for (var key in this._cache) {\n          this._cache[key].length = this._lengthCalculator(this._cache[key].value)\n          this._length += this._cache[key].length\n        }\n      }\n\n      if (this._length > this._max) trim(this)\n    }\n  , get : function () { return this._lengthCalculator }\n  , enumerable : true\n  })\n\nObject.defineProperty(LRUCache.prototype, \"length\",\n  { get : function () { return this._length }\n  , enumerable : true\n  })\n\n\nObject.defineProperty(LRUCache.prototype, \"itemCount\",\n  { get : function () { return this._itemCount }\n  , enumerable : true\n  })\n\nLRUCache.prototype.forEach = function (fn, thisp) {\n  thisp = thisp || this\n  var i = 0;\n  for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {\n    i++\n    var hit = this._lruList[k]\n    if (this._maxAge && (Date.now() - hit.now > this._maxAge)) {\n      del(this, hit)\n      if (!this._allowStale) hit = undefined\n    }\n    if (hit) {\n      fn.call(thisp, hit.value, hit.key, this)\n    }\n  }\n}\n\nLRUCache.prototype.keys = function () {\n  var keys = new Array(this._itemCount)\n  var i = 0\n  for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {\n    var hit = this._lruList[k]\n    keys[i++] = hit.key\n  }\n  return keys\n}\n\nLRUCache.prototype.values = function () {\n  var values = new Array(this._itemCount)\n  var i = 0\n  for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {\n    var hit = this._lruList[k]\n    values[i++] = hit.value\n  }\n  return values\n}\n\nLRUCache.prototype.reset = function () {\n  if (this._dispose && this._cache) {\n    for (var k in this._cache) {\n      this._dispose(k, this._cache[k].value)\n    }\n  }\n\n  this._cache = Object.create(null) // hash of items by key\n  this._lruList = Object.create(null) // list of items in order of use recency\n  this._mru = 0 // most recently used\n  this._lru = 0 // least recently used\n  this._length = 0 // number of items in the list\n  this._itemCount = 0\n}\n\n// Provided for debugging/dev purposes only. No promises whatsoever that\n// this API stays stable.\nLRUCache.prototype.dump = function () {\n  return this._cache\n}\n\nLRUCache.prototype.dumpLru = function () {\n  return this._lruList\n}\n\nLRUCache.prototype.set = function (key, value) {\n  if (hOP(this._cache, key)) {\n    // dispose of the old one before overwriting\n    if (this._dispose) this._dispose(key, this._cache[key].value)\n    if (this._maxAge) this._cache[key].now = Date.now()\n    this._cache[key].value = value\n    this.get(key)\n    return true\n  }\n\n  var len = this._lengthCalculator(value)\n  var age = this._maxAge ? Date.now() : 0\n  var hit = new Entry(key, value, this._mru++, len, age)\n\n  // oversized objects fall out of cache automatically.\n  if (hit.length > this._max) {\n    if (this._dispose) this._dispose(key, value)\n    return false\n  }\n\n  this._length += hit.length\n  this._lruList[hit.lu] = this._cache[key] = hit\n  this._itemCount ++\n\n  if (this._length > this._max) trim(this)\n  return true\n}\n\nLRUCache.prototype.has = function (key) {\n  if (!hOP(this._cache, key)) return false\n  var hit = this._cache[key]\n  if (this._maxAge && (Date.now() - hit.now > this._maxAge)) {\n    return false\n  }\n  return true\n}\n\nLRUCache.prototype.get = function (key) {\n  return get(this, key, true)\n}\n\nLRUCache.prototype.peek = function (key) {\n  return get(this, key, false)\n}\n\nLRUCache.prototype.pop = function () {\n  var hit = this._lruList[this._lru]\n  del(this, hit)\n  return hit || null\n}\n\nLRUCache.prototype.del = function (key) {\n  del(this, this._cache[key])\n}\n\nfunction get (self, key, doUse) {\n  var hit = self._cache[key]\n  if (hit) {\n    if (self._maxAge && (Date.now() - hit.now > self._maxAge)) {\n      del(self, hit)\n      if (!self._allowStale) hit = undefined\n    } else {\n      if (doUse) use(self, hit)\n    }\n    if (hit) hit = hit.value\n  }\n  return hit\n}\n\nfunction use (self, hit) {\n  shiftLU(self, hit)\n  hit.lu = self._mru ++\n  self._lruList[hit.lu] = hit\n}\n\nfunction trim (self) {\n  while (self._lru < self._mru && self._length > self._max)\n    del(self, self._lruList[self._lru])\n}\n\nfunction shiftLU (self, hit) {\n  delete self._lruList[ hit.lu ]\n  while (self._lru < self._mru && !self._lruList[self._lru]) self._lru ++\n}\n\nfunction del (self, hit) {\n  if (hit) {\n    if (self._dispose) self._dispose(hit.key, hit.value)\n    self._length -= hit.length\n    self._itemCount --\n    delete self._cache[ hit.key ]\n    shiftLU(self, hit)\n  }\n}\n\n// classy, since V8 prefers predictable objects.\nfunction Entry (key, value, lu, length, now) {\n  this.key = key\n  this.value = value\n  this.lu = lu\n  this.length = length\n  this.now = now\n}\n\n})()\n\n\n// WEBPACK FOOTER\n// module.id = 48\n// module.readableIdentifier = ./~/lru-cache/lib/lru-cache.js\n//@ sourceURL=webpack-module:///./~/lru-cache/lib/lru-cache.js");

/***/ },
/* 49 */
/***/ function(module, exports, __webpack_require__) {

	eval("module.exports = function(options) {\n  var sjcl = options.sjcl; // inject sjcl dependency\n\n  var base58 = __webpack_require__(58)({ sjcl: options.sjcl });;\n  var MasterKey = __webpack_require__(59)({ sjcl: options.sjcl });\n  var RippleAddress = __webpack_require__(60)({ sjcl: options.sjcl });\n  var PublicGenerator = __webpack_require__(61)({ sjcl: options.sjcl });\n\n  function firstHalfOfSHA512(bytes) {\n    return sjcl.bitArray.bitSlice(\n      sjcl.hash.sha512.hash(sjcl.codec.bytes.toBits(bytes)),\n      0, 256\n    );\n  }\n\n  function append_int(a, i) {\n    return [].concat(a, i >> 24, (i >> 16) & 0xff, (i >> 8) & 0xff, i & 0xff)\n  }\n\n  function RippleWallet(secret){\n    this.secret = secret;\n\n    if (!this.secret) {\n      throw \"Invalid secret.\"\n    }\n  }\n\n  RippleWallet.prototype = {\n\n    getPrivateKey: function(secret){\n      var self = this;\n      return base58.decode_base_check(33, self.secret);\n    },\n\n    getPrivateGenerator: function(privateKey){\n      var i = 0;\n      do {\n        // Compute the hash of the 128-bit privateKey and the sequenceuence number\n        privateGenerator = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(privateKey, i)));\n        i++;\n        // If the hash is equal to or greater than the SECp256k1 order, increment sequenceuence and try agin\n      } while (!sjcl.ecc.curves.c256.r.greaterEquals(privateGenerator));\n      return privateGenerator; \n    },\n\n    getPublicGenerator: function (){\n      var privateKey = this.getPrivateKey(this.secret);\n      var privateGenerator = this.getPrivateGenerator(privateKey);\n      return PublicGenerator.fromPrivateGenerator(privateGenerator);\n    },\n\n    getPublicKey: function(publicGenerator){\n      var sec;\n      var i = 0;\n      do {\n        // Compute the hash of the public generator with the sub-sequence number\n        sec = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(append_int(publicGenerator.toBytesCompressed(), 0), i)));\n        i++;\n        // If the hash is equal to or greater than the SECp256k1 order, increment the sequenceuence and retry\n      } while (!sjcl.ecc.curves.c256.r.greaterEquals(sec));\n      // Treating this hash as a private key, compute the corresponding public key as an EC point. \n      return sjcl.ecc.curves.c256.G.mult(sec).toJac().add(publicGenerator).toAffine();\n    },\n\n    getAddress: function(){\n      var privateKey = this.getPrivateKey(this.secret);\n      var privateGenerator = this.getPrivateGenerator(privateKey);\n      var publicGenerator = PublicGenerator.fromPrivateGenerator(privateGenerator).value;\n      var publicKey = this.getPublicKey(publicGenerator);\n      return RippleAddress.fromPublicKey(publicKey);\n    }\n  }\n\n  RippleWallet.getRandom = function(){\n    var secretKey = MasterKey.getRandom().value;\n    return new RippleWallet(secretKey);\n  };\n\n  RippleWallet.generate = function() {\n    /* Generate a 128-bit master key that can be used to make \n       any number of private / public key pairs and accounts\n    */\n    var secretKey = MasterKey.getRandom().value;\n    var wallet = new RippleWallet(secretKey);\n    return {\n      address: wallet.getAddress().value,\n      secret: secretKey \n    };\n  };\n\n  return RippleWallet;\n};\n\n\n// WEBPACK FOOTER\n// module.id = 49\n// module.readableIdentifier = ./~/ripple-wallet-generator/lib/wallet.js\n//@ sourceURL=webpack-module:///./~/ripple-wallet-generator/lib/wallet.js");

/***/ },
/* 50 */
/***/ function(module, exports, __webpack_require__) {

	eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(process) {/*!\n * async\n * https://github.com/caolan/async\n *\n * Copyright 2010-2014 Caolan McMahon\n * Released under the MIT license\n */\n/*jshint onevar: false, indent:4 */\n/*global setImmediate: false, setTimeout: false, console: false */\n(function () {\n\n    var async = {};\n\n    // global on the server, window in the browser\n    var root, previous_async;\n\n    root = this;\n    if (root != null) {\n      previous_async = root.async;\n    }\n\n    async.noConflict = function () {\n        root.async = previous_async;\n        return async;\n    };\n\n    function only_once(fn) {\n        var called = false;\n        return function() {\n            if (called) throw new Error(\"Callback was already called.\");\n            called = true;\n            fn.apply(root, arguments);\n        }\n    }\n\n    //// cross-browser compatiblity functions ////\n\n    var _toString = Object.prototype.toString;\n\n    var _isArray = Array.isArray || function (obj) {\n        return _toString.call(obj) === '[object Array]';\n    };\n\n    var _each = function (arr, iterator) {\n        if (arr.forEach) {\n            return arr.forEach(iterator);\n        }\n        for (var i = 0; i < arr.length; i += 1) {\n            iterator(arr[i], i, arr);\n        }\n    };\n\n    var _map = function (arr, iterator) {\n        if (arr.map) {\n            return arr.map(iterator);\n        }\n        var results = [];\n        _each(arr, function (x, i, a) {\n            results.push(iterator(x, i, a));\n        });\n        return results;\n    };\n\n    var _reduce = function (arr, iterator, memo) {\n        if (arr.reduce) {\n            return arr.reduce(iterator, memo);\n        }\n        _each(arr, function (x, i, a) {\n            memo = iterator(memo, x, i, a);\n        });\n        return memo;\n    };\n\n    var _keys = function (obj) {\n        if (Object.keys) {\n            return Object.keys(obj);\n        }\n        var keys = [];\n        for (var k in obj) {\n            if (obj.hasOwnProperty(k)) {\n                keys.push(k);\n            }\n        }\n        return keys;\n    };\n\n    //// exported async module functions ////\n\n    //// nextTick implementation with browser-compatible fallback ////\n    if (typeof process === 'undefined' || !(process.nextTick)) {\n        if (typeof setImmediate === 'function') {\n            async.nextTick = function (fn) {\n                // not a direct alias for IE10 compatibility\n                setImmediate(fn);\n            };\n            async.setImmediate = async.nextTick;\n        }\n        else {\n            async.nextTick = function (fn) {\n                setTimeout(fn, 0);\n            };\n            async.setImmediate = async.nextTick;\n        }\n    }\n    else {\n        async.nextTick = process.nextTick;\n        if (typeof setImmediate !== 'undefined') {\n            async.setImmediate = function (fn) {\n              // not a direct alias for IE10 compatibility\n              setImmediate(fn);\n            };\n        }\n        else {\n            async.setImmediate = async.nextTick;\n        }\n    }\n\n    async.each = function (arr, iterator, callback) {\n        callback = callback || function () {};\n        if (!arr.length) {\n            return callback();\n        }\n        var completed = 0;\n        _each(arr, function (x) {\n            iterator(x, only_once(done) );\n        });\n        function done(err) {\n          if (err) {\n              callback(err);\n              callback = function () {};\n          }\n          else {\n              completed += 1;\n              if (completed >= arr.length) {\n                  callback();\n              }\n          }\n        }\n    };\n    async.forEach = async.each;\n\n    async.eachSeries = function (arr, iterator, callback) {\n        callback = callback || function () {};\n        if (!arr.length) {\n            return callback();\n        }\n        var completed = 0;\n        var iterate = function () {\n            iterator(arr[completed], function (err) {\n                if (err) {\n                    callback(err);\n                    callback = function () {};\n                }\n                else {\n                    completed += 1;\n                    if (completed >= arr.length) {\n                        callback();\n                    }\n                    else {\n                        iterate();\n                    }\n                }\n            });\n        };\n        iterate();\n    };\n    async.forEachSeries = async.eachSeries;\n\n    async.eachLimit = function (arr, limit, iterator, callback) {\n        var fn = _eachLimit(limit);\n        fn.apply(null, [arr, iterator, callback]);\n    };\n    async.forEachLimit = async.eachLimit;\n\n    var _eachLimit = function (limit) {\n\n        return function (arr, iterator, callback) {\n            callback = callback || function () {};\n            if (!arr.length || limit <= 0) {\n                return callback();\n            }\n            var completed = 0;\n            var started = 0;\n            var running = 0;\n\n            (function replenish () {\n                if (completed >= arr.length) {\n                    return callback();\n                }\n\n                while (running < limit && started < arr.length) {\n                    started += 1;\n                    running += 1;\n                    iterator(arr[started - 1], function (err) {\n                        if (err) {\n                            callback(err);\n                            callback = function () {};\n                        }\n                        else {\n                            completed += 1;\n                            running -= 1;\n                            if (completed >= arr.length) {\n                                callback();\n                            }\n                            else {\n                                replenish();\n                            }\n                        }\n                    });\n                }\n            })();\n        };\n    };\n\n\n    var doParallel = function (fn) {\n        return function () {\n            var args = Array.prototype.slice.call(arguments);\n            return fn.apply(null, [async.each].concat(args));\n        };\n    };\n    var doParallelLimit = function(limit, fn) {\n        return function () {\n            var args = Array.prototype.slice.call(arguments);\n            return fn.apply(null, [_eachLimit(limit)].concat(args));\n        };\n    };\n    var doSeries = function (fn) {\n        return function () {\n            var args = Array.prototype.slice.call(arguments);\n            return fn.apply(null, [async.eachSeries].concat(args));\n        };\n    };\n\n\n    var _asyncMap = function (eachfn, arr, iterator, callback) {\n        arr = _map(arr, function (x, i) {\n            return {index: i, value: x};\n        });\n        if (!callback) {\n            eachfn(arr, function (x, callback) {\n                iterator(x.value, function (err) {\n                    callback(err);\n                });\n            });\n        } else {\n            var results = [];\n            eachfn(arr, function (x, callback) {\n                iterator(x.value, function (err, v) {\n                    results[x.index] = v;\n                    callback(err);\n                });\n            }, function (err) {\n                callback(err, results);\n            });\n        }\n    };\n    async.map = doParallel(_asyncMap);\n    async.mapSeries = doSeries(_asyncMap);\n    async.mapLimit = function (arr, limit, iterator, callback) {\n        return _mapLimit(limit)(arr, iterator, callback);\n    };\n\n    var _mapLimit = function(limit) {\n        return doParallelLimit(limit, _asyncMap);\n    };\n\n    // reduce only has a series version, as doing reduce in parallel won't\n    // work in many situations.\n    async.reduce = function (arr, memo, iterator, callback) {\n        async.eachSeries(arr, function (x, callback) {\n            iterator(memo, x, function (err, v) {\n                memo = v;\n                callback(err);\n            });\n        }, function (err) {\n            callback(err, memo);\n        });\n    };\n    // inject alias\n    async.inject = async.reduce;\n    // foldl alias\n    async.foldl = async.reduce;\n\n    async.reduceRight = function (arr, memo, iterator, callback) {\n        var reversed = _map(arr, function (x) {\n            return x;\n        }).reverse();\n        async.reduce(reversed, memo, iterator, callback);\n    };\n    // foldr alias\n    async.foldr = async.reduceRight;\n\n    var _filter = function (eachfn, arr, iterator, callback) {\n        var results = [];\n        arr = _map(arr, function (x, i) {\n            return {index: i, value: x};\n        });\n        eachfn(arr, function (x, callback) {\n            iterator(x.value, function (v) {\n                if (v) {\n                    results.push(x);\n                }\n                callback();\n            });\n        }, function (err) {\n            callback(_map(results.sort(function (a, b) {\n                return a.index - b.index;\n            }), function (x) {\n                return x.value;\n            }));\n        });\n    };\n    async.filter = doParallel(_filter);\n    async.filterSeries = doSeries(_filter);\n    // select alias\n    async.select = async.filter;\n    async.selectSeries = async.filterSeries;\n\n    var _reject = function (eachfn, arr, iterator, callback) {\n        var results = [];\n        arr = _map(arr, function (x, i) {\n            return {index: i, value: x};\n        });\n        eachfn(arr, function (x, callback) {\n            iterator(x.value, function (v) {\n                if (!v) {\n                    results.push(x);\n                }\n                callback();\n            });\n        }, function (err) {\n            callback(_map(results.sort(function (a, b) {\n                return a.index - b.index;\n            }), function (x) {\n                return x.value;\n            }));\n        });\n    };\n    async.reject = doParallel(_reject);\n    async.rejectSeries = doSeries(_reject);\n\n    var _detect = function (eachfn, arr, iterator, main_callback) {\n        eachfn(arr, function (x, callback) {\n            iterator(x, function (result) {\n                if (result) {\n                    main_callback(x);\n                    main_callback = function () {};\n                }\n                else {\n                    callback();\n                }\n            });\n        }, function (err) {\n            main_callback();\n        });\n    };\n    async.detect = doParallel(_detect);\n    async.detectSeries = doSeries(_detect);\n\n    async.some = function (arr, iterator, main_callback) {\n        async.each(arr, function (x, callback) {\n            iterator(x, function (v) {\n                if (v) {\n                    main_callback(true);\n                    main_callback = function () {};\n                }\n                callback();\n            });\n        }, function (err) {\n            main_callback(false);\n        });\n    };\n    // any alias\n    async.any = async.some;\n\n    async.every = function (arr, iterator, main_callback) {\n        async.each(arr, function (x, callback) {\n            iterator(x, function (v) {\n                if (!v) {\n                    main_callback(false);\n                    main_callback = function () {};\n                }\n                callback();\n            });\n        }, function (err) {\n            main_callback(true);\n        });\n    };\n    // all alias\n    async.all = async.every;\n\n    async.sortBy = function (arr, iterator, callback) {\n        async.map(arr, function (x, callback) {\n            iterator(x, function (err, criteria) {\n                if (err) {\n                    callback(err);\n                }\n                else {\n                    callback(null, {value: x, criteria: criteria});\n                }\n            });\n        }, function (err, results) {\n            if (err) {\n                return callback(err);\n            }\n            else {\n                var fn = function (left, right) {\n                    var a = left.criteria, b = right.criteria;\n                    return a < b ? -1 : a > b ? 1 : 0;\n                };\n                callback(null, _map(results.sort(fn), function (x) {\n                    return x.value;\n                }));\n            }\n        });\n    };\n\n    async.auto = function (tasks, callback) {\n        callback = callback || function () {};\n        var keys = _keys(tasks);\n        var remainingTasks = keys.length\n        if (!remainingTasks) {\n            return callback();\n        }\n\n        var results = {};\n\n        var listeners = [];\n        var addListener = function (fn) {\n            listeners.unshift(fn);\n        };\n        var removeListener = function (fn) {\n            for (var i = 0; i < listeners.length; i += 1) {\n                if (listeners[i] === fn) {\n                    listeners.splice(i, 1);\n                    return;\n                }\n            }\n        };\n        var taskComplete = function () {\n            remainingTasks--\n            _each(listeners.slice(0), function (fn) {\n                fn();\n            });\n        };\n\n        addListener(function () {\n            if (!remainingTasks) {\n                var theCallback = callback;\n                // prevent final callback from calling itself if it errors\n                callback = function () {};\n\n                theCallback(null, results);\n            }\n        });\n\n        _each(keys, function (k) {\n            var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];\n            var taskCallback = function (err) {\n                var args = Array.prototype.slice.call(arguments, 1);\n                if (args.length <= 1) {\n                    args = args[0];\n                }\n                if (err) {\n                    var safeResults = {};\n                    _each(_keys(results), function(rkey) {\n                        safeResults[rkey] = results[rkey];\n                    });\n                    safeResults[k] = args;\n                    callback(err, safeResults);\n                    // stop subsequent errors hitting callback multiple times\n                    callback = function () {};\n                }\n                else {\n                    results[k] = args;\n                    async.setImmediate(taskComplete);\n                }\n            };\n            var requires = task.slice(0, Math.abs(task.length - 1)) || [];\n            var ready = function () {\n                return _reduce(requires, function (a, x) {\n                    return (a && results.hasOwnProperty(x));\n                }, true) && !results.hasOwnProperty(k);\n            };\n            if (ready()) {\n                task[task.length - 1](taskCallback, results);\n            }\n            else {\n                var listener = function () {\n                    if (ready()) {\n                        removeListener(listener);\n                        task[task.length - 1](taskCallback, results);\n                    }\n                };\n                addListener(listener);\n            }\n        });\n    };\n\n    async.retry = function(times, task, callback) {\n        var DEFAULT_TIMES = 5;\n        var attempts = [];\n        // Use defaults if times not passed\n        if (typeof times === 'function') {\n            callback = task;\n            task = times;\n            times = DEFAULT_TIMES;\n        }\n        // Make sure times is a number\n        times = parseInt(times, 10) || DEFAULT_TIMES;\n        var wrappedTask = function(wrappedCallback, wrappedResults) {\n            var retryAttempt = function(task, finalAttempt) {\n                return function(seriesCallback) {\n                    task(function(err, result){\n                        seriesCallback(!err || finalAttempt, {err: err, result: result});\n                    }, wrappedResults);\n                };\n            };\n            while (times) {\n                attempts.push(retryAttempt(task, !(times-=1)));\n            }\n            async.series(attempts, function(done, data){\n                data = data[data.length - 1];\n                (wrappedCallback || callback)(data.err, data.result);\n            });\n        }\n        // If a callback is passed, run this as a controll flow\n        return callback ? wrappedTask() : wrappedTask\n    };\n\n    async.waterfall = function (tasks, callback) {\n        callback = callback || function () {};\n        if (!_isArray(tasks)) {\n          var err = new Error('First argument to waterfall must be an array of functions');\n          return callback(err);\n        }\n        if (!tasks.length) {\n            return callback();\n        }\n        var wrapIterator = function (iterator) {\n            return function (err) {\n                if (err) {\n                    callback.apply(null, arguments);\n                    callback = function () {};\n                }\n                else {\n                    var args = Array.prototype.slice.call(arguments, 1);\n                    var next = iterator.next();\n                    if (next) {\n                        args.push(wrapIterator(next));\n                    }\n                    else {\n                        args.push(callback);\n                    }\n                    async.setImmediate(function () {\n                        iterator.apply(null, args);\n                    });\n                }\n            };\n        };\n        wrapIterator(async.iterator(tasks))();\n    };\n\n    var _parallel = function(eachfn, tasks, callback) {\n        callback = callback || function () {};\n        if (_isArray(tasks)) {\n            eachfn.map(tasks, function (fn, callback) {\n                if (fn) {\n                    fn(function (err) {\n                        var args = Array.prototype.slice.call(arguments, 1);\n                        if (args.length <= 1) {\n                            args = args[0];\n                        }\n                        callback.call(null, err, args);\n                    });\n                }\n            }, callback);\n        }\n        else {\n            var results = {};\n            eachfn.each(_keys(tasks), function (k, callback) {\n                tasks[k](function (err) {\n                    var args = Array.prototype.slice.call(arguments, 1);\n                    if (args.length <= 1) {\n                        args = args[0];\n                    }\n                    results[k] = args;\n                    callback(err);\n                });\n            }, function (err) {\n                callback(err, results);\n            });\n        }\n    };\n\n    async.parallel = function (tasks, callback) {\n        _parallel({ map: async.map, each: async.each }, tasks, callback);\n    };\n\n    async.parallelLimit = function(tasks, limit, callback) {\n        _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);\n    };\n\n    async.series = function (tasks, callback) {\n        callback = callback || function () {};\n        if (_isArray(tasks)) {\n            async.mapSeries(tasks, function (fn, callback) {\n                if (fn) {\n                    fn(function (err) {\n                        var args = Array.prototype.slice.call(arguments, 1);\n                        if (args.length <= 1) {\n                            args = args[0];\n                        }\n                        callback.call(null, err, args);\n                    });\n                }\n            }, callback);\n        }\n        else {\n            var results = {};\n            async.eachSeries(_keys(tasks), function (k, callback) {\n                tasks[k](function (err) {\n                    var args = Array.prototype.slice.call(arguments, 1);\n                    if (args.length <= 1) {\n                        args = args[0];\n                    }\n                    results[k] = args;\n                    callback(err);\n                });\n            }, function (err) {\n                callback(err, results);\n            });\n        }\n    };\n\n    async.iterator = function (tasks) {\n        var makeCallback = function (index) {\n            var fn = function () {\n                if (tasks.length) {\n                    tasks[index].apply(null, arguments);\n                }\n                return fn.next();\n            };\n            fn.next = function () {\n                return (index < tasks.length - 1) ? makeCallback(index + 1): null;\n            };\n            return fn;\n        };\n        return makeCallback(0);\n    };\n\n    async.apply = function (fn) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        return function () {\n            return fn.apply(\n                null, args.concat(Array.prototype.slice.call(arguments))\n            );\n        };\n    };\n\n    var _concat = function (eachfn, arr, fn, callback) {\n        var r = [];\n        eachfn(arr, function (x, cb) {\n            fn(x, function (err, y) {\n                r = r.concat(y || []);\n                cb(err);\n            });\n        }, function (err) {\n            callback(err, r);\n        });\n    };\n    async.concat = doParallel(_concat);\n    async.concatSeries = doSeries(_concat);\n\n    async.whilst = function (test, iterator, callback) {\n        if (test()) {\n            iterator(function (err) {\n                if (err) {\n                    return callback(err);\n                }\n                async.whilst(test, iterator, callback);\n            });\n        }\n        else {\n            callback();\n        }\n    };\n\n    async.doWhilst = function (iterator, test, callback) {\n        iterator(function (err) {\n            if (err) {\n                return callback(err);\n            }\n            var args = Array.prototype.slice.call(arguments, 1);\n            if (test.apply(null, args)) {\n                async.doWhilst(iterator, test, callback);\n            }\n            else {\n                callback();\n            }\n        });\n    };\n\n    async.until = function (test, iterator, callback) {\n        if (!test()) {\n            iterator(function (err) {\n                if (err) {\n                    return callback(err);\n                }\n                async.until(test, iterator, callback);\n            });\n        }\n        else {\n            callback();\n        }\n    };\n\n    async.doUntil = function (iterator, test, callback) {\n        iterator(function (err) {\n            if (err) {\n                return callback(err);\n            }\n            var args = Array.prototype.slice.call(arguments, 1);\n            if (!test.apply(null, args)) {\n                async.doUntil(iterator, test, callback);\n            }\n            else {\n                callback();\n            }\n        });\n    };\n\n    async.queue = function (worker, concurrency) {\n        if (concurrency === undefined) {\n            concurrency = 1;\n        }\n        function _insert(q, data, pos, callback) {\n          if (!q.started){\n            q.started = true;\n          }\n          if (!_isArray(data)) {\n              data = [data];\n          }\n          if(data.length == 0) {\n             // call drain immediately if there are no tasks\n             return async.setImmediate(function() {\n                 if (q.drain) {\n                     q.drain();\n                 }\n             });\n          }\n          _each(data, function(task) {\n              var item = {\n                  data: task,\n                  callback: typeof callback === 'function' ? callback : null\n              };\n\n              if (pos) {\n                q.tasks.unshift(item);\n              } else {\n                q.tasks.push(item);\n              }\n\n              if (q.saturated && q.tasks.length === q.concurrency) {\n                  q.saturated();\n              }\n              async.setImmediate(q.process);\n          });\n        }\n\n        var workers = 0;\n        var q = {\n            tasks: [],\n            concurrency: concurrency,\n            saturated: null,\n            empty: null,\n            drain: null,\n            started: false,\n            paused: false,\n            push: function (data, callback) {\n              _insert(q, data, false, callback);\n            },\n            kill: function () {\n              q.drain = null;\n              q.tasks = [];\n            },\n            unshift: function (data, callback) {\n              _insert(q, data, true, callback);\n            },\n            process: function () {\n                if (!q.paused && workers < q.concurrency && q.tasks.length) {\n                    var task = q.tasks.shift();\n                    if (q.empty && q.tasks.length === 0) {\n                        q.empty();\n                    }\n                    workers += 1;\n                    var next = function () {\n                        workers -= 1;\n                        if (task.callback) {\n                            task.callback.apply(task, arguments);\n                        }\n                        if (q.drain && q.tasks.length + workers === 0) {\n                            q.drain();\n                        }\n                        q.process();\n                    };\n                    var cb = only_once(next);\n                    worker(task.data, cb);\n                }\n            },\n            length: function () {\n                return q.tasks.length;\n            },\n            running: function () {\n                return workers;\n            },\n            idle: function() {\n                return q.tasks.length + workers === 0;\n            },\n            pause: function () {\n                if (q.paused === true) { return; }\n                q.paused = true;\n                q.process();\n            },\n            resume: function () {\n                if (q.paused === false) { return; }\n                q.paused = false;\n                q.process();\n            }\n        };\n        return q;\n    };\n\n    async.cargo = function (worker, payload) {\n        var working     = false,\n            tasks       = [];\n\n        var cargo = {\n            tasks: tasks,\n            payload: payload,\n            saturated: null,\n            empty: null,\n            drain: null,\n            drained: true,\n            push: function (data, callback) {\n                if (!_isArray(data)) {\n                    data = [data];\n                }\n                _each(data, function(task) {\n                    tasks.push({\n                        data: task,\n                        callback: typeof callback === 'function' ? callback : null\n                    });\n                    cargo.drained = false;\n                    if (cargo.saturated && tasks.length === payload) {\n                        cargo.saturated();\n                    }\n                });\n                async.setImmediate(cargo.process);\n            },\n            process: function process() {\n                if (working) return;\n                if (tasks.length === 0) {\n                    if(cargo.drain && !cargo.drained) cargo.drain();\n                    cargo.drained = true;\n                    return;\n                }\n\n                var ts = typeof payload === 'number'\n                            ? tasks.splice(0, payload)\n                            : tasks.splice(0, tasks.length);\n\n                var ds = _map(ts, function (task) {\n                    return task.data;\n                });\n\n                if(cargo.empty) cargo.empty();\n                working = true;\n                worker(ds, function () {\n                    working = false;\n\n                    var args = arguments;\n                    _each(ts, function (data) {\n                        if (data.callback) {\n                            data.callback.apply(null, args);\n                        }\n                    });\n\n                    process();\n                });\n            },\n            length: function () {\n                return tasks.length;\n            },\n            running: function () {\n                return working;\n            }\n        };\n        return cargo;\n    };\n\n    var _console_fn = function (name) {\n        return function (fn) {\n            var args = Array.prototype.slice.call(arguments, 1);\n            fn.apply(null, args.concat([function (err) {\n                var args = Array.prototype.slice.call(arguments, 1);\n                if (typeof console !== 'undefined') {\n                    if (err) {\n                        if (console.error) {\n                            console.error(err);\n                        }\n                    }\n                    else if (console[name]) {\n                        _each(args, function (x) {\n                            console[name](x);\n                        });\n                    }\n                }\n            }]));\n        };\n    };\n    async.log = _console_fn('log');\n    async.dir = _console_fn('dir');\n    /*async.info = _console_fn('info');\n    async.warn = _console_fn('warn');\n    async.error = _console_fn('error');*/\n\n    async.memoize = function (fn, hasher) {\n        var memo = {};\n        var queues = {};\n        hasher = hasher || function (x) {\n            return x;\n        };\n        var memoized = function () {\n            var args = Array.prototype.slice.call(arguments);\n            var callback = args.pop();\n            var key = hasher.apply(null, args);\n            if (key in memo) {\n                async.nextTick(function () {\n                    callback.apply(null, memo[key]);\n                });\n            }\n            else if (key in queues) {\n                queues[key].push(callback);\n            }\n            else {\n                queues[key] = [callback];\n                fn.apply(null, args.concat([function () {\n                    memo[key] = arguments;\n                    var q = queues[key];\n                    delete queues[key];\n                    for (var i = 0, l = q.length; i < l; i++) {\n                      q[i].apply(null, arguments);\n                    }\n                }]));\n            }\n        };\n        memoized.memo = memo;\n        memoized.unmemoized = fn;\n        return memoized;\n    };\n\n    async.unmemoize = function (fn) {\n      return function () {\n        return (fn.unmemoized || fn).apply(null, arguments);\n      };\n    };\n\n    async.times = function (count, iterator, callback) {\n        var counter = [];\n        for (var i = 0; i < count; i++) {\n            counter.push(i);\n        }\n        return async.map(counter, iterator, callback);\n    };\n\n    async.timesSeries = function (count, iterator, callback) {\n        var counter = [];\n        for (var i = 0; i < count; i++) {\n            counter.push(i);\n        }\n        return async.mapSeries(counter, iterator, callback);\n    };\n\n    async.seq = function (/* functions... */) {\n        var fns = arguments;\n        return function () {\n            var that = this;\n            var args = Array.prototype.slice.call(arguments);\n            var callback = args.pop();\n            async.reduce(fns, args, function (newargs, fn, cb) {\n                fn.apply(that, newargs.concat([function () {\n                    var err = arguments[0];\n                    var nextargs = Array.prototype.slice.call(arguments, 1);\n                    cb(err, nextargs);\n                }]))\n            },\n            function (err, results) {\n                callback.apply(that, [err].concat(results));\n            });\n        };\n    };\n\n    async.compose = function (/* functions... */) {\n      return async.seq.apply(null, Array.prototype.reverse.call(arguments));\n    };\n\n    var _applyEach = function (eachfn, fns /*args...*/) {\n        var go = function () {\n            var that = this;\n            var args = Array.prototype.slice.call(arguments);\n            var callback = args.pop();\n            return eachfn(fns, function (fn, cb) {\n                fn.apply(that, args.concat([cb]));\n            },\n            callback);\n        };\n        if (arguments.length > 2) {\n            var args = Array.prototype.slice.call(arguments, 2);\n            return go.apply(this, args);\n        }\n        else {\n            return go;\n        }\n    };\n    async.applyEach = doParallel(_applyEach);\n    async.applyEachSeries = doSeries(_applyEach);\n\n    async.forever = function (fn, callback) {\n        function next(err) {\n            if (err) {\n                if (callback) {\n                    return callback(err);\n                }\n                throw err;\n            }\n            fn(next);\n        }\n        next();\n    };\n\n    // Node.js\n    if (typeof module !== 'undefined' && module.exports) {\n        module.exports = async;\n    }\n    // AMD / RequireJS\n    else if (true) {\n        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function () {\n            return async;\n        }.apply(null, __WEBPACK_AMD_DEFINE_ARRAY__)), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n    }\n    // included directly via <script> tag\n    else {\n        root.async = async;\n    }\n\n}());\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(62)))\n\n// WEBPACK FOOTER\n// module.id = 50\n// module.readableIdentifier = ./~/async/lib/async.js\n//@ sourceURL=webpack-module:///./~/async/lib/async.js");

/***/ },
/* 51 */
/***/ function(module, exports, __webpack_require__) {

	eval("/**\n * Module dependencies.\n */\n\nvar Emitter = __webpack_require__(71);\nvar reduce = __webpack_require__(72);\n\n/**\n * Root reference for iframes.\n */\n\nvar root = 'undefined' == typeof window\n  ? this\n  : window;\n\n/**\n * Noop.\n */\n\nfunction noop(){};\n\n/**\n * Check if `obj` is a host object,\n * we don't want to serialize these :)\n *\n * TODO: future proof, move to compoent land\n *\n * @param {Object} obj\n * @return {Boolean}\n * @api private\n */\n\nfunction isHost(obj) {\n  var str = {}.toString.call(obj);\n\n  switch (str) {\n    case '[object File]':\n    case '[object Blob]':\n    case '[object FormData]':\n      return true;\n    default:\n      return false;\n  }\n}\n\n/**\n * Determine XHR.\n */\n\nfunction getXHR() {\n  if (root.XMLHttpRequest\n    && ('file:' != root.location.protocol || !root.ActiveXObject)) {\n    return new XMLHttpRequest;\n  } else {\n    try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}\n    try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {}\n    try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {}\n    try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}\n  }\n  return false;\n}\n\n/**\n * Removes leading and trailing whitespace, added to support IE.\n *\n * @param {String} s\n * @return {String}\n * @api private\n */\n\nvar trim = ''.trim\n  ? function(s) { return s.trim(); }\n  : function(s) { return s.replace(/(^\\s*|\\s*$)/g, ''); };\n\n/**\n * Check if `obj` is an object.\n *\n * @param {Object} obj\n * @return {Boolean}\n * @api private\n */\n\nfunction isObject(obj) {\n  return obj === Object(obj);\n}\n\n/**\n * Serialize the given `obj`.\n *\n * @param {Object} obj\n * @return {String}\n * @api private\n */\n\nfunction serialize(obj) {\n  if (!isObject(obj)) return obj;\n  var pairs = [];\n  for (var key in obj) {\n    if (null != obj[key]) {\n      pairs.push(encodeURIComponent(key)\n        + '=' + encodeURIComponent(obj[key]));\n    }\n  }\n  return pairs.join('&');\n}\n\n/**\n * Expose serialization method.\n */\n\n request.serializeObject = serialize;\n\n /**\n  * Parse the given x-www-form-urlencoded `str`.\n  *\n  * @param {String} str\n  * @return {Object}\n  * @api private\n  */\n\nfunction parseString(str) {\n  var obj = {};\n  var pairs = str.split('&');\n  var parts;\n  var pair;\n\n  for (var i = 0, len = pairs.length; i < len; ++i) {\n    pair = pairs[i];\n    parts = pair.split('=');\n    obj[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);\n  }\n\n  return obj;\n}\n\n/**\n * Expose parser.\n */\n\nrequest.parseString = parseString;\n\n/**\n * Default MIME type map.\n *\n *     superagent.types.xml = 'application/xml';\n *\n */\n\nrequest.types = {\n  html: 'text/html',\n  json: 'application/json',\n  xml: 'application/xml',\n  urlencoded: 'application/x-www-form-urlencoded',\n  'form': 'application/x-www-form-urlencoded',\n  'form-data': 'application/x-www-form-urlencoded'\n};\n\n/**\n * Default serialization map.\n *\n *     superagent.serialize['application/xml'] = function(obj){\n *       return 'generated xml here';\n *     };\n *\n */\n\n request.serialize = {\n   'application/x-www-form-urlencoded': serialize,\n   'application/json': JSON.stringify\n };\n\n /**\n  * Default parsers.\n  *\n  *     superagent.parse['application/xml'] = function(str){\n  *       return { object parsed from str };\n  *     };\n  *\n  */\n\nrequest.parse = {\n  'application/x-www-form-urlencoded': parseString,\n  'application/json': JSON.parse\n};\n\n/**\n * Parse the given header `str` into\n * an object containing the mapped fields.\n *\n * @param {String} str\n * @return {Object}\n * @api private\n */\n\nfunction parseHeader(str) {\n  var lines = str.split(/\\r?\\n/);\n  var fields = {};\n  var index;\n  var line;\n  var field;\n  var val;\n\n  lines.pop(); // trailing CRLF\n\n  for (var i = 0, len = lines.length; i < len; ++i) {\n    line = lines[i];\n    index = line.indexOf(':');\n    field = line.slice(0, index).toLowerCase();\n    val = trim(line.slice(index + 1));\n    fields[field] = val;\n  }\n\n  return fields;\n}\n\n/**\n * Return the mime type for the given `str`.\n *\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nfunction type(str){\n  return str.split(/ *; */).shift();\n};\n\n/**\n * Return header field parameters.\n *\n * @param {String} str\n * @return {Object}\n * @api private\n */\n\nfunction params(str){\n  return reduce(str.split(/ *; */), function(obj, str){\n    var parts = str.split(/ *= */)\n      , key = parts.shift()\n      , val = parts.shift();\n\n    if (key && val) obj[key] = val;\n    return obj;\n  }, {});\n};\n\n/**\n * Initialize a new `Response` with the given `xhr`.\n *\n *  - set flags (.ok, .error, etc)\n *  - parse header\n *\n * Examples:\n *\n *  Aliasing `superagent` as `request` is nice:\n *\n *      request = superagent;\n *\n *  We can use the promise-like API, or pass callbacks:\n *\n *      request.get('/').end(function(res){});\n *      request.get('/', function(res){});\n *\n *  Sending data can be chained:\n *\n *      request\n *        .post('/user')\n *        .send({ name: 'tj' })\n *        .end(function(res){});\n *\n *  Or passed to `.send()`:\n *\n *      request\n *        .post('/user')\n *        .send({ name: 'tj' }, function(res){});\n *\n *  Or passed to `.post()`:\n *\n *      request\n *        .post('/user', { name: 'tj' })\n *        .end(function(res){});\n *\n * Or further reduced to a single call for simple cases:\n *\n *      request\n *        .post('/user', { name: 'tj' }, function(res){});\n *\n * @param {XMLHTTPRequest} xhr\n * @param {Object} options\n * @api private\n */\n\nfunction Response(req, options) {\n  options = options || {};\n  this.req = req;\n  this.xhr = this.req.xhr;\n  this.text = this.xhr.responseText;\n  this.setStatusProperties(this.xhr.status);\n  this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders());\n  // getAllResponseHeaders sometimes falsely returns \"\" for CORS requests, but\n  // getResponseHeader still works. so we get content-type even if getting\n  // other headers fails.\n  this.header['content-type'] = this.xhr.getResponseHeader('content-type');\n  this.setHeaderProperties(this.header);\n  this.body = this.req.method != 'HEAD'\n    ? this.parseBody(this.text)\n    : null;\n}\n\n/**\n * Get case-insensitive `field` value.\n *\n * @param {String} field\n * @return {String}\n * @api public\n */\n\nResponse.prototype.get = function(field){\n  return this.header[field.toLowerCase()];\n};\n\n/**\n * Set header related properties:\n *\n *   - `.type` the content type without params\n *\n * A response of \"Content-Type: text/plain; charset=utf-8\"\n * will provide you with a `.type` of \"text/plain\".\n *\n * @param {Object} header\n * @api private\n */\n\nResponse.prototype.setHeaderProperties = function(header){\n  // content-type\n  var ct = this.header['content-type'] || '';\n  this.type = type(ct);\n\n  // params\n  var obj = params(ct);\n  for (var key in obj) this[key] = obj[key];\n};\n\n/**\n * Parse the given body `str`.\n *\n * Used for auto-parsing of bodies. Parsers\n * are defined on the `superagent.parse` object.\n *\n * @param {String} str\n * @return {Mixed}\n * @api private\n */\n\nResponse.prototype.parseBody = function(str){\n  var parse = request.parse[this.type];\n  return parse\n    ? parse(str)\n    : null;\n};\n\n/**\n * Set flags such as `.ok` based on `status`.\n *\n * For example a 2xx response will give you a `.ok` of __true__\n * whereas 5xx will be __false__ and `.error` will be __true__. The\n * `.clientError` and `.serverError` are also available to be more\n * specific, and `.statusType` is the class of error ranging from 1..5\n * sometimes useful for mapping respond colors etc.\n *\n * \"sugar\" properties are also defined for common cases. Currently providing:\n *\n *   - .noContent\n *   - .badRequest\n *   - .unauthorized\n *   - .notAcceptable\n *   - .notFound\n *\n * @param {Number} status\n * @api private\n */\n\nResponse.prototype.setStatusProperties = function(status){\n  var type = status / 100 | 0;\n\n  // status / class\n  this.status = status;\n  this.statusType = type;\n\n  // basics\n  this.info = 1 == type;\n  this.ok = 2 == type;\n  this.clientError = 4 == type;\n  this.serverError = 5 == type;\n  this.error = (4 == type || 5 == type)\n    ? this.toError()\n    : false;\n\n  // sugar\n  this.accepted = 202 == status;\n  this.noContent = 204 == status || 1223 == status;\n  this.badRequest = 400 == status;\n  this.unauthorized = 401 == status;\n  this.notAcceptable = 406 == status;\n  this.notFound = 404 == status;\n  this.forbidden = 403 == status;\n};\n\n/**\n * Return an `Error` representative of this response.\n *\n * @return {Error}\n * @api public\n */\n\nResponse.prototype.toError = function(){\n  var req = this.req;\n  var method = req.method;\n  var url = req.url;\n\n  var msg = 'cannot ' + method + ' ' + url + ' (' + this.status + ')';\n  var err = new Error(msg);\n  err.status = this.status;\n  err.method = method;\n  err.url = url;\n\n  return err;\n};\n\n/**\n * Expose `Response`.\n */\n\nrequest.Response = Response;\n\n/**\n * Initialize a new `Request` with the given `method` and `url`.\n *\n * @param {String} method\n * @param {String} url\n * @api public\n */\n\nfunction Request(method, url) {\n  var self = this;\n  Emitter.call(this);\n  this._query = this._query || [];\n  this.method = method;\n  this.url = url;\n  this.header = {};\n  this._header = {};\n  this.on('end', function(){\n    var res = new Response(self);\n    if ('HEAD' == method) res.text = null;\n    self.callback(null, res);\n  });\n}\n\n/**\n * Mixin `Emitter`.\n */\n\nEmitter(Request.prototype);\n\n/**\n * Allow for extension\n */\n\nRequest.prototype.use = function(fn) {\n  fn(this);\n  return this;\n}\n\n/**\n * Set timeout to `ms`.\n *\n * @param {Number} ms\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.timeout = function(ms){\n  this._timeout = ms;\n  return this;\n};\n\n/**\n * Clear previous timeout.\n *\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.clearTimeout = function(){\n  this._timeout = 0;\n  clearTimeout(this._timer);\n  return this;\n};\n\n/**\n * Abort the request, and clear potential timeout.\n *\n * @return {Request}\n * @api public\n */\n\nRequest.prototype.abort = function(){\n  if (this.aborted) return;\n  this.aborted = true;\n  this.xhr.abort();\n  this.clearTimeout();\n  this.emit('abort');\n  return this;\n};\n\n/**\n * Set header `field` to `val`, or multiple fields with one object.\n *\n * Examples:\n *\n *      req.get('/')\n *        .set('Accept', 'application/json')\n *        .set('X-API-Key', 'foobar')\n *        .end(callback);\n *\n *      req.get('/')\n *        .set({ Accept: 'application/json', 'X-API-Key': 'foobar' })\n *        .end(callback);\n *\n * @param {String|Object} field\n * @param {String} val\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.set = function(field, val){\n  if (isObject(field)) {\n    for (var key in field) {\n      this.set(key, field[key]);\n    }\n    return this;\n  }\n  this._header[field.toLowerCase()] = val;\n  this.header[field] = val;\n  return this;\n};\n\n/**\n * Get case-insensitive header `field` value.\n *\n * @param {String} field\n * @return {String}\n * @api private\n */\n\nRequest.prototype.getHeader = function(field){\n  return this._header[field.toLowerCase()];\n};\n\n/**\n * Set Content-Type to `type`, mapping values from `request.types`.\n *\n * Examples:\n *\n *      superagent.types.xml = 'application/xml';\n *\n *      request.post('/')\n *        .type('xml')\n *        .send(xmlstring)\n *        .end(callback);\n *\n *      request.post('/')\n *        .type('application/xml')\n *        .send(xmlstring)\n *        .end(callback);\n *\n * @param {String} type\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.type = function(type){\n  this.set('Content-Type', request.types[type] || type);\n  return this;\n};\n\n/**\n * Set Accept to `type`, mapping values from `request.types`.\n *\n * Examples:\n *\n *      superagent.types.json = 'application/json';\n *\n *      request.get('/agent')\n *        .accept('json')\n *        .end(callback);\n *\n *      request.get('/agent')\n *        .accept('application/json')\n *        .end(callback);\n *\n * @param {String} accept\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.accept = function(type){\n  this.set('Accept', request.types[type] || type);\n  return this;\n};\n\n/**\n * Set Authorization field value with `user` and `pass`.\n *\n * @param {String} user\n * @param {String} pass\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.auth = function(user, pass){\n  var str = btoa(user + ':' + pass);\n  this.set('Authorization', 'Basic ' + str);\n  return this;\n};\n\n/**\n* Add query-string `val`.\n*\n* Examples:\n*\n*   request.get('/shoes')\n*     .query('size=10')\n*     .query({ color: 'blue' })\n*\n* @param {Object|String} val\n* @return {Request} for chaining\n* @api public\n*/\n\nRequest.prototype.query = function(val){\n  if ('string' != typeof val) val = serialize(val);\n  if (val) this._query.push(val);\n  return this;\n};\n\n/**\n * Write the field `name` and `val` for \"multipart/form-data\"\n * request bodies.\n *\n * ``` js\n * request.post('/upload')\n *   .field('foo', 'bar')\n *   .end(callback);\n * ```\n *\n * @param {String} name\n * @param {String|Blob|File} val\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.field = function(name, val){\n  if (!this._formData) this._formData = new FormData();\n  this._formData.append(name, val);\n  return this;\n};\n\n/**\n * Queue the given `file` as an attachment to the specified `field`,\n * with optional `filename`.\n *\n * ``` js\n * request.post('/upload')\n *   .attach(new Blob(['<a id=\"a\"><b id=\"b\">hey!</b></a>'], { type: \"text/html\"}))\n *   .end(callback);\n * ```\n *\n * @param {String} field\n * @param {Blob|File} file\n * @param {String} filename\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.attach = function(field, file, filename){\n  if (!this._formData) this._formData = new FormData();\n  this._formData.append(field, file, filename);\n  return this;\n};\n\n/**\n * Send `data`, defaulting the `.type()` to \"json\" when\n * an object is given.\n *\n * Examples:\n *\n *       // querystring\n *       request.get('/search')\n *         .end(callback)\n *\n *       // multiple data \"writes\"\n *       request.get('/search')\n *         .send({ search: 'query' })\n *         .send({ range: '1..5' })\n *         .send({ order: 'desc' })\n *         .end(callback)\n *\n *       // manual json\n *       request.post('/user')\n *         .type('json')\n *         .send('{\"name\":\"tj\"})\n *         .end(callback)\n *\n *       // auto json\n *       request.post('/user')\n *         .send({ name: 'tj' })\n *         .end(callback)\n *\n *       // manual x-www-form-urlencoded\n *       request.post('/user')\n *         .type('form')\n *         .send('name=tj')\n *         .end(callback)\n *\n *       // auto x-www-form-urlencoded\n *       request.post('/user')\n *         .type('form')\n *         .send({ name: 'tj' })\n *         .end(callback)\n *\n *       // defaults to x-www-form-urlencoded\n  *      request.post('/user')\n  *        .send('name=tobi')\n  *        .send('species=ferret')\n  *        .end(callback)\n *\n * @param {String|Object} data\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.send = function(data){\n  var obj = isObject(data);\n  var type = this.getHeader('Content-Type');\n\n  // merge\n  if (obj && isObject(this._data)) {\n    for (var key in data) {\n      this._data[key] = data[key];\n    }\n  } else if ('string' == typeof data) {\n    if (!type) this.type('form');\n    type = this.getHeader('Content-Type');\n    if ('application/x-www-form-urlencoded' == type) {\n      this._data = this._data\n        ? this._data + '&' + data\n        : data;\n    } else {\n      this._data = (this._data || '') + data;\n    }\n  } else {\n    this._data = data;\n  }\n\n  if (!obj) return this;\n  if (!type) this.type('json');\n  return this;\n};\n\n/**\n * Invoke the callback with `err` and `res`\n * and handle arity check.\n *\n * @param {Error} err\n * @param {Response} res\n * @api private\n */\n\nRequest.prototype.callback = function(err, res){\n  var fn = this._callback;\n  if (2 == fn.length) return fn(err, res);\n  if (err) return this.emit('error', err);\n  fn(res);\n};\n\n/**\n * Invoke callback with x-domain error.\n *\n * @api private\n */\n\nRequest.prototype.crossDomainError = function(){\n  var err = new Error('Origin is not allowed by Access-Control-Allow-Origin');\n  err.crossDomain = true;\n  this.callback(err);\n};\n\n/**\n * Invoke callback with timeout error.\n *\n * @api private\n */\n\nRequest.prototype.timeoutError = function(){\n  var timeout = this._timeout;\n  var err = new Error('timeout of ' + timeout + 'ms exceeded');\n  err.timeout = timeout;\n  this.callback(err);\n};\n\n/**\n * Enable transmission of cookies with x-domain requests.\n *\n * Note that for this to work the origin must not be\n * using \"Access-Control-Allow-Origin\" with a wildcard,\n * and also must set \"Access-Control-Allow-Credentials\"\n * to \"true\".\n *\n * @api public\n */\n\nRequest.prototype.withCredentials = function(){\n  this._withCredentials = true;\n  return this;\n};\n\n/**\n * Initiate request, invoking callback `fn(res)`\n * with an instanceof `Response`.\n *\n * @param {Function} fn\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.end = function(fn){\n  var self = this;\n  var xhr = this.xhr = getXHR();\n  var query = this._query.join('&');\n  var timeout = this._timeout;\n  var data = this._formData || this._data;\n\n  // store callback\n  this._callback = fn || noop;\n\n  // state change\n  xhr.onreadystatechange = function(){\n    if (4 != xhr.readyState) return;\n    if (0 == xhr.status) {\n      if (self.aborted) return self.timeoutError();\n      return self.crossDomainError();\n    }\n    self.emit('end');\n  };\n\n  // progress\n  if (xhr.upload) {\n    xhr.upload.onprogress = function(e){\n      e.percent = e.loaded / e.total * 100;\n      self.emit('progress', e);\n    };\n  }\n\n  // timeout\n  if (timeout && !this._timer) {\n    this._timer = setTimeout(function(){\n      self.abort();\n    }, timeout);\n  }\n\n  // querystring\n  if (query) {\n    query = request.serializeObject(query);\n    this.url += ~this.url.indexOf('?')\n      ? '&' + query\n      : '?' + query;\n  }\n\n  // initiate request\n  xhr.open(this.method, this.url, true);\n\n  // CORS\n  if (this._withCredentials) xhr.withCredentials = true;\n\n  // body\n  if ('GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !isHost(data)) {\n    // serialize stuff\n    var serialize = request.serialize[this.getHeader('Content-Type')];\n    if (serialize) data = serialize(data);\n  }\n\n  // set header fields\n  for (var field in this.header) {\n    if (null == this.header[field]) continue;\n    xhr.setRequestHeader(field, this.header[field]);\n  }\n\n  // send stuff\n  this.emit('request', this);\n  xhr.send(data);\n  return this;\n};\n\n/**\n * Expose `Request`.\n */\n\nrequest.Request = Request;\n\n/**\n * Issue a request:\n *\n * Examples:\n *\n *    request('GET', '/users').end(callback)\n *    request('/users').end(callback)\n *    request('/users', callback)\n *\n * @param {String} method\n * @param {String|Function} url or callback\n * @return {Request}\n * @api public\n */\n\nfunction request(method, url) {\n  // callback\n  if ('function' == typeof url) {\n    return new Request('GET', method).end(url);\n  }\n\n  // url first\n  if (1 == arguments.length) {\n    return new Request('GET', method);\n  }\n\n  return new Request(method, url);\n}\n\n/**\n * GET `url` with optional callback `fn(res)`.\n *\n * @param {String} url\n * @param {Mixed|Function} data or fn\n * @param {Function} fn\n * @return {Request}\n * @api public\n */\n\nrequest.get = function(url, data, fn){\n  var req = request('GET', url);\n  if ('function' == typeof data) fn = data, data = null;\n  if (data) req.query(data);\n  if (fn) req.end(fn);\n  return req;\n};\n\n/**\n * HEAD `url` with optional callback `fn(res)`.\n *\n * @param {String} url\n * @param {Mixed|Function} data or fn\n * @param {Function} fn\n * @return {Request}\n * @api public\n */\n\nrequest.head = function(url, data, fn){\n  var req = request('HEAD', url);\n  if ('function' == typeof data) fn = data, data = null;\n  if (data) req.send(data);\n  if (fn) req.end(fn);\n  return req;\n};\n\n/**\n * DELETE `url` with optional callback `fn(res)`.\n *\n * @param {String} url\n * @param {Function} fn\n * @return {Request}\n * @api public\n */\n\nrequest.del = function(url, fn){\n  var req = request('DELETE', url);\n  if (fn) req.end(fn);\n  return req;\n};\n\n/**\n * PATCH `url` with optional `data` and callback `fn(res)`.\n *\n * @param {String} url\n * @param {Mixed} data\n * @param {Function} fn\n * @return {Request}\n * @api public\n */\n\nrequest.patch = function(url, data, fn){\n  var req = request('PATCH', url);\n  if ('function' == typeof data) fn = data, data = null;\n  if (data) req.send(data);\n  if (fn) req.end(fn);\n  return req;\n};\n\n/**\n * POST `url` with optional `data` and callback `fn(res)`.\n *\n * @param {String} url\n * @param {Mixed} data\n * @param {Function} fn\n * @return {Request}\n * @api public\n */\n\nrequest.post = function(url, data, fn){\n  var req = request('POST', url);\n  if ('function' == typeof data) fn = data, data = null;\n  if (data) req.send(data);\n  if (fn) req.end(fn);\n  return req;\n};\n\n/**\n * PUT `url` with optional `data` and callback `fn(res)`.\n *\n * @param {String} url\n * @param {Mixed|Function} data or fn\n * @param {Function} fn\n * @return {Request}\n * @api public\n */\n\nrequest.put = function(url, data, fn){\n  var req = request('PUT', url);\n  if ('function' == typeof data) fn = data, data = null;\n  if (data) req.send(data);\n  if (fn) req.end(fn);\n  return req;\n};\n\n/**\n * Expose `request`.\n */\n\nmodule.exports = request;\n\n\n// WEBPACK FOOTER\n// module.id = 51\n// module.readableIdentifier = ./~/superagent/lib/client.js\n//@ sourceURL=webpack-module:///./~/superagent/lib/client.js");

/***/ },
/* 52 */
/***/ function(module, exports, __webpack_require__) {

	eval("'use strict';\n\nexports.decode = exports.parse = __webpack_require__(63);\nexports.encode = exports.stringify = __webpack_require__(64);\n\n\n// WEBPACK FOOTER\n// module.id = 52\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/querystring-es3/index.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/querystring-es3/index.js");

/***/ },
/* 53 */
/***/ function(module, exports, __webpack_require__) {

	eval("/* WEBPACK VAR INJECTION */(function(Buffer) {// Original code adapted from Robert Kieffer.\n// details at https://github.com/broofa/node-uuid\n\n\n(function() {\n  var _global = this;\n\n  var mathRNG, whatwgRNG;\n\n  // NOTE: Math.random() does not guarantee \"cryptographic quality\"\n  mathRNG = function(size) {\n    var bytes = new Buffer(size);\n    var r;\n\n    for (var i = 0, r; i < size; i++) {\n      if ((i & 0x03) == 0) r = Math.random() * 0x100000000;\n      bytes[i] = r >>> ((i & 0x03) << 3) & 0xff;\n    }\n\n    return bytes;\n  }\n\n  if (_global.crypto && crypto.getRandomValues) {\n    whatwgRNG = function(size) {\n      var bytes = new Buffer(size); //in browserify, this is an extended Uint8Array\n      crypto.getRandomValues(bytes);\n      return bytes;\n    }\n  }\n\n  module.exports = whatwgRNG || mathRNG;\n\n}())\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(41).Buffer))\n\n// WEBPACK FOOTER\n// module.id = 53\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/rng.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/rng.js");

/***/ },
/* 54 */
/***/ function(module, exports, __webpack_require__) {

	eval("/* WEBPACK VAR INJECTION */(function(Buffer) {var createHash = __webpack_require__(73)\n\nvar md5 = toConstructor(__webpack_require__(66))\nvar rmd160 = toConstructor(__webpack_require__(75))\n\nfunction toConstructor (fn) {\n  return function () {\n    var buffers = []\n    var m= {\n      update: function (data, enc) {\n        if(!Buffer.isBuffer(data)) data = new Buffer(data, enc)\n        buffers.push(data)\n        return this\n      },\n      digest: function (enc) {\n        var buf = Buffer.concat(buffers)\n        var r = fn(buf)\n        buffers = null\n        return enc ? r.toString(enc) : r\n      }\n    }\n    return m\n  }\n}\n\nmodule.exports = function (alg) {\n  if('md5' === alg) return new md5()\n  if('rmd160' === alg) return new rmd160()\n  return createHash(alg)\n}\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(41).Buffer))\n\n// WEBPACK FOOTER\n// module.id = 54\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/create-hash.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/create-hash.js");

/***/ },
/* 55 */
/***/ function(module, exports, __webpack_require__) {

	eval("/* WEBPACK VAR INJECTION */(function(Buffer) {var createHash = __webpack_require__(54)\n\nvar blocksize = 64\nvar zeroBuffer = new Buffer(blocksize); zeroBuffer.fill(0)\n\nmodule.exports = Hmac\n\nfunction Hmac (alg, key) {\n  if(!(this instanceof Hmac)) return new Hmac(alg, key)\n  this._opad = opad\n  this._alg = alg\n\n  key = this._key = !Buffer.isBuffer(key) ? new Buffer(key) : key\n\n  if(key.length > blocksize) {\n    key = createHash(alg).update(key).digest()\n  } else if(key.length < blocksize) {\n    key = Buffer.concat([key, zeroBuffer], blocksize)\n  }\n\n  var ipad = this._ipad = new Buffer(blocksize)\n  var opad = this._opad = new Buffer(blocksize)\n\n  for(var i = 0; i < blocksize; i++) {\n    ipad[i] = key[i] ^ 0x36\n    opad[i] = key[i] ^ 0x5C\n  }\n\n  this._hash = createHash(alg).update(ipad)\n}\n\nHmac.prototype.update = function (data, enc) {\n  this._hash.update(data, enc)\n  return this\n}\n\nHmac.prototype.digest = function (enc) {\n  var h = this._hash.digest()\n  return createHash(this._alg).update(this._opad).update(h).digest(enc)\n}\n\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(41).Buffer))\n\n// WEBPACK FOOTER\n// module.id = 55\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/create-hmac.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/create-hmac.js");

/***/ },
/* 56 */
/***/ function(module, exports, __webpack_require__) {

	eval("/* WEBPACK VAR INJECTION */(function(Buffer) {// JavaScript PBKDF2 Implementation\n// Based on http://git.io/qsv2zw\n// Licensed under LGPL v3\n// Copyright (c) 2013 jduncanator\n\nvar blocksize = 64\nvar zeroBuffer = new Buffer(blocksize); zeroBuffer.fill(0)\n\nmodule.exports = function (createHmac, exports) {\n  exports = exports || {}\n\n  exports.pbkdf2 = function(password, salt, iterations, keylen, cb) {\n    if('function' !== typeof cb)\n      throw new Error('No callback provided to pbkdf2');\n    setTimeout(function () {\n      cb(null, exports.pbkdf2Sync(password, salt, iterations, keylen))\n    })\n  }\n\n  exports.pbkdf2Sync = function(key, salt, iterations, keylen) {\n    if('number' !== typeof iterations)\n      throw new TypeError('Iterations not a number')\n    if(iterations < 0)\n      throw new TypeError('Bad iterations')\n    if('number' !== typeof keylen)\n      throw new TypeError('Key length not a number')\n    if(keylen < 0)\n      throw new TypeError('Bad key length')\n\n    //stretch key to the correct length that hmac wants it,\n    //otherwise this will happen every time hmac is called\n    //twice per iteration.\n    var key = !Buffer.isBuffer(key) ? new Buffer(key) : key\n\n    if(key.length > blocksize) {\n      key = createHash(alg).update(key).digest()\n    } else if(key.length < blocksize) {\n      key = Buffer.concat([key, zeroBuffer], blocksize)\n    }\n\n    var HMAC;\n    var cplen, p = 0, i = 1, itmp = new Buffer(4), digtmp;\n    var out = new Buffer(keylen);\n    out.fill(0);\n    while(keylen) {\n      if(keylen > 20)\n        cplen = 20;\n      else\n        cplen = keylen;\n\n      /* We are unlikely to ever use more than 256 blocks (5120 bits!)\n         * but just in case...\n         */\n        itmp[0] = (i >> 24) & 0xff;\n        itmp[1] = (i >> 16) & 0xff;\n          itmp[2] = (i >> 8) & 0xff;\n          itmp[3] = i & 0xff;\n\n          HMAC = createHmac('sha1', key);\n          HMAC.update(salt)\n          HMAC.update(itmp);\n        digtmp = HMAC.digest();\n        digtmp.copy(out, p, 0, cplen);\n\n        for(var j = 1; j < iterations; j++) {\n          HMAC = createHmac('sha1', key);\n          HMAC.update(digtmp);\n          digtmp = HMAC.digest();\n          for(var k = 0; k < cplen; k++) {\n            out[k] ^= digtmp[k];\n          }\n        }\n      keylen -= cplen;\n      i++;\n      p += cplen;\n    }\n\n    return out;\n  }\n\n  return exports\n}\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(41).Buffer))\n\n// WEBPACK FOOTER\n// module.id = 56\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/pbkdf2.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/pbkdf2.js");

/***/ },
/* 57 */
/***/ function(module, exports, __webpack_require__) {

	eval("module.exports = function isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.readUInt8 === 'function';\n}\n\n// WEBPACK FOOTER\n// module.id = 57\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/util/support/isBufferBrowser.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/util/support/isBufferBrowser.js");

/***/ },
/* 58 */
/***/ function(module, exports, __webpack_require__) {

	eval("module.exports = function(options) { // inject sjcl dependency\n  var sjcl = options.sjcl;\n\n  var Base58Utils = (function () {\n    var alphabets = {\n      'ripple':  \"rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz\",\n      'bitcoin': \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\"\n    };\n\n    var SHA256  = function (bytes) {\n      return sjcl.codec.bytes.fromBits(sjcl.hash.sha256.hash(sjcl.codec.bytes.toBits(bytes)));\n    };\n\n    return {\n      // --> input: big-endian array of bytes.\n      // <-- string at least as long as input.\n      encode_base: function (input, alphabetName) {\n        var alphabet = alphabets[alphabetName || 'ripple'],\n            base     = new sjcl.bn(alphabet.length),\n            bi       = sjcl.bn.fromBits(sjcl.codec.bytes.toBits(input)),\n            buffer   = [];\n\n        while (bi.greaterEquals(base)) {\n          var mod = bi.mod(base);\n          buffer.push(alphabet[mod.limbs[0]]);\n          bi = bi.div(base);\n        }\n        buffer.push(alphabet[bi.limbs[0]]);\n\n        // Convert leading zeros too.\n        for (var i = 0; i != input.length && !input[i]; i += 1) {\n          buffer.push(alphabet[0]);\n        }\n\n        return buffer.reverse().join(\"\");\n      },\n\n      // --> input: String\n      // <-- array of bytes or undefined.\n      decode_base: function (input, alphabetName) {\n        var alphabet = alphabets[alphabetName || 'ripple'],\n            base     = new sjcl.bn(alphabet.length),\n            bi       = new sjcl.bn(0);\n\n        var i;\n        while (i != input.length && input[i] === alphabet[0]) {\n          i += 1;\n        }\n\n        for (i = 0; i != input.length; i += 1) {\n          var v = alphabet.indexOf(input[i]);\n\n          if (v < 0) {\n            return null;\n          }\n\n          bi = bi.mul(base).addM(v);\n        }\n\n        var bytes = sjcl.codec.bytes.fromBits(bi.toBits()).reverse();\n\n        // Remove leading zeros\n        while(bytes[bytes.length-1] === 0) {\n          bytes.pop();\n        }\n\n        // Add the right number of leading zeros\n        for (i = 0; input[i] === alphabet[0]; i++) {\n          bytes.push(0);\n        }\n\n        bytes.reverse();\n\n        return bytes;\n      },\n\n      // --> input: Array\n      // <-- String\n      encode_base_check: function (version, input, alphabet) {\n        var buffer  = [].concat(version, input);\n        var check   = SHA256(SHA256(buffer)).slice(0, 4);\n        return Base58Utils.encode_base([].concat(buffer, check), alphabet);\n      },\n\n      // --> input : String\n      // <-- NaN || BigInteger\n      decode_base_check: function (version, input, alphabet) {\n        var buffer = Base58Utils.decode_base(input, alphabet);\n\n        if (!buffer || buffer[0] !== version || buffer.length < 5) {\n          return NaN;\n        }\n\n        var computed = SHA256(SHA256(buffer.slice(0, -4))).slice(0, 4),\n            checksum = buffer.slice(-4);\n\n        var i;\n        for (i = 0; i != 4; i += 1)\n          if (computed[i] !== checksum[i])\n            return NaN;\n\n        return buffer.slice(1, -4);\n      }\n    };\n  })();\n  return Base58Utils;\n};\n\n\n// WEBPACK FOOTER\n// module.id = 58\n// module.readableIdentifier = ./~/ripple-wallet-generator/lib/base58.js\n//@ sourceURL=webpack-module:///./~/ripple-wallet-generator/lib/base58.js");

/***/ },
/* 59 */
/***/ function(module, exports, __webpack_require__) {

	eval("module.exports = function(options) {\n  var sjcl = options.sjcl;\n  var base58 = __webpack_require__(58)({ sjcl: sjcl });\n\n  function MasterKey(key){ \n    this.value = key;\n  };\n\n  MasterKey.fromBytes = function(bytes){\n    return new MasterKey(base58.encode_base_check(33, bytes));\n  };\n\n  MasterKey.getRandom = function(){\n    for (var i = 0; i < 8; i++) {\n      sjcl.random.addEntropy(Math.random(), 32, \"Math.random()\");\n    }\n    var randomBytes = sjcl.codec.bytes.fromBits(sjcl.random.randomWords(4));\n    return MasterKey.fromBytes(randomBytes);\n  };\n  return MasterKey;\n}\n\n\n// WEBPACK FOOTER\n// module.id = 59\n// module.readableIdentifier = ./~/ripple-wallet-generator/lib/master_key.js\n//@ sourceURL=webpack-module:///./~/ripple-wallet-generator/lib/master_key.js");

/***/ },
/* 60 */
/***/ function(module, exports, __webpack_require__) {

	eval("\nmodule.exports = function(options) { // inject sjcl dependency\n  var sjcl = options.sjcl\n  var base58 = __webpack_require__(58)({ sjcl: sjcl });\n\n\n  function SHA256_RIPEMD160(bits) {\n    return sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits));\n  }\n\n  function RippleAddress(address){\n    this.value = address;\n  }\n\n  RippleAddress.fromPublicKey = function(publicKey){\n    /* Encode the EC public key as a ripple address \n       using SHA256 and then RIPEMD160\n    */\n    var publicKeyBytes = sjcl.codec.bytes.fromBits(SHA256_RIPEMD160(sjcl.codec.bytes.toBits(publicKey.toBytesCompressed())));\n    return new this(base58.encode_base_check(0, publicKeyBytes));\n  }\n\n  return RippleAddress;\n}\n\n\n// WEBPACK FOOTER\n// module.id = 60\n// module.readableIdentifier = ./~/ripple-wallet-generator/lib/ripple_address.js\n//@ sourceURL=webpack-module:///./~/ripple-wallet-generator/lib/ripple_address.js");

/***/ },
/* 61 */
/***/ function(module, exports, __webpack_require__) {

	eval("module.exports = function(options) { // inject sjcl dependency\n  var sjcl = options.sjcl; \n\n  function PublicGenerator(eccPoint) {\n    if (eccPoint instanceof sjcl.ecc.point) {\n      this.value = eccPoint;\n    } else {\n      throw new Error('eccPoint must be a sjcl.ecc.point'); \n    }\n  }\n\n  PublicGenerator.fromPrivateGenerator = function(privateGenerator) {\n    /* Compute the public generator using from the \n       private generator on the elliptic curve\n    */\n    return new this(sjcl.ecc.curves.c256.G.mult(privateGenerator));\n  };\n\n  PublicGenerator.prototype = {\n    toString: function() {\n      return this.value.toString();\n    }\n  }\n\n  return PublicGenerator;\n}\n\n\n\n// WEBPACK FOOTER\n// module.id = 61\n// module.readableIdentifier = ./~/ripple-wallet-generator/lib/public_generator.js\n//@ sourceURL=webpack-module:///./~/ripple-wallet-generator/lib/public_generator.js");

/***/ },
/* 62 */
/***/ function(module, exports, __webpack_require__) {

	eval("// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            var source = ev.source;\n            if ((source === window || source === null) && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n\n// WEBPACK FOOTER\n// module.id = 62\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/process/browser.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/process/browser.js");

/***/ },
/* 63 */
/***/ function(module, exports, __webpack_require__) {

	eval("// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\n// If obj.hasOwnProperty has been overridden, then calling\n// obj.hasOwnProperty(prop) will break.\n// See: https://github.com/joyent/node/issues/1707\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\nmodule.exports = function(qs, sep, eq, options) {\n  sep = sep || '&';\n  eq = eq || '=';\n  var obj = {};\n\n  if (typeof qs !== 'string' || qs.length === 0) {\n    return obj;\n  }\n\n  var regexp = /\\+/g;\n  qs = qs.split(sep);\n\n  var maxKeys = 1000;\n  if (options && typeof options.maxKeys === 'number') {\n    maxKeys = options.maxKeys;\n  }\n\n  var len = qs.length;\n  // maxKeys <= 0 means that we should not limit keys count\n  if (maxKeys > 0 && len > maxKeys) {\n    len = maxKeys;\n  }\n\n  for (var i = 0; i < len; ++i) {\n    var x = qs[i].replace(regexp, '%20'),\n        idx = x.indexOf(eq),\n        kstr, vstr, k, v;\n\n    if (idx >= 0) {\n      kstr = x.substr(0, idx);\n      vstr = x.substr(idx + 1);\n    } else {\n      kstr = x;\n      vstr = '';\n    }\n\n    k = decodeURIComponent(kstr);\n    v = decodeURIComponent(vstr);\n\n    if (!hasOwnProperty(obj, k)) {\n      obj[k] = v;\n    } else if (isArray(obj[k])) {\n      obj[k].push(v);\n    } else {\n      obj[k] = [obj[k], v];\n    }\n  }\n\n  return obj;\n};\n\nvar isArray = Array.isArray || function (xs) {\n  return Object.prototype.toString.call(xs) === '[object Array]';\n};\n\n\n// WEBPACK FOOTER\n// module.id = 63\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/querystring-es3/decode.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/querystring-es3/decode.js");

/***/ },
/* 64 */
/***/ function(module, exports, __webpack_require__) {

	eval("// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nvar stringifyPrimitive = function(v) {\n  switch (typeof v) {\n    case 'string':\n      return v;\n\n    case 'boolean':\n      return v ? 'true' : 'false';\n\n    case 'number':\n      return isFinite(v) ? v : '';\n\n    default:\n      return '';\n  }\n};\n\nmodule.exports = function(obj, sep, eq, name) {\n  sep = sep || '&';\n  eq = eq || '=';\n  if (obj === null) {\n    obj = undefined;\n  }\n\n  if (typeof obj === 'object') {\n    return map(objectKeys(obj), function(k) {\n      var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;\n      if (isArray(obj[k])) {\n        return map(obj[k], function(v) {\n          return ks + encodeURIComponent(stringifyPrimitive(v));\n        }).join(sep);\n      } else {\n        return ks + encodeURIComponent(stringifyPrimitive(obj[k]));\n      }\n    }).join(sep);\n\n  }\n\n  if (!name) return '';\n  return encodeURIComponent(stringifyPrimitive(name)) + eq +\n         encodeURIComponent(stringifyPrimitive(obj));\n};\n\nvar isArray = Array.isArray || function (xs) {\n  return Object.prototype.toString.call(xs) === '[object Array]';\n};\n\nfunction map (xs, f) {\n  if (xs.map) return xs.map(f);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    res.push(f(xs[i], i));\n  }\n  return res;\n}\n\nvar objectKeys = Object.keys || function (obj) {\n  var res = [];\n  for (var key in obj) {\n    if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);\n  }\n  return res;\n};\n\n\n// WEBPACK FOOTER\n// module.id = 64\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/querystring-es3/encode.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/querystring-es3/encode.js");

/***/ },
/* 65 */
/***/ function(module, exports, __webpack_require__) {

	eval("exports.read = function(buffer, offset, isLE, mLen, nBytes) {\n  var e, m,\n      eLen = nBytes * 8 - mLen - 1,\n      eMax = (1 << eLen) - 1,\n      eBias = eMax >> 1,\n      nBits = -7,\n      i = isLE ? (nBytes - 1) : 0,\n      d = isLE ? -1 : 1,\n      s = buffer[offset + i];\n\n  i += d;\n\n  e = s & ((1 << (-nBits)) - 1);\n  s >>= (-nBits);\n  nBits += eLen;\n  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);\n\n  m = e & ((1 << (-nBits)) - 1);\n  e >>= (-nBits);\n  nBits += mLen;\n  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);\n\n  if (e === 0) {\n    e = 1 - eBias;\n  } else if (e === eMax) {\n    return m ? NaN : ((s ? -1 : 1) * Infinity);\n  } else {\n    m = m + Math.pow(2, mLen);\n    e = e - eBias;\n  }\n  return (s ? -1 : 1) * m * Math.pow(2, e - mLen);\n};\n\nexports.write = function(buffer, value, offset, isLE, mLen, nBytes) {\n  var e, m, c,\n      eLen = nBytes * 8 - mLen - 1,\n      eMax = (1 << eLen) - 1,\n      eBias = eMax >> 1,\n      rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),\n      i = isLE ? 0 : (nBytes - 1),\n      d = isLE ? 1 : -1,\n      s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;\n\n  value = Math.abs(value);\n\n  if (isNaN(value) || value === Infinity) {\n    m = isNaN(value) ? 1 : 0;\n    e = eMax;\n  } else {\n    e = Math.floor(Math.log(value) / Math.LN2);\n    if (value * (c = Math.pow(2, -e)) < 1) {\n      e--;\n      c *= 2;\n    }\n    if (e + eBias >= 1) {\n      value += rt / c;\n    } else {\n      value += rt * Math.pow(2, 1 - eBias);\n    }\n    if (value * c >= 2) {\n      e++;\n      c /= 2;\n    }\n\n    if (e + eBias >= eMax) {\n      m = 0;\n      e = eMax;\n    } else if (e + eBias >= 1) {\n      m = (value * c - 1) * Math.pow(2, mLen);\n      e = e + eBias;\n    } else {\n      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);\n      e = 0;\n    }\n  }\n\n  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);\n\n  e = (e << mLen) | m;\n  eLen += mLen;\n  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);\n\n  buffer[offset + i - d] |= s * 128;\n};\n\n\n// WEBPACK FOOTER\n// module.id = 65\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/buffer/~/ieee754/index.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/buffer/~/ieee754/index.js");

/***/ },
/* 66 */
/***/ function(module, exports, __webpack_require__) {

	eval("/*\n * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message\n * Digest Algorithm, as defined in RFC 1321.\n * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.\n * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\n * Distributed under the BSD License\n * See http://pajhome.org.uk/crypt/md5 for more info.\n */\n\nvar helpers = __webpack_require__(74);\n\n/*\n * Calculate the MD5 of an array of little-endian words, and a bit length\n */\nfunction core_md5(x, len)\n{\n  /* append padding */\n  x[len >> 5] |= 0x80 << ((len) % 32);\n  x[(((len + 64) >>> 9) << 4) + 14] = len;\n\n  var a =  1732584193;\n  var b = -271733879;\n  var c = -1732584194;\n  var d =  271733878;\n\n  for(var i = 0; i < x.length; i += 16)\n  {\n    var olda = a;\n    var oldb = b;\n    var oldc = c;\n    var oldd = d;\n\n    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);\n    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);\n    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);\n    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);\n    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);\n    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);\n    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);\n    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);\n    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);\n    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);\n    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);\n    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);\n    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);\n    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);\n    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);\n    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);\n\n    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);\n    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);\n    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);\n    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);\n    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);\n    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);\n    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);\n    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);\n    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);\n    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);\n    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);\n    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);\n    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);\n    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);\n    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);\n    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);\n\n    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);\n    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);\n    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);\n    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);\n    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);\n    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);\n    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);\n    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);\n    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);\n    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);\n    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);\n    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);\n    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);\n    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);\n    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);\n    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);\n\n    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);\n    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);\n    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);\n    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);\n    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);\n    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);\n    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);\n    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);\n    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);\n    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);\n    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);\n    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);\n    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);\n    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);\n    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);\n    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);\n\n    a = safe_add(a, olda);\n    b = safe_add(b, oldb);\n    c = safe_add(c, oldc);\n    d = safe_add(d, oldd);\n  }\n  return Array(a, b, c, d);\n\n}\n\n/*\n * These functions implement the four basic operations the algorithm uses.\n */\nfunction md5_cmn(q, a, b, x, s, t)\n{\n  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);\n}\nfunction md5_ff(a, b, c, d, x, s, t)\n{\n  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);\n}\nfunction md5_gg(a, b, c, d, x, s, t)\n{\n  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);\n}\nfunction md5_hh(a, b, c, d, x, s, t)\n{\n  return md5_cmn(b ^ c ^ d, a, b, x, s, t);\n}\nfunction md5_ii(a, b, c, d, x, s, t)\n{\n  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);\n}\n\n/*\n * Add integers, wrapping at 2^32. This uses 16-bit operations internally\n * to work around bugs in some JS interpreters.\n */\nfunction safe_add(x, y)\n{\n  var lsw = (x & 0xFFFF) + (y & 0xFFFF);\n  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n  return (msw << 16) | (lsw & 0xFFFF);\n}\n\n/*\n * Bitwise rotate a 32-bit number to the left.\n */\nfunction bit_rol(num, cnt)\n{\n  return (num << cnt) | (num >>> (32 - cnt));\n}\n\nmodule.exports = function md5(buf) {\n  return helpers.hash(buf, core_md5, 16);\n};\n\n\n// WEBPACK FOOTER\n// module.id = 66\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/md5.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/md5.js");

/***/ },
/* 67 */
/***/ function(module, exports, __webpack_require__) {

	eval("if (typeof Object.create === 'function') {\n  // implementation from standard node.js 'util' module\n  module.exports = function inherits(ctor, superCtor) {\n    ctor.super_ = superCtor\n    ctor.prototype = Object.create(superCtor.prototype, {\n      constructor: {\n        value: ctor,\n        enumerable: false,\n        writable: true,\n        configurable: true\n      }\n    });\n  };\n} else {\n  // old school shim for old browsers\n  module.exports = function inherits(ctor, superCtor) {\n    ctor.super_ = superCtor\n    var TempCtor = function () {}\n    TempCtor.prototype = superCtor.prototype\n    ctor.prototype = new TempCtor()\n    ctor.prototype.constructor = ctor\n  }\n}\n\n\n// WEBPACK FOOTER\n// module.id = 67\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/util/~/inherits/inherits_browser.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/util/~/inherits/inherits_browser.js");

/***/ },
/* 68 */
/***/ function(module, exports, __webpack_require__) {

	eval("var __WEBPACK_AMD_DEFINE_RESULT__;// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// Query String Utilities\n\n!(__WEBPACK_AMD_DEFINE_RESULT__ = (function(require, exports, module, undefined) {\n\"use strict\";\n\nvar QueryString = exports;\n\nfunction charCode(c) {\n  return c.charCodeAt(0);\n}\n\nQueryString.unescape = decodeURIComponent;\nQueryString.escape = encodeURIComponent;\n\nvar stringifyPrimitive = function(v) {\n  switch (typeof v) {\n    case 'string':\n      return v;\n\n    case 'boolean':\n      return v ? 'true' : 'false';\n\n    case 'number':\n      return isFinite(v) ? v : '';\n\n    default:\n      return '';\n  }\n};\n\n\nQueryString.stringify = QueryString.encode = function(obj, sep, eq, name) {\n  sep = sep || '&';\n  eq = eq || '=';\n  obj = (obj === null) ? undefined : obj;\n\n  switch (typeof obj) {\n    case 'object':\n      return Object.keys(obj).map(function(k) {\n        if (Array.isArray(obj[k])) {\n          return obj[k].map(function(v) {\n            return QueryString.escape(stringifyPrimitive(k)) +\n                   eq +\n                   QueryString.escape(stringifyPrimitive(v));\n          }).join(sep);\n        } else {\n          return QueryString.escape(stringifyPrimitive(k)) +\n                 eq +\n                 QueryString.escape(stringifyPrimitive(obj[k]));\n        }\n      }).join(sep);\n\n    default:\n      if (!name) return '';\n      return QueryString.escape(stringifyPrimitive(name)) + eq +\n             QueryString.escape(stringifyPrimitive(obj));\n  }\n};\n\n// Parse a key=val string.\nQueryString.parse = QueryString.decode = function(qs, sep, eq) {\n  sep = sep || '&';\n  eq = eq || '=';\n  var obj = {};\n\n  if (typeof qs !== 'string' || qs.length === 0) {\n    return obj;\n  }\n\n  qs.split(sep).forEach(function(kvp) {\n    var x = kvp.split(eq);\n    var k = QueryString.unescape(x[0], true);\n    var v = QueryString.unescape(x.slice(1).join(eq), true);\n\n    if (!(k in obj)) {\n      obj[k] = v;\n    } else if (!Array.isArray(obj[k])) {\n      obj[k] = [obj[k], v];\n    } else {\n      obj[k].push(v);\n    }\n  });\n\n  return obj;\n};\n\n}.call(exports, __webpack_require__, exports, module)), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\n\n// WEBPACK FOOTER\n// module.id = 68\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/url/~/querystring/querystring.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/url/~/querystring/querystring.js");

/***/ },
/* 69 */
/***/ function(module, exports, __webpack_require__) {

	eval("var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;var require;/* WEBPACK VAR INJECTION */(function(module) {/*! http://mths.be/punycode by @mathias */\n;(function(root) {\n\n\t/**\n\t * The `punycode` object.\n\t * @name punycode\n\t * @type Object\n\t */\n\tvar punycode,\n\n\t/** Detect free variables `define`, `exports`, `module` and `require` */\n\tfreeDefine = __webpack_require__(79),\n\tfreeExports = typeof exports == 'object' && exports,\n\tfreeModule = typeof module == 'object' && module,\n\tfreeRequire = typeof require == 'function' && require,\n\n\t/** Highest positive signed 32-bit float value */\n\tmaxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1\n\n\t/** Bootstring parameters */\n\tbase = 36,\n\ttMin = 1,\n\ttMax = 26,\n\tskew = 38,\n\tdamp = 700,\n\tinitialBias = 72,\n\tinitialN = 128, // 0x80\n\tdelimiter = '-', // '\\x2D'\n\n\t/** Regular expressions */\n\tregexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars\n\tregexPunycode = /^xn--/,\n\n\t/** Error messages */\n\terrors = {\n\t\t'overflow': 'Overflow: input needs wider integers to process.',\n\t\t'ucs2decode': 'UCS-2(decode): illegal sequence',\n\t\t'ucs2encode': 'UCS-2(encode): illegal value',\n\t\t'not-basic': 'Illegal input >= 0x80 (not a basic code point)',\n\t\t'invalid-input': 'Invalid input'\n\t},\n\n\t/** Convenience shortcuts */\n\tbaseMinusTMin = base - tMin,\n\tfloor = Math.floor,\n\tstringFromCharCode = String.fromCharCode,\n\n\t/** Temporary variable */\n\tkey;\n\n\t/*--------------------------------------------------------------------------*/\n\n\t/**\n\t * A generic error utility function.\n\t * @private\n\t * @param {String} type The error type.\n\t * @returns {Error} Throws a `RangeError` with the applicable error message.\n\t */\n\tfunction error(type) {\n\t\tthrow RangeError(errors[type]);\n\t}\n\n\t/**\n\t * A generic `Array#map` utility function.\n\t * @private\n\t * @param {Array} array The array to iterate over.\n\t * @param {Function} callback The function that gets called for every array\n\t * item.\n\t * @returns {Array} A new array of values returned by the callback function.\n\t */\n\tfunction map(array, fn) {\n\t\tvar length = array.length;\n\t\twhile (length--) {\n\t\t\tarray[length] = fn(array[length]);\n\t\t}\n\t\treturn array;\n\t}\n\n\t/**\n\t * A simple `Array#map`-like wrapper to work with domain name strings.\n\t * @private\n\t * @param {String} domain The domain name.\n\t * @param {Function} callback The function that gets called for every\n\t * character.\n\t * @returns {Array} A new string of characters returned by the callback\n\t * function.\n\t */\n\tfunction mapDomain(string, fn) {\n\t\tvar glue = '.';\n\t\treturn map(string.split(glue), fn).join(glue);\n\t}\n\n\t/**\n\t * Creates an array containing the decimal code points of each Unicode\n\t * character in the string. While JavaScript uses UCS-2 internally,\n\t * this function will convert a pair of surrogate halves (each of which\n\t * UCS-2 exposes as separate characters) into a single code point,\n\t * matching UTF-16.\n\t * @see `punycode.ucs2.encode`\n\t * @see <http://mathiasbynens.be/notes/javascript-encoding>\n\t * @memberOf punycode.ucs2\n\t * @name decode\n\t * @param {String} string The Unicode input string (UCS-2).\n\t * @returns {Array} The new array of code points.\n\t */\n\tfunction ucs2decode(string) {\n\t\tvar output = [],\n\t\t    counter = 0,\n\t\t    length = string.length,\n\t\t    value,\n\t\t    extra;\n\t\twhile (counter < length) {\n\t\t\tvalue = string.charCodeAt(counter++);\n\t\t\tif ((value & 0xF800) == 0xD800) {\n\t\t\t\textra = string.charCodeAt(counter++);\n\t\t\t\tif ((value & 0xFC00) != 0xD800 || (extra & 0xFC00) != 0xDC00) {\n\t\t\t\t\terror('ucs2decode');\n\t\t\t\t}\n\t\t\t\tvalue = ((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000;\n\t\t\t}\n\t\t\toutput.push(value);\n\t\t}\n\t\treturn output;\n\t}\n\n\t/**\n\t * Creates a string based on an array of decimal code points.\n\t * @see `punycode.ucs2.decode`\n\t * @memberOf punycode.ucs2\n\t * @name encode\n\t * @param {Array} codePoints The array of decimal code points.\n\t * @returns {String} The new Unicode string (UCS-2).\n\t */\n\tfunction ucs2encode(array) {\n\t\treturn map(array, function(value) {\n\t\t\tvar output = '';\n\t\t\tif ((value & 0xF800) == 0xD800) {\n\t\t\t\terror('ucs2encode');\n\t\t\t}\n\t\t\tif (value > 0xFFFF) {\n\t\t\t\tvalue -= 0x10000;\n\t\t\t\toutput += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);\n\t\t\t\tvalue = 0xDC00 | value & 0x3FF;\n\t\t\t}\n\t\t\toutput += stringFromCharCode(value);\n\t\t\treturn output;\n\t\t}).join('');\n\t}\n\n\t/**\n\t * Converts a basic code point into a digit/integer.\n\t * @see `digitToBasic()`\n\t * @private\n\t * @param {Number} codePoint The basic (decimal) code point.\n\t * @returns {Number} The numeric value of a basic code point (for use in\n\t * representing integers) in the range `0` to `base - 1`, or `base` if\n\t * the code point does not represent a value.\n\t */\n\tfunction basicToDigit(codePoint) {\n\t\treturn codePoint - 48 < 10\n\t\t\t? codePoint - 22\n\t\t\t: codePoint - 65 < 26\n\t\t\t\t? codePoint - 65\n\t\t\t\t: codePoint - 97 < 26\n\t\t\t\t\t? codePoint - 97\n\t\t\t\t\t: base;\n\t}\n\n\t/**\n\t * Converts a digit/integer into a basic code point.\n\t * @see `basicToDigit()`\n\t * @private\n\t * @param {Number} digit The numeric value of a basic code point.\n\t * @returns {Number} The basic code point whose value (when used for\n\t * representing integers) is `digit`, which needs to be in the range\n\t * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is\n\t * used; else, the lowercase form is used. The behavior is undefined\n\t * if flag is non-zero and `digit` has no uppercase form.\n\t */\n\tfunction digitToBasic(digit, flag) {\n\t\t//  0..25 map to ASCII a..z or A..Z\n\t\t// 26..35 map to ASCII 0..9\n\t\treturn digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);\n\t}\n\n\t/**\n\t * Bias adaptation function as per section 3.4 of RFC 3492.\n\t * http://tools.ietf.org/html/rfc3492#section-3.4\n\t * @private\n\t */\n\tfunction adapt(delta, numPoints, firstTime) {\n\t\tvar k = 0;\n\t\tdelta = firstTime ? floor(delta / damp) : delta >> 1;\n\t\tdelta += floor(delta / numPoints);\n\t\tfor (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {\n\t\t\tdelta = floor(delta / baseMinusTMin);\n\t\t}\n\t\treturn floor(k + (baseMinusTMin + 1) * delta / (delta + skew));\n\t}\n\n\t/**\n\t * Converts a basic code point to lowercase is `flag` is falsy, or to\n\t * uppercase if `flag` is truthy. The code point is unchanged if it's\n\t * caseless. The behavior is undefined if `codePoint` is not a basic code\n\t * point.\n\t * @private\n\t * @param {Number} codePoint The numeric value of a basic code point.\n\t * @returns {Number} The resulting basic code point.\n\t */\n\tfunction encodeBasic(codePoint, flag) {\n\t\tcodePoint -= (codePoint - 97 < 26) << 5;\n\t\treturn codePoint + (!flag && codePoint - 65 < 26) << 5;\n\t}\n\n\t/**\n\t * Converts a Punycode string of ASCII code points to a string of Unicode\n\t * code points.\n\t * @memberOf punycode\n\t * @param {String} input The Punycode string of ASCII code points.\n\t * @returns {String} The resulting string of Unicode code points.\n\t */\n\tfunction decode(input) {\n\t\t// Don't use UCS-2\n\t\tvar output = [],\n\t\t    inputLength = input.length,\n\t\t    out,\n\t\t    i = 0,\n\t\t    n = initialN,\n\t\t    bias = initialBias,\n\t\t    basic,\n\t\t    j,\n\t\t    index,\n\t\t    oldi,\n\t\t    w,\n\t\t    k,\n\t\t    digit,\n\t\t    t,\n\t\t    length,\n\t\t    /** Cached calculation results */\n\t\t    baseMinusT;\n\n\t\t// Handle the basic code points: let `basic` be the number of input code\n\t\t// points before the last delimiter, or `0` if there is none, then copy\n\t\t// the first basic code points to the output.\n\n\t\tbasic = input.lastIndexOf(delimiter);\n\t\tif (basic < 0) {\n\t\t\tbasic = 0;\n\t\t}\n\n\t\tfor (j = 0; j < basic; ++j) {\n\t\t\t// if it's not a basic code point\n\t\t\tif (input.charCodeAt(j) >= 0x80) {\n\t\t\t\terror('not-basic');\n\t\t\t}\n\t\t\toutput.push(input.charCodeAt(j));\n\t\t}\n\n\t\t// Main decoding loop: start just after the last delimiter if any basic code\n\t\t// points were copied; start at the beginning otherwise.\n\n\t\tfor (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {\n\n\t\t\t// `index` is the index of the next character to be consumed.\n\t\t\t// Decode a generalized variable-length integer into `delta`,\n\t\t\t// which gets added to `i`. The overflow checking is easier\n\t\t\t// if we increase `i` as we go, then subtract off its starting\n\t\t\t// value at the end to obtain `delta`.\n\t\t\tfor (oldi = i, w = 1, k = base; /* no condition */; k += base) {\n\n\t\t\t\tif (index >= inputLength) {\n\t\t\t\t\terror('invalid-input');\n\t\t\t\t}\n\n\t\t\t\tdigit = basicToDigit(input.charCodeAt(index++));\n\n\t\t\t\tif (digit >= base || digit > floor((maxInt - i) / w)) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\ti += digit * w;\n\t\t\t\tt = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\n\t\t\t\tif (digit < t) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tbaseMinusT = base - t;\n\t\t\t\tif (w > floor(maxInt / baseMinusT)) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\tw *= baseMinusT;\n\n\t\t\t}\n\n\t\t\tout = output.length + 1;\n\t\t\tbias = adapt(i - oldi, out, oldi == 0);\n\n\t\t\t// `i` was supposed to wrap around from `out` to `0`,\n\t\t\t// incrementing `n` each time, so we'll fix that now:\n\t\t\tif (floor(i / out) > maxInt - n) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\tn += floor(i / out);\n\t\t\ti %= out;\n\n\t\t\t// Insert `n` at position `i` of the output\n\t\t\toutput.splice(i++, 0, n);\n\n\t\t}\n\n\t\treturn ucs2encode(output);\n\t}\n\n\t/**\n\t * Converts a string of Unicode code points to a Punycode string of ASCII\n\t * code points.\n\t * @memberOf punycode\n\t * @param {String} input The string of Unicode code points.\n\t * @returns {String} The resulting Punycode string of ASCII code points.\n\t */\n\tfunction encode(input) {\n\t\tvar n,\n\t\t    delta,\n\t\t    handledCPCount,\n\t\t    basicLength,\n\t\t    bias,\n\t\t    j,\n\t\t    m,\n\t\t    q,\n\t\t    k,\n\t\t    t,\n\t\t    currentValue,\n\t\t    output = [],\n\t\t    /** `inputLength` will hold the number of code points in `input`. */\n\t\t    inputLength,\n\t\t    /** Cached calculation results */\n\t\t    handledCPCountPlusOne,\n\t\t    baseMinusT,\n\t\t    qMinusT;\n\n\t\t// Convert the input in UCS-2 to Unicode\n\t\tinput = ucs2decode(input);\n\n\t\t// Cache the length\n\t\tinputLength = input.length;\n\n\t\t// Initialize the state\n\t\tn = initialN;\n\t\tdelta = 0;\n\t\tbias = initialBias;\n\n\t\t// Handle the basic code points\n\t\tfor (j = 0; j < inputLength; ++j) {\n\t\t\tcurrentValue = input[j];\n\t\t\tif (currentValue < 0x80) {\n\t\t\t\toutput.push(stringFromCharCode(currentValue));\n\t\t\t}\n\t\t}\n\n\t\thandledCPCount = basicLength = output.length;\n\n\t\t// `handledCPCount` is the number of code points that have been handled;\n\t\t// `basicLength` is the number of basic code points.\n\n\t\t// Finish the basic string - if it is not empty - with a delimiter\n\t\tif (basicLength) {\n\t\t\toutput.push(delimiter);\n\t\t}\n\n\t\t// Main encoding loop:\n\t\twhile (handledCPCount < inputLength) {\n\n\t\t\t// All non-basic code points < n have been handled already. Find the next\n\t\t\t// larger one:\n\t\t\tfor (m = maxInt, j = 0; j < inputLength; ++j) {\n\t\t\t\tcurrentValue = input[j];\n\t\t\t\tif (currentValue >= n && currentValue < m) {\n\t\t\t\t\tm = currentValue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,\n\t\t\t// but guard against overflow\n\t\t\thandledCPCountPlusOne = handledCPCount + 1;\n\t\t\tif (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\tdelta += (m - n) * handledCPCountPlusOne;\n\t\t\tn = m;\n\n\t\t\tfor (j = 0; j < inputLength; ++j) {\n\t\t\t\tcurrentValue = input[j];\n\n\t\t\t\tif (currentValue < n && ++delta > maxInt) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\tif (currentValue == n) {\n\t\t\t\t\t// Represent delta as a generalized variable-length integer\n\t\t\t\t\tfor (q = delta, k = base; /* no condition */; k += base) {\n\t\t\t\t\t\tt = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\t\t\t\t\t\tif (q < t) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tqMinusT = q - t;\n\t\t\t\t\t\tbaseMinusT = base - t;\n\t\t\t\t\t\toutput.push(\n\t\t\t\t\t\t\tstringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))\n\t\t\t\t\t\t);\n\t\t\t\t\t\tq = floor(qMinusT / baseMinusT);\n\t\t\t\t\t}\n\n\t\t\t\t\toutput.push(stringFromCharCode(digitToBasic(q, 0)));\n\t\t\t\t\tbias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);\n\t\t\t\t\tdelta = 0;\n\t\t\t\t\t++handledCPCount;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t++delta;\n\t\t\t++n;\n\n\t\t}\n\t\treturn output.join('');\n\t}\n\n\t/**\n\t * Converts a Punycode string representing a domain name to Unicode. Only the\n\t * Punycoded parts of the domain name will be converted, i.e. it doesn't\n\t * matter if you call it on a string that has already been converted to\n\t * Unicode.\n\t * @memberOf punycode\n\t * @param {String} domain The Punycode domain name to convert to Unicode.\n\t * @returns {String} The Unicode representation of the given Punycode\n\t * string.\n\t */\n\tfunction toUnicode(domain) {\n\t\treturn mapDomain(domain, function(string) {\n\t\t\treturn regexPunycode.test(string)\n\t\t\t\t? decode(string.slice(4).toLowerCase())\n\t\t\t\t: string;\n\t\t});\n\t}\n\n\t/**\n\t * Converts a Unicode string representing a domain name to Punycode. Only the\n\t * non-ASCII parts of the domain name will be converted, i.e. it doesn't\n\t * matter if you call it with a domain that's already in ASCII.\n\t * @memberOf punycode\n\t * @param {String} domain The domain name to convert, as a Unicode string.\n\t * @returns {String} The Punycode representation of the given domain name.\n\t */\n\tfunction toASCII(domain) {\n\t\treturn mapDomain(domain, function(string) {\n\t\t\treturn regexNonASCII.test(string)\n\t\t\t\t? 'xn--' + encode(string)\n\t\t\t\t: string;\n\t\t});\n\t}\n\n\t/*--------------------------------------------------------------------------*/\n\n\t/** Define the public API */\n\tpunycode = {\n\t\t/**\n\t\t * A string representing the current Punycode.js version number.\n\t\t * @memberOf punycode\n\t\t * @type String\n\t\t */\n\t\t'version': '1.0.0',\n\t\t/**\n\t\t * An object of methods to convert from JavaScript's internal character\n\t\t * representation (UCS-2) to decimal Unicode code points, and back.\n\t\t * @see <http://mathiasbynens.be/notes/javascript-encoding>\n\t\t * @memberOf punycode\n\t\t * @type Object\n\t\t */\n\t\t'ucs2': {\n\t\t\t'decode': ucs2decode,\n\t\t\t'encode': ucs2encode\n\t\t},\n\t\t'decode': decode,\n\t\t'encode': encode,\n\t\t'toASCII': toASCII,\n\t\t'toUnicode': toUnicode\n\t};\n\n\t/** Expose `punycode` */\n\tif (freeExports) {\n\t\tif (freeModule && freeModule.exports == freeExports) {\n\t\t\t// in Node.js or Ringo 0.8+\n\t\t\tfreeModule.exports = punycode;\n\t\t} else {\n\t\t\t// in Narwhal or Ringo 0.7-\n\t\t\tfor (key in punycode) {\n\t\t\t\tpunycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);\n\t\t\t}\n\t\t}\n\t} else if (__webpack_require__(79)) {\n\t\t// via curl.js or RequireJS\n\t\t!(__WEBPACK_AMD_DEFINE_FACTORY__ = (punycode), (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_RESULT__ = __WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) : module.exports = __WEBPACK_AMD_DEFINE_FACTORY__));\n\t} else {\n\t\t// in a browser or Rhino\n\t\troot.punycode = punycode;\n\t}\n\n}(this));\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(80)(module)))\n\n// WEBPACK FOOTER\n// module.id = 69\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/url/~/punycode/punycode.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/url/~/punycode/punycode.js");

/***/ },
/* 70 */
/***/ function(module, exports, __webpack_require__) {

	eval("var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n;(function (exports) {\n\t'use strict';\n\n  var Arr = (typeof Uint8Array !== 'undefined')\n    ? Uint8Array\n    : Array\n\n\tvar PLUS   = '+'.charCodeAt(0)\n\tvar SLASH  = '/'.charCodeAt(0)\n\tvar NUMBER = '0'.charCodeAt(0)\n\tvar LOWER  = 'a'.charCodeAt(0)\n\tvar UPPER  = 'A'.charCodeAt(0)\n\n\tfunction decode (elt) {\n\t\tvar code = elt.charCodeAt(0)\n\t\tif (code === PLUS)\n\t\t\treturn 62 // '+'\n\t\tif (code === SLASH)\n\t\t\treturn 63 // '/'\n\t\tif (code < NUMBER)\n\t\t\treturn -1 //no match\n\t\tif (code < NUMBER + 10)\n\t\t\treturn code - NUMBER + 26 + 26\n\t\tif (code < UPPER + 26)\n\t\t\treturn code - UPPER\n\t\tif (code < LOWER + 26)\n\t\t\treturn code - LOWER + 26\n\t}\n\n\tfunction b64ToByteArray (b64) {\n\t\tvar i, j, l, tmp, placeHolders, arr\n\n\t\tif (b64.length % 4 > 0) {\n\t\t\tthrow new Error('Invalid string. Length must be a multiple of 4')\n\t\t}\n\n\t\t// the number of equal signs (place holders)\n\t\t// if there are two placeholders, than the two characters before it\n\t\t// represent one byte\n\t\t// if there is only one, then the three characters before it represent 2 bytes\n\t\t// this is just a cheap hack to not do indexOf twice\n\t\tvar len = b64.length\n\t\tplaceHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0\n\n\t\t// base64 is 4/3 + up to two characters of the original data\n\t\tarr = new Arr(b64.length * 3 / 4 - placeHolders)\n\n\t\t// if there are placeholders, only get up to the last complete 4 chars\n\t\tl = placeHolders > 0 ? b64.length - 4 : b64.length\n\n\t\tvar L = 0\n\n\t\tfunction push (v) {\n\t\t\tarr[L++] = v\n\t\t}\n\n\t\tfor (i = 0, j = 0; i < l; i += 4, j += 3) {\n\t\t\ttmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))\n\t\t\tpush((tmp & 0xFF0000) >> 16)\n\t\t\tpush((tmp & 0xFF00) >> 8)\n\t\t\tpush(tmp & 0xFF)\n\t\t}\n\n\t\tif (placeHolders === 2) {\n\t\t\ttmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)\n\t\t\tpush(tmp & 0xFF)\n\t\t} else if (placeHolders === 1) {\n\t\t\ttmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)\n\t\t\tpush((tmp >> 8) & 0xFF)\n\t\t\tpush(tmp & 0xFF)\n\t\t}\n\n\t\treturn arr\n\t}\n\n\tfunction uint8ToBase64 (uint8) {\n\t\tvar i,\n\t\t\textraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes\n\t\t\toutput = \"\",\n\t\t\ttemp, length\n\n\t\tfunction encode (num) {\n\t\t\treturn lookup.charAt(num)\n\t\t}\n\n\t\tfunction tripletToBase64 (num) {\n\t\t\treturn encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)\n\t\t}\n\n\t\t// go through the array every three bytes, we'll deal with trailing stuff later\n\t\tfor (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {\n\t\t\ttemp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])\n\t\t\toutput += tripletToBase64(temp)\n\t\t}\n\n\t\t// pad the end with zeros, but make sure to not forget the extra bytes\n\t\tswitch (extraBytes) {\n\t\t\tcase 1:\n\t\t\t\ttemp = uint8[uint8.length - 1]\n\t\t\t\toutput += encode(temp >> 2)\n\t\t\t\toutput += encode((temp << 4) & 0x3F)\n\t\t\t\toutput += '=='\n\t\t\t\tbreak\n\t\t\tcase 2:\n\t\t\t\ttemp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])\n\t\t\t\toutput += encode(temp >> 10)\n\t\t\t\toutput += encode((temp >> 4) & 0x3F)\n\t\t\t\toutput += encode((temp << 2) & 0x3F)\n\t\t\t\toutput += '='\n\t\t\t\tbreak\n\t\t}\n\n\t\treturn output\n\t}\n\n\texports.toByteArray = b64ToByteArray\n\texports.fromByteArray = uint8ToBase64\n}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))\n\n\n// WEBPACK FOOTER\n// module.id = 70\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/buffer/~/base64-js/lib/b64.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/buffer/~/base64-js/lib/b64.js");

/***/ },
/* 71 */
/***/ function(module, exports, __webpack_require__) {

	eval("\n/**\n * Expose `Emitter`.\n */\n\nmodule.exports = Emitter;\n\n/**\n * Initialize a new `Emitter`.\n *\n * @api public\n */\n\nfunction Emitter(obj) {\n  if (obj) return mixin(obj);\n};\n\n/**\n * Mixin the emitter properties.\n *\n * @param {Object} obj\n * @return {Object}\n * @api private\n */\n\nfunction mixin(obj) {\n  for (var key in Emitter.prototype) {\n    obj[key] = Emitter.prototype[key];\n  }\n  return obj;\n}\n\n/**\n * Listen on the given `event` with `fn`.\n *\n * @param {String} event\n * @param {Function} fn\n * @return {Emitter}\n * @api public\n */\n\nEmitter.prototype.on =\nEmitter.prototype.addEventListener = function(event, fn){\n  this._callbacks = this._callbacks || {};\n  (this._callbacks[event] = this._callbacks[event] || [])\n    .push(fn);\n  return this;\n};\n\n/**\n * Adds an `event` listener that will be invoked a single\n * time then automatically removed.\n *\n * @param {String} event\n * @param {Function} fn\n * @return {Emitter}\n * @api public\n */\n\nEmitter.prototype.once = function(event, fn){\n  var self = this;\n  this._callbacks = this._callbacks || {};\n\n  function on() {\n    self.off(event, on);\n    fn.apply(this, arguments);\n  }\n\n  on.fn = fn;\n  this.on(event, on);\n  return this;\n};\n\n/**\n * Remove the given callback for `event` or all\n * registered callbacks.\n *\n * @param {String} event\n * @param {Function} fn\n * @return {Emitter}\n * @api public\n */\n\nEmitter.prototype.off =\nEmitter.prototype.removeListener =\nEmitter.prototype.removeAllListeners =\nEmitter.prototype.removeEventListener = function(event, fn){\n  this._callbacks = this._callbacks || {};\n\n  // all\n  if (0 == arguments.length) {\n    this._callbacks = {};\n    return this;\n  }\n\n  // specific event\n  var callbacks = this._callbacks[event];\n  if (!callbacks) return this;\n\n  // remove all handlers\n  if (1 == arguments.length) {\n    delete this._callbacks[event];\n    return this;\n  }\n\n  // remove specific handler\n  var cb;\n  for (var i = 0; i < callbacks.length; i++) {\n    cb = callbacks[i];\n    if (cb === fn || cb.fn === fn) {\n      callbacks.splice(i, 1);\n      break;\n    }\n  }\n  return this;\n};\n\n/**\n * Emit `event` with the given args.\n *\n * @param {String} event\n * @param {Mixed} ...\n * @return {Emitter}\n */\n\nEmitter.prototype.emit = function(event){\n  this._callbacks = this._callbacks || {};\n  var args = [].slice.call(arguments, 1)\n    , callbacks = this._callbacks[event];\n\n  if (callbacks) {\n    callbacks = callbacks.slice(0);\n    for (var i = 0, len = callbacks.length; i < len; ++i) {\n      callbacks[i].apply(this, args);\n    }\n  }\n\n  return this;\n};\n\n/**\n * Return array of callbacks for `event`.\n *\n * @param {String} event\n * @return {Array}\n * @api public\n */\n\nEmitter.prototype.listeners = function(event){\n  this._callbacks = this._callbacks || {};\n  return this._callbacks[event] || [];\n};\n\n/**\n * Check if this emitter has `event` handlers.\n *\n * @param {String} event\n * @return {Boolean}\n * @api public\n */\n\nEmitter.prototype.hasListeners = function(event){\n  return !! this.listeners(event).length;\n};\n\n\n// WEBPACK FOOTER\n// module.id = 71\n// module.readableIdentifier = ./~/superagent/~/component-emitter/index.js\n//@ sourceURL=webpack-module:///./~/superagent/~/component-emitter/index.js");

/***/ },
/* 72 */
/***/ function(module, exports, __webpack_require__) {

	eval("\n/**\n * Reduce `arr` with `fn`.\n *\n * @param {Array} arr\n * @param {Function} fn\n * @param {Mixed} initial\n *\n * TODO: combatible error handling?\n */\n\nmodule.exports = function(arr, fn, initial){  \n  var idx = 0;\n  var len = arr.length;\n  var curr = arguments.length == 3\n    ? initial\n    : arr[idx++];\n\n  while (idx < len) {\n    curr = fn.call(null, curr, arr[idx], ++idx, arr);\n  }\n  \n  return curr;\n};\n\n// WEBPACK FOOTER\n// module.id = 72\n// module.readableIdentifier = ./~/superagent/~/reduce-component/index.js\n//@ sourceURL=webpack-module:///./~/superagent/~/reduce-component/index.js");

/***/ },
/* 73 */
/***/ function(module, exports, __webpack_require__) {

	eval("var exports = module.exports = function (alg) {\n  var Alg = exports[alg]\n  if(!Alg) throw new Error(alg + ' is not supported (we accept pull requests)')\n  return new Alg()\n}\n\nvar Buffer = __webpack_require__(81).Buffer\nvar Hash   = __webpack_require__(76)(Buffer)\n\nexports.sha =\nexports.sha1 = __webpack_require__(77)(Buffer, Hash)\nexports.sha256 = __webpack_require__(78)(Buffer, Hash)\n\n\n// WEBPACK FOOTER\n// module.id = 73\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/index.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/index.js");

/***/ },
/* 74 */
/***/ function(module, exports, __webpack_require__) {

	eval("/* WEBPACK VAR INJECTION */(function(Buffer) {var intSize = 4;\nvar zeroBuffer = new Buffer(intSize); zeroBuffer.fill(0);\nvar chrsz = 8;\n\nfunction toArray(buf, bigEndian) {\n  if ((buf.length % intSize) !== 0) {\n    var len = buf.length + (intSize - (buf.length % intSize));\n    buf = Buffer.concat([buf, zeroBuffer], len);\n  }\n\n  var arr = [];\n  var fn = bigEndian ? buf.readInt32BE : buf.readInt32LE;\n  for (var i = 0; i < buf.length; i += intSize) {\n    arr.push(fn.call(buf, i));\n  }\n  return arr;\n}\n\nfunction toBuffer(arr, size, bigEndian) {\n  var buf = new Buffer(size);\n  var fn = bigEndian ? buf.writeInt32BE : buf.writeInt32LE;\n  for (var i = 0; i < arr.length; i++) {\n    fn.call(buf, arr[i], i * 4, true);\n  }\n  return buf;\n}\n\nfunction hash(buf, fn, hashSize, bigEndian) {\n  if (!Buffer.isBuffer(buf)) buf = new Buffer(buf);\n  var arr = fn(toArray(buf, bigEndian), buf.length * chrsz);\n  return toBuffer(arr, hashSize, bigEndian);\n}\n\nmodule.exports = { hash: hash };\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(41).Buffer))\n\n// WEBPACK FOOTER\n// module.id = 74\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/helpers.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/helpers.js");

/***/ },
/* 75 */
/***/ function(module, exports, __webpack_require__) {

	eval("/* WEBPACK VAR INJECTION */(function(Buffer) {\nmodule.exports = ripemd160\n\n\n\n/*\nCryptoJS v3.1.2\ncode.google.com/p/crypto-js\n(c) 2009-2013 by Jeff Mott. All rights reserved.\ncode.google.com/p/crypto-js/wiki/License\n*/\n/** @preserve\n(c) 2012 by Cédric Mesnil. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n    - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n    - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n// Constants table\nvar zl = [\n    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,\n    7,  4, 13,  1, 10,  6, 15,  3, 12,  0,  9,  5,  2, 14, 11,  8,\n    3, 10, 14,  4,  9, 15,  8,  1,  2,  7,  0,  6, 13, 11,  5, 12,\n    1,  9, 11, 10,  0,  8, 12,  4, 13,  3,  7, 15, 14,  5,  6,  2,\n    4,  0,  5,  9,  7, 12,  2, 10, 14,  1,  3,  8, 11,  6, 15, 13];\nvar zr = [\n    5, 14,  7,  0,  9,  2, 11,  4, 13,  6, 15,  8,  1, 10,  3, 12,\n    6, 11,  3,  7,  0, 13,  5, 10, 14, 15,  8, 12,  4,  9,  1,  2,\n    15,  5,  1,  3,  7, 14,  6,  9, 11,  8, 12,  2, 10,  0,  4, 13,\n    8,  6,  4,  1,  3, 11, 15,  0,  5, 12,  2, 13,  9,  7, 10, 14,\n    12, 15, 10,  4,  1,  5,  8,  7,  6,  2, 13, 14,  0,  3,  9, 11];\nvar sl = [\n     11, 14, 15, 12,  5,  8,  7,  9, 11, 13, 14, 15,  6,  7,  9,  8,\n    7, 6,   8, 13, 11,  9,  7, 15,  7, 12, 15,  9, 11,  7, 13, 12,\n    11, 13,  6,  7, 14,  9, 13, 15, 14,  8, 13,  6,  5, 12,  7,  5,\n      11, 12, 14, 15, 14, 15,  9,  8,  9, 14,  5,  6,  8,  6,  5, 12,\n    9, 15,  5, 11,  6,  8, 13, 12,  5, 12, 13, 14, 11,  8,  5,  6 ];\nvar sr = [\n    8,  9,  9, 11, 13, 15, 15,  5,  7,  7,  8, 11, 14, 14, 12,  6,\n    9, 13, 15,  7, 12,  8,  9, 11,  7,  7, 12,  7,  6, 15, 13, 11,\n    9,  7, 15, 11,  8,  6,  6, 14, 12, 13,  5, 14, 13, 13,  7,  5,\n    15,  5,  8, 11, 14, 14,  6, 14,  6,  9, 12,  9, 12,  5, 15,  8,\n    8,  5, 12,  9, 12,  5, 14,  6,  8, 13,  6,  5, 15, 13, 11, 11 ];\n\nvar hl =  [ 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E];\nvar hr =  [ 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000];\n\nvar bytesToWords = function (bytes) {\n  var words = [];\n  for (var i = 0, b = 0; i < bytes.length; i++, b += 8) {\n    words[b >>> 5] |= bytes[i] << (24 - b % 32);\n  }\n  return words;\n};\n\nvar wordsToBytes = function (words) {\n  var bytes = [];\n  for (var b = 0; b < words.length * 32; b += 8) {\n    bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);\n  }\n  return bytes;\n};\n\nvar processBlock = function (H, M, offset) {\n\n  // Swap endian\n  for (var i = 0; i < 16; i++) {\n    var offset_i = offset + i;\n    var M_offset_i = M[offset_i];\n\n    // Swap\n    M[offset_i] = (\n        (((M_offset_i << 8)  | (M_offset_i >>> 24)) & 0x00ff00ff) |\n        (((M_offset_i << 24) | (M_offset_i >>> 8))  & 0xff00ff00)\n    );\n  }\n\n  // Working variables\n  var al, bl, cl, dl, el;\n  var ar, br, cr, dr, er;\n\n  ar = al = H[0];\n  br = bl = H[1];\n  cr = cl = H[2];\n  dr = dl = H[3];\n  er = el = H[4];\n  // Computation\n  var t;\n  for (var i = 0; i < 80; i += 1) {\n    t = (al +  M[offset+zl[i]])|0;\n    if (i<16){\n        t +=  f1(bl,cl,dl) + hl[0];\n    } else if (i<32) {\n        t +=  f2(bl,cl,dl) + hl[1];\n    } else if (i<48) {\n        t +=  f3(bl,cl,dl) + hl[2];\n    } else if (i<64) {\n        t +=  f4(bl,cl,dl) + hl[3];\n    } else {// if (i<80) {\n        t +=  f5(bl,cl,dl) + hl[4];\n    }\n    t = t|0;\n    t =  rotl(t,sl[i]);\n    t = (t+el)|0;\n    al = el;\n    el = dl;\n    dl = rotl(cl, 10);\n    cl = bl;\n    bl = t;\n\n    t = (ar + M[offset+zr[i]])|0;\n    if (i<16){\n        t +=  f5(br,cr,dr) + hr[0];\n    } else if (i<32) {\n        t +=  f4(br,cr,dr) + hr[1];\n    } else if (i<48) {\n        t +=  f3(br,cr,dr) + hr[2];\n    } else if (i<64) {\n        t +=  f2(br,cr,dr) + hr[3];\n    } else {// if (i<80) {\n        t +=  f1(br,cr,dr) + hr[4];\n    }\n    t = t|0;\n    t =  rotl(t,sr[i]) ;\n    t = (t+er)|0;\n    ar = er;\n    er = dr;\n    dr = rotl(cr, 10);\n    cr = br;\n    br = t;\n  }\n  // Intermediate hash value\n  t    = (H[1] + cl + dr)|0;\n  H[1] = (H[2] + dl + er)|0;\n  H[2] = (H[3] + el + ar)|0;\n  H[3] = (H[4] + al + br)|0;\n  H[4] = (H[0] + bl + cr)|0;\n  H[0] =  t;\n};\n\nfunction f1(x, y, z) {\n  return ((x) ^ (y) ^ (z));\n}\n\nfunction f2(x, y, z) {\n  return (((x)&(y)) | ((~x)&(z)));\n}\n\nfunction f3(x, y, z) {\n  return (((x) | (~(y))) ^ (z));\n}\n\nfunction f4(x, y, z) {\n  return (((x) & (z)) | ((y)&(~(z))));\n}\n\nfunction f5(x, y, z) {\n  return ((x) ^ ((y) |(~(z))));\n}\n\nfunction rotl(x,n) {\n  return (x<<n) | (x>>>(32-n));\n}\n\nfunction ripemd160(message) {\n  var H = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0];\n\n  if (typeof message == 'string')\n    message = new Buffer(message, 'utf8');\n\n  var m = bytesToWords(message);\n\n  var nBitsLeft = message.length * 8;\n  var nBitsTotal = message.length * 8;\n\n  // Add padding\n  m[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);\n  m[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (\n      (((nBitsTotal << 8)  | (nBitsTotal >>> 24)) & 0x00ff00ff) |\n      (((nBitsTotal << 24) | (nBitsTotal >>> 8))  & 0xff00ff00)\n  );\n\n  for (var i=0 ; i<m.length; i += 16) {\n    processBlock(H, m, i);\n  }\n\n  // Swap endian\n  for (var i = 0; i < 5; i++) {\n      // Shortcut\n    var H_i = H[i];\n\n    // Swap\n    H[i] = (((H_i << 8)  | (H_i >>> 24)) & 0x00ff00ff) |\n          (((H_i << 24) | (H_i >>> 8))  & 0xff00ff00);\n  }\n\n  var digestbytes = wordsToBytes(H);\n  return new Buffer(digestbytes);\n}\n\n\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(41).Buffer))\n\n// WEBPACK FOOTER\n// module.id = 75\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/~/ripemd160/lib/ripemd160.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/~/ripemd160/lib/ripemd160.js");

/***/ },
/* 76 */
/***/ function(module, exports, __webpack_require__) {

	eval("var u = __webpack_require__(82)\nvar write = u.write\nvar fill = u.zeroFill\n\nmodule.exports = function (Buffer) {\n\n  //prototype class for hash functions\n  function Hash (blockSize, finalSize) {\n    this._block = new Buffer(blockSize) //new Uint32Array(blockSize/4)\n    this._finalSize = finalSize\n    this._blockSize = blockSize\n    this._len = 0\n    this._s = 0\n  }\n\n  Hash.prototype.init = function () {\n    this._s = 0\n    this._len = 0\n  }\n\n  function lengthOf(data, enc) {\n    if(enc == null)     return data.byteLength || data.length\n    if(enc == 'ascii' || enc == 'binary')  return data.length\n    if(enc == 'hex')    return data.length/2\n    if(enc == 'base64') return data.length/3\n  }\n\n  Hash.prototype.update = function (data, enc) {\n    var bl = this._blockSize\n\n    //I'd rather do this with a streaming encoder, like the opposite of\n    //http://nodejs.org/api/string_decoder.html\n    var length\n      if(!enc && 'string' === typeof data)\n        enc = 'utf8'\n\n    if(enc) {\n      if(enc === 'utf-8')\n        enc = 'utf8'\n\n      if(enc === 'base64' || enc === 'utf8')\n        data = new Buffer(data, enc), enc = null\n\n      length = lengthOf(data, enc)\n    } else\n      length = data.byteLength || data.length\n\n    var l = this._len += length\n    var s = this._s = (this._s || 0)\n    var f = 0\n    var buffer = this._block\n    while(s < l) {\n      var t = Math.min(length, f + bl)\n      write(buffer, data, enc, s%bl, f, t)\n      var ch = (t - f);\n      s += ch; f += ch\n\n      if(!(s%bl))\n        this._update(buffer)\n    }\n    this._s = s\n\n    return this\n\n  }\n\n  Hash.prototype.digest = function (enc) {\n    var bl = this._blockSize\n    var fl = this._finalSize\n    var len = this._len*8\n\n    var x = this._block\n\n    var bits = len % (bl*8)\n\n    //add end marker, so that appending 0's creats a different hash.\n    x[this._len % bl] = 0x80\n    fill(this._block, this._len % bl + 1)\n\n    if(bits >= fl*8) {\n      this._update(this._block)\n      u.zeroFill(this._block, 0)\n    }\n\n    //TODO: handle case where the bit length is > Math.pow(2, 29)\n    x.writeInt32BE(len, fl + 4) //big endian\n\n    var hash = this._update(this._block) || this._hash()\n    if(enc == null) return hash\n    return hash.toString(enc)\n  }\n\n  Hash.prototype._update = function () {\n    throw new Error('_update must be implemented by subclass')\n  }\n\n  return Hash\n}\n\n\n// WEBPACK FOOTER\n// module.id = 76\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/hash.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/hash.js");

/***/ },
/* 77 */
/***/ function(module, exports, __webpack_require__) {

	eval("/*\n * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined\n * in FIPS PUB 180-1\n * Version 2.1a Copyright Paul Johnston 2000 - 2002.\n * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\n * Distributed under the BSD License\n * See http://pajhome.org.uk/crypt/md5 for details.\n */\nmodule.exports = function (Buffer, Hash) {\n\n  var inherits = __webpack_require__(38).inherits\n\n  inherits(Sha1, Hash)\n\n  var A = 0|0\n  var B = 4|0\n  var C = 8|0\n  var D = 12|0\n  var E = 16|0\n\n  var BE = false\n  var LE = true\n\n  var W = new Int32Array(80)\n\n  var POOL = []\n\n  function Sha1 () {\n    if(POOL.length)\n      return POOL.pop().init()\n\n    if(!(this instanceof Sha1)) return new Sha1()\n    this._w = W\n    Hash.call(this, 16*4, 14*4)\n  \n    this._h = null\n    this.init()\n  }\n\n  Sha1.prototype.init = function () {\n    this._a = 0x67452301\n    this._b = 0xefcdab89\n    this._c = 0x98badcfe\n    this._d = 0x10325476\n    this._e = 0xc3d2e1f0\n\n    Hash.prototype.init.call(this)\n    return this\n  }\n\n  Sha1.prototype._POOL = POOL\n\n  // assume that array is a Uint32Array with length=16,\n  // and that if it is the last block, it already has the length and the 1 bit appended.\n\n\n  var isDV = new Buffer(1) instanceof DataView\n  function readInt32BE (X, i) {\n    return isDV\n      ? X.getInt32(i, false)\n      : X.readInt32BE(i)\n  }\n\n  Sha1.prototype._update = function (array) {\n\n    var X = this._block\n    var h = this._h\n    var a, b, c, d, e, _a, _b, _c, _d, _e\n\n    a = _a = this._a\n    b = _b = this._b\n    c = _c = this._c\n    d = _d = this._d\n    e = _e = this._e\n\n    var w = this._w\n\n    for(var j = 0; j < 80; j++) {\n      var W = w[j]\n        = j < 16\n        //? X.getInt32(j*4, false)\n        //? readInt32BE(X, j*4) //*/ X.readInt32BE(j*4) //*/\n        ? X.readInt32BE(j*4)\n        : rol(w[j - 3] ^ w[j -  8] ^ w[j - 14] ^ w[j - 16], 1)\n\n      var t =\n        add(\n          add(rol(a, 5), sha1_ft(j, b, c, d)),\n          add(add(e, W), sha1_kt(j))\n        );\n\n      e = d\n      d = c\n      c = rol(b, 30)\n      b = a\n      a = t\n    }\n\n    this._a = add(a, _a)\n    this._b = add(b, _b)\n    this._c = add(c, _c)\n    this._d = add(d, _d)\n    this._e = add(e, _e)\n  }\n\n  Sha1.prototype._hash = function () {\n    if(POOL.length < 100) POOL.push(this)\n    var H = new Buffer(20)\n    //console.log(this._a|0, this._b|0, this._c|0, this._d|0, this._e|0)\n    H.writeInt32BE(this._a|0, A)\n    H.writeInt32BE(this._b|0, B)\n    H.writeInt32BE(this._c|0, C)\n    H.writeInt32BE(this._d|0, D)\n    H.writeInt32BE(this._e|0, E)\n    return H\n  }\n\n  /*\n   * Perform the appropriate triplet combination function for the current\n   * iteration\n   */\n  function sha1_ft(t, b, c, d) {\n    if(t < 20) return (b & c) | ((~b) & d);\n    if(t < 40) return b ^ c ^ d;\n    if(t < 60) return (b & c) | (b & d) | (c & d);\n    return b ^ c ^ d;\n  }\n\n  /*\n   * Determine the appropriate additive constant for the current iteration\n   */\n  function sha1_kt(t) {\n    return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :\n           (t < 60) ? -1894007588 : -899497514;\n  }\n\n  /*\n   * Add integers, wrapping at 2^32. This uses 16-bit operations internally\n   * to work around bugs in some JS interpreters.\n   * //dominictarr: this is 10 years old, so maybe this can be dropped?)\n   *\n   */\n  function add(x, y) {\n    return (x + y ) | 0\n  //lets see how this goes on testling.\n  //  var lsw = (x & 0xFFFF) + (y & 0xFFFF);\n  //  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n  //  return (msw << 16) | (lsw & 0xFFFF);\n  }\n\n  /*\n   * Bitwise rotate a 32-bit number to the left.\n   */\n  function rol(num, cnt) {\n    return (num << cnt) | (num >>> (32 - cnt));\n  }\n\n  return Sha1\n}\n\n\n// WEBPACK FOOTER\n// module.id = 77\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/sha1.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/sha1.js");

/***/ },
/* 78 */
/***/ function(module, exports, __webpack_require__) {

	eval("\n/**\n * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined\n * in FIPS 180-2\n * Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009.\n * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\n *\n */\n\nvar inherits = __webpack_require__(38).inherits\nvar BE       = false\nvar LE       = true\nvar u        = __webpack_require__(82)\n\nmodule.exports = function (Buffer, Hash) {\n\n  var K = [\n      0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,\n      0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,\n      0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,\n      0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,\n      0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,\n      0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,\n      0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,\n      0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,\n      0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,\n      0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,\n      0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,\n      0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,\n      0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,\n      0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,\n      0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,\n      0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2\n    ]\n\n  inherits(Sha256, Hash)\n  var W = new Array(64)\n  var POOL = []\n  function Sha256() {\n    if(POOL.length) {\n      //return POOL.shift().init()\n    }\n    //this._data = new Buffer(32)\n\n    this.init()\n\n    this._w = W //new Array(64)\n\n    Hash.call(this, 16*4, 14*4)\n  };\n\n  Sha256.prototype.init = function () {\n\n    this._a = 0x6a09e667|0\n    this._b = 0xbb67ae85|0\n    this._c = 0x3c6ef372|0\n    this._d = 0xa54ff53a|0\n    this._e = 0x510e527f|0\n    this._f = 0x9b05688c|0\n    this._g = 0x1f83d9ab|0\n    this._h = 0x5be0cd19|0\n\n    this._len = this._s = 0\n\n    return this\n  }\n\n  var safe_add = function(x, y) {\n    var lsw = (x & 0xFFFF) + (y & 0xFFFF);\n    var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n    return (msw << 16) | (lsw & 0xFFFF);\n  }\n\n  function S (X, n) {\n    return (X >>> n) | (X << (32 - n));\n  }\n\n  function R (X, n) {\n    return (X >>> n);\n  }\n\n  function Ch (x, y, z) {\n    return ((x & y) ^ ((~x) & z));\n  }\n\n  function Maj (x, y, z) {\n    return ((x & y) ^ (x & z) ^ (y & z));\n  }\n\n  function Sigma0256 (x) {\n    return (S(x, 2) ^ S(x, 13) ^ S(x, 22));\n  }\n\n  function Sigma1256 (x) {\n    return (S(x, 6) ^ S(x, 11) ^ S(x, 25));\n  }\n\n  function Gamma0256 (x) {\n    return (S(x, 7) ^ S(x, 18) ^ R(x, 3));\n  }\n\n  function Gamma1256 (x) {\n    return (S(x, 17) ^ S(x, 19) ^ R(x, 10));\n  }\n\n  Sha256.prototype._update = function(m) {\n    var M = this._block\n    var W = this._w\n    var a, b, c, d, e, f, g, h\n    var T1, T2\n\n    a = this._a | 0\n    b = this._b | 0\n    c = this._c | 0\n    d = this._d | 0\n    e = this._e | 0\n    f = this._f | 0\n    g = this._g | 0\n    h = this._h | 0\n\n    for (var j = 0; j < 64; j++) {\n      var w = W[j] = j < 16\n        ? M.readInt32BE(j * 4)\n        : Gamma1256(W[j - 2]) + W[j - 7] + Gamma0256(W[j - 15]) + W[j - 16]\n\n      T1 = h + Sigma1256(e) + Ch(e, f, g) + K[j] + w\n\n      T2 = Sigma0256(a) + Maj(a, b, c);\n      h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2;\n    }\n\n    this._a = (a + this._a) | 0\n    this._b = (b + this._b) | 0\n    this._c = (c + this._c) | 0\n    this._d = (d + this._d) | 0\n    this._e = (e + this._e) | 0\n    this._f = (f + this._f) | 0\n    this._g = (g + this._g) | 0\n    this._h = (h + this._h) | 0\n\n  };\n\n  Sha256.prototype._hash = function () {\n    if(POOL.length < 10)\n      POOL.push(this)\n\n    var H = new Buffer(32)\n\n    H.writeInt32BE(this._a,  0)\n    H.writeInt32BE(this._b,  4)\n    H.writeInt32BE(this._c,  8)\n    H.writeInt32BE(this._d, 12)\n    H.writeInt32BE(this._e, 16)\n    H.writeInt32BE(this._f, 20)\n    H.writeInt32BE(this._g, 24)\n    H.writeInt32BE(this._h, 28)\n\n    return H\n  }\n\n  return Sha256\n\n}\n\n\n// WEBPACK FOOTER\n// module.id = 78\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/sha256.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/sha256.js");

/***/ },
/* 79 */
/***/ function(module, exports, __webpack_require__) {

	eval("module.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n// WEBPACK FOOTER\n// module.id = 79\n// module.readableIdentifier = (webpack)/buildin/amd-define.js\n//@ sourceURL=webpack-module:///(webpack)/buildin/amd-define.js");

/***/ },
/* 80 */
/***/ function(module, exports, __webpack_require__) {

	eval("module.exports = function(module) {\r\n\tif(!module.webpackPolyfill) {\r\n\t\tmodule.deprecate = function() {};\r\n\t\tmodule.paths = [];\r\n\t\t// module.parent = undefined by default\r\n\t\tmodule.children = [];\r\n\t\tmodule.webpackPolyfill = 1;\r\n\t}\r\n\treturn module;\r\n}\r\n\n\n// WEBPACK FOOTER\n// module.id = 80\n// module.readableIdentifier = (webpack)/buildin/module.js\n//@ sourceURL=webpack-module:///(webpack)/buildin/module.js");

/***/ },
/* 81 */
/***/ function(module, exports, __webpack_require__) {

	eval("/* WEBPACK VAR INJECTION */(function(Buffer) {/*!\n * The buffer module from node.js, for the browser.\n *\n * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>\n * @license  MIT\n */\n\nvar base64 = __webpack_require__(84)\nvar ieee754 = __webpack_require__(83)\n\nexports.Buffer = Buffer\nexports.SlowBuffer = Buffer\nexports.INSPECT_MAX_BYTES = 50\nBuffer.poolSize = 8192\n\n/**\n * If `Buffer._useTypedArrays`:\n *   === true    Use Uint8Array implementation (fastest)\n *   === false   Use Object implementation (compatible down to IE6)\n */\nBuffer._useTypedArrays = (function () {\n  // Detect if browser supports Typed Arrays. Supported browsers are IE 10+, Firefox 4+,\n  // Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. If the browser does not support adding\n  // properties to `Uint8Array` instances, then that's the same as no `Uint8Array` support\n  // because we need to be able to add all the node Buffer API methods. This is an issue\n  // in Firefox 4-29. Now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438\n  try {\n    var buf = new ArrayBuffer(0)\n    var arr = new Uint8Array(buf)\n    arr.foo = function () { return 42 }\n    return 42 === arr.foo() &&\n        typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray`\n  } catch (e) {\n    return false\n  }\n})()\n\n/**\n * Class: Buffer\n * =============\n *\n * The Buffer constructor returns instances of `Uint8Array` that are augmented\n * with function properties for all the node `Buffer` API functions. We use\n * `Uint8Array` so that square bracket notation works as expected -- it returns\n * a single octet.\n *\n * By augmenting the instances, we can avoid modifying the `Uint8Array`\n * prototype.\n */\nfunction Buffer (subject, encoding, noZero) {\n  if (!(this instanceof Buffer))\n    return new Buffer(subject, encoding, noZero)\n\n  var type = typeof subject\n\n  if (encoding === 'base64' && type === 'string') {\n    subject = base64clean(subject)\n  }\n\n  // Find the length\n  var length\n  if (type === 'number')\n    length = coerce(subject)\n  else if (type === 'string')\n    length = Buffer.byteLength(subject, encoding)\n  else if (type === 'object')\n    length = coerce(subject.length) // assume that object is array-like\n  else\n    throw new Error('First argument needs to be a number, array or string.')\n\n  var buf\n  if (Buffer._useTypedArrays) {\n    // Preferred: Return an augmented `Uint8Array` instance for best performance\n    buf = Buffer._augment(new Uint8Array(length))\n  } else {\n    // Fallback: Return THIS instance of Buffer (created by `new`)\n    buf = this\n    buf.length = length\n    buf._isBuffer = true\n  }\n\n  var i\n  if (Buffer._useTypedArrays && typeof subject.byteLength === 'number') {\n    // Speed optimization -- use set if we're copying from a typed array\n    buf._set(subject)\n  } else if (isArrayish(subject)) {\n    // Treat array-ish objects as a byte array\n    if (Buffer.isBuffer(subject)) {\n      for (i = 0; i < length; i++)\n        buf[i] = subject.readUInt8(i)\n    } else {\n      for (i = 0; i < length; i++)\n        buf[i] = ((subject[i] % 256) + 256) % 256\n    }\n  } else if (type === 'string') {\n    buf.write(subject, 0, encoding)\n  } else if (type === 'number' && !Buffer._useTypedArrays && !noZero) {\n    for (i = 0; i < length; i++) {\n      buf[i] = 0\n    }\n  }\n\n  return buf\n}\n\n// STATIC METHODS\n// ==============\n\nBuffer.isEncoding = function (encoding) {\n  switch (String(encoding).toLowerCase()) {\n    case 'hex':\n    case 'utf8':\n    case 'utf-8':\n    case 'ascii':\n    case 'binary':\n    case 'base64':\n    case 'raw':\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      return true\n    default:\n      return false\n  }\n}\n\nBuffer.isBuffer = function (b) {\n  return !!(b != null && b._isBuffer)\n}\n\nBuffer.byteLength = function (str, encoding) {\n  var ret\n  str = str.toString()\n  switch (encoding || 'utf8') {\n    case 'hex':\n      ret = str.length / 2\n      break\n    case 'utf8':\n    case 'utf-8':\n      ret = utf8ToBytes(str).length\n      break\n    case 'ascii':\n    case 'binary':\n    case 'raw':\n      ret = str.length\n      break\n    case 'base64':\n      ret = base64ToBytes(str).length\n      break\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      ret = str.length * 2\n      break\n    default:\n      throw new Error('Unknown encoding')\n  }\n  return ret\n}\n\nBuffer.concat = function (list, totalLength) {\n  assert(isArray(list), 'Usage: Buffer.concat(list[, length])')\n\n  if (list.length === 0) {\n    return new Buffer(0)\n  } else if (list.length === 1) {\n    return list[0]\n  }\n\n  var i\n  if (totalLength === undefined) {\n    totalLength = 0\n    for (i = 0; i < list.length; i++) {\n      totalLength += list[i].length\n    }\n  }\n\n  var buf = new Buffer(totalLength)\n  var pos = 0\n  for (i = 0; i < list.length; i++) {\n    var item = list[i]\n    item.copy(buf, pos)\n    pos += item.length\n  }\n  return buf\n}\n\nBuffer.compare = function (a, b) {\n  assert(Buffer.isBuffer(a) && Buffer.isBuffer(b), 'Arguments must be Buffers')\n  var x = a.length\n  var y = b.length\n  for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {}\n  if (i !== len) {\n    x = a[i]\n    y = b[i]\n  }\n  if (x < y) {\n    return -1\n  }\n  if (y < x) {\n    return 1\n  }\n  return 0\n}\n\n// BUFFER INSTANCE METHODS\n// =======================\n\nfunction hexWrite (buf, string, offset, length) {\n  offset = Number(offset) || 0\n  var remaining = buf.length - offset\n  if (!length) {\n    length = remaining\n  } else {\n    length = Number(length)\n    if (length > remaining) {\n      length = remaining\n    }\n  }\n\n  // must be an even number of digits\n  var strLen = string.length\n  assert(strLen % 2 === 0, 'Invalid hex string')\n\n  if (length > strLen / 2) {\n    length = strLen / 2\n  }\n  for (var i = 0; i < length; i++) {\n    var byte = parseInt(string.substr(i * 2, 2), 16)\n    assert(!isNaN(byte), 'Invalid hex string')\n    buf[offset + i] = byte\n  }\n  return i\n}\n\nfunction utf8Write (buf, string, offset, length) {\n  var charsWritten = blitBuffer(utf8ToBytes(string), buf, offset, length)\n  return charsWritten\n}\n\nfunction asciiWrite (buf, string, offset, length) {\n  var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length)\n  return charsWritten\n}\n\nfunction binaryWrite (buf, string, offset, length) {\n  return asciiWrite(buf, string, offset, length)\n}\n\nfunction base64Write (buf, string, offset, length) {\n  var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length)\n  return charsWritten\n}\n\nfunction utf16leWrite (buf, string, offset, length) {\n  var charsWritten = blitBuffer(utf16leToBytes(string), buf, offset, length)\n  return charsWritten\n}\n\nBuffer.prototype.write = function (string, offset, length, encoding) {\n  // Support both (string, offset, length, encoding)\n  // and the legacy (string, encoding, offset, length)\n  if (isFinite(offset)) {\n    if (!isFinite(length)) {\n      encoding = length\n      length = undefined\n    }\n  } else {  // legacy\n    var swap = encoding\n    encoding = offset\n    offset = length\n    length = swap\n  }\n\n  offset = Number(offset) || 0\n  var remaining = this.length - offset\n  if (!length) {\n    length = remaining\n  } else {\n    length = Number(length)\n    if (length > remaining) {\n      length = remaining\n    }\n  }\n  encoding = String(encoding || 'utf8').toLowerCase()\n\n  var ret\n  switch (encoding) {\n    case 'hex':\n      ret = hexWrite(this, string, offset, length)\n      break\n    case 'utf8':\n    case 'utf-8':\n      ret = utf8Write(this, string, offset, length)\n      break\n    case 'ascii':\n      ret = asciiWrite(this, string, offset, length)\n      break\n    case 'binary':\n      ret = binaryWrite(this, string, offset, length)\n      break\n    case 'base64':\n      ret = base64Write(this, string, offset, length)\n      break\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      ret = utf16leWrite(this, string, offset, length)\n      break\n    default:\n      throw new Error('Unknown encoding')\n  }\n  return ret\n}\n\nBuffer.prototype.toString = function (encoding, start, end) {\n  var self = this\n\n  encoding = String(encoding || 'utf8').toLowerCase()\n  start = Number(start) || 0\n  end = (end === undefined) ? self.length : Number(end)\n\n  // Fastpath empty strings\n  if (end === start)\n    return ''\n\n  var ret\n  switch (encoding) {\n    case 'hex':\n      ret = hexSlice(self, start, end)\n      break\n    case 'utf8':\n    case 'utf-8':\n      ret = utf8Slice(self, start, end)\n      break\n    case 'ascii':\n      ret = asciiSlice(self, start, end)\n      break\n    case 'binary':\n      ret = binarySlice(self, start, end)\n      break\n    case 'base64':\n      ret = base64Slice(self, start, end)\n      break\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      ret = utf16leSlice(self, start, end)\n      break\n    default:\n      throw new Error('Unknown encoding')\n  }\n  return ret\n}\n\nBuffer.prototype.toJSON = function () {\n  return {\n    type: 'Buffer',\n    data: Array.prototype.slice.call(this._arr || this, 0)\n  }\n}\n\nBuffer.prototype.equals = function (b) {\n  assert(Buffer.isBuffer(b), 'Argument must be a Buffer')\n  return Buffer.compare(this, b) === 0\n}\n\nBuffer.prototype.compare = function (b) {\n  assert(Buffer.isBuffer(b), 'Argument must be a Buffer')\n  return Buffer.compare(this, b)\n}\n\n// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)\nBuffer.prototype.copy = function (target, target_start, start, end) {\n  var source = this\n\n  if (!start) start = 0\n  if (!end && end !== 0) end = this.length\n  if (!target_start) target_start = 0\n\n  // Copy 0 bytes; we're done\n  if (end === start) return\n  if (target.length === 0 || source.length === 0) return\n\n  // Fatal error conditions\n  assert(end >= start, 'sourceEnd < sourceStart')\n  assert(target_start >= 0 && target_start < target.length,\n      'targetStart out of bounds')\n  assert(start >= 0 && start < source.length, 'sourceStart out of bounds')\n  assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds')\n\n  // Are we oob?\n  if (end > this.length)\n    end = this.length\n  if (target.length - target_start < end - start)\n    end = target.length - target_start + start\n\n  var len = end - start\n\n  if (len < 100 || !Buffer._useTypedArrays) {\n    for (var i = 0; i < len; i++) {\n      target[i + target_start] = this[i + start]\n    }\n  } else {\n    target._set(this.subarray(start, start + len), target_start)\n  }\n}\n\nfunction base64Slice (buf, start, end) {\n  if (start === 0 && end === buf.length) {\n    return base64.fromByteArray(buf)\n  } else {\n    return base64.fromByteArray(buf.slice(start, end))\n  }\n}\n\nfunction utf8Slice (buf, start, end) {\n  var res = ''\n  var tmp = ''\n  end = Math.min(buf.length, end)\n\n  for (var i = start; i < end; i++) {\n    if (buf[i] <= 0x7F) {\n      res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i])\n      tmp = ''\n    } else {\n      tmp += '%' + buf[i].toString(16)\n    }\n  }\n\n  return res + decodeUtf8Char(tmp)\n}\n\nfunction asciiSlice (buf, start, end) {\n  var ret = ''\n  end = Math.min(buf.length, end)\n\n  for (var i = start; i < end; i++) {\n    ret += String.fromCharCode(buf[i])\n  }\n  return ret\n}\n\nfunction binarySlice (buf, start, end) {\n  return asciiSlice(buf, start, end)\n}\n\nfunction hexSlice (buf, start, end) {\n  var len = buf.length\n\n  if (!start || start < 0) start = 0\n  if (!end || end < 0 || end > len) end = len\n\n  var out = ''\n  for (var i = start; i < end; i++) {\n    out += toHex(buf[i])\n  }\n  return out\n}\n\nfunction utf16leSlice (buf, start, end) {\n  var bytes = buf.slice(start, end)\n  var res = ''\n  for (var i = 0; i < bytes.length; i += 2) {\n    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)\n  }\n  return res\n}\n\nBuffer.prototype.slice = function (start, end) {\n  var len = this.length\n  start = clamp(start, len, 0)\n  end = clamp(end, len, len)\n\n  if (Buffer._useTypedArrays) {\n    return Buffer._augment(this.subarray(start, end))\n  } else {\n    var sliceLen = end - start\n    var newBuf = new Buffer(sliceLen, undefined, true)\n    for (var i = 0; i < sliceLen; i++) {\n      newBuf[i] = this[i + start]\n    }\n    return newBuf\n  }\n}\n\n// `get` will be removed in Node 0.13+\nBuffer.prototype.get = function (offset) {\n  console.log('.get() is deprecated. Access using array indexes instead.')\n  return this.readUInt8(offset)\n}\n\n// `set` will be removed in Node 0.13+\nBuffer.prototype.set = function (v, offset) {\n  console.log('.set() is deprecated. Access using array indexes instead.')\n  return this.writeUInt8(v, offset)\n}\n\nBuffer.prototype.readUInt8 = function (offset, noAssert) {\n  if (!noAssert) {\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset < this.length, 'Trying to read beyond buffer length')\n  }\n\n  if (offset >= this.length)\n    return\n\n  return this[offset]\n}\n\nfunction readUInt16 (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  var val\n  if (littleEndian) {\n    val = buf[offset]\n    if (offset + 1 < len)\n      val |= buf[offset + 1] << 8\n  } else {\n    val = buf[offset] << 8\n    if (offset + 1 < len)\n      val |= buf[offset + 1]\n  }\n  return val\n}\n\nBuffer.prototype.readUInt16LE = function (offset, noAssert) {\n  return readUInt16(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readUInt16BE = function (offset, noAssert) {\n  return readUInt16(this, offset, false, noAssert)\n}\n\nfunction readUInt32 (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  var val\n  if (littleEndian) {\n    if (offset + 2 < len)\n      val = buf[offset + 2] << 16\n    if (offset + 1 < len)\n      val |= buf[offset + 1] << 8\n    val |= buf[offset]\n    if (offset + 3 < len)\n      val = val + (buf[offset + 3] << 24 >>> 0)\n  } else {\n    if (offset + 1 < len)\n      val = buf[offset + 1] << 16\n    if (offset + 2 < len)\n      val |= buf[offset + 2] << 8\n    if (offset + 3 < len)\n      val |= buf[offset + 3]\n    val = val + (buf[offset] << 24 >>> 0)\n  }\n  return val\n}\n\nBuffer.prototype.readUInt32LE = function (offset, noAssert) {\n  return readUInt32(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readUInt32BE = function (offset, noAssert) {\n  return readUInt32(this, offset, false, noAssert)\n}\n\nBuffer.prototype.readInt8 = function (offset, noAssert) {\n  if (!noAssert) {\n    assert(offset !== undefined && offset !== null,\n        'missing offset')\n    assert(offset < this.length, 'Trying to read beyond buffer length')\n  }\n\n  if (offset >= this.length)\n    return\n\n  var neg = this[offset] & 0x80\n  if (neg)\n    return (0xff - this[offset] + 1) * -1\n  else\n    return this[offset]\n}\n\nfunction readInt16 (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  var val = readUInt16(buf, offset, littleEndian, true)\n  var neg = val & 0x8000\n  if (neg)\n    return (0xffff - val + 1) * -1\n  else\n    return val\n}\n\nBuffer.prototype.readInt16LE = function (offset, noAssert) {\n  return readInt16(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readInt16BE = function (offset, noAssert) {\n  return readInt16(this, offset, false, noAssert)\n}\n\nfunction readInt32 (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  var val = readUInt32(buf, offset, littleEndian, true)\n  var neg = val & 0x80000000\n  if (neg)\n    return (0xffffffff - val + 1) * -1\n  else\n    return val\n}\n\nBuffer.prototype.readInt32LE = function (offset, noAssert) {\n  return readInt32(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readInt32BE = function (offset, noAssert) {\n  return readInt32(this, offset, false, noAssert)\n}\n\nfunction readFloat (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  return ieee754.read(buf, offset, littleEndian, 23, 4)\n}\n\nBuffer.prototype.readFloatLE = function (offset, noAssert) {\n  return readFloat(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readFloatBE = function (offset, noAssert) {\n  return readFloat(this, offset, false, noAssert)\n}\n\nfunction readDouble (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset + 7 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  return ieee754.read(buf, offset, littleEndian, 52, 8)\n}\n\nBuffer.prototype.readDoubleLE = function (offset, noAssert) {\n  return readDouble(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readDoubleBE = function (offset, noAssert) {\n  return readDouble(this, offset, false, noAssert)\n}\n\nBuffer.prototype.writeUInt8 = function (value, offset, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset < this.length, 'trying to write beyond buffer length')\n    verifuint(value, 0xff)\n  }\n\n  if (offset >= this.length) return\n\n  this[offset] = value\n  return offset + 1\n}\n\nfunction writeUInt16 (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 1 < buf.length, 'trying to write beyond buffer length')\n    verifuint(value, 0xffff)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) {\n    buf[offset + i] =\n        (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>\n            (littleEndian ? i : 1 - i) * 8\n  }\n  return offset + 2\n}\n\nBuffer.prototype.writeUInt16LE = function (value, offset, noAssert) {\n  return writeUInt16(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeUInt16BE = function (value, offset, noAssert) {\n  return writeUInt16(this, value, offset, false, noAssert)\n}\n\nfunction writeUInt32 (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'trying to write beyond buffer length')\n    verifuint(value, 0xffffffff)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) {\n    buf[offset + i] =\n        (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff\n  }\n  return offset + 4\n}\n\nBuffer.prototype.writeUInt32LE = function (value, offset, noAssert) {\n  return writeUInt32(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeUInt32BE = function (value, offset, noAssert) {\n  return writeUInt32(this, value, offset, false, noAssert)\n}\n\nBuffer.prototype.writeInt8 = function (value, offset, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset < this.length, 'Trying to write beyond buffer length')\n    verifsint(value, 0x7f, -0x80)\n  }\n\n  if (offset >= this.length)\n    return\n\n  if (value >= 0)\n    this.writeUInt8(value, offset, noAssert)\n  else\n    this.writeUInt8(0xff + value + 1, offset, noAssert)\n  return offset + 1\n}\n\nfunction writeInt16 (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 1 < buf.length, 'Trying to write beyond buffer length')\n    verifsint(value, 0x7fff, -0x8000)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  if (value >= 0)\n    writeUInt16(buf, value, offset, littleEndian, noAssert)\n  else\n    writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert)\n  return offset + 2\n}\n\nBuffer.prototype.writeInt16LE = function (value, offset, noAssert) {\n  return writeInt16(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeInt16BE = function (value, offset, noAssert) {\n  return writeInt16(this, value, offset, false, noAssert)\n}\n\nfunction writeInt32 (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')\n    verifsint(value, 0x7fffffff, -0x80000000)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  if (value >= 0)\n    writeUInt32(buf, value, offset, littleEndian, noAssert)\n  else\n    writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert)\n  return offset + 4\n}\n\nBuffer.prototype.writeInt32LE = function (value, offset, noAssert) {\n  return writeInt32(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeInt32BE = function (value, offset, noAssert) {\n  return writeInt32(this, value, offset, false, noAssert)\n}\n\nfunction writeFloat (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')\n    verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  ieee754.write(buf, value, offset, littleEndian, 23, 4)\n  return offset + 4\n}\n\nBuffer.prototype.writeFloatLE = function (value, offset, noAssert) {\n  return writeFloat(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeFloatBE = function (value, offset, noAssert) {\n  return writeFloat(this, value, offset, false, noAssert)\n}\n\nfunction writeDouble (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 7 < buf.length,\n        'Trying to write beyond buffer length')\n    verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  ieee754.write(buf, value, offset, littleEndian, 52, 8)\n  return offset + 8\n}\n\nBuffer.prototype.writeDoubleLE = function (value, offset, noAssert) {\n  return writeDouble(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeDoubleBE = function (value, offset, noAssert) {\n  return writeDouble(this, value, offset, false, noAssert)\n}\n\n// fill(value, start=0, end=buffer.length)\nBuffer.prototype.fill = function (value, start, end) {\n  if (!value) value = 0\n  if (!start) start = 0\n  if (!end) end = this.length\n\n  assert(end >= start, 'end < start')\n\n  // Fill 0 bytes; we're done\n  if (end === start) return\n  if (this.length === 0) return\n\n  assert(start >= 0 && start < this.length, 'start out of bounds')\n  assert(end >= 0 && end <= this.length, 'end out of bounds')\n\n  var i\n  if (typeof value === 'number') {\n    for (i = start; i < end; i++) {\n      this[i] = value\n    }\n  } else {\n    var bytes = utf8ToBytes(value.toString())\n    var len = bytes.length\n    for (i = start; i < end; i++) {\n      this[i] = bytes[i % len]\n    }\n  }\n\n  return this\n}\n\nBuffer.prototype.inspect = function () {\n  var out = []\n  var len = this.length\n  for (var i = 0; i < len; i++) {\n    out[i] = toHex(this[i])\n    if (i === exports.INSPECT_MAX_BYTES) {\n      out[i + 1] = '...'\n      break\n    }\n  }\n  return '<Buffer ' + out.join(' ') + '>'\n}\n\n/**\n * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.\n * Added in Node 0.12. Only available in browsers that support ArrayBuffer.\n */\nBuffer.prototype.toArrayBuffer = function () {\n  if (typeof Uint8Array !== 'undefined') {\n    if (Buffer._useTypedArrays) {\n      return (new Buffer(this)).buffer\n    } else {\n      var buf = new Uint8Array(this.length)\n      for (var i = 0, len = buf.length; i < len; i += 1) {\n        buf[i] = this[i]\n      }\n      return buf.buffer\n    }\n  } else {\n    throw new Error('Buffer.toArrayBuffer not supported in this browser')\n  }\n}\n\n// HELPER FUNCTIONS\n// ================\n\nvar BP = Buffer.prototype\n\n/**\n * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods\n */\nBuffer._augment = function (arr) {\n  arr._isBuffer = true\n\n  // save reference to original Uint8Array get/set methods before overwriting\n  arr._get = arr.get\n  arr._set = arr.set\n\n  // deprecated, will be removed in node 0.13+\n  arr.get = BP.get\n  arr.set = BP.set\n\n  arr.write = BP.write\n  arr.toString = BP.toString\n  arr.toLocaleString = BP.toString\n  arr.toJSON = BP.toJSON\n  arr.equals = BP.equals\n  arr.compare = BP.compare\n  arr.copy = BP.copy\n  arr.slice = BP.slice\n  arr.readUInt8 = BP.readUInt8\n  arr.readUInt16LE = BP.readUInt16LE\n  arr.readUInt16BE = BP.readUInt16BE\n  arr.readUInt32LE = BP.readUInt32LE\n  arr.readUInt32BE = BP.readUInt32BE\n  arr.readInt8 = BP.readInt8\n  arr.readInt16LE = BP.readInt16LE\n  arr.readInt16BE = BP.readInt16BE\n  arr.readInt32LE = BP.readInt32LE\n  arr.readInt32BE = BP.readInt32BE\n  arr.readFloatLE = BP.readFloatLE\n  arr.readFloatBE = BP.readFloatBE\n  arr.readDoubleLE = BP.readDoubleLE\n  arr.readDoubleBE = BP.readDoubleBE\n  arr.writeUInt8 = BP.writeUInt8\n  arr.writeUInt16LE = BP.writeUInt16LE\n  arr.writeUInt16BE = BP.writeUInt16BE\n  arr.writeUInt32LE = BP.writeUInt32LE\n  arr.writeUInt32BE = BP.writeUInt32BE\n  arr.writeInt8 = BP.writeInt8\n  arr.writeInt16LE = BP.writeInt16LE\n  arr.writeInt16BE = BP.writeInt16BE\n  arr.writeInt32LE = BP.writeInt32LE\n  arr.writeInt32BE = BP.writeInt32BE\n  arr.writeFloatLE = BP.writeFloatLE\n  arr.writeFloatBE = BP.writeFloatBE\n  arr.writeDoubleLE = BP.writeDoubleLE\n  arr.writeDoubleBE = BP.writeDoubleBE\n  arr.fill = BP.fill\n  arr.inspect = BP.inspect\n  arr.toArrayBuffer = BP.toArrayBuffer\n\n  return arr\n}\n\nvar INVALID_BASE64_RE = /[^+\\/0-9A-z]/g\n\nfunction base64clean (str) {\n  // Node strips out invalid characters like \\n and \\t from the string, base64-js does not\n  str = stringtrim(str).replace(INVALID_BASE64_RE, '')\n  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not\n  while (str.length % 4 !== 0) {\n    str = str + '='\n  }\n  return str\n}\n\nfunction stringtrim (str) {\n  if (str.trim) return str.trim()\n  return str.replace(/^\\s+|\\s+$/g, '')\n}\n\n// slice(start, end)\nfunction clamp (index, len, defaultValue) {\n  if (typeof index !== 'number') return defaultValue\n  index = ~~index;  // Coerce to integer.\n  if (index >= len) return len\n  if (index >= 0) return index\n  index += len\n  if (index >= 0) return index\n  return 0\n}\n\nfunction coerce (length) {\n  // Coerce length to a number (possibly NaN), round up\n  // in case it's fractional (e.g. 123.456) then do a\n  // double negate to coerce a NaN to 0. Easy, right?\n  length = ~~Math.ceil(+length)\n  return length < 0 ? 0 : length\n}\n\nfunction isArray (subject) {\n  return (Array.isArray || function (subject) {\n    return Object.prototype.toString.call(subject) === '[object Array]'\n  })(subject)\n}\n\nfunction isArrayish (subject) {\n  return isArray(subject) || Buffer.isBuffer(subject) ||\n      subject && typeof subject === 'object' &&\n      typeof subject.length === 'number'\n}\n\nfunction toHex (n) {\n  if (n < 16) return '0' + n.toString(16)\n  return n.toString(16)\n}\n\nfunction utf8ToBytes (str) {\n  var byteArray = []\n  for (var i = 0; i < str.length; i++) {\n    var b = str.charCodeAt(i)\n    if (b <= 0x7F) {\n      byteArray.push(b)\n    } else {\n      var start = i\n      if (b >= 0xD800 && b <= 0xDFFF) i++\n      var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%')\n      for (var j = 0; j < h.length; j++) {\n        byteArray.push(parseInt(h[j], 16))\n      }\n    }\n  }\n  return byteArray\n}\n\nfunction asciiToBytes (str) {\n  var byteArray = []\n  for (var i = 0; i < str.length; i++) {\n    // Node's code seems to be doing this and not & 0x7F..\n    byteArray.push(str.charCodeAt(i) & 0xFF)\n  }\n  return byteArray\n}\n\nfunction utf16leToBytes (str) {\n  var c, hi, lo\n  var byteArray = []\n  for (var i = 0; i < str.length; i++) {\n    c = str.charCodeAt(i)\n    hi = c >> 8\n    lo = c % 256\n    byteArray.push(lo)\n    byteArray.push(hi)\n  }\n\n  return byteArray\n}\n\nfunction base64ToBytes (str) {\n  return base64.toByteArray(str)\n}\n\nfunction blitBuffer (src, dst, offset, length) {\n  for (var i = 0; i < length; i++) {\n    if ((i + offset >= dst.length) || (i >= src.length))\n      break\n    dst[i + offset] = src[i]\n  }\n  return i\n}\n\nfunction decodeUtf8Char (str) {\n  try {\n    return decodeURIComponent(str)\n  } catch (err) {\n    return String.fromCharCode(0xFFFD) // UTF 8 invalid char\n  }\n}\n\n/*\n * We have to make sure that the value is a valid integer. This means that it\n * is non-negative. It has no fractional component and that it does not\n * exceed the maximum allowed value.\n */\nfunction verifuint (value, max) {\n  assert(typeof value === 'number', 'cannot write a non-number as a number')\n  assert(value >= 0, 'specified a negative value for writing an unsigned value')\n  assert(value <= max, 'value is larger than maximum value for type')\n  assert(Math.floor(value) === value, 'value has a fractional component')\n}\n\nfunction verifsint (value, max, min) {\n  assert(typeof value === 'number', 'cannot write a non-number as a number')\n  assert(value <= max, 'value larger than maximum allowed value')\n  assert(value >= min, 'value smaller than minimum allowed value')\n  assert(Math.floor(value) === value, 'value has a fractional component')\n}\n\nfunction verifIEEE754 (value, max, min) {\n  assert(typeof value === 'number', 'cannot write a non-number as a number')\n  assert(value <= max, 'value larger than maximum allowed value')\n  assert(value >= min, 'value smaller than minimum allowed value')\n}\n\nfunction assert (test, message) {\n  if (!test) throw new Error(message || 'Failed assertion')\n}\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(41).Buffer))\n\n// WEBPACK FOOTER\n// module.id = 81\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/~/buffer/index.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/~/buffer/index.js");

/***/ },
/* 82 */
/***/ function(module, exports, __webpack_require__) {

	eval("exports.write = write\nexports.zeroFill = zeroFill\n\nexports.toString = toString\n\nfunction write (buffer, string, enc, start, from, to, LE) {\n  var l = (to - from)\n  if(enc === 'ascii' || enc === 'binary') {\n    for( var i = 0; i < l; i++) {\n      buffer[start + i] = string.charCodeAt(i + from)\n    }\n  }\n  else if(enc == null) {\n    for( var i = 0; i < l; i++) {\n      buffer[start + i] = string[i + from]\n    }\n  }\n  else if(enc === 'hex') {\n    for(var i = 0; i < l; i++) {\n      var j = from + i\n      buffer[start + i] = parseInt(string[j*2] + string[(j*2)+1], 16)\n    }\n  }\n  else if(enc === 'base64') {\n    throw new Error('base64 encoding not yet supported')\n  }\n  else\n    throw new Error(enc +' encoding not yet supported')\n}\n\n//always fill to the end!\nfunction zeroFill(buf, from) {\n  for(var i = from; i < buf.length; i++)\n    buf[i] = 0\n}\n\n\n\n// WEBPACK FOOTER\n// module.id = 82\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/util.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/util.js");

/***/ },
/* 83 */
/***/ function(module, exports, __webpack_require__) {

	eval("exports.read = function(buffer, offset, isLE, mLen, nBytes) {\n  var e, m,\n      eLen = nBytes * 8 - mLen - 1,\n      eMax = (1 << eLen) - 1,\n      eBias = eMax >> 1,\n      nBits = -7,\n      i = isLE ? (nBytes - 1) : 0,\n      d = isLE ? -1 : 1,\n      s = buffer[offset + i];\n\n  i += d;\n\n  e = s & ((1 << (-nBits)) - 1);\n  s >>= (-nBits);\n  nBits += eLen;\n  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);\n\n  m = e & ((1 << (-nBits)) - 1);\n  e >>= (-nBits);\n  nBits += mLen;\n  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);\n\n  if (e === 0) {\n    e = 1 - eBias;\n  } else if (e === eMax) {\n    return m ? NaN : ((s ? -1 : 1) * Infinity);\n  } else {\n    m = m + Math.pow(2, mLen);\n    e = e - eBias;\n  }\n  return (s ? -1 : 1) * m * Math.pow(2, e - mLen);\n};\n\nexports.write = function(buffer, value, offset, isLE, mLen, nBytes) {\n  var e, m, c,\n      eLen = nBytes * 8 - mLen - 1,\n      eMax = (1 << eLen) - 1,\n      eBias = eMax >> 1,\n      rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),\n      i = isLE ? 0 : (nBytes - 1),\n      d = isLE ? 1 : -1,\n      s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;\n\n  value = Math.abs(value);\n\n  if (isNaN(value) || value === Infinity) {\n    m = isNaN(value) ? 1 : 0;\n    e = eMax;\n  } else {\n    e = Math.floor(Math.log(value) / Math.LN2);\n    if (value * (c = Math.pow(2, -e)) < 1) {\n      e--;\n      c *= 2;\n    }\n    if (e + eBias >= 1) {\n      value += rt / c;\n    } else {\n      value += rt * Math.pow(2, 1 - eBias);\n    }\n    if (value * c >= 2) {\n      e++;\n      c /= 2;\n    }\n\n    if (e + eBias >= eMax) {\n      m = 0;\n      e = eMax;\n    } else if (e + eBias >= 1) {\n      m = (value * c - 1) * Math.pow(2, mLen);\n      e = e + eBias;\n    } else {\n      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);\n      e = 0;\n    }\n  }\n\n  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);\n\n  e = (e << mLen) | m;\n  eLen += mLen;\n  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);\n\n  buffer[offset + i - d] |= s * 128;\n};\n\n\n// WEBPACK FOOTER\n// module.id = 83\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/~/buffer/~/ieee754/index.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/~/buffer/~/ieee754/index.js");

/***/ },
/* 84 */
/***/ function(module, exports, __webpack_require__) {

	eval("var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n;(function (exports) {\n\t'use strict';\n\n  var Arr = (typeof Uint8Array !== 'undefined')\n    ? Uint8Array\n    : Array\n\n\tvar PLUS   = '+'.charCodeAt(0)\n\tvar SLASH  = '/'.charCodeAt(0)\n\tvar NUMBER = '0'.charCodeAt(0)\n\tvar LOWER  = 'a'.charCodeAt(0)\n\tvar UPPER  = 'A'.charCodeAt(0)\n\n\tfunction decode (elt) {\n\t\tvar code = elt.charCodeAt(0)\n\t\tif (code === PLUS)\n\t\t\treturn 62 // '+'\n\t\tif (code === SLASH)\n\t\t\treturn 63 // '/'\n\t\tif (code < NUMBER)\n\t\t\treturn -1 //no match\n\t\tif (code < NUMBER + 10)\n\t\t\treturn code - NUMBER + 26 + 26\n\t\tif (code < UPPER + 26)\n\t\t\treturn code - UPPER\n\t\tif (code < LOWER + 26)\n\t\t\treturn code - LOWER + 26\n\t}\n\n\tfunction b64ToByteArray (b64) {\n\t\tvar i, j, l, tmp, placeHolders, arr\n\n\t\tif (b64.length % 4 > 0) {\n\t\t\tthrow new Error('Invalid string. Length must be a multiple of 4')\n\t\t}\n\n\t\t// the number of equal signs (place holders)\n\t\t// if there are two placeholders, than the two characters before it\n\t\t// represent one byte\n\t\t// if there is only one, then the three characters before it represent 2 bytes\n\t\t// this is just a cheap hack to not do indexOf twice\n\t\tvar len = b64.length\n\t\tplaceHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0\n\n\t\t// base64 is 4/3 + up to two characters of the original data\n\t\tarr = new Arr(b64.length * 3 / 4 - placeHolders)\n\n\t\t// if there are placeholders, only get up to the last complete 4 chars\n\t\tl = placeHolders > 0 ? b64.length - 4 : b64.length\n\n\t\tvar L = 0\n\n\t\tfunction push (v) {\n\t\t\tarr[L++] = v\n\t\t}\n\n\t\tfor (i = 0, j = 0; i < l; i += 4, j += 3) {\n\t\t\ttmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))\n\t\t\tpush((tmp & 0xFF0000) >> 16)\n\t\t\tpush((tmp & 0xFF00) >> 8)\n\t\t\tpush(tmp & 0xFF)\n\t\t}\n\n\t\tif (placeHolders === 2) {\n\t\t\ttmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)\n\t\t\tpush(tmp & 0xFF)\n\t\t} else if (placeHolders === 1) {\n\t\t\ttmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)\n\t\t\tpush((tmp >> 8) & 0xFF)\n\t\t\tpush(tmp & 0xFF)\n\t\t}\n\n\t\treturn arr\n\t}\n\n\tfunction uint8ToBase64 (uint8) {\n\t\tvar i,\n\t\t\textraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes\n\t\t\toutput = \"\",\n\t\t\ttemp, length\n\n\t\tfunction encode (num) {\n\t\t\treturn lookup.charAt(num)\n\t\t}\n\n\t\tfunction tripletToBase64 (num) {\n\t\t\treturn encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)\n\t\t}\n\n\t\t// go through the array every three bytes, we'll deal with trailing stuff later\n\t\tfor (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {\n\t\t\ttemp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])\n\t\t\toutput += tripletToBase64(temp)\n\t\t}\n\n\t\t// pad the end with zeros, but make sure to not forget the extra bytes\n\t\tswitch (extraBytes) {\n\t\t\tcase 1:\n\t\t\t\ttemp = uint8[uint8.length - 1]\n\t\t\t\toutput += encode(temp >> 2)\n\t\t\t\toutput += encode((temp << 4) & 0x3F)\n\t\t\t\toutput += '=='\n\t\t\t\tbreak\n\t\t\tcase 2:\n\t\t\t\ttemp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])\n\t\t\t\toutput += encode(temp >> 10)\n\t\t\t\toutput += encode((temp >> 4) & 0x3F)\n\t\t\t\toutput += encode((temp << 2) & 0x3F)\n\t\t\t\toutput += '='\n\t\t\t\tbreak\n\t\t}\n\n\t\treturn output\n\t}\n\n\texports.toByteArray = b64ToByteArray\n\texports.fromByteArray = uint8ToBase64\n}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))\n\n\n// WEBPACK FOOTER\n// module.id = 84\n// module.readableIdentifier = (webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/~/buffer/~/base64-js/lib/b64.js\n//@ sourceURL=webpack-module:///(webpack)/~/node-libs-browser/~/crypto-browserify/~/sha.js/~/buffer/~/base64-js/lib/b64.js");

/***/ }
/******/ ])
// Import SJCL from ripple.js
window.sjcl = ripple.sjcl;

/* =========================================================
 * bootstrap-modal.js v2.2.2
 * http://twitter.github.com/bootstrap/javascript.html#modals
 * =========================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================= */


!function ($) {

  "use strict"; // jshint ;_;


  /* MODAL CLASS DEFINITION
   * ====================== */

  var Modal = function (element, options) {
    this.options = options
    this.$element = $(element)
        .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
    this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
  }

  Modal.prototype = {

    constructor: Modal

    , toggle: function () {
      return this[!this.isShown ? 'show' : 'hide']()
    }

    , show: function () {
      var that = this
          , e = $.Event('show')

      this.$element.trigger(e)

      if (this.isShown || e.isDefaultPrevented()) return

      this.isShown = true

      this.escape()

      this.backdrop(function () {
        var transition = $.support.transition && that.$element.hasClass('fade')

        if (!that.$element.parent().length) {
          that.$element.appendTo(document.body) //don't move modals dom position
        }

        that.$element
            .show()

        if (transition) {
          that.$element[0].offsetWidth // force reflow
        }

        that.$element
            .addClass('in')
            .attr('aria-hidden', false)

        that.enforceFocus()

        transition ?
            that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :
            that.$element.focus().trigger('shown')

      })
    }

    , hide: function (e) {
      e && e.preventDefault()

      var that = this

      e = $.Event('hide')

      this.$element.trigger(e)

      if (!this.isShown || e.isDefaultPrevented()) return

      this.isShown = false

      this.escape()

      $(document).off('focusin.modal')

      this.$element
          .removeClass('in')
          .attr('aria-hidden', true)

      $.support.transition && this.$element.hasClass('fade') ?
          this.hideWithTransition() :
          this.hideModal()
    }

    , enforceFocus: function () {
      var that = this
      $(document).on('focusin.modal', function (e) {
        if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
          that.$element.focus()
        }
      })
    }

    , escape: function () {
      var that = this
      if (this.isShown && this.options.keyboard) {
        this.$element.on('keyup.dismiss.modal', function ( e ) {
          e.which == 27 && that.hide()
        })
      } else if (!this.isShown) {
        this.$element.off('keyup.dismiss.modal')
      }
    }

    , hideWithTransition: function () {
      var that = this
          , timeout = setTimeout(function () {
            that.$element.off($.support.transition.end)
            that.hideModal()
          }, 500)

      this.$element.one($.support.transition.end, function () {
        clearTimeout(timeout)
        that.hideModal()
      })
    }

    , hideModal: function (that) {
      this.$element
          .hide()
          .trigger('hidden')

      this.backdrop()
    }

    , removeBackdrop: function () {
      this.$backdrop.remove()
      this.$backdrop = null
    }

    , backdrop: function (callback) {
      var that = this
          , animate = this.$element.hasClass('fade') ? 'fade' : ''

      if (this.isShown && this.options.backdrop) {
        var doAnimate = $.support.transition && animate

        this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
            .appendTo(document.body)

        this.$backdrop.click(
            this.options.backdrop == 'static' ?
                $.proxy(this.$element[0].focus, this.$element[0])
                : $.proxy(this.hide, this)
        )

        if (doAnimate) this.$backdrop[0].offsetWidth // force reflow

        this.$backdrop.addClass('in')

        doAnimate ?
            this.$backdrop.one($.support.transition.end, callback) :
            callback()

      } else if (!this.isShown && this.$backdrop) {
        this.$backdrop.removeClass('in')

        $.support.transition && this.$element.hasClass('fade')?
            this.$backdrop.one($.support.transition.end, $.proxy(this.removeBackdrop, this)) :
            this.removeBackdrop()

      } else if (callback) {
        callback()
      }
    }
  }


  /* MODAL PLUGIN DEFINITION
   * ======================= */

  var old = $.fn.modal

  $.fn.modal = function (option) {
    return this.each(function () {
      var $this = $(this)
          , data = $this.data('modal')
          , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
      if (!data) $this.data('modal', (data = new Modal(this, options)))
      if (typeof option == 'string') data[option]()
      else if (options.show) data.show()
    })
  }

  $.fn.modal.defaults = {
    backdrop: true
    , keyboard: true
    , show: true
  }

  $.fn.modal.Constructor = Modal


  /* MODAL NO CONFLICT
   * ================= */

  $.fn.modal.noConflict = function () {
    $.fn.modal = old
    return this
  }


  /* MODAL DATA-API
   * ============== */

  $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) {
    var $this = $(this)
        , href = $this.attr('href')
        , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
        , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())

    e.preventDefault()

    $target
        .modal(option)
        .one('hide', function () {
          $this.focus()
        })
  })

}(window.jQuery);
/* ===========================================================
 * bootstrap-tooltip.js v2.3.2
 * http://getbootstrap.com/2.3.2/javascript.html#tooltips
 * Inspired by the original jQuery.tipsy by Jason Frame
 * ===========================================================
 * Copyright 2013 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================== */


!function ($) {

  "use strict"; // jshint ;_;


 /* TOOLTIP PUBLIC CLASS DEFINITION
  * =============================== */

  var Tooltip = function (element, options) {
    this.init('tooltip', element, options)
  }

  Tooltip.prototype = {

    constructor: Tooltip

  , init: function (type, element, options) {
      var eventIn
        , eventOut
        , triggers
        , trigger
        , i

      this.type = type
      this.$element = $(element)
      this.options = this.getOptions(options)
      this.enabled = true

      triggers = this.options.trigger.split(' ')

      for (i = triggers.length; i--;) {
        trigger = triggers[i]
        if (trigger == 'click') {
          this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
        } else if (trigger != 'manual') {
          eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
          eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
          this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
          this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
        }
      }

      this.options.selector ?
        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
        this.fixTitle()
    }

  , getOptions: function (options) {
      options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options)

      if (options.delay && typeof options.delay == 'number') {
        options.delay = {
          show: options.delay
        , hide: options.delay
        }
      }

      return options
    }

  , enter: function (e) {
      var defaults = $.fn[this.type].defaults
        , options = {}
        , self

      this._options && $.each(this._options, function (key, value) {
        if (defaults[key] != value) options[key] = value
      }, this)

      self = $(e.currentTarget)[this.type](options).data(this.type)

      if (!self.options.delay || !self.options.delay.show) return self.show()

      clearTimeout(this.timeout)
      self.hoverState = 'in'
      this.timeout = setTimeout(function() {
        if (self.hoverState == 'in') self.show()
      }, self.options.delay.show)
    }

  , leave: function (e) {
      var self = $(e.currentTarget)[this.type](this._options).data(this.type)

      if (this.timeout) clearTimeout(this.timeout)
      if (!self.options.delay || !self.options.delay.hide) return self.hide()

      self.hoverState = 'out'
      this.timeout = setTimeout(function() {
        if (self.hoverState == 'out') self.hide()
      }, self.options.delay.hide)
    }

  , show: function () {
      var $tip
        , pos
        , actualWidth
        , actualHeight
        , placement
        , tp
        , e = $.Event('show')

      if (this.hasContent() && this.enabled) {
        this.$element.trigger(e)
        if (e.isDefaultPrevented()) return
        $tip = this.tip()
        this.setContent()

        if (this.options.animation) {
          $tip.addClass('fade')
        }

        placement = typeof this.options.placement == 'function' ?
          this.options.placement.call(this, $tip[0], this.$element[0]) :
          this.options.placement

        $tip
          .detach()
          .css({ top: 0, left: 0, display: 'block' })

        this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)

        pos = this.getPosition()

        actualWidth = $tip[0].offsetWidth
        actualHeight = $tip[0].offsetHeight

        switch (placement) {
          case 'bottom':
            tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
            break
          case 'top':
            tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
            break
          case 'left':
            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
            break
          case 'right':
            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
            break
        }

        this.applyPlacement(tp, placement)
        this.$element.trigger('shown')
      }
    }

  , applyPlacement: function(offset, placement){
      var $tip = this.tip()
        , width = $tip[0].offsetWidth
        , height = $tip[0].offsetHeight
        , actualWidth
        , actualHeight
        , delta
        , replace

      $tip
        .offset(offset)
        .addClass(placement)
        .addClass('in')

      actualWidth = $tip[0].offsetWidth
      actualHeight = $tip[0].offsetHeight

      if (placement == 'top' && actualHeight != height) {
        offset.top = offset.top + height - actualHeight
        replace = true
      }

      if (placement == 'bottom' || placement == 'top') {
        delta = 0

        if (offset.left < 0){
          delta = offset.left * -2
          offset.left = 0
          $tip.offset(offset)
          actualWidth = $tip[0].offsetWidth
          actualHeight = $tip[0].offsetHeight
        }

        this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
      } else {
        this.replaceArrow(actualHeight - height, actualHeight, 'top')
      }

      if (replace) $tip.offset(offset)
    }

  , replaceArrow: function(delta, dimension, position){
      this
        .arrow()
        .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
    }

  , setContent: function () {
      var $tip = this.tip()
        , title = this.getTitle()

      $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
      $tip.removeClass('fade in top bottom left right')
    }

  , hide: function () {
      var that = this
        , $tip = this.tip()
        , e = $.Event('hide')

      this.$element.trigger(e)
      if (e.isDefaultPrevented()) return

      $tip.removeClass('in')

      function removeWithAnimation() {
        var timeout = setTimeout(function () {
          $tip.off($.support.transition.end).detach()
        }, 500)

        $tip.one($.support.transition.end, function () {
          clearTimeout(timeout)
          $tip.detach()
        })
      }

      $.support.transition && this.$tip.hasClass('fade') ?
        removeWithAnimation() :
        $tip.detach()

      this.$element.trigger('hidden')

      return this
    }

  , fixTitle: function () {
      var $e = this.$element
      if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
        $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
      }
    }

  , hasContent: function () {
      return this.getTitle()
    }

  , getPosition: function () {
      var el = this.$element[0]
      return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
        width: el.offsetWidth
      , height: el.offsetHeight
      }, this.$element.offset())
    }

  , getTitle: function () {
      var title
        , $e = this.$element
        , o = this.options

      title = $e.attr('data-original-title')
        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)

      return title
    }

  , tip: function () {
      return this.$tip = this.$tip || $(this.options.template)
    }

  , arrow: function(){
      return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
    }

  , validate: function () {
      if (!this.$element[0].parentNode) {
        this.hide()
        this.$element = null
        this.options = null
      }
    }

  , enable: function () {
      this.enabled = true
    }

  , disable: function () {
      this.enabled = false
    }

  , toggleEnabled: function () {
      this.enabled = !this.enabled
    }

  , toggle: function (e) {
      var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this
      self.tip().hasClass('in') ? self.hide() : self.show()
    }

  , destroy: function () {
      this.hide().$element.off('.' + this.type).removeData(this.type)
    }

  }


 /* TOOLTIP PLUGIN DEFINITION
  * ========================= */

  var old = $.fn.tooltip

  $.fn.tooltip = function ( option ) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('tooltip')
        , options = typeof option == 'object' && option
      if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  $.fn.tooltip.Constructor = Tooltip

  $.fn.tooltip.defaults = {
    animation: true
  , placement: 'top'
  , selector: false
  , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
  , trigger: 'hover focus'
  , title: ''
  , delay: 0
  , html: false
  , container: false
  }


 /* TOOLTIP NO CONFLICT
  * =================== */

  $.fn.tooltip.noConflict = function () {
    $.fn.tooltip = old
    return this
  }

}(window.jQuery);

/* ===========================================================
 * bootstrap-popover.js v2.3.2
 * http://getbootstrap.com/2.3.2/javascript.html#popovers
 * ===========================================================
 * Copyright 2013 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =========================================================== */


!function ($) {

  "use strict"; // jshint ;_;


 /* POPOVER PUBLIC CLASS DEFINITION
  * =============================== */

  var Popover = function (element, options) {
    this.init('popover', element, options)
  }


  /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
     ========================================== */

  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {

    constructor: Popover

  , setContent: function () {
      var $tip = this.tip()
        , title = this.getTitle()
        , content = this.getContent()

      $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
      $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)

      $tip.removeClass('fade top bottom left right in')
    }

  , hasContent: function () {
      return this.getTitle() || this.getContent()
    }

  , getContent: function () {
      var content
        , $e = this.$element
        , o = this.options

      content = (typeof o.content == 'function' ? o.content.call($e[0]) :  o.content)
        || $e.attr('data-content')

      return content
    }

  , tip: function () {
      if (!this.$tip) {
        this.$tip = $(this.options.template)
      }
      return this.$tip
    }

  , destroy: function () {
      this.hide().$element.off('.' + this.type).removeData(this.type)
    }

  })


 /* POPOVER PLUGIN DEFINITION
  * ======================= */

  var old = $.fn.popover

  $.fn.popover = function (option) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('popover')
        , options = typeof option == 'object' && option
      if (!data) $this.data('popover', (data = new Popover(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  $.fn.popover.Constructor = Popover

  $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
    placement: 'right'
  , trigger: 'click'
  , content: ''
  , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
  })


 /* POPOVER NO CONFLICT
  * =================== */

  $.fn.popover.noConflict = function () {
    $.fn.popover = old
    return this
  }

}(window.jQuery);

/*
 * angular-ui-bootstrap
 * http://angular-ui.github.io/bootstrap/

 * Version: 0.10.0 - 2014-01-13
 * License: MIT
 */
angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdownToggle","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]);
angular.module("ui.bootstrap.tpls", ["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/popup.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]);
angular.module('ui.bootstrap.transition', [])

/**
 * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete.
 * @param  {DOMElement} element  The DOMElement that will be animated.
 * @param  {string|object|function} trigger  The thing that will cause the transition to start:
 *   - As a string, it represents the css class to be added to the element.
 *   - As an object, it represents a hash of style attributes to be applied to the element.
 *   - As a function, it represents a function to be called that will cause the transition to occur.
 * @return {Promise}  A promise that is resolved when the transition finishes.
 */
.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {

  var $transition = function(element, trigger, options) {
    options = options || {};
    var deferred = $q.defer();
    var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"];

    var transitionEndHandler = function(event) {
      $rootScope.$apply(function() {
        element.unbind(endEventName, transitionEndHandler);
        deferred.resolve(element);
      });
    };

    if (endEventName) {
      element.bind(endEventName, transitionEndHandler);
    }

    // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur
    $timeout(function() {
      if ( angular.isString(trigger) ) {
        element.addClass(trigger);
      } else if ( angular.isFunction(trigger) ) {
        trigger(element);
      } else if ( angular.isObject(trigger) ) {
        element.css(trigger);
      }
      //If browser does not support transitions, instantly resolve
      if ( !endEventName ) {
        deferred.resolve(element);
      }
    });

    // Add our custom cancel function to the promise that is returned
    // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,
    // i.e. it will therefore never raise a transitionEnd event for that transition
    deferred.promise.cancel = function() {
      if ( endEventName ) {
        element.unbind(endEventName, transitionEndHandler);
      }
      deferred.reject('Transition cancelled');
    };

    return deferred.promise;
  };

  // Work out the name of the transitionEnd event
  var transElement = document.createElement('trans');
  var transitionEndEventNames = {
    'WebkitTransition': 'webkitTransitionEnd',
    'MozTransition': 'transitionend',
    'OTransition': 'oTransitionEnd',
    'transition': 'transitionend'
  };
  var animationEndEventNames = {
    'WebkitTransition': 'webkitAnimationEnd',
    'MozTransition': 'animationend',
    'OTransition': 'oAnimationEnd',
    'transition': 'animationend'
  };
  function findEndEventName(endEventNames) {
    for (var name in endEventNames){
      if (transElement.style[name] !== undefined) {
        return endEventNames[name];
      }
    }
  }
  $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
  $transition.animationEndEventName = findEndEventName(animationEndEventNames);
  return $transition;
}]);

angular.module('ui.bootstrap.collapse', ['ui.bootstrap.transition'])

  .directive('collapse', ['$transition', function ($transition, $timeout) {

    return {
      link: function (scope, element, attrs) {

        var initialAnimSkip = true;
        var currentTransition;

        function doTransition(change) {
          var newTransition = $transition(element, change);
          if (currentTransition) {
            currentTransition.cancel();
          }
          currentTransition = newTransition;
          newTransition.then(newTransitionDone, newTransitionDone);
          return newTransition;

          function newTransitionDone() {
            // Make sure it's this transition, otherwise, leave it alone.
            if (currentTransition === newTransition) {
              currentTransition = undefined;
            }
          }
        }

        function expand() {
          if (initialAnimSkip) {
            initialAnimSkip = false;
            expandDone();
          } else {
            element.removeClass('collapse').addClass('collapsing');
            doTransition({ height: element[0].scrollHeight + 'px' }).then(expandDone);
          }
        }

        function expandDone() {
          element.removeClass('collapsing');
          element.addClass('collapse in');
          element.css({height: 'auto'});
        }

        function collapse() {
          if (initialAnimSkip) {
            initialAnimSkip = false;
            collapseDone();
            element.css({height: 0});
          } else {
            // CSS transitions don't work with height: auto, so we have to manually change the height to a specific value
            element.css({ height: element[0].scrollHeight + 'px' });
            //trigger reflow so a browser realizes that height was updated from auto to a specific value
            var x = element[0].offsetWidth;

            element.removeClass('collapse in').addClass('collapsing');

            doTransition({ height: 0 }).then(collapseDone);
          }
        }

        function collapseDone() {
          element.removeClass('collapsing');
          element.addClass('collapse');
        }

        scope.$watch(attrs.collapse, function (shouldCollapse) {
          if (shouldCollapse) {
            collapse();
          } else {
            expand();
          }
        });
      }
    };
  }]);

angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])

.constant('accordionConfig', {
  closeOthers: true
})

.controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) {

  // This array keeps track of the accordion groups
  this.groups = [];

  // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
  this.closeOthers = function(openGroup) {
    var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
    if ( closeOthers ) {
      angular.forEach(this.groups, function (group) {
        if ( group !== openGroup ) {
          group.isOpen = false;
        }
      });
    }
  };
  
  // This is called from the accordion-group directive to add itself to the accordion
  this.addGroup = function(groupScope) {
    var that = this;
    this.groups.push(groupScope);

    groupScope.$on('$destroy', function (event) {
      that.removeGroup(groupScope);
    });
  };

  // This is called from the accordion-group directive when to remove itself
  this.removeGroup = function(group) {
    var index = this.groups.indexOf(group);
    if ( index !== -1 ) {
      this.groups.splice(this.groups.indexOf(group), 1);
    }
  };

}])

// The accordion directive simply sets up the directive controller
// and adds an accordion CSS class to itself element.
.directive('accordion', function () {
  return {
    restrict:'EA',
    controller:'AccordionController',
    transclude: true,
    replace: false,
    templateUrl: 'template/accordion/accordion.html'
  };
})

// The accordion-group directive indicates a block of html that will expand and collapse in an accordion
.directive('accordionGroup', ['$parse', function($parse) {
  return {
    require:'^accordion',         // We need this directive to be inside an accordion
    restrict:'EA',
    transclude:true,              // It transcludes the contents of the directive into the template
    replace: true,                // The element containing the directive will be replaced with the template
    templateUrl:'template/accordion/accordion-group.html',
    scope:{ heading:'@' },        // Create an isolated scope and interpolate the heading attribute onto this scope
    controller: function() {
      this.setHeading = function(element) {
        this.heading = element;
      };
    },
    link: function(scope, element, attrs, accordionCtrl) {
      var getIsOpen, setIsOpen;

      accordionCtrl.addGroup(scope);

      scope.isOpen = false;
      
      if ( attrs.isOpen ) {
        getIsOpen = $parse(attrs.isOpen);
        setIsOpen = getIsOpen.assign;

        scope.$parent.$watch(getIsOpen, function(value) {
          scope.isOpen = !!value;
        });
      }

      scope.$watch('isOpen', function(value) {
        if ( value ) {
          accordionCtrl.closeOthers(scope);
        }
        if ( setIsOpen ) {
          setIsOpen(scope.$parent, value);
        }
      });
    }
  };
}])

// Use accordion-heading below an accordion-group to provide a heading containing HTML
// <accordion-group>
//   <accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
// </accordion-group>
.directive('accordionHeading', function() {
  return {
    restrict: 'EA',
    transclude: true,   // Grab the contents to be used as the heading
    template: '',       // In effect remove this element!
    replace: true,
    require: '^accordionGroup',
    compile: function(element, attr, transclude) {
      return function link(scope, element, attr, accordionGroupCtrl) {
        // Pass the heading to the accordion-group controller
        // so that it can be transcluded into the right place in the template
        // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
        accordionGroupCtrl.setHeading(transclude(scope, function() {}));
      };
    }
  };
})

// Use in the accordion-group template to indicate where you want the heading to be transcluded
// You must provide the property on the accordion-group controller that will hold the transcluded element
// <div class="accordion-group">
//   <div class="accordion-heading" ><a ... accordion-transclude="heading">...</a></div>
//   ...
// </div>
.directive('accordionTransclude', function() {
  return {
    require: '^accordionGroup',
    link: function(scope, element, attr, controller) {
      scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) {
        if ( heading ) {
          element.html('');
          element.append(heading);
        }
      });
    }
  };
});

angular.module("ui.bootstrap.alert", [])

.controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) {
  $scope.closeable = 'close' in $attrs;
}])

.directive('alert', function () {
  return {
    restrict:'EA',
    controller:'AlertController',
    templateUrl:'template/alert/alert.html',
    transclude:true,
    replace:true,
    scope: {
      type: '=',
      close: '&'
    }
  };
});

angular.module('ui.bootstrap.bindHtml', [])

  .directive('bindHtmlUnsafe', function () {
    return function (scope, element, attr) {
      element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe);
      scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) {
        element.html(value || '');
      });
    };
  });
angular.module('ui.bootstrap.buttons', [])

.constant('buttonConfig', {
  activeClass: 'active',
  toggleEvent: 'click'
})

.controller('ButtonsController', ['buttonConfig', function(buttonConfig) {
  this.activeClass = buttonConfig.activeClass || 'active';
  this.toggleEvent = buttonConfig.toggleEvent || 'click';
}])

.directive('btnRadio', function () {
  return {
    require: ['btnRadio', 'ngModel'],
    controller: 'ButtonsController',
    link: function (scope, element, attrs, ctrls) {
      var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];

      //model -> UI
      ngModelCtrl.$render = function () {
        element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio)));
      };

      //ui->model
      element.bind(buttonsCtrl.toggleEvent, function () {
        if (!element.hasClass(buttonsCtrl.activeClass)) {
          scope.$apply(function () {
            ngModelCtrl.$setViewValue(scope.$eval(attrs.btnRadio));
            ngModelCtrl.$render();
          });
        }
      });
    }
  };
})

.directive('btnCheckbox', function () {
  return {
    require: ['btnCheckbox', 'ngModel'],
    controller: 'ButtonsController',
    link: function (scope, element, attrs, ctrls) {
      var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];

      function getTrueValue() {
        return getCheckboxValue(attrs.btnCheckboxTrue, true);
      }

      function getFalseValue() {
        return getCheckboxValue(attrs.btnCheckboxFalse, false);
      }
      
      function getCheckboxValue(attributeValue, defaultValue) {
        var val = scope.$eval(attributeValue);
        return angular.isDefined(val) ? val : defaultValue;
      }

      //model -> UI
      ngModelCtrl.$render = function () {
        element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
      };

      //ui->model
      element.bind(buttonsCtrl.toggleEvent, function () {
        scope.$apply(function () {
          ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());
          ngModelCtrl.$render();
        });
      });
    }
  };
});

/**
* @ngdoc overview
* @name ui.bootstrap.carousel
*
* @description
* AngularJS version of an image carousel.
*
*/
angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
.controller('CarouselController', ['$scope', '$timeout', '$transition', '$q', function ($scope, $timeout, $transition, $q) {
  var self = this,
    slides = self.slides = [],
    currentIndex = -1,
    currentTimeout, isPlaying;
  self.currentSlide = null;

  var destroyed = false;
  /* direction: "prev" or "next" */
  self.select = function(nextSlide, direction) {
    var nextIndex = slides.indexOf(nextSlide);
    //Decide direction if it's not given
    if (direction === undefined) {
      direction = nextIndex > currentIndex ? "next" : "prev";
    }
    if (nextSlide && nextSlide !== self.currentSlide) {
      if ($scope.$currentTransition) {
        $scope.$currentTransition.cancel();
        //Timeout so ng-class in template has time to fix classes for finished slide
        $timeout(goNext);
      } else {
        goNext();
      }
    }
    function goNext() {
      // Scope has been destroyed, stop here.
      if (destroyed) { return; }
      //If we have a slide to transition from and we have a transition type and we're allowed, go
      if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) {
        //We shouldn't do class manip in here, but it's the same weird thing bootstrap does. need to fix sometime
        nextSlide.$element.addClass(direction);
        var reflow = nextSlide.$element[0].offsetWidth; //force reflow

        //Set all other slides to stop doing their stuff for the new transition
        angular.forEach(slides, function(slide) {
          angular.extend(slide, {direction: '', entering: false, leaving: false, active: false});
        });
        angular.extend(nextSlide, {direction: direction, active: true, entering: true});
        angular.extend(self.currentSlide||{}, {direction: direction, leaving: true});

        $scope.$currentTransition = $transition(nextSlide.$element, {});
        //We have to create new pointers inside a closure since next & current will change
        (function(next,current) {
          $scope.$currentTransition.then(
            function(){ transitionDone(next, current); },
            function(){ transitionDone(next, current); }
          );
        }(nextSlide, self.currentSlide));
      } else {
        transitionDone(nextSlide, self.currentSlide);
      }
      self.currentSlide = nextSlide;
      currentIndex = nextIndex;
      //every time you change slides, reset the timer
      restartTimer();
    }
    function transitionDone(next, current) {
      angular.extend(next, {direction: '', active: true, leaving: false, entering: false});
      angular.extend(current||{}, {direction: '', active: false, leaving: false, entering: false});
      $scope.$currentTransition = null;
    }
  };
  $scope.$on('$destroy', function () {
    destroyed = true;
  });

  /* Allow outside people to call indexOf on slides array */
  self.indexOfSlide = function(slide) {
    return slides.indexOf(slide);
  };

  $scope.next = function() {
    var newIndex = (currentIndex + 1) % slides.length;

    //Prevent this user-triggered transition from occurring if there is already one in progress
    if (!$scope.$currentTransition) {
      return self.select(slides[newIndex], 'next');
    }
  };

  $scope.prev = function() {
    var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1;

    //Prevent this user-triggered transition from occurring if there is already one in progress
    if (!$scope.$currentTransition) {
      return self.select(slides[newIndex], 'prev');
    }
  };

  $scope.select = function(slide) {
    self.select(slide);
  };

  $scope.isActive = function(slide) {
     return self.currentSlide === slide;
  };

  $scope.slides = function() {
    return slides;
  };

  $scope.$watch('interval', restartTimer);
  $scope.$on('$destroy', resetTimer);

  function restartTimer() {
    resetTimer();
    var interval = +$scope.interval;
    if (!isNaN(interval) && interval>=0) {
      currentTimeout = $timeout(timerFn, interval);
    }
  }

  function resetTimer() {
    if (currentTimeout) {
      $timeout.cancel(currentTimeout);
      currentTimeout = null;
    }
  }

  function timerFn() {
    if (isPlaying) {
      $scope.next();
      restartTimer();
    } else {
      $scope.pause();
    }
  }

  $scope.play = function() {
    if (!isPlaying) {
      isPlaying = true;
      restartTimer();
    }
  };
  $scope.pause = function() {
    if (!$scope.noPause) {
      isPlaying = false;
      resetTimer();
    }
  };

  self.addSlide = function(slide, element) {
    slide.$element = element;
    slides.push(slide);
    //if this is the first slide or the slide is set to active, select it
    if(slides.length === 1 || slide.active) {
      self.select(slides[slides.length-1]);
      if (slides.length == 1) {
        $scope.play();
      }
    } else {
      slide.active = false;
    }
  };

  self.removeSlide = function(slide) {
    //get the index of the slide inside the carousel
    var index = slides.indexOf(slide);
    slides.splice(index, 1);
    if (slides.length > 0 && slide.active) {
      if (index >= slides.length) {
        self.select(slides[index-1]);
      } else {
        self.select(slides[index]);
      }
    } else if (currentIndex > index) {
      currentIndex--;
    }
  };

}])

/**
 * @ngdoc directive
 * @name ui.bootstrap.carousel.directive:carousel
 * @restrict EA
 *
 * @description
 * Carousel is the outer container for a set of image 'slides' to showcase.
 *
 * @param {number=} interval The time, in milliseconds, that it will take the carousel to go to the next slide.
 * @param {boolean=} noTransition Whether to disable transitions on the carousel.
 * @param {boolean=} noPause Whether to disable pausing on the carousel (by default, the carousel interval pauses on hover).
 *
 * @example
<example module="ui.bootstrap">
  <file name="index.html">
    <carousel>
      <slide>
        <img src="http://placekitten.com/150/150" style="margin:auto;">
        <div class="carousel-caption">
          <p>Beautiful!</p>
        </div>
      </slide>
      <slide>
        <img src="http://placekitten.com/100/150" style="margin:auto;">
        <div class="carousel-caption">
          <p>D'aww!</p>
        </div>
      </slide>
    </carousel>
  </file>
  <file name="demo.css">
    .carousel-indicators {
      top: auto;
      bottom: 15px;
    }
  </file>
</example>
 */
.directive('carousel', [function() {
  return {
    restrict: 'EA',
    transclude: true,
    replace: true,
    controller: 'CarouselController',
    require: 'carousel',
    templateUrl: 'template/carousel/carousel.html',
    scope: {
      interval: '=',
      noTransition: '=',
      noPause: '='
    }
  };
}])

/**
 * @ngdoc directive
 * @name ui.bootstrap.carousel.directive:slide
 * @restrict EA
 *
 * @description
 * Creates a slide inside a {@link ui.bootstrap.carousel.directive:carousel carousel}.  Must be placed as a child of a carousel element.
 *
 * @param {boolean=} active Model binding, whether or not this slide is currently active.
 *
 * @example
<example module="ui.bootstrap">
  <file name="index.html">
<div ng-controller="CarouselDemoCtrl">
  <carousel>
    <slide ng-repeat="slide in slides" active="slide.active">
      <img ng-src="{{slide.image}}" style="margin:auto;">
      <div class="carousel-caption">
        <h4>Slide {{$index}}</h4>
        <p>{{slide.text}}</p>
      </div>
    </slide>
  </carousel>
  <div class="row-fluid">
    <div class="span6">
      <ul>
        <li ng-repeat="slide in slides">
          <button class="btn btn-mini" ng-class="{'btn-info': !slide.active, 'btn-success': slide.active}" ng-disabled="slide.active" ng-click="slide.active = true">select</button>
          {{$index}}: {{slide.text}}
        </li>
      </ul>
      <a class="btn" ng-click="addSlide()">Add Slide</a>
    </div>
    <div class="span6">
      Interval, in milliseconds: <input type="number" ng-model="myInterval">
      <br />Enter a negative number to stop the interval.
    </div>
  </div>
</div>
  </file>
  <file name="script.js">
function CarouselDemoCtrl($scope) {
  $scope.myInterval = 5000;
  var slides = $scope.slides = [];
  $scope.addSlide = function() {
    var newWidth = 200 + ((slides.length + (25 * slides.length)) % 150);
    slides.push({
      image: 'http://placekitten.com/' + newWidth + '/200',
      text: ['More','Extra','Lots of','Surplus'][slides.length % 4] + ' '
        ['Cats', 'Kittys', 'Felines', 'Cutes'][slides.length % 4]
    });
  };
  for (var i=0; i<4; i++) $scope.addSlide();
}
  </file>
  <file name="demo.css">
    .carousel-indicators {
      top: auto;
      bottom: 15px;
    }
  </file>
</example>
*/

.directive('slide', ['$parse', function($parse) {
  return {
    require: '^carousel',
    restrict: 'EA',
    transclude: true,
    replace: true,
    templateUrl: 'template/carousel/slide.html',
    scope: {
    },
    link: function (scope, element, attrs, carouselCtrl) {
      //Set up optional 'active' = binding
      if (attrs.active) {
        var getActive = $parse(attrs.active);
        var setActive = getActive.assign;
        var lastValue = scope.active = getActive(scope.$parent);
        scope.$watch(function parentActiveWatch() {
          var parentActive = getActive(scope.$parent);

          if (parentActive !== scope.active) {
            // we are out of sync and need to copy
            if (parentActive !== lastValue) {
              // parent changed and it has precedence
              lastValue = scope.active = parentActive;
            } else {
              // if the parent can be assigned then do so
              setActive(scope.$parent, parentActive = lastValue = scope.active);
            }
          }
          return parentActive;
        });
      }

      carouselCtrl.addSlide(scope, element);
      //when the scope is destroyed then remove the slide from the current slides array
      scope.$on('$destroy', function() {
        carouselCtrl.removeSlide(scope);
      });

      scope.$watch('active', function(active) {
        if (active) {
          carouselCtrl.select(scope);
        }
      });
    }
  };
}]);

angular.module('ui.bootstrap.position', [])

/**
 * A set of utility methods that can be use to retrieve position of DOM elements.
 * It is meant to be used where we need to absolute-position DOM elements in
 * relation to other, existing elements (this is the case for tooltips, popovers,
 * typeahead suggestions etc.).
 */
  .factory('$position', ['$document', '$window', function ($document, $window) {

    function getStyle(el, cssprop) {
      if (el.currentStyle) { //IE
        return el.currentStyle[cssprop];
      } else if ($window.getComputedStyle) {
        return $window.getComputedStyle(el)[cssprop];
      }
      // finally try and get inline style
      return el.style[cssprop];
    }

    /**
     * Checks if a given element is statically positioned
     * @param element - raw DOM element
     */
    function isStaticPositioned(element) {
      return (getStyle(element, "position") || 'static' ) === 'static';
    }

    /**
     * returns the closest, non-statically positioned parentOffset of a given element
     * @param element
     */
    var parentOffsetEl = function (element) {
      var docDomEl = $document[0];
      var offsetParent = element.offsetParent || docDomEl;
      while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) {
        offsetParent = offsetParent.offsetParent;
      }
      return offsetParent || docDomEl;
    };

    return {
      /**
       * Provides read-only equivalent of jQuery's position function:
       * http://api.jquery.com/position/
       */
      position: function (element) {
        var elBCR = this.offset(element);
        var offsetParentBCR = { top: 0, left: 0 };
        var offsetParentEl = parentOffsetEl(element[0]);
        if (offsetParentEl != $document[0]) {
          offsetParentBCR = this.offset(angular.element(offsetParentEl));
          offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
          offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
        }

        var boundingClientRect = element[0].getBoundingClientRect();
        return {
          width: boundingClientRect.width || element.prop('offsetWidth'),
          height: boundingClientRect.height || element.prop('offsetHeight'),
          top: elBCR.top - offsetParentBCR.top,
          left: elBCR.left - offsetParentBCR.left
        };
      },

      /**
       * Provides read-only equivalent of jQuery's offset function:
       * http://api.jquery.com/offset/
       */
      offset: function (element) {
        var boundingClientRect = element[0].getBoundingClientRect();
        return {
          width: boundingClientRect.width || element.prop('offsetWidth'),
          height: boundingClientRect.height || element.prop('offsetHeight'),
          top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop),
          left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft  || $document[0].documentElement.scrollLeft)
        };
      }
    };
  }]);

angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.position'])

.constant('datepickerConfig', {
  dayFormat: 'dd',
  monthFormat: 'MMMM',
  yearFormat: 'yyyy',
  dayHeaderFormat: 'EEE',
  dayTitleFormat: 'MMMM yyyy',
  monthTitleFormat: 'yyyy',
  showWeeks: true,
  startingDay: 0,
  yearRange: 20,
  minDate: null,
  maxDate: null
})

.controller('DatepickerController', ['$scope', '$attrs', 'dateFilter', 'datepickerConfig', function($scope, $attrs, dateFilter, dtConfig) {
  var format = {
    day:        getValue($attrs.dayFormat,        dtConfig.dayFormat),
    month:      getValue($attrs.monthFormat,      dtConfig.monthFormat),
    year:       getValue($attrs.yearFormat,       dtConfig.yearFormat),
    dayHeader:  getValue($attrs.dayHeaderFormat,  dtConfig.dayHeaderFormat),
    dayTitle:   getValue($attrs.dayTitleFormat,   dtConfig.dayTitleFormat),
    monthTitle: getValue($attrs.monthTitleFormat, dtConfig.monthTitleFormat)
  },
  startingDay = getValue($attrs.startingDay,      dtConfig.startingDay),
  yearRange =   getValue($attrs.yearRange,        dtConfig.yearRange);

  this.minDate = dtConfig.minDate ? new Date(dtConfig.minDate) : null;
  this.maxDate = dtConfig.maxDate ? new Date(dtConfig.maxDate) : null;

  function getValue(value, defaultValue) {
    return angular.isDefined(value) ? $scope.$parent.$eval(value) : defaultValue;
  }

  function getDaysInMonth( year, month ) {
    return new Date(year, month, 0).getDate();
  }

  function getDates(startDate, n) {
    var dates = new Array(n);
    var current = startDate, i = 0;
    while (i < n) {
      dates[i++] = new Date(current);
      current.setDate( current.getDate() + 1 );
    }
    return dates;
  }

  function makeDate(date, format, isSelected, isSecondary) {
    return { date: date, label: dateFilter(date, format), selected: !!isSelected, secondary: !!isSecondary };
  }

  this.modes = [
    {
      name: 'day',
      getVisibleDates: function(date, selected) {
        var year = date.getFullYear(), month = date.getMonth(), firstDayOfMonth = new Date(year, month, 1);
        var difference = startingDay - firstDayOfMonth.getDay(),
        numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference,
        firstDate = new Date(firstDayOfMonth), numDates = 0;

        if ( numDisplayedFromPreviousMonth > 0 ) {
          firstDate.setDate( - numDisplayedFromPreviousMonth + 1 );
          numDates += numDisplayedFromPreviousMonth; // Previous
        }
        numDates += getDaysInMonth(year, month + 1); // Current
        numDates += (7 - numDates % 7) % 7; // Next

        var days = getDates(firstDate, numDates), labels = new Array(7);
        for (var i = 0; i < numDates; i ++) {
          var dt = new Date(days[i]);
          days[i] = makeDate(dt, format.day, (selected && selected.getDate() === dt.getDate() && selected.getMonth() === dt.getMonth() && selected.getFullYear() === dt.getFullYear()), dt.getMonth() !== month);
        }
        for (var j = 0; j < 7; j++) {
          labels[j] = dateFilter(days[j].date, format.dayHeader);
        }
        return { objects: days, title: dateFilter(date, format.dayTitle), labels: labels };
      },
      compare: function(date1, date2) {
        return (new Date( date1.getFullYear(), date1.getMonth(), date1.getDate() ) - new Date( date2.getFullYear(), date2.getMonth(), date2.getDate() ) );
      },
      split: 7,
      step: { months: 1 }
    },
    {
      name: 'month',
      getVisibleDates: function(date, selected) {
        var months = new Array(12), year = date.getFullYear();
        for ( var i = 0; i < 12; i++ ) {
          var dt = new Date(year, i, 1);
          months[i] = makeDate(dt, format.month, (selected && selected.getMonth() === i && selected.getFullYear() === year));
        }
        return { objects: months, title: dateFilter(date, format.monthTitle) };
      },
      compare: function(date1, date2) {
        return new Date( date1.getFullYear(), date1.getMonth() ) - new Date( date2.getFullYear(), date2.getMonth() );
      },
      split: 3,
      step: { years: 1 }
    },
    {
      name: 'year',
      getVisibleDates: function(date, selected) {
        var years = new Array(yearRange), year = date.getFullYear(), startYear = parseInt((year - 1) / yearRange, 10) * yearRange + 1;
        for ( var i = 0; i < yearRange; i++ ) {
          var dt = new Date(startYear + i, 0, 1);
          years[i] = makeDate(dt, format.year, (selected && selected.getFullYear() === dt.getFullYear()));
        }
        return { objects: years, title: [years[0].label, years[yearRange - 1].label].join(' - ') };
      },
      compare: function(date1, date2) {
        return date1.getFullYear() - date2.getFullYear();
      },
      split: 5,
      step: { years: yearRange }
    }
  ];

  this.isDisabled = function(date, mode) {
    var currentMode = this.modes[mode || 0];
    return ((this.minDate && currentMode.compare(date, this.minDate) < 0) || (this.maxDate && currentMode.compare(date, this.maxDate) > 0) || ($scope.dateDisabled && $scope.dateDisabled({date: date, mode: currentMode.name})));
  };
}])

.directive( 'datepicker', ['dateFilter', '$parse', 'datepickerConfig', '$log', function (dateFilter, $parse, datepickerConfig, $log) {
  return {
    restrict: 'EA',
    replace: true,
    templateUrl: 'template/datepicker/datepicker.html',
    scope: {
      dateDisabled: '&'
    },
    require: ['datepicker', '?^ngModel'],
    controller: 'DatepickerController',
    link: function(scope, element, attrs, ctrls) {
      var datepickerCtrl = ctrls[0], ngModel = ctrls[1];

      if (!ngModel) {
        return; // do nothing if no ng-model
      }

      // Configuration parameters
      var mode = 0, selected = new Date(), showWeeks = datepickerConfig.showWeeks;

      if (attrs.showWeeks) {
        scope.$parent.$watch($parse(attrs.showWeeks), function(value) {
          showWeeks = !! value;
          updateShowWeekNumbers();
        });
      } else {
        updateShowWeekNumbers();
      }

      if (attrs.min) {
        scope.$parent.$watch($parse(attrs.min), function(value) {
          datepickerCtrl.minDate = value ? new Date(value) : null;
          refill();
        });
      }
      if (attrs.max) {
        scope.$parent.$watch($parse(attrs.max), function(value) {
          datepickerCtrl.maxDate = value ? new Date(value) : null;
          refill();
        });
      }

      function updateShowWeekNumbers() {
        scope.showWeekNumbers = mode === 0 && showWeeks;
      }

      // Split array into smaller arrays
      function split(arr, size) {
        var arrays = [];
        while (arr.length > 0) {
          arrays.push(arr.splice(0, size));
        }
        return arrays;
      }

      function refill( updateSelected ) {
        var date = null, valid = true;

        if ( ngModel.$modelValue ) {
          date = new Date( ngModel.$modelValue );

          if ( isNaN(date) ) {
            valid = false;
            $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');
          } else if ( updateSelected ) {
            selected = date;
          }
        }
        ngModel.$setValidity('date', valid);

        var currentMode = datepickerCtrl.modes[mode], data = currentMode.getVisibleDates(selected, date);
        angular.forEach(data.objects, function(obj) {
          obj.disabled = datepickerCtrl.isDisabled(obj.date, mode);
        });

        ngModel.$setValidity('date-disabled', (!date || !datepickerCtrl.isDisabled(date)));

        scope.rows = split(data.objects, currentMode.split);
        scope.labels = data.labels || [];
        scope.title = data.title;
      }

      function setMode(value) {
        mode = value;
        updateShowWeekNumbers();
        refill();
      }

      ngModel.$render = function() {
        refill( true );
      };

      scope.select = function( date ) {
        if ( mode === 0 ) {
          var dt = ngModel.$modelValue ? new Date( ngModel.$modelValue ) : new Date(0, 0, 0, 0, 0, 0, 0);
          dt.setFullYear( date.getFullYear(), date.getMonth(), date.getDate() );
          ngModel.$setViewValue( dt );
          refill( true );
        } else {
          selected = date;
          setMode( mode - 1 );
        }
      };
      scope.move = function(direction) {
        var step = datepickerCtrl.modes[mode].step;
        selected.setMonth( selected.getMonth() + direction * (step.months || 0) );
        selected.setFullYear( selected.getFullYear() + direction * (step.years || 0) );
        refill();
      };
      scope.toggleMode = function() {
        setMode( (mode + 1) % datepickerCtrl.modes.length );
      };
      scope.getWeekNumber = function(row) {
        return ( mode === 0 && scope.showWeekNumbers && row.length === 7 ) ? getISO8601WeekNumber(row[0].date) : null;
      };

      function getISO8601WeekNumber(date) {
        var checkDate = new Date(date);
        checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday
        var time = checkDate.getTime();
        checkDate.setMonth(0); // Compare with Jan 1
        checkDate.setDate(1);
        return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
      }
    }
  };
}])

.constant('datepickerPopupConfig', {
  dateFormat: 'yyyy-MM-dd',
  currentText: 'Today',
  toggleWeeksText: 'Weeks',
  clearText: 'Clear',
  closeText: 'Done',
  closeOnDateSelection: true,
  appendToBody: false,
  showButtonBar: true
})

.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'datepickerPopupConfig', 'datepickerConfig',
function ($compile, $parse, $document, $position, dateFilter, datepickerPopupConfig, datepickerConfig) {
  return {
    restrict: 'EA',
    require: 'ngModel',
    link: function(originalScope, element, attrs, ngModel) {
      var scope = originalScope.$new(), // create a child scope so we are not polluting original one
          dateFormat,
          closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? originalScope.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection,
          appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? originalScope.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody;

      attrs.$observe('datepickerPopup', function(value) {
          dateFormat = value || datepickerPopupConfig.dateFormat;
          ngModel.$render();
      });

      scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? originalScope.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar;

      originalScope.$on('$destroy', function() {
        $popup.remove();
        scope.$destroy();
      });

      attrs.$observe('currentText', function(text) {
        scope.currentText = angular.isDefined(text) ? text : datepickerPopupConfig.currentText;
      });
      attrs.$observe('toggleWeeksText', function(text) {
        scope.toggleWeeksText = angular.isDefined(text) ? text : datepickerPopupConfig.toggleWeeksText;
      });
      attrs.$observe('clearText', function(text) {
        scope.clearText = angular.isDefined(text) ? text : datepickerPopupConfig.clearText;
      });
      attrs.$observe('closeText', function(text) {
        scope.closeText = angular.isDefined(text) ? text : datepickerPopupConfig.closeText;
      });

      var getIsOpen, setIsOpen;
      if ( attrs.isOpen ) {
        getIsOpen = $parse(attrs.isOpen);
        setIsOpen = getIsOpen.assign;

        originalScope.$watch(getIsOpen, function updateOpen(value) {
          scope.isOpen = !! value;
        });
      }
      scope.isOpen = getIsOpen ? getIsOpen(originalScope) : false; // Initial state

      function setOpen( value ) {
        if (setIsOpen) {
          setIsOpen(originalScope, !!value);
        } else {
          scope.isOpen = !!value;
        }
      }

      var documentClickBind = function(event) {
        if (scope.isOpen && event.target !== element[0]) {
          scope.$apply(function() {
            setOpen(false);
          });
        }
      };

      var elementFocusBind = function() {
        scope.$apply(function() {
          setOpen( true );
        });
      };

      // popup element used to display calendar
      var popupEl = angular.element('<div datepicker-popup-wrap><div datepicker></div></div>');
      popupEl.attr({
        'ng-model': 'date',
        'ng-change': 'dateSelection()'
      });
      var datepickerEl = angular.element(popupEl.children()[0]),
          datepickerOptions = {};
      if (attrs.datepickerOptions) {
        datepickerOptions = originalScope.$eval(attrs.datepickerOptions);
        datepickerEl.attr(angular.extend({}, datepickerOptions));
      }

      // TODO: reverse from dateFilter string to Date object
      function parseDate(viewValue) {
        if (!viewValue) {
          ngModel.$setValidity('date', true);
          return null;
        } else if (angular.isDate(viewValue)) {
          ngModel.$setValidity('date', true);
          return viewValue;
        } else if (angular.isString(viewValue)) {
          var date = new Date(viewValue);
          if (isNaN(date)) {
            ngModel.$setValidity('date', false);
            return undefined;
          } else {
            ngModel.$setValidity('date', true);
            return date;
          }
        } else {
          ngModel.$setValidity('date', false);
          return undefined;
        }
      }
      ngModel.$parsers.unshift(parseDate);

      // Inner change
      scope.dateSelection = function(dt) {
        if (angular.isDefined(dt)) {
          scope.date = dt;
        }
        ngModel.$setViewValue(scope.date);
        ngModel.$render();

        if (closeOnDateSelection) {
          setOpen( false );
        }
      };

      element.bind('input change keyup', function() {
        scope.$apply(function() {
          scope.date = ngModel.$modelValue;
        });
      });

      // Outter change
      ngModel.$render = function() {
        var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '';
        element.val(date);
        scope.date = ngModel.$modelValue;
      };

      function addWatchableAttribute(attribute, scopeProperty, datepickerAttribute) {
        if (attribute) {
          originalScope.$watch($parse(attribute), function(value){
            scope[scopeProperty] = value;
          });
          datepickerEl.attr(datepickerAttribute || scopeProperty, scopeProperty);
        }
      }
      addWatchableAttribute(attrs.min, 'min');
      addWatchableAttribute(attrs.max, 'max');
      if (attrs.showWeeks) {
        addWatchableAttribute(attrs.showWeeks, 'showWeeks', 'show-weeks');
      } else {
        scope.showWeeks = 'show-weeks' in datepickerOptions ? datepickerOptions['show-weeks'] : datepickerConfig.showWeeks;
        datepickerEl.attr('show-weeks', 'showWeeks');
      }
      if (attrs.dateDisabled) {
        datepickerEl.attr('date-disabled', attrs.dateDisabled);
      }

      function updatePosition() {
        scope.position = appendToBody ? $position.offset(element) : $position.position(element);
        scope.position.top = scope.position.top + element.prop('offsetHeight');
      }

      var documentBindingInitialized = false, elementFocusInitialized = false;
      scope.$watch('isOpen', function(value) {
        if (value) {
          updatePosition();
          $document.bind('click', documentClickBind);
          if(elementFocusInitialized) {
            element.unbind('focus', elementFocusBind);
          }
          element[0].focus();
          documentBindingInitialized = true;
        } else {
          if(documentBindingInitialized) {
            $document.unbind('click', documentClickBind);
          }
          element.bind('focus', elementFocusBind);
          elementFocusInitialized = true;
        }

        if ( setIsOpen ) {
          setIsOpen(originalScope, value);
        }
      });

      scope.today = function() {
        scope.dateSelection(new Date());
      };
      scope.clear = function() {
        scope.dateSelection(null);
      };

      var $popup = $compile(popupEl)(scope);
      if ( appendToBody ) {
        $document.find('body').append($popup);
      } else {
        element.after($popup);
      }
    }
  };
}])

.directive('datepickerPopupWrap', function() {
  return {
    restrict:'EA',
    replace: true,
    transclude: true,
    templateUrl: 'template/datepicker/popup.html',
    link:function (scope, element, attrs) {
      element.bind('click', function(event) {
        event.preventDefault();
        event.stopPropagation();
      });
    }
  };
});

/*
 * dropdownToggle - Provides dropdown menu functionality in place of bootstrap js
 * @restrict class or attribute
 * @example:
   <li class="dropdown">
     <a class="dropdown-toggle">My Dropdown Menu</a>
     <ul class="dropdown-menu">
       <li ng-repeat="choice in dropChoices">
         <a ng-href="{{choice.href}}">{{choice.text}}</a>
       </li>
     </ul>
   </li>
 */

angular.module('ui.bootstrap.dropdownToggle', []).directive('dropdownToggle', ['$document', '$location', function ($document, $location) {
  var openElement = null,
      closeMenu   = angular.noop;
  return {
    restrict: 'CA',
    link: function(scope, element, attrs) {
      scope.$watch('$location.path', function() { closeMenu(); });
      element.parent().bind('click', function() { closeMenu(); });
      element.bind('click', function (event) {

        var elementWasOpen = (element === openElement);

        event.preventDefault();
        event.stopPropagation();

        if (!!openElement) {
          closeMenu();
        }

        if (!elementWasOpen && !element.hasClass('disabled') && !element.prop('disabled')) {
          element.parent().addClass('open');
          openElement = element;
          closeMenu = function (event) {
            if (event) {
              event.preventDefault();
              event.stopPropagation();
            }
            $document.unbind('click', closeMenu);
            element.parent().removeClass('open');
            closeMenu = angular.noop;
            openElement = null;
          };
          $document.bind('click', closeMenu);
        }
      });
    }
  };
}]);

angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])

/**
 * A helper, internal data structure that acts as a map but also allows getting / removing
 * elements in the LIFO order
 */
  .factory('$$stackedMap', function () {
    return {
      createNew: function () {
        var stack = [];

        return {
          add: function (key, value) {
            stack.push({
              key: key,
              value: value
            });
          },
          get: function (key) {
            for (var i = 0; i < stack.length; i++) {
              if (key == stack[i].key) {
                return stack[i];
              }
            }
          },
          keys: function() {
            var keys = [];
            for (var i = 0; i < stack.length; i++) {
              keys.push(stack[i].key);
            }
            return keys;
          },
          top: function () {
            return stack[stack.length - 1];
          },
          remove: function (key) {
            var idx = -1;
            for (var i = 0; i < stack.length; i++) {
              if (key == stack[i].key) {
                idx = i;
                break;
              }
            }
            return stack.splice(idx, 1)[0];
          },
          removeTop: function () {
            return stack.splice(stack.length - 1, 1)[0];
          },
          length: function () {
            return stack.length;
          }
        };
      }
    };
  })

/**
 * A helper directive for the $modal service. It creates a backdrop element.
 */
  .directive('modalBackdrop', ['$timeout', function ($timeout) {
    return {
      restrict: 'EA',
      replace: true,
      templateUrl: 'template/modal/backdrop.html',
      link: function (scope) {

        scope.animate = false;

        //trigger CSS transitions
        $timeout(function () {
          scope.animate = true;
        });
      }
    };
  }])

  .directive('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) {
    return {
      restrict: 'EA',
      scope: {
        index: '@',
        animate: '='
      },
      replace: true,
      transclude: true,
      templateUrl: 'template/modal/window.html',
      link: function (scope, element, attrs) {
        scope.windowClass = attrs.windowClass || '';

        $timeout(function () {
          // trigger CSS transitions
          scope.animate = true;
          // focus a freshly-opened modal
          element[0].focus();
        });

        scope.close = function (evt) {
          var modal = $modalStack.getTop();
          if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) {
            evt.preventDefault();
            evt.stopPropagation();
            $modalStack.dismiss(modal.key, 'backdrop click');
          }
        };
      }
    };
  }])

  .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',
    function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {

      var OPENED_MODAL_CLASS = 'modal-open';

      var backdropDomEl, backdropScope;
      var openedWindows = $$stackedMap.createNew();
      var $modalStack = {};

      function backdropIndex() {
        var topBackdropIndex = -1;
        var opened = openedWindows.keys();
        for (var i = 0; i < opened.length; i++) {
          if (openedWindows.get(opened[i]).value.backdrop) {
            topBackdropIndex = i;
          }
        }
        return topBackdropIndex;
      }

      $rootScope.$watch(backdropIndex, function(newBackdropIndex){
        if (backdropScope) {
          backdropScope.index = newBackdropIndex;
        }
      });

      function removeModalWindow(modalInstance) {

        var body = $document.find('body').eq(0);
        var modalWindow = openedWindows.get(modalInstance).value;

        //clean up the stack
        openedWindows.remove(modalInstance);

        //remove window DOM element
        removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, checkRemoveBackdrop);
        body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
      }

      function checkRemoveBackdrop() {
          //remove backdrop if no longer needed
          if (backdropDomEl && backdropIndex() == -1) {
            var backdropScopeRef = backdropScope;
            removeAfterAnimate(backdropDomEl, backdropScope, 150, function () {
              backdropScopeRef.$destroy();
              backdropScopeRef = null;
            });
            backdropDomEl = undefined;
            backdropScope = undefined;
          }
      }

      function removeAfterAnimate(domEl, scope, emulateTime, done) {
        // Closing animation
        scope.animate = false;

        var transitionEndEventName = $transition.transitionEndEventName;
        if (transitionEndEventName) {
          // transition out
          var timeout = $timeout(afterAnimating, emulateTime);

          domEl.bind(transitionEndEventName, function () {
            $timeout.cancel(timeout);
            afterAnimating();
            scope.$apply();
          });
        } else {
          // Ensure this call is async
          $timeout(afterAnimating, 0);
        }

        function afterAnimating() {
          if (afterAnimating.done) {
            return;
          }
          afterAnimating.done = true;

          domEl.remove();
          if (done) {
            done();
          }
        }
      }

      $document.bind('keydown', function (evt) {
        var modal;

        if (evt.which === 27) {
          modal = openedWindows.top();
          if (modal && modal.value.keyboard) {
            $rootScope.$apply(function () {
              $modalStack.dismiss(modal.key);
            });
          }
        }
      });

      $modalStack.open = function (modalInstance, modal) {

        openedWindows.add(modalInstance, {
          deferred: modal.deferred,
          modalScope: modal.scope,
          backdrop: modal.backdrop,
          keyboard: modal.keyboard
        });

        var body = $document.find('body').eq(0),
            currBackdropIndex = backdropIndex();

        if (currBackdropIndex >= 0 && !backdropDomEl) {
          backdropScope = $rootScope.$new(true);
          backdropScope.index = currBackdropIndex;
          backdropDomEl = $compile('<div modal-backdrop></div>')(backdropScope);
          body.append(backdropDomEl);
        }
          
        var angularDomEl = angular.element('<div modal-window></div>');
        angularDomEl.attr('window-class', modal.windowClass);
        angularDomEl.attr('index', openedWindows.length() - 1);
        angularDomEl.attr('animate', 'animate');
        angularDomEl.html(modal.content);

        var modalDomEl = $compile(angularDomEl)(modal.scope);
        openedWindows.top().value.modalDomEl = modalDomEl;
        body.append(modalDomEl);
        body.addClass(OPENED_MODAL_CLASS);
      };

      $modalStack.close = function (modalInstance, result) {
        var modalWindow = openedWindows.get(modalInstance).value;
        if (modalWindow) {
          modalWindow.deferred.resolve(result);
          removeModalWindow(modalInstance);
        }
      };

      $modalStack.dismiss = function (modalInstance, reason) {
        var modalWindow = openedWindows.get(modalInstance).value;
        if (modalWindow) {
          modalWindow.deferred.reject(reason);
          removeModalWindow(modalInstance);
        }
      };

      $modalStack.dismissAll = function (reason) {
        var topModal = this.getTop();
        while (topModal) {
          this.dismiss(topModal.key, reason);
          topModal = this.getTop();
        }
      };

      $modalStack.getTop = function () {
        return openedWindows.top();
      };

      return $modalStack;
    }])

  .provider('$modal', function () {

    var $modalProvider = {
      options: {
        backdrop: true, //can be also false or 'static'
        keyboard: true
      },
      $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack',
        function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) {

          var $modal = {};

          function getTemplatePromise(options) {
            return options.template ? $q.when(options.template) :
              $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) {
                return result.data;
              });
          }

          function getResolvePromises(resolves) {
            var promisesArr = [];
            angular.forEach(resolves, function (value, key) {
              if (angular.isFunction(value) || angular.isArray(value)) {
                promisesArr.push($q.when($injector.invoke(value)));
              }
            });
            return promisesArr;
          }

          $modal.open = function (modalOptions) {

            var modalResultDeferred = $q.defer();
            var modalOpenedDeferred = $q.defer();

            //prepare an instance of a modal to be injected into controllers and returned to a caller
            var modalInstance = {
              result: modalResultDeferred.promise,
              opened: modalOpenedDeferred.promise,
              close: function (result) {
                $modalStack.close(modalInstance, result);
              },
              dismiss: function (reason) {
                $modalStack.dismiss(modalInstance, reason);
              }
            };

            //merge and clean up options
            modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
            modalOptions.resolve = modalOptions.resolve || {};

            //verify options
            if (!modalOptions.template && !modalOptions.templateUrl) {
              throw new Error('One of template or templateUrl options is required.');
            }

            var templateAndResolvePromise =
              $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));


            templateAndResolvePromise.then(function resolveSuccess(tplAndVars) {

              var modalScope = (modalOptions.scope || $rootScope).$new();
              modalScope.$close = modalInstance.close;
              modalScope.$dismiss = modalInstance.dismiss;

              var ctrlInstance, ctrlLocals = {};
              var resolveIter = 1;

              //controllers
              if (modalOptions.controller) {
                ctrlLocals.$scope = modalScope;
                ctrlLocals.$modalInstance = modalInstance;
                angular.forEach(modalOptions.resolve, function (value, key) {
                  ctrlLocals[key] = tplAndVars[resolveIter++];
                });

                ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
              }

              $modalStack.open(modalInstance, {
                scope: modalScope,
                deferred: modalResultDeferred,
                content: tplAndVars[0],
                backdrop: modalOptions.backdrop,
                keyboard: modalOptions.keyboard,
                windowClass: modalOptions.windowClass
              });

            }, function resolveError(reason) {
              modalResultDeferred.reject(reason);
            });

            templateAndResolvePromise.then(function () {
              modalOpenedDeferred.resolve(true);
            }, function () {
              modalOpenedDeferred.reject(false);
            });

            return modalInstance;
          };

          return $modal;
        }]
    };

    return $modalProvider;
  });

angular.module('ui.bootstrap.pagination', [])

.controller('PaginationController', ['$scope', '$attrs', '$parse', '$interpolate', function ($scope, $attrs, $parse, $interpolate) {
  var self = this,
      setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;

  this.init = function(defaultItemsPerPage) {
    if ($attrs.itemsPerPage) {
      $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) {
        self.itemsPerPage = parseInt(value, 10);
        $scope.totalPages = self.calculateTotalPages();
      });
    } else {
      this.itemsPerPage = defaultItemsPerPage;
    }
  };

  this.noPrevious = function() {
    return this.page === 1;
  };
  this.noNext = function() {
    return this.page === $scope.totalPages;
  };

  this.isActive = function(page) {
    return this.page === page;
  };

  this.calculateTotalPages = function() {
    var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage);
    return Math.max(totalPages || 0, 1);
  };

  this.getAttributeValue = function(attribute, defaultValue, interpolate) {
    return angular.isDefined(attribute) ? (interpolate ? $interpolate(attribute)($scope.$parent) : $scope.$parent.$eval(attribute)) : defaultValue;
  };

  this.render = function() {
    this.page = parseInt($scope.page, 10) || 1;
    if (this.page > 0 && this.page <= $scope.totalPages) {
      $scope.pages = this.getPages(this.page, $scope.totalPages);
    }
  };

  $scope.selectPage = function(page) {
    if ( ! self.isActive(page) && page > 0 && page <= $scope.totalPages) {
      $scope.page = page;
      $scope.onSelectPage({ page: page });
    }
  };

  $scope.$watch('page', function() {
    self.render();
  });

  $scope.$watch('totalItems', function() {
    $scope.totalPages = self.calculateTotalPages();
  });

  $scope.$watch('totalPages', function(value) {
    setNumPages($scope.$parent, value); // Readonly variable

    if ( self.page > value ) {
      $scope.selectPage(value);
    } else {
      self.render();
    }
  });
}])

.constant('paginationConfig', {
  itemsPerPage: 10,
  boundaryLinks: false,
  directionLinks: true,
  firstText: 'First',
  previousText: 'Previous',
  nextText: 'Next',
  lastText: 'Last',
  rotate: true
})

.directive('pagination', ['$parse', 'paginationConfig', function($parse, config) {
  return {
    restrict: 'EA',
    scope: {
      page: '=',
      totalItems: '=',
      onSelectPage:' &'
    },
    controller: 'PaginationController',
    templateUrl: 'template/pagination/pagination.html',
    replace: true,
    link: function(scope, element, attrs, paginationCtrl) {

      // Setup configuration parameters
      var maxSize,
      boundaryLinks  = paginationCtrl.getAttributeValue(attrs.boundaryLinks,  config.boundaryLinks      ),
      directionLinks = paginationCtrl.getAttributeValue(attrs.directionLinks, config.directionLinks     ),
      firstText      = paginationCtrl.getAttributeValue(attrs.firstText,      config.firstText,     true),
      previousText   = paginationCtrl.getAttributeValue(attrs.previousText,   config.previousText,  true),
      nextText       = paginationCtrl.getAttributeValue(attrs.nextText,       config.nextText,      true),
      lastText       = paginationCtrl.getAttributeValue(attrs.lastText,       config.lastText,      true),
      rotate         = paginationCtrl.getAttributeValue(attrs.rotate,         config.rotate);

      paginationCtrl.init(config.itemsPerPage);

      if (attrs.maxSize) {
        scope.$parent.$watch($parse(attrs.maxSize), function(value) {
          maxSize = parseInt(value, 10);
          paginationCtrl.render();
        });
      }

      // Create page object used in template
      function makePage(number, text, isActive, isDisabled) {
        return {
          number: number,
          text: text,
          active: isActive,
          disabled: isDisabled
        };
      }

      paginationCtrl.getPages = function(currentPage, totalPages) {
        var pages = [];

        // Default page limits
        var startPage = 1, endPage = totalPages;
        var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages );

        // recompute if maxSize
        if ( isMaxSized ) {
          if ( rotate ) {
            // Current page is displayed in the middle of the visible ones
            startPage = Math.max(currentPage - Math.floor(maxSize/2), 1);
            endPage   = startPage + maxSize - 1;

            // Adjust if limit is exceeded
            if (endPage > totalPages) {
              endPage   = totalPages;
              startPage = endPage - maxSize + 1;
            }
          } else {
            // Visible pages are paginated with maxSize
            startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1;

            // Adjust last page if limit is exceeded
            endPage = Math.min(startPage + maxSize - 1, totalPages);
          }
        }

        // Add page number links
        for (var number = startPage; number <= endPage; number++) {
          var page = makePage(number, number, paginationCtrl.isActive(number), false);
          pages.push(page);
        }

        // Add links to move between page sets
        if ( isMaxSized && ! rotate ) {
          if ( startPage > 1 ) {
            var previousPageSet = makePage(startPage - 1, '...', false, false);
            pages.unshift(previousPageSet);
          }

          if ( endPage < totalPages ) {
            var nextPageSet = makePage(endPage + 1, '...', false, false);
            pages.push(nextPageSet);
          }
        }

        // Add previous & next links
        if (directionLinks) {
          var previousPage = makePage(currentPage - 1, previousText, false, paginationCtrl.noPrevious());
          pages.unshift(previousPage);

          var nextPage = makePage(currentPage + 1, nextText, false, paginationCtrl.noNext());
          pages.push(nextPage);
        }

        // Add first & last links
        if (boundaryLinks) {
          var firstPage = makePage(1, firstText, false, paginationCtrl.noPrevious());
          pages.unshift(firstPage);

          var lastPage = makePage(totalPages, lastText, false, paginationCtrl.noNext());
          pages.push(lastPage);
        }

        return pages;
      };
    }
  };
}])

.constant('pagerConfig', {
  itemsPerPage: 10,
  previousText: '« Previous',
  nextText: 'Next »',
  align: true
})

.directive('pager', ['pagerConfig', function(config) {
  return {
    restrict: 'EA',
    scope: {
      page: '=',
      totalItems: '=',
      onSelectPage:' &'
    },
    controller: 'PaginationController',
    templateUrl: 'template/pagination/pager.html',
    replace: true,
    link: function(scope, element, attrs, paginationCtrl) {

      // Setup configuration parameters
      var previousText = paginationCtrl.getAttributeValue(attrs.previousText, config.previousText, true),
      nextText         = paginationCtrl.getAttributeValue(attrs.nextText,     config.nextText,     true),
      align            = paginationCtrl.getAttributeValue(attrs.align,        config.align);

      paginationCtrl.init(config.itemsPerPage);

      // Create page object used in template
      function makePage(number, text, isDisabled, isPrevious, isNext) {
        return {
          number: number,
          text: text,
          disabled: isDisabled,
          previous: ( align && isPrevious ),
          next: ( align && isNext )
        };
      }

      paginationCtrl.getPages = function(currentPage) {
        return [
          makePage(currentPage - 1, previousText, paginationCtrl.noPrevious(), true, false),
          makePage(currentPage + 1, nextText, paginationCtrl.noNext(), false, true)
        ];
      };
    }
  };
}]);

/**
 * The following features are still outstanding: animation as a
 * function, placement as a function, inside, support for more triggers than
 * just mouse enter/leave, html tooltips, and selector delegation.
 */
angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] )

/**
 * The $tooltip service creates tooltip- and popover-like directives as well as
 * houses global options for them.
 */
.provider( '$tooltip', function () {
  // The default options tooltip and popover.
  var defaultOptions = {
    placement: 'top',
    animation: true,
    popupDelay: 0
  };

  // Default hide triggers for each show trigger
  var triggerMap = {
    'mouseenter': 'mouseleave',
    'click': 'click',
    'focus': 'blur'
  };

  // The options specified to the provider globally.
  var globalOptions = {};
  
  /**
   * `options({})` allows global configuration of all tooltips in the
   * application.
   *
   *   var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {
   *     // place tooltips left instead of top by default
   *     $tooltipProvider.options( { placement: 'left' } );
   *   });
   */
	this.options = function( value ) {
		angular.extend( globalOptions, value );
	};

  /**
   * This allows you to extend the set of trigger mappings available. E.g.:
   *
   *   $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' );
   */
  this.setTriggers = function setTriggers ( triggers ) {
    angular.extend( triggerMap, triggers );
  };

  /**
   * This is a helper function for translating camel-case to snake-case.
   */
  function snake_case(name){
    var regexp = /[A-Z]/g;
    var separator = '-';
    return name.replace(regexp, function(letter, pos) {
      return (pos ? separator : '') + letter.toLowerCase();
    });
  }

  /**
   * Returns the actual instance of the $tooltip service.
   * TODO support multiple triggers
   */
  this.$get = [ '$window', '$compile', '$timeout', '$parse', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $parse, $document, $position, $interpolate ) {
    return function $tooltip ( type, prefix, defaultTriggerShow ) {
      var options = angular.extend( {}, defaultOptions, globalOptions );

      /**
       * Returns an object of show and hide triggers.
       *
       * If a trigger is supplied,
       * it is used to show the tooltip; otherwise, it will use the `trigger`
       * option passed to the `$tooltipProvider.options` method; else it will
       * default to the trigger supplied to this directive factory.
       *
       * The hide trigger is based on the show trigger. If the `trigger` option
       * was passed to the `$tooltipProvider.options` method, it will use the
       * mapped trigger from `triggerMap` or the passed trigger if the map is
       * undefined; otherwise, it uses the `triggerMap` value of the show
       * trigger; else it will just use the show trigger.
       */
      function getTriggers ( trigger ) {
        var show = trigger || options.trigger || defaultTriggerShow;
        var hide = triggerMap[show] || show;
        return {
          show: show,
          hide: hide
        };
      }

      var directiveName = snake_case( type );

      var startSym = $interpolate.startSymbol();
      var endSym = $interpolate.endSymbol();
      var template = 
        '<div '+ directiveName +'-popup '+
          'title="'+startSym+'tt_title'+endSym+'" '+
          'content="'+startSym+'tt_content'+endSym+'" '+
          'placement="'+startSym+'tt_placement'+endSym+'" '+
          'animation="tt_animation" '+
          'is-open="tt_isOpen"'+
          '>'+
        '</div>';

      return {
        restrict: 'EA',
        scope: true,
        compile: function (tElem, tAttrs) {
          var tooltipLinker = $compile( template );

          return function link ( scope, element, attrs ) {
            var tooltip;
            var transitionTimeout;
            var popupTimeout;
            var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false;
            var triggers = getTriggers( undefined );
            var hasRegisteredTriggers = false;
            var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']);

            var positionTooltip = function (){
              var position,
                ttWidth,
                ttHeight,
                ttPosition;
              // Get the position of the directive element.
              position = appendToBody ? $position.offset( element ) : $position.position( element );

              // Get the height and width of the tooltip so we can center it.
              ttWidth = tooltip.prop( 'offsetWidth' );
              ttHeight = tooltip.prop( 'offsetHeight' );

              // Calculate the tooltip's top and left coordinates to center it with
              // this directive.
              switch ( scope.tt_placement ) {
                case 'right':
                  ttPosition = {
                    top: position.top + position.height / 2 - ttHeight / 2,
                    left: position.left + position.width
                  };
                  break;
                case 'bottom':
                  ttPosition = {
                    top: position.top + position.height,
                    left: position.left + position.width / 2 - ttWidth / 2
                  };
                  break;
                case 'left':
                  ttPosition = {
                    top: position.top + position.height / 2 - ttHeight / 2,
                    left: position.left - ttWidth
                  };
                  break;
                default:
                  ttPosition = {
                    top: position.top - ttHeight,
                    left: position.left + position.width / 2 - ttWidth / 2
                  };
                  break;
              }

              ttPosition.top += 'px';
              ttPosition.left += 'px';

              // Now set the calculated positioning.
              tooltip.css( ttPosition );

            };

            // By default, the tooltip is not open.
            // TODO add ability to start tooltip opened
            scope.tt_isOpen = false;

            function toggleTooltipBind () {
              if ( ! scope.tt_isOpen ) {
                showTooltipBind();
              } else {
                hideTooltipBind();
              }
            }

            // Show the tooltip with delay if specified, otherwise show it immediately
            function showTooltipBind() {
              if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) {
                return;
              }
              if ( scope.tt_popupDelay ) {
                popupTimeout = $timeout( show, scope.tt_popupDelay, false );
                popupTimeout.then(function(reposition){reposition();});
              } else {
                show()();
              }
            }

            function hideTooltipBind () {
              scope.$apply(function () {
                hide();
              });
            }

            // Show the tooltip popup element.
            function show() {


              // Don't show empty tooltips.
              if ( ! scope.tt_content ) {
                return angular.noop;
              }

              createTooltip();

              // If there is a pending remove transition, we must cancel it, lest the
              // tooltip be mysteriously removed.
              if ( transitionTimeout ) {
                $timeout.cancel( transitionTimeout );
              }

              // Set the initial positioning.
              tooltip.css({ top: 0, left: 0, display: 'block' });

              // Now we add it to the DOM because need some info about it. But it's not 
              // visible yet anyway.
              if ( appendToBody ) {
                  $document.find( 'body' ).append( tooltip );
              } else {
                element.after( tooltip );
              }

              positionTooltip();

              // And show the tooltip.
              scope.tt_isOpen = true;
              scope.$digest(); // digest required as $apply is not called

              // Return positioning function as promise callback for correct
              // positioning after draw.
              return positionTooltip;
            }

            // Hide the tooltip popup element.
            function hide() {
              // First things first: we don't show it anymore.
              scope.tt_isOpen = false;

              //if tooltip is going to be shown after delay, we must cancel this
              $timeout.cancel( popupTimeout );

              // And now we remove it from the DOM. However, if we have animation, we 
              // need to wait for it to expire beforehand.
              // FIXME: this is a placeholder for a port of the transitions library.
              if ( scope.tt_animation ) {
                transitionTimeout = $timeout(removeTooltip, 500);
              } else {
                removeTooltip();
              }
            }

            function createTooltip() {
              // There can only be one tooltip element per directive shown at once.
              if (tooltip) {
                removeTooltip();
              }
              tooltip = tooltipLinker(scope, function () {});

              // Get contents rendered into the tooltip
              scope.$digest();
            }

            function removeTooltip() {
              if (tooltip) {
                tooltip.remove();
                tooltip = null;
              }
            }

            /**
             * Observe the relevant attributes.
             */
            attrs.$observe( type, function ( val ) {
              scope.tt_content = val;

              if (!val && scope.tt_isOpen ) {
                hide();
              }
            });

            attrs.$observe( prefix+'Title', function ( val ) {
              scope.tt_title = val;
            });

            attrs.$observe( prefix+'Placement', function ( val ) {
              scope.tt_placement = angular.isDefined( val ) ? val : options.placement;
            });

            attrs.$observe( prefix+'PopupDelay', function ( val ) {
              var delay = parseInt( val, 10 );
              scope.tt_popupDelay = ! isNaN(delay) ? delay : options.popupDelay;
            });

            var unregisterTriggers = function() {
              if (hasRegisteredTriggers) {
                element.unbind( triggers.show, showTooltipBind );
                element.unbind( triggers.hide, hideTooltipBind );
              }
            };

            attrs.$observe( prefix+'Trigger', function ( val ) {
              unregisterTriggers();

              triggers = getTriggers( val );

              if ( triggers.show === triggers.hide ) {
                element.bind( triggers.show, toggleTooltipBind );
              } else {
                element.bind( triggers.show, showTooltipBind );
                element.bind( triggers.hide, hideTooltipBind );
              }

              hasRegisteredTriggers = true;
            });

            var animation = scope.$eval(attrs[prefix + 'Animation']);
            scope.tt_animation = angular.isDefined(animation) ? !!animation : options.animation;

            attrs.$observe( prefix+'AppendToBody', function ( val ) {
              appendToBody = angular.isDefined( val ) ? $parse( val )( scope ) : appendToBody;
            });

            // if a tooltip is attached to <body> we need to remove it on
            // location change as its parent scope will probably not be destroyed
            // by the change.
            if ( appendToBody ) {
              scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () {
              if ( scope.tt_isOpen ) {
                hide();
              }
            });
            }

            // Make sure tooltip is destroyed and removed.
            scope.$on('$destroy', function onDestroyTooltip() {
              $timeout.cancel( transitionTimeout );
              $timeout.cancel( popupTimeout );
              unregisterTriggers();
              removeTooltip();
            });
          };
        }
      };
    };
  }];
})

.directive( 'tooltipPopup', function () {
  return {
    restrict: 'EA',
    replace: true,
    scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
    templateUrl: 'template/tooltip/tooltip-popup.html'
  };
})

.directive( 'tooltip', [ '$tooltip', function ( $tooltip ) {
  return $tooltip( 'tooltip', 'tooltip', 'mouseenter' );
}])

.directive( 'tooltipHtmlUnsafePopup', function () {
  return {
    restrict: 'EA',
    replace: true,
    scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
    templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html'
  };
})

.directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) {
  return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' );
}]);

/**
 * The following features are still outstanding: popup delay, animation as a
 * function, placement as a function, inside, support for more triggers than
 * just mouse enter/leave, html popovers, and selector delegatation.
 */
angular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] )

.directive( 'popoverPopup', function () {
  return {
    restrict: 'EA',
    replace: true,
    scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },
    templateUrl: 'template/popover/popover.html'
  };
})

.directive( 'popover', [ '$tooltip', function ( $tooltip ) {
  return $tooltip( 'popover', 'popover', 'click' );
}]);

angular.module('ui.bootstrap.progressbar', ['ui.bootstrap.transition'])

.constant('progressConfig', {
  animate: true,
  max: 100
})

.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', '$transition', function($scope, $attrs, progressConfig, $transition) {
    var self = this,
        bars = [],
        max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max,
        animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;

    this.addBar = function(bar, element) {
        var oldValue = 0, index = bar.$parent.$index;
        if ( angular.isDefined(index) &&  bars[index] ) {
            oldValue = bars[index].value;
        }
        bars.push(bar);

        this.update(element, bar.value, oldValue);

        bar.$watch('value', function(value, oldValue) {
            if (value !== oldValue) {
                self.update(element, value, oldValue);
            }
        });

        bar.$on('$destroy', function() {
            self.removeBar(bar);
        });
    };

    // Update bar element width
    this.update = function(element, newValue, oldValue) {
        var percent = this.getPercentage(newValue);

        if (animate) {
            element.css('width', this.getPercentage(oldValue) + '%');
            $transition(element, {width: percent + '%'});
        } else {
            element.css({'transition': 'none', 'width': percent + '%'});
        }
    };

    this.removeBar = function(bar) {
        bars.splice(bars.indexOf(bar), 1);
    };

    this.getPercentage = function(value) {
        return Math.round(100 * value / max);
    };
}])

.directive('progress', function() {
    return {
        restrict: 'EA',
        replace: true,
        transclude: true,
        controller: 'ProgressController',
        require: 'progress',
        scope: {},
        template: '<div class="progress" ng-transclude></div>'
        //templateUrl: 'template/progressbar/progress.html' // Works in AngularJS 1.2
    };
})

.directive('bar', function() {
    return {
        restrict: 'EA',
        replace: true,
        transclude: true,
        require: '^progress',
        scope: {
            value: '=',
            type: '@'
        },
        templateUrl: 'template/progressbar/bar.html',
        link: function(scope, element, attrs, progressCtrl) {
            progressCtrl.addBar(scope, element);
        }
    };
})

.directive('progressbar', function() {
    return {
        restrict: 'EA',
        replace: true,
        transclude: true,
        controller: 'ProgressController',
        scope: {
            value: '=',
            type: '@'
        },
        templateUrl: 'template/progressbar/progressbar.html',
        link: function(scope, element, attrs, progressCtrl) {
            progressCtrl.addBar(scope, angular.element(element.children()[0]));
        }
    };
});
angular.module('ui.bootstrap.rating', [])

.constant('ratingConfig', {
  max: 5,
  stateOn: null,
  stateOff: null
})

.controller('RatingController', ['$scope', '$attrs', '$parse', 'ratingConfig', function($scope, $attrs, $parse, ratingConfig) {

  this.maxRange = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max;
  this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn;
  this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff;

  this.createRateObjects = function(states) {
    var defaultOptions = {
      stateOn: this.stateOn,
      stateOff: this.stateOff
    };

    for (var i = 0, n = states.length; i < n; i++) {
      states[i] = angular.extend({ index: i }, defaultOptions, states[i]);
    }
    return states;
  };

  // Get objects used in template
  $scope.range = angular.isDefined($attrs.ratingStates) ?  this.createRateObjects(angular.copy($scope.$parent.$eval($attrs.ratingStates))): this.createRateObjects(new Array(this.maxRange));

  $scope.rate = function(value) {
    if ( $scope.value !== value && !$scope.readonly ) {
      $scope.value = value;
    }
  };

  $scope.enter = function(value) {
    if ( ! $scope.readonly ) {
      $scope.val = value;
    }
    $scope.onHover({value: value});
  };

  $scope.reset = function() {
    $scope.val = angular.copy($scope.value);
    $scope.onLeave();
  };

  $scope.$watch('value', function(value) {
    $scope.val = value;
  });

  $scope.readonly = false;
  if ($attrs.readonly) {
    $scope.$parent.$watch($parse($attrs.readonly), function(value) {
      $scope.readonly = !!value;
    });
  }
}])

.directive('rating', function() {
  return {
    restrict: 'EA',
    scope: {
      value: '=',
      onHover: '&',
      onLeave: '&'
    },
    controller: 'RatingController',
    templateUrl: 'template/rating/rating.html',
    replace: true
  };
});

/**
 * @ngdoc overview
 * @name ui.bootstrap.tabs
 *
 * @description
 * AngularJS version of the tabs directive.
 */

angular.module('ui.bootstrap.tabs', [])

.controller('TabsetController', ['$scope', function TabsetCtrl($scope) {
  var ctrl = this,
      tabs = ctrl.tabs = $scope.tabs = [];

  ctrl.select = function(tab) {
    angular.forEach(tabs, function(tab) {
      tab.active = false;
    });
    tab.active = true;
  };

  ctrl.addTab = function addTab(tab) {
    tabs.push(tab);
    if (tabs.length === 1 || tab.active) {
      ctrl.select(tab);
    }
  };

  ctrl.removeTab = function removeTab(tab) {
    var index = tabs.indexOf(tab);
    //Select a new tab if the tab to be removed is selected
    if (tab.active && tabs.length > 1) {
      //If this is the last tab, select the previous tab. else, the next tab.
      var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1;
      ctrl.select(tabs[newActiveIndex]);
    }
    tabs.splice(index, 1);
  };
}])

/**
 * @ngdoc directive
 * @name ui.bootstrap.tabs.directive:tabset
 * @restrict EA
 *
 * @description
 * Tabset is the outer container for the tabs directive
 *
 * @param {boolean=} vertical Whether or not to use vertical styling for the tabs.
 * @param {boolean=} justified Whether or not to use justified styling for the tabs.
 *
 * @example
<example module="ui.bootstrap">
  <file name="index.html">
    <tabset>
      <tab heading="Tab 1"><b>First</b> Content!</tab>
      <tab heading="Tab 2"><i>Second</i> Content!</tab>
    </tabset>
    <hr />
    <tabset vertical="true">
      <tab heading="Vertical Tab 1"><b>First</b> Vertical Content!</tab>
      <tab heading="Vertical Tab 2"><i>Second</i> Vertical Content!</tab>
    </tabset>
    <tabset justified="true">
      <tab heading="Justified Tab 1"><b>First</b> Justified Content!</tab>
      <tab heading="Justified Tab 2"><i>Second</i> Justified Content!</tab>
    </tabset>
  </file>
</example>
 */
.directive('tabset', function() {
  return {
    restrict: 'EA',
    transclude: true,
    replace: true,
    scope: {},
    controller: 'TabsetController',
    templateUrl: 'template/tabs/tabset.html',
    link: function(scope, element, attrs) {
      scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false;
      scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false;
      scope.type = angular.isDefined(attrs.type) ? scope.$parent.$eval(attrs.type) : 'tabs';
    }
  };
})

/**
 * @ngdoc directive
 * @name ui.bootstrap.tabs.directive:tab
 * @restrict EA
 *
 * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link ui.bootstrap.tabs.directive:tabHeading tabHeading}.
 * @param {string=} select An expression to evaluate when the tab is selected.
 * @param {boolean=} active A binding, telling whether or not this tab is selected.
 * @param {boolean=} disabled A binding, telling whether or not this tab is disabled.
 *
 * @description
 * Creates a tab with a heading and content. Must be placed within a {@link ui.bootstrap.tabs.directive:tabset tabset}.
 *
 * @example
<example module="ui.bootstrap">
  <file name="index.html">
    <div ng-controller="TabsDemoCtrl">
      <button class="btn btn-small" ng-click="items[0].active = true">
        Select item 1, using active binding
      </button>
      <button class="btn btn-small" ng-click="items[1].disabled = !items[1].disabled">
        Enable/disable item 2, using disabled binding
      </button>
      <br />
      <tabset>
        <tab heading="Tab 1">First Tab</tab>
        <tab select="alertMe()">
          <tab-heading><i class="icon-bell"></i> Alert me!</tab-heading>
          Second Tab, with alert callback and html heading!
        </tab>
        <tab ng-repeat="item in items"
          heading="{{item.title}}"
          disabled="item.disabled"
          active="item.active">
          {{item.content}}
        </tab>
      </tabset>
    </div>
  </file>
  <file name="script.js">
    function TabsDemoCtrl($scope) {
      $scope.items = [
        { title:"Dynamic Title 1", content:"Dynamic Item 0" },
        { title:"Dynamic Title 2", content:"Dynamic Item 1", disabled: true }
      ];

      $scope.alertMe = function() {
        setTimeout(function() {
          alert("You've selected the alert tab!");
        });
      };
    };
  </file>
</example>
 */

/**
 * @ngdoc directive
 * @name ui.bootstrap.tabs.directive:tabHeading
 * @restrict EA
 *
 * @description
 * Creates an HTML heading for a {@link ui.bootstrap.tabs.directive:tab tab}. Must be placed as a child of a tab element.
 *
 * @example
<example module="ui.bootstrap">
  <file name="index.html">
    <tabset>
      <tab>
        <tab-heading><b>HTML</b> in my titles?!</tab-heading>
        And some content, too!
      </tab>
      <tab>
        <tab-heading><i class="icon-heart"></i> Icon heading?!?</tab-heading>
        That's right.
      </tab>
    </tabset>
  </file>
</example>
 */
.directive('tab', ['$parse', function($parse) {
  return {
    require: '^tabset',
    restrict: 'EA',
    replace: true,
    templateUrl: 'template/tabs/tab.html',
    transclude: true,
    scope: {
      heading: '@',
      onSelect: '&select', //This callback is called in contentHeadingTransclude
                          //once it inserts the tab's content into the dom
      onDeselect: '&deselect'
    },
    controller: function() {
      //Empty controller so other directives can require being 'under' a tab
    },
    compile: function(elm, attrs, transclude) {
      return function postLink(scope, elm, attrs, tabsetCtrl) {
        var getActive, setActive;
        if (attrs.active) {
          getActive = $parse(attrs.active);
          setActive = getActive.assign;
          scope.$parent.$watch(getActive, function updateActive(value, oldVal) {
            // Avoid re-initializing scope.active as it is already initialized
            // below. (watcher is called async during init with value ===
            // oldVal)
            if (value !== oldVal) {
              scope.active = !!value;
            }
          });
          scope.active = getActive(scope.$parent);
        } else {
          setActive = getActive = angular.noop;
        }

        scope.$watch('active', function(active) {
          // Note this watcher also initializes and assigns scope.active to the
          // attrs.active expression.
          setActive(scope.$parent, active);
          if (active) {
            tabsetCtrl.select(scope);
            scope.onSelect();
          } else {
            scope.onDeselect();
          }
        });

        scope.disabled = false;
        if ( attrs.disabled ) {
          scope.$parent.$watch($parse(attrs.disabled), function(value) {
            scope.disabled = !! value;
          });
        }

        scope.select = function() {
          if ( ! scope.disabled ) {
            scope.active = true;
          }
        };

        tabsetCtrl.addTab(scope);
        scope.$on('$destroy', function() {
          tabsetCtrl.removeTab(scope);
        });


        //We need to transclude later, once the content container is ready.
        //when this link happens, we're inside a tab heading.
        scope.$transcludeFn = transclude;
      };
    }
  };
}])

.directive('tabHeadingTransclude', [function() {
  return {
    restrict: 'A',
    require: '^tab',
    link: function(scope, elm, attrs, tabCtrl) {
      scope.$watch('headingElement', function updateHeadingElement(heading) {
        if (heading) {
          elm.html('');
          elm.append(heading);
        }
      });
    }
  };
}])

.directive('tabContentTransclude', function() {
  return {
    restrict: 'A',
    require: '^tabset',
    link: function(scope, elm, attrs) {
      var tab = scope.$eval(attrs.tabContentTransclude);

      //Now our tab is ready to be transcluded: both the tab heading area
      //and the tab content area are loaded.  Transclude 'em both.
      tab.$transcludeFn(tab.$parent, function(contents) {
        angular.forEach(contents, function(node) {
          if (isTabHeading(node)) {
            //Let tabHeadingTransclude know.
            tab.headingElement = node;
          } else {
            elm.append(node);
          }
        });
      });
    }
  };
  function isTabHeading(node) {
    return node.tagName &&  (
      node.hasAttribute('tab-heading') ||
      node.hasAttribute('data-tab-heading') ||
      node.tagName.toLowerCase() === 'tab-heading' ||
      node.tagName.toLowerCase() === 'data-tab-heading'
    );
  }
})

;

angular.module('ui.bootstrap.timepicker', [])

.constant('timepickerConfig', {
  hourStep: 1,
  minuteStep: 1,
  showMeridian: true,
  meridians: null,
  readonlyInput: false,
  mousewheel: true
})

.directive('timepicker', ['$parse', '$log', 'timepickerConfig', '$locale', function ($parse, $log, timepickerConfig, $locale) {
  return {
    restrict: 'EA',
    require:'?^ngModel',
    replace: true,
    scope: {},
    templateUrl: 'template/timepicker/timepicker.html',
    link: function(scope, element, attrs, ngModel) {
      if ( !ngModel ) {
        return; // do nothing if no ng-model
      }

      var selected = new Date(),
          meridians = angular.isDefined(attrs.meridians) ? scope.$parent.$eval(attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS;

      var hourStep = timepickerConfig.hourStep;
      if (attrs.hourStep) {
        scope.$parent.$watch($parse(attrs.hourStep), function(value) {
          hourStep = parseInt(value, 10);
        });
      }

      var minuteStep = timepickerConfig.minuteStep;
      if (attrs.minuteStep) {
        scope.$parent.$watch($parse(attrs.minuteStep), function(value) {
          minuteStep = parseInt(value, 10);
        });
      }

      // 12H / 24H mode
      scope.showMeridian = timepickerConfig.showMeridian;
      if (attrs.showMeridian) {
        scope.$parent.$watch($parse(attrs.showMeridian), function(value) {
          scope.showMeridian = !!value;

          if ( ngModel.$error.time ) {
            // Evaluate from template
            var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate();
            if (angular.isDefined( hours ) && angular.isDefined( minutes )) {
              selected.setHours( hours );
              refresh();
            }
          } else {
            updateTemplate();
          }
        });
      }

      // Get scope.hours in 24H mode if valid
      function getHoursFromTemplate ( ) {
        var hours = parseInt( scope.hours, 10 );
        var valid = ( scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24);
        if ( !valid ) {
          return undefined;
        }

        if ( scope.showMeridian ) {
          if ( hours === 12 ) {
            hours = 0;
          }
          if ( scope.meridian === meridians[1] ) {
            hours = hours + 12;
          }
        }
        return hours;
      }

      function getMinutesFromTemplate() {
        var minutes = parseInt(scope.minutes, 10);
        return ( minutes >= 0 && minutes < 60 ) ? minutes : undefined;
      }

      function pad( value ) {
        return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value;
      }

      // Input elements
      var inputs = element.find('input'), hoursInputEl = inputs.eq(0), minutesInputEl = inputs.eq(1);

      // Respond on mousewheel spin
      var mousewheel = (angular.isDefined(attrs.mousewheel)) ? scope.$eval(attrs.mousewheel) : timepickerConfig.mousewheel;
      if ( mousewheel ) {

        var isScrollingUp = function(e) {
          if (e.originalEvent) {
            e = e.originalEvent;
          }
          //pick correct delta variable depending on event
          var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY;
          return (e.detail || delta > 0);
        };

        hoursInputEl.bind('mousewheel wheel', function(e) {
          scope.$apply( (isScrollingUp(e)) ? scope.incrementHours() : scope.decrementHours() );
          e.preventDefault();
        });

        minutesInputEl.bind('mousewheel wheel', function(e) {
          scope.$apply( (isScrollingUp(e)) ? scope.incrementMinutes() : scope.decrementMinutes() );
          e.preventDefault();
        });
      }

      scope.readonlyInput = (angular.isDefined(attrs.readonlyInput)) ? scope.$eval(attrs.readonlyInput) : timepickerConfig.readonlyInput;
      if ( ! scope.readonlyInput ) {

        var invalidate = function(invalidHours, invalidMinutes) {
          ngModel.$setViewValue( null );
          ngModel.$setValidity('time', false);
          if (angular.isDefined(invalidHours)) {
            scope.invalidHours = invalidHours;
          }
          if (angular.isDefined(invalidMinutes)) {
            scope.invalidMinutes = invalidMinutes;
          }
        };

        scope.updateHours = function() {
          var hours = getHoursFromTemplate();

          if ( angular.isDefined(hours) ) {
            selected.setHours( hours );
            refresh( 'h' );
          } else {
            invalidate(true);
          }
        };

        hoursInputEl.bind('blur', function(e) {
          if ( !scope.validHours && scope.hours < 10) {
            scope.$apply( function() {
              scope.hours = pad( scope.hours );
            });
          }
        });

        scope.updateMinutes = function() {
          var minutes = getMinutesFromTemplate();

          if ( angular.isDefined(minutes) ) {
            selected.setMinutes( minutes );
            refresh( 'm' );
          } else {
            invalidate(undefined, true);
          }
        };

        minutesInputEl.bind('blur', function(e) {
          if ( !scope.invalidMinutes && scope.minutes < 10 ) {
            scope.$apply( function() {
              scope.minutes = pad( scope.minutes );
            });
          }
        });
      } else {
        scope.updateHours = angular.noop;
        scope.updateMinutes = angular.noop;
      }

      ngModel.$render = function() {
        var date = ngModel.$modelValue ? new Date( ngModel.$modelValue ) : null;

        if ( isNaN(date) ) {
          ngModel.$setValidity('time', false);
          $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');
        } else {
          if ( date ) {
            selected = date;
          }
          makeValid();
          updateTemplate();
        }
      };

      // Call internally when we know that model is valid.
      function refresh( keyboardChange ) {
        makeValid();
        ngModel.$setViewValue( new Date(selected) );
        updateTemplate( keyboardChange );
      }

      function makeValid() {
        ngModel.$setValidity('time', true);
        scope.invalidHours = false;
        scope.invalidMinutes = false;
      }

      function updateTemplate( keyboardChange ) {
        var hours = selected.getHours(), minutes = selected.getMinutes();

        if ( scope.showMeridian ) {
          hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; // Convert 24 to 12 hour system
        }
        scope.hours =  keyboardChange === 'h' ? hours : pad(hours);
        scope.minutes = keyboardChange === 'm' ? minutes : pad(minutes);
        scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];
      }

      function addMinutes( minutes ) {
        var dt = new Date( selected.getTime() + minutes * 60000 );
        selected.setHours( dt.getHours(), dt.getMinutes() );
        refresh();
      }

      scope.incrementHours = function() {
        addMinutes( hourStep * 60 );
      };
      scope.decrementHours = function() {
        addMinutes( - hourStep * 60 );
      };
      scope.incrementMinutes = function() {
        addMinutes( minuteStep );
      };
      scope.decrementMinutes = function() {
        addMinutes( - minuteStep );
      };
      scope.toggleMeridian = function() {
        addMinutes( 12 * 60 * (( selected.getHours() < 12 ) ? 1 : -1) );
      };
    }
  };
}]);

angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml'])

/**
 * A helper service that can parse typeahead's syntax (string provided by users)
 * Extracted to a separate service for ease of unit testing
 */
  .factory('typeaheadParser', ['$parse', function ($parse) {

  //                      00000111000000000000022200000000000000003333333333333330000000000044000
  var TYPEAHEAD_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;

  return {
    parse:function (input) {

      var match = input.match(TYPEAHEAD_REGEXP), modelMapper, viewMapper, source;
      if (!match) {
        throw new Error(
          "Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_'" +
            " but got '" + input + "'.");
      }

      return {
        itemName:match[3],
        source:$parse(match[4]),
        viewMapper:$parse(match[2] || match[1]),
        modelMapper:$parse(match[1])
      };
    }
  };
}])

  .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser',
    function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) {

  var HOT_KEYS = [9, 13, 27, 38, 40];

  return {
    require:'ngModel',
    link:function (originalScope, element, attrs, modelCtrl) {

      //SUPPORTED ATTRIBUTES (OPTIONS)

      //minimal no of characters that needs to be entered before typeahead kicks-in
      var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1;

      //minimal wait time after last character typed before typehead kicks-in
      var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;

      //should it restrict model values to the ones selected from the popup only?
      var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;

      //binding to a variable that indicates if matches are being retrieved asynchronously
      var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;

      //a callback executed when a match is selected
      var onSelectCallback = $parse(attrs.typeaheadOnSelect);

      var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;

      var appendToBody =  attrs.typeaheadAppendToBody ? $parse(attrs.typeaheadAppendToBody) : false;

      //INTERNAL VARIABLES

      //model setter executed upon match selection
      var $setModelValue = $parse(attrs.ngModel).assign;

      //expressions used by typeahead
      var parserResult = typeaheadParser.parse(attrs.typeahead);

      var hasFocus;

      //pop-up element used to display matches
      var popUpEl = angular.element('<div typeahead-popup></div>');
      popUpEl.attr({
        matches: 'matches',
        active: 'activeIdx',
        select: 'select(activeIdx)',
        query: 'query',
        position: 'position'
      });
      //custom item template
      if (angular.isDefined(attrs.typeaheadTemplateUrl)) {
        popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);
      }

      //create a child scope for the typeahead directive so we are not polluting original scope
      //with typeahead-specific data (matches, query etc.)
      var scope = originalScope.$new();
      originalScope.$on('$destroy', function(){
        scope.$destroy();
      });

      var resetMatches = function() {
        scope.matches = [];
        scope.activeIdx = -1;
      };

      var getMatchesAsync = function(inputValue) {

        var locals = {$viewValue: inputValue};
        isLoadingSetter(originalScope, true);
        $q.when(parserResult.source(originalScope, locals)).then(function(matches) {

          //it might happen that several async queries were in progress if a user were typing fast
          //but we are interested only in responses that correspond to the current view value
          if (inputValue === modelCtrl.$viewValue && hasFocus) {
            if (matches.length > 0) {

              scope.activeIdx = 0;
              scope.matches.length = 0;

              //transform labels
              for(var i=0; i<matches.length; i++) {
                locals[parserResult.itemName] = matches[i];
                scope.matches.push({
                  label: parserResult.viewMapper(scope, locals),
                  model: matches[i]
                });
              }

              scope.query = inputValue;
              //position pop-up with matches - we need to re-calculate its position each time we are opening a window
              //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page
              //due to other elements being rendered
              scope.position = appendToBody ? $position.offset(element) : $position.position(element);
              scope.position.top = scope.position.top + element.prop('offsetHeight');

            } else {
              resetMatches();
            }
            isLoadingSetter(originalScope, false);
          }
        }, function(){
          resetMatches();
          isLoadingSetter(originalScope, false);
        });
      };

      resetMatches();

      //we need to propagate user's query so we can higlight matches
      scope.query = undefined;

      //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later 
      var timeoutPromise;

      //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM
      //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue
      modelCtrl.$parsers.unshift(function (inputValue) {

        hasFocus = true;

        if (inputValue && inputValue.length >= minSearch) {
          if (waitTime > 0) {
            if (timeoutPromise) {
              $timeout.cancel(timeoutPromise);//cancel previous timeout
            }
            timeoutPromise = $timeout(function () {
              getMatchesAsync(inputValue);
            }, waitTime);
          } else {
            getMatchesAsync(inputValue);
          }
        } else {
          isLoadingSetter(originalScope, false);
          resetMatches();
        }

        if (isEditable) {
          return inputValue;
        } else {
          if (!inputValue) {
            // Reset in case user had typed something previously.
            modelCtrl.$setValidity('editable', true);
            return inputValue;
          } else {
            modelCtrl.$setValidity('editable', false);
            return undefined;
          }
        }
      });

      modelCtrl.$formatters.push(function (modelValue) {

        var candidateViewValue, emptyViewValue;
        var locals = {};

        if (inputFormatter) {

          locals['$model'] = modelValue;
          return inputFormatter(originalScope, locals);

        } else {

          //it might happen that we don't have enough info to properly render input value
          //we need to check for this situation and simply return model value if we can't apply custom formatting
          locals[parserResult.itemName] = modelValue;
          candidateViewValue = parserResult.viewMapper(originalScope, locals);
          locals[parserResult.itemName] = undefined;
          emptyViewValue = parserResult.viewMapper(originalScope, locals);

          return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue;
        }
      });

      scope.select = function (activeIdx) {
        //called from within the $digest() cycle
        var locals = {};
        var model, item;

        locals[parserResult.itemName] = item = scope.matches[activeIdx].model;
        model = parserResult.modelMapper(originalScope, locals);
        $setModelValue(originalScope, model);
        modelCtrl.$setValidity('editable', true);

        onSelectCallback(originalScope, {
          $item: item,
          $model: model,
          $label: parserResult.viewMapper(originalScope, locals)
        });

        resetMatches();

        //return focus to the input element if a mach was selected via a mouse click event
        element[0].focus();
      };

      //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)
      element.bind('keydown', function (evt) {

        //typeahead is open and an "interesting" key was pressed
        if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {
          return;
        }

        evt.preventDefault();

        if (evt.which === 40) {
          scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;
          scope.$digest();

        } else if (evt.which === 38) {
          scope.activeIdx = (scope.activeIdx ? scope.activeIdx : scope.matches.length) - 1;
          scope.$digest();

        } else if (evt.which === 13 || evt.which === 9) {
          scope.$apply(function () {
            scope.select(scope.activeIdx);
          });

        } else if (evt.which === 27) {
          evt.stopPropagation();

          resetMatches();
          scope.$digest();
        }
      });

      element.bind('blur', function (evt) {
        hasFocus = false;
      });

      // Keep reference to click handler to unbind it.
      var dismissClickHandler = function (evt) {
        if (element[0] !== evt.target) {
          resetMatches();
          scope.$digest();
        }
      };

      $document.bind('click', dismissClickHandler);

      originalScope.$on('$destroy', function(){
        $document.unbind('click', dismissClickHandler);
      });

      var $popup = $compile(popUpEl)(scope);
      if ( appendToBody ) {
        $document.find('body').append($popup);
      } else {
        element.after($popup);
      }
    }
  };

}])

  .directive('typeaheadPopup', function () {
    return {
      restrict:'EA',
      scope:{
        matches:'=',
        query:'=',
        active:'=',
        position:'=',
        select:'&'
      },
      replace:true,
      templateUrl:'template/typeahead/typeahead-popup.html',
      link:function (scope, element, attrs) {

        scope.templateUrl = attrs.templateUrl;

        scope.isOpen = function () {
          return scope.matches.length > 0;
        };

        scope.isActive = function (matchIdx) {
          return scope.active == matchIdx;
        };

        scope.selectActive = function (matchIdx) {
          scope.active = matchIdx;
        };

        scope.selectMatch = function (activeIdx) {
          scope.select({activeIdx:activeIdx});
        };
      }
    };
  })

  .directive('typeaheadMatch', ['$http', '$templateCache', '$compile', '$parse', function ($http, $templateCache, $compile, $parse) {
    return {
      restrict:'EA',
      scope:{
        index:'=',
        match:'=',
        query:'='
      },
      link:function (scope, element, attrs) {
        var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html';
        $http.get(tplUrl, {cache: $templateCache}).success(function(tplContent){
           element.replaceWith($compile(tplContent.trim())(scope));
        });
      }
    };
  }])

  .filter('typeaheadHighlight', function() {

    function escapeRegexp(queryToEscape) {
      return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
    }

    return function(matchItem, query) {
      return query ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem;
    };
  });
angular.module("template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/accordion/accordion-group.html",
    "<div class=\"panel panel-default\">\n" +
    "  <div class=\"panel-heading\">\n" +
    "    <h4 class=\"panel-title\">\n" +
    "      <a class=\"accordion-toggle\" ng-click=\"isOpen = !isOpen\" accordion-transclude=\"heading\">{{heading}}</a>\n" +
    "    </h4>\n" +
    "  </div>\n" +
    "  <div class=\"panel-collapse\" collapse=\"!isOpen\">\n" +
    "	  <div class=\"panel-body\" ng-transclude></div>\n" +
    "  </div>\n" +
    "</div>");
}]);

angular.module("template/accordion/accordion.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/accordion/accordion.html",
    "<div class=\"panel-group\" ng-transclude></div>");
}]);

angular.module("template/alert/alert.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/alert/alert.html",
    "<div class='alert' ng-class='\"alert-\" + (type || \"warning\")'>\n" +
    "    <button ng-show='closeable' type='button' class='close' ng-click='close()'>&times;</button>\n" +
    "    <div ng-transclude></div>\n" +
    "</div>\n" +
    "");
}]);

angular.module("template/carousel/carousel.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/carousel/carousel.html",
    "<div ng-mouseenter=\"pause()\" ng-mouseleave=\"play()\" class=\"carousel\">\n" +
    "    <ol class=\"carousel-indicators\" ng-show=\"slides().length > 1\">\n" +
    "        <li ng-repeat=\"slide in slides()\" ng-class=\"{active: isActive(slide)}\" ng-click=\"select(slide)\"></li>\n" +
    "    </ol>\n" +
    "    <div class=\"carousel-inner\" ng-transclude></div>\n" +
    "    <a class=\"left carousel-control\" ng-click=\"prev()\" ng-show=\"slides().length > 1\"><span class=\"icon-prev\"></span></a>\n" +
    "    <a class=\"right carousel-control\" ng-click=\"next()\" ng-show=\"slides().length > 1\"><span class=\"icon-next\"></span></a>\n" +
    "</div>\n" +
    "");
}]);

angular.module("template/carousel/slide.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/carousel/slide.html",
    "<div ng-class=\"{\n" +
    "    'active': leaving || (active && !entering),\n" +
    "    'prev': (next || active) && direction=='prev',\n" +
    "    'next': (next || active) && direction=='next',\n" +
    "    'right': direction=='prev',\n" +
    "    'left': direction=='next'\n" +
    "  }\" class=\"item text-center\" ng-transclude></div>\n" +
    "");
}]);

angular.module("template/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/datepicker/datepicker.html",
    "<table>\n" +
    "  <thead>\n" +
    "    <tr>\n" +
    "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left\" ng-click=\"move(-1)\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
    "      <th colspan=\"{{rows[0].length - 2 + showWeekNumbers}}\"><button type=\"button\" class=\"btn btn-default btn-sm btn-block\" ng-click=\"toggleMode()\"><strong>{{title}}</strong></button></th>\n" +
    "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right\" ng-click=\"move(1)\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
    "    </tr>\n" +
    "    <tr ng-show=\"labels.length > 0\" class=\"h6\">\n" +
    "      <th ng-show=\"showWeekNumbers\" class=\"text-center\">#</th>\n" +
    "      <th ng-repeat=\"label in labels\" class=\"text-center\">{{label}}</th>\n" +
    "    </tr>\n" +
    "  </thead>\n" +
    "  <tbody>\n" +
    "    <tr ng-repeat=\"row in rows\">\n" +
    "      <td ng-show=\"showWeekNumbers\" class=\"text-center\"><em>{{ getWeekNumber(row) }}</em></td>\n" +
    "      <td ng-repeat=\"dt in row\" class=\"text-center\">\n" +
    "        <button type=\"button\" style=\"width:100%;\" class=\"btn btn-default btn-sm\" ng-class=\"{'btn-info': dt.selected}\" ng-click=\"select(dt.date)\" ng-disabled=\"dt.disabled\"><span ng-class=\"{'text-muted': dt.secondary}\">{{dt.label}}</span></button>\n" +
    "      </td>\n" +
    "    </tr>\n" +
    "  </tbody>\n" +
    "</table>\n" +
    "");
}]);

angular.module("template/datepicker/popup.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/datepicker/popup.html",
    "<ul class=\"dropdown-menu\" ng-style=\"{display: (isOpen && 'block') || 'none', top: position.top+'px', left: position.left+'px'}\">\n" +
    "	<li ng-transclude></li>\n" +
    "	<li ng-show=\"showButtonBar\" style=\"padding:10px 9px 2px\">\n" +
    "		<span class=\"btn-group\">\n" +
    "			<button type=\"button\" class=\"btn btn-sm btn-info\" ng-click=\"today()\">{{currentText}}</button>\n" +
    "			<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"showWeeks = ! showWeeks\" ng-class=\"{active: showWeeks}\">{{toggleWeeksText}}</button>\n" +
    "			<button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"clear()\">{{clearText}}</button>\n" +
    "		</span>\n" +
    "		<button type=\"button\" class=\"btn btn-sm btn-success pull-right\" ng-click=\"isOpen = false\">{{closeText}}</button>\n" +
    "	</li>\n" +
    "</ul>\n" +
    "");
}]);

angular.module("template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/modal/backdrop.html",
    "<div class=\"modal-backdrop fade\" ng-class=\"{in: animate}\" ng-style=\"{'z-index': 1040 + index*10}\"></div>");
}]);

angular.module("template/modal/window.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/modal/window.html",
    "<div tabindex=\"-1\" class=\"modal fade {{ windowClass }}\" ng-class=\"{in: animate}\" ng-style=\"{'z-index': 1050 + index*10, display: 'block'}\" ng-click=\"close($event)\">\n" +
    "    <div class=\"modal-dialog\"><div class=\"modal-content\" ng-transclude></div></div>\n" +
    "</div>");
}]);

angular.module("template/pagination/pager.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/pagination/pager.html",
    "<ul class=\"pager\">\n" +
    "  <li ng-repeat=\"page in pages\" ng-class=\"{disabled: page.disabled, previous: page.previous, next: page.next}\"><a ng-click=\"selectPage(page.number)\">{{page.text}}</a></li>\n" +
    "</ul>");
}]);

angular.module("template/pagination/pagination.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/pagination/pagination.html",
    "<ul class=\"pagination\">\n" +
    "  <li ng-repeat=\"page in pages\" ng-class=\"{active: page.active, disabled: page.disabled}\"><a ng-click=\"selectPage(page.number)\">{{page.text}}</a></li>\n" +
    "</ul>");
}]);

angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html",
    "<div class=\"tooltip {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
    "  <div class=\"tooltip-arrow\"></div>\n" +
    "  <div class=\"tooltip-inner\" bind-html-unsafe=\"content\"></div>\n" +
    "</div>\n" +
    "");
}]);

angular.module("template/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/tooltip/tooltip-popup.html",
    "<div class=\"tooltip {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
    "  <div class=\"tooltip-arrow\"></div>\n" +
    "  <div class=\"tooltip-inner\" ng-bind=\"content\"></div>\n" +
    "</div>\n" +
    "");
}]);

angular.module("template/popover/popover.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/popover/popover.html",
    "<div class=\"popover {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
    "  <div class=\"arrow\"></div>\n" +
    "\n" +
    "  <div class=\"popover-inner\">\n" +
    "      <h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3>\n" +
    "      <div class=\"popover-content\" ng-bind=\"content\"></div>\n" +
    "  </div>\n" +
    "</div>\n" +
    "");
}]);

angular.module("template/progressbar/bar.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/progressbar/bar.html",
    "<div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" ng-transclude></div>");
}]);

angular.module("template/progressbar/progress.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/progressbar/progress.html",
    "<div class=\"progress\" ng-transclude></div>");
}]);

angular.module("template/progressbar/progressbar.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/progressbar/progressbar.html",
    "<div class=\"progress\"><div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" ng-transclude></div></div>");
}]);

angular.module("template/rating/rating.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/rating/rating.html",
    "<span ng-mouseleave=\"reset()\">\n" +
    "    <i ng-repeat=\"r in range\" ng-mouseenter=\"enter($index + 1)\" ng-click=\"rate($index + 1)\" class=\"glyphicon\" ng-class=\"$index < val && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')\"></i>\n" +
    "</span>");
}]);

angular.module("template/tabs/tab.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/tabs/tab.html",
    "<li ng-class=\"{active: active, disabled: disabled}\">\n" +
    "  <a ng-click=\"select()\" tab-heading-transclude>{{heading}}</a>\n" +
    "</li>\n" +
    "");
}]);

angular.module("template/tabs/tabset-titles.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/tabs/tabset-titles.html",
    "<ul class=\"nav {{type && 'nav-' + type}}\" ng-class=\"{'nav-stacked': vertical}\">\n" +
    "</ul>\n" +
    "");
}]);

angular.module("template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/tabs/tabset.html",
    "\n" +
    "<div class=\"tabbable\">\n" +
    "  <ul class=\"nav {{type && 'nav-' + type}}\" ng-class=\"{'nav-stacked': vertical, 'nav-justified': justified}\" ng-transclude></ul>\n" +
    "  <div class=\"tab-content\">\n" +
    "    <div class=\"tab-pane\" \n" +
    "         ng-repeat=\"tab in tabs\" \n" +
    "         ng-class=\"{active: tab.active}\"\n" +
    "         tab-content-transclude=\"tab\">\n" +
    "    </div>\n" +
    "  </div>\n" +
    "</div>\n" +
    "");
}]);

angular.module("template/timepicker/timepicker.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/timepicker/timepicker.html",
    "<table>\n" +
    "	<tbody>\n" +
    "		<tr class=\"text-center\">\n" +
    "			<td><a ng-click=\"incrementHours()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
    "			<td>&nbsp;</td>\n" +
    "			<td><a ng-click=\"incrementMinutes()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
    "			<td ng-show=\"showMeridian\"></td>\n" +
    "		</tr>\n" +
    "		<tr>\n" +
    "			<td style=\"width:50px;\" class=\"form-group\" ng-class=\"{'has-error': invalidHours}\">\n" +
    "				<input type=\"text\" ng-model=\"hours\" ng-change=\"updateHours()\" class=\"form-control text-center\" ng-mousewheel=\"incrementHours()\" ng-readonly=\"readonlyInput\" maxlength=\"2\">\n" +
    "			</td>\n" +
    "			<td>:</td>\n" +
    "			<td style=\"width:50px;\" class=\"form-group\" ng-class=\"{'has-error': invalidMinutes}\">\n" +
    "				<input type=\"text\" ng-model=\"minutes\" ng-change=\"updateMinutes()\" class=\"form-control text-center\" ng-readonly=\"readonlyInput\" maxlength=\"2\">\n" +
    "			</td>\n" +
    "			<td ng-show=\"showMeridian\"><button type=\"button\" class=\"btn btn-default text-center\" ng-click=\"toggleMeridian()\">{{meridian}}</button></td>\n" +
    "		</tr>\n" +
    "		<tr class=\"text-center\">\n" +
    "			<td><a ng-click=\"decrementHours()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
    "			<td>&nbsp;</td>\n" +
    "			<td><a ng-click=\"decrementMinutes()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
    "			<td ng-show=\"showMeridian\"></td>\n" +
    "		</tr>\n" +
    "	</tbody>\n" +
    "</table>\n" +
    "");
}]);

angular.module("template/typeahead/typeahead-match.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/typeahead/typeahead-match.html",
    "<a tabindex=\"-1\" bind-html-unsafe=\"match.label | typeaheadHighlight:query\"></a>");
}]);

angular.module("template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/typeahead/typeahead-popup.html",
    "<ul class=\"dropdown-menu\" ng-style=\"{display: isOpen()&&'block' || 'none', top: position.top+'px', left: position.left+'px'}\">\n" +
    "    <li ng-repeat=\"match in matches\" ng-class=\"{active: isActive($index) }\" ng-mouseenter=\"selectActive($index)\" ng-click=\"selectMatch($index)\">\n" +
    "        <div typeahead-match index=\"$index\" match=\"match\" query=\"query\" template-url=\"templateUrl\"></div>\n" +
    "    </li>\n" +
    "</ul>");
}]);

/* =========================================================
 * bootstrap-datepicker.js 
 * http://www.eyecon.ro/bootstrap-datepicker
 * =========================================================
 * Copyright 2012 Stefan Petre
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================= */
 
!function( $ ) {
	
	// Picker object
	
	var Datepicker = function(element, options){
		this.element = $(element);
		this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy');
		this.picker = $(DPGlobal.template)
							.appendTo('body')
							.on({
								click: $.proxy(this.click, this)//,
								//mousedown: $.proxy(this.mousedown, this)
							});
		this.isInput = this.element.is('input');
		this.component = this.element.is('.date') ? this.element.find('.add-on') : false;
		
		if (this.isInput) {
			this.element.on({
				focus: $.proxy(this.show, this),
				//blur: $.proxy(this.hide, this),
				keyup: $.proxy(this.update, this)
			});
		} else {
			if (this.component){
				this.component.on('click', $.proxy(this.show, this));
			} else {
				this.element.on('click', $.proxy(this.show, this));
			}
		}
	
		this.minViewMode = options.minViewMode||this.element.data('date-minviewmode')||0;
		if (typeof this.minViewMode === 'string') {
			switch (this.minViewMode) {
				case 'months':
					this.minViewMode = 1;
					break;
				case 'years':
					this.minViewMode = 2;
					break;
				default:
					this.minViewMode = 0;
					break;
			}
		}
		this.viewMode = options.viewMode||this.element.data('date-viewmode')||0;
		if (typeof this.viewMode === 'string') {
			switch (this.viewMode) {
				case 'months':
					this.viewMode = 1;
					break;
				case 'years':
					this.viewMode = 2;
					break;
				default:
					this.viewMode = 0;
					break;
			}
		}
		this.startViewMode = this.viewMode;
		this.weekStart = options.weekStart||this.element.data('date-weekstart')||0;
		this.weekEnd = this.weekStart === 0 ? 6 : this.weekStart - 1;
		this.onRender = options.onRender;
		this.fillDow();
		this.fillMonths();
		this.update();
		this.showMode();
	};
	
	Datepicker.prototype = {
		constructor: Datepicker,
		
		show: function(e) {
			this.picker.show();
			this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
			this.place();
			$(window).on('resize', $.proxy(this.place, this));
			if (e ) {
				e.stopPropagation();
				e.preventDefault();
			}
			if (!this.isInput) {
			}
			var that = this;
			$(document).on('mousedown', function(ev){
				if ($(ev.target).closest('.datepicker').length == 0) {
					that.hide();
				}
			});
			this.element.trigger({
				type: 'show',
				date: this.date
			});
		},
		
		hide: function(){
			this.picker.hide();
			$(window).off('resize', this.place);
			this.viewMode = this.startViewMode;
			this.showMode();
			if (!this.isInput) {
				$(document).off('mousedown', this.hide);
			}
			//this.set();
			this.element.trigger({
				type: 'hide',
				date: this.date
			});
		},
		
		set: function() {
			var formated = DPGlobal.formatDate(this.date, this.format);
			if (!this.isInput) {
				if (this.component){
					this.element.find('input').prop('value', formated);
				}
				this.element.data('date', formated);
			} else {
				this.element.prop('value', formated);
			}
		},
		
		setValue: function(newDate) {
			if (typeof newDate === 'string') {
				this.date = DPGlobal.parseDate(newDate, this.format);
			} else {
				this.date = new Date(newDate);
			}
			this.set();
			this.viewDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0, 0);
			this.fill();
		},
		
		place: function(){
			var offset = this.component ? this.component.offset() : this.element.offset();
			this.picker.css({
				top: offset.top + this.height,
				left: offset.left
			});
		},
		
		update: function(newDate){
			this.date = DPGlobal.parseDate(
				typeof newDate === 'string' ? newDate : (this.isInput ? this.element.prop('value') : this.element.data('date')),
				this.format
			);
			this.viewDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0, 0);
			this.fill();
		},
		
		fillDow: function(){
			var dowCnt = this.weekStart;
			var html = '<tr>';
			while (dowCnt < this.weekStart + 7) {
				html += '<th class="dow">'+DPGlobal.dates.daysMin[(dowCnt++)%7]+'</th>';
			}
			html += '</tr>';
			this.picker.find('.datepicker-days thead').append(html);
		},
		
		fillMonths: function(){
			var html = '';
			var i = 0
			while (i < 12) {
				html += '<span class="month">'+DPGlobal.dates.monthsShort[i++]+'</span>';
			}
			this.picker.find('.datepicker-months td').append(html);
		},
		
		fill: function() {
			var d = new Date(this.viewDate),
				year = d.getFullYear(),
				month = d.getMonth(),
				currentDate = this.date.valueOf();
			this.picker.find('.datepicker-days th:eq(1)')
						.text(DPGlobal.dates.months[month]+' '+year);
			var prevMonth = new Date(year, month-1, 28,0,0,0,0),
				day = DPGlobal.getDaysInMonth(prevMonth.getFullYear(), prevMonth.getMonth());
			prevMonth.setDate(day);
			prevMonth.setDate(day - (prevMonth.getDay() - this.weekStart + 7)%7);
			var nextMonth = new Date(prevMonth);
			nextMonth.setDate(nextMonth.getDate() + 42);
			nextMonth = nextMonth.valueOf();
			var html = [];
			var clsName,
				prevY,
				prevM;
			while(prevMonth.valueOf() < nextMonth) {
				if (prevMonth.getDay() === this.weekStart) {
					html.push('<tr>');
				}
				clsName = this.onRender(prevMonth);
				prevY = prevMonth.getFullYear();
				prevM = prevMonth.getMonth();
				if ((prevM < month &&  prevY === year) ||  prevY < year) {
					clsName += ' old';
				} else if ((prevM > month && prevY === year) || prevY > year) {
					clsName += ' new';
				}
				if (prevMonth.valueOf() === currentDate) {
					clsName += ' active';
				}
				html.push('<td class="day '+clsName+'">'+prevMonth.getDate() + '</td>');
				if (prevMonth.getDay() === this.weekEnd) {
					html.push('</tr>');
				}
				prevMonth.setDate(prevMonth.getDate()+1);
			}
			this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
			var currentYear = this.date.getFullYear();
			
			var months = this.picker.find('.datepicker-months')
						.find('th:eq(1)')
							.text(year)
							.end()
						.find('span').removeClass('active');
			if (currentYear === year) {
				months.eq(this.date.getMonth()).addClass('active');
			}
			
			html = '';
			year = parseInt(year/10, 10) * 10;
			var yearCont = this.picker.find('.datepicker-years')
								.find('th:eq(1)')
									.text(year + '-' + (year + 9))
									.end()
								.find('td');
			year -= 1;
			for (var i = -1; i < 11; i++) {
				html += '<span class="year'+(i === -1 || i === 10 ? ' old' : '')+(currentYear === year ? ' active' : '')+'">'+year+'</span>';
				year += 1;
			}
			yearCont.html(html);
		},
		
		click: function(e) {
			e.stopPropagation();
			e.preventDefault();
			var target = $(e.target).closest('span, td, th');
			if (target.length === 1) {
				switch(target[0].nodeName.toLowerCase()) {
					case 'th':
						switch(target[0].className) {
							case 'switch':
								this.showMode(1);
								break;
							case 'prev':
							case 'next':
								this.viewDate['set'+DPGlobal.modes[this.viewMode].navFnc].call(
									this.viewDate,
									this.viewDate['get'+DPGlobal.modes[this.viewMode].navFnc].call(this.viewDate) + 
									DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1)
								);
								this.fill();
								this.set();
								break;
						}
						break;
					case 'span':
						if (target.is('.month')) {
							var month = target.parent().find('span').index(target);
							this.viewDate.setMonth(month);
						} else {
							var year = parseInt(target.text(), 10)||0;
							this.viewDate.setFullYear(year);
						}
						if (this.viewMode !== 0) {
							this.date = new Date(this.viewDate);
							this.element.trigger({
								type: 'changeDate',
								date: this.date,
								viewMode: DPGlobal.modes[this.viewMode].clsName
							});
						}
						this.showMode(-1);
						this.fill();
						this.set();
						break;
					case 'td':
						if (target.is('.day') && !target.is('.disabled')){
							var day = parseInt(target.text(), 10)||1;
							var month = this.viewDate.getMonth();
							if (target.is('.old')) {
								month -= 1;
							} else if (target.is('.new')) {
								month += 1;
							}
							var year = this.viewDate.getFullYear();
							this.date = new Date(year, month, day,0,0,0,0);
							this.viewDate = new Date(year, month, Math.min(28, day),0,0,0,0);
							this.fill();
							this.set();
							this.element.trigger({
								type: 'changeDate',
								date: this.date,
								viewMode: DPGlobal.modes[this.viewMode].clsName
							});
						}
						break;
				}
			}
		},
		
		mousedown: function(e){
			e.stopPropagation();
			e.preventDefault();
		},
		
		showMode: function(dir) {
			if (dir) {
				this.viewMode = Math.max(this.minViewMode, Math.min(2, this.viewMode + dir));
			}
			this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
		}
	};
	
	$.fn.datepicker = function ( option, val ) {
		return this.each(function () {
			var $this = $(this),
				data = $this.data('datepicker'),
				options = typeof option === 'object' && option;
			if (!data) {
				$this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options))));
			}
			if (typeof option === 'string') data[option](val);
		});
	};

	$.fn.datepicker.defaults = {
		onRender: function(date) {
			return '';
		}
	};
	$.fn.datepicker.Constructor = Datepicker;
	
	var DPGlobal = {
		modes: [
			{
				clsName: 'days',
				navFnc: 'Month',
				navStep: 1
			},
			{
				clsName: 'months',
				navFnc: 'FullYear',
				navStep: 1
			},
			{
				clsName: 'years',
				navFnc: 'FullYear',
				navStep: 10
		}],
		dates:{
			days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
			daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
			daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
			months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
			monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
		},
		isLeapYear: function (year) {
			return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
		},
		getDaysInMonth: function (year, month) {
			return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
		},
		parseFormat: function(format){
			var separator = format.match(/[.\/\-\s].*?/),
				parts = format.split(/\W+/);
			if (!separator || !parts || parts.length === 0){
				throw new Error("Invalid date format.");
			}
			return {separator: separator, parts: parts};
		},
		parseDate: function(date, format) {
			var parts = date.split(format.separator),
				date = new Date(),
				val;
			date.setHours(0);
			date.setMinutes(0);
			date.setSeconds(0);
			date.setMilliseconds(0);
			if (parts.length === format.parts.length) {
				var year = date.getFullYear(), day = date.getDate(), month = date.getMonth();
				for (var i=0, cnt = format.parts.length; i < cnt; i++) {
					val = parseInt(parts[i], 10)||1;
					switch(format.parts[i]) {
						case 'dd':
						case 'd':
							day = val;
							date.setDate(val);
							break;
						case 'mm':
						case 'm':
							month = val - 1;
							date.setMonth(val - 1);
							break;
						case 'yy':
							year = 2000 + val;
							date.setFullYear(2000 + val);
							break;
						case 'yyyy':
							year = val;
							date.setFullYear(val);
							break;
					}
				}
				date = new Date(year, month, day, 0 ,0 ,0);
			}
			return date;
		},
		formatDate: function(date, format){
			var val = {
				d: date.getDate(),
				m: date.getMonth() + 1,
				yy: date.getFullYear().toString().substring(2),
				yyyy: date.getFullYear()
			};
			val.dd = (val.d < 10 ? '0' : '') + val.d;
			val.mm = (val.m < 10 ? '0' : '') + val.m;
			var date = [];
			for (var i=0, cnt = format.parts.length; i < cnt; i++) {
				date.push(val[format.parts[i]]);
			}
			return date.join(format.separator);
		},
		headTemplate: '<thead>'+
							'<tr>'+
								'<th class="prev">&lsaquo;</th>'+
								'<th colspan="5" class="switch"></th>'+
								'<th class="next">&rsaquo;</th>'+
							'</tr>'+
						'</thead>',
		contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
	};
	DPGlobal.template = '<div class="datepicker dropdown-menu">'+
							'<div class="datepicker-days">'+
								'<table class=" table-condensed">'+
									DPGlobal.headTemplate+
									'<tbody></tbody>'+
								'</table>'+
							'</div>'+
							'<div class="datepicker-months">'+
								'<table class="table-condensed">'+
									DPGlobal.headTemplate+
									DPGlobal.contTemplate+
								'</table>'+
							'</div>'+
							'<div class="datepicker-years">'+
								'<table class="table-condensed">'+
									DPGlobal.headTemplate+
									DPGlobal.contTemplate+
								'</table>'+
							'</div>'+
						'</div>';

}( window.jQuery );
//---------------------------------------------------------------------
//
// QR Code Generator for JavaScript
//
// Copyright (c) 2009 Kazuhiko Arase
//
// URL: http://www.d-project.com/
//
// Licensed under the MIT license:
//	http://www.opensource.org/licenses/mit-license.php
//
// The word 'QR Code' is registered trademark of
// DENSO WAVE INCORPORATED
//	http://www.denso-wave.com/qrcode/faqpatent-e.html
//
//---------------------------------------------------------------------

var qrcode = function() {

	//---------------------------------------------------------------------
	// qrcode
	//---------------------------------------------------------------------

	/**
	 * qrcode
	 * @param typeNumber 1 to 10
	 * @param errorCorrectLevel 'L','M','Q','H'
	 */
	var qrcode = function(typeNumber, errorCorrectLevel) {

		var PAD0 = 0xEC;
		var PAD1 = 0x11;

		var _typeNumber = typeNumber;
		var _errorCorrectLevel = QRErrorCorrectLevel[errorCorrectLevel];
		var _modules = null;
		var _moduleCount = 0;
		var _dataCache = null;
		var _dataList = new Array();

		var _this = {};

		var makeImpl = function(test, maskPattern) {

			_moduleCount = _typeNumber * 4 + 17;
			_modules = function(moduleCount) {
				var modules = new Array(moduleCount);
				for (var row = 0; row < moduleCount; row += 1) {
					modules[row] = new Array(moduleCount);
					for (var col = 0; col < moduleCount; col += 1) {
						modules[row][col] = null;
					}
				}
				return modules;
			}(_moduleCount);

			setupPositionProbePattern(0, 0);
			setupPositionProbePattern(_moduleCount - 7, 0);
			setupPositionProbePattern(0, _moduleCount - 7);
			setupPositionAdjustPattern();
			setupTimingPattern();
			setupTypeInfo(test, maskPattern);

			if (_typeNumber >= 7) {
				setupTypeNumber(test);
			}

			if (_dataCache == null) {
				_dataCache = createData(_typeNumber, _errorCorrectLevel, _dataList);
			}

			mapData(_dataCache, maskPattern);
		};

		var setupPositionProbePattern = function(row, col) {

			for (var r = -1; r <= 7; r += 1) {

				if (row + r <= -1 || _moduleCount <= row + r) continue;

				for (var c = -1; c <= 7; c += 1) {

					if (col + c <= -1 || _moduleCount <= col + c) continue;

					if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )
							|| (0 <= c && c <= 6 && (r == 0 || r == 6) )
							|| (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {
						_modules[row + r][col + c] = true;
					} else {
						_modules[row + r][col + c] = false;
					}
				}
			}
		};

		var getBestMaskPattern = function() {

			var minLostPoint = 0;
			var pattern = 0;

			for (var i = 0; i < 8; i += 1) {

				makeImpl(true, i);

				var lostPoint = QRUtil.getLostPoint(_this);

				if (i == 0 || minLostPoint > lostPoint) {
					minLostPoint = lostPoint;
					pattern = i;
				}
			}

			return pattern;
		};

		var setupTimingPattern = function() {

			for (var r = 8; r < _moduleCount - 8; r += 1) {
				if (_modules[r][6] != null) {
					continue;
				}
				_modules[r][6] = (r % 2 == 0);
			}

			for (var c = 8; c < _moduleCount - 8; c += 1) {
				if (_modules[6][c] != null) {
					continue;
				}
				_modules[6][c] = (c % 2 == 0);
			}
		};

		var setupPositionAdjustPattern = function() {

			var pos = QRUtil.getPatternPosition(_typeNumber);

			for (var i = 0; i < pos.length; i += 1) {

				for (var j = 0; j < pos.length; j += 1) {

					var row = pos[i];
					var col = pos[j];

					if (_modules[row][col] != null) {
						continue;
					}

					for (var r = -2; r <= 2; r += 1) {

						for (var c = -2; c <= 2; c += 1) {

							if (r == -2 || r == 2 || c == -2 || c == 2
									|| (r == 0 && c == 0) ) {
								_modules[row + r][col + c] = true;
							} else {
								_modules[row + r][col + c] = false;
							}
						}
					}
				}
			}
		};

		var setupTypeNumber = function(test) {

			var bits = QRUtil.getBCHTypeNumber(_typeNumber);

			for (var i = 0; i < 18; i += 1) {
				var mod = (!test && ( (bits >> i) & 1) == 1);
				_modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;
			}

			for (var i = 0; i < 18; i += 1) {
				var mod = (!test && ( (bits >> i) & 1) == 1);
				_modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
			}
		};

		var setupTypeInfo = function(test, maskPattern) {

			var data = (_errorCorrectLevel << 3) | maskPattern;
			var bits = QRUtil.getBCHTypeInfo(data);

			// vertical
			for (var i = 0; i < 15; i += 1) {

				var mod = (!test && ( (bits >> i) & 1) == 1);

				if (i < 6) {
					_modules[i][8] = mod;
				} else if (i < 8) {
					_modules[i + 1][8] = mod;
				} else {
					_modules[_moduleCount - 15 + i][8] = mod;
				}
			}

			// horizontal
			for (var i = 0; i < 15; i += 1) {

				var mod = (!test && ( (bits >> i) & 1) == 1);

				if (i < 8) {
					_modules[8][_moduleCount - i - 1] = mod;
				} else if (i < 9) {
					_modules[8][15 - i - 1 + 1] = mod;
				} else {
					_modules[8][15 - i - 1] = mod;
				}
			}

			// fixed module
			_modules[_moduleCount - 8][8] = (!test);
		};

		var mapData = function(data, maskPattern) {

			var inc = -1;
			var row = _moduleCount - 1;
			var bitIndex = 7;
			var byteIndex = 0;
			var maskFunc = QRUtil.getMaskFunction(maskPattern);

			for (var col = _moduleCount - 1; col > 0; col -= 2) {

				if (col == 6) col -= 1;

				while (true) {

					for (var c = 0; c < 2; c += 1) {

						if (_modules[row][col - c] == null) {

							var dark = false;

							if (byteIndex < data.length) {
								dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);
							}

							var mask = maskFunc(row, col - c);

							if (mask) {
								dark = !dark;
							}

							_modules[row][col - c] = dark;
							bitIndex -= 1;

							if (bitIndex == -1) {
								byteIndex += 1;
								bitIndex = 7;
							}
						}
					}

					row += inc;

					if (row < 0 || _moduleCount <= row) {
						row -= inc;
						inc = -inc;
						break;
					}
				}
			}
		};

		var createBytes = function(buffer, rsBlocks) {

			var offset = 0;

			var maxDcCount = 0;
			var maxEcCount = 0;

			var dcdata = new Array(rsBlocks.length);
			var ecdata = new Array(rsBlocks.length);

			for (var r = 0; r < rsBlocks.length; r += 1) {

				var dcCount = rsBlocks[r].dataCount;
				var ecCount = rsBlocks[r].totalCount - dcCount;

				maxDcCount = Math.max(maxDcCount, dcCount);
				maxEcCount = Math.max(maxEcCount, ecCount);

				dcdata[r] = new Array(dcCount);

				for (var i = 0; i < dcdata[r].length; i += 1) {
					dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];
				}
				offset += dcCount;

				var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
				var rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1);

				var modPoly = rawPoly.mod(rsPoly);
				ecdata[r] = new Array(rsPoly.getLength() - 1);
				for (var i = 0; i < ecdata[r].length; i += 1) {
					var modIndex = i + modPoly.getLength() - ecdata[r].length;
					ecdata[r][i] = (modIndex >= 0)? modPoly.getAt(modIndex) : 0;
				}
			}

			var totalCodeCount = 0;
			for (var i = 0; i < rsBlocks.length; i += 1) {
				totalCodeCount += rsBlocks[i].totalCount;
			}

			var data = new Array(totalCodeCount);
			var index = 0;

			for (var i = 0; i < maxDcCount; i += 1) {
				for (var r = 0; r < rsBlocks.length; r += 1) {
					if (i < dcdata[r].length) {
						data[index] = dcdata[r][i];
						index += 1;
					}
				}
			}

			for (var i = 0; i < maxEcCount; i += 1) {
				for (var r = 0; r < rsBlocks.length; r += 1) {
					if (i < ecdata[r].length) {
						data[index] = ecdata[r][i];
						index += 1;
					}
				}
			}

			return data;
		};

		var createData = function(typeNumber, errorCorrectLevel, dataList) {

			var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);

			var buffer = qrBitBuffer();

			for (var i = 0; i < dataList.length; i += 1) {
				var data = dataList[i];
				buffer.put(data.getMode(), 4);
				buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );
				data.write(buffer);
			}

			// calc num max data.
			var totalDataCount = 0;
			for (var i = 0; i < rsBlocks.length; i += 1) {
				totalDataCount += rsBlocks[i].dataCount;
			}

			if (buffer.getLengthInBits() > totalDataCount * 8) {
				throw new Error('code length overflow. ('
					+ buffer.getLengthInBits()
					+ '>'
					+ totalDataCount * 8
					+ ')');
			}

			// end code
			if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
				buffer.put(0, 4);
			}

			// padding
			while (buffer.getLengthInBits() % 8 != 0) {
				buffer.putBit(false);
			}

			// padding
			while (true) {

				if (buffer.getLengthInBits() >= totalDataCount * 8) {
					break;
				}
				buffer.put(PAD0, 8);

				if (buffer.getLengthInBits() >= totalDataCount * 8) {
					break;
				}
				buffer.put(PAD1, 8);
			}

			return createBytes(buffer, rsBlocks);
		};

		_this.addData = function(data) {
			var newData = qr8BitByte(data);
			_dataList.push(newData);
			_dataCache = null;
		};

		_this.isDark = function(row, col) {
			if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {
				throw new Error(row + ',' + col);
			}
			return _modules[row][col];
		};

		_this.getModuleCount = function() {
			return _moduleCount;
		};

		_this.make = function() {
			makeImpl(false, getBestMaskPattern() );
		};

		_this.createTableTag = function(cellSize, margin) {

			cellSize = cellSize || 2;
			margin = (typeof margin == 'undefined')? cellSize * 4 : margin;

			var qrHtml = '';

			qrHtml += '<table style="';
			qrHtml += ' border-width: 0px; border-style: none;';
			qrHtml += ' border-collapse: collapse;';
			qrHtml += ' padding: 0px; margin: ' + margin + 'px;';
			qrHtml += '">';
			qrHtml += '<tbody>';

			for (var r = 0; r < _this.getModuleCount(); r += 1) {

				qrHtml += '<tr>';

				for (var c = 0; c < _this.getModuleCount(); c += 1) {
					qrHtml += '<td style="';
					qrHtml += ' border-width: 0px; border-style: none;';
					qrHtml += ' border-collapse: collapse;';
					qrHtml += ' padding: 0px; margin: 0px;';
					qrHtml += ' width: ' + cellSize + 'px;';
					qrHtml += ' height: ' + cellSize + 'px;';
					qrHtml += ' background-color: ';
					qrHtml += _this.isDark(r, c)? '#000000' : '#ffffff';
					qrHtml += ';';
					qrHtml += '"/>';
				}

				qrHtml += '</tr>';
			}

			qrHtml += '</tbody>';
			qrHtml += '</table>';

			return qrHtml;
		};

		_this.createImgTag = function(cellSize, margin) {

			cellSize = cellSize || 2;
			margin = (typeof margin == 'undefined')? cellSize * 4 : margin;

			var size = _this.getModuleCount() * cellSize + margin * 2;
			var min = margin;
			var max = size - margin;

			return createImgTag(size, size, function(x, y) {
				if (min <= x && x < max && min <= y && y < max) {
					var c = Math.floor( (x - min) / cellSize);
					var r = Math.floor( (y - min) / cellSize);
					return _this.isDark(r, c)? 0 : 1;
				} else {
					return 1;
				}
			} );
		};

		return _this;
	};

	//---------------------------------------------------------------------
	// qrcode.stringToBytes
	//---------------------------------------------------------------------

	qrcode.stringToBytes = function(s) {
		var bytes = new Array();
		for (var i = 0; i < s.length; i += 1) {
			var c = s.charCodeAt(i);
			bytes.push(c & 0xff);
		}
		return bytes;
	};

	//---------------------------------------------------------------------
	// qrcode.createStringToBytes
	//---------------------------------------------------------------------

	/**
	 * @param unicodeData base64 string of byte array.
	 * [16bit Unicode],[16bit Bytes], ...
	 * @param numChars
	 */
	qrcode.createStringToBytes = function(unicodeData, numChars) {

		// create conversion map.

		var unicodeMap = function() {

			var bin = base64DecodeInputStream(unicodeData);
			var read = function() {
				var b = bin.read();
				if (b == -1) throw new Error();
				return b;
			};

			var count = 0;
			var unicodeMap = {};
			while (true) {
				var b0 = bin.read();
				if (b0 == -1) break;
				var b1 = read();
				var b2 = read();
				var b3 = read();
				var k = String.fromCharCode( (b0 << 8) | b1);
				var v = (b2 << 8) | b3;
				unicodeMap[k] = v;
				count += 1;
			}
			if (count != numChars) {
				throw new Error(count + ' != ' + numChars);
			}

			return unicodeMap;
		}();

		var unknownChar = '?'.charCodeAt(0);

		return function(s) {
			var bytes = new Array();
			for (var i = 0; i < s.length; i += 1) {
				var c = s.charCodeAt(i);
				if (c < 128) {
					bytes.push(c);
				} else {
					var b = unicodeMap[s.charAt(i)];
					if (typeof b == 'number') {
						if ( (b & 0xff) == b) {
							// 1byte
							bytes.push(b);
						} else {
							// 2bytes
							bytes.push(b >>> 8);
							bytes.push(b & 0xff);
						}
					} else {
						bytes.push(unknownChar);
					}
				}
			}
			return bytes;
		};
	};

	//---------------------------------------------------------------------
	// QRMode
	//---------------------------------------------------------------------

	var QRMode = {
		MODE_NUMBER :		1 << 0,
		MODE_ALPHA_NUM : 	1 << 1,
		MODE_8BIT_BYTE : 	1 << 2,
		MODE_KANJI :		1 << 3
	};

	//---------------------------------------------------------------------
	// QRErrorCorrectLevel
	//---------------------------------------------------------------------

	var QRErrorCorrectLevel = {
		L : 1,
		M : 0,
		Q : 3,
		H : 2
	};

	//---------------------------------------------------------------------
	// QRMaskPattern
	//---------------------------------------------------------------------

	var QRMaskPattern = {
		PATTERN000 : 0,
		PATTERN001 : 1,
		PATTERN010 : 2,
		PATTERN011 : 3,
		PATTERN100 : 4,
		PATTERN101 : 5,
		PATTERN110 : 6,
		PATTERN111 : 7
	};

	//---------------------------------------------------------------------
	// QRUtil
	//---------------------------------------------------------------------

	var QRUtil = function() {

		var PATTERN_POSITION_TABLE = [
			[],
			[6, 18],
			[6, 22],
			[6, 26],
			[6, 30],
			[6, 34],
			[6, 22, 38],
			[6, 24, 42],
			[6, 26, 46],
			[6, 28, 50],
			[6, 30, 54],
			[6, 32, 58],
			[6, 34, 62],
			[6, 26, 46, 66],
			[6, 26, 48, 70],
			[6, 26, 50, 74],
			[6, 30, 54, 78],
			[6, 30, 56, 82],
			[6, 30, 58, 86],
			[6, 34, 62, 90],
			[6, 28, 50, 72, 94],
			[6, 26, 50, 74, 98],
			[6, 30, 54, 78, 102],
			[6, 28, 54, 80, 106],
			[6, 32, 58, 84, 110],
			[6, 30, 58, 86, 114],
			[6, 34, 62, 90, 118],
			[6, 26, 50, 74, 98, 122],
			[6, 30, 54, 78, 102, 126],
			[6, 26, 52, 78, 104, 130],
			[6, 30, 56, 82, 108, 134],
			[6, 34, 60, 86, 112, 138],
			[6, 30, 58, 86, 114, 142],
			[6, 34, 62, 90, 118, 146],
			[6, 30, 54, 78, 102, 126, 150],
			[6, 24, 50, 76, 102, 128, 154],
			[6, 28, 54, 80, 106, 132, 158],
			[6, 32, 58, 84, 110, 136, 162],
			[6, 26, 54, 82, 110, 138, 166],
			[6, 30, 58, 86, 114, 142, 170]
		];
		var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
		var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
		var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);

		var _this = {};

		var getBCHDigit = function(data) {
			var digit = 0;
			while (data != 0) {
				digit += 1;
				data >>>= 1;
			}
			return digit;
		};

		_this.getBCHTypeInfo = function(data) {
			var d = data << 10;
			while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
				d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );
			}
			return ( (data << 10) | d) ^ G15_MASK;
		};

		_this.getBCHTypeNumber = function(data) {
			var d = data << 12;
			while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
				d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );
			}
			return (data << 12) | d;
		};

		_this.getPatternPosition = function(typeNumber) {
			return PATTERN_POSITION_TABLE[typeNumber - 1];
		};

		_this.getMaskFunction = function(maskPattern) {

			switch (maskPattern) {

			case QRMaskPattern.PATTERN000 :
				return function(i, j) { return (i + j) % 2 == 0; };
			case QRMaskPattern.PATTERN001 :
				return function(i, j) { return i % 2 == 0; };
			case QRMaskPattern.PATTERN010 :
				return function(i, j) { return j % 3 == 0; };
			case QRMaskPattern.PATTERN011 :
				return function(i, j) { return (i + j) % 3 == 0; };
			case QRMaskPattern.PATTERN100 :
				return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; };
			case QRMaskPattern.PATTERN101 :
				return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };
			case QRMaskPattern.PATTERN110 :
				return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; };
			case QRMaskPattern.PATTERN111 :
				return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; };

			default :
				throw new Error('bad maskPattern:' + maskPattern);
			}
		};

		_this.getErrorCorrectPolynomial = function(errorCorrectLength) {
			var a = qrPolynomial([1], 0);
			for (var i = 0; i < errorCorrectLength; i += 1) {
				a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) );
			}
			return a;
		};

		_this.getLengthInBits = function(mode, type) {

			if (1 <= type && type < 10) {

				// 1 - 9

				switch(mode) {
				case QRMode.MODE_NUMBER 	: return 10;
				case QRMode.MODE_ALPHA_NUM 	: return 9;
				case QRMode.MODE_8BIT_BYTE	: return 8;
				case QRMode.MODE_KANJI		: return 8;
				default :
					throw new Error('mode:' + mode);
				}

			} else if (type < 27) {

				// 10 - 26

				switch(mode) {
				case QRMode.MODE_NUMBER 	: return 12;
				case QRMode.MODE_ALPHA_NUM 	: return 11;
				case QRMode.MODE_8BIT_BYTE	: return 16;
				case QRMode.MODE_KANJI		: return 10;
				default :
					throw new Error('mode:' + mode);
				}

			} else if (type < 41) {

				// 27 - 40

				switch(mode) {
				case QRMode.MODE_NUMBER 	: return 14;
				case QRMode.MODE_ALPHA_NUM	: return 13;
				case QRMode.MODE_8BIT_BYTE	: return 16;
				case QRMode.MODE_KANJI		: return 12;
				default :
					throw new Error('mode:' + mode);
				}

			} else {
				throw new Error('type:' + type);
			}
		};

		_this.getLostPoint = function(qrcode) {

			var moduleCount = qrcode.getModuleCount();

			var lostPoint = 0;

			// LEVEL1

			for (var row = 0; row < moduleCount; row += 1) {
				for (var col = 0; col < moduleCount; col += 1) {

					var sameCount = 0;
					var dark = qrcode.isDark(row, col);

					for (var r = -1; r <= 1; r += 1) {

						if (row + r < 0 || moduleCount <= row + r) {
							continue;
						}

						for (var c = -1; c <= 1; c += 1) {

							if (col + c < 0 || moduleCount <= col + c) {
								continue;
							}

							if (r == 0 && c == 0) {
								continue;
							}

							if (dark == qrcode.isDark(row + r, col + c) ) {
								sameCount += 1;
							}
						}
					}

					if (sameCount > 5) {
						lostPoint += (3 + sameCount - 5);
					}
				}
			};

			// LEVEL2

			for (var row = 0; row < moduleCount - 1; row += 1) {
				for (var col = 0; col < moduleCount - 1; col += 1) {
					var count = 0;
					if (qrcode.isDark(row, col) ) count += 1;
					if (qrcode.isDark(row + 1, col) ) count += 1;
					if (qrcode.isDark(row, col + 1) ) count += 1;
					if (qrcode.isDark(row + 1, col + 1) ) count += 1;
					if (count == 0 || count == 4) {
						lostPoint += 3;
					}
				}
			}

			// LEVEL3

			for (var row = 0; row < moduleCount; row += 1) {
				for (var col = 0; col < moduleCount - 6; col += 1) {
					if (qrcode.isDark(row, col)
							&& !qrcode.isDark(row, col + 1)
							&&  qrcode.isDark(row, col + 2)
							&&  qrcode.isDark(row, col + 3)
							&&  qrcode.isDark(row, col + 4)
							&& !qrcode.isDark(row, col + 5)
							&&  qrcode.isDark(row, col + 6) ) {
						lostPoint += 40;
					}
				}
			}

			for (var col = 0; col < moduleCount; col += 1) {
				for (var row = 0; row < moduleCount - 6; row += 1) {
					if (qrcode.isDark(row, col)
							&& !qrcode.isDark(row + 1, col)
							&&  qrcode.isDark(row + 2, col)
							&&  qrcode.isDark(row + 3, col)
							&&  qrcode.isDark(row + 4, col)
							&& !qrcode.isDark(row + 5, col)
							&&  qrcode.isDark(row + 6, col) ) {
						lostPoint += 40;
					}
				}
			}

			// LEVEL4

			var darkCount = 0;

			for (var col = 0; col < moduleCount; col += 1) {
				for (var row = 0; row < moduleCount; row += 1) {
					if (qrcode.isDark(row, col) ) {
						darkCount += 1;
					}
				}
			}

			var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
			lostPoint += ratio * 10;

			return lostPoint;
		};

		return _this;
	}();

	//---------------------------------------------------------------------
	// QRMath
	//---------------------------------------------------------------------

	var QRMath = function() {

		var EXP_TABLE = new Array(256);
		var LOG_TABLE = new Array(256);

		// initialize tables
		for (var i = 0; i < 8; i += 1) {
			EXP_TABLE[i] = 1 << i;
		}
		for (var i = 8; i < 256; i += 1) {
			EXP_TABLE[i] = EXP_TABLE[i - 4]
				^ EXP_TABLE[i - 5]
				^ EXP_TABLE[i - 6]
				^ EXP_TABLE[i - 8];
		}
		for (var i = 0; i < 255; i += 1) {
			LOG_TABLE[EXP_TABLE[i] ] = i;
		}

		var _this = {};

		_this.glog = function(n) {

			if (n < 1) {
				throw new Error('glog(' + n + ')');
			}

			return LOG_TABLE[n];
		};

		_this.gexp = function(n) {

			while (n < 0) {
				n += 255;
			}

			while (n >= 256) {
				n -= 255;
			}

			return EXP_TABLE[n];
		};

		return _this;
	}();

	//---------------------------------------------------------------------
	// qrPolynomial
	//---------------------------------------------------------------------

	function qrPolynomial(num, shift) {

		if (typeof num.length == 'undefined') {
			throw new Error(num.length + '/' + shift);
		}

		var _num = function() {
			var offset = 0;
			while (offset < num.length && num[offset] == 0) {
				offset += 1;
			}
			var _num = new Array(num.length - offset + shift);
			for (var i = 0; i < num.length - offset; i += 1) {
				_num[i] = num[i + offset];
			}
			return _num;
		}();

		var _this = {};

		_this.getAt = function(index) {
			return _num[index];
		};

		_this.getLength = function() {
			return _num.length;
		};

		_this.multiply = function(e) {

			var num = new Array(_this.getLength() + e.getLength() - 1);

			for (var i = 0; i < _this.getLength(); i += 1) {
				for (var j = 0; j < e.getLength(); j += 1) {
					num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i) ) + QRMath.glog(e.getAt(j) ) );
				}
			}

			return qrPolynomial(num, 0);
		};

		_this.mod = function(e) {

			if (_this.getLength() - e.getLength() < 0) {
				return _this;
			}

			var ratio = QRMath.glog(_this.getAt(0) ) - QRMath.glog(e.getAt(0) );

			var num = new Array(_this.getLength() );
			for (var i = 0; i < _this.getLength(); i += 1) {
				num[i] = _this.getAt(i);
			}

			for (var i = 0; i < e.getLength(); i += 1) {
				num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio);
			}

			// recursive call
			return qrPolynomial(num, 0).mod(e);
		};

		return _this;
	};

	//---------------------------------------------------------------------
	// QRRSBlock
	//---------------------------------------------------------------------

	var QRRSBlock = function() {

		var RS_BLOCK_TABLE = [

			// L
			// M
			// Q
			// H

			// 1
			[1, 26, 19],
			[1, 26, 16],
			[1, 26, 13],
			[1, 26, 9],

			// 2
			[1, 44, 34],
			[1, 44, 28],
			[1, 44, 22],
			[1, 44, 16],

			// 3
			[1, 70, 55],
			[1, 70, 44],
			[2, 35, 17],
			[2, 35, 13],

			// 4
			[1, 100, 80],
			[2, 50, 32],
			[2, 50, 24],
			[4, 25, 9],

			// 5
			[1, 134, 108],
			[2, 67, 43],
			[2, 33, 15, 2, 34, 16],
			[2, 33, 11, 2, 34, 12],

			// 6
			[2, 86, 68],
			[4, 43, 27],
			[4, 43, 19],
			[4, 43, 15],

			// 7
			[2, 98, 78],
			[4, 49, 31],
			[2, 32, 14, 4, 33, 15],
			[4, 39, 13, 1, 40, 14],

			// 8
			[2, 121, 97],
			[2, 60, 38, 2, 61, 39],
			[4, 40, 18, 2, 41, 19],
			[4, 40, 14, 2, 41, 15],

			// 9
			[2, 146, 116],
			[3, 58, 36, 2, 59, 37],
			[4, 36, 16, 4, 37, 17],
			[4, 36, 12, 4, 37, 13],

			// 10
			[2, 86, 68, 2, 87, 69],
			[4, 69, 43, 1, 70, 44],
			[6, 43, 19, 2, 44, 20],
			[6, 43, 15, 2, 44, 16]
		];

		var qrRSBlock = function(totalCount, dataCount) {
			var _this = {};
			_this.totalCount = totalCount;
			_this.dataCount = dataCount;
			return _this;
		};

		var _this = {};

		var getRsBlockTable = function(typeNumber, errorCorrectLevel) {

			switch(errorCorrectLevel) {
			case QRErrorCorrectLevel.L :
				return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
			case QRErrorCorrectLevel.M :
				return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
			case QRErrorCorrectLevel.Q :
				return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
			case QRErrorCorrectLevel.H :
				return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
			default :
				return undefined;
			}
		};

		_this.getRSBlocks = function(typeNumber, errorCorrectLevel) {

			var rsBlock = getRsBlockTable(typeNumber, errorCorrectLevel);

			if (typeof rsBlock == 'undefined') {
				throw new Error('bad rs block @ typeNumber:' + typeNumber +
						'/errorCorrectLevel:' + errorCorrectLevel);
			}

			var length = rsBlock.length / 3;

			var list = new Array();

			for (var i = 0; i < length; i += 1) {

				var count = rsBlock[i * 3 + 0];
				var totalCount = rsBlock[i * 3 + 1];
				var dataCount = rsBlock[i * 3 + 2];

				for (var j = 0; j < count; j += 1) {
					list.push(qrRSBlock(totalCount, dataCount) );
				}
			}

			return list;
		};

		return _this;
	}();

	//---------------------------------------------------------------------
	// qrBitBuffer
	//---------------------------------------------------------------------

	var qrBitBuffer = function() {

		var _buffer = new Array();
		var _length = 0;

		var _this = {};

		_this.getBuffer = function() {
			return _buffer;
		};

		_this.getAt = function(index) {
			var bufIndex = Math.floor(index / 8);
			return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;
		};

		_this.put = function(num, length) {
			for (var i = 0; i < length; i += 1) {
				_this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);
			}
		};

		_this.getLengthInBits = function() {
			return _length;
		};

		_this.putBit = function(bit) {

			var bufIndex = Math.floor(_length / 8);
			if (_buffer.length <= bufIndex) {
				_buffer.push(0);
			}

			if (bit) {
				_buffer[bufIndex] |= (0x80 >>> (_length % 8) );
			}

			_length += 1;
		};

		return _this;
	};

	//---------------------------------------------------------------------
	// qr8BitByte
	//---------------------------------------------------------------------

	var qr8BitByte = function(data) {

		var _mode = QRMode.MODE_8BIT_BYTE;
		var _data = data;
		var _bytes = qrcode.stringToBytes(data);

		var _this = {};

		_this.getMode = function() {
			return _mode;
		};

		_this.getLength = function(buffer) {
			return _bytes.length;
		};

		_this.write = function(buffer) {
			for (var i = 0; i < _bytes.length; i += 1) {
				buffer.put(_bytes[i], 8);
			}
		};

		return _this;
	};

	//=====================================================================
	// GIF Support etc.
	//

	//---------------------------------------------------------------------
	// byteArrayOutputStream
	//---------------------------------------------------------------------

	var byteArrayOutputStream = function() {

		var _bytes = new Array();

		var _this = {};

		_this.writeByte = function(b) {
			_bytes.push(b & 0xff);
		};

		_this.writeShort = function(i) {
			_this.writeByte(i);
			_this.writeByte(i >>> 8);
		};

		_this.writeBytes = function(b, off, len) {
			off = off || 0;
			len = len || b.length;
			for (var i = 0; i < len; i += 1) {
				_this.writeByte(b[i + off]);
			}
		};

		_this.writeString = function(s) {
			for (var i = 0; i < s.length; i += 1) {
				_this.writeByte(s.charCodeAt(i) );
			}
		};

		_this.toByteArray = function() {
			return _bytes;
		};

		_this.toString = function() {
			var s = '';
			s += '[';
			for (var i = 0; i < _bytes.length; i += 1) {
				if (i > 0) {
					s += ',';
				}
				s += _bytes[i];
			}
			s += ']';
			return s;
		};

		return _this;
	};

	//---------------------------------------------------------------------
	// base64EncodeOutputStream
	//---------------------------------------------------------------------

	var base64EncodeOutputStream = function() {

		var _buffer = 0;
		var _buflen = 0;
		var _length = 0;
		var _base64 = '';

		var _this = {};

		var writeEncoded = function(b) {
			_base64 += String.fromCharCode(encode(b & 0x3f) );
		};

		var encode = function(n) {
			if (n < 0) {
				// error.
			} else if (n < 26) {
				return 0x41 + n;
			} else if (n < 52) {
				return 0x61 + (n - 26);
			} else if (n < 62) {
				return 0x30 + (n - 52);
			} else if (n == 62) {
				return 0x2b;
			} else if (n == 63) {
				return 0x2f;
			}
			throw new Error('n:' + n);
		};

		_this.writeByte = function(n) {

			_buffer = (_buffer << 8) | (n & 0xff);
			_buflen += 8;
			_length += 1;

			while (_buflen >= 6) {
				writeEncoded(_buffer >>> (_buflen - 6) );
				_buflen -= 6;
			}
		};

		_this.flush = function() {

			if (_buflen > 0) {
				writeEncoded(_buffer << (6 - _buflen) );
				_buffer = 0;
				_buflen = 0;
			}

			if (_length % 3 != 0) {
				// padding
				var padlen = 3 - _length % 3;
				for (var i = 0; i < padlen; i += 1) {
					_base64 += '=';
				}
			}
		};

		_this.toString = function() {
			return _base64;
		};

		return _this;
	};

	//---------------------------------------------------------------------
	// base64DecodeInputStream
	//---------------------------------------------------------------------

	var base64DecodeInputStream = function(str) {

		var _str = str;
		var _pos = 0;
		var _buffer = 0;
		var _buflen = 0;

		var _this = {};

		_this.read = function() {

			while (_buflen < 8) {

				if (_pos >= _str.length) {
					if (_buflen == 0) {
						return -1;
					}
					throw new Error('unexpected end of file./' + _buflen);
				}

				var c = _str.charAt(_pos);
				_pos += 1;

				if (c == '=') {
					_buflen = 0;
					return -1;
				} else if (c.match(/^\s$/) ) {
					// ignore if whitespace.
					continue;
				}

				_buffer = (_buffer << 6) | decode(c.charCodeAt(0) );
				_buflen += 6;
			}

			var n = (_buffer >>> (_buflen - 8) ) & 0xff;
			_buflen -= 8;
			return n;
		};

		var decode = function(c) {
			if (0x41 <= c && c <= 0x5a) {
				return c - 0x41;
			} else if (0x61 <= c && c <= 0x7a) {
				return c - 0x61 + 26;
			} else if (0x30 <= c && c <= 0x39) {
				return c - 0x30 + 52;
			} else if (c == 0x2b) {
				return 62;
			} else if (c == 0x2f) {
				return 63;
			} else {
				throw new Error('c:' + c);
			}
		};

		return _this;
	};

	//---------------------------------------------------------------------
	// gifImage (B/W)
	//---------------------------------------------------------------------

	var gifImage = function(width, height) {

		var _width = width;
		var _height = height;
		var _data = new Array(width * height);

		var _this = {};

		_this.setPixel = function(x, y, pixel) {
			_data[y * _width + x] = pixel;
		};

		_this.write = function(out) {

			//---------------------------------
			// GIF Signature

			out.writeString('GIF87a');

			//---------------------------------
			// Screen Descriptor

			out.writeShort(_width);
			out.writeShort(_height);

			out.writeByte(0x80); // 2bit
			out.writeByte(0);
			out.writeByte(0);

			//---------------------------------
			// Global Color Map

			// black
			out.writeByte(0x00);
			out.writeByte(0x00);
			out.writeByte(0x00);

			// white
			out.writeByte(0xff);
			out.writeByte(0xff);
			out.writeByte(0xff);

			//---------------------------------
			// Image Descriptor

			out.writeString(',');
			out.writeShort(0);
			out.writeShort(0);
			out.writeShort(_width);
			out.writeShort(_height);
			out.writeByte(0);

			//---------------------------------
			// Local Color Map

			//---------------------------------
			// Raster Data

			var lzwMinCodeSize = 2;
			var raster = getLZWRaster(lzwMinCodeSize);

			out.writeByte(lzwMinCodeSize);

			var offset = 0;

			while (raster.length - offset > 255) {
				out.writeByte(255);
				out.writeBytes(raster, offset, 255);
				offset += 255;
			}

			out.writeByte(raster.length - offset);
			out.writeBytes(raster, offset, raster.length - offset);
			out.writeByte(0x00);

			//---------------------------------
			// GIF Terminator
			out.writeString(';');
		};

		var bitOutputStream = function(out) {

			var _out = out;
			var _bitLength = 0;
			var _bitBuffer = 0;

			var _this = {};

			_this.write = function(data, length) {

				if ( (data >>> length) != 0) {
					throw new Error('length over');
				}

				while (_bitLength + length >= 8) {
					_out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) );
					length -= (8 - _bitLength);
					data >>>= (8 - _bitLength);
					_bitBuffer = 0;
					_bitLength = 0;
				}

				_bitBuffer = (data << _bitLength) | _bitBuffer;
				_bitLength = _bitLength + length;
			};

			_this.flush = function() {
				if (_bitLength > 0) {
					_out.writeByte(_bitBuffer);
				}
			};

			return _this;
		};

		var getLZWRaster = function(lzwMinCodeSize) {

			var clearCode = 1 << lzwMinCodeSize;
			var endCode = (1 << lzwMinCodeSize) + 1;
			var bitLength = lzwMinCodeSize + 1;

			// Setup LZWTable
			var table = lzwTable();

			for (var i = 0; i < clearCode; i += 1) {
				table.add(String.fromCharCode(i) );
			}
			table.add(String.fromCharCode(clearCode) );
			table.add(String.fromCharCode(endCode) );

			var byteOut = byteArrayOutputStream();
			var bitOut = bitOutputStream(byteOut);

			// clear code
			bitOut.write(clearCode, bitLength);

			var dataIndex = 0;

			var s = String.fromCharCode(_data[dataIndex]);
			dataIndex += 1;

			while (dataIndex < _data.length) {

				var c = String.fromCharCode(_data[dataIndex]);
				dataIndex += 1;

				if (table.contains(s + c) ) {

					s = s + c;

				} else {

					bitOut.write(table.indexOf(s), bitLength);

					if (table.size() < 0xfff) {

						if (table.size() == (1 << bitLength) ) {
							bitLength += 1;
						}

						table.add(s + c);
					}

					s = c;
				}
			}

			bitOut.write(table.indexOf(s), bitLength);

			// end code
			bitOut.write(endCode, bitLength);

			bitOut.flush();

			return byteOut.toByteArray();
		};

		var lzwTable = function() {

			var _map = {};
			var _size = 0;

			var _this = {};

			_this.add = function(key) {
				if (_this.contains(key) ) {
					throw new Error('dup key:' + key);
				}
				_map[key] = _size;
				_size += 1;
			};

			_this.size = function() {
				return _size;
			};

			_this.indexOf = function(key) {
				return _map[key];
			};

			_this.contains = function(key) {
				return typeof _map[key] != 'undefined';
			};

			return _this;
		};

		return _this;
	};

	var createImgTag = function(width, height, getPixel, alt) {

		var gif = gifImage(width, height);
		for (var y = 0; y < height; y += 1) {
			for (var x = 0; x < width; x += 1) {
				gif.setPixel(x, y, getPixel(x, y) );
			}
		}

		var b = byteArrayOutputStream();
		gif.write(b);

		var base64 = base64EncodeOutputStream();
		var bytes = b.toByteArray();
		for (var i = 0; i < bytes.length; i += 1) {
			base64.writeByte(bytes[i]);
		}
		base64.flush();

		var img = '';
		img += '<img';
		img += '\u0020src="';
		img += 'data:image/gif;base64,';
		img += base64;
		img += '"';
		img += '\u0020width="';
		img += width;
		img += '"';
		img += '\u0020height="';
		img += height;
		img += '"';
		if (alt) {
			img += '\u0020alt="';
			img += alt;
			img += '"';
		}
		img += '/>';

		return img;
	};

	//---------------------------------------------------------------------
	// returns qrcode function.

	return qrcode;
}();

/**
 * Copyright (c) 2011-2014 Felix Gnass
 * Licensed under the MIT license
 */
(function(root, factory) {

  /* CommonJS */
  if (typeof exports == 'object')  module.exports = factory()

  /* AMD module */
  else if (typeof define == 'function' && define.amd) define(factory)

  /* Browser global */
  else root.Spinner = factory()
}
(this, function() {
  "use strict";

  var prefixes = ['webkit', 'Moz', 'ms', 'O'] /* Vendor prefixes */
    , animations = {} /* Animation rules keyed by their name */
    , useCssAnimations /* Whether to use CSS animations or setTimeout */

  /**
   * Utility function to create elements. If no tag name is given,
   * a DIV is created. Optionally properties can be passed.
   */
  function createEl(tag, prop) {
    var el = document.createElement(tag || 'div')
      , n

    for(n in prop) el[n] = prop[n]
    return el
  }

  /**
   * Appends children and returns the parent.
   */
  function ins(parent /* child1, child2, ...*/) {
    for (var i=1, n=arguments.length; i<n; i++)
      parent.appendChild(arguments[i])

    return parent
  }

  /**
   * Insert a new stylesheet to hold the @keyframe or VML rules.
   */
  var sheet = (function() {
    var el = createEl('style', {type : 'text/css'})
    ins(document.getElementsByTagName('head')[0], el)
    return el.sheet || el.styleSheet
  }())

  /**
   * Creates an opacity keyframe animation rule and returns its name.
   * Since most mobile Webkits have timing issues with animation-delay,
   * we create separate rules for each line/segment.
   */
  function addAnimation(alpha, trail, i, lines) {
    var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-')
      , start = 0.01 + i/lines * 100
      , z = Math.max(1 - (1-alpha) / trail * (100-start), alpha)
      , prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase()
      , pre = prefix && '-' + prefix + '-' || ''

    if (!animations[name]) {
      sheet.insertRule(
        '@' + pre + 'keyframes ' + name + '{' +
        '0%{opacity:' + z + '}' +
        start + '%{opacity:' + alpha + '}' +
        (start+0.01) + '%{opacity:1}' +
        (start+trail) % 100 + '%{opacity:' + alpha + '}' +
        '100%{opacity:' + z + '}' +
        '}', sheet.cssRules.length)

      animations[name] = 1
    }

    return name
  }

  /**
   * Tries various vendor prefixes and returns the first supported property.
   */
  function vendor(el, prop) {
    var s = el.style
      , pp
      , i

    prop = prop.charAt(0).toUpperCase() + prop.slice(1)
    for(i=0; i<prefixes.length; i++) {
      pp = prefixes[i]+prop
      if(s[pp] !== undefined) return pp
    }
    if(s[prop] !== undefined) return prop
  }

  /**
   * Sets multiple style properties at once.
   */
  function css(el, prop) {
    for (var n in prop)
      el.style[vendor(el, n)||n] = prop[n]

    return el
  }

  /**
   * Fills in default values.
   */
  function merge(obj) {
    for (var i=1; i < arguments.length; i++) {
      var def = arguments[i]
      for (var n in def)
        if (obj[n] === undefined) obj[n] = def[n]
    }
    return obj
  }

  /**
   * Returns the absolute page-offset of the given element.
   */
  function pos(el) {
    var o = { x:el.offsetLeft, y:el.offsetTop }
    while((el = el.offsetParent))
      o.x+=el.offsetLeft, o.y+=el.offsetTop

    return o
  }

  /**
   * Returns the line color from the given string or array.
   */
  function getColor(color, idx) {
    return typeof color == 'string' ? color : color[idx % color.length]
  }

  // Built-in defaults

  var defaults = {
    lines: 12,            // The number of lines to draw
    length: 7,            // The length of each line
    width: 5,             // The line thickness
    radius: 10,           // The radius of the inner circle
    rotate: 0,            // Rotation offset
    corners: 1,           // Roundness (0..1)
    color: '#000',        // #rgb or #rrggbb
    direction: 1,         // 1: clockwise, -1: counterclockwise
    speed: 1,             // Rounds per second
    trail: 100,           // Afterglow percentage
    opacity: 1/4,         // Opacity of the lines
    fps: 20,              // Frames per second when using setTimeout()
    zIndex: 2e9,          // Use a high z-index by default
    className: 'spinner', // CSS class to assign to the element
    top: '50%',           // center vertically
    left: '50%',          // center horizontally
    position: 'absolute'  // element position
  }

  /** The constructor */
  function Spinner(o) {
    this.opts = merge(o || {}, Spinner.defaults, defaults)
  }

  // Global defaults that override the built-ins:
  Spinner.defaults = {}

  merge(Spinner.prototype, {

    /**
     * Adds the spinner to the given target element. If this instance is already
     * spinning, it is automatically removed from its previous target b calling
     * stop() internally.
     */
    spin: function(target) {
      this.stop()

      var self = this
        , o = self.opts
        , el = self.el = css(createEl(0, {className: o.className}), {position: o.position, width: 0, zIndex: o.zIndex})
        , mid = o.radius+o.length+o.width

      css(el, {
        left: o.left,
        top: o.top
      })
        
      if (target) {
        target.insertBefore(el, target.firstChild||null)
      }

      el.setAttribute('role', 'progressbar')
      self.lines(el, self.opts)

      if (!useCssAnimations) {
        // No CSS animation support, use setTimeout() instead
        var i = 0
          , start = (o.lines - 1) * (1 - o.direction) / 2
          , alpha
          , fps = o.fps
          , f = fps/o.speed
          , ostep = (1-o.opacity) / (f*o.trail / 100)
          , astep = f/o.lines

        ;(function anim() {
          i++;
          for (var j = 0; j < o.lines; j++) {
            alpha = Math.max(1 - (i + (o.lines - j) * astep) % f * ostep, o.opacity)

            self.opacity(el, j * o.direction + start, alpha, o)
          }
          self.timeout = self.el && setTimeout(anim, ~~(1000/fps))
        })()
      }
      return self
    },

    /**
     * Stops and removes the Spinner.
     */
    stop: function() {
      var el = this.el
      if (el) {
        clearTimeout(this.timeout)
        if (el.parentNode) el.parentNode.removeChild(el)
        this.el = undefined
      }
      return this
    },

    /**
     * Internal method that draws the individual lines. Will be overwritten
     * in VML fallback mode below.
     */
    lines: function(el, o) {
      var i = 0
        , start = (o.lines - 1) * (1 - o.direction) / 2
        , seg

      function fill(color, shadow) {
        return css(createEl(), {
          position: 'absolute',
          width: (o.length+o.width) + 'px',
          height: o.width + 'px',
          background: color,
          boxShadow: shadow,
          transformOrigin: 'left',
          transform: 'rotate(' + ~~(360/o.lines*i+o.rotate) + 'deg) translate(' + o.radius+'px' +',0)',
          borderRadius: (o.corners * o.width>>1) + 'px'
        })
      }

      for (; i < o.lines; i++) {
        seg = css(createEl(), {
          position: 'absolute',
          top: 1+~(o.width/2) + 'px',
          transform: o.hwaccel ? 'translate3d(0,0,0)' : '',
          opacity: o.opacity,
          animation: useCssAnimations && addAnimation(o.opacity, o.trail, start + i * o.direction, o.lines) + ' ' + 1/o.speed + 's linear infinite'
        })

        if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'}))
        ins(el, ins(seg, fill(getColor(o.color, i), '0 0 1px rgba(0,0,0,.1)')))
      }
      return el
    },

    /**
     * Internal method that adjusts the opacity of a single line.
     * Will be overwritten in VML fallback mode below.
     */
    opacity: function(el, i, val) {
      if (i < el.childNodes.length) el.childNodes[i].style.opacity = val
    }

  })


  function initVML() {

    /* Utility function to create a VML tag */
    function vml(tag, attr) {
      return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr)
    }

    // No CSS transforms but VML support, add a CSS rule for VML elements:
    sheet.addRule('.spin-vml', 'behavior:url(#default#VML)')

    Spinner.prototype.lines = function(el, o) {
      var r = o.length+o.width
        , s = 2*r

      function grp() {
        return css(
          vml('group', {
            coordsize: s + ' ' + s,
            coordorigin: -r + ' ' + -r
          }),
          { width: s, height: s }
        )
      }

      var margin = -(o.width+o.length)*2 + 'px'
        , g = css(grp(), {position: 'absolute', top: margin, left: margin})
        , i

      function seg(i, dx, filter) {
        ins(g,
          ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
            ins(css(vml('roundrect', {arcsize: o.corners}), {
                width: r,
                height: o.width,
                left: o.radius,
                top: -o.width>>1,
                filter: filter
              }),
              vml('fill', {color: getColor(o.color, i), opacity: o.opacity}),
              vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
            )
          )
        )
      }

      if (o.shadow)
        for (i = 1; i <= o.lines; i++)
          seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)')

      for (i = 1; i <= o.lines; i++) seg(i)
      return ins(el, g)
    }

    Spinner.prototype.opacity = function(el, i, val, o) {
      var c = el.firstChild
      o = o.shadow && o.lines || 0
      if (c && i+o < c.childNodes.length) {
        c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild
        if (c) c.opacity = val
      }
    }
  }

  var probe = css(createEl('group'), {behavior: 'url(#default#VML)'})

  if (!vendor(probe, 'transform') && probe.adj) initVML()
  else useCssAnimations = vendor(probe, 'animation')

  return Spinner

}));

/*
 The MIT License (MIT)

 Copyright (c) 2014 Muhammed Ashik

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 */

/*jshint indent: 2 */
/*global angular: false */

(function () {
  'use strict';
  angular.module('ui.sortable', [])
    .constant('sortableConfig', {
      itemClass: 'as-sortable-item',
      handleClass: 'as-sortable-item-handle',
      placeHolderClass: 'as-sortable-placeholder',
      dragClass: 'as-sortable-drag',
      hiddenClass: 'as-sortable-hidden'
    });
}());

/*jshint indent: 2 */
/*global angular: false */

(function () {
  'use strict';

  var mainModule = angular.module('ui.sortable');

  /**
   * Helper factory for sortable.
   */
  mainModule.factory('$helper', ['$document', '$window',
    function ($document, $window) {
      return {

        /**
         * Get the height of an element.
         *
         * @param {Object} element Angular element.
         * @returns {String} Height
         */
        height: function (element) {
          return element.prop('offsetHeight');
        },

        /**
         * Get the width of an element.
         *
         * @param {Object} element Angular element.
         * @returns {String} Width
         */
        width: function (element) {
          return element.prop('offsetWidth');
        },

        /**
         * Get the offset values of an element.
         *
         * @param {Object} element Angular element.
         * @param {Object} [scrollableContainer] Scrollable container object for calculating relative top & left (optional, defaults to Document)
         * @returns {Object} Object with properties width, height, top and left
         */
        offset: function (element, scrollableContainer) {
          var boundingClientRect = element[0].getBoundingClientRect();
          if (!scrollableContainer) { scrollableContainer = $document[0].documentElement; }

          return {
            width: boundingClientRect.width || element.prop('offsetWidth'),
            height: boundingClientRect.height || element.prop('offsetHeight'),
            top: boundingClientRect.top + ($window.pageYOffset || scrollableContainer.scrollTop - scrollableContainer.offsetTop),
            left: boundingClientRect.left + ($window.pageXOffset || scrollableContainer.scrollLeft - scrollableContainer.offsetLeft)
          };
        },

        /**
         * get the event object for touch.
         *
         * @param  {Object} event the touch event
         * @return {Object} the touch event object.
         */
        eventObj: function (event) {
          var obj = event;
          if (event.targetTouches !== undefined) {
            obj = event.targetTouches.item(0);
          } else if (event.originalEvent !== undefined && event.originalEvent.targetTouches !== undefined) {
            obj = event.originalEvent.targetTouches.item(0);
          }
          return obj;
        },

        /**
         * Checks whether the touch is valid and multiple.
         *
         * @param event the event object.
         * @returns {boolean} true if touch is multiple.
         */
        isTouchInvalid: function (event) {

          var touchInvalid = false;
          if (event.touches !== undefined && event.touches.length > 1) {
            touchInvalid = true;
          } else if (event.originalEvent !== undefined &&
            event.originalEvent.touches !== undefined && event.originalEvent.touches.length > 1) {
            touchInvalid = true;
          }
          return touchInvalid;
        },

        /**
         * Get the start position of the target element according to the provided event properties.
         *
         * @param {Object} event Event
         * @param {Object} target Target element
         * @param {Object} [scrollableContainer] (optional) Scrollable container object
         * @returns {Object} Object with properties offsetX, offsetY.
         */
        positionStarted: function (event, target, scrollableContainer) {
          var pos = {};
          pos.offsetX = event.pageX - this.offset(target, scrollableContainer).left;
          pos.offsetY = event.pageY - this.offset(target, scrollableContainer).top;
          pos.startX = pos.lastX = event.pageX;
          pos.startY = pos.lastY = event.pageY;
          pos.nowX = pos.nowY = pos.distX = pos.distY = pos.dirAx = 0;
          pos.dirX = pos.dirY = pos.lastDirX = pos.lastDirY = pos.distAxX = pos.distAxY = 0;
          return pos;
        },

        /**
         * Calculates the event position and sets the direction
         * properties.
         *
         * @param pos the current position of the element.
         * @param event the move event.
         */
        calculatePosition: function (pos, event) {
          // mouse position last events
          pos.lastX = pos.nowX;
          pos.lastY = pos.nowY;

          // mouse position this events
          pos.nowX = event.pageX;
          pos.nowY = event.pageY;

          // distance mouse moved between events
          pos.distX = pos.nowX - pos.lastX;
          pos.distY = pos.nowY - pos.lastY;

          // direction mouse was moving
          pos.lastDirX = pos.dirX;
          pos.lastDirY = pos.dirY;

          // direction mouse is now moving (on both axis)
          pos.dirX = pos.distX === 0 ? 0 : pos.distX > 0 ? 1 : -1;
          pos.dirY = pos.distY === 0 ? 0 : pos.distY > 0 ? 1 : -1;

          // axis mouse is now moving on
          var newAx = Math.abs(pos.distX) > Math.abs(pos.distY) ? 1 : 0;

          // calc distance moved on this axis (and direction)
          if (pos.dirAx !== newAx) {
            pos.distAxX = 0;
            pos.distAxY = 0;
          } else {
            pos.distAxX += Math.abs(pos.distX);
            if (pos.dirX !== 0 && pos.dirX !== pos.lastDirX) {
              pos.distAxX = 0;
            }

            pos.distAxY += Math.abs(pos.distY);
            if (pos.dirY !== 0 && pos.dirY !== pos.lastDirY) {
              pos.distAxY = 0;
            }
          }
          pos.dirAx = newAx;
        },

        /**
         * Move the position by applying style.
         *
         * @param event the event object
         * @param element - the dom element
         * @param pos - current position
         * @param container - the bounding container.
         * @param containerPositioning - absolute or relative positioning.
         * @param {Object} [scrollableContainer] (optional) Scrollable container object
         */
        movePosition: function (event, element, pos, container, containerPositioning, scrollableContainer) {
          var bounds;
          var useRelative = (containerPositioning === 'relative');

          element.x = event.pageX - pos.offsetX;
          element.y = event.pageY - pos.offsetY;

          if (container) {
            bounds = this.offset(container, scrollableContainer);

            if (useRelative) {
              // reduce positioning by bounds
              element.x -= bounds.left;
              element.y -= bounds.top;

              // reset bounds
              bounds.left = 0;
              bounds.top = 0;
            }

            if (element.x < bounds.left) {
              element.x = bounds.left;
            } else if (element.x >= bounds.width + bounds.left - this.offset(element).width) {
              element.x = bounds.width + bounds.left - this.offset(element).width;
            }
            if (element.y < bounds.top) {
              element.y = bounds.top;
            } else if (element.y >= bounds.height + bounds.top - this.offset(element).height) {
              element.y = bounds.height + bounds.top - this.offset(element).height;
            }
          }

          element.css({
            'left': element.x + 'px',
            'top': element.y + 'px'
          });

          this.calculatePosition(pos, event);
        },

        /**
         * The drag item info and functions.
         * retains the item info before and after move.
         * holds source item and target scope.
         *
         * @param item - the drag item
         * @returns {{index: *, parent: *, source: *,
                 *          sourceInfo: {index: *, itemScope: (*|.dragItem.sourceInfo.itemScope|$scope.itemScope|itemScope), sortableScope: *},
                 *         moveTo: moveTo, isSameParent: isSameParent, isOrderChanged: isOrderChanged, eventArgs: eventArgs, apply: apply}}
         */
        dragItem: function (item) {

          return {
            index: item.index(),
            parent: item.sortableScope,
            source: item,
            sourceInfo: {
              index: item.index(),
              itemScope: item.itemScope,
              sortableScope: item.sortableScope
            },
            moveTo: function (parent, index) { // Move the item to a new position
              this.parent = parent;
              //If source Item is in the same Parent.
              if (this.isSameParent() && this.source.index() < index) { // and target after
                index = index - 1;
              }
              this.index = index;
            },
            isSameParent: function () {
              return this.parent.element === this.sourceInfo.sortableScope.element;
            },
            isOrderChanged: function () {
              return this.index !== this.sourceInfo.index;
            },
            eventArgs: function () {
              return {
                source: this.sourceInfo,
                dest: {
                  index: this.index,
                  sortableScope: this.parent
                }
              };
            },
            apply: function () {
              this.sourceInfo.sortableScope.removeItem(this.sourceInfo.index); // Remove from source.
              this.parent.insertItem(this.index, this.source.modelValue); // Insert in to destination.
            }
          };
        },

        /**
         * Check the drag is not allowed for the element.
         *
         * @param element - the element to check
         * @returns {boolean} - true if drag is not allowed.
         */
        noDrag: function (element) {
          return element.attr('no-drag') !== undefined || element.attr('data-no-drag') !== undefined;
        }
      };
    }
  ]);

}());
/*jshint undef: false, unused: false, indent: 2*/
/*global angular: false */

(function () {

  'use strict';
  var mainModule = angular.module('ui.sortable');

  /**
   * Controller for Sortable.
   * @param $scope - the sortable scope.
   */
  mainModule.controller('ui.sortable.sortableController', ['$scope', function ($scope) {

    this.scope = $scope;

    $scope.modelValue = null; // sortable list.
    $scope.callbacks = null;
    $scope.type = 'sortable';
    $scope.options = {};
    $scope.isDisabled = false;

    /**
     * Inserts the item in to the sortable list.
     *
     * @param index - the item index.
     * @param itemData - the item model data.
     */
    $scope.insertItem = function (index, itemData) {
      $scope.safeApply(function () {
        $scope.modelValue.splice(index, 0, itemData);
      });
    };

    /**
     * Removes the item from the sortable list.
     *
     * @param index - index to be removed.
     * @returns {*} - removed item.
     */
    $scope.removeItem = function (index) {
      var removedItem = null;
      if (index > -1) {
        $scope.safeApply(function () {
          removedItem = $scope.modelValue.splice(index, 1)[0];
        });
      }
      return removedItem;
    };

    /**
     * Checks whether the sortable list is empty.
     *
     * @returns {null|*|$scope.modelValue|boolean}
     */
    $scope.isEmpty = function () {
      return ($scope.modelValue && $scope.modelValue.length === 0);
    };

    /**
     * Wrapper for the accept callback delegates to callback.
     *
     * @param sourceItemHandleScope - drag item handle scope.
     * @param destScope - sortable target scope.
     * @param destItemScope - sortable destination item scope.
     * @returns {*|boolean} - true if drop is allowed for the drag item in drop target.
     */
    $scope.accept = function (sourceItemHandleScope, destScope, destItemScope) {
      return $scope.callbacks.accept(sourceItemHandleScope, destScope, destItemScope);
    };

    /**
     * Checks the current phase before executing the function.
     *
     * @param fn the function to execute.
     */
    $scope.safeApply = function (fn) {
      var phase = this.$root.$$phase;
      if (phase === '$apply' || phase === '$digest') {
        if (fn && (typeof fn === 'function')) {
          fn();
        }
      } else {
        this.$apply(fn);
      }
    };

  }]);

  /**
   * Sortable directive - defines callbacks.
   * Parent directive for draggable and sortable items.
   * Sets modelValue, callbacks, element in scope.
   */
  mainModule.directive('asSortable',
    function () {
      return {
        require: 'ngModel', // get a hold of NgModelController
        restrict: 'A',
        scope: true,
        controller: 'ui.sortable.sortableController',
        link: function (scope, element, attrs, ngModelController) {

          var ngModel, callbacks;

          ngModel = ngModelController;

          if (!ngModel) {
            return; // do nothing if no ng-model
          }

          // Set the model value in to scope.
          ngModel.$render = function () {
            //set an empty array, in case if none is provided.
            if (!ngModel.$modelValue || !angular.isArray(ngModel.$modelValue)) {
              ngModel.$setViewValue([]);
            }
            scope.modelValue = ngModel.$modelValue;
          };
          //set the element in scope to be accessed by its sub scope.
          scope.element = element;

          callbacks = {accept: null, orderChanged: null, itemMoved: null, dragStart: null, dragCancel: null, dragEnd: null};

          /**
           * Invoked to decide whether to allow drop.
           *
           * @param sourceItemHandleScope - the drag item handle scope.
           * @param destSortableScope - the drop target sortable scope.
           * @param destItemScope - the drop target item scope.
           * @returns {boolean} - true if allowed for drop.
           */
          callbacks.accept = function (sourceItemHandleScope, destSortableScope, destItemScope) {
            return true;
          };

          /**
           * Invoked when order of a drag item is changed.
           *
           * @param event - the event object.
           */
          callbacks.orderChanged = function (event) {
          };

          /**
           * Invoked when the item is moved to other sortable.
           *
           * @param event - the event object.
           */
          callbacks.itemMoved = function (event) {
          };

          /**
           * Invoked when the drag started successfully.
           *
           * @param event - the event object.
           */
          callbacks.dragStart = function (event) {
          };

          /**
           * Invoked when the drag cancelled.
           *
           * @param event - the event object.
           */
          callbacks.dragCancel = function (event) {
          };

          /**
           * Invoked when the drag stopped.
           *
           * @param event - the event object.
           */
          callbacks.dragEnd = function (event) {
          };

          //Set the sortOptions callbacks else set it to default.
          scope.$watch(attrs.asSortable, function (newVal, oldVal) {
            angular.forEach(newVal, function (value, key) {
              if (callbacks[key]) {
                if (typeof value === 'function') {
                  callbacks[key] = value;
                }
              } else {
                scope.options[key] = value;
              }
            });
            scope.callbacks = callbacks;
          }, true);

          // Set isDisabled if attr is set, if undefined isDisabled = false
          if(angular.isDefined(attrs.isDisabled)) {
            scope.$watch(attrs.isDisabled, function (newVal, oldVal) {
              if(!angular.isUndefined(newVal)) {
                scope.isDisabled = newVal;
              }
            }, true);
          }
        }
      };
    });

}());

/*jshint indent: 2 */
/*global angular: false */

(function () {

  'use strict';
  var mainModule = angular.module('ui.sortable');

  /**
   * Controller for sortableItemHandle
   *
   * @param $scope - item handle scope.
   */
  mainModule.controller('ui.sortable.sortableItemHandleController', ['$scope', function ($scope) {

    this.scope = $scope;

    $scope.itemScope = null;
    $scope.type = 'handle';
  }]);

  /**
   * Directive for sortable item handle.
   */
  mainModule.directive('asSortableItemHandle', ['sortableConfig', '$helper', '$window', '$document',
    function (sortableConfig, $helper, $window, $document) {
      return {
        require: '^asSortableItem',
        scope: true,
        restrict: 'A',
        controller: 'ui.sortable.sortableItemHandleController',
        link: function (scope, element, attrs, itemController) {

          var dragElement, //drag item element.
            placeHolder, //place holder class element.
            placeElement,//hidden place element.
            itemPosition, //drag item element position.
            dragItemInfo, //drag item data.
            containment,//the drag container.
            containerPositioning, // absolute or relative positioning.
            dragListen,// drag listen event.
            scrollableContainer, //the scrollable container
            dragStart,// drag start event.
            dragMove,//drag move event.
            dragEnd,//drag end event.
            dragCancel,//drag cancel event.
            isDraggable,//is element draggable.
            isDragBefore,//is element moved up direction.
            isPlaceHolderPresent,//is placeholder present.
            bindDrag,//bind drag events.
            unbindDrag,//unbind drag events.
            bindEvents,//bind the drag events.
            unBindEvents,//unbind the drag events.
            hasTouch,// has touch support.
            dragHandled, //drag handled.
            isDisabled = false; // drag enabled

          hasTouch = $window.hasOwnProperty('ontouchstart');

          if (sortableConfig.handleClass) {
            element.addClass(sortableConfig.handleClass);
          }

          scope.itemScope = itemController.scope;

          scope.$watch('sortableScope.isDisabled', function(newVal) {
            if(isDisabled !== newVal) {
              isDisabled = newVal;
              if(isDisabled) {
                unbindDrag();
              } else {
                bindDrag();
              }
            }
          });

          /**
          * Listens for a 10px movement before
          * dragStart is called to allow for
          * a click event on the element.
          *
          * @param event - the event object.
          */
          dragListen = function (event) {

            var unbindMoveListen = function () {
              angular.element($document).unbind('mousemove', moveListen);
              angular.element($document).unbind('touchmove', moveListen);
              element.unbind('mouseup', unbindMoveListen);
              element.unbind('touchend', unbindMoveListen);
              element.unbind('touchcancel', unbindMoveListen);
            };
            
            var startPosition;
            var moveListen = function (e) {
              e.preventDefault();
              var eventObj = $helper.eventObj(e);
              if (!startPosition) {
                startPosition = { clientX: eventObj.clientX, clientY: eventObj.clientY };
              }
              if (Math.abs(eventObj.clientX - startPosition.clientX) + Math.abs(eventObj.clientY - startPosition.clientY) > 10) {
                unbindMoveListen();
                dragStart(event);
              }
            };
            
            angular.element($document).bind('mousemove', moveListen);
            angular.element($document).bind('touchmove', moveListen);
            element.bind('mouseup', unbindMoveListen);
            element.bind('touchend', unbindMoveListen);
            element.bind('touchcancel', unbindMoveListen);
          };

          /**
           * Triggered when drag event starts.
           *
           * @param event the event object.
           */
          dragStart = function (event) {

            var eventObj, tagName;

            if (!hasTouch && (event.button === 2 || event.which === 3)) {
              // disable right click
              return;
            }
            if (hasTouch && $helper.isTouchInvalid(event)) {
              return;
            }
            if (dragHandled || !isDraggable(event)) {
              // event has already fired in other scope.
              return;
            }
            // Set the flag to prevent other items from inheriting the drag event
            dragHandled = true;
            event.preventDefault();
            eventObj = $helper.eventObj(event);

            // (optional) Scrollable container as reference for top & left offset calculations, defaults to Document
            scrollableContainer = angular.element($document[0].querySelector(scope.sortableScope.options.scrollableContainer)).length > 0 ?
              $document[0].querySelector(scope.sortableScope.options.scrollableContainer) : $document[0].documentElement;

            containment = angular.element($document[0].querySelector(scope.sortableScope.options.containment)).length > 0 ?
              angular.element($document[0].querySelector(scope.sortableScope.options.containment)) : angular.element($document[0].body);
            //capture mouse move on containment.
            containment.css('cursor', 'move');

            // container positioning
            containerPositioning = scope.sortableScope.options.containerPositioning || 'absolute';

            dragItemInfo = $helper.dragItem(scope);
            tagName = scope.itemScope.element.prop('tagName');

            dragElement = angular.element($document[0].createElement(scope.sortableScope.element.prop('tagName')))
              .addClass(scope.sortableScope.element.attr('class')).addClass(sortableConfig.dragClass);
            dragElement.css('width', $helper.width(scope.itemScope.element) + 'px');
            dragElement.css('height', $helper.height(scope.itemScope.element) + 'px');

            placeHolder = angular.element($document[0].createElement(tagName))
                .addClass(sortableConfig.placeHolderClass).addClass(scope.sortableScope.options.additionalPlaceholderClass);
            placeHolder.css('width', $helper.width(scope.itemScope.element) + 'px');
            placeHolder.css('height', $helper.height(scope.itemScope.element) + 'px');

            placeElement = angular.element($document[0].createElement(tagName));
            if (sortableConfig.hiddenClass) {
              placeElement.addClass(sortableConfig.hiddenClass);
            }

            itemPosition = $helper.positionStarted(eventObj, scope.itemScope.element, scrollableContainer);
            //fill the immediate vacuum.
            scope.itemScope.element.after(placeHolder);
            //hidden place element in original position.
            scope.itemScope.element.after(placeElement);
            dragElement.append(scope.itemScope.element);

            containment.append(dragElement);
            $helper.movePosition(eventObj, dragElement, itemPosition, containment, containerPositioning, scrollableContainer);

            scope.sortableScope.$apply(function () {
              scope.callbacks.dragStart(dragItemInfo.eventArgs());
            });
            bindEvents();
          };

          /**
           * Allow Drag if it is a proper item-handle element.
           *
           * @param event - the event object.
           * @return boolean - true if element is draggable.
           */
          isDraggable = function (event) {

            var elementClicked, sourceScope, isDraggable;

            elementClicked = angular.element(event.target);
            sourceScope = elementClicked.scope();

            // look for the handle on the current scope or parent scopes
            isDraggable = false;
            while (!isDraggable && sourceScope !== undefined) {
              if (sourceScope.type && sourceScope.type === 'handle') {
                isDraggable = true;
              } else {
                sourceScope = sourceScope.$parent;
              }
            }

            //If a 'no-drag' element inside item-handle if any.
            while (isDraggable && elementClicked[0] !== element[0]) {
              if ($helper.noDrag(elementClicked)) {
                isDraggable = false;
              }
              elementClicked = elementClicked.parent();
            }
            return isDraggable;
          };

          /**
           * Inserts the placeHolder in to the targetScope.
           *
           * @param targetElement the target element
           * @param targetScope the target scope
           */
          function insertBefore(targetElement, targetScope) {
            targetElement[0].parentNode.insertBefore(placeHolder[0], targetElement[0]);
            dragItemInfo.moveTo(targetScope.sortableScope, targetScope.index());
          }

          /**
           * Inserts the placeHolder next to the targetScope.
           *
           * @param targetElement the target element
           * @param targetScope the target scope
           */
          function insertAfter(targetElement, targetScope) {
            targetElement.after(placeHolder);
            dragItemInfo.moveTo(targetScope.sortableScope, targetScope.index() + 1);
          }

          /**
           * Triggered when drag is moving.
           *
           * @param event - the event object.
           */
          dragMove = function (event) {

            var eventObj, targetX, targetY, targetScope, targetElement;

            if (hasTouch && $helper.isTouchInvalid(event)) {
              return;
            }
            // Ignore event if not handled
            if (!dragHandled) {
              return;
            }
            if (dragElement) {

              event.preventDefault();

              eventObj = $helper.eventObj(event);
              $helper.movePosition(eventObj, dragElement, itemPosition, containment, containerPositioning, scrollableContainer);

              targetX = eventObj.pageX - $document[0].documentElement.scrollLeft;
              targetY = eventObj.pageY - ($window.pageYOffset || $document[0].documentElement.scrollTop);

              //IE fixes: hide show element, call element from point twice to return pick correct element.
              dragElement.addClass(sortableConfig.hiddenClass);
              $document[0].elementFromPoint(targetX, targetY);
              targetElement = angular.element($document[0].elementFromPoint(targetX, targetY));
              dragElement.removeClass(sortableConfig.hiddenClass);

              targetScope = targetElement.scope();

              if (!targetScope || !targetScope.type) {
                return;
              }
              if (targetScope.type === 'handle') {
                targetScope = targetScope.itemScope;
              }
              if (targetScope.type !== 'item' && targetScope.type !== 'sortable') {
                return;
              }

              if (targetScope.type === 'item') {
                targetElement = targetScope.element;
                if (targetScope.sortableScope.accept(scope, targetScope.sortableScope, targetScope)) {
                  if (itemPosition.dirAx && //move horizontal
                    scope.itemScope.sortableScope.$id === targetScope.sortableScope.$id) { //move same column
                    itemPosition.distAxX = 0;
                    if (itemPosition.distX < 0) {//move left
                      insertBefore(targetElement, targetScope);
                    } else if (itemPosition.distX > 0) {//move right
                      insertAfter(targetElement, targetScope);
                    }
                  } else { //move vertical
                    if (isDragBefore(eventObj, targetElement)) {//move up
                      insertBefore(targetElement, targetScope);
                    } else {//move bottom
                      insertAfter(targetElement, targetScope);
                    }
                  }
                }
              }
              if (targetScope.type === 'sortable') {//sortable scope.
                if (targetScope.accept(scope, targetScope) &&
                  targetElement[0].parentNode !== targetScope.element[0]) {
                  //moving over sortable bucket. not over item.
                  if (!isPlaceHolderPresent(targetElement)) {
                    //append to bottom.
                    targetElement[0].appendChild(placeHolder[0]);
                    dragItemInfo.moveTo(targetScope, targetScope.modelValue.length);
                  }
                }
              }
            }
          };

          /**
           * Check there is no place holder placed by itemScope.
           * @param targetElement the target element to check with.
           * @returns {*} true if place holder present.
           */
          isPlaceHolderPresent = function (targetElement) {
            var itemElements, hasPlaceHolder, i;

            itemElements = targetElement.children();
            for (i = 0; i < itemElements.length; i += 1) {
              if (angular.element(itemElements[i]).hasClass(sortableConfig.placeHolderClass)) {
                hasPlaceHolder = true;
                break;
              }
            }
            return hasPlaceHolder;
          };


          /**
           * Determines whether the item is dragged upwards.
           *
           * @param eventObj - the event object.
           * @param targetElement - the target element.
           * @returns {boolean} - true if moving upwards.
           */
          isDragBefore = function (eventObj, targetElement) {
            var dragBefore, targetOffset;

            dragBefore = false;
            // check it's new position
            targetOffset = $helper.offset(targetElement);
            if ($helper.offset(placeHolder).top > targetOffset.top) { // the move direction is up?
              dragBefore = $helper.offset(dragElement).top < targetOffset.top + $helper.height(targetElement) / 2;
            } else {
              dragBefore = eventObj.pageY < targetOffset.top;
            }
            return dragBefore;
          };

          /**
           * Rollback the drag data changes.
           */

          function rollbackDragChanges() {
            placeElement.replaceWith(scope.itemScope.element);
            placeHolder.remove();
            dragElement.remove();
            dragElement = null;
            dragHandled = false;
            containment.css('cursor', '');
          }

          /**
           * triggered while drag ends.
           *
           * @param event - the event object.
           */
          dragEnd = function (event) {
            // Ignore event if not handled
            if (!dragHandled) {
              return;
            }
            event.preventDefault();
            if (dragElement) {
              //rollback all the changes.
              rollbackDragChanges();
              // update model data
              dragItemInfo.apply();
              scope.sortableScope.$apply(function () {
                if (dragItemInfo.isSameParent()) {
                  if (dragItemInfo.isOrderChanged()) {
                    scope.callbacks.orderChanged(dragItemInfo.eventArgs());
                  }
                } else {
                  scope.callbacks.itemMoved(dragItemInfo.eventArgs());
                }
              });
              scope.sortableScope.$apply(function () {
                scope.callbacks.dragEnd(dragItemInfo.eventArgs());
              });
              dragItemInfo = null;
            }
            unBindEvents();
          };

          /**
           * triggered while drag is cancelled.
           *
           * @param event - the event object.
           */
          dragCancel = function (event) {
            // Ignore event if not handled
            if (!dragHandled) {
              return;
            }
            event.preventDefault();

            if (dragElement) {
              //rollback all the changes.
              rollbackDragChanges();
              scope.sortableScope.$apply(function () {
                scope.callbacks.dragCancel(dragItemInfo.eventArgs());
              });
              dragItemInfo = null;
            }
            unBindEvents();
          };

          /**
           * Binds the drag start events.
           */
          bindDrag = function () {
            element.bind('touchstart', dragListen);
            element.bind('mousedown', dragListen);
          };

          /**
           * Unbinds the drag start events.
           */
          unbindDrag = function () {
            element.unbind('touchstart', dragListen);
            element.unbind('mousedown', dragListen);
          };

          //bind drag start events.
          bindDrag();

          //Cancel drag on escape press.
          angular.element($document[0].body).bind('keydown', function (event) {
            if (event.keyCode === 27) {
              dragCancel(event);
            }
          });

          /**
           * Binds the events based on the actions.
           */
          bindEvents = function () {
            angular.element($document).bind('touchmove', dragMove);
            angular.element($document).bind('touchend', dragEnd);
            angular.element($document).bind('touchcancel', dragCancel);
            angular.element($document).bind('mousemove', dragMove);
            angular.element($document).bind('mouseup', dragEnd);
          };

          /**
           * Un binds the events for drag support.
           */
          unBindEvents = function () {
            angular.element($document).unbind('touchend', dragEnd);
            angular.element($document).unbind('touchcancel', dragCancel);
            angular.element($document).unbind('touchmove', dragMove);
            angular.element($document).unbind('mouseup', dragEnd);
            angular.element($document).unbind('mousemove', dragMove);
          };
        }
      };
    }]);
}());

/*jshint indent: 2 */
/*global angular: false */

(function () {

  'use strict';
  var mainModule = angular.module('ui.sortable');

  /**
   * Controller for sortable item.
   *
   * @param $scope - drag item scope
   */
  mainModule.controller('ui.sortable.sortableItemController', ['$scope', function ($scope) {

    this.scope = $scope;

    $scope.sortableScope = null;
    $scope.modelValue = null; // sortable item.
    $scope.type = 'item';

    /**
     * returns the index of the drag item from the sortable list.
     *
     * @returns {*} - index value.
     */
    $scope.index = function () {
      return $scope.sortableScope.modelValue.indexOf($scope.modelValue);
    };

    /**
     * Returns the item model data.
     *
     * @returns {*} - item model value.
     */
    $scope.itemData = function () {
      return $scope.sortableScope.modelValue[$scope.$index];
    };

  }]);

  /**
   * sortableItem directive.
   */
  mainModule.directive('asSortableItem', ['sortableConfig',
    function (sortableConfig) {
      return {
        require: '^asSortable',
        restrict: 'A',
        controller: 'ui.sortable.sortableItemController',
        link: function (scope, element, attrs, sortableController) {

          if (sortableConfig.itemClass) {
            element.addClass(sortableConfig.itemClass);
          }
          scope.sortableScope = sortableController.scope;
          scope.modelValue = sortableController.scope.modelValue[scope.$index];
          scope.element = element;
        }
      };
    }]);

}());
/*
 * Snap.js
 *
 * Copyright 2013, Jacob Kelley - http://jakiestfu.com/
 * Released under the MIT Licence
 * http://opensource.org/licenses/MIT
 *
 * Github:  http://github.com/jakiestfu/Snap.js/
 * Version: 1.9.3
 */
/*jslint browser: true*/
/*global define, module, ender*/
(function(win, doc) {
    'use strict';
    var Snap = Snap || function(userOpts) {
        var settings = {
            element: null,
            dragger: null,
            disable: 'none',
            addBodyClasses: true,
            hyperextensible: true,
            resistance: 0.5,
            flickThreshold: 50,
            transitionSpeed: 0.3,
            easing: 'ease',
            maxPosition: 266,
            minPosition: -266,
            tapToClose: true,
            touchToDrag: true,
            slideIntent: 40, // degrees
            minDragDistance: 5
        },
        cache = {
            simpleStates: {
                opening: null,
                towards: null,
                hyperExtending: null,
                halfway: null,
                flick: null,
                translation: {
                    absolute: 0,
                    relative: 0,
                    sinceDirectionChange: 0,
                    percentage: 0
                }
            }
        },
        eventList = {},
        utils = {
            hasTouch: ('ontouchstart' in doc.documentElement || win.navigator.msPointerEnabled),
            eventType: function(action) {
                var eventTypes = {
                        down: (utils.hasTouch ? 'touchstart' : 'mousedown'),
                        move: (utils.hasTouch ? 'touchmove' : 'mousemove'),
                        up: (utils.hasTouch ? 'touchend' : 'mouseup'),
                        out: (utils.hasTouch ? 'touchcancel' : 'mouseout')
                    };
                return eventTypes[action];
            },
            page: function(t, e){
                return (utils.hasTouch && e.touches.length && e.touches[0]) ? e.touches[0]['page'+t] : e['page'+t];
            },
            klass: {
                has: function(el, name){
                    return (el.className).indexOf(name) !== -1;
                },
                add: function(el, name){
                    if(!utils.klass.has(el, name) && settings.addBodyClasses){
                        el.className += " "+name;
                    }
                },
                remove: function(el, name){
                    if(settings.addBodyClasses){
                        el.className = (el.className).replace(name, "").replace(/^\s+|\s+$/g, '');
                    }
                }
            },
            dispatchEvent: function(type) {
                if (typeof eventList[type] === 'function') {
                    return eventList[type].call();
                }
            },
            vendor: function(){
                var tmp = doc.createElement("div"),
                    prefixes = 'webkit Moz O ms'.split(' '),
                    i;
                for (i in prefixes) {
                    if (typeof tmp.style[prefixes[i] + 'Transition'] !== 'undefined') {
                        return prefixes[i];
                    }
                }
            },
            transitionCallback: function(){
                return (cache.vendor==='Moz' || cache.vendor==='ms') ? 'transitionend' : cache.vendor+'TransitionEnd';
            },
            canTransform: function(){
                return typeof settings.element.style[cache.vendor+'Transform'] !== 'undefined';
            },
            deepExtend: function(destination, source) {
                var property;
                for (property in source) {
                    if (source[property] && source[property].constructor && source[property].constructor === Object) {
                        destination[property] = destination[property] || {};
                        utils.deepExtend(destination[property], source[property]);
                    } else {
                        destination[property] = source[property];
                    }
                }
                return destination;
            },
            angleOfDrag: function(x, y) {
                var degrees, theta;
                // Calc Theta
                theta = Math.atan2(-(cache.startDragY - y), (cache.startDragX - x));
                if (theta < 0) {
                    theta += 2 * Math.PI;
                }
                // Calc Degrees
                degrees = Math.floor(theta * (180 / Math.PI) - 180);
                if (degrees < 0 && degrees > -180) {
                    degrees = 360 - Math.abs(degrees);
                }
                return Math.abs(degrees);
            },
            events: {
                addEvent: function addEvent(element, eventName, func) {
                    if (element.addEventListener) {
                        return element.addEventListener(eventName, func, false);
                    } else if (element.attachEvent) {
                        return element.attachEvent("on" + eventName, func);
                    }
                },
                removeEvent: function addEvent(element, eventName, func) {
                    if (element.addEventListener) {
                        return element.removeEventListener(eventName, func, false);
                    } else if (element.attachEvent) {
                        return element.detachEvent("on" + eventName, func);
                    }
                },
                prevent: function(e) {
                    if (e.preventDefault) {
                        e.preventDefault();
                    } else {
                        e.returnValue = false;
                    }
                }
            },
            parentUntil: function(el, attr) {
                var isStr = typeof attr === 'string';
                while (el.parentNode) {
                    if (isStr && el.getAttribute && el.getAttribute(attr)){
                        return el;
                    } else if(!isStr && el === attr){
                        return el;
                    }
                    el = el.parentNode;
                }
                return null;
            }
        },
        action = {
            translate: {
                get: {
                    matrix: function(index) {

                        if( !utils.canTransform() ){
                            return parseInt(settings.element.style.left, 10);
                        } else {
                            var matrix = win.getComputedStyle(settings.element)[cache.vendor+'Transform'].match(/\((.*)\)/),
                                ieOffset = 8;
                            if (matrix) {
                                matrix = matrix[1].split(',');
                                if(matrix.length===16){
                                    index+=ieOffset;
                                }
                                return parseInt(matrix[index], 10);
                            }
                            return 0;
                        }
                    }
                },
                easeCallback: function(){
                    settings.element.style[cache.vendor+'Transition'] = '';
                    cache.translation = action.translate.get.matrix(4);
                    cache.easing = false;
                    clearInterval(cache.animatingInterval);

                    if(cache.easingTo===0){
                        utils.klass.remove(doc.body, 'snapjs-right');
                        utils.klass.remove(doc.body, 'snapjs-left');
                    }

                    utils.dispatchEvent('animated');
                    utils.events.removeEvent(settings.element, utils.transitionCallback(), action.translate.easeCallback);
                },
                easeTo: function(n) {

                    if( !utils.canTransform() ){
                        cache.translation = n;
                        action.translate.x(n);
                    } else {
                        cache.easing = true;
                        cache.easingTo = n;

                        settings.element.style[cache.vendor+'Transition'] = 'all ' + settings.transitionSpeed + 's ' + settings.easing;

                        cache.animatingInterval = setInterval(function() {
                            utils.dispatchEvent('animating');
                        }, 1);
                        
                        utils.events.addEvent(settings.element, utils.transitionCallback(), action.translate.easeCallback);
                        action.translate.x(n);
                    }
                    if(n===0){
                           settings.element.style[cache.vendor+'Transform'] = '';
                       }
                },
                x: function(n) {
                    if( (settings.disable==='left' && n>0) ||
                        (settings.disable==='right' && n<0)
                    ){ return; }
                    
                    if( !settings.hyperextensible ){
                        if( n===settings.maxPosition || n>settings.maxPosition ){
                            n=settings.maxPosition;
                        } else if( n===settings.minPosition || n<settings.minPosition ){
                            n=settings.minPosition;
                        }
                    }
                    
                    n = parseInt(n, 10);
                    if(isNaN(n)){
                        n = 0;
                    }

                    if( utils.canTransform() ){
                        var theTranslate = 'translate3d(' + n + 'px, 0,0)';
                        settings.element.style[cache.vendor+'Transform'] = theTranslate;
                    } else {
                        settings.element.style.width = (win.innerWidth || doc.documentElement.clientWidth)+'px';

                        settings.element.style.left = n+'px';
                        settings.element.style.right = '';
                    }
                }
            },
            drag: {
                listen: function() {
                    cache.translation = 0;
                    cache.easing = false;
                    utils.events.addEvent(settings.element, utils.eventType('down'), action.drag.startDrag);
                    utils.events.addEvent(settings.element, utils.eventType('move'), action.drag.dragging);
                    utils.events.addEvent(settings.element, utils.eventType('up'), action.drag.endDrag);
                },
                stopListening: function() {
                    utils.events.removeEvent(settings.element, utils.eventType('down'), action.drag.startDrag);
                    utils.events.removeEvent(settings.element, utils.eventType('move'), action.drag.dragging);
                    utils.events.removeEvent(settings.element, utils.eventType('up'), action.drag.endDrag);
                },
                startDrag: function(e) {
                    // No drag on ignored elements
                    var target = e.target ? e.target : e.srcElement,
                        ignoreParent = utils.parentUntil(target, 'data-snap-ignore');
                    
                    if (ignoreParent) {
                        utils.dispatchEvent('ignore');
                        return;
                    }
                    
                    
                    if(settings.dragger){
                        var dragParent = utils.parentUntil(target, settings.dragger);
                        
                        // Only use dragger if we're in a closed state
                        if( !dragParent && 
                            (cache.translation !== settings.minPosition && 
                            cache.translation !== settings.maxPosition
                        )){
                            return;
                        }
                    }
                    
                    utils.dispatchEvent('start');
                    settings.element.style[cache.vendor+'Transition'] = '';
                    cache.isDragging = true;
                    cache.hasIntent = null;
                    cache.intentChecked = false;
                    cache.startDragX = utils.page('X', e);
                    cache.startDragY = utils.page('Y', e);
                    cache.dragWatchers = {
                        current: 0,
                        last: 0,
                        hold: 0,
                        state: ''
                    };
                    cache.simpleStates = {
                        opening: null,
                        towards: null,
                        hyperExtending: null,
                        halfway: null,
                        flick: null,
                        translation: {
                            absolute: 0,
                            relative: 0,
                            sinceDirectionChange: 0,
                            percentage: 0
                        }
                    };
                },
                dragging: function(e) {
                    if (cache.isDragging && settings.touchToDrag) {

                        var thePageX = utils.page('X', e),
                            thePageY = utils.page('Y', e),
                            translated = cache.translation,
                            absoluteTranslation = action.translate.get.matrix(4),
                            whileDragX = thePageX - cache.startDragX,
                            openingLeft = absoluteTranslation > 0,
                            translateTo = whileDragX,
                            diff;

                        // Shown no intent already
                        if((cache.intentChecked && !cache.hasIntent)){
                            return;
                        }

                        if(settings.addBodyClasses){
                            if((absoluteTranslation)>0){
                                utils.klass.add(doc.body, 'snapjs-left');
                                utils.klass.remove(doc.body, 'snapjs-right');
                            } else if((absoluteTranslation)<0){
                                utils.klass.add(doc.body, 'snapjs-right');
                                utils.klass.remove(doc.body, 'snapjs-left');
                            }
                        }

                        if (cache.hasIntent === false || cache.hasIntent === null) {
                            var deg = utils.angleOfDrag(thePageX, thePageY),
                                inRightRange = (deg >= 0 && deg <= settings.slideIntent) || (deg <= 360 && deg > (360 - settings.slideIntent)),
                                inLeftRange = (deg >= 180 && deg <= (180 + settings.slideIntent)) || (deg <= 180 && deg >= (180 - settings.slideIntent));
                            if (!inLeftRange && !inRightRange) {
                                cache.hasIntent = false;
                            } else {
                                cache.hasIntent = true;
                            }
                            cache.intentChecked = true;
                        }

                        if (
                            (settings.minDragDistance>=Math.abs(thePageX-cache.startDragX)) || // Has user met minimum drag distance?
                            (cache.hasIntent === false)
                        ) {
                            return;
                        }

                        utils.events.prevent(e);
                        utils.dispatchEvent('drag');

                        cache.dragWatchers.current = thePageX;
                        // Determine which direction we are going
                        if (cache.dragWatchers.last > thePageX) {
                            if (cache.dragWatchers.state !== 'left') {
                                cache.dragWatchers.state = 'left';
                                cache.dragWatchers.hold = thePageX;
                            }
                            cache.dragWatchers.last = thePageX;
                        } else if (cache.dragWatchers.last < thePageX) {
                            if (cache.dragWatchers.state !== 'right') {
                                cache.dragWatchers.state = 'right';
                                cache.dragWatchers.hold = thePageX;
                            }
                            cache.dragWatchers.last = thePageX;
                        }
                        if (openingLeft) {
                            // Pulling too far to the right
                            if (settings.maxPosition < absoluteTranslation) {
                                diff = (absoluteTranslation - settings.maxPosition) * settings.resistance;
                                translateTo = whileDragX - diff;
                            }
                            cache.simpleStates = {
                                opening: 'left',
                                towards: cache.dragWatchers.state,
                                hyperExtending: settings.maxPosition < absoluteTranslation,
                                halfway: absoluteTranslation > (settings.maxPosition / 2),
                                flick: Math.abs(cache.dragWatchers.current - cache.dragWatchers.hold) > settings.flickThreshold,
                                translation: {
                                    absolute: absoluteTranslation,
                                    relative: whileDragX,
                                    sinceDirectionChange: (cache.dragWatchers.current - cache.dragWatchers.hold),
                                    percentage: (absoluteTranslation/settings.maxPosition)*100
                                }
                            };
                        } else {
                            // Pulling too far to the left
                            if (settings.minPosition > absoluteTranslation) {
                                diff = (absoluteTranslation - settings.minPosition) * settings.resistance;
                                translateTo = whileDragX - diff;
                            }
                            cache.simpleStates = {
                                opening: 'right',
                                towards: cache.dragWatchers.state,
                                hyperExtending: settings.minPosition > absoluteTranslation,
                                halfway: absoluteTranslation < (settings.minPosition / 2),
                                flick: Math.abs(cache.dragWatchers.current - cache.dragWatchers.hold) > settings.flickThreshold,
                                translation: {
                                    absolute: absoluteTranslation,
                                    relative: whileDragX,
                                    sinceDirectionChange: (cache.dragWatchers.current - cache.dragWatchers.hold),
                                    percentage: (absoluteTranslation/settings.minPosition)*100
                                }
                            };
                        }
                        action.translate.x(translateTo + translated);
                    }
                },
                endDrag: function(e) {
                    if (cache.isDragging) {
                        utils.dispatchEvent('end');
                        var translated = action.translate.get.matrix(4);

                        // Tap Close
                        if (cache.dragWatchers.current === 0 && translated !== 0 && settings.tapToClose) {
                            utils.dispatchEvent('close');
                            utils.events.prevent(e);
                            action.translate.easeTo(0);
                            cache.isDragging = false;
                            cache.startDragX = 0;
                            return;
                        }

                        // Revealing Left
                        if (cache.simpleStates.opening === 'left') {
                            // Halfway, Flicking, or Too Far Out
                            if ((cache.simpleStates.halfway || cache.simpleStates.hyperExtending || cache.simpleStates.flick)) {
                                if (cache.simpleStates.flick && cache.simpleStates.towards === 'left') { // Flicking Closed
                                    action.translate.easeTo(0);
                                } else if (
                                    (cache.simpleStates.flick && cache.simpleStates.towards === 'right') || // Flicking Open OR
                                    (cache.simpleStates.halfway || cache.simpleStates.hyperExtending) // At least halfway open OR hyperextending
                                ) {
                                    action.translate.easeTo(settings.maxPosition); // Open Left
                                }
                            } else {
                                action.translate.easeTo(0); // Close Left
                            }
                            // Revealing Right
                        } else if (cache.simpleStates.opening === 'right') {
                            // Halfway, Flicking, or Too Far Out
                            if ((cache.simpleStates.halfway || cache.simpleStates.hyperExtending || cache.simpleStates.flick)) {
                                if (cache.simpleStates.flick && cache.simpleStates.towards === 'right') { // Flicking Closed
                                    action.translate.easeTo(0);
                                } else if (
                                    (cache.simpleStates.flick && cache.simpleStates.towards === 'left') || // Flicking Open OR
                                    (cache.simpleStates.halfway || cache.simpleStates.hyperExtending) // At least halfway open OR hyperextending
                                ) {
                                    action.translate.easeTo(settings.minPosition); // Open Right
                                }
                            } else {
                                action.translate.easeTo(0); // Close Right
                            }
                        }
                        cache.isDragging = false;
                        cache.startDragX = utils.page('X', e);
                    }
                }
            }
        },
        init = function(opts) {
            if (opts.element) {
                utils.deepExtend(settings, opts);
                cache.vendor = utils.vendor();
                action.drag.listen();
            }
        };
        /*
         * Public
         */
        this.open = function(side) {
            utils.dispatchEvent('open');
            utils.klass.remove(doc.body, 'snapjs-expand-left');
            utils.klass.remove(doc.body, 'snapjs-expand-right');

            if (side === 'left') {
                cache.simpleStates.opening = 'left';
                cache.simpleStates.towards = 'right';
                utils.klass.add(doc.body, 'snapjs-left');
                utils.klass.remove(doc.body, 'snapjs-right');
                action.translate.easeTo(settings.maxPosition);
            } else if (side === 'right') {
                cache.simpleStates.opening = 'right';
                cache.simpleStates.towards = 'left';
                utils.klass.remove(doc.body, 'snapjs-left');
                utils.klass.add(doc.body, 'snapjs-right');
                action.translate.easeTo(settings.minPosition);
            }
        };
        this.close = function() {
            utils.dispatchEvent('close');
            action.translate.easeTo(0);
        };
        this.expand = function(side){
            var to = win.innerWidth || doc.documentElement.clientWidth;

            if(side==='left'){
                utils.dispatchEvent('expandLeft');
                utils.klass.add(doc.body, 'snapjs-expand-left');
                utils.klass.remove(doc.body, 'snapjs-expand-right');
            } else {
                utils.dispatchEvent('expandRight');
                utils.klass.add(doc.body, 'snapjs-expand-right');
                utils.klass.remove(doc.body, 'snapjs-expand-left');
                to *= -1;
            }
            action.translate.easeTo(to);
        };

        this.on = function(evt, fn) {
            eventList[evt] = fn;
            return this;
        };
        this.off = function(evt) {
            if (eventList[evt]) {
                eventList[evt] = false;
            }
        };

        this.enable = function() {
            utils.dispatchEvent('enable');
            action.drag.listen();
        };
        this.disable = function() {
            utils.dispatchEvent('disable');
            action.drag.stopListening();
        };

        this.settings = function(opts){
            utils.deepExtend(settings, opts);
        };

        this.state = function() {
            var state,
                fromLeft = action.translate.get.matrix(4);
            if (fromLeft === settings.maxPosition) {
                state = 'left';
            } else if (fromLeft === settings.minPosition) {
                state = 'right';
            } else {
                state = 'closed';
            }
            return {
                state: state,
                info: cache.simpleStates
            };
        };
        init(userOpts);
    };
    if ((typeof module !== 'undefined') && module.exports) {
        module.exports = Snap;
    }
    if (typeof ender === 'undefined') {
        this.Snap = Snap;
    }
    if ((typeof define === "function") && define.amd) {
        define("snap", [], function() {
            return Snap;
        });
    }
}).call(this, window, document);
