2014-09-26 08:14:42 +00:00
// Underscore.js 1.6.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 . _ ;
// Establish the object that gets returned to break out of a loop iteration.
var breaker = { } ;
// 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
nativeForEach = ArrayProto . forEach ,
nativeMap = ArrayProto . map ,
nativeReduce = ArrayProto . reduce ,
nativeReduceRight = ArrayProto . reduceRight ,
nativeFilter = ArrayProto . filter ,
nativeEvery = ArrayProto . every ,
nativeSome = ArrayProto . some ,
nativeIndexOf = ArrayProto . indexOf ,
nativeLastIndexOf = ArrayProto . lastIndexOf ,
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 via a string identifier,
// for Closure Compiler "advanced" mode.
if ( typeof exports !== 'undefined' ) {
if ( typeof module !== 'undefined' && module . exports ) {
exports = module . exports = _ ;
}
exports . _ = _ ;
} else {
root . _ = _ ;
}
// Current version.
_ . VERSION = '1.6.0' ;
// Collection Functions
// --------------------
// The cornerstone, an `each` implementation, aka `forEach`.
// Handles objects with the built-in `forEach`, arrays, and raw objects.
// Delegates to **ECMAScript 5**'s native `forEach` if available.
var each = _ . each = _ . forEach = function ( obj , iterator , context ) {
if ( obj == null ) return obj ;
if ( nativeForEach && obj . forEach === nativeForEach ) {
obj . forEach ( iterator , context ) ;
} else if ( obj . length === + obj . length ) {
for ( var i = 0 , length = obj . length ; i < length ; i ++ ) {
if ( iterator . call ( context , obj [ i ] , i , obj ) === breaker ) return ;
}
} else {
var keys = _ . keys ( obj ) ;
for ( var i = 0 , length = keys . length ; i < length ; i ++ ) {
if ( iterator . call ( context , obj [ keys [ i ] ] , keys [ i ] , obj ) === breaker ) return ;
}
}
return obj ;
} ;
// Return the results of applying the iterator to each element.
// Delegates to **ECMAScript 5**'s native `map` if available.
_ . map = _ . collect = function ( obj , iterator , context ) {
var results = [ ] ;
if ( obj == null ) return results ;
if ( nativeMap && obj . map === nativeMap ) return obj . map ( iterator , context ) ;
each ( obj , function ( value , index , list ) {
results . push ( iterator . call ( context , value , index , list ) ) ;
} ) ;
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`. Delegates to **ECMAScript 5**'s native `reduce` if available.
_ . reduce = _ . foldl = _ . inject = function ( obj , iterator , memo , context ) {
var initial = arguments . length > 2 ;
if ( obj == null ) obj = [ ] ;
if ( nativeReduce && obj . reduce === nativeReduce ) {
if ( context ) iterator = _ . bind ( iterator , context ) ;
return initial ? obj . reduce ( iterator , memo ) : obj . reduce ( iterator ) ;
}
each ( obj , function ( value , index , list ) {
if ( ! initial ) {
memo = value ;
initial = true ;
} else {
memo = iterator . call ( context , memo , value , index , list ) ;
}
} ) ;
if ( ! initial ) throw new TypeError ( reduceError ) ;
return memo ;
} ;
// The right-associative version of reduce, also known as `foldr`.
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
_ . reduceRight = _ . foldr = function ( obj , iterator , memo , context ) {
var initial = arguments . length > 2 ;
if ( obj == null ) obj = [ ] ;
if ( nativeReduceRight && obj . reduceRight === nativeReduceRight ) {
if ( context ) iterator = _ . bind ( iterator , context ) ;
return initial ? obj . reduceRight ( iterator , memo ) : obj . reduceRight ( iterator ) ;
}
var length = obj . length ;
if ( length !== + length ) {
var keys = _ . keys ( obj ) ;
length = keys . length ;
}
each ( obj , function ( value , index , list ) {
index = keys ? keys [ -- length ] : -- length ;
if ( ! initial ) {
memo = obj [ index ] ;
initial = true ;
} else {
memo = iterator . call ( context , memo , obj [ index ] , index , list ) ;
}
} ) ;
if ( ! initial ) throw new TypeError ( reduceError ) ;
return memo ;
} ;
// Return the first value which passes a truth test. Aliased as `detect`.
_ . find = _ . detect = function ( obj , predicate , context ) {
var result ;
any ( obj , function ( value , index , list ) {
if ( predicate . call ( context , value , index , list ) ) {
result = value ;
return true ;
}
} ) ;
return result ;
} ;
// Return all the elements that pass a truth test.
// Delegates to **ECMAScript 5**'s native `filter` if available.
// Aliased as `select`.
_ . filter = _ . select = function ( obj , predicate , context ) {
var results = [ ] ;
if ( obj == null ) return results ;
if ( nativeFilter && obj . filter === nativeFilter ) return obj . filter ( predicate , context ) ;
each ( obj , function ( value , index , list ) {
if ( predicate . call ( context , 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 , function ( value , index , list ) {
return ! predicate . call ( context , value , index , list ) ;
} , context ) ;
} ;
// Determine whether all of the elements match a truth test.
// Delegates to **ECMAScript 5**'s native `every` if available.
// Aliased as `all`.
_ . every = _ . all = function ( obj , predicate , context ) {
predicate || ( predicate = _ . identity ) ;
var result = true ;
if ( obj == null ) return result ;
if ( nativeEvery && obj . every === nativeEvery ) return obj . every ( predicate , context ) ;
each ( obj , function ( value , index , list ) {
if ( ! ( result = result && predicate . call ( context , value , index , list ) ) ) return breaker ;
} ) ;
return ! ! result ;
} ;
// Determine if at least one element in the object matches a truth test.
// Delegates to **ECMAScript 5**'s native `some` if available.
// Aliased as `any`.
var any = _ . some = _ . any = function ( obj , predicate , context ) {
predicate || ( predicate = _ . identity ) ;
var result = false ;
if ( obj == null ) return result ;
if ( nativeSome && obj . some === nativeSome ) return obj . some ( predicate , context ) ;
each ( obj , function ( value , index , list ) {
if ( result || ( result = predicate . call ( context , value , index , list ) ) ) return breaker ;
} ) ;
return ! ! result ;
} ;
// 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 ( nativeIndexOf && obj . indexOf === nativeIndexOf ) return obj . indexOf ( target ) != - 1 ;
return any ( obj , function ( value ) {
return value === target ;
} ) ;
} ;
// 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).
// Can't optimize arrays of integers longer than 65,535 elements.
// See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)
_ . max = function ( obj , iterator , context ) {
if ( ! iterator && _ . isArray ( obj ) && obj [ 0 ] === + obj [ 0 ] && obj . length < 65535 ) {
return Math . max . apply ( Math , obj ) ;
}
var result = - Infinity , lastComputed = - Infinity ;
each ( obj , function ( value , index , list ) {
var computed = iterator ? iterator . call ( context , value , index , list ) : value ;
if ( computed > lastComputed ) {
result = value ;
lastComputed = computed ;
}
} ) ;
return result ;
} ;
// Return the minimum element (or element-based computation).
_ . min = function ( obj , iterator , context ) {
if ( ! iterator && _ . isArray ( obj ) && obj [ 0 ] === + obj [ 0 ] && obj . length < 65535 ) {
return Math . min . apply ( Math , obj ) ;
}
var result = Infinity , lastComputed = Infinity ;
each ( obj , function ( value , index , list ) {
var computed = iterator ? iterator . call ( context , value , index , list ) : value ;
if ( computed < lastComputed ) {
result = value ;
lastComputed = computed ;
}
} ) ;
return result ;
} ;
// Shuffle an array, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher– Yates_shuffle).
_ . shuffle = function ( obj ) {
var rand ;
var index = 0 ;
var shuffled = [ ] ;
each ( obj , function ( value ) {
rand = _ . random ( index ++ ) ;
shuffled [ index - 1 ] = shuffled [ rand ] ;
shuffled [ rand ] = value ;
} ) ;
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 ) ) ;
} ;
// An internal function to generate lookup iterators.
var lookupIterator = function ( value ) {
if ( value == null ) return _ . identity ;
if ( _ . isFunction ( value ) ) return value ;
return _ . property ( value ) ;
} ;
// Sort the object's values by a criterion produced by an iterator.
_ . sortBy = function ( obj , iterator , context ) {
iterator = lookupIterator ( iterator ) ;
return _ . pluck ( _ . map ( obj , function ( value , index , list ) {
return {
value : value ,
index : index ,
criteria : iterator . call ( context , 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 , iterator , context ) {
var result = { } ;
iterator = lookupIterator ( iterator ) ;
each ( obj , function ( value , index ) {
var key = iterator . call ( context , value , index , obj ) ;
behavior ( result , key , value ) ;
} ) ;
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 , key , value ) {
_ . has ( result , key ) ? result [ key ] . push ( value ) : 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 , key , value ) {
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 , key ) {
_ . has ( result , key ) ? result [ key ] ++ : 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 , iterator , context ) {
iterator = lookupIterator ( iterator ) ;
var value = iterator . call ( context , obj ) ;
var low = 0 , high = array . length ;
while ( low < high ) {
var mid = ( low + high ) >>> 1 ;
iterator . call ( context , array [ mid ] ) < value ? low = mid + 1 : 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 ;
} ;
// 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 , 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 , output ) {
if ( shallow && _ . every ( input , _ . isArray ) ) {
return concat . apply ( output , input ) ;
}
each ( input , function ( value ) {
if ( _ . isArray ( value ) || _ . isArguments ( value ) ) {
shallow ? push . apply ( output , value ) : flatten ( value , shallow , output ) ;
} else {
output . push ( value ) ;
}
} ) ;
return output ;
} ;
// Flatten out an array, either recursively (by default), or just one level.
_ . flatten = function ( array , shallow ) {
return flatten ( array , shallow , [ ] ) ;
} ;
// Return a version of the array that does not contain the specified value(s).
_ . without = function ( array ) {
return _ . difference ( array , slice . call ( arguments , 1 ) ) ;
} ;
// Split an array into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_ . partition = function ( array , predicate ) {
var pass = [ ] , fail = [ ] ;
each ( array , function ( elem ) {
( predicate ( elem ) ? pass : fail ) . push ( elem ) ;
} ) ;
return [ pass , fail ] ;
} ;
// 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 , iterator , context ) {
if ( _ . isFunction ( isSorted ) ) {
context = iterator ;
iterator = isSorted ;
isSorted = false ;
}
var initial = iterator ? _ . map ( array , iterator , context ) : array ;
var results = [ ] ;
var seen = [ ] ;
each ( initial , function ( value , index ) {
if ( isSorted ? ( ! index || seen [ seen . length - 1 ] !== value ) : ! _ . contains ( seen , value ) ) {
seen . push ( value ) ;
results . push ( array [ index ] ) ;
}
} ) ;
return results ;
} ;
// Produce an array that contains the union: each distinct element from all of
// the passed-in arrays.
_ . union = function ( ) {
return _ . uniq ( _ . flatten ( arguments , true ) ) ;
} ;
// Produce an array that contains every item shared between all the
// passed-in arrays.
_ . intersection = function ( array ) {
var rest = slice . call ( arguments , 1 ) ;
return _ . filter ( _ . uniq ( array ) , function ( item ) {
return _ . every ( rest , function ( other ) {
return _ . contains ( other , item ) ;
} ) ;
} ) ;
} ;
// 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 = concat . apply ( ArrayProto , slice . call ( arguments , 1 ) ) ;
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 ( ) {
var length = _ . max ( _ . pluck ( arguments , 'length' ) . concat ( 0 ) ) ;
var results = new 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 ;
} ;
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
// we need this function. Return the position of the first occurrence of an
// item in an array, or -1 if the item is not included in the array.
// Delegates to **ECMAScript 5**'s native `indexOf` if available.
// 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 ;
}
}
if ( nativeIndexOf && array . indexOf === nativeIndexOf ) return array . indexOf ( item , isSorted ) ;
for ( ; i < length ; i ++ ) if ( array [ i ] === item ) return i ;
return - 1 ;
} ;
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
_ . lastIndexOf = function ( array , item , from ) {
if ( array == null ) return - 1 ;
var hasIndex = from != null ;
if ( nativeLastIndexOf && array . lastIndexOf === nativeLastIndexOf ) {
return hasIndex ? array . lastIndexOf ( item , from ) : array . lastIndexOf ( item ) ;
}
var i = ( hasIndex ? from : array . length ) ;
while ( i -- ) if ( array [ i ] === item ) return i ;
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 = arguments [ 2 ] || 1 ;
var length = Math . max ( Math . ceil ( ( stop - start ) / step ) , 0 ) ;
var idx = 0 ;
var range = new Array ( length ) ;
while ( idx < length ) {
range [ idx ++ ] = start ;
start += step ;
}
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 ;
args = slice . call ( arguments , 2 ) ;
return 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 ( Object ( result ) === result ) return result ;
return self ;
} ;
} ;
// 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 funcs = slice . call ( arguments , 1 ) ;
if ( funcs . length === 0 ) throw new Error ( 'bindAll must be passed function names' ) ;
each ( funcs , function ( f ) { obj [ f ] = _ . bind ( obj [ f ] , obj ) ; } ) ;
return obj ;
} ;
// Memoize an expensive function by storing its results.
_ . memoize = function ( func , hasher ) {
var memo = { } ;
hasher || ( hasher = _ . identity ) ;
return function ( ) {
var key = hasher . apply ( this , arguments ) ;
return _ . has ( memo , key ) ? memo [ key ] : ( memo [ key ] = func . apply ( this , arguments ) ) ;
} ;
} ;
// 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 ;
options || ( options = { } ) ;
var later = function ( ) {
previous = options . leading === false ? 0 : _ . now ( ) ;
timeout = null ;
result = func . apply ( context , args ) ;
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 ) {
clearTimeout ( timeout ) ;
timeout = null ;
previous = now ;
result = func . apply ( context , args ) ;
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 ) {
timeout = setTimeout ( later , wait - last ) ;
} else {
timeout = null ;
if ( ! immediate ) {
result = func . apply ( context , args ) ;
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 a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_ . once = function ( func ) {
var ran = false , memo ;
return function ( ) {
if ( ran ) return memo ;
ran = true ;
memo = func . apply ( this , arguments ) ;
func = null ;
return memo ;
} ;
} ;
// 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 function that is the composition of a list of functions, each
// consuming the return value of the function that follows.
_ . compose = function ( ) {
var funcs = arguments ;
return function ( ) {
var args = arguments ;
for ( var i = funcs . length - 1 ; i >= 0 ; i -- ) {
args = [ funcs [ i ] . apply ( this , args ) ] ;
}
return args [ 0 ] ;
} ;
} ;
// 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 ) ;
}
} ;
} ;
// 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 = new 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 = new 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 ) {
each ( slice . call ( arguments , 1 ) , function ( source ) {
if ( source ) {
for ( var prop in source ) {
obj [ prop ] = source [ prop ] ;
}
}
} ) ;
return obj ;
} ;
// Return a copy of the object only containing the whitelisted properties.
_ . pick = function ( obj ) {
var copy = { } ;
var keys = concat . apply ( ArrayProto , slice . call ( arguments , 1 ) ) ;
each ( keys , function ( key ) {
if ( key in obj ) copy [ key ] = obj [ key ] ;
} ) ;
return copy ;
} ;
// Return a copy of the object without the blacklisted properties.
_ . omit = function ( obj ) {
var copy = { } ;
var keys = concat . apply ( ArrayProto , slice . call ( arguments , 1 ) ) ;
for ( var key in obj ) {
if ( ! _ . contains ( keys , key ) ) copy [ key ] = obj [ key ] ;
}
return copy ;
} ;
// Fill in a given object with default properties.
_ . defaults = function ( obj ) {
each ( slice . call ( arguments , 1 ) , function ( source ) {
if ( source ) {
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, dates, and booleans are compared by value.
case '[object String]' :
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`.
return a == String ( b ) ;
case '[object Number]' :
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
// other numeric values.
return a != + a ? b != + b : ( 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 ;
// RegExps are compared by their source patterns and flags.
case '[object RegExp]' :
return a . source == b . source &&
a . global == b . global &&
a . multiline == b . multiline &&
a . ignoreCase == b . ignoreCase ;
}
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 && ! ( _ . isFunction ( aCtor ) && ( aCtor instanceof aCtor ) &&
_ . isFunction ( bCtor ) && ( bCtor instanceof bCtor ) )
&& ( 'constructor' in a && 'constructor' in b ) ) {
return false ;
}
// Add the first object to the stack of traversed objects.
aStack . push ( a ) ;
bStack . push ( b ) ;
var size = 0 , result = true ;
// 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.
for ( var key in a ) {
if ( _ . has ( a , key ) ) {
// Count the expected number of properties.
size ++ ;
// Deep compare each member.
if ( ! ( result = _ . has ( b , key ) && eq ( a [ key ] , b [ key ] , aStack , bStack ) ) ) break ;
}
}
// Ensure that both objects contain the same number of properties.
if ( result ) {
for ( key in b ) {
if ( _ . has ( b , key ) && ! ( size -- ) ) break ;
}
result = ! size ;
}
}
// 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 ) ) 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 ) {
return obj === 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 ! ! ( obj && _ . has ( obj , 'callee' ) ) ;
} ;
}
// Optimize `isFunction` if appropriate.
if ( typeof ( /./ ) !== 'function' ) {
_ . isFunction = function ( obj ) {
return typeof obj === 'function' ;
} ;
}
// 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 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 iterators.
_ . identity = function ( value ) {
return value ;
} ;
_ . constant = function ( value ) {
return function ( ) {
return value ;
} ;
} ;
_ . 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 ) {
return function ( obj ) {
if ( obj === attrs ) return true ; //avoid comparing an object to itself.
for ( var key in attrs ) {
if ( attrs [ key ] !== obj [ key ] )
return false ;
}
return true ;
}
} ;
// Run a function **n** times.
_ . times = function ( n , iterator , context ) {
var accum = Array ( Math . max ( 0 , n ) ) ;
for ( var i = 0 ; i < n ; i ++ ) accum [ i ] = iterator . call ( context , 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 entityMap = {
escape : {
'&' : '&' ,
'<' : '<' ,
'>' : '>' ,
'"' : '"' ,
"'" : '''
}
} ;
entityMap . unescape = _ . invert ( entityMap . escape ) ;
// Regexes containing the keys and values listed immediately above.
var entityRegexes = {
escape : new RegExp ( '[' + _ . keys ( entityMap . escape ) . join ( '' ) + ']' , 'g' ) ,
unescape : new RegExp ( '(' + _ . keys ( entityMap . unescape ) . join ( '|' ) + ')' , 'g' )
} ;
// Functions for escaping and unescaping strings to/from HTML interpolation.
_ . each ( [ 'escape' , 'unescape' ] , function ( method ) {
_ [ method ] = function ( string ) {
if ( string == null ) return '' ;
return ( '' + string ) . replace ( entityRegexes [ method ] , function ( match ) {
return entityMap [ method ] [ match ] ;
} ) ;
} ;
} ) ;
// 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 ) ? value . call ( object ) : value ;
} ;
// 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 ) ) ;
} ;
} ) ;
} ;
// 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' ,
'\t' : 't' ,
'\u2028' : 'u2028' ,
'\u2029' : 'u2029'
} ;
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g ;
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
_ . template = function ( text , data , settings ) {
var render ;
settings = _ . defaults ( { } , settings , _ . templateSettings ) ;
// Combine delimiters into one regular expression via alternation.
var matcher = new 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 , function ( match ) { return '\\' + escapes [ match ] ; } ) ;
if ( escape ) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" ;
}
if ( interpolate ) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" ;
}
if ( evaluate ) {
source += "';\n" + evaluate + "\n__p+='" ;
}
index = offset + match . length ;
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 {
render = new Function ( settings . variable || 'obj' , '_' , source ) ;
} catch ( e ) {
e . source = source ;
throw e ;
}
if ( data ) return render ( data , _ ) ;
var template = function ( data ) {
return render . call ( this , data , _ ) ;
} ;
// Provide the compiled function source as a convenience for precompilation.
template . source = 'function(' + ( settings . variable || 'obj' ) + '){\n' + source + '}' ;
return template ;
} ;
// Add a "chain" function, which will delegate to the wrapper.
_ . chain = function ( obj ) {
return _ ( obj ) . chain ( ) ;
} ;
// 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 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 ) ) ;
} ;
} ) ;
_ . extend ( _ . prototype , {
// Start chaining a wrapped Underscore object.
chain : function ( ) {
this . _chain = true ;
return this ;
} ,
// Extracts the result from a wrapped and chained object.
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 ) ;
/ * !
handlebars v1 . 3.0
Copyright ( C ) 2011 by Yehuda Katz
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 .
@ license
* /
var Handlebars = function ( ) { var a = function ( ) { "use strict" ; function a ( a ) { this . string = a } var b ; return a . prototype . toString = function ( ) { return "" + this . string } , b = a } ( ) , b = function ( a ) { "use strict" ; function b ( a ) { return h [ a ] || "&" } function c ( a , b ) { for ( var c in b ) Object . prototype . hasOwnProperty . call ( b , c ) && ( a [ c ] = b [ c ] ) } function d ( a ) { return a instanceof g ? a . toString ( ) : a || 0 === a ? ( a = "" + a , j . test ( a ) ? a . replace ( i , b ) : a ) : "" } function e ( a ) { return a || 0 === a ? m ( a ) && 0 === a . length ? ! 0 : ! 1 : ! 0 } var f = { } , g = a , h = { "&" : "&" , "<" : "<" , ">" : ">" , '"' : """ , "'" : "'" , "`" : "`" } , i = /[&<>"'`]/g , j = /[&<>"'`]/ ; f . extend = c ; var k = Object . prototype . toString ; f . toString = k ; var l = function ( a ) { return "function" == typeof a } ; l ( /x/ ) && ( l = function ( a ) { return "function" == typeof a && "[object Function]" === k . call ( a ) } ) ; var l ; f . isFunction = l ; var m = Array . isArray || function ( a ) { return a && "object" == typeof a ? "[object Array]" === k . call ( a ) : ! 1 } ; return f . isArray = m , f . escapeExpression = d , f . isEmpty = e , f } ( a ) , c = function ( ) { "use strict" ; function a ( a , b ) { var d ; b && b . firstLine && ( d = b . firstLine , a += " - " + d + ":" + b . firstColumn ) ; for ( var e = Error . prototype . constructor . call ( this , a ) , f = 0 ; f < c . length ; f ++ ) this [ c [ f ] ] = e [ c [ f ] ] ; d && ( this . lineNumber = d , this . column = b . firstColumn ) } var b , c = [ "description" , "fileName" , "lineNumber" , "message" , "name" , "number" , "stack" ] ; return a . prototype = new Error , b = a } ( ) , d = function ( a , b ) { "use strict" ; function c ( a , b ) { this . helpers = a || { } , this . partials = b || { } , d ( this ) } function d ( a ) { a . registerHelper ( "helperMissing" , function ( a ) { if ( 2 === arguments . length ) return void 0 ; throw new h ( "Missing helper: '" + a + "'" ) } ) , a . registerHelper ( "blockHelperMissing" , function ( b , c ) { var d = c . inverse || function ( ) { } , e = c . fn ; return m ( b ) && ( b = b . call ( this ) ) , b === ! 0 ? e ( this ) : b === ! 1 || null == b ? d ( this ) : l ( b ) ? b . length > 0 ? a . helpers . each ( b , c ) : d ( this ) : e ( b ) } ) , a . registerHelper ( "each" , function ( a , b ) { var c , d = b . fn , e = b . inverse , f = 0 , g = "" ; if ( m ( a ) && ( a = a . call ( this ) ) , b . data && ( c = q ( b . data ) ) , a && "object" == typeof a ) if ( l ( a ) ) for ( var h = a . length ; h > f ; f ++ ) c && ( c . index = f , c . first = 0 === f , c . last = f === a . length - 1 ) , g += d ( a [ f ] , { data : c } ) ; else for ( var i in a ) a . hasOwnProperty ( i ) && ( c && ( c . key = i , c . index = f , c . first = 0 === f ) , g += d ( a [ i ] , { data : c } ) , f ++ ) ; return 0 === f && ( g = e ( this ) ) , g } ) , a . registerHelper ( "if" , function ( a , b ) { return m ( a ) && ( a = a . call ( this ) ) , ! b . hash . includeZero && ! a || g . isEmpty ( a ) ? b . inverse ( this ) : b . fn ( this ) } ) , a . registerHelper ( "unless" , function ( b , c ) { return a . helpers [ "if" ] . call ( this , b , { fn : c . inverse , inverse : c . fn , hash : c . hash } ) } ) , a . registerHelper ( "with" , function ( a , b ) { return m ( a ) && ( a = a . call ( this ) ) , g . isEmpty ( a ) ? void 0 : b . fn ( a ) } ) , a . registerHelper ( "log" , function ( b , c ) { var d = c . data && null != c . data . level ? parseInt ( c . data . level , 10 ) : 1 ; a . log ( d , b ) } ) } function e ( a , b ) { p . log ( a , b ) } var f = { } , g = a , h = b , i = "1.3.0" ; f . VERSION = i ; var j = 4 ; f . COMPILER _REVISION = j ; var k = { 1 : "<= 1.0.rc.2" , 2 : "== 1.0.0-rc.3" , 3 : "== 1.0.0-rc.4" , 4 : ">= 1.0.0" } ; f . REVISION _CHANGES = k ; var l = g . isArray , m = g . isFunction , n = g . toString , o = "[object Object]" ; f . HandlebarsEnvironment = c , c . prototype = { constructor : c , logger : p , log : e , registerHelper : function ( a , b , c ) { if ( n . call ( a ) === o ) { if ( c || b ) throw new h ( "Arg not supported with multiple helpers" ) ; g . extend ( this . helpers , a ) } else c && ( b . not = c ) , this . helpers [ a ] = b } , registerPartial : function ( a , b ) { n . call ( a ) === o ? g . extend ( this . partials , a ) : this . partials [ a ] = b } } ; var p = { methodMap : { 0 : "debug" , 1 : "info" , 2 : "warn" , 3 : "error" } , DEBUG : 0 , INFO : 1 , WARN : 2 , ERROR : 3 , level : 3 , log : function ( a , b ) { if ( p . level <= a ) { var c = p . methodMap [ a ] ; "undefined" != typeof console && console [ c ] && console [ c ] . call ( console , b ) } } } ; f . logger = p , f . log = e ; var q = function ( a ) { var b = { } ; return g . extend ( b , a ) , b } ; return f . createFrame = q , f } ( b , c ) , e = function ( a , b , c ) { "use strict" ; function d ( a ) { var b = a && a [ 0 ] || 1 , c = m ; if ( b !== c ) { if ( c > b ) { var d = n [ c ] , e = n [ b ] ; throw new l ( "Template was precompiled with an older version of Handlebars than the current runtime. Please update your precompiler to a newer version (" + d + ") or downgrade your runtime to an older version (" + e + ")." ) } throw new l ( "Template was precompiled with a newer version of Handlebars than the current runtime. Please update your runtime to a newer version (" + a [ 1 ] + ")." ) } } function e ( a , b ) { if ( ! b ) throw new l ( "No environment passed to template" ) ; var c = function ( a , c , d , e , f , g ) { var h = b . VM . invokePartial . a
var e , f = a . opcodes ; this . i = 0 ; for ( var g = f . length ; this . i < g ; this . i ++ ) e = f [ this . i ] , "DECLARE" === e . opcode ? this [ e . name ] = e . value : this [ e . opcode ] . apply ( this , e . args ) , e . opcode !== this . stripNext && ( this . stripNext = ! 1 ) ; if ( this . pushSource ( "" ) , this . stackSlot || this . inlineStack . length || this . compileStack . length ) throw new i ( "Compile completed with content left on stack" ) ; return this . createFunctionContext ( d ) } , preamble : function ( ) { var a = [ ] ; if ( this . isChild ) a . push ( "" ) ; else { var b = this . namespace , c = "helpers = this.merge(helpers, " + b + ".helpers);" ; this . environment . usePartial && ( c = c + " partials = this.merge(partials, " + b + ".partials);" ) , this . options . data && ( c += " data = data || {};" ) , a . push ( c ) } this . environment . isSimple ? a . push ( "" ) : a . push ( ", buffer = " + this . initializeBuffer ( ) ) , this . lastContext = 0 , this . source = a } , createFunctionContext : function ( a ) { var b = this . stackVars . concat ( this . registers . list ) ; if ( b . length > 0 && ( this . source [ 1 ] = this . source [ 1 ] + ", " + b . join ( ", " ) ) , ! this . isChild ) for ( var c in this . context . aliases ) this . context . aliases . hasOwnProperty ( c ) && ( this . source [ 1 ] = this . source [ 1 ] + ", " + c + "=" + this . context . aliases [ c ] ) ; this . source [ 1 ] && ( this . source [ 1 ] = "var " + this . source [ 1 ] . substring ( 2 ) + ";" ) , this . isChild || ( this . source [ 1 ] += "\n" + this . context . programs . join ( "\n" ) + "\n" ) , this . environment . isSimple || this . pushSource ( "return buffer;" ) ; for ( var d = this . isChild ? [ "depth0" , "data" ] : [ "Handlebars" , "depth0" , "helpers" , "partials" , "data" ] , e = 0 , f = this . environment . depths . list . length ; f > e ; e ++ ) d . push ( "depth" + this . environment . depths . list [ e ] ) ; var g = this . mergeSource ( ) ; if ( this . isChild || ( g = this . compilerInfo ( ) + g ) , a ) return d . push ( g ) , Function . apply ( this , d ) ; var i = "function " + ( this . name || "" ) + "(" + d . join ( "," ) + ") {\n " + g + "}" ; return h ( "debug" , i + "\n\n" ) , i } , mergeSource : function ( ) { for ( var a , b = "" , c = 0 , d = this . source . length ; d > c ; c ++ ) { var e = this . source [ c ] ; e . appendToBuffer ? a = a ? a + "\n + " + e . content : e . content : ( a && ( b += "buffer += " + a + ";\n " , a = void 0 ) , b += e + "\n " ) } return b } , blockValue : function ( ) { this . context . aliases . blockHelperMissing = "helpers.blockHelperMissing" ; var a = [ "depth0" ] ; this . setupParams ( 0 , a ) , this . replaceStack ( function ( b ) { return a . splice ( 1 , 0 , b ) , "blockHelperMissing.call(" + a . join ( ", " ) + ")" } ) } , ambiguousBlockValue : function ( ) { this . context . aliases . blockHelperMissing = "helpers.blockHelperMissing" ; var a = [ "depth0" ] ; this . setupParams ( 0 , a ) ; var b = this . topStack ( ) ; a . splice ( 1 , 0 , b ) , this . pushSource ( "if (!" + this . lastHelper + ") { " + b + " = blockHelperMissing.call(" + a . join ( ", " ) + "); }" ) } , appendContent : function ( a ) { this . pendingContent && ( a = this . pendingContent + a ) , this . stripNext && ( a = a . replace ( /^\s+/ , "" ) ) , this . pendingContent = a } , strip : function ( ) { this . pendingContent && ( this . pendingContent = this . pendingContent . replace ( /\s+$/ , "" ) ) , this . stripNext = "strip" } , append : function ( ) { this . flushInline ( ) ; var a = this . popStack ( ) ; this . pushSource ( "if(" + a + " || " + a + " === 0) { " + this . appendToBuffer ( a ) + " }" ) , this . environment . isSimple && this . pushSource ( "else { " + this . appendToBuffer ( "''" ) + " }" ) } , appendEscaped : function ( ) { this . context . aliases . escapeExpression = "this.escapeExpression" , this . pushSource ( this . appendToBuffer ( "escapeExpression(" + this . popStack ( ) + ")" ) ) } , getContext : function ( a ) { this . lastContext !== a && ( this . lastContext = a ) } , lookupOnContext : function ( a ) { this . push ( this . nameLookup ( "depth" + this . lastContext , a , "context" ) ) } , pushContext : function ( ) { this . pushStackLiteral ( "depth" + this . lastContext ) } , resolvePossibleLambda : function ( ) { this . context . aliases . functionType = '"function"' , this . replaceStack ( function ( a ) { return "typeof " + a + " === functionType ? " + a + ".apply(depth0) : " + a } ) } , lookup : function ( a ) { this . replaceStack ( function ( b ) { return b + " == null || " + b + " === false ? " + b + " : " + this . nameLookup ( b , a , "context" ) } ) } , lookupData : function ( ) { this . pushStackLiteral ( "data" ) } , pushStringParam : function ( a , b ) { this . pushStackLiteral ( "depth" + this . lastContext ) , this . pushString ( b ) , "sexpr" !== b && ( "string" == typeof a ? this . pushString ( a ) : this . pushStackLiteral ( a ) ) } , emptyHash : function ( ) { this . pushStackLiteral ( "{}" ) , this . options . stringParams && ( this . push ( "{}" ) , this . push ( "{}" ) ) } , pushHash : function ( ) { this . hash && this . hashes . push ( this . hash ) , this . hash = { values : [ ] , types : [ ] , contexts : [ ] } } , popHash : function ( ) { var a = this . hash ; this . hash = this . hashes .
/*! jQuery v2.1.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
! function ( a , b ) { "object" == typeof module && "object" == typeof module . exports ? module . exports = a . document ? b ( a , ! 0 ) : function ( a ) { if ( ! a . document ) throw new Error ( "jQuery requires a window with a document" ) ; return b ( a ) } : b ( a ) } ( "undefined" != typeof window ? window : this , function ( a , b ) { var c = [ ] , d = c . slice , e = c . concat , f = c . push , g = c . indexOf , h = { } , i = h . toString , j = h . hasOwnProperty , k = { } , l = a . document , m = "2.1.1" , n = function ( a , b ) { return new n . fn . init ( a , b ) } , o = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g , p = /^-ms-/ , q = /-([\da-z])/gi , r = function ( a , b ) { return b . toUpperCase ( ) } ; n . fn = n . prototype = { jquery : m , constructor : n , selector : "" , length : 0 , toArray : function ( ) { return d . call ( this ) } , get : function ( a ) { return null != a ? 0 > a ? this [ a + this . length ] : this [ a ] : d . call ( this ) } , pushStack : function ( a ) { var b = n . merge ( this . constructor ( ) , a ) ; return b . prevObject = this , b . context = this . context , b } , each : function ( a , b ) { return n . each ( this , a , b ) } , map : function ( a ) { return this . pushStack ( n . map ( this , function ( b , c ) { return a . call ( b , c , b ) } ) ) } , slice : function ( ) { return this . pushStack ( d . apply ( this , arguments ) ) } , first : function ( ) { return this . eq ( 0 ) } , last : function ( ) { return this . eq ( - 1 ) } , eq : function ( a ) { var b = this . length , c = + a + ( 0 > a ? b : 0 ) ; return this . pushStack ( c >= 0 && b > c ? [ this [ c ] ] : [ ] ) } , end : function ( ) { return this . prevObject || this . constructor ( null ) } , push : f , sort : c . sort , splice : c . splice } , n . extend = n . fn . extend = function ( ) { var a , b , c , d , e , f , g = arguments [ 0 ] || { } , h = 1 , i = arguments . length , j = ! 1 ; for ( "boolean" == typeof g && ( j = g , g = arguments [ h ] || { } , h ++ ) , "object" == typeof g || n . isFunction ( g ) || ( g = { } ) , h === i && ( g = this , h -- ) ; i > h ; h ++ ) if ( null != ( a = arguments [ h ] ) ) for ( b in a ) c = g [ b ] , d = a [ b ] , g !== d && ( j && d && ( n . isPlainObject ( d ) || ( e = n . isArray ( d ) ) ) ? ( e ? ( e = ! 1 , f = c && n . isArray ( c ) ? c : [ ] ) : f = c && n . isPlainObject ( c ) ? c : { } , g [ b ] = n . extend ( j , f , d ) ) : void 0 !== d && ( g [ b ] = d ) ) ; return g } , n . extend ( { expando : "jQuery" + ( m + Math . random ( ) ) . replace ( /\D/g , "" ) , isReady : ! 0 , error : function ( a ) { throw new Error ( a ) } , noop : function ( ) { } , isFunction : function ( a ) { return "function" === n . type ( a ) } , isArray : Array . isArray , isWindow : function ( a ) { return null != a && a === a . window } , isNumeric : function ( a ) { return ! n . isArray ( a ) && a - parseFloat ( a ) >= 0 } , isPlainObject : function ( a ) { return "object" !== n . type ( a ) || a . nodeType || n . isWindow ( a ) ? ! 1 : a . constructor && ! j . call ( a . constructor . prototype , "isPrototypeOf" ) ? ! 1 : ! 0 } , isEmptyObject : function ( a ) { var b ; for ( b in a ) return ! 1 ; return ! 0 } , type : function ( a ) { return null == a ? a + "" : "object" == typeof a || "function" == typeof a ? h [ i . call ( a ) ] || "object" : typeof a } , globalEval : function ( a ) { var b , c = eval ; a = n . trim ( a ) , a && ( 1 === a . indexOf ( "use strict" ) ? ( b = l . createElement ( "script" ) , b . text = a , l . head . appendChild ( b ) . parentNode . removeChild ( b ) ) : c ( a ) ) } , camelCase : function ( a ) { return a . replace ( p , "ms-" ) . replace ( q , r ) } , nodeName : function ( a , b ) { return a . nodeName && a . nodeName . toLowerCase ( ) === b . toLowerCase ( ) } , each : function ( a , b , c ) { var d , e = 0 , f = a . length , g = s ( a ) ; if ( c ) { if ( g ) { for ( ; f > e ; e ++ ) if ( d = b . apply ( a [ e ] , c ) , d === ! 1 ) break } else for ( e in a ) if ( d = b . apply ( a [ e ] , c ) , d === ! 1 ) break } else if ( g ) { for ( ; f > e ; e ++ ) if ( d = b . call ( a [ e ] , e , a [ e ] ) , d === ! 1 ) break } else for ( e in a ) if ( d = b . call ( a [ e ] , e , a [ e ] ) , d === ! 1 ) break ; return a } , trim : function ( a ) { return null == a ? "" : ( a + "" ) . replace ( o , "" ) } , makeArray : function ( a , b ) { var c = b || [ ] ; return null != a && ( s ( Object ( a ) ) ? n . merge ( c , "string" == typeof a ? [ a ] : a ) : f . call ( c , a ) ) , c } , inArray : function ( a , b , c ) { return null == b ? - 1 : g . call ( b , a , c ) } , merge : function ( a , b ) { for ( var c = + b . length , d = 0 , e = a . length ; c > d ; d ++ ) a [ e ++ ] = b [ d ] ; return a . length = e , a } , grep : function ( a , b , c ) { for ( var d , e = [ ] , f = 0 , g = a . length , h = ! c ; g > f ; f ++ ) d = ! b ( a [ f ] , f ) , d !== h && e . push ( a [ f ] ) ; return e } , map : function ( a , b , c ) { var d , f = 0 , g = a . length , h = s ( a ) , i = [ ] ; if ( h ) for ( ; g > f ; f ++ ) d = b ( a [ f ] , f , c ) , null != d && i . push ( d ) ; else for ( f in a ) d = b ( a [ f ] , f , c ) , null != d && i . push ( d ) ; return e . apply ( [ ] , i ) } , guid : 1 , proxy : function ( a , b ) { var c , e , f ; return "string" == typeof b && ( c = a [ b ] , b = a , a = c ) , n . isFunction ( a ) ? ( e = d . call ( arguments , 2 ) , f = function ( ) { return a . apply ( b || this , e . concat ( d . call ( arguments ) ) ) } , f . guid = a . guid = a . guid || n . guid ++ , f ) : void 0 } , now : Date . now , support : k } ) , n . each ( "Boolean Number String Function Array Date RegExp Object Error" . split ( " " ) , function ( a , b ) { h [ "[object " + b + "]" ] = b . toLowerCase ( ) } ) ; function s ( a ) { var b = a . length , c = n . type ( a ) ; return "function" === c || n . isWindow ( a ) ? ! 1 : 1 === a . nodeType && b ? ! 0 : "array" === c || 0 === b || " num
} , _data : function ( a , b , c ) { return L . access ( a , b , c ) } , _removeData : function ( a , b ) { L . remove ( a , b ) } } ) , n . fn . extend ( { data : function ( a , b ) { var c , d , e , f = this [ 0 ] , g = f && f . attributes ; if ( void 0 === a ) { if ( this . length && ( e = M . get ( f ) , 1 === f . nodeType && ! L . get ( f , "hasDataAttrs" ) ) ) { c = g . length ; while ( c -- ) g [ c ] && ( d = g [ c ] . name , 0 === d . indexOf ( "data-" ) && ( d = n . camelCase ( d . slice ( 5 ) ) , P ( f , d , e [ d ] ) ) ) ; L . set ( f , "hasDataAttrs" , ! 0 ) } return e } return "object" == typeof a ? this . each ( function ( ) { M . set ( this , a ) } ) : J ( this , function ( b ) { var c , d = n . camelCase ( a ) ; if ( f && void 0 === b ) { if ( c = M . get ( f , a ) , void 0 !== c ) return c ; if ( c = M . get ( f , d ) , void 0 !== c ) return c ; if ( c = P ( f , d , void 0 ) , void 0 !== c ) return c } else this . each ( function ( ) { var c = M . get ( this , d ) ; M . set ( this , d , b ) , - 1 !== a . indexOf ( "-" ) && void 0 !== c && M . set ( this , a , b ) } ) } , null , b , arguments . length > 1 , null , ! 0 ) } , removeData : function ( a ) { return this . each ( function ( ) { M . remove ( this , a ) } ) } } ) , n . extend ( { queue : function ( a , b , c ) { var d ; return a ? ( b = ( b || "fx" ) + "queue" , d = L . get ( a , b ) , c && ( ! d || n . isArray ( c ) ? d = L . access ( a , b , n . makeArray ( c ) ) : d . push ( c ) ) , d || [ ] ) : void 0 } , dequeue : function ( a , b ) { b = b || "fx" ; var c = n . queue ( a , b ) , d = c . length , e = c . shift ( ) , f = n . _queueHooks ( a , b ) , g = function ( ) { n . dequeue ( a , b ) } ; "inprogress" === e && ( e = c . shift ( ) , d -- ) , e && ( "fx" === b && c . unshift ( "inprogress" ) , delete f . stop , e . call ( a , g , f ) ) , ! d && f && f . empty . fire ( ) } , _queueHooks : function ( a , b ) { var c = b + "queueHooks" ; return L . get ( a , c ) || L . access ( a , c , { empty : n . Callbacks ( "once memory" ) . add ( function ( ) { L . remove ( a , [ b + "queue" , c ] ) } ) } ) } } ) , n . fn . extend ( { queue : function ( a , b ) { var c = 2 ; return "string" != typeof a && ( b = a , a = "fx" , c -- ) , arguments . length < c ? n . queue ( this [ 0 ] , a ) : void 0 === b ? this : this . each ( function ( ) { var c = n . queue ( this , a , b ) ; n . _queueHooks ( this , a ) , "fx" === a && "inprogress" !== c [ 0 ] && n . dequeue ( this , a ) } ) } , dequeue : function ( a ) { return this . each ( function ( ) { n . dequeue ( this , a ) } ) } , clearQueue : function ( a ) { return this . queue ( a || "fx" , [ ] ) } , promise : function ( a , b ) { var c , d = 1 , e = n . Deferred ( ) , f = this , g = this . length , h = function ( ) { -- d || e . resolveWith ( f , [ f ] ) } ; "string" != typeof a && ( b = a , a = void 0 ) , a = a || "fx" ; while ( g -- ) c = L . get ( f [ g ] , a + "queueHooks" ) , c && c . empty && ( d ++ , c . empty . add ( h ) ) ; return h ( ) , e . promise ( b ) } } ) ; var Q = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ . source , R = [ "Top" , "Right" , "Bottom" , "Left" ] , S = function ( a , b ) { return a = b || a , "none" === n . css ( a , "display" ) || ! n . contains ( a . ownerDocument , a ) } , T = /^(?:checkbox|radio)$/i ; ! function ( ) { var a = l . createDocumentFragment ( ) , b = a . appendChild ( l . createElement ( "div" ) ) , c = l . createElement ( "input" ) ; c . setAttribute ( "type" , "radio" ) , c . setAttribute ( "checked" , "checked" ) , c . setAttribute ( "name" , "t" ) , b . appendChild ( c ) , k . checkClone = b . cloneNode ( ! 0 ) . cloneNode ( ! 0 ) . lastChild . checked , b . innerHTML = "<textarea>x</textarea>" , k . noCloneChecked = ! ! b . cloneNode ( ! 0 ) . lastChild . defaultValue } ( ) ; var U = "undefined" ; k . focusinBubbles = "onfocusin" in a ; var V = /^key/ , W = /^(?:mouse|pointer|contextmenu)|click/ , X = /^(?:focusinfocus|focusoutblur)$/ , Y = /^([^.]*)(?:\.(.+)|)$/ ; function Z ( ) { return ! 0 } function $ ( ) { return ! 1 } function _ ( ) { try { return l . activeElement } catch ( a ) { } } n . event = { global : { } , add : function ( a , b , c , d , e ) { var f , g , h , i , j , k , l , m , o , p , q , r = L . get ( a ) ; if ( r ) { c . handler && ( f = c , c = f . handler , e = f . selector ) , c . guid || ( c . guid = n . guid ++ ) , ( i = r . events ) || ( i = r . events = { } ) , ( g = r . handle ) || ( g = r . handle = function ( b ) { return typeof n !== U && n . event . triggered !== b . type ? n . event . dispatch . apply ( a , arguments ) : void 0 } ) , b = ( b || "" ) . match ( E ) || [ "" ] , j = b . length ; while ( j -- ) h = Y . exec ( b [ j ] ) || [ ] , o = q = h [ 1 ] , p = ( h [ 2 ] || "" ) . split ( "." ) . sort ( ) , o && ( l = n . event . special [ o ] || { } , o = ( e ? l . delegateType : l . bindType ) || o , l = n . event . special [ o ] || { } , k = n . extend ( { type : o , origType : q , data : d , handler : c , guid : c . guid , selector : e , needsContext : e && n . expr . match . needsContext . test ( e ) , namespace : p . join ( "." ) } , f ) , ( m = i [ o ] ) || ( m = i [ o ] = [ ] , m . delegateCount = 0 , l . setup && l . setup . call ( a , d , p , g ) !== ! 1 || a . addEventListener && a . addEventListener ( o , g , ! 1 ) ) , l . add && ( l . add . call ( a , k ) , k . handler . guid || ( k . handler . guid = c . guid ) ) , e ? m . splice ( m . delegateCount ++ , 0 , k ) : m . push ( k ) , n . event . global [ o ] = ! 0 ) } } , remove : function ( a , b , c , d , e ) { var f , g , h , i , j , k , l , m , o , p , q , r = L . hasData ( a ) && L . get ( a ) ; if ( r && ( i = r . events ) ) { b = ( b || "" ) . match ( E ) || [ "" ] , j = b . length ; while ( j -- ) if ( h = Y . exec ( b [ j ] ) || [ ] , o = q = h [ 1 ] , p = ( h [ 2 ] || "" ) . split ( "." ) . sort ( ) , o ) { l = n . event . special [ o ] || { } , o = ( d ? l . delegateType : l . bindType ) || o , m = i [ o ] || [ ] , h = h [ 2 ] && new
} , removeAttr : function ( a , b ) { var c , d , e = 0 , f = b && b . match ( E ) ; if ( f && 1 === a . nodeType ) while ( c = f [ e ++ ] ) d = n . propFix [ c ] || c , n . expr . match . bool . test ( c ) && ( a [ d ] = ! 1 ) , a . removeAttribute ( c ) } , attrHooks : { type : { set : function ( a , b ) { if ( ! k . radioValue && "radio" === b && n . nodeName ( a , "input" ) ) { var c = a . value ; return a . setAttribute ( "type" , b ) , c && ( a . value = c ) , b } } } } } ) , Zb = { set : function ( a , b , c ) { return b === ! 1 ? n . removeAttr ( a , c ) : a . setAttribute ( c , c ) , c } } , n . each ( n . expr . match . bool . source . match ( /\w+/g ) , function ( a , b ) { var c = $b [ b ] || n . find . attr ; $b [ b ] = function ( a , b , d ) { var e , f ; return d || ( f = $b [ b ] , $b [ b ] = e , e = null != c ( a , b , d ) ? b . toLowerCase ( ) : null , $b [ b ] = f ) , e } } ) ; var _b = /^(?:input|select|textarea|button)$/i ; n . fn . extend ( { prop : function ( a , b ) { return J ( this , n . prop , a , b , arguments . length > 1 ) } , removeProp : function ( a ) { return this . each ( function ( ) { delete this [ n . propFix [ a ] || a ] } ) } } ) , n . extend ( { propFix : { "for" : "htmlFor" , "class" : "className" } , prop : function ( a , b , c ) { var d , e , f , g = a . nodeType ; if ( a && 3 !== g && 8 !== g && 2 !== g ) return f = 1 !== g || ! n . isXMLDoc ( a ) , f && ( b = n . propFix [ b ] || b , e = n . propHooks [ b ] ) , void 0 !== c ? e && "set" in e && void 0 !== ( d = e . set ( a , c , b ) ) ? d : a [ b ] = c : e && "get" in e && null !== ( d = e . get ( a , b ) ) ? d : a [ b ] } , propHooks : { tabIndex : { get : function ( a ) { return a . hasAttribute ( "tabindex" ) || _b . test ( a . nodeName ) || a . href ? a . tabIndex : - 1 } } } } ) , k . optSelected || ( n . propHooks . selected = { get : function ( a ) { var b = a . parentNode ; return b && b . parentNode && b . parentNode . selectedIndex , null } } ) , n . each ( [ "tabIndex" , "readOnly" , "maxLength" , "cellSpacing" , "cellPadding" , "rowSpan" , "colSpan" , "useMap" , "frameBorder" , "contentEditable" ] , function ( ) { n . propFix [ this . toLowerCase ( ) ] = this } ) ; var ac = /[\t\r\n\f]/g ; n . fn . extend ( { addClass : function ( a ) { var b , c , d , e , f , g , h = "string" == typeof a && a , i = 0 , j = this . length ; if ( n . isFunction ( a ) ) return this . each ( function ( b ) { n ( this ) . addClass ( a . call ( this , b , this . className ) ) } ) ; if ( h ) for ( b = ( a || "" ) . match ( E ) || [ ] ; j > i ; i ++ ) if ( c = this [ i ] , d = 1 === c . nodeType && ( c . className ? ( " " + c . className + " " ) . replace ( ac , " " ) : " " ) ) { f = 0 ; while ( e = b [ f ++ ] ) d . indexOf ( " " + e + " " ) < 0 && ( d += e + " " ) ; g = n . trim ( d ) , c . className !== g && ( c . className = g ) } return this } , removeClass : function ( a ) { var b , c , d , e , f , g , h = 0 === arguments . length || "string" == typeof a && a , i = 0 , j = this . length ; if ( n . isFunction ( a ) ) return this . each ( function ( b ) { n ( this ) . removeClass ( a . call ( this , b , this . className ) ) } ) ; if ( h ) for ( b = ( a || "" ) . match ( E ) || [ ] ; j > i ; i ++ ) if ( c = this [ i ] , d = 1 === c . nodeType && ( c . className ? ( " " + c . className + " " ) . replace ( ac , " " ) : "" ) ) { f = 0 ; while ( e = b [ f ++ ] ) while ( d . indexOf ( " " + e + " " ) >= 0 ) d = d . replace ( " " + e + " " , " " ) ; g = a ? n . trim ( d ) : "" , c . className !== g && ( c . className = g ) } return this } , toggleClass : function ( a , b ) { var c = typeof a ; return "boolean" == typeof b && "string" === c ? b ? this . addClass ( a ) : this . removeClass ( a ) : this . each ( n . isFunction ( a ) ? function ( c ) { n ( this ) . toggleClass ( a . call ( this , c , this . className , b ) , b ) } : function ( ) { if ( "string" === c ) { var b , d = 0 , e = n ( this ) , f = a . match ( E ) || [ ] ; while ( b = f [ d ++ ] ) e . hasClass ( b ) ? e . removeClass ( b ) : e . addClass ( b ) } else ( c === U || "boolean" === c ) && ( this . className && L . set ( this , "__className__" , this . className ) , this . className = this . className || a === ! 1 ? "" : L . get ( this , "__className__" ) || "" ) } ) } , hasClass : function ( a ) { for ( var b = " " + a + " " , c = 0 , d = this . length ; d > c ; c ++ ) if ( 1 === this [ c ] . nodeType && ( " " + this [ c ] . className + " " ) . replace ( ac , " " ) . indexOf ( b ) >= 0 ) return ! 0 ; return ! 1 } } ) ; var bc = /\r/g ; n . fn . extend ( { val : function ( a ) { var b , c , d , e = this [ 0 ] ; { if ( arguments . length ) return d = n . isFunction ( a ) , this . each ( function ( c ) { var e ; 1 === this . nodeType && ( e = d ? a . call ( this , c , n ( this ) . val ( ) ) : a , null == e ? e = "" : "number" == typeof e ? e += "" : n . isArray ( e ) && ( e = n . map ( e , function ( a ) { return null == a ? "" : a + "" } ) ) , b = n . valHooks [ this . type ] || n . valHooks [ this . nodeName . toLowerCase ( ) ] , b && "set" in b && void 0 !== b . set ( this , e , "value" ) || ( this . value = e ) ) } ) ; if ( e ) return b = n . valHooks [ e . type ] || n . valHooks [ e . nodeName . toLowerCase ( ) ] , b && "get" in b && void 0 !== ( c = b . get ( e , "value" ) ) ? c : ( c = e . value , "string" == typeof c ? c . replace ( bc , "" ) : null == c ? "" : c ) } } } ) , n . extend ( { valHooks : { option : { get : function ( a ) { var b = n . find . attr ( a , "value" ) ; return null != b ? b : n . trim ( n . text ( a ) ) } } , select : { get : function ( a ) { for ( var b , c , d = a . options , e = a . selectedIndex , f = "select-one" === a . type || 0 > e , g = f ? null : [ ] , h = f ? e + 1 : d . length , i = 0 > e ? h : f ? e : 0 ; h > i ; i ++ ) if ( c = d [ i ] , ! ( ! c . selected && i !== e || ( k . optDisabled ? c . disabled : null !== c . getAttribute ( "disabled" ) ) || c . par
//# sourceMappingURL=jquery.min.map
/* build: `node build.js modules=ALL exclude=gestures,cufon,json minifier=uglifyjs` */ /*! Fabric.js Copyright 2008-2014, Printio (Juriy Zaytsev, Maxim Chernyak) */ var fabric = fabric || { version : "1.4.11" } ; typeof exports != "undefined" && ( exports . fabric = fabric ) , typeof document != "undefined" && typeof window != "undefined" ? ( fabric . document = document , fabric . window = window ) : ( fabric . document = require ( "jsdom" ) . jsdom ( "<!DOCTYPE html><html><head></head><body></body></html>" ) , fabric . window = fabric . document . createWindow ( ) ) , fabric . isTouchSupported = "ontouchstart" in fabric . document . documentElement , fabric . isLikelyNode = typeof Buffer != "undefined" && typeof window == "undefined" , fabric . SHARED _ATTRIBUTES = [ "display" , "transform" , "fill" , "fill-opacity" , "fill-rule" , "opacity" , "stroke" , "stroke-dasharray" , "stroke-linecap" , "stroke-linejoin" , "stroke-miterlimit" , "stroke-opacity" , "stroke-width" ] , fabric . DPI = 96 , function ( ) { function e ( e , t ) { if ( ! this . _ _eventListeners [ e ] ) return ; t ? fabric . util . removeFromArray ( this . _ _eventListeners [ e ] , t ) : this . _ _eventListeners [ e ] . length = 0 } function t ( e , t ) { this . _ _eventListeners || ( this . _ _eventListeners = { } ) ; if ( arguments . length === 1 ) for ( var n in e ) this . on ( n , e [ n ] ) ; else this . _ _eventListeners [ e ] || ( this . _ _eventListeners [ e ] = [ ] ) , this . _ _eventListeners [ e ] . push ( t ) ; return this } function n ( t , n ) { if ( ! this . _ _eventListeners ) return ; if ( arguments . length === 0 ) this . _ _eventListeners = { } ; else if ( arguments . length === 1 && typeof arguments [ 0 ] == "object" ) for ( var r in t ) e . call ( this , r , t [ r ] ) ; else e . call ( this , t , n ) ; return this } function r ( e , t ) { if ( ! this . _ _eventListeners ) return ; var n = this . _ _eventListeners [ e ] ; if ( ! n ) return ; for ( var r = 0 , i = n . length ; r < i ; r ++ ) n [ r ] . call ( this , t || { } ) ; return this } fabric . Observable = { observe : t , stopObserving : n , fire : r , on : t , off : n , trigger : r } } ( ) , fabric . Collection = { add : function ( ) { this . _objects . push . apply ( this . _objects , arguments ) ; for ( var e = 0 , t = arguments . length ; e < t ; e ++ ) this . _onObjectAdded ( arguments [ e ] ) ; return this . renderOnAddRemove && this . renderAll ( ) , this } , insertAt : function ( e , t , n ) { var r = this . getObjects ( ) ; return n ? r [ t ] = e : r . splice ( t , 0 , e ) , this . _onObjectAdded ( e ) , this . renderOnAddRemove && this . renderAll ( ) , this } , remove : function ( ) { var e = this . getObjects ( ) , t ; for ( var n = 0 , r = arguments . length ; n < r ; n ++ ) t = e . indexOf ( arguments [ n ] ) , t !== - 1 && ( e . splice ( t , 1 ) , this . _onObjectRemoved ( arguments [ n ] ) ) ; return this . renderOnAddRemove && this . renderAll ( ) , this } , forEachObject : function ( e , t ) { var n = this . getObjects ( ) , r = n . length ; while ( r -- ) e . call ( t , n [ r ] , r , n ) ; return this } , getObjects : function ( e ) { return typeof e == "undefined" ? this . _objects : this . _objects . filter ( function ( t ) { return t . type === e } ) } , item : function ( e ) { return this . getObjects ( ) [ e ] } , isEmpty : function ( ) { return this . getObjects ( ) . length === 0 } , size : function ( ) { return this . getObjects ( ) . length } , contains : function ( e ) { return this . getObjects ( ) . indexOf ( e ) > - 1 } , complexity : function ( ) { return this . getObjects ( ) . reduce ( function ( e , t ) { return e += t . complexity ? t . complexity ( ) : 0 , e } , 0 ) } } , function ( e ) { var t = Math . sqrt , n = Math . atan2 , r = Math . PI / 180 ; fabric . util = { removeFromArray : function ( e , t ) { var n = e . indexOf ( t ) ; return n !== - 1 && e . splice ( n , 1 ) , e } , getRandomInt : function ( e , t ) { return Math . floor ( Math . random ( ) * ( t - e + 1 ) ) + e } , degreesToRadians : function ( e ) { return e * r } , radiansToDegrees : function ( e ) { return e / r } , rotatePoint : function ( e , t , n ) { var r = Math . sin ( n ) , i = Math . cos ( n ) ; e . subtractEquals ( t ) ; var s = e . x * i - e . y * r , o = e . x * r + e . y * i ; return ( new fabric . Point ( s , o ) ) . addEquals ( t ) } , transformPoint : function ( e , t , n ) { return n ? new fabric . Point ( t [ 0 ] * e . x + t [ 1 ] * e . y , t [ 2 ] * e . x + t [ 3 ] * e . y ) : new fabric . Point ( t [ 0 ] * e . x + t [ 1 ] * e . y + t [ 4 ] , t [ 2 ] * e . x + t [ 3 ] * e . y + t [ 5 ] ) } , invertTransform : function ( e ) { var t = e . slice ( ) , n = 1 / ( e [ 0 ] * e [ 3 ] - e [ 1 ] * e [ 2 ] ) ; t = [ n * e [ 3 ] , - n * e [ 1 ] , - n * e [ 2 ] , n * e [ 0 ] , 0 , 0 ] ; var r = fabric . util . transformPoint ( { x : e [ 4 ] , y : e [ 5 ] } , t ) ; return t [ 4 ] = - r . x , t [ 5 ] = - r . y , t } , toFixed : function ( e , t ) { return parseFloat ( Number ( e ) . toFixed ( t ) ) } , parseUnit : function ( e ) { var t = /\D{0,2}$/ . exec ( e ) , n = parseFloat ( e ) ; switch ( t [ 0 ] ) { case "mm" : return n * fabric . DPI / 25.4 ; case "cm" : return n * fabric . DPI / 2.54 ; case "in" : return n * fabric . DPI ; case "pt" : return n * fabric . DPI / 72 ; case "pc" : return n * fabric . DPI / 72 * 12 ; default : return n } } , falseFunction : function ( ) { return ! 1 } , getKlass : function ( e , t ) { return e = fabric . util . string . camelize ( e . charAt ( 0 ) . toUp
: "get" , onComplete : i } ) } ) } , loadSVGFromString : function ( e , n , r ) { e = e . trim ( ) ; var i ; if ( typeof DOMParser != "undefined" ) { var s = new DOMParser ; s && s . parseFromString && ( i = s . parseFromString ( e , "text/xml" ) ) } else t . window . ActiveXObject && ( i = new ActiveXObject ( "Microsoft.XMLDOM" ) , i . async = "false" , i . loadXML ( e . replace ( /<!DOCTYPE[\s\S]*?(\[[\s\S]*\])*?>/i , "" ) ) ) ; t . parseSVGDocument ( i . documentElement , function ( e , t ) { n ( e , t ) } , r ) } , createSVGFontFacesMarkup : function ( e ) { var t = "" ; for ( var n = 0 , r = e . length ; n < r ; n ++ ) { if ( e [ n ] . type !== "text" || ! e [ n ] . path ) continue ; t += [ "@font-face {" , "font-family: " , e [ n ] . fontFamily , "; " , "src: url('" , e [ n ] . path , "')" , "}" ] . join ( "" ) } return t && ( t = [ '<style type="text/css">' , "<![CDATA[" , t , "]]>" , "</style>" ] . join ( "" ) ) , t } , createSVGRefElementsMarkup : function ( e ) { var t = [ ] ; return T ( t , e , "backgroundColor" ) , T ( t , e , "overlayColor" ) , t . join ( "" ) } } ) } ( typeof exports != "undefined" ? exports : this ) , fabric . ElementsParser = function ( e , t , n , r ) { this . elements = e , this . callback = t , this . options = n , this . reviver = r } , fabric . ElementsParser . prototype . parse = function ( ) { this . instances = new Array ( this . elements . length ) , this . numElements = this . elements . length , this . createObjects ( ) } , fabric . ElementsParser . prototype . createObjects = function ( ) { for ( var e = 0 , t = this . elements . length ; e < t ; e ++ ) ( function ( e , t ) { setTimeout ( function ( ) { e . createObject ( e . elements [ t ] , t ) } , 0 ) } ) ( this , e ) } , fabric . ElementsParser . prototype . createObject = function ( e , t ) { var n = fabric [ fabric . util . string . capitalize ( e . tagName ) ] ; if ( n && n . fromElement ) try { this . _createObject ( n , e , t ) } catch ( r ) { fabric . log ( r ) } else this . checkIfDone ( ) } , fabric . ElementsParser . prototype . _createObject = function ( e , t , n ) { if ( e . async ) e . fromElement ( t , this . createCallback ( n , t ) , this . options ) ; else { var r = e . fromElement ( t , this . options ) ; this . resolveGradient ( r , "fill" ) , this . resolveGradient ( r , "stroke" ) , this . reviver && this . reviver ( t , r ) , this . instances [ n ] = r , this . checkIfDone ( ) } } , fabric . ElementsParser . prototype . createCallback = function ( e , t ) { var n = this ; return function ( r ) { n . resolveGradient ( r , "fill" ) , n . resolveGradient ( r , "stroke" ) , n . reviver && n . reviver ( t , r ) , n . instances [ e ] = r , n . checkIfDone ( ) } } , fabric . ElementsParser . prototype . resolveGradient = function ( e , t ) { var n = e . get ( t ) ; if ( ! /^url\(/ . test ( n ) ) return ; var r = n . slice ( 5 , n . length - 1 ) ; fabric . gradientDefs [ r ] && e . set ( t , fabric . Gradient . fromElement ( fabric . gradientDefs [ r ] , e ) ) } , fabric . ElementsParser . prototype . checkIfDone = function ( ) { -- this . numElements === 0 && ( this . instances = this . instances . filter ( function ( e ) { return e != null } ) , this . callback ( this . instances ) ) } , function ( e ) { "use strict" ; function n ( e , t ) { this . x = e , this . y = t } var t = e . fabric || ( e . fabric = { } ) ; if ( t . Point ) { t . warn ( "fabric.Point is already defined" ) ; return } t . Point = n , n . prototype = { constructor : n , add : function ( e ) { return new n ( this . x + e . x , this . y + e . y ) } , addEquals : function ( e ) { return this . x += e . x , this . y += e . y , this } , scalarAdd : function ( e ) { return new n ( this . x + e , this . y + e ) } , scalarAddEquals : function ( e ) { return this . x += e , this . y += e , this } , subtract : function ( e ) { return new n ( this . x - e . x , this . y - e . y ) } , subtractEquals : function ( e ) { return this . x -= e . x , this . y -= e . y , this } , scalarSubtract : function ( e ) { return new n ( this . x - e , this . y - e ) } , scalarSubtractEquals : function ( e ) { return this . x -= e , this . y -= e , this } , multiply : function ( e ) { return new n ( this . x * e , this . y * e ) } , multiplyEquals : function ( e ) { return this . x *= e , this . y *= e , this } , divide : function ( e ) { return new n ( this . x / e , this . y / e ) } , divideEquals : function ( e ) { return this . x /= e , this . y /= e , this } , eq : function ( e ) { return this . x === e . x && this . y === e . y } , lt : function ( e ) { return this . x < e . x && this . y < e . y } , lte : function ( e ) { return this . x <= e . x && this . y <= e . y } , gt : function ( e ) { return this . x > e . x && this . y > e . y } , gte : function ( e ) { return this . x >= e . x && this . y >= e . y } , lerp : function ( e , t ) { return new n ( this . x + ( e . x - this . x ) * t , this . y + ( e . y - this . y ) * t ) } , distanceFrom : function ( e ) { var t = this . x - e . x , n = this . y - e . y ; return Math . sqrt ( t * t + n * n ) } , midPointFrom : function ( e ) { return new n ( this . x + ( e . x - this . x ) / 2 , this . y + ( e . y - this . y ) / 2 ) } , min : function ( e ) { return new n ( Math . min ( this . x , e . x ) , Math . min ( this . y , e . y ) ) } , max : function ( e ) { return new n ( Math . max ( this . x , e . x ) , Math . max ( this . y , e . y ) ) } , toString : function ( ) { return this . x + "," + this . y } , setXY : function ( e , t ) { this . x = e , this . y = t } , setFromPoint : function ( e ) { this . x = e . x , this . y = e . y } , swap : functio
( ) } , onMouseUp : function ( ) { this . _finalizeAndAddPath ( ) } , _prepareForDrawing : function ( e ) { var t = new fabric . Point ( e . x , e . y ) ; this . _reset ( ) , this . _addPoint ( t ) , this . canvas . contextTop . moveTo ( t . x , t . y ) } , _addPoint : function ( e ) { this . _points . push ( e ) } , _reset : function ( ) { this . _points . length = 0 , this . _setBrushStyles ( ) , this . _setShadow ( ) } , _captureDrawingPath : function ( e ) { var t = new fabric . Point ( e . x , e . y ) ; this . _addPoint ( t ) } , _render : function ( ) { var e = this . canvas . contextTop , t = this . canvas . viewportTransform , n = this . _points [ 0 ] , r = this . _points [ 1 ] ; e . save ( ) , e . transform ( t [ 0 ] , t [ 1 ] , t [ 2 ] , t [ 3 ] , t [ 4 ] , t [ 5 ] ) , e . beginPath ( ) , this . _points . length === 2 && n . x === r . x && n . y === r . y && ( n . x -= . 5 , r . x += . 5 ) , e . moveTo ( n . x , n . y ) ; for ( var i = 1 , s = this . _points . length ; i < s ; i ++ ) { var o = n . midPointFrom ( r ) ; e . quadraticCurveTo ( n . x , n . y , o . x , o . y ) , n = this . _points [ i ] , r = this . _points [ i + 1 ] } e . lineTo ( n . x , n . y ) , e . stroke ( ) , e . restore ( ) } , _getSVGPathData : function ( ) { return this . box = this . getPathBoundingBox ( this . _points ) , this . convertPointsToSVGPath ( this . _points , this . box . minX , this . box . minY ) } , getPathBoundingBox : function ( n ) { var r = [ ] , i = [ ] , s = n [ 0 ] , o = n [ 1 ] , u = s ; for ( var a = 1 , f = n . length ; a < f ; a ++ ) { var l = s . midPointFrom ( o ) ; r . push ( u . x ) , r . push ( l . x ) , i . push ( u . y ) , i . push ( l . y ) , s = n [ a ] , o = n [ a + 1 ] , u = l } return r . push ( s . x ) , i . push ( s . y ) , { minX : e ( r ) , minY : e ( i ) , maxX : t ( r ) , maxY : t ( i ) } } , convertPointsToSVGPath : function ( e , t , n ) { var r = [ ] , i = new fabric . Point ( e [ 0 ] . x - t , e [ 0 ] . y - n ) , s = new fabric . Point ( e [ 1 ] . x - t , e [ 1 ] . y - n ) ; r . push ( "M " , e [ 0 ] . x - t , " " , e [ 0 ] . y - n , " " ) ; for ( var o = 1 , u = e . length ; o < u ; o ++ ) { var a = i . midPointFrom ( s ) ; r . push ( "Q " , i . x , " " , i . y , " " , a . x , " " , a . y , " " ) , i = new fabric . Point ( e [ o ] . x - t , e [ o ] . y - n ) , o + 1 < e . length && ( s = new fabric . Point ( e [ o + 1 ] . x - t , e [ o + 1 ] . y - n ) ) } return r . push ( "L " , i . x , " " , i . y , " " ) , r } , createPath : function ( e ) { var t = new fabric . Path ( e ) ; return t . fill = null , t . stroke = this . color , t . strokeWidth = this . width , t . strokeLineCap = this . strokeLineCap , t . strokeLineJoin = this . strokeLineJoin , this . shadow && ( this . shadow . affectStroke = ! 0 , t . setShadow ( this . shadow ) ) , t } , _finalizeAndAddPath : function ( ) { var e = this . canvas . contextTop ; e . closePath ( ) ; var t = this . _getSVGPathData ( ) . join ( "" ) ; if ( t === "M 0 0 Q 0 0 0 0 L 0 0" ) { this . canvas . renderAll ( ) ; return } var n = this . box . minX + ( this . box . maxX - this . box . minX ) / 2 , r = this . box . minY + ( this . box . maxY - this . box . minY ) / 2 ; this . canvas . contextTop . arc ( n , r , 3 , 0 , Math . PI * 2 , ! 1 ) ; var i = this . createPath ( t ) ; i . set ( { left : n , top : r , originX : "center" , originY : "center" } ) , this . canvas . add ( i ) , i . setCoords ( ) , this . canvas . clearContext ( this . canvas . contextTop ) , this . _resetShadow ( ) , this . canvas . renderAll ( ) , this . canvas . fire ( "path:created" , { path : i } ) } } ) } ( ) , fabric . CircleBrush = fabric . util . createClass ( fabric . BaseBrush , { width : 10 , initialize : function ( e ) { this . canvas = e , this . points = [ ] } , drawDot : function ( e ) { var t = this . addPoint ( e ) , n = this . canvas . contextTop , r = this . canvas . viewportTransform ; n . save ( ) , n . transform ( r [ 0 ] , r [ 1 ] , r [ 2 ] , r [ 3 ] , r [ 4 ] , r [ 5 ] ) , n . fillStyle = t . fill , n . beginPath ( ) , n . arc ( t . x , t . y , t . radius , 0 , Math . PI * 2 , ! 1 ) , n . closePath ( ) , n . fill ( ) , n . restore ( ) } , onMouseDown : function ( e ) { this . points . length = 0 , this . canvas . clearContext ( this . canvas . contextTop ) , this . _setShadow ( ) , this . drawDot ( e ) } , onMouseMove : function ( e ) { this . drawDot ( e ) } , onMouseUp : function ( ) { var e = this . canvas . renderOnAddRemove ; this . canvas . renderOnAddRemove = ! 1 ; var t = [ ] ; for ( var n = 0 , r = this . points . length ; n < r ; n ++ ) { var i = this . points [ n ] , s = new fabric . Circle ( { radius : i . radius , left : i . x , top : i . y , originX : "center" , originY : "center" , fill : i . fill } ) ; this . shadow && s . setShadow ( this . shadow ) , t . push ( s ) } var o = new fabric . Group ( t , { originX : "center" , originY : "center" } ) ; o . canvas = this . canvas , this . canvas . add ( o ) , this . canvas . fire ( "path:created" , { path : o } ) , this . canvas . clearContext ( this . canvas . contextTop ) , this . _resetShadow ( ) , this . canvas . renderOnAddRemove = e , this . canvas . renderAll ( ) } , addPoint : function ( e ) { var t = new fabric . Point ( e . x , e . y ) , n = fabric . util . getRandomInt ( Math . max ( 0 , this . width - 20 ) , this . width + 20 ) / 2 , r = ( new fabric . Color ( this . color ) ) . setAlpha ( fabric . util . getRandomInt ( 0 , 100 ) / 100 ) . toRgba ( ) ; return t . radius = n , t . fill = r , this . points . push ( t ) , t } } ) , fabric . SprayBrush = fabric . util . createClass ( fabric . BaseBrush , { width : 10 , density : 20 , dotWidth : 1 , dotWidthVariance : 1 , randomOpacity : ! 1 , optimizeOverlapping : ! 0 , initialize : function ( e ) { this . canvas = e , this . sprayChunks = [ ]
. object . extend ( fabric . StaticCanvas . prototype , { loadFromDatalessJSON : function ( e , t , n ) { return this . loadFromJSON ( e , t , n ) } , loadFromJSON : function ( e , t , n ) { if ( ! e ) return ; var r = typeof e == "string" ? JSON . parse ( e ) : e ; this . clear ( ) ; var i = this ; return this . _enlivenObjects ( r . objects , function ( ) { i . _setBgOverlay ( r , t ) } , n ) , this } , _setBgOverlay : function ( e , t ) { var n = this , r = { backgroundColor : ! 1 , overlayColor : ! 1 , backgroundImage : ! 1 , overlayImage : ! 1 } ; if ( ! e . backgroundImage && ! e . overlayImage && ! e . background && ! e . overlay ) { t && t ( ) ; return } var i = function ( ) { r . backgroundImage && r . overlayImage && r . backgroundColor && r . overlayColor && ( n . renderAll ( ) , t && t ( ) ) } ; this . _ _setBgOverlay ( "backgroundImage" , e . backgroundImage , r , i ) , this . _ _setBgOverlay ( "overlayImage" , e . overlayImage , r , i ) , this . _ _setBgOverlay ( "backgroundColor" , e . background , r , i ) , this . _ _setBgOverlay ( "overlayColor" , e . overlay , r , i ) , i ( ) } , _ _setBgOverlay : function ( e , t , n , r ) { var i = this ; if ( ! t ) { n [ e ] = ! 0 ; return } e === "backgroundImage" || e === "overlayImage" ? fabric . Image . fromObject ( t , function ( t ) { i [ e ] = t , n [ e ] = ! 0 , r && r ( ) } ) : this [ "set" + fabric . util . string . capitalize ( e , ! 0 ) ] ( t , function ( ) { n [ e ] = ! 0 , r && r ( ) } ) } , _enlivenObjects : function ( e , t , n ) { var r = this ; if ( ! e || e . length === 0 ) { t && t ( ) ; return } var i = this . renderOnAddRemove ; this . renderOnAddRemove = ! 1 , fabric . util . enlivenObjects ( e , function ( e ) { e . forEach ( function ( e , t ) { r . insertAt ( e , t , ! 0 ) } ) , r . renderOnAddRemove = i , t && t ( ) } , null , n ) } , _toDataURL : function ( e , t ) { this . clone ( function ( n ) { t ( n . toDataURL ( e ) ) } ) } , _toDataURLWithMultiplier : function ( e , t , n ) { this . clone ( function ( r ) { n ( r . toDataURLWithMultiplier ( e , t ) ) } ) } , clone : function ( e , t ) { var n = JSON . stringify ( this . toJSON ( t ) ) ; this . cloneWithoutData ( function ( t ) { t . loadFromJSON ( n , function ( ) { e && e ( t ) } ) } ) } , cloneWithoutData : function ( e ) { var t = fabric . document . createElement ( "canvas" ) ; t . width = this . getWidth ( ) , t . height = this . getHeight ( ) ; var n = new fabric . Canvas ( t ) ; n . clipTo = this . clipTo , this . backgroundImage ? ( n . setBackgroundImage ( this . backgroundImage . src , function ( ) { n . renderAll ( ) , e && e ( n ) } ) , n . backgroundImageOpacity = this . backgroundImageOpacity , n . backgroundImageStretch = this . backgroundImageStretch ) : e && e ( n ) } } ) , function ( e ) { "use strict" ; var t = e . fabric || ( e . fabric = { } ) , n = t . util . object . extend , r = t . util . toFixed , i = t . util . string . capitalize , s = t . util . degreesToRadians , o = t . StaticCanvas . supports ( "setLineDash" ) ; if ( t . Object ) return ; t . Object = t . util . createClass ( { type : "object" , originX : "left" , originY : "top" , top : 0 , left : 0 , width : 0 , height : 0 , scaleX : 1 , scaleY : 1 , flipX : ! 1 , flipY : ! 1 , opacity : 1 , angle : 0 , cornerSize : 12 , transparentCorners : ! 0 , hoverCursor : null , padding : 0 , borderColor : "rgba(102,153,255,0.75)" , cornerColor : "rgba(102,153,255,0.5)" , centeredScaling : ! 1 , centeredRotation : ! 0 , fill : "rgb(0,0,0)" , fillRule : "source-over" , backgroundColor : "" , stroke : null , strokeWidth : 1 , strokeDashArray : null , strokeLineCap : "butt" , strokeLineJoin : "miter" , strokeMiterLimit : 10 , shadow : null , borderOpacityWhenMoving : . 4 , borderScaleFactor : 1 , transformMatrix : null , minScaleLimit : . 01 , selectable : ! 0 , evented : ! 0 , visible : ! 0 , hasControls : ! 0 , hasBorders : ! 0 , hasRotatingPoint : ! 0 , rotatingPointOffset : 40 , perPixelTargetFind : ! 1 , includeDefaultValues : ! 0 , clipTo : null , lockMovementX : ! 1 , lockMovementY : ! 1 , lockRotation : ! 1 , lockScalingX : ! 1 , lockScalingY : ! 1 , lockUniScaling : ! 1 , lockScalingFlip : ! 1 , stateProperties : "top left width height scaleX scaleY flipX flipY originX originY transformMatrix stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit angle opacity fill fillRule shadow clipTo visible backgroundColor" . split ( " " ) , initialize : function ( e ) { e && this . setOptions ( e ) } , _initGradient : function ( e ) { e . fill && e . fill . colorStops && ! ( e . fill instanceof t . Gradient ) && this . set ( "fill" , new t . Gradient ( e . fill ) ) } , _initPattern : function ( e ) { e . fill && e . fill . source && ! ( e . fill instanceof t . Pattern ) && this . set ( "fill" , new t . Pattern ( e . fill ) ) , e . stroke && e . stroke . source && ! ( e . stroke instanceof t . Pattern ) && this . set ( "stroke" , new t . Pattern ( e . stroke ) ) } , _initClipping : function ( e ) { if ( ! e . clipTo || typeof e . clipTo != "string" ) return ; var n = t . util . getFunctionBody ( e . clipTo ) ; typeof n != "undefined" && ( this . clipTo = new Function ( "ctx" , n ) ) } , setOptions : function ( e ) { for ( var t in e ) this . set ( t , e [ t ] ) ; this . _initGradient ( e ) , this . _initPattern ( e ) , this . _initClipping ( e ) } , transform : function
this . radius ) , t . push ( "<circle " , 'cx="' + n + '" cy="' + r + '" ' , 'r="' , this . radius , '" style="' , this . getSvgStyles ( ) , '" transform="' , this . getSvgTransform ( ) , " " , this . getSvgTransformMatrix ( ) , '"/>\n' ) , e ? e ( t . join ( "" ) ) : t . join ( "" ) } , _render : function ( e , t ) { e . beginPath ( ) , e . arc ( t ? this . left + this . radius : 0 , t ? this . top + this . radius : 0 , this . radius , 0 , n , ! 1 ) , this . _renderFill ( e ) , this . _renderStroke ( e ) } , getRadiusX : function ( ) { return this . get ( "radius" ) * this . get ( "scaleX" ) } , getRadiusY : function ( ) { return this . get ( "radius" ) * this . get ( "scaleY" ) } , setRadius : function ( e ) { this . radius = e , this . set ( "width" , e * 2 ) . set ( "height" , e * 2 ) } , complexity : function ( ) { return 1 } } ) , t . Circle . ATTRIBUTE _NAMES = t . SHARED _ATTRIBUTES . concat ( "cx cy r" . split ( " " ) ) , t . Circle . fromElement = function ( e , n ) { n || ( n = { } ) ; var s = t . parseAttributes ( e , t . Circle . ATTRIBUTE _NAMES ) ; if ( ! i ( s ) ) throw new Error ( "value of `r` attribute is required and can not be negative" ) ; s . left = s . left || 0 , s . top = s . top || 0 ; var o = new t . Circle ( r ( s , n ) ) ; return o . left -= o . radius , o . top -= o . radius , o } , t . Circle . fromObject = function ( e ) { return new t . Circle ( e ) } } ( typeof exports != "undefined" ? exports : this ) , function ( e ) { "use strict" ; var t = e . fabric || ( e . fabric = { } ) ; if ( t . Triangle ) { t . warn ( "fabric.Triangle is already defined" ) ; return } t . Triangle = t . util . createClass ( t . Object , { type : "triangle" , initialize : function ( e ) { e = e || { } , this . callSuper ( "initialize" , e ) , this . set ( "width" , e . width || 100 ) . set ( "height" , e . height || 100 ) } , _render : function ( e ) { var t = this . width / 2 , n = this . height / 2 ; e . beginPath ( ) , e . moveTo ( - t , n ) , e . lineTo ( 0 , - n ) , e . lineTo ( t , n ) , e . closePath ( ) , this . _renderFill ( e ) , this . _renderStroke ( e ) } , _renderDashedStroke : function ( e ) { var n = this . width / 2 , r = this . height / 2 ; e . beginPath ( ) , t . util . drawDashedLine ( e , - n , r , 0 , - r , this . strokeDashArray ) , t . util . drawDashedLine ( e , 0 , - r , n , r , this . strokeDashArray ) , t . util . drawDashedLine ( e , n , r , - n , r , this . strokeDashArray ) , e . closePath ( ) } , toSVG : function ( e ) { var t = this . _createBaseSVGMarkup ( ) , n = this . width / 2 , r = this . height / 2 , i = [ - n + " " + r , "0 " + - r , n + " " + r ] . join ( "," ) ; return t . push ( "<polygon " , 'points="' , i , '" style="' , this . getSvgStyles ( ) , '" transform="' , this . getSvgTransform ( ) , '"/>' ) , e ? e ( t . join ( "" ) ) : t . join ( "" ) } , complexity : function ( ) { return 1 } } ) , t . Triangle . fromObject = function ( e ) { return new t . Triangle ( e ) } } ( typeof exports != "undefined" ? exports : this ) , function ( e ) { "use strict" ; var t = e . fabric || ( e . fabric = { } ) , n = Math . PI * 2 , r = t . util . object . extend ; if ( t . Ellipse ) { t . warn ( "fabric.Ellipse is already defined." ) ; return } t . Ellipse = t . util . createClass ( t . Object , { type : "ellipse" , rx : 0 , ry : 0 , initialize : function ( e ) { e = e || { } , this . callSuper ( "initialize" , e ) , this . set ( "rx" , e . rx || 0 ) , this . set ( "ry" , e . ry || 0 ) , this . set ( "width" , this . get ( "rx" ) * 2 ) , this . set ( "height" , this . get ( "ry" ) * 2 ) } , toObject : function ( e ) { return r ( this . callSuper ( "toObject" , e ) , { rx : this . get ( "rx" ) , ry : this . get ( "ry" ) } ) } , toSVG : function ( e ) { var t = this . _createBaseSVGMarkup ( ) , n = 0 , r = 0 ; return this . group && ( n = this . left + this . rx , r = this . top + this . ry ) , t . push ( "<ellipse " , 'cx="' , n , '" cy="' , r , '" ' , 'rx="' , this . rx , '" ry="' , this . ry , '" style="' , this . getSvgStyles ( ) , '" transform="' , this . getSvgTransform ( ) , this . getSvgTransformMatrix ( ) , '"/>\n' ) , e ? e ( t . join ( "" ) ) : t . join ( "" ) } , _render : function ( e , t ) { e . beginPath ( ) , e . save ( ) , e . transform ( 1 , 0 , 0 , this . ry / this . rx , 0 , 0 ) , e . arc ( t ? this . left + this . rx : 0 , t ? ( this . top + this . ry ) * this . rx / this . ry : 0 , this . rx , 0 , n , ! 1 ) , e . restore ( ) , this . _renderFill ( e ) , this . _renderStroke ( e ) } , complexity : function ( ) { return 1 } } ) , t . Ellipse . ATTRIBUTE _NAMES = t . SHARED _ATTRIBUTES . concat ( "cx cy rx ry" . split ( " " ) ) , t . Ellipse . fromElement = function ( e , n ) { n || ( n = { } ) ; var i = t . parseAttributes ( e , t . Ellipse . ATTRIBUTE _NAMES ) ; i . left = i . left || 0 , i . top = i . top || 0 ; var s = new t . Ellipse ( r ( i , n ) ) ; return s . top -= s . ry , s . left -= s . rx , s } , t . Ellipse . fromObject = function ( e ) { return new t . Ellipse ( e ) } } ( typeof exports != "undefined" ? exports : this ) , function ( e ) { "use strict" ; var t = e . fabric || ( e . fabric = { } ) , n = t . util . object . extend ; if ( t . Rect ) { console . warn ( "fabric.Rect is already defined" ) ; return } var r = t . Object . prototype . stateProperties . concat ( ) ; r . push ( "rx" , "ry" , "x" , "y" ) , t . Rect = t . util . createClass ( t . Object , { stateProperties : r , type : "rect" , rx : 0 , ry : 0 , strokeDashArray : null , initialize : function ( e ) { e = e || { } , this . callSuper ( "initialize" , e ) , this . _initRxRy ( ) } , _initRxRy : function ( ) { th
e . fabric || ( e . fabric = { } ) , n = t . util . object . extend ; t . Image . filters . Mask = t . util . createClass ( t . Image . filters . BaseFilter , { type : "Mask" , initialize : function ( e ) { e = e || { } , this . mask = e . mask , this . channel = [ 0 , 1 , 2 , 3 ] . indexOf ( e . channel ) > - 1 ? e . channel : 0 } , applyTo : function ( e ) { if ( ! this . mask ) return ; var n = e . getContext ( "2d" ) , r = n . getImageData ( 0 , 0 , e . width , e . height ) , i = r . data , s = this . mask . getElement ( ) , o = t . util . createCanvasElement ( ) , u = this . channel , a , f = r . width * r . height * 4 ; o . width = s . width , o . height = s . height , o . getContext ( "2d" ) . drawImage ( s , 0 , 0 , s . width , s . height ) ; var l = o . getContext ( "2d" ) . getImageData ( 0 , 0 , s . width , s . height ) , c = l . data ; for ( a = 0 ; a < f ; a += 4 ) i [ a + 3 ] = c [ a + u ] ; n . putImageData ( r , 0 , 0 ) } , toObject : function ( ) { return n ( this . callSuper ( "toObject" ) , { mask : this . mask . toObject ( ) , channel : this . channel } ) } } ) , t . Image . filters . Mask . fromObject = function ( e , n ) { t . util . loadImage ( e . mask . src , function ( r ) { e . mask = new t . Image ( r , e . mask ) , n && n ( new t . Image . filters . Mask ( e ) ) } ) } , t . Image . filters . Mask . async = ! 0 } ( typeof exports != "undefined" ? exports : this ) , function ( e ) { "use strict" ; var t = e . fabric || ( e . fabric = { } ) , n = t . util . object . extend ; t . Image . filters . Noise = t . util . createClass ( t . Image . filters . BaseFilter , { type : "Noise" , initialize : function ( e ) { e = e || { } , this . noise = e . noise || 0 } , applyTo : function ( e ) { var t = e . getContext ( "2d" ) , n = t . getImageData ( 0 , 0 , e . width , e . height ) , r = n . data , i = this . noise , s ; for ( var o = 0 , u = r . length ; o < u ; o += 4 ) s = ( . 5 - Math . random ( ) ) * i , r [ o ] += s , r [ o + 1 ] += s , r [ o + 2 ] += s ; t . putImageData ( n , 0 , 0 ) } , toObject : function ( ) { return n ( this . callSuper ( "toObject" ) , { noise : this . noise } ) } } ) , t . Image . filters . Noise . fromObject = function ( e ) { return new t . Image . filters . Noise ( e ) } } ( typeof exports != "undefined" ? exports : this ) , function ( e ) { "use strict" ; var t = e . fabric || ( e . fabric = { } ) , n = t . util . object . extend ; t . Image . filters . Pixelate = t . util . createClass ( t . Image . filters . BaseFilter , { type : "Pixelate" , initialize : function ( e ) { e = e || { } , this . blocksize = e . blocksize || 4 } , applyTo : function ( e ) { var t = e . getContext ( "2d" ) , n = t . getImageData ( 0 , 0 , e . width , e . height ) , r = n . data , i = n . height , s = n . width , o , u , a , f , l , c , h ; for ( u = 0 ; u < i ; u += this . blocksize ) for ( a = 0 ; a < s ; a += this . blocksize ) { o = u * 4 * s + a * 4 , f = r [ o ] , l = r [ o + 1 ] , c = r [ o + 2 ] , h = r [ o + 3 ] ; for ( var p = u , d = u + this . blocksize ; p < d ; p ++ ) for ( var v = a , m = a + this . blocksize ; v < m ; v ++ ) o = p * 4 * s + v * 4 , r [ o ] = f , r [ o + 1 ] = l , r [ o + 2 ] = c , r [ o + 3 ] = h } t . putImageData ( n , 0 , 0 ) } , toObject : function ( ) { return n ( this . callSuper ( "toObject" ) , { blocksize : this . blocksize } ) } } ) , t . Image . filters . Pixelate . fromObject = function ( e ) { return new t . Image . filters . Pixelate ( e ) } } ( typeof exports != "undefined" ? exports : this ) , function ( e ) { "use strict" ; var t = e . fabric || ( e . fabric = { } ) , n = t . util . object . extend ; t . Image . filters . RemoveWhite = t . util . createClass ( t . Image . filters . BaseFilter , { type : "RemoveWhite" , initialize : function ( e ) { e = e || { } , this . threshold = e . threshold || 30 , this . distance = e . distance || 20 } , applyTo : function ( e ) { var t = e . getContext ( "2d" ) , n = t . getImageData ( 0 , 0 , e . width , e . height ) , r = n . data , i = this . threshold , s = this . distance , o = 255 - i , u = Math . abs , a , f , l ; for ( var c = 0 , h = r . length ; c < h ; c += 4 ) a = r [ c ] , f = r [ c + 1 ] , l = r [ c + 2 ] , a > o && f > o && l > o && u ( a - f ) < s && u ( a - l ) < s && u ( f - l ) < s && ( r [ c + 3 ] = 1 ) ; t . putImageData ( n , 0 , 0 ) } , toObject : function ( ) { return n ( this . callSuper ( "toObject" ) , { threshold : this . threshold , distance : this . distance } ) } } ) , t . Image . filters . RemoveWhite . fromObject = function ( e ) { return new t . Image . filters . RemoveWhite ( e ) } } ( typeof exports != "undefined" ? exports : this ) , function ( e ) { "use strict" ; var t = e . fabric || ( e . fabric = { } ) ; t . Image . filters . Sepia = t . util . createClass ( t . Image . filters . BaseFilter , { type : "Sepia" , applyTo : function ( e ) { var t = e . getContext ( "2d" ) , n = t . getImageData ( 0 , 0 , e . width , e . height ) , r = n . data , i = r . length , s , o ; for ( s = 0 ; s < i ; s += 4 ) o = . 3 * r [ s ] + . 59 * r [ s + 1 ] + . 11 * r [ s + 2 ] , r [ s ] = o + 100 , r [ s + 1 ] = o + 50 , r [ s + 2 ] = o + 255 ; t . putImageData ( n , 0 , 0 ) } } ) , t . Image . filters . Sepia . fromObject = function ( ) { return new t . Image . filters . Sepia } } ( typeof exports != "undefined" ? exports : this ) , function ( e ) { "use strict" ; var t = e . fabric || ( e . fabric = { } ) ; t . Image . filters . Sepia2 = t . util . createClass ( t . Image . filters . BaseFilter , { type : "Sepia2" , applyTo : function ( e ) { var t = e . getContext ( "2d" ) , n = t . getImageData ( 0 , 0 , e . width , e . height ) , r = n . data , i = r . length , s , o , u , a ; for ( s = 0 ; s < i ; s += 4 ) o = r [ s ] , u = r [ s + 1 ] , a = r [ s + 2 ] , r [ s ] = ( o * . 393 + u * . 769 + a * . 189 ) / 1.351 , r [ s + 1 ] = ( o * . 349 + u * . 686 + a * . 168 ) / 1.203 , r [ s + 2 ] = ( o * . 27
n ) ) && n > - 1 ) t ++ , n -- ; return e - t } , findWordBoundaryRight : function ( e ) { var t = 0 , n = e ; if ( this . _reSpace . test ( this . text . charAt ( n ) ) ) while ( this . _reSpace . test ( this . text . charAt ( n ) ) ) t ++ , n ++ ; while ( /\S/ . test ( this . text . charAt ( n ) ) && n < this . text . length ) t ++ , n ++ ; return e + t } , findLineBoundaryLeft : function ( e ) { var t = 0 , n = e - 1 ; while ( ! /\n/ . test ( this . text . charAt ( n ) ) && n > - 1 ) t ++ , n -- ; return e - t } , findLineBoundaryRight : function ( e ) { var t = 0 , n = e ; while ( ! /\n/ . test ( this . text . charAt ( n ) ) && n < this . text . length ) t ++ , n ++ ; return e + t } , getNumNewLinesInSelectedText : function ( ) { var e = this . getSelectedText ( ) , t = 0 ; for ( var n = 0 , r = e . split ( "" ) , i = r . length ; n < i ; n ++ ) r [ n ] === "\n" && t ++ ; return t } , searchWordBoundary : function ( e , t ) { var n = this . _reSpace . test ( this . text . charAt ( e ) ) ? e - 1 : e , r = this . text . charAt ( n ) , i = /[ \n\.,;!\?\-]/ ; while ( ! i . test ( r ) && n > 0 && n < this . text . length ) n += t , r = this . text . charAt ( n ) ; return i . test ( r ) && r !== "\n" && ( n += t === 1 ? 0 : 1 ) , n } , selectWord : function ( e ) { var t = this . searchWordBoundary ( e , - 1 ) , n = this . searchWordBoundary ( e , 1 ) ; this . setSelectionStart ( t ) , this . setSelectionEnd ( n ) , this . initDelayedCursor ( ! 0 ) } , selectLine : function ( e ) { var t = this . findLineBoundaryLeft ( e ) , n = this . findLineBoundaryRight ( e ) ; this . setSelectionStart ( t ) , this . setSelectionEnd ( n ) , this . initDelayedCursor ( ! 0 ) } , enterEditing : function ( ) { if ( this . isEditing || ! this . editable ) return ; return this . exitEditingOnOthers ( ) , this . isEditing = ! 0 , this . initHiddenTextarea ( ) , this . _updateTextarea ( ) , this . _saveEditingProps ( ) , this . _setEditingProps ( ) , this . _tick ( ) , this . canvas && this . canvas . renderAll ( ) , this . fire ( "editing:entered" ) , this . canvas && this . canvas . fire ( "text:editing:entered" , { target : this } ) , this } , exitEditingOnOthers : function ( ) { fabric . IText . instances . forEach ( function ( e ) { e . selected = ! 1 , e . isEditing && e . exitEditing ( ) } , this ) } , _setEditingProps : function ( ) { this . hoverCursor = "text" , this . canvas && ( this . canvas . defaultCursor = this . canvas . moveCursor = "text" ) , this . borderColor = this . editingBorderColor , this . hasControls = this . selectable = ! 1 , this . lockMovementX = this . lockMovementY = ! 0 } , _updateTextarea : function ( ) { if ( ! this . hiddenTextarea ) return ; this . hiddenTextarea . value = this . text , this . hiddenTextarea . selectionStart = this . selectionStart } , _saveEditingProps : function ( ) { this . _savedProps = { hasControls : this . hasControls , borderColor : this . borderColor , lockMovementX : this . lockMovementX , lockMovementY : this . lockMovementY , hoverCursor : this . hoverCursor , defaultCursor : this . canvas && this . canvas . defaultCursor , moveCursor : this . canvas && this . canvas . moveCursor } } , _restoreEditingProps : function ( ) { if ( ! this . _savedProps ) return ; this . hoverCursor = this . _savedProps . overCursor , this . hasControls = this . _savedProps . hasControls , this . borderColor = this . _savedProps . borderColor , this . lockMovementX = this . _savedProps . lockMovementX , this . lockMovementY = this . _savedProps . lockMovementY , this . canvas && ( this . canvas . defaultCursor = this . _savedProps . defaultCursor , this . canvas . moveCursor = this . _savedProps . moveCursor ) } , exitEditing : function ( ) { return this . selected = ! 1 , this . isEditing = ! 1 , this . selectable = ! 0 , this . selectionEnd = this . selectionStart , this . hiddenTextarea && this . canvas && this . hiddenTextarea . parentNode . removeChild ( this . hiddenTextarea ) , this . hiddenTextarea = null , this . abortCursorAnimation ( ) , this . _restoreEditingProps ( ) , this . _currentCursorOpacity = 0 , this . fire ( "editing:exited" ) , this . canvas && this . canvas . fire ( "text:editing:exited" , { target : this } ) , this } , _removeExtraneousStyles : function ( ) { var e = this . text . split ( this . _reNewline ) ; for ( var t in this . styles ) e [ t ] || delete this . styles [ t ] } , _removeCharsFromTo : function ( e , t ) { var n = t ; while ( n !== e ) { var r = this . get2DCursorLocation ( n ) . charIndex ; n -- ; var i = this . get2DCursorLocation ( n ) . charIndex , s = i > r ; s ? this . removeStyleObject ( s , n + 1 ) : this . removeStyleObject ( this . get2DCursorLocation ( n ) . charIndex === 0 , n ) } this . text = this . text . slice ( 0 , e ) + this . text . slice ( t ) } , insertChars : function ( e ) { var t = this . text . slice ( this . selectionStart , this . selectionStart + 1 ) === "\n" ; this . text = this . text . slice ( 0 , this . selectionStart ) + e + this . text . slice ( this . selectionEnd ) , this . selectionStart === this . selectionEnd && this . insertStyleObjects ( e , t , this . copiedStyles ) , this . selectionStart += e . length , this . selectionEnd = this . selectionStart , this . canvas && this . canvas . renderAll ( ) . renderAll ( ) , this . setCoords ( ) , this . fire ( " cha
// TinyColor v1.0.0
// https://github.com/bgrins/TinyColor
// 2014-06-13, Brian Grinstead, MIT License
( function ( ) {
var trimLeft = /^[\s,#]+/ ,
trimRight = /\s+$/ ,
tinyCounter = 0 ,
math = Math ,
mathRound = math . round ,
mathMin = math . min ,
mathMax = math . max ,
mathRandom = math . random ;
var tinycolor = function tinycolor ( color , opts ) {
color = ( color ) ? color : '' ;
opts = opts || { } ;
// If input is already a tinycolor, return itself
if ( color instanceof tinycolor ) {
return color ;
}
// If we are called as a function, call using new instead
if ( ! ( this instanceof tinycolor ) ) {
return new tinycolor ( color , opts ) ;
}
var rgb = inputToRGB ( color ) ;
this . _r = rgb . r ,
this . _g = rgb . g ,
this . _b = rgb . b ,
this . _a = rgb . a ,
this . _roundA = mathRound ( 100 * this . _a ) / 100 ,
this . _format = opts . format || rgb . format ;
this . _gradientType = opts . gradientType ;
// Don't let the range of [0,255] come back in [0,1].
// Potentially lose a little bit of precision here, but will fix issues where
// .5 gets interpreted as half of the total, instead of half of 1
// If it was supposed to be 128, this was already taken care of by `inputToRgb`
if ( this . _r < 1 ) { this . _r = mathRound ( this . _r ) ; }
if ( this . _g < 1 ) { this . _g = mathRound ( this . _g ) ; }
if ( this . _b < 1 ) { this . _b = mathRound ( this . _b ) ; }
this . _ok = rgb . ok ;
this . _tc _id = tinyCounter ++ ;
} ;
tinycolor . prototype = {
isDark : function ( ) {
return this . getBrightness ( ) < 128 ;
} ,
isLight : function ( ) {
return ! this . isDark ( ) ;
} ,
isValid : function ( ) {
return this . _ok ;
} ,
getFormat : function ( ) {
return this . _format ;
} ,
getAlpha : function ( ) {
return this . _a ;
} ,
getBrightness : function ( ) {
var rgb = this . toRgb ( ) ;
return ( rgb . r * 299 + rgb . g * 587 + rgb . b * 114 ) / 1000 ;
} ,
setAlpha : function ( value ) {
this . _a = boundAlpha ( value ) ;
this . _roundA = mathRound ( 100 * this . _a ) / 100 ;
return this ;
} ,
toHsv : function ( ) {
var hsv = rgbToHsv ( this . _r , this . _g , this . _b ) ;
return { h : hsv . h * 360 , s : hsv . s , v : hsv . v , a : this . _a } ;
} ,
toHsvString : function ( ) {
var hsv = rgbToHsv ( this . _r , this . _g , this . _b ) ;
var h = mathRound ( hsv . h * 360 ) , s = mathRound ( hsv . s * 100 ) , v = mathRound ( hsv . v * 100 ) ;
return ( this . _a == 1 ) ?
"hsv(" + h + ", " + s + "%, " + v + "%)" :
"hsva(" + h + ", " + s + "%, " + v + "%, " + this . _roundA + ")" ;
} ,
toHsl : function ( ) {
var hsl = rgbToHsl ( this . _r , this . _g , this . _b ) ;
return { h : hsl . h * 360 , s : hsl . s , l : hsl . l , a : this . _a } ;
} ,
toHslString : function ( ) {
var hsl = rgbToHsl ( this . _r , this . _g , this . _b ) ;
var h = mathRound ( hsl . h * 360 ) , s = mathRound ( hsl . s * 100 ) , l = mathRound ( hsl . l * 100 ) ;
return ( this . _a == 1 ) ?
"hsl(" + h + ", " + s + "%, " + l + "%)" :
"hsla(" + h + ", " + s + "%, " + l + "%, " + this . _roundA + ")" ;
} ,
toHex : function ( allow3Char ) {
return rgbToHex ( this . _r , this . _g , this . _b , allow3Char ) ;
} ,
toHexString : function ( allow3Char ) {
return '#' + this . toHex ( allow3Char ) ;
} ,
toHex8 : function ( ) {
return rgbaToHex ( this . _r , this . _g , this . _b , this . _a ) ;
} ,
toHex8String : function ( ) {
return '#' + this . toHex8 ( ) ;
} ,
toRgb : function ( ) {
return { r : mathRound ( this . _r ) , g : mathRound ( this . _g ) , b : mathRound ( this . _b ) , a : this . _a } ;
} ,
toRgbString : function ( ) {
return ( this . _a == 1 ) ?
"rgb(" + mathRound ( this . _r ) + ", " + mathRound ( this . _g ) + ", " + mathRound ( this . _b ) + ")" :
"rgba(" + mathRound ( this . _r ) + ", " + mathRound ( this . _g ) + ", " + mathRound ( this . _b ) + ", " + this . _roundA + ")" ;
} ,
toPercentageRgb : function ( ) {
return { r : mathRound ( bound01 ( this . _r , 255 ) * 100 ) + "%" , g : mathRound ( bound01 ( this . _g , 255 ) * 100 ) + "%" , b : mathRound ( bound01 ( this . _b , 255 ) * 100 ) + "%" , a : this . _a } ;
} ,
toPercentageRgbString : function ( ) {
return ( this . _a == 1 ) ?
"rgb(" + mathRound ( bound01 ( this . _r , 255 ) * 100 ) + "%, " + mathRound ( bound01 ( this . _g , 255 ) * 100 ) + "%, " + mathRound ( bound01 ( this . _b , 255 ) * 100 ) + "%)" :
"rgba(" + mathRound ( bound01 ( this . _r , 255 ) * 100 ) + "%, " + mathRound ( bound01 ( this . _g , 255 ) * 100 ) + "%, " + mathRound ( bound01 ( this . _b , 255 ) * 100 ) + "%, " + this . _roundA + ")" ;
} ,
toName : function ( ) {
if ( this . _a === 0 ) {
return "transparent" ;
}
if ( this . _a < 1 ) {
return false ;
}
return hexNames [ rgbToHex ( this . _r , this . _g , this . _b , true ) ] || false ;
} ,
toFilter : function ( secondColor ) {
var hex8String = '#' + rgbaToHex ( this . _r , this . _g , this . _b , this . _a ) ;
var secondHex8String = hex8String ;
var gradientType = this . _gradientType ? "GradientType = 1, " : "" ;
if ( secondColor ) {
var s = tinycolor ( secondColor ) ;
secondHex8String = s . toHex8String ( ) ;
}
return "progid:DXImageTransform.Microsoft.gradient(" + gradientType + "startColorstr=" + hex8String + ",endColorstr=" + secondHex8String + ")" ;
} ,
toString : function ( format ) {
var formatSet = ! ! format ;
format = format || this . _format ;
var formattedString = false ;
var hasAlpha = this . _a < 1 && this . _a >= 0 ;
var needsAlphaFormat = ! formatSet && hasAlpha && ( format === "hex" || format === "hex6" || format === "hex3" || format === "name" ) ;
if ( needsAlphaFormat ) {
// Special case for "transparent", all other non-alpha formats
// will return rgba when there is transparency.
if ( format === "name" && this . _a === 0 ) {
return this . toName ( ) ;
}
return this . toRgbString ( ) ;
}
if ( format === "rgb" ) {
formattedString = this . toRgbString ( ) ;
}
if ( format === "prgb" ) {
formattedString = this . toPercentageRgbString ( ) ;
}
if ( format === "hex" || format === "hex6" ) {
formattedString = this . toHexString ( ) ;
}
if ( format === "hex3" ) {
formattedString = this . toHexString ( true ) ;
}
if ( format === "hex8" ) {
formattedString = this . toHex8String ( ) ;
}
if ( format === "name" ) {
formattedString = this . toName ( ) ;
}
if ( format === "hsl" ) {
formattedString = this . toHslString ( ) ;
}
if ( format === "hsv" ) {
formattedString = this . toHsvString ( ) ;
}
return formattedString || this . toHexString ( ) ;
} ,
_applyModification : function ( fn , args ) {
var color = fn . apply ( null , [ this ] . concat ( [ ] . slice . call ( args ) ) ) ;
this . _r = color . _r ;
this . _g = color . _g ;
this . _b = color . _b ;
this . setAlpha ( color . _a ) ;
return this ;
} ,
lighten : function ( ) {
return this . _applyModification ( lighten , arguments ) ;
} ,
brighten : function ( ) {
return this . _applyModification ( brighten , arguments ) ;
} ,
darken : function ( ) {
return this . _applyModification ( darken , arguments ) ;
} ,
desaturate : function ( ) {
return this . _applyModification ( desaturate , arguments ) ;
} ,
saturate : function ( ) {
return this . _applyModification ( saturate , arguments ) ;
} ,
greyscale : function ( ) {
return this . _applyModification ( greyscale , arguments ) ;
} ,
spin : function ( ) {
return this . _applyModification ( spin , arguments ) ;
} ,
_applyCombination : function ( fn , args ) {
return fn . apply ( null , [ this ] . concat ( [ ] . slice . call ( args ) ) ) ;
} ,
analogous : function ( ) {
return this . _applyCombination ( analogous , arguments ) ;
} ,
complement : function ( ) {
return this . _applyCombination ( complement , arguments ) ;
} ,
monochromatic : function ( ) {
return this . _applyCombination ( monochromatic , arguments ) ;
} ,
splitcomplement : function ( ) {
return this . _applyCombination ( splitcomplement , arguments ) ;
} ,
triad : function ( ) {
return this . _applyCombination ( triad , arguments ) ;
} ,
tetrad : function ( ) {
return this . _applyCombination ( tetrad , arguments ) ;
}
} ;
// If input is an object, force 1 into "1.0" to handle ratios properly
// String input requires "1.0" as input, so 1 will be treated as 1
tinycolor . fromRatio = function ( color , opts ) {
if ( typeof color == "object" ) {
var newColor = { } ;
for ( var i in color ) {
if ( color . hasOwnProperty ( i ) ) {
if ( i === "a" ) {
newColor [ i ] = color [ i ] ;
}
else {
newColor [ i ] = convertToPercentage ( color [ i ] ) ;
}
}
}
color = newColor ;
}
return tinycolor ( color , opts ) ;
} ;
// Given a string or object, convert that input to RGB
// Possible string inputs:
//
// "red"
// "#f00" or "f00"
// "#ff0000" or "ff0000"
// "#ff000000" or "ff000000"
// "rgb 255 0 0" or "rgb (255, 0, 0)"
// "rgb 1.0 0 0" or "rgb (1, 0, 0)"
// "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
// "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
// "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
// "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
// "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
//
function inputToRGB ( color ) {
var rgb = { r : 0 , g : 0 , b : 0 } ;
var a = 1 ;
var ok = false ;
var format = false ;
if ( typeof color == "string" ) {
color = stringInputToObject ( color ) ;
}
if ( typeof color == "object" ) {
if ( color . hasOwnProperty ( "r" ) && color . hasOwnProperty ( "g" ) && color . hasOwnProperty ( "b" ) ) {
rgb = rgbToRgb ( color . r , color . g , color . b ) ;
ok = true ;
format = String ( color . r ) . substr ( - 1 ) === "%" ? "prgb" : "rgb" ;
}
else if ( color . hasOwnProperty ( "h" ) && color . hasOwnProperty ( "s" ) && color . hasOwnProperty ( "v" ) ) {
color . s = convertToPercentage ( color . s ) ;
color . v = convertToPercentage ( color . v ) ;
rgb = hsvToRgb ( color . h , color . s , color . v ) ;
ok = true ;
format = "hsv" ;
}
else if ( color . hasOwnProperty ( "h" ) && color . hasOwnProperty ( "s" ) && color . hasOwnProperty ( "l" ) ) {
color . s = convertToPercentage ( color . s ) ;
color . l = convertToPercentage ( color . l ) ;
rgb = hslToRgb ( color . h , color . s , color . l ) ;
ok = true ;
format = "hsl" ;
}
if ( color . hasOwnProperty ( "a" ) ) {
a = color . a ;
}
}
a = boundAlpha ( a ) ;
return {
ok : ok ,
format : color . format || format ,
r : mathMin ( 255 , mathMax ( rgb . r , 0 ) ) ,
g : mathMin ( 255 , mathMax ( rgb . g , 0 ) ) ,
b : mathMin ( 255 , mathMax ( rgb . b , 0 ) ) ,
a : a
} ;
}
// Conversion Functions
// --------------------
// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
// <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
// `rgbToRgb`
// Handle bounds / percentage checking to conform to CSS color spec
// <http://www.w3.org/TR/css3-color/>
// *Assumes:* r, g, b in [0, 255] or [0, 1]
// *Returns:* { r, g, b } in [0, 255]
function rgbToRgb ( r , g , b ) {
return {
r : bound01 ( r , 255 ) * 255 ,
g : bound01 ( g , 255 ) * 255 ,
b : bound01 ( b , 255 ) * 255
} ;
}
// `rgbToHsl`
// Converts an RGB color value to HSL.
// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
// *Returns:* { h, s, l } in [0,1]
function rgbToHsl ( r , g , b ) {
r = bound01 ( r , 255 ) ;
g = bound01 ( g , 255 ) ;
b = bound01 ( b , 255 ) ;
var max = mathMax ( r , g , b ) , min = mathMin ( r , g , b ) ;
var h , s , l = ( max + min ) / 2 ;
if ( max == min ) {
h = s = 0 ; // achromatic
}
else {
var d = max - min ;
s = l > 0.5 ? d / ( 2 - max - min ) : d / ( max + min ) ;
switch ( max ) {
case r : h = ( g - b ) / d + ( g < b ? 6 : 0 ) ; break ;
case g : h = ( b - r ) / d + 2 ; break ;
case b : h = ( r - g ) / d + 4 ; break ;
}
h /= 6 ;
}
return { h : h , s : s , l : l } ;
}
// `hslToRgb`
// Converts an HSL color value to RGB.
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
// *Returns:* { r, g, b } in the set [0, 255]
function hslToRgb ( h , s , l ) {
var r , g , b ;
h = bound01 ( h , 360 ) ;
s = bound01 ( s , 100 ) ;
l = bound01 ( l , 100 ) ;
function hue2rgb ( p , q , t ) {
if ( t < 0 ) t += 1 ;
if ( t > 1 ) t -= 1 ;
if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t ;
if ( t < 1 / 2 ) return q ;
if ( t < 2 / 3 ) return p + ( q - p ) * ( 2 / 3 - t ) * 6 ;
return p ;
}
if ( s === 0 ) {
r = g = b = l ; // achromatic
}
else {
var q = l < 0.5 ? l * ( 1 + s ) : l + s - l * s ;
var p = 2 * l - q ;
r = hue2rgb ( p , q , h + 1 / 3 ) ;
g = hue2rgb ( p , q , h ) ;
b = hue2rgb ( p , q , h - 1 / 3 ) ;
}
return { r : r * 255 , g : g * 255 , b : b * 255 } ;
}
// `rgbToHsv`
// Converts an RGB color value to HSV
// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
// *Returns:* { h, s, v } in [0,1]
function rgbToHsv ( r , g , b ) {
r = bound01 ( r , 255 ) ;
g = bound01 ( g , 255 ) ;
b = bound01 ( b , 255 ) ;
var max = mathMax ( r , g , b ) , min = mathMin ( r , g , b ) ;
var h , s , v = max ;
var d = max - min ;
s = max === 0 ? 0 : d / max ;
if ( max == min ) {
h = 0 ; // achromatic
}
else {
switch ( max ) {
case r : h = ( g - b ) / d + ( g < b ? 6 : 0 ) ; break ;
case g : h = ( b - r ) / d + 2 ; break ;
case b : h = ( r - g ) / d + 4 ; break ;
}
h /= 6 ;
}
return { h : h , s : s , v : v } ;
}
// `hsvToRgb`
// Converts an HSV color value to RGB.
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
// *Returns:* { r, g, b } in the set [0, 255]
function hsvToRgb ( h , s , v ) {
h = bound01 ( h , 360 ) * 6 ;
s = bound01 ( s , 100 ) ;
v = bound01 ( v , 100 ) ;
var i = math . floor ( h ) ,
f = h - i ,
p = v * ( 1 - s ) ,
q = v * ( 1 - f * s ) ,
t = v * ( 1 - ( 1 - f ) * s ) ,
mod = i % 6 ,
r = [ v , q , p , p , t , v ] [ mod ] ,
g = [ t , v , v , q , p , p ] [ mod ] ,
b = [ p , p , t , v , v , q ] [ mod ] ;
return { r : r * 255 , g : g * 255 , b : b * 255 } ;
}
// `rgbToHex`
// Converts an RGB color to hex
// Assumes r, g, and b are contained in the set [0, 255]
// Returns a 3 or 6 character hex
function rgbToHex ( r , g , b , allow3Char ) {
var hex = [
pad2 ( mathRound ( r ) . toString ( 16 ) ) ,
pad2 ( mathRound ( g ) . toString ( 16 ) ) ,
pad2 ( mathRound ( b ) . toString ( 16 ) )
] ;
// Return a 3 character hex if possible
if ( allow3Char && hex [ 0 ] . charAt ( 0 ) == hex [ 0 ] . charAt ( 1 ) && hex [ 1 ] . charAt ( 0 ) == hex [ 1 ] . charAt ( 1 ) && hex [ 2 ] . charAt ( 0 ) == hex [ 2 ] . charAt ( 1 ) ) {
return hex [ 0 ] . charAt ( 0 ) + hex [ 1 ] . charAt ( 0 ) + hex [ 2 ] . charAt ( 0 ) ;
}
return hex . join ( "" ) ;
}
// `rgbaToHex`
// Converts an RGBA color plus alpha transparency to hex
// Assumes r, g, b and a are contained in the set [0, 255]
// Returns an 8 character hex
function rgbaToHex ( r , g , b , a ) {
var hex = [
pad2 ( convertDecimalToHex ( a ) ) ,
pad2 ( mathRound ( r ) . toString ( 16 ) ) ,
pad2 ( mathRound ( g ) . toString ( 16 ) ) ,
pad2 ( mathRound ( b ) . toString ( 16 ) )
] ;
return hex . join ( "" ) ;
}
// `equals`
// Can be called with any tinycolor input
tinycolor . equals = function ( color1 , color2 ) {
if ( ! color1 || ! color2 ) { return false ; }
return tinycolor ( color1 ) . toRgbString ( ) == tinycolor ( color2 ) . toRgbString ( ) ;
} ;
tinycolor . random = function ( ) {
return tinycolor . fromRatio ( {
r : mathRandom ( ) ,
g : mathRandom ( ) ,
b : mathRandom ( )
} ) ;
} ;
// Modification Functions
// ----------------------
// Thanks to less.js for some of the basics here
// <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
function desaturate ( color , amount ) {
amount = ( amount === 0 ) ? 0 : ( amount || 10 ) ;
var hsl = tinycolor ( color ) . toHsl ( ) ;
hsl . s -= amount / 100 ;
hsl . s = clamp01 ( hsl . s ) ;
return tinycolor ( hsl ) ;
}
function saturate ( color , amount ) {
amount = ( amount === 0 ) ? 0 : ( amount || 10 ) ;
var hsl = tinycolor ( color ) . toHsl ( ) ;
hsl . s += amount / 100 ;
hsl . s = clamp01 ( hsl . s ) ;
return tinycolor ( hsl ) ;
}
function greyscale ( color ) {
return tinycolor ( color ) . desaturate ( 100 ) ;
}
function lighten ( color , amount ) {
amount = ( amount === 0 ) ? 0 : ( amount || 10 ) ;
var hsl = tinycolor ( color ) . toHsl ( ) ;
hsl . l += amount / 100 ;
hsl . l = clamp01 ( hsl . l ) ;
return tinycolor ( hsl ) ;
}
function brighten ( color , amount ) {
amount = ( amount === 0 ) ? 0 : ( amount || 10 ) ;
var rgb = tinycolor ( color ) . toRgb ( ) ;
rgb . r = mathMax ( 0 , mathMin ( 255 , rgb . r - mathRound ( 255 * - ( amount / 100 ) ) ) ) ;
rgb . g = mathMax ( 0 , mathMin ( 255 , rgb . g - mathRound ( 255 * - ( amount / 100 ) ) ) ) ;
rgb . b = mathMax ( 0 , mathMin ( 255 , rgb . b - mathRound ( 255 * - ( amount / 100 ) ) ) ) ;
return tinycolor ( rgb ) ;
}
function darken ( color , amount ) {
amount = ( amount === 0 ) ? 0 : ( amount || 10 ) ;
var hsl = tinycolor ( color ) . toHsl ( ) ;
hsl . l -= amount / 100 ;
hsl . l = clamp01 ( hsl . l ) ;
return tinycolor ( hsl ) ;
}
// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
// Values outside of this range will be wrapped into this range.
function spin ( color , amount ) {
var hsl = tinycolor ( color ) . toHsl ( ) ;
var hue = ( mathRound ( hsl . h ) + amount ) % 360 ;
hsl . h = hue < 0 ? 360 + hue : hue ;
return tinycolor ( hsl ) ;
}
// Combination Functions
// ---------------------
// Thanks to jQuery xColor for some of the ideas behind these
// <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
function complement ( color ) {
var hsl = tinycolor ( color ) . toHsl ( ) ;
hsl . h = ( hsl . h + 180 ) % 360 ;
return tinycolor ( hsl ) ;
}
function triad ( color ) {
var hsl = tinycolor ( color ) . toHsl ( ) ;
var h = hsl . h ;
return [
tinycolor ( color ) ,
tinycolor ( { h : ( h + 120 ) % 360 , s : hsl . s , l : hsl . l } ) ,
tinycolor ( { h : ( h + 240 ) % 360 , s : hsl . s , l : hsl . l } )
] ;
}
function tetrad ( color ) {
var hsl = tinycolor ( color ) . toHsl ( ) ;
var h = hsl . h ;
return [
tinycolor ( color ) ,
tinycolor ( { h : ( h + 90 ) % 360 , s : hsl . s , l : hsl . l } ) ,
tinycolor ( { h : ( h + 180 ) % 360 , s : hsl . s , l : hsl . l } ) ,
tinycolor ( { h : ( h + 270 ) % 360 , s : hsl . s , l : hsl . l } )
] ;
}
function splitcomplement ( color ) {
var hsl = tinycolor ( color ) . toHsl ( ) ;
var h = hsl . h ;
return [
tinycolor ( color ) ,
tinycolor ( { h : ( h + 72 ) % 360 , s : hsl . s , l : hsl . l } ) ,
tinycolor ( { h : ( h + 216 ) % 360 , s : hsl . s , l : hsl . l } )
] ;
}
function analogous ( color , results , slices ) {
results = results || 6 ;
slices = slices || 30 ;
var hsl = tinycolor ( color ) . toHsl ( ) ;
var part = 360 / slices ;
var ret = [ tinycolor ( color ) ] ;
for ( hsl . h = ( ( hsl . h - ( part * results >> 1 ) ) + 720 ) % 360 ; -- results ; ) {
hsl . h = ( hsl . h + part ) % 360 ;
ret . push ( tinycolor ( hsl ) ) ;
}
return ret ;
}
function monochromatic ( color , results ) {
results = results || 6 ;
var hsv = tinycolor ( color ) . toHsv ( ) ;
var h = hsv . h , s = hsv . s , v = hsv . v ;
var ret = [ ] ;
var modification = 1 / results ;
while ( results -- ) {
ret . push ( tinycolor ( { h : h , s : s , v : v } ) ) ;
v = ( v + modification ) % 1 ;
}
return ret ;
}
// Utility Functions
// ---------------------
tinycolor . mix = function ( color1 , color2 , amount ) {
amount = ( amount === 0 ) ? 0 : ( amount || 50 ) ;
var rgb1 = tinycolor ( color1 ) . toRgb ( ) ;
var rgb2 = tinycolor ( color2 ) . toRgb ( ) ;
var p = amount / 100 ;
var w = p * 2 - 1 ;
var a = rgb2 . a - rgb1 . a ;
var w1 ;
if ( w * a == - 1 ) {
w1 = w ;
} else {
w1 = ( w + a ) / ( 1 + w * a ) ;
}
w1 = ( w1 + 1 ) / 2 ;
var w2 = 1 - w1 ;
var rgba = {
r : rgb2 . r * w1 + rgb1 . r * w2 ,
g : rgb2 . g * w1 + rgb1 . g * w2 ,
b : rgb2 . b * w1 + rgb1 . b * w2 ,
a : rgb2 . a * p + rgb1 . a * ( 1 - p )
} ;
return tinycolor ( rgba ) ;
} ;
// Readability Functions
// ---------------------
// <http://www.w3.org/TR/AERT#color-contrast>
// `readability`
// Analyze the 2 colors and returns an object with the following properties:
// `brightness`: difference in brightness between the two colors
// `color`: difference in color/hue between the two colors
tinycolor . readability = function ( color1 , color2 ) {
var c1 = tinycolor ( color1 ) ;
var c2 = tinycolor ( color2 ) ;
var rgb1 = c1 . toRgb ( ) ;
var rgb2 = c2 . toRgb ( ) ;
var brightnessA = c1 . getBrightness ( ) ;
var brightnessB = c2 . getBrightness ( ) ;
var colorDiff = (
Math . max ( rgb1 . r , rgb2 . r ) - Math . min ( rgb1 . r , rgb2 . r ) +
Math . max ( rgb1 . g , rgb2 . g ) - Math . min ( rgb1 . g , rgb2 . g ) +
Math . max ( rgb1 . b , rgb2 . b ) - Math . min ( rgb1 . b , rgb2 . b )
) ;
return {
brightness : Math . abs ( brightnessA - brightnessB ) ,
color : colorDiff
} ;
} ;
// `readable`
// http://www.w3.org/TR/AERT#color-contrast
// Ensure that foreground and background color combinations provide sufficient contrast.
// *Example*
// tinycolor.isReadable("#000", "#111") => false
tinycolor . isReadable = function ( color1 , color2 ) {
var readability = tinycolor . readability ( color1 , color2 ) ;
return readability . brightness > 125 && readability . color > 500 ;
} ;
// `mostReadable`
// Given a base color and a list of possible foreground or background
// colors for that base, returns the most readable color.
// *Example*
// tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
tinycolor . mostReadable = function ( baseColor , colorList ) {
var bestColor = null ;
var bestScore = 0 ;
var bestIsReadable = false ;
for ( var i = 0 ; i < colorList . length ; i ++ ) {
// We normalize both around the "acceptable" breaking point,
// but rank brightness constrast higher than hue.
var readability = tinycolor . readability ( baseColor , colorList [ i ] ) ;
var readable = readability . brightness > 125 && readability . color > 500 ;
var score = 3 * ( readability . brightness / 125 ) + ( readability . color / 500 ) ;
if ( ( readable && ! bestIsReadable ) ||
( readable && bestIsReadable && score > bestScore ) ||
( ( ! readable ) && ( ! bestIsReadable ) && score > bestScore ) ) {
bestIsReadable = readable ;
bestScore = score ;
bestColor = tinycolor ( colorList [ i ] ) ;
}
}
return bestColor ;
} ;
// Big List of Colors
// ------------------
// <http://www.w3.org/TR/css3-color/#svg-color>
var names = tinycolor . names = {
aliceblue : "f0f8ff" ,
antiquewhite : "faebd7" ,
aqua : "0ff" ,
aquamarine : "7fffd4" ,
azure : "f0ffff" ,
beige : "f5f5dc" ,
bisque : "ffe4c4" ,
black : "000" ,
blanchedalmond : "ffebcd" ,
blue : "00f" ,
blueviolet : "8a2be2" ,
brown : "a52a2a" ,
burlywood : "deb887" ,
burntsienna : "ea7e5d" ,
cadetblue : "5f9ea0" ,
chartreuse : "7fff00" ,
chocolate : "d2691e" ,
coral : "ff7f50" ,
cornflowerblue : "6495ed" ,
cornsilk : "fff8dc" ,
crimson : "dc143c" ,
cyan : "0ff" ,
darkblue : "00008b" ,
darkcyan : "008b8b" ,
darkgoldenrod : "b8860b" ,
darkgray : "a9a9a9" ,
darkgreen : "006400" ,
darkgrey : "a9a9a9" ,
darkkhaki : "bdb76b" ,
darkmagenta : "8b008b" ,
darkolivegreen : "556b2f" ,
darkorange : "ff8c00" ,
darkorchid : "9932cc" ,
darkred : "8b0000" ,
darksalmon : "e9967a" ,
darkseagreen : "8fbc8f" ,
darkslateblue : "483d8b" ,
darkslategray : "2f4f4f" ,
darkslategrey : "2f4f4f" ,
darkturquoise : "00ced1" ,
darkviolet : "9400d3" ,
deeppink : "ff1493" ,
deepskyblue : "00bfff" ,
dimgray : "696969" ,
dimgrey : "696969" ,
dodgerblue : "1e90ff" ,
firebrick : "b22222" ,
floralwhite : "fffaf0" ,
forestgreen : "228b22" ,
fuchsia : "f0f" ,
gainsboro : "dcdcdc" ,
ghostwhite : "f8f8ff" ,
gold : "ffd700" ,
goldenrod : "daa520" ,
gray : "808080" ,
green : "008000" ,
greenyellow : "adff2f" ,
grey : "808080" ,
honeydew : "f0fff0" ,
hotpink : "ff69b4" ,
indianred : "cd5c5c" ,
indigo : "4b0082" ,
ivory : "fffff0" ,
khaki : "f0e68c" ,
lavender : "e6e6fa" ,
lavenderblush : "fff0f5" ,
lawngreen : "7cfc00" ,
lemonchiffon : "fffacd" ,
lightblue : "add8e6" ,
lightcoral : "f08080" ,
lightcyan : "e0ffff" ,
lightgoldenrodyellow : "fafad2" ,
lightgray : "d3d3d3" ,
lightgreen : "90ee90" ,
lightgrey : "d3d3d3" ,
lightpink : "ffb6c1" ,
lightsalmon : "ffa07a" ,
lightseagreen : "20b2aa" ,
lightskyblue : "87cefa" ,
lightslategray : "789" ,
lightslategrey : "789" ,
lightsteelblue : "b0c4de" ,
lightyellow : "ffffe0" ,
lime : "0f0" ,
limegreen : "32cd32" ,
linen : "faf0e6" ,
magenta : "f0f" ,
maroon : "800000" ,
mediumaquamarine : "66cdaa" ,
mediumblue : "0000cd" ,
mediumorchid : "ba55d3" ,
mediumpurple : "9370db" ,
mediumseagreen : "3cb371" ,
mediumslateblue : "7b68ee" ,
mediumspringgreen : "00fa9a" ,
mediumturquoise : "48d1cc" ,
mediumvioletred : "c71585" ,
midnightblue : "191970" ,
mintcream : "f5fffa" ,
mistyrose : "ffe4e1" ,
moccasin : "ffe4b5" ,
navajowhite : "ffdead" ,
navy : "000080" ,
oldlace : "fdf5e6" ,
olive : "808000" ,
olivedrab : "6b8e23" ,
orange : "ffa500" ,
orangered : "ff4500" ,
orchid : "da70d6" ,
palegoldenrod : "eee8aa" ,
palegreen : "98fb98" ,
paleturquoise : "afeeee" ,
palevioletred : "db7093" ,
papayawhip : "ffefd5" ,
peachpuff : "ffdab9" ,
peru : "cd853f" ,
pink : "ffc0cb" ,
plum : "dda0dd" ,
powderblue : "b0e0e6" ,
purple : "800080" ,
red : "f00" ,
rosybrown : "bc8f8f" ,
royalblue : "4169e1" ,
saddlebrown : "8b4513" ,
salmon : "fa8072" ,
sandybrown : "f4a460" ,
seagreen : "2e8b57" ,
seashell : "fff5ee" ,
sienna : "a0522d" ,
silver : "c0c0c0" ,
skyblue : "87ceeb" ,
slateblue : "6a5acd" ,
slategray : "708090" ,
slategrey : "708090" ,
snow : "fffafa" ,
springgreen : "00ff7f" ,
steelblue : "4682b4" ,
tan : "d2b48c" ,
teal : "008080" ,
thistle : "d8bfd8" ,
tomato : "ff6347" ,
turquoise : "40e0d0" ,
violet : "ee82ee" ,
wheat : "f5deb3" ,
white : "fff" ,
whitesmoke : "f5f5f5" ,
yellow : "ff0" ,
yellowgreen : "9acd32"
} ;
// Make it easy to access colors via `hexNames[hex]`
var hexNames = tinycolor . hexNames = flip ( names ) ;
// Utilities
// ---------
// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
function flip ( o ) {
var flipped = { } ;
for ( var i in o ) {
if ( o . hasOwnProperty ( i ) ) {
flipped [ o [ i ] ] = i ;
}
}
return flipped ;
}
// Return a valid alpha value [0,1] with all invalid values being set to 1
function boundAlpha ( a ) {
a = parseFloat ( a ) ;
if ( isNaN ( a ) || a < 0 || a > 1 ) {
a = 1 ;
}
return a ;
}
// Take input from [0, n] and return it as [0, 1]
function bound01 ( n , max ) {
if ( isOnePointZero ( n ) ) { n = "100%" ; }
var processPercent = isPercentage ( n ) ;
n = mathMin ( max , mathMax ( 0 , parseFloat ( n ) ) ) ;
// Automatically convert percentage into number
if ( processPercent ) {
n = parseInt ( n * max , 10 ) / 100 ;
}
// Handle floating point rounding errors
if ( ( math . abs ( n - max ) < 0.000001 ) ) {
return 1 ;
}
// Convert into [0, 1] range if it isn't already
return ( n % max ) / parseFloat ( max ) ;
}
// Force a number between 0 and 1
function clamp01 ( val ) {
return mathMin ( 1 , mathMax ( 0 , val ) ) ;
}
// Parse a base-16 hex value into a base-10 integer
function parseIntFromHex ( val ) {
return parseInt ( val , 16 ) ;
}
// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
// <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
function isOnePointZero ( n ) {
return typeof n == "string" && n . indexOf ( '.' ) != - 1 && parseFloat ( n ) === 1 ;
}
// Check to see if string passed in is a percentage
function isPercentage ( n ) {
return typeof n === "string" && n . indexOf ( '%' ) != - 1 ;
}
// Force a hex value to have 2 characters
function pad2 ( c ) {
return c . length == 1 ? '0' + c : '' + c ;
}
// Replace a decimal with it's percentage value
function convertToPercentage ( n ) {
if ( n <= 1 ) {
n = ( n * 100 ) + "%" ;
}
return n ;
}
// Converts a decimal to a hex value
function convertDecimalToHex ( d ) {
return Math . round ( parseFloat ( d ) * 255 ) . toString ( 16 ) ;
}
// Converts a hex value to a decimal
function convertHexToDecimal ( h ) {
return ( parseIntFromHex ( h ) / 255 ) ;
}
var matchers = ( function ( ) {
// <http://www.w3.org/TR/css3-values/#integers>
var CSS _INTEGER = "[-\\+]?\\d+%?" ;
// <http://www.w3.org/TR/css3-values/#number-value>
var CSS _NUMBER = "[-\\+]?\\d*\\.\\d+%?" ;
// Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
var CSS _UNIT = "(?:" + CSS _NUMBER + ")|(?:" + CSS _INTEGER + ")" ;
// Actual matching.
// Parentheses and commas are optional, but not required.
// Whitespace can take the place of commas or opening paren
var PERMISSIVE _MATCH3 = "[\\s|\\(]+(" + CSS _UNIT + ")[,|\\s]+(" + CSS _UNIT + ")[,|\\s]+(" + CSS _UNIT + ")\\s*\\)?" ;
var PERMISSIVE _MATCH4 = "[\\s|\\(]+(" + CSS _UNIT + ")[,|\\s]+(" + CSS _UNIT + ")[,|\\s]+(" + CSS _UNIT + ")[,|\\s]+(" + CSS _UNIT + ")\\s*\\)?" ;
return {
rgb : new RegExp ( "rgb" + PERMISSIVE _MATCH3 ) ,
rgba : new RegExp ( "rgba" + PERMISSIVE _MATCH4 ) ,
hsl : new RegExp ( "hsl" + PERMISSIVE _MATCH3 ) ,
hsla : new RegExp ( "hsla" + PERMISSIVE _MATCH4 ) ,
hsv : new RegExp ( "hsv" + PERMISSIVE _MATCH3 ) ,
hex3 : /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/ ,
hex6 : /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ ,
hex8 : /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
} ;
} ) ( ) ;
// `stringInputToObject`
// Permissive string parsing. Take in a number of formats, and output an object
// based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
function stringInputToObject ( color ) {
color = color . replace ( trimLeft , '' ) . replace ( trimRight , '' ) . toLowerCase ( ) ;
var named = false ;
if ( names [ color ] ) {
color = names [ color ] ;
named = true ;
}
else if ( color == 'transparent' ) {
return { r : 0 , g : 0 , b : 0 , a : 0 , format : "name" } ;
}
// Try to match string input using regular expressions.
// Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
// Just return an object and let the conversion functions handle that.
// This way the result will be the same whether the tinycolor is initialized with string or object.
var match ;
if ( ( match = matchers . rgb . exec ( color ) ) ) {
return { r : match [ 1 ] , g : match [ 2 ] , b : match [ 3 ] } ;
}
if ( ( match = matchers . rgba . exec ( color ) ) ) {
return { r : match [ 1 ] , g : match [ 2 ] , b : match [ 3 ] , a : match [ 4 ] } ;
}
if ( ( match = matchers . hsl . exec ( color ) ) ) {
return { h : match [ 1 ] , s : match [ 2 ] , l : match [ 3 ] } ;
}
if ( ( match = matchers . hsla . exec ( color ) ) ) {
return { h : match [ 1 ] , s : match [ 2 ] , l : match [ 3 ] , a : match [ 4 ] } ;
}
if ( ( match = matchers . hsv . exec ( color ) ) ) {
return { h : match [ 1 ] , s : match [ 2 ] , v : match [ 3 ] } ;
}
if ( ( match = matchers . hex8 . exec ( color ) ) ) {
return {
a : convertHexToDecimal ( match [ 1 ] ) ,
r : parseIntFromHex ( match [ 2 ] ) ,
g : parseIntFromHex ( match [ 3 ] ) ,
b : parseIntFromHex ( match [ 4 ] ) ,
format : named ? "name" : "hex8"
} ;
}
if ( ( match = matchers . hex6 . exec ( color ) ) ) {
return {
r : parseIntFromHex ( match [ 1 ] ) ,
g : parseIntFromHex ( match [ 2 ] ) ,
b : parseIntFromHex ( match [ 3 ] ) ,
format : named ? "name" : "hex"
} ;
}
if ( ( match = matchers . hex3 . exec ( color ) ) ) {
return {
r : parseIntFromHex ( match [ 1 ] + '' + match [ 1 ] ) ,
g : parseIntFromHex ( match [ 2 ] + '' + match [ 2 ] ) ,
b : parseIntFromHex ( match [ 3 ] + '' + match [ 3 ] ) ,
format : named ? "name" : "hex"
} ;
}
return false ;
}
// Node: Export function
if ( typeof module !== "undefined" && module . exports ) {
module . exports = tinycolor ;
}
// AMD/requirejs: Define the module
else if ( typeof define === 'function' && define . amd ) {
define ( function ( ) { return tinycolor ; } ) ;
}
// Browser: Expose to window
else {
window . tinycolor = tinycolor ;
}
} ) ( ) ;
2014-09-30 04:26:34 +00:00
/ * !
* Bootstrap v3 . 2.0 ( http : //getbootstrap.com)
* Copyright 2011 - 2014 Twitter , Inc .
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/master/LICENSE)
* /
if ( "undefined" == typeof jQuery ) throw new Error ( "Bootstrap's JavaScript requires jQuery" ) ; + function ( a ) { "use strict" ; function b ( ) { var a = document . createElement ( "bootstrap" ) , b = { WebkitTransition : "webkitTransitionEnd" , MozTransition : "transitionend" , OTransition : "oTransitionEnd otransitionend" , transition : "transitionend" } ; for ( var c in b ) if ( void 0 !== a . style [ c ] ) return { end : b [ c ] } ; return ! 1 } a . fn . emulateTransitionEnd = function ( b ) { var c = ! 1 , d = this ; a ( this ) . one ( "bsTransitionEnd" , function ( ) { c = ! 0 } ) ; var e = function ( ) { c || a ( d ) . trigger ( a . support . transition . end ) } ; return setTimeout ( e , b ) , this } , a ( function ( ) { a . support . transition = b ( ) , a . support . transition && ( a . event . special . bsTransitionEnd = { bindType : a . support . transition . end , delegateType : a . support . transition . end , handle : function ( b ) { return a ( b . target ) . is ( this ) ? b . handleObj . handler . apply ( this , arguments ) : void 0 } } ) } ) } ( jQuery ) , + function ( a ) { "use strict" ; function b ( b ) { return this . each ( function ( ) { var c = a ( this ) , e = c . data ( "bs.alert" ) ; e || c . data ( "bs.alert" , e = new d ( this ) ) , "string" == typeof b && e [ b ] . call ( c ) } ) } var c = '[data-dismiss="alert"]' , d = function ( b ) { a ( b ) . on ( "click" , c , this . close ) } ; d . VERSION = "3.2.0" , d . prototype . close = function ( b ) { function c ( ) { f . detach ( ) . trigger ( "closed.bs.alert" ) . remove ( ) } var d = a ( this ) , e = d . attr ( "data-target" ) ; e || ( e = d . attr ( "href" ) , e = e && e . replace ( /.*(?=#[^\s]*$)/ , "" ) ) ; var f = a ( e ) ; b && b . preventDefault ( ) , f . length || ( f = d . hasClass ( "alert" ) ? d : d . parent ( ) ) , f . trigger ( b = a . Event ( "close.bs.alert" ) ) , b . isDefaultPrevented ( ) || ( f . removeClass ( "in" ) , a . support . transition && f . hasClass ( "fade" ) ? f . one ( "bsTransitionEnd" , c ) . emulateTransitionEnd ( 150 ) : c ( ) ) } ; var e = a . fn . alert ; a . fn . alert = b , a . fn . alert . Constructor = d , a . fn . alert . noConflict = function ( ) { return a . fn . alert = e , this } , a ( document ) . on ( "click.bs.alert.data-api" , c , d . prototype . close ) } ( jQuery ) , + function ( a ) { "use strict" ; function b ( b ) { return this . each ( function ( ) { var d = a ( this ) , e = d . data ( "bs.button" ) , f = "object" == typeof b && b ; e || d . data ( "bs.button" , e = new c ( this , f ) ) , "toggle" == b ? e . toggle ( ) : b && e . setState ( b ) } ) } var c = function ( b , d ) { this . $element = a ( b ) , this . options = a . extend ( { } , c . DEFAULTS , d ) , this . isLoading = ! 1 } ; c . VERSION = "3.2.0" , c . DEFAULTS = { loadingText : "loading..." } , c . prototype . setState = function ( b ) { var c = "disabled" , d = this . $element , e = d . is ( "input" ) ? "val" : "html" , f = d . data ( ) ; b += "Text" , null == f . resetText && d . data ( "resetText" , d [ e ] ( ) ) , d [ e ] ( null == f [ b ] ? this . options [ b ] : f [ b ] ) , setTimeout ( a . proxy ( function ( ) { "loadingText" == b ? ( this . isLoading = ! 0 , d . addClass ( c ) . attr ( c , c ) ) : this . isLoading && ( this . isLoading = ! 1 , d . removeClass ( c ) . removeAttr ( c ) ) } , this ) , 0 ) } , c . prototype . toggle = function ( ) { var a = ! 0 , b = this . $element . closest ( '[data-toggle="buttons"]' ) ; if ( b . length ) { var c = this . $element . find ( "input" ) ; "radio" == c . prop ( "type" ) && ( c . prop ( "checked" ) && this . $element . hasClass ( "active" ) ? a = ! 1 : b . find ( ".active" ) . removeClass ( "active" ) ) , a && c . prop ( "checked" , ! this . $element . hasClass ( "active" ) ) . trigger ( "change" ) } a && this . $element . toggleClass ( "active" ) } ; var d = a . fn . button ; a . fn . button = b , a . fn . button . Constructor = c , a . fn . button . noConflict = function ( ) { return a . fn . button = d , this } , a ( document ) . on ( "click.bs.button.data-api" , '[data-toggle^="button"]' , function ( c ) { var d = a ( c . target ) ; d . hasClass ( "btn" ) || ( d = d . closest ( ".btn" ) ) , b . call ( d , "toggle" ) , c . preventDefault ( ) } ) } ( jQuery ) , + function ( a ) { "use strict" ; function b ( b ) { return this . each ( function ( ) { var d = a ( this ) , e = d . data ( "bs.carousel" ) , f = a . extend ( { } , c . DEFAULTS , d . data ( ) , "object" == typeof b && b ) , g = "string" == typeof b ? b : f . slide ; e || d . data ( "bs.carousel" , e = new c ( this , f ) ) , "number" == typeof b ? e . to ( b ) : g ? e [ g ] ( ) : f . interval && e . pause ( ) . cycle ( ) } ) } var c = function ( b , c ) { this . $element = a ( b ) . on ( "keydown.bs.carousel" , a . proxy ( this . keydown , this ) ) , this . $indicators = this . $element . find ( ".carousel-indicators" ) , this . options = c , this . paused = this . sliding = this . interval = this . $active = this . $items = null , "hover" == this . options . pause && this . $element . on ( "mouseenter.bs.carousel" , a . proxy ( this . pause , this ) ) . on ( "mouseleave.bs.carousel" , a . proxy ( this . cycle , this ) ) } ; c . VERSION = "3.2.0" , c . DEFAULTS = { interval : 5e3 , pause : "hover" , wrap : ! 0 } , c . prototype . keydown = function ( a ) { switch ( a . which ) { case 37 : this . prev ( ) ; break ; case 39 : this . next ( ) ; break ; default : return } a . preventDefault ( ) } , c . prototype . cycle = function ( b ) { return b || ( thi
/ * !
* Bootstrap - select v1 . 6.2 ( http : //silviomoreto.github.io/bootstrap-select/)
*
* Copyright 2013 - 2014 bootstrap - select
* Licensed under MIT ( https : //github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
* /
! function ( a ) { "use strict" ; function b ( b , d ) { var e = arguments , b = e [ 0 ] , d = e [ 1 ] ; [ ] . shift . apply ( e ) ; var f , g = this . each ( function ( ) { var g = a ( this ) ; if ( g . is ( "select" ) ) { var h = g . data ( "selectpicker" ) , i = "object" == typeof b && b ; if ( h ) { if ( i ) for ( var j in i ) i . hasOwnProperty ( j ) && ( h . options [ j ] = i [ j ] ) } else { var k = a . extend ( { } , c . DEFAULTS , a . fn . selectpicker . defaults , g . data ( ) , i ) ; g . data ( "selectpicker" , h = new c ( this , k , d ) ) } "string" == typeof b && ( f = h [ b ] instanceof Function ? h [ b ] . apply ( h , e ) : h . options [ b ] ) } } ) ; return "undefined" != typeof f ? f : g } a . expr [ ":" ] . icontains = function ( b , c , d ) { return a ( b ) . text ( ) . toUpperCase ( ) . indexOf ( d [ 3 ] . toUpperCase ( ) ) >= 0 } ; var c = function ( b , d , e ) { e && ( e . stopPropagation ( ) , e . preventDefault ( ) ) , this . $element = a ( b ) , this . $newElement = null , this . $button = null , this . $menu = null , this . $lis = null , this . options = d , null === this . options . title && ( this . options . title = this . $element . attr ( "title" ) ) , this . val = c . prototype . val , this . render = c . prototype . render , this . refresh = c . prototype . refresh , this . setStyle = c . prototype . setStyle , this . selectAll = c . prototype . selectAll , this . deselectAll = c . prototype . deselectAll , this . destroy = c . prototype . remove , this . remove = c . prototype . remove , this . show = c . prototype . show , this . hide = c . prototype . hide , this . init ( ) } ; c . VERSION = "1.6.2" , c . DEFAULTS = { noneSelectedText : "Nothing selected" , noneResultsText : "No results match" , countSelectedText : "{0} of {1} selected" , maxOptionsText : [ "Limit reached ({n} {var} max)" , "Group limit reached ({n} {var} max)" , [ "items" , "item" ] ] , multipleSeparator : ", " , style : "btn-default" , size : "auto" , title : null , selectedTextFormat : "values" , width : ! 1 , container : ! 1 , hideDisabled : ! 1 , showSubtext : ! 1 , showIcon : ! 0 , showContent : ! 0 , dropupAuto : ! 0 , header : ! 1 , liveSearch : ! 1 , actionsBox : ! 1 , iconBase : "glyphicon" , tickIcon : "glyphicon-ok" , maxOptions : ! 1 , mobile : ! 1 , selectOnTab : ! 1 , dropdownAlignRight : ! 1 } , c . prototype = { constructor : c , init : function ( ) { var b = this , c = this . $element . attr ( "id" ) ; this . $element . hide ( ) , this . multiple = this . $element . prop ( "multiple" ) , this . autofocus = this . $element . prop ( "autofocus" ) , this . $newElement = this . createView ( ) , this . $element . after ( this . $newElement ) , this . $menu = this . $newElement . find ( "> .dropdown-menu" ) , this . $button = this . $newElement . find ( "> button" ) , this . $searchbox = this . $newElement . find ( "input" ) , this . options . dropdownAlignRight && this . $menu . addClass ( "pull-right" ) , "undefined" != typeof c && ( this . $button . attr ( "data-id" , c ) , a ( 'label[for="' + c + '"]' ) . click ( function ( a ) { a . preventDefault ( ) , b . $button . focus ( ) } ) ) , this . checkDisabled ( ) , this . clickListener ( ) , this . options . liveSearch && this . liveSearchListener ( ) , this . render ( ) , this . liHeight ( ) , this . setStyle ( ) , this . setWidth ( ) , this . options . container && this . selectPosition ( ) , this . $menu . data ( "this" , this ) , this . $newElement . data ( "this" , this ) , this . options . mobile && this . mobile ( ) } , createDropdown : function ( ) { var b = this . multiple ? " show-tick" : "" , c = this . $element . parent ( ) . hasClass ( "input-group" ) ? " input-group-btn" : "" , d = this . autofocus ? " autofocus" : "" , e = this . options . header ? '<div class="popover-title"><button type="button" class="close" aria-hidden="true">×</button>' + this . options . header + "</div>" : "" , f = this . options . liveSearch ? '<div class="bootstrap-select-searchbox"><input type="text" class="input-block-level form-control" autocomplete="off" /></div>' : "" , g = this . options . actionsBox ? '<div class="bs-actionsbox"><div class="btn-group btn-block"><button class="actions-btn bs-select-all btn btn-sm btn-default">Select All</button><button class="actions-btn bs-deselect-all btn btn-sm btn-default">Deselect All</button></div></div>' : "" , h = '<div class="btn-group bootstrap-select' + b + c + '"><button type="button" class="btn dropdown-toggle selectpicker" data-toggle="dropdown"' + d + '><span class="filter-option pull-left"></span> <span class="caret"></span></button><div class="dropdown-menu open">' + e + f + g + '<ul class="dropdown-menu inner selectpicker" role="menu"></ul></div></div>' ; return a ( h ) } , createView : function ( ) { var a = this . createDropdown ( ) , b = this . createLi ( ) ; return a . find ( "ul" ) . append ( b ) , a } , reloadLi : function ( ) { this . destroyLi ( ) ; var a = this . createLi ( ) ; this . $menu . find ( "ul" ) . append ( a ) } , destroyLi : function ( ) { this . $menu . find ( "li" ) . remove ( ) } , createLi : function ( ) { var b = this , c = [ ] , d = "" , e = 0 ; return this . $el
//# sourceMappingURL=bootstrap-select.js.map
2014-09-26 08:14:42 +00:00
( function ( hscd ) {
2014-09-30 04:26:34 +00:00
'use strict' ;
2014-09-26 08:14:42 +00:00
var ctx = { } ;
function onAdjust ( name , value ) {
ctx . searchParams [ name ] = value ;
var query = {
searchParams : ctx . searchParams ,
searchRange : ctx . searchRange ,
minScore : ctx . minScore ,
hintSteps : ctx . hintSteps ,
maxResults : ctx . maxResults
} ;
$ . getJSON ( '/node/search' , query , function ( results ) {
var hintData = { } ;
for ( var keyword in results . columns ) {
hintData [ keyword ] = results . columns [ keyword ] . hints ;
}
ctx . grapher . setColumnHints ( hintData ) ;
outputResults ( results . items , results . count ) ;
} ) ;
}
function onSearch ( ) {
var keywords = $ ( '#keywordsToSearch' ) . val ( ) || [ ] ;
var searchParams = { } ;
for ( var i = 0 , count = keywords . length ; i < count ; ++ i ) {
searchParams [ keywords [ i ] ] = 1.0 ;
}
var query = {
searchParams : searchParams ,
searchRange : { min : - 1.0 , max : 1.0 } ,
minScore : parseFloat ( $ ( '#minScore' ) . val ( ) ) ,
hintSteps : parseInt ( $ ( '#hintSteps' ) . val ( ) ) ,
maxResults : parseInt ( $ ( '#maxResults' ) . val ( ) )
} ;
$ . getJSON ( '/node/search' , query , function ( results ) {
ctx . searchParams = query . searchParams ;
ctx . searchRange = query . searchRange ;
ctx . minScore = query . minScore ;
ctx . hintSteps = query . hintSteps ;
ctx . maxResults = query . maxResults ;
2014-09-30 04:26:34 +00:00
ctx . grapher = new grapher . Grapher ( 'grapher' , ctx . searchRange , 150 , true , true ) ;
2014-09-26 08:14:42 +00:00
ctx . grapher . setColumns ( results . columns ) ;
ctx . grapher . setValueChangedListener ( onAdjust ) ;
outputResults ( results . items , results . count ) ;
$ ( '#query' ) . text ( keywords . join ( ', ' ) ) ;
$ ( '#useLocalScale' ) . click ( function ( ) {
var useLocalScale = $ ( '#useLocalScale' ) . is ( ':checked' ) ;
ctx . grapher . setUseLocalScale ( useLocalScale ) ;
} ) ;
$ ( '#useRelativeScale' ) . click ( function ( ) {
var useRelativeScale = $ ( '#useRelativeScale' ) . is ( ':checked' ) ;
ctx . grapher . setUseRelativeScale ( useRelativeScale ) ;
} ) ;
$ ( '#input' ) . fadeOut ( function ( ) {
$ ( '#output' ) . fadeIn ( ) ;
} ) ;
} ) ;
}
function onLearn ( ) {
$ ( '#learnKeyword' ) . prop ( 'disabled' , true ) ;
$ ( '#learnError' ) . slideUp ( function ( ) {
var query = {
keyword : $ ( '#keywordToLearn' ) . val ( ) ,
params : ctx . searchParams
} ;
$ . getJSON ( '/node/addKeyword' , query , function ( results ) {
if ( results . success ) {
$ ( '#learnDialog' ) . modal ( 'hide' ) ;
}
else {
$ ( '#learnError' ) . slideDown ( function ( ) {
$ ( '#learnKeyword' ) . prop ( 'disabled' , false ) ;
} ) ;
}
} ) ;
} ) ;
}
function onForget ( ) {
$ ( '#forgetKeyword' ) . prop ( 'disabled' , true ) ;
$ ( '#forgetError' ) . slideUp ( function ( ) {
var query = {
keyword : $ ( '#keywordToForget' ) . val ( )
} ;
$ . getJSON ( '/node/removeKeyword' , query , function ( results ) {
if ( results . success ) {
$ ( '#forgetDialog' ) . modal ( 'hide' ) ;
}
else {
$ ( '#forgetError' ) . slideDown ( function ( ) {
$ ( '#forgetKeyword' ) . prop ( 'disabled' , false ) ;
} ) ;
}
} ) ;
} ) ;
}
function outputResults ( results , count ) {
var searchResultCnt = String ( results . length ) ;
if ( results . length < count ) {
searchResultCnt += ' of ' + count ;
}
$ ( '#count' ) . text ( searchResultCnt ) ;
var template = Handlebars . compile ( $ ( '#template' ) . html ( ) ) ;
$ ( '#results' ) . empty ( ) ;
$ ( '#results' ) . append ( template ( { 'results' : results } ) ) ;
}
$ ( document ) . on ( {
ajaxStart : function ( ) {
$ ( '#spinner' ) . show ( ) ;
} ,
ajaxStop : function ( ) {
$ ( '#spinner' ) . hide ( ) ;
} ,
ready : function ( ) {
$ ( '#keywordsToSearch' ) . selectpicker ( ) ;
$ . getJSON ( '/node/getKeywords' , function ( keywords ) {
$ ( '#searchKeywords' ) . click ( onSearch ) ;
for ( var i = 0 , count = keywords . length ; i < count ; ++ i ) {
$ ( '#keywordsToSearch' ) . append ( $ ( '<option></option>' , {
value : keywords [ i ] ,
text : keywords [ i ]
} ) ) ;
}
$ ( '#keywordsToSearch' ) . selectpicker ( 'refresh' ) ;
$ ( '#keywordsToSearch' ) . change ( function ( ) {
$ ( '#searchKeywords' ) . prop ( 'disabled' , ! $ ( this ) . val ( ) ) ;
} ) ;
$ ( '#forgetKeyword' ) . click ( onForget ) ;
$ ( '#forgetDialog' ) . on ( 'show.bs.modal' , function ( ) {
$ ( '#forgetError' ) . hide ( ) ;
$ . getJSON ( '/node/getKeywords' , function ( keywords ) {
$ ( '#forgetKeyword' ) . prop ( 'disabled' , keywords . length === 0 ) ;
$ ( '#keywordToForget' ) . empty ( ) ;
for ( var i = 0 , count = keywords . length ; i < count ; ++ i ) {
$ ( '#keywordToForget' ) . append ( $ ( '<option></option>' , {
value : keywords [ i ] ,
text : keywords [ i ]
} ) ) ;
}
} ) ;
} ) ;
$ ( '#learnKeyword' ) . click ( onLearn ) ;
$ ( '#keywordToLearn' ) . bind ( 'input' , function ( ) {
$ ( '#learnKeyword' ) . prop ( 'disabled' , ! $ ( this ) . val ( ) ) ;
} ) ;
$ ( '#learnDialog' ) . on ( 'show.bs.modal' , function ( ) {
$ ( '#learnKeyword' ) . prop ( 'disabled' , true ) ;
$ ( '#keywordToLearn' ) . val ( '' ) ;
$ ( '#learnError' ) . hide ( ) ;
} ) ;
} ) ;
}
} ) ;
} ( window . hscd = window . hscd || { } ) ) ;
2014-09-30 04:26:34 +00:00
/ *
global
$ ,
Handlebars ,
document ,
grapher ,
window ,
* /
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
( function ( grapher ) {
'use strict' ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
//
// Coord
//
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
function Coord ( x , y ) {
this . x = x ;
this . y = y ;
}
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
//
// Rect
//
function Rect ( left , top , width , height ) {
this . left = left ;
this . top = top ;
this . width = width ;
this . height = height ;
this . right = left + width ;
this . bottom = top + height ;
this . contains = function ( coord ) {
var contained =
coord . x >= this . left &&
coord . x < this . right &&
coord . y >= this . top &&
coord . y < this . bottom ;
return contained ;
} ;
this . intersection = function ( rect ) {
var left = Math . max ( this . left , rect . left ) ;
var top = Math . max ( this . top , rect . top ) ;
var right = Math . min ( this . right , rect . right ) ;
var bottom = Math . min ( this . bottom , rect . bottom ) ;
return new Rect ( left , top , right - left , bottom - top ) ;
} ;
2014-09-26 08:14:42 +00:00
}
2014-09-30 04:26:34 +00:00
//
// Range
//
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
function Range ( start , end ) {
this . start = start ;
this . end = end ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . containsPoint = function ( value ) {
return value >= this . start && value <= this . end ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getLength = function ( ) {
return this . end - this . start ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . clamp = function ( value ) {
if ( value < this . start ) {
return this . start ;
}
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
if ( value > this . end ) {
return this . end ;
}
return value ;
} ;
}
//
// Column
//
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
function Column ( canvas , name , params , scale , range , bounds ) {
this . clearShapes = function ( ) {
_ . each ( this . shapes , function ( shape ) {
this . canvas . remove ( shape ) ;
2014-09-26 08:14:42 +00:00
} ) ;
2014-09-30 04:26:34 +00:00
this . shapes = [ ] ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . updateShapes = function ( final ) {
this . columnBounds = this . getColumnBounds ( this . bounds ) ;
this . labelBounds = this . getLabelBounds ( this . columnBounds ) ;
this . hintBounds = this . getHintBounds ( this . columnBounds ) ;
this . fillBounds = this . getFillBounds ( this . columnBounds ) ;
this . handleBounds = this . getHandleBounds ( this . columnBounds , this . fillBounds ) ;
if ( final ) {
this . updateRect ( 'boundsRect' , {
left : this . columnBounds . left ,
top : this . columnBounds . top ,
width : this . columnBounds . width ,
height : this . columnBounds . height ,
stroke : this . strokeColor ,
fill : this . emptyColor
} ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . updateRect ( 'hintRect' , {
left : this . hintBounds . left ,
top : this . hintBounds . top ,
width : this . hintBounds . width ,
height : this . hintBounds . height ,
stroke : this . strokeColor
} ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . hintRect . setGradient ( 'fill' , {
x1 : 0.0 ,
y1 : 0.0 ,
x2 : 0.0 ,
y2 : this . hintRect . height ,
colorStops : this . decimateHints ( this . steps , this . scale )
} ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . updateRect ( 'labelRect' , {
left : this . labelBounds . left ,
top : this . labelBounds . top ,
width : this . labelBounds . width ,
height : this . labelBounds . height ,
fill : this . strokeColor
} ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . updateText ( 'label' , this . name , {
left : this . fillBounds . left + this . fillBounds . width / 2 ,
top : this . labelBounds . top + this . labelBounds . height / 2 ,
fontSize : this . labelFontSize ,
originX : 'center' ,
originY : 'center' ,
} ) ;
2014-09-26 08:14:42 +00:00
}
2014-09-30 04:26:34 +00:00
this . updateRect ( 'fillRect' , {
left : this . fillBounds . left ,
top : this . fillBounds . top ,
width : this . fillBounds . width ,
height : this . fillBounds . height ,
fill : this . getFillColor ( )
} ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . updateRect ( 'handleRect' , {
left : this . handleBounds . left ,
top : this . handleBounds . top ,
width : this . handleBounds . width ,
height : this . handleBounds . height ,
fill : this . getHandleColor ( )
} ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
if ( final && this . range . containsPoint ( 0.0 ) ) {
var y = this . getPosFromValue ( 0.0 ) ;
var p = [ this . bounds . left , y , this . bounds . left + this . tickLength , y ] ;
this . updateLine ( 'baseline' , p , {
stroke : this . tickColor
} ) ;
}
this . canvas . renderAll ( ) ;
} ;
this . updateRect = function ( name , args ) {
if ( name in this ) {
this [ name ] . set ( args ) ;
}
else {
var rect = new fabric . Rect ( args ) ;
this . canvas . add ( rect ) ;
this . shapes . push ( rect ) ;
this [ name ] = rect ;
}
} ;
this . updateText = function ( name , str , args ) {
if ( name in this ) {
this [ name ] . set ( args ) ;
}
else {
var text = new fabric . Text ( str , args ) ;
this . canvas . add ( text ) ;
this . shapes . push ( text ) ;
this [ name ] = text ;
}
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . updateLine = function ( name , points , args ) {
if ( name in this ) {
this [ name ] . set ( args ) ;
}
else {
var line = new fabric . Line ( points , args ) ;
this . canvas . add ( line ) ;
this . shapes . push ( line ) ;
this [ name ] = line ;
}
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . decimateHints = function ( steps , scale ) {
var groups = this . groupHints ( steps ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
var colorStops = { } ;
_ . each ( groups , function ( count , index ) {
var colorPercent = 0 ;
if ( scale . getLength ( ) > 0 ) {
colorPercent = Math . max ( 0 , count - scale . start ) / scale . getLength ( ) ;
2014-09-26 08:14:42 +00:00
}
2014-09-30 04:26:34 +00:00
var colorByte = 0xff - Math . min ( 0xff , Math . round ( 0xff * colorPercent ) ) ;
var colorObj = tinycolor ( { r : colorByte , g : colorByte , b : colorByte } ) ;
var colorStr = colorObj . toHexString ( ) ;
colorStops [ index / steps ] = colorStr ;
2014-09-26 08:14:42 +00:00
} ) ;
2014-09-30 04:26:34 +00:00
return colorStops ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . groupHints = function ( steps ) {
var stepSize = this . range . getLength ( ) / steps ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
var hintGroups = [ ] ;
for ( var i = 0 ; i < steps ; ++ i ) {
var stepMax = this . range . end - stepSize * i ;
var stepMin = stepMax - stepSize ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
var hintCount = 0 ;
for ( var j = 0 , count = this . hints . length ; j < count ; ++ j ) {
var hint = this . hints [ j ] ;
if ( hint . sample > stepMin && hint . sample <= stepMax ) {
hintCount += hint . count ;
}
}
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
hintGroups . push ( hintCount ) ;
}
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
return hintGroups ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . setClampedValue = function ( value , final ) {
this . value = this . range . clamp ( value ) ;
this . updateShapes ( final ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
if ( this . onValueChanged && final ) {
this . onValueChanged ( this . name , this . value ) ;
}
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . setHints = function ( hints , scale ) {
this . hints = hints ;
this . scale = scale ;
this . updateShapes ( true ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getLabelBounds = function ( bounds ) {
return new Rect (
bounds . left ,
bounds . top + bounds . height ,
bounds . width ,
this . labelSize
) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getColumnBounds = function ( bounds ) {
return new Rect (
bounds . left + this . tickLength ,
bounds . top ,
bounds . width - this . tickLength ,
bounds . height - this . labelSize
) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getHintBounds = function ( bounds ) {
return new Rect (
bounds . left + bounds . width - this . hintSize ,
bounds . top ,
this . hintSize ,
bounds . height
) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getFillBounds = function ( bounds ) {
var y1 = this . getPosFromValue ( 0.0 ) ;
var y2 = this . getPosFromValue ( this . value ) ;
return new Rect (
bounds . left ,
Math . min ( y1 , y2 ) ,
bounds . width - this . hintSize ,
Math . abs ( y1 - y2 )
) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getHandleBounds = function ( bounds , fillBounds ) {
var handleBounds = new Rect (
fillBounds . left ,
this . getPosFromValue ( this . value ) - this . handleSize / 2 ,
fillBounds . width ,
this . handleSize
) ;
handleBounds . intersection ( bounds ) ;
return handleBounds ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . valueColorAdjust = function ( color , offset ) {
var colorObj = tinycolor ( color ) ;
var rangeEnd = this . value >= 0.0 ? this . range . end : this . range . start ;
var rangeMid = ( this . range . start + this . range . end ) / 2.0 ;
var rangeRat = ( this . value - rangeMid ) / ( rangeEnd - rangeMid ) ;
var desatVal = Math . max ( 0.0 , 1.0 - rangeRat + offset ) * 100.0 ;
return colorObj . desaturate ( desatVal ) . toHexString ( ) ;
} ;
this . getFillColor = function ( ) {
var color = this . value >= 0.0 ? this . fillColorPos : this . fillColorNeg ;
return this . valueColorAdjust ( color , this . desatOffset ) ;
} ;
this . getHandleColor = function ( ) {
var color = this . value >= 0.0 ? this . handleColorPos : this . handleColorNeg ;
return this . valueColorAdjust ( color , this . desatOffset ) ;
} ;
this . mouseDown = function ( position ) {
if ( this . isGrabbing ( position ) ) {
this . stateTransition ( this . State . DRAG , position ) ;
}
} ;
this . mouseUp = function ( position ) {
this . stateTransition (
this . isHovering ( position ) ? this . State . HOVER : this . State . NORMAL ,
position
) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . mouseMove = function ( position ) {
switch ( this . state ) {
case this . State . NORMAL :
if ( this . isHovering ( position ) ) {
2014-09-26 08:14:42 +00:00
this . stateTransition ( this . State . HOVER , position ) ;
}
break ;
2014-09-30 04:26:34 +00:00
case this . State . HOVER :
if ( ! this . isHovering ( position ) ) {
2014-09-26 08:14:42 +00:00
this . stateTransition ( this . State . NORMAL , position ) ;
}
break ;
2014-09-30 04:26:34 +00:00
}
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . stateUpdate ( position ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . mouseOut = function ( position ) {
this . mouseUp ( position ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . mouseDoubleClick = function ( position ) {
if ( this . isContained ( position ) ) {
this . setClampedValue ( this . getValueFromPos ( position . y ) , true ) ;
}
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getValueFromPos = function ( position ) {
var percent = 1.0 - ( position - this . columnBounds . top ) / this . columnBounds . height ;
return this . range . start + this . range . getLength ( ) * percent ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getPosFromValue = function ( value ) {
var percent = 1.0 - ( value - this . range . start ) / this . range . getLength ( ) ;
var range = new Range ( this . columnBounds . top , this . columnBounds . top + this . columnBounds . height ) ;
return range . clamp ( this . columnBounds . top + this . columnBounds . height * percent ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . isHovering = function ( position ) {
return this . isGrabbing ( position ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . isGrabbing = function ( position ) {
return this . handleBounds . contains ( position ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . isContained = function ( position ) {
return this . columnBounds . contains ( position ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . stateUpdate = function ( position ) {
switch ( this . state ) {
case this . State . DRAG :
this . setClampedValue ( this . getValueFromPos ( position . y ) + this . dragDelta , false ) ;
2014-09-26 08:14:42 +00:00
break ;
2014-09-30 04:26:34 +00:00
}
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . stateTransition = function ( state , position ) {
if ( state == this . state ) {
return ;
}
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
switch ( this . state ) {
case this . State . DRAG :
this . setClampedValue ( this . getValueFromPos ( position . y ) + this . dragDelta , true ) ;
/* falls through */
case this . State . HOVER :
if ( state == this . State . NORMAL ) {
this . canvas . contextContainer . canvas . style . cursor = 'default' ;
}
2014-09-26 08:14:42 +00:00
break ;
2014-09-30 04:26:34 +00:00
}
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
switch ( state ) {
case this . State . DRAG :
this . dragDelta = this . value - this . getValueFromPos ( position . y ) ;
/* falls through */
case this . State . HOVER :
this . canvas . contextContainer . canvas . style . cursor = 'ns-resize' ;
2014-09-26 08:14:42 +00:00
break ;
2014-09-30 04:26:34 +00:00
}
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . state = state ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . State = {
NORMAL : 0 ,
HOVER : 1 ,
DRAG : 2
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . handleSize = 10 ;
this . desatOffset = - 0.3 ;
this . hintSize = 10 ;
this . labelFontSize = 15 ;
this . labelSize = 20 ;
this . tickLength = 5 ;
this . emptyColor = '#eeeeec' ;
this . strokeColor = '#d3d7cf' ;
this . tickColor = '#888a85' ;
this . fillColorNeg = '#3465a4' ;
this . fillColorPos = '#cc0000' ;
this . handleColorNeg = '#204a87' ;
this . handleColorPos = '#a40000' ;
this . canvas = canvas ;
this . shapes = [ ] ;
this . name = name ;
this . value = params . value ;
this . hints = params . hints ;
this . steps = params . steps ;
this . scale = scale ;
this . range = range ;
this . bounds = bounds ;
this . state = this . State . NORMAL ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . updateShapes ( true ) ;
}
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
//
// Grapher
//
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
grapher . Grapher = function ( canvas , range , columnWidth , useLocalScale , useRelativeScale ) {
this . setColumns = function ( columns ) {
this . clearColumns ( ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
var scale = 0 ;
if ( ! useLocalScale ) {
var hintData = { } ;
_ . each ( columns , function ( columnValue , columnName ) {
hintData [ columnName ] = columnValue . hints || [ ] ;
} ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
scale = this . getGlobalScale ( hintData ) ;
2014-09-26 08:14:42 +00:00
}
2014-09-30 04:26:34 +00:00
var graphBounds = this . getGraphBounds ( this . getCanvasBounds ( ) ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
var index = 0 ;
var that = this ;
_ . each ( columns , function ( columnValue , columnName ) {
if ( useLocalScale ) {
scale = that . getLocalScale ( columnValue . hints ) ;
}
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
var columnBounds = that . getColumnBounds ( graphBounds , index ) ;
that . columns . push ( new Column ( that . canvas , columnName , columnValue , scale , that . range , columnBounds ) ) ;
that . indexMap [ columnName ] = index ++ ;
} ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . clearColumns = function ( ) {
_ . each ( this . columns , function ( column ) {
column . clearShapes ( ) ;
} ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . columns = [ ] ;
this . indexMap = { } ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . setColumnHints = function ( hintData ) {
var scale = 0 ;
if ( ! this . useLocalScale ) {
scale = this . getGlobalScale ( hintData ) ;
2014-09-26 08:14:42 +00:00
}
2014-09-30 04:26:34 +00:00
var that = this ;
_ . each ( hintData , function ( hints , name ) {
var index = that . getColumnIndex ( name ) ;
console . assert ( index >= 0 ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
if ( that . useLocalScale ) {
scale = that . getLocalScale ( hints ) ;
}
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
that . columns [ index ] . setHints ( hints , scale ) ;
} ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . setUseLocalScale = function ( useLocalScale ) {
if ( useLocalScale != this . useLocalScale ) {
this . useLocalScale = useLocalScale ;
this . invalidateHints ( ) ;
}
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . setUseRelativeScale = function ( useRelativeScale ) {
if ( useRelativeScale != this . useRelativeScale ) {
this . useRelativeScale = useRelativeScale ;
this . invalidateHints ( ) ;
}
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . invalidateHints = function ( ) {
var hintData = { } ;
_ . each ( this . columns , function ( column ) {
hintData [ column . name ] = column . hints ;
} ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . setColumnHints ( hintData ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . setValueChangedListener = function ( listener ) {
_ . each ( this . columns , function ( column ) {
column . onValueChanged = listener ;
} ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getLocalScale = function ( hints ) {
var counts = _ . pluck ( hints , 'count' ) ;
var min = this . useRelativeScale ? _ . min ( counts ) : 0 ;
return new Range ( min , _ . max ( counts ) ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getGlobalScale = function ( hintData ) {
var that = this ;
var globalScale = null ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
_ . each ( hintData , function ( hints ) {
var localScale = that . getLocalScale ( hints ) ;
if ( globalScale ) {
globalScale . includeRange ( localScale ) ;
}
else {
globalScale = localScale ;
}
} ) ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
return globalScale ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getColumnCount = function ( ) {
return this . columns . length ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getColumnIndex = function ( name ) {
console . assert ( name in this . indexMap ) ;
return this . indexMap [ name ] ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getColumnName = function ( index ) {
return this . columns [ index ] . name ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getColumnNames = function ( ) {
return _ . pluck ( this . columns , 'name' ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getCanvasBounds = function ( ) {
return new Rect ( 0 , 0 , this . canvas . width - 1 , this . canvas . height - 1 ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getGraphBounds = function ( bounds ) {
return this . getCanvasBounds ( ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getColumnBounds = function ( bounds , index , count ) {
var width = this . columnWidth + this . padding * 2 ;
return new Rect (
bounds . left + width * index + this . padding ,
bounds . top ,
this . columnWidth ,
bounds . height
) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . getMousePos = function ( e ) {
var rect = e . target . getBoundingClientRect ( ) ;
return new Coord ( e . clientX - rect . left , e . clientY - rect . top ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . mouseDown = function ( e ) {
var position = this . grapher . getMousePos ( e ) ;
_ . each ( this . grapher . columns , function ( column ) {
column . mouseDown ( position ) ;
} ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . mouseUp = function ( e ) {
var position = this . grapher . getMousePos ( e ) ;
_ . each ( this . grapher . columns , function ( column ) {
column . mouseUp ( position ) ;
} ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . mouseMove = function ( e ) {
var position = this . grapher . getMousePos ( e ) ;
_ . each ( this . grapher . columns , function ( column ) {
column . mouseMove ( position ) ;
} ) ;
} ;
2014-09-26 08:14:42 +00:00
2014-09-30 04:26:34 +00:00
this . mouseOut = function ( e ) {
var position = this . grapher . getMousePos ( e ) ;
_ . each ( this . grapher . columns , function ( column ) {
column . mouseOut ( position ) ;
} ) ;
} ;
this . mouseDoubleClick = function ( e ) {
var position = this . grapher . getMousePos ( e ) ;
_ . each ( this . grapher . columns , function ( column ) {
column . mouseDoubleClick ( position ) ;
} ) ;
} ;
this . useLocalScale = useLocalScale ;
this . useRelativeScale = useRelativeScale ;
this . columnWidth = columnWidth ;
this . canvas = new fabric . StaticCanvas ( canvas ) ;
this . range = new Range ( range . min , range . max ) ;
this . padding = 10 ;
this . indexMap = { } ;
this . columns = [ ] ;
var c = this . canvas . contextContainer . canvas ;
c . addEventListener ( 'mousedown' , this . mouseDown , false ) ;
c . addEventListener ( 'mouseup' , this . mouseUp , false ) ;
c . addEventListener ( 'mousemove' , this . mouseMove , false ) ;
c . addEventListener ( 'mouseout' , this . mouseOut , false ) ;
c . addEventListener ( 'dblclick' , this . mouseDoubleClick , false ) ;
c . grapher = this ;
} ;
} ( window . grapher = window . grapher || { } ) ) ;