| author | veltr |
| Tue, 23 Apr 2013 15:23:20 +0200 | |
| changeset 997 | 1615c7e4ef9d |
| parent 996 | c472984db275 |
| child 998 | 9521347ede1d |
| src/js/defaults.js | file | annotate | diff | comparison | revisions | |
| src/js/libs/backbone-relational.js | file | annotate | diff | comparison | revisions | |
| src/js/libs/backbone.js | file | annotate | diff | comparison | revisions | |
| src/js/libs/jquery.min.js | file | annotate | diff | comparison | revisions | |
| src/js/libs/renkan-publish.js | file | annotate | diff | comparison | revisions | |
| src/js/libs/renkan.js | file | annotate | diff | comparison | revisions | |
| src/js/libs/underscore-min.js | file | annotate | diff | comparison | revisions | |
| src/widgets/Renkan.css | file | annotate | diff | comparison | revisions | |
| src/widgets/Renkan.js | file | annotate | diff | comparison | revisions | |
| test/renkan.htm | file | annotate | diff | comparison | revisions | |
| test/youtube.htm | file | annotate | diff | comparison | revisions |
--- a/src/js/defaults.js Wed Apr 03 15:44:17 2013 +0200 +++ b/src/js/defaults.js Tue Apr 23 15:23:20 2013 +0200 @@ -21,7 +21,7 @@ backboneRelational: "backbone-relational.js", paper: "paper.js", jqueryMousewheel: "jquery.mousewheel.min.js", - renkanPublish: "renkan-publish.js", + renkanPublish: "renkan.js", processing: "processing-1.3.6.min.js", recordMicSwf: "record_mic.swf" },
--- a/src/js/libs/backbone-relational.js Wed Apr 03 15:44:17 2013 +0200 +++ b/src/js/libs/backbone-relational.js Tue Apr 23 15:23:20 2013 +0200 @@ -1,6 +1,7 @@ +/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab: */ /** - * Backbone-relational.js 0.6.0 - * (c) 2011 Paul Uithol + * Backbone-relational.js 0.8.5 + * (c) 2011-2013 Paul Uithol and contributors (https://github.com/PaulUithol/Backbone-relational/graphs/contributors) * * Backbone-relational may be freely distributed under the MIT license; see the accompanying LICENSE.txt. * For details and documentation: https://github.com/PaulUithol/Backbone-relational. @@ -8,7 +9,7 @@ */ ( function( undefined ) { "use strict"; - + /** * CommonJS shim **/ @@ -34,7 +35,7 @@ Backbone.Semaphore = { _permitsAvailable: null, _permitsUsed: 0, - + acquire: function() { if ( this._permitsAvailable && this._permitsUsed >= this._permitsAvailable ) { throw new Error( 'Max permits acquired' ); @@ -43,7 +44,7 @@ this._permitsUsed++; } }, - + release: function() { if ( this._permitsUsed === 0 ) { throw new Error( 'All permits released' ); @@ -52,11 +53,11 @@ this._permitsUsed--; } }, - + isLocked: function() { return this._permitsUsed > 0; }, - + setAvailablePermits: function( amount ) { if ( this._permitsUsed > amount ) { throw new Error( 'Available permits cannot be less than used permits' ); @@ -64,7 +65,7 @@ this._permitsAvailable = amount; } }; - + /** * A BlockingQueue that accumulates items while blocked (via 'block'), * and processes them when unblocked (via 'unblock'). @@ -75,7 +76,7 @@ }; _.extend( Backbone.BlockingQueue.prototype, Backbone.Semaphore, { _queue: null, - + add: function( func ) { if ( this.isBlocked() ) { this._queue.push( func ); @@ -84,34 +85,34 @@ func(); } }, - + process: function() { while ( this._queue && this._queue.length ) { this._queue.shift()(); } }, - + block: function() { this.acquire(); }, - + unblock: function() { this.release(); if ( !this.isBlocked() ) { this.process(); } }, - + isBlocked: function() { return this.isLocked(); } }); /** - * Global event queue. Accumulates external events ('add:<key>', 'remove:<key>' and 'update:<key>') + * Global event queue. Accumulates external events ('add:<key>', 'remove:<key>' and 'change:<key>') * until the top-level object is fully initialized (see 'Backbone.RelationalModel'). */ Backbone.Relational.eventQueue = new Backbone.BlockingQueue(); - + /** * Backbone.Store keeps track of all created (and destruction of) Backbone.RelationalModel. * Handles lookup for relations. @@ -119,15 +120,44 @@ Backbone.Store = function() { this._collections = []; this._reverseRelations = []; + this._orphanRelations = []; this._subModels = []; this._modelScopes = [ exports ]; }; _.extend( Backbone.Store.prototype, Backbone.Events, { + /** + * Create a new `Relation`. + * @param {Backbone.RelationalModel} [model] + * @param {Object} relation + * @param {Object} [options] + */ + initializeRelation: function( model, relation, options ) { + var type = !_.isString( relation.type ) ? relation.type : Backbone[ relation.type ] || this.getObjectByName( relation.type ); + if ( type && type.prototype instanceof Backbone.Relation ) { + new type( model, relation, options ); // Also pushes the new Relation into `model._relations` + } + else { + Backbone.Relational.showWarnings && typeof console !== 'undefined' && console.warn( 'Relation=%o; missing or invalid relation type!', relation ); + } + }, + + /** + * Add a scope for `getObjectByName` to look for model types by name. + * @param {Object} scope + */ addModelScope: function( scope ) { this._modelScopes.push( scope ); }, /** + * Remove a scope. + * @param {Object} scope + */ + removeModelScope: function( scope ) { + this._modelScopes = _.without( this._modelScopes, scope ); + }, + + /** * Add a set of subModelTypes to the store, that can be used to resolve the '_superModel' * for a model later in 'setupSuperModel'. * @@ -149,7 +179,7 @@ */ setupSuperModel: function( modelType ) { _.find( this._subModels, function( subModelDef ) { - return _.find( subModelDef.subModels, function( subModelTypeName, typeValue ) { + return _.find( subModelDef.subModels || [], function( subModelTypeName, typeValue ) { var subModelType = this.getObjectByName( subModelTypeName ); if ( modelType === subModelType ) { @@ -165,7 +195,7 @@ }, this ); }, this ); }, - + /** * Add a reverse relation. Is added to the 'relations' property on model's prototype, and to * existing instances of 'model' in the store as well. @@ -177,74 +207,108 @@ */ addReverseRelation: function( relation ) { var exists = _.any( this._reverseRelations, function( rel ) { - return _.all( relation, function( val, key ) { - return val === rel[ key ]; - }); + return _.all( relation || [], function( val, key ) { + return val === rel[ key ]; }); + }); if ( !exists && relation.model && relation.type ) { this._reverseRelations.push( relation ); - - var addRelation = function( model, relation ) { - if ( !model.prototype.relations ) { - model.prototype.relations = []; - } - model.prototype.relations.push( relation ); - - _.each( model._subModels, function( subModel ) { - addRelation( subModel, relation ); - }, this ); - }; - - addRelation( relation.model, relation ); - + this._addRelation( relation.model, relation ); this.retroFitRelation( relation ); } }, - + + /** + * Deposit a `relation` for which the `relatedModel` can't be resolved at the moment. + * + * @param {Object} relation + */ + addOrphanRelation: function( relation ) { + var exists = _.any( this._orphanRelations, function( rel ) { + return _.all( relation || [], function( val, key ) { + return val === rel[ key ]; + }); + }); + + if ( !exists && relation.model && relation.type ) { + this._orphanRelations.push( relation ); + } + }, + + /** + * Try to initialize any `_orphanRelation`s + */ + processOrphanRelations: function() { + // Make sure to operate on a copy since we're removing while iterating + _.each( this._orphanRelations.slice( 0 ), function( rel ) { + var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel ); + if ( relatedModel ) { + this.initializeRelation( null, rel ); + this._orphanRelations = _.without( this._orphanRelations, rel ); + } + }, this ); + }, + + /** + * + * @param {Backbone.RelationalModel.constructor} type + * @param {Object} relation + * @private + */ + _addRelation: function( type, relation ) { + if ( !type.prototype.relations ) { + type.prototype.relations = []; + } + type.prototype.relations.push( relation ); + + _.each( type._subModels || [], function( subModel ) { + this._addRelation( subModel, relation ); + }, this ); + }, + /** * Add a 'relation' to all existing instances of 'relation.model' in the store * @param {Object} relation */ retroFitRelation: function( relation ) { - var coll = this.getCollection( relation.model ); - coll.each( function( model ) { + var coll = this.getCollection( relation.model, false ); + coll && coll.each( function( model ) { if ( !( model instanceof relation.model ) ) { return; } new relation.type( model, relation ); - }, this); + }, this ); }, - + /** * Find the Store's collection for a certain type of model. - * @param {Backbone.RelationalModel} model + * @param {Backbone.RelationalModel} type + * @param {Boolean} [create=true] Should a collection be created if none is found? * @return {Backbone.Collection} A collection if found (or applicable for 'model'), or null */ - getCollection: function( model ) { - if ( model instanceof Backbone.RelationalModel ) { - model = model.constructor; + getCollection: function( type, create ) { + if ( type instanceof Backbone.RelationalModel ) { + type = type.constructor; } - var rootModel = model; + var rootModel = type; while ( rootModel._superModel ) { rootModel = rootModel._superModel; } - var coll = _.detect( this._collections, function( c ) { - return c.model === rootModel; - }); + var coll = _.findWhere( this._collections, { model: rootModel } ); - if ( !coll ) { + if ( !coll && create !== false ) { coll = this._createCollection( rootModel ); } return coll; }, - + /** - * Find a type on the global object by name. Splits name on dots. + * Find a model type on one of the modelScopes by name. Names are split on dots. * @param {String} name * @return {Object} */ @@ -253,8 +317,8 @@ type = null; _.find( this._modelScopes, function( scope ) { - type = _.reduce( parts, function( memo, val ) { - return memo[ val ]; + type = _.reduce( parts || [], function( memo, val ) { + return memo ? memo[ val ] : undefined; }, scope ); if ( type && type !== scope ) { @@ -264,7 +328,7 @@ return type; }, - + _createCollection: function( type ) { var coll; @@ -311,7 +375,7 @@ }, /** - * + * Find a specific model of a certain `type` in the store * @param type * @param {String|Number|Object|Backbone.RelationalModel} item */ @@ -331,52 +395,82 @@ return null; }, - + /** - * Add a 'model' to it's appropriate collection. Retain the original contents of 'model.collection'. + * Add a 'model' to its appropriate collection. Retain the original contents of 'model.collection'. * @param {Backbone.RelationalModel} model */ register: function( model ) { var coll = this.getCollection( model ); if ( coll ) { - if ( coll.get( model ) ) { - throw new Error( "Cannot instantiate more than one Backbone.RelationalModel with the same id per type!" ); - } - var modelColl = model.collection; coll.add( model ); - model.bind( 'destroy', this.unregister, this ); + this.listenTo( model, 'destroy', this.unregister, this ); model.collection = modelColl; } }, - + /** - * Explicitly update a model's id in it's store collection + * Check if the given model may use the given `id` + * @param model + * @param [id] + */ + checkId: function( model, id ) { + var coll = this.getCollection( model ), + duplicate = coll && coll.get( id ); + + if ( duplicate && model !== duplicate ) { + if ( Backbone.Relational.showWarnings && typeof console !== 'undefined' ) { + console.warn( 'Duplicate id! Old RelationalModel=%o, new RelationalModel=%o', duplicate, model ); + } + + throw new Error( "Cannot instantiate more than one Backbone.RelationalModel with the same id per type!" ); + } + }, + + /** + * Explicitly update a model's id in its store collection * @param {Backbone.RelationalModel} model */ update: function( model ) { var coll = this.getCollection( model ); + // This triggers updating the lookup indices kept in a collection coll._onModelEvent( 'change:' + model.idAttribute, model, coll ); + + // Trigger an event on model so related models (having the model's new id in their keyContents) can add it. + model.trigger( 'relational:change:id', model, coll ); }, - + /** * Remove a 'model' from the store. * @param {Backbone.RelationalModel} model */ unregister: function( model ) { - model.unbind( 'destroy', this.unregister ); + this.stopListening( model, 'destroy', this.unregister ); var coll = this.getCollection( model ); coll && coll.remove( model ); + }, + + /** + * Reset the `store` to it's original state. The `reverseRelations` are kept though, since attempting to + * re-initialize these on models would lead to a large amount of warnings. + */ + reset: function() { + this.stopListening(); + this._collections = []; + this._subModels = []; + this._modelScopes = [ exports ]; } }); Backbone.Relational.store = new Backbone.Store(); - + /** * The main Relation class, from which 'HasOne' and 'HasMany' inherit. Internally, 'relational:<key>' events * are used to regulate addition and removal of models from relations. * - * @param {Backbone.RelationalModel} instance + * @param {Backbone.RelationalModel} [instance] Model that this relation is created for. If no model is supplied, + * Relation just tries to instantiate it's `reverseRelation` if specified, and bails out after that. * @param {Object} options * @param {string} options.key * @param {Backbone.RelationalModel.constructor} options.relatedModel @@ -385,41 +479,30 @@ * @param {Object} [options.reverseRelation] Specify a bi-directional relation. If provided, Relation will reciprocate * the relation to the 'relatedModel'. Required and optional properties match 'options', except that it also needs * {Backbone.Relation|String} type ('HasOne' or 'HasMany'). + * @param {Object} opts */ - Backbone.Relation = function( instance, options ) { + Backbone.Relation = function( instance, options, opts ) { this.instance = instance; // Make sure 'options' is sane, and fill with defaults from subclasses and this object's prototype options = _.isObject( options ) ? options : {}; this.reverseRelation = _.defaults( options.reverseRelation || {}, this.options.reverseRelation ); + this.options = _.defaults( options, this.options, Backbone.Relation.prototype.options ); + this.reverseRelation.type = !_.isString( this.reverseRelation.type ) ? this.reverseRelation.type : Backbone[ this.reverseRelation.type ] || Backbone.Relational.store.getObjectByName( this.reverseRelation.type ); - this.model = options.model || this.instance.constructor; - this.options = _.defaults( options, this.options, Backbone.Relation.prototype.options ); - + this.key = this.options.key; this.keySource = this.options.keySource || this.key; this.keyDestination = this.options.keyDestination || this.keySource || this.key; - // 'exports' should be the global object where 'relatedModel' can be found on if given as a string. + this.model = this.options.model || this.instance.constructor; this.relatedModel = this.options.relatedModel; if ( _.isString( this.relatedModel ) ) { this.relatedModel = Backbone.Relational.store.getObjectByName( this.relatedModel ); } if ( !this.checkPreconditions() ) { - return false; - } - - if ( instance ) { - this.keyContents = this.instance.get( this.keySource ); - - // Explicitly clear 'keySource', to prevent a leaky abstraction if 'keySource' differs from 'key'. - if ( this.key !== this.keySource ) { - this.instance.unset( this.keySource, { silent: true } ); - } - - // Add this Relation to instance._relations - this.instance._relations.push( this ); + return; } // Add the reverse relation on 'relatedModel' to the store's reverseRelations @@ -428,25 +511,39 @@ isAutoRelation: true, model: this.relatedModel, relatedModel: this.model, - reverseRelation: this.options // current relation is the 'reverseRelation' for it's own reverseRelation + reverseRelation: this.options // current relation is the 'reverseRelation' for its own reverseRelation }, this.reverseRelation // Take further properties from this.reverseRelation (type, key, etc.) ) ); } - _.bindAll( this, '_modelRemovedFromCollection', '_relatedModelAdded', '_relatedModelRemoved' ); + if ( instance ) { + var contentKey = this.keySource; + if ( contentKey !== this.key && typeof this.instance.get( this.key ) === 'object' ) { + contentKey = this.key; + } + + this.setKeyContents( this.instance.get( contentKey ) ); + this.relatedCollection = Backbone.Relational.store.getCollection( this.relatedModel ); - if ( instance ) { - this.initialize(); + // Explicitly clear 'keySource', to prevent a leaky abstraction if 'keySource' differs from 'key'. + if ( this.keySource !== this.key ) { + this.instance.unset( this.keySource, { silent: true } ); + } - // When a model in the store is destroyed, check if it is 'this.instance'. - Backbone.Relational.store.getCollection( this.instance ) - .bind( 'relational:remove', this._modelRemovedFromCollection ); + // Add this Relation to instance._relations + this.instance._relations[ this.key ] = this; + + this.initialize( opts ); + + if ( this.options.autoFetch ) { + this.instance.fetchRelated( this.key, _.isObject( this.options.autoFetch ) ? this.options.autoFetch : {} ); + } // When 'relatedModel' are created or destroyed, check if it affects this relation. - Backbone.Relational.store.getCollection( this.relatedModel ) - .bind( 'relational:add', this._relatedModelAdded ) - .bind( 'relational:remove', this._relatedModelRemoved ); + this.listenTo( this.instance, 'destroy', this.destroy ) + .listenTo( this.relatedCollection, 'relational:add relational:change:id', this.tryAddRelated ) + .listenTo( this.relatedCollection, 'relational:remove', this.removeRelated ) } }; // Fix inheritance :\ @@ -456,35 +553,19 @@ options: { createModels: true, includeInJSON: true, - isAutoRelation: false + isAutoRelation: false, + autoFetch: false, + parse: false }, - + instance: null, key: null, keyContents: null, relatedModel: null, + relatedCollection: null, reverseRelation: null, related: null, - - _relatedModelAdded: function( model, coll, options ) { - // Allow 'model' to set up it's relations, before calling 'tryAddRelated' - // (which can result in a call to 'addRelated' on a relation of 'model') - var dit = this; - model.queue( function() { - dit.tryAddRelated( model, options ); - }); - }, - - _relatedModelRemoved: function( model, coll, options ) { - this.removeRelated( model, options ); - }, - - _modelRemovedFromCollection: function( model ) { - if ( model === this.instance ) { - this.destroy(); - } - }, - + /** * Check several pre-conditions. * @return {Boolean} True if pre-conditions are satisfied, false if they're not. @@ -497,36 +578,33 @@ warn = Backbone.Relational.showWarnings && typeof console !== 'undefined'; if ( !m || !k || !rm ) { - warn && console.warn( 'Relation=%o; no model, key or relatedModel (%o, %o, %o)', this, m, k, rm ); + warn && console.warn( 'Relation=%o: missing model, key or relatedModel (%o, %o, %o).', this, m, k, rm ); return false; } // Check if the type in 'model' inherits from Backbone.RelationalModel if ( !( m.prototype instanceof Backbone.RelationalModel ) ) { - warn && console.warn( 'Relation=%o; model does not inherit from Backbone.RelationalModel (%o)', this, i ); + warn && console.warn( 'Relation=%o: model does not inherit from Backbone.RelationalModel (%o).', this, i ); return false; } // Check if the type in 'relatedModel' inherits from Backbone.RelationalModel if ( !( rm.prototype instanceof Backbone.RelationalModel ) ) { - warn && console.warn( 'Relation=%o; relatedModel does not inherit from Backbone.RelationalModel (%o)', this, rm ); + warn && console.warn( 'Relation=%o: relatedModel does not inherit from Backbone.RelationalModel (%o).', this, rm ); return false; } // Check if this is not a HasMany, and the reverse relation is HasMany as well if ( this instanceof Backbone.HasMany && this.reverseRelation.type === Backbone.HasMany ) { - warn && console.warn( 'Relation=%o; relation is a HasMany, and the reverseRelation is HasMany as well.', this ); + warn && console.warn( 'Relation=%o: relation is a HasMany, and the reverseRelation is HasMany as well.', this ); return false; } + // Check if we're not attempting to create a relationship on a `key` that's already used. + if ( i && _.keys( i._relations ).length ) { + var existing = _.find( i._relations, function( rel ) { + return rel.key === k; + }, this ); - // Check if we're not attempting to create a duplicate relationship - if ( i && i._relations.length ) { - var exists = _.any( i._relations, function( rel ) { - var hasReverseRelation = this.reverseRelation.key && rel.reverseRelation.key; - return rel.relatedModel === rm && rel.key === k && - ( !hasReverseRelation || this.reverseRelation.key === rel.reverseRelation.key ); - }, this ); - - if ( exists ) { - warn && console.warn( 'Relation=%o between instance=%o.%s and relatedModel=%o.%s already exists', - this, i, k, rm, this.reverseRelation.key ); + if ( existing ) { + warn && console.warn( 'Cannot create relation=%o on %o for model=%o: already taken by relation=%o.', + this, k, i, existing ); return false; } } @@ -536,17 +614,16 @@ /** * Set the related model(s) for this relation - * @param {Backbone.Mode|Backbone.Collection} related - * @param {Object} [options] + * @param {Backbone.Model|Backbone.Collection} related */ - setRelated: function( related, options ) { + setRelated: function( related ) { this.related = related; this.instance.acquire(); - this.instance.set( this.key, related, _.defaults( options || {}, { silent: true } ) ); + this.instance.attributes[ this.key ] = related; this.instance.release(); }, - + /** * Determine if a relation (on a different RelationalModel) is the reverse * relation of the current one. @@ -554,13 +631,10 @@ * @return {Boolean} */ _isReverseRelation: function( relation ) { - if ( relation.instance instanceof this.relatedModel && this.reverseRelation.key === relation.key && - this.key === relation.reverseRelation.key ) { - return true; - } - return false; + return relation.instance instanceof this.relatedModel && this.reverseRelation.key === relation.key && + this.key === relation.reverseRelation.key; }, - + /** * Get the reverse relations (pointing back to 'this.key' on 'this.instance') for the currently related model(s). * @param {Backbone.RelationalModel} [model] Get the reverse relations for a specific model. @@ -571,97 +645,92 @@ var reverseRelations = []; // Iterate over 'model', 'this.related.models' (if this.related is a Backbone.Collection), or wrap 'this.related' in an array. var models = !_.isUndefined( model ) ? [ model ] : this.related && ( this.related.models || [ this.related ] ); - _.each( models , function( related ) { - _.each( related.getRelations(), function( relation ) { - if ( this._isReverseRelation( relation ) ) { - reverseRelations.push( relation ); - } - }, this ); - }, this ); + _.each( models || [], function( related ) { + _.each( related.getRelations() || [], function( relation ) { + if ( this._isReverseRelation( relation ) ) { + reverseRelations.push( relation ); + } + }, this ); + }, this ); return reverseRelations; }, - - /** - * Rename options.silent to options.silentChange, so events propagate properly. - * (for example in HasMany, from 'addRelated'->'handleAddition') - * @param {Object} [options] - * @return {Object} - */ - sanitizeOptions: function( options ) { - options = options ? _.clone( options ) : {}; - if ( options.silent ) { - options.silentChange = true; - delete options.silent; - } - return options; - }, /** - * Rename options.silentChange to options.silent, so events are silenced as intended in Backbone's - * original functions. - * @param {Object} [options] - * @return {Object} + * When `this.instance` is destroyed, cleanup our relations. + * Get reverse relation, call removeRelated on each. */ - unsanitizeOptions: function( options ) { - options = options ? _.clone( options ) : {}; - if ( options.silentChange ) { - options.silent = true; - delete options.silentChange; + destroy: function() { + this.stopListening(); + + if ( this instanceof Backbone.HasOne ) { + this.setRelated( null ); } - return options; - }, - - // Cleanup. Get reverse relation, call removeRelated on each. - destroy: function() { - Backbone.Relational.store.getCollection( this.instance ) - .unbind( 'relational:remove', this._modelRemovedFromCollection ); - - Backbone.Relational.store.getCollection( this.relatedModel ) - .unbind( 'relational:add', this._relatedModelAdded ) - .unbind( 'relational:remove', this._relatedModelRemoved ); + else if ( this instanceof Backbone.HasMany ) { + this.setRelated( this._prepareCollection() ); + } _.each( this.getReverseRelations(), function( relation ) { - relation.removeRelated( this.instance ); - }, this ); + relation.removeRelated( this.instance ); + }, this ); } }); - + Backbone.HasOne = Backbone.Relation.extend({ options: { reverseRelation: { type: 'HasMany' } }, - - initialize: function() { - _.bindAll( this, 'onChange' ); - this.instance.bind( 'relational:change:' + this.key, this.onChange ); + initialize: function( opts ) { + this.listenTo( this.instance, 'relational:change:' + this.key, this.onChange ); - var model = this.findRelated( { silent: true } ); - this.setRelated( model ); + var related = this.findRelated( opts ); + this.setRelated( related ); // Notify new 'related' object of the new relation. _.each( this.getReverseRelations(), function( relation ) { - relation.addRelated( this.instance ); - }, this ); + relation.addRelated( this.instance, opts ); + }, this ); }, - + + /** + * Find related Models. + * @param {Object} [options] + * @return {Backbone.Model} + */ findRelated: function( options ) { - var item = this.keyContents; - var model = null; - - if ( item instanceof this.relatedModel ) { - model = item; + var related = null; + + options = _.defaults( { parse: this.options.parse }, options ); + + if ( this.keyContents instanceof this.relatedModel ) { + related = this.keyContents; + } + else if ( this.keyContents || this.keyContents === 0 ) { // since 0 can be a valid `id` as well + var opts = _.defaults( { create: this.options.createModels }, options ); + related = this.relatedModel.findOrCreate( this.keyContents, opts ); + } + + // Nullify `keyId` if we have a related model; in case it was already part of the relation + if ( this.related ) { + this.keyId = null; } - else if ( item || item === 0 ) { // since 0 can be a valid `id` as well - model = this.relatedModel.findOrCreate( item, { create: this.options.createModels } ); - } - - return model; + + return related; }, - + /** - * If the key is changed, notify old & new reverse relations and initialize the new relation + * Normalize and reduce `keyContents` to an `id`, for easier comparison + * @param {String|Number|Backbone.Model} keyContents + */ + setKeyContents: function( keyContents ) { + this.keyContents = keyContents; + this.keyId = Backbone.Relational.store.resolveIdForItem( this.relatedModel, this.keyContents ); + }, + + /** + * Event handler for `change:<key>`. + * If the key is changed, notify old & new reverse relations and initialize the new relation. */ onChange: function( model, attr, options ) { // Don't accept recursive calls to onChange (like onChange->findRelated->findOrCreate->initializeRelations->addRelated->onChange) @@ -669,81 +738,70 @@ return; } this.acquire(); - options = this.sanitizeOptions( options ); + options = options ? _.clone( options ) : {}; - // 'options._related' is set by 'addRelated'/'removeRelated'. If it is set, the change + // 'options.__related' is set by 'addRelated'/'removeRelated'. If it is set, the change // is the result of a call from a relation. If it's not, the change is the result of // a 'set' call on this.instance. - var changed = _.isUndefined( options._related ); - var oldRelated = changed ? this.related : options._related; + var changed = _.isUndefined( options.__related ), + oldRelated = changed ? this.related : options.__related; - if ( changed ) { - this.keyContents = attr; - - // Set new 'related' - if ( attr instanceof this.relatedModel ) { - this.related = attr; - } - else if ( attr ) { - var related = this.findRelated( options ); - this.setRelated( related ); - } - else { - this.setRelated( null ); - } + if ( changed ) { + this.setKeyContents( attr ); + var related = this.findRelated( options ); + this.setRelated( related ); } // Notify old 'related' object of the terminated relation if ( oldRelated && this.related !== oldRelated ) { _.each( this.getReverseRelations( oldRelated ), function( relation ) { - relation.removeRelated( this.instance, options ); - }, this ); + relation.removeRelated( this.instance, null, options ); + }, this ); } - + // Notify new 'related' object of the new relation. Note we do re-apply even if this.related is oldRelated; // that can be necessary for bi-directional relations if 'this.instance' was created after 'this.related'. // In that case, 'this.instance' will already know 'this.related', but the reverse might not exist yet. _.each( this.getReverseRelations(), function( relation ) { - relation.addRelated( this.instance, options ); - }, this); + relation.addRelated( this.instance, options ); + }, this ); - // Fire the 'update:<key>' event if 'related' was updated - if ( !options.silentChange && this.related !== oldRelated ) { + // Fire the 'change:<key>' event if 'related' was updated + if ( !options.silent && this.related !== oldRelated ) { var dit = this; + this.changed = true; Backbone.Relational.eventQueue.add( function() { - dit.instance.trigger( 'update:' + dit.key, dit.instance, dit.related, options ); + dit.instance.trigger( 'change:' + dit.key, dit.instance, dit.related, options, true ); + dit.changed = false; }); } this.release(); }, - + /** * If a new 'this.relatedModel' appears in the 'store', try to match it to the last set 'keyContents' */ - tryAddRelated: function( model, options ) { - if ( this.related ) { - return; - } - options = this.sanitizeOptions( options ); - - var item = this.keyContents; - if ( item || item === 0 ) { // since 0 can be a valid `id` as well - var id = Backbone.Relational.store.resolveIdForItem( this.relatedModel, item ); - if ( !_.isNull( id ) && model.id === id ) { - this.addRelated( model, options ); - } + tryAddRelated: function( model, coll, options ) { + if ( ( this.keyId || this.keyId === 0 ) && model.id === this.keyId ) { // since 0 can be a valid `id` as well + this.addRelated( model, options ); + this.keyId = null; } }, - + addRelated: function( model, options ) { - if ( model !== this.related ) { - var oldRelated = this.related || null; - this.setRelated( model ); - this.onChange( this.instance, model, { _related: oldRelated } ); - } + // Allow 'model' to set up its relations before proceeding. + // (which can result in a call to 'addRelated' from a relation of 'model') + var dit = this; + model.queue( function() { + if ( model !== dit.related ) { + var oldRelated = dit.related || null; + dit.setRelated( model ); + dit.onChange( dit.instance, model, _.defaults( { __related: oldRelated }, options ) ); + } + }); }, - - removeRelated: function( model, options ) { + + removeRelated: function( model, coll, options ) { if ( !this.related ) { return; } @@ -751,66 +809,53 @@ if ( model === this.related ) { var oldRelated = this.related || null; this.setRelated( null ); - this.onChange( this.instance, model, { _related: oldRelated } ); + this.onChange( this.instance, model, _.defaults( { __related: oldRelated }, options ) ); } } }); - + Backbone.HasMany = Backbone.Relation.extend({ collectionType: null, - + options: { reverseRelation: { type: 'HasOne' }, collectionType: Backbone.Collection, collectionKey: true, collectionOptions: {} }, - - initialize: function() { - _.bindAll( this, 'onChange', 'handleAddition', 'handleRemoval', 'handleReset' ); - this.instance.bind( 'relational:change:' + this.key, this.onChange ); + + initialize: function( opts ) { + this.listenTo( this.instance, 'relational:change:' + this.key, this.onChange ); // Handle a custom 'collectionType' this.collectionType = this.options.collectionType; if ( _.isString( this.collectionType ) ) { this.collectionType = Backbone.Relational.store.getObjectByName( this.collectionType ); } - if ( !this.collectionType.prototype instanceof Backbone.Collection ){ - throw new Error( 'collectionType must inherit from Backbone.Collection' ); + if ( this.collectionType !== Backbone.Collection && !( this.collectionType.prototype instanceof Backbone.Collection ) ) { + throw new Error( '`collectionType` must inherit from Backbone.Collection' ); } - // Handle cases where a model/relation is created with a collection passed straight into 'attributes' - if ( this.keyContents instanceof Backbone.Collection ) { - this.setRelated( this._prepareCollection( this.keyContents ) ); - } - else { - this.setRelated( this._prepareCollection() ); - } - - this.findRelated( { silent: true } ); - }, - - _getCollectionOptions: function() { - return _.isFunction( this.options.collectionOptions ) ? - this.options.collectionOptions( this.instance ) : - this.options.collectionOptions; + var related = this.findRelated( opts ); + this.setRelated( related ); }, /** * Bind events and setup collectionKeys for a collection that is to be used as the backing store for a HasMany. * If no 'collection' is supplied, a new collection will be created of the specified 'collectionType' option. * @param {Backbone.Collection} [collection] + * @return {Backbone.Collection} */ _prepareCollection: function( collection ) { if ( this.related ) { - this.related - .unbind( 'relational:add', this.handleAddition ) - .unbind( 'relational:remove', this.handleRemoval ) - .unbind( 'relational:reset', this.handleReset ) + this.stopListening( this.related ); } if ( !collection || !( collection instanceof Backbone.Collection ) ) { - collection = new this.collectionType( [], this._getCollectionOptions() ); + var options = _.isFunction( this.options.collectionOptions ) ? + this.options.collectionOptions( this.instance ) : this.options.collectionOptions; + + collection = new this.collectionType( null, options ); } collection.model = this.relatedModel; @@ -827,191 +872,191 @@ collection[ key ] = this.instance; } } - - collection - .bind( 'relational:add', this.handleAddition ) - .bind( 'relational:remove', this.handleRemoval ) - .bind( 'relational:reset', this.handleReset ); + + this.listenTo( collection, 'relational:add', this.handleAddition ) + .listenTo( collection, 'relational:remove', this.handleRemoval ) + .listenTo( collection, 'relational:reset', this.handleReset ); return collection; }, - + + /** + * Find related Models. + * @param {Object} [options] + * @return {Backbone.Collection} + */ findRelated: function( options ) { - if ( this.keyContents ) { - var models = []; + var related = null; + + options = _.defaults( { parse: this.options.parse }, options ); + + // Replace 'this.related' by 'this.keyContents' if it is a Backbone.Collection + if ( this.keyContents instanceof Backbone.Collection ) { + this._prepareCollection( this.keyContents ); + related = this.keyContents; + } + // Otherwise, 'this.keyContents' should be an array of related object ids. + // Re-use the current 'this.related' if it is a Backbone.Collection; otherwise, create a new collection. + else { + var toAdd = []; - if ( this.keyContents instanceof Backbone.Collection ) { - models = this.keyContents.models; + _.each( this.keyContents, function( attributes ) { + if ( attributes instanceof this.relatedModel ) { + var model = attributes; + } + else { + // If `merge` is true, update models here, instead of during update. + model = this.relatedModel.findOrCreate( attributes, + _.extend( { merge: true }, options, { create: this.options.createModels } ) + ); + } + + model && toAdd.push( model ); + }, this ); + + if ( this.related instanceof Backbone.Collection ) { + related = this.related; } else { - // Handle cases the an API/user supplies just an Object/id instead of an Array - this.keyContents = _.isArray( this.keyContents ) ? this.keyContents : [ this.keyContents ]; - - // Try to find instances of the appropriate 'relatedModel' in the store - _.each( this.keyContents, function( item ) { - var model = null; - if ( item instanceof this.relatedModel ) { - model = item; - } - else if ( item || item === 0 ) { // since 0 can be a valid `id` as well - model = this.relatedModel.findOrCreate( item, { create: this.options.createModels } ); - } - - if ( model && !this.related.getByCid( model ) && !this.related.get( model ) ) { - models.push( model ); - } - }, this ); + related = this._prepareCollection(); } - // Add all found 'models' in on go, so 'add' will only be called once (and thus 'sort', etc.) - if ( models.length ) { - options = this.unsanitizeOptions( options ); - this.related.add( models, options ); - } + // By now, both `merge` and `parse` will already have been executed for models if they were specified. + // Disable them to prevent additional calls. + related.set( toAdd, _.defaults( { merge: false, parse: false }, options ) ); + } + + // Remove entries from `keyIds` that were already part of the relation (and are thus 'unchanged') + this.keyIds = _.difference( this.keyIds, _.pluck( related.models, 'id' ) ); + + return related; + }, + + /** + * Normalize and reduce `keyContents` to a list of `ids`, for easier comparison + * @param {String|Number|String[]|Number[]|Backbone.Collection} keyContents + */ + setKeyContents: function( keyContents ) { + this.keyContents = keyContents instanceof Backbone.Collection ? keyContents : null; + this.keyIds = []; + + if ( !this.keyContents && ( keyContents || keyContents === 0 ) ) { // since 0 can be a valid `id` as well + // Handle cases the an API/user supplies just an Object/id instead of an Array + this.keyContents = _.isArray( keyContents ) ? keyContents : [ keyContents ]; + + _.each( this.keyContents, function( item ) { + var itemId = Backbone.Relational.store.resolveIdForItem( this.relatedModel, item ); + if ( itemId || itemId === 0 ) { + this.keyIds.push( itemId ); + } + }, this ); } }, - + /** - * If the key is changed, notify old & new reverse relations and initialize the new relation + * Event handler for `change:<key>`. + * If the contents of the key are changed, notify old & new reverse relations and initialize the new relation. */ onChange: function( model, attr, options ) { - options = this.sanitizeOptions( options ); - this.keyContents = attr; - - // Notify old 'related' object of the terminated relation - _.each( this.getReverseRelations(), function( relation ) { - relation.removeRelated( this.instance, options ); - }, this ); - - // Replace 'this.related' by 'attr' if it is a Backbone.Collection - if ( attr instanceof Backbone.Collection ) { - this._prepareCollection( attr ); - this.related = attr; - } - // Otherwise, 'attr' should be an array of related object ids. - // Re-use the current 'this.related' if it is a Backbone.Collection, and remove any current entries. - // Otherwise, create a new collection. - else { - var coll; + options = options ? _.clone( options ) : {}; + this.setKeyContents( attr ); + this.changed = false; - if ( this.related instanceof Backbone.Collection ) { - coll = this.related; - coll.remove( coll.models ); - } - else { - coll = this._prepareCollection(); - } + var related = this.findRelated( options ); + this.setRelated( related ); - this.setRelated( coll ); - this.findRelated( options ); - } - - // Notify new 'related' object of the new relation - _.each( this.getReverseRelations(), function( relation ) { - relation.addRelated( this.instance, options ); - }, this ); - - var dit = this; - Backbone.Relational.eventQueue.add( function() { - !options.silentChange && dit.instance.trigger( 'update:' + dit.key, dit.instance, dit.related, options ); - }); - }, - - tryAddRelated: function( model, options ) { - options = this.sanitizeOptions( options ); - if ( !this.related.getByCid( model ) && !this.related.get( model ) ) { - // Check if this new model was specified in 'this.keyContents' - var item = _.any( this.keyContents, function( item ) { - var id = Backbone.Relational.store.resolveIdForItem( this.relatedModel, item ); - return !_.isNull( id ) && id === model.id; - }, this ); - - if ( item ) { - this.related.add( model, options ); - } + if ( !options.silent ) { + var dit = this; + Backbone.Relational.eventQueue.add( function() { + // The `changed` flag can be set in `handleAddition` or `handleRemoval` + if ( dit.changed ) { + dit.instance.trigger( 'change:' + dit.key, dit.instance, dit.related, options, true ); + dit.changed = false; + } + }); } }, - + /** * When a model is added to a 'HasMany', trigger 'add' on 'this.instance' and notify reverse relations. * (should be 'HasOne', must set 'this.instance' as their related). - */ + */ handleAddition: function( model, coll, options ) { //console.debug('handleAddition called; args=%o', arguments); - // Make sure the model is in fact a valid model before continuing. - // (it can be invalid as a result of failing validation in Backbone.Collection._prepareModel) - if ( !( model instanceof Backbone.Model ) ) { - return; - } - - options = this.sanitizeOptions( options ); + options = options ? _.clone( options ) : {}; + this.changed = true; _.each( this.getReverseRelations( model ), function( relation ) { - relation.addRelated( this.instance, options ); - }, this ); + relation.addRelated( this.instance, options ); + }, this ); - // Only trigger 'add' once the newly added model is initialized (so, has it's relations set up) + // Only trigger 'add' once the newly added model is initialized (so, has its relations set up) var dit = this; - Backbone.Relational.eventQueue.add( function() { - !options.silentChange && dit.instance.trigger( 'add:' + dit.key, model, dit.related, options ); + !options.silent && Backbone.Relational.eventQueue.add( function() { + dit.instance.trigger( 'add:' + dit.key, model, dit.related, options ); }); }, - + /** * When a model is removed from a 'HasMany', trigger 'remove' on 'this.instance' and notify reverse relations. * (should be 'HasOne', which should be nullified) */ handleRemoval: function( model, coll, options ) { //console.debug('handleRemoval called; args=%o', arguments); - if ( !( model instanceof Backbone.Model ) ) { - return; - } - - options = this.sanitizeOptions( options ); + options = options ? _.clone( options ) : {}; + this.changed = true; _.each( this.getReverseRelations( model ), function( relation ) { - relation.removeRelated( this.instance, options ); - }, this ); + relation.removeRelated( this.instance, null, options ); + }, this ); var dit = this; - Backbone.Relational.eventQueue.add( function() { - !options.silentChange && dit.instance.trigger( 'remove:' + dit.key, model, dit.related, options ); + !options.silent && Backbone.Relational.eventQueue.add( function() { + dit.instance.trigger( 'remove:' + dit.key, model, dit.related, options ); }); }, handleReset: function( coll, options ) { - options = this.sanitizeOptions( options ); - var dit = this; - Backbone.Relational.eventQueue.add( function() { - !options.silentChange && dit.instance.trigger( 'reset:' + dit.key, dit.related, options ); + options = options ? _.clone( options ) : {}; + !options.silent && Backbone.Relational.eventQueue.add( function() { + dit.instance.trigger( 'reset:' + dit.key, dit.related, options ); }); }, - + + tryAddRelated: function( model, coll, options ) { + var item = _.contains( this.keyIds, model.id ); + + if ( item ) { + this.addRelated( model, options ); + this.keyIds = _.without( this.keyIds, model.id ); + } + }, + addRelated: function( model, options ) { + // Allow 'model' to set up its relations before proceeding. + // (which can result in a call to 'addRelated' from a relation of 'model') var dit = this; - options = this.unsanitizeOptions( options ); - model.queue( function() { // Queued to avoid errors for adding 'model' to the 'this.related' set twice - if ( dit.related && !dit.related.getByCid( model ) && !dit.related.get( model ) ) { - dit.related.add( model, options ); + model.queue( function() { + if ( dit.related && !dit.related.get( model ) ) { + dit.related.add( model, _.defaults( { parse: false }, options ) ); } }); }, - - removeRelated: function( model, options ) { - options = this.unsanitizeOptions( options ); - if ( this.related.getByCid( model ) || this.related.get( model ) ) { + + removeRelated: function( model, coll, options ) { + if ( this.related.get( model ) ) { this.related.remove( model, options ); } } }); - + /** * A type of Backbone.Model that also maintains relations to other models and collections. * New events when compared to the original: * - 'add:<key>' (model, related collection, options) * - 'remove:<key>' (model, related collection, options) - * - 'update:<key>' (model, related model or collection, options) + * - 'change:<key>' (model, related model or collection, options) */ Backbone.RelationalModel = Backbone.Model.extend({ relations: null, // Relation descriptions on the prototype @@ -1019,82 +1064,118 @@ _isInitialized: false, _deferProcessing: false, _queue: null, - + subModelTypeAttribute: 'type', subModelTypes: null, - + constructor: function( attributes, options ) { // Nasty hack, for cases like 'model.get( <HasMany key> ).add( item )'. - // Defer 'processQueue', so that when 'Relation.createModels' is used we: - // a) Survive 'Backbone.Collection.add'; this takes care we won't error on "can't add model to a set twice" - // (by creating a model from properties, having the model add itself to the collection via one of - // it's relations, then trying to add it to the collection). - // b) Trigger 'HasMany' collection events only after the model is really fully set up. - // Example that triggers both a and b: "p.get('jobs').add( { company: c, person: p } )". - var dit = this; + // Defer 'processQueue', so that when 'Relation.createModels' is used we trigger 'HasMany' + // collection events only after the model is really fully set up. + // Example: event for "p.on( 'add:jobs' )" -> "p.get('jobs').add( { company: c.id, person: p.id } )". if ( options && options.collection ) { + var dit = this, + collection = this.collection = options.collection; + + // Prevent `collection` from cascading down to nested models; they shouldn't go into this `if` clause. + delete options.collection; + this._deferProcessing = true; - + var processQueue = function( model ) { if ( model === dit ) { dit._deferProcessing = false; dit.processQueue(); - options.collection.unbind( 'relational:add', processQueue ); + collection.off( 'relational:add', processQueue ); } }; - options.collection.bind( 'relational:add', processQueue ); - - // So we do process the queue eventually, regardless of whether this model really gets added to 'options.collection'. + collection.on( 'relational:add', processQueue ); + + // So we do process the queue eventually, regardless of whether this model actually gets added to 'options.collection'. _.defer( function() { processQueue( dit ); }); } + + Backbone.Relational.store.processOrphanRelations(); this._queue = new Backbone.BlockingQueue(); this._queue.block(); Backbone.Relational.eventQueue.block(); - - Backbone.Model.apply( this, arguments ); - - // Try to run the global queue holding external events - Backbone.Relational.eventQueue.unblock(); + + try { + Backbone.Model.apply( this, arguments ); + } + finally { + // Try to run the global queue holding external events + Backbone.Relational.eventQueue.unblock(); + } }, - + /** * Override 'trigger' to queue 'change' and 'change:*' events */ trigger: function( eventName ) { - if ( eventName.length > 5 && 'change' === eventName.substr( 0, 6 ) ) { - var dit = this, args = arguments; + if ( eventName.length > 5 && eventName.indexOf( 'change' ) === 0 ) { + var dit = this, + args = arguments; + Backbone.Relational.eventQueue.add( function() { - Backbone.Model.prototype.trigger.apply( dit, args ); - }); + if ( !dit._isInitialized ) { + return; + } + + // Determine if the `change` event is still valid, now that all relations are populated + var changed = true; + if ( eventName === 'change' ) { + changed = dit.hasChanged(); + } + else { + var attr = eventName.slice( 7 ), + rel = dit.getRelation( attr ); + + if ( rel ) { + // If `attr` is a relation, `change:attr` get triggered from `Relation.onChange`. + // These take precedence over `change:attr` events triggered by `Model.set`. + // The relation set a fourth attribute to `true`. If this attribute is present, + // continue triggering this event; otherwise, it's from `Model.set` and should be stopped. + changed = ( args[ 4 ] === true ); + + // If this event was triggered by a relation, set the right value in `this.changed` + // (a Collection or Model instead of raw data). + if ( changed ) { + dit.changed[ attr ] = args[ 2 ]; + } + // Otherwise, this event is from `Model.set`. If the relation doesn't report a change, + // remove attr from `dit.changed` so `hasChanged` doesn't take it into account. + else if ( !rel.changed ) { + delete dit.changed[ attr ]; + } + } + } + + changed && Backbone.Model.prototype.trigger.apply( dit, args ); + }); } else { Backbone.Model.prototype.trigger.apply( this, arguments ); } - + return this; }, - + /** * Initialize Relations present in this.relations; determine the type (HasOne/HasMany), then creates a new instance. * Invoked in the first call so 'set' (which is made from the Backbone.Model constructor). */ - initializeRelations: function() { + initializeRelations: function( options ) { this.acquire(); // Setting up relations often also involve calls to 'set', and we only want to enter this function once - this._relations = []; - - _.each( this.relations, function( rel ) { - var type = !_.isString( rel.type ) ? rel.type : Backbone[ rel.type ] || Backbone.Relational.store.getObjectByName( rel.type ); - if ( type && type.prototype instanceof Backbone.Relation ) { - new type( this, rel ); // Also pushes the new Relation into _relations - } - else { - Backbone.Relational.showWarnings && typeof console !== 'undefined' && console.warn( 'Relation=%o; missing or invalid type!', rel ); - } - }, this ); - + this._relations = {}; + + _.each( this.relations || [], function( rel ) { + Backbone.Relational.store.initializeRelation( this, rel, options ); + }, this ); + this._isInitialized = true; this.release(); this.processQueue(); @@ -1115,14 +1196,14 @@ }, this ); } }, - + /** * Either add to the queue (if we're not initialized yet), or execute right away. */ queue: function( func ) { this._queue.add( func ); }, - + /** * Process _queue */ @@ -1131,68 +1212,71 @@ this._queue.unblock(); } }, - + /** * Get a specific relation. * @param key {string} The relation key to look for. * @return {Backbone.Relation} An instance of 'Backbone.Relation', if a relation was found for 'key', or null. */ getRelation: function( key ) { - return _.detect( this._relations, function( rel ) { - if ( rel.key === key ) { - return true; - } - }, this ); + return this._relations[ key ]; }, - + /** * Get all of the created relations. * @return {Backbone.Relation[]} */ getRelations: function() { - return this._relations; + return _.values( this._relations ); }, - + /** * Retrieve related objects. * @param key {string} The relation key to fetch models for. * @param [options] {Object} Options for 'Backbone.Model.fetch' and 'Backbone.sync'. - * @param [update=false] {boolean} Whether to force a fetch from the server (updating existing models). + * @param [refresh=false] {boolean} Fetch existing models from the server as well (in order to update them). * @return {jQuery.when[]} An array of request objects */ - fetchRelated: function( key, options, update ) { - options || ( options = {} ); + fetchRelated: function( key, options, refresh ) { + // Set default `options` for fetch + options = _.extend( { update: true, remove: false }, options ); + var setUrl, requests = [], rel = this.getRelation( key ), - keyContents = rel && rel.keyContents, - toFetch = keyContents && _.select( _.isArray( keyContents ) ? keyContents : [ keyContents ], function( item ) { - var id = Backbone.Relational.store.resolveIdForItem( rel.relatedModel, item ); - return !_.isNull( id ) && ( update || !Backbone.Relational.store.find( rel.relatedModel, id ) ); - }, this ); - - if ( toFetch && toFetch.length ) { - // Create a model for each entry in 'keyContents' that is to be fetched - var models = _.map( toFetch, function( item ) { - var model; + idsToFetch = rel && ( rel.keyIds || ( ( rel.keyId || rel.keyId === 0 ) ? [ rel.keyId ] : [] ) ); + + // On `refresh`, add the ids for current models in the relation to `idsToFetch` + if ( refresh ) { + var models = rel.related instanceof Backbone.Collection ? rel.related.models : [ rel.related ]; + _.each( models, function( model ) { + if ( model.id || model.id === 0 ) { + idsToFetch.push( model.id ); + } + }); + } - if ( _.isObject( item ) ) { - model = rel.relatedModel.build( item ); - } - else { - var attrs = {}; - attrs[ rel.relatedModel.prototype.idAttribute ] = item; - model = rel.relatedModel.build( attrs ); - } + if ( idsToFetch && idsToFetch.length ) { + // Find (or create) a model for each one that is to be fetched + var created = [], + models = _.map( idsToFetch, function( id ) { + var model = Backbone.Relational.store.find( rel.relatedModel, id ); + + if ( !model ) { + var attrs = {}; + attrs[ rel.relatedModel.prototype.idAttribute ] = id; + model = rel.relatedModel.findOrCreate( attrs, options ); + created.push( model ); + } - return model; - }, this ); + return model; + }, this ); // Try if the 'collection' can provide a url to fetch a set of models in one request. if ( rel.related instanceof Backbone.Collection && _.isFunction( rel.related.url ) ) { setUrl = rel.related.url( models ); } - + // An assumption is that when 'Backbone.Collection.url' is a function, it can handle building of set urls. // To make sure it can, test if the url we got by supplying a list of models to fetch is different from // the one supplied for the default fetch action (without args to 'url'). @@ -1201,15 +1285,14 @@ { error: function() { var args = arguments; - _.each( models, function( model ) { - model.trigger( 'destroy', model, model.collection, options ); - options.error && options.error.apply( model, args ); - }); + _.each( created, function( model ) { + model.trigger( 'destroy', model, model.collection, options ); + options.error && options.error.apply( model, args ); + }); }, url: setUrl }, - options, - { add: true } + options ); requests = [ rel.related.fetch( opts ) ]; @@ -1219,8 +1302,10 @@ var opts = _.defaults( { error: function() { - model.trigger( 'destroy', model, model.collection, options ); - options.error && options.error.apply( model, arguments ); + if ( _.contains( created, model ) ) { + model.trigger( 'destroy', model, model.collection, options ); + options.error && options.error.apply( model, arguments ); + } } }, options @@ -1232,10 +1317,35 @@ return requests; }, - + + get: function( attr ) { + var originalResult = Backbone.Model.prototype.get.call( this, attr ); + + // Use `originalResult` get if dotNotation not enabled or not required because no dot is in `attr` + if ( !this.dotNotation || attr.indexOf( '.' ) === -1 ) { + return originalResult; + } + + // Go through all splits and return the final result + var splits = attr.split( '.' ); + var result = _.reduce(splits, function( model, split ) { + if ( !( model instanceof Backbone.Model ) ) { + throw new Error( 'Attribute must be an instanceof Backbone.Model. Is: ' + model + ', currentSplit: ' + split ); + } + + return Backbone.Model.prototype.get.call( model, split ); + }, this ); + + if ( originalResult !== undefined && result !== undefined ) { + throw new Error( "Ambiguous result for '" + attr + "'. direct result: " + originalResult + ", dotNotation: " + result ); + } + + return originalResult || result; + }, + set: function( key, value, options ) { Backbone.Relational.eventQueue.block(); - + // Duplicate backbone's behavior to allow separate key/value parameters, instead of a single 'attributes' object var attributes; if ( _.isObject( key ) || key == null ) { @@ -1246,66 +1356,62 @@ attributes = {}; attributes[ key ] = value; } - - var result = Backbone.Model.prototype.set.apply( this, arguments ); - - // Ideal place to set up relations :) - if ( !this._isInitialized && !this.isLocked() ) { - this.constructor.initializeModelHierarchy(); + + try { + var id = this.id, + newId = attributes && this.idAttribute in attributes && attributes[ this.idAttribute ]; + + // Check if we're not setting a duplicate id before actually calling `set`. + Backbone.Relational.store.checkId( this, newId ); + + var result = Backbone.Model.prototype.set.apply( this, arguments ); - Backbone.Relational.store.register( this ); + // Ideal place to set up relations, if this is the first time we're here for this model + if ( !this._isInitialized && !this.isLocked() ) { + this.constructor.initializeModelHierarchy(); + Backbone.Relational.store.register( this ); + this.initializeRelations( options ); + } + // The store should know about an `id` update asap + else if ( newId && newId !== id ) { + Backbone.Relational.store.update( this ); + } - this.initializeRelations(); + if ( attributes ) { + this.updateRelations( options ); + } } - // Update the 'idAttribute' in Backbone.store if; we don't want it to miss an 'id' update due to {silent:true} - else if ( attributes && this.idAttribute in attributes ) { - Backbone.Relational.store.update( this ); + finally { + // Try to run the global queue holding external events + Backbone.Relational.eventQueue.unblock(); } - if ( attributes ) { - this.updateRelations( options ); - } - - // Try to run the global queue holding external events - Backbone.Relational.eventQueue.unblock(); - return result; }, - + unset: function( attribute, options ) { Backbone.Relational.eventQueue.block(); - + var result = Backbone.Model.prototype.unset.apply( this, arguments ); this.updateRelations( options ); - + // Try to run the global queue holding external events Backbone.Relational.eventQueue.unblock(); - + return result; }, - + clear: function( options ) { Backbone.Relational.eventQueue.block(); var result = Backbone.Model.prototype.clear.apply( this, arguments ); this.updateRelations( options ); - + // Try to run the global queue holding external events Backbone.Relational.eventQueue.unblock(); - + return result; }, - - /** - * Override 'change', so the change will only execute after 'set' has finised (relations are updated), - * and 'previousAttributes' will be available when the event is fired. - */ - change: function( options ) { - var dit = this, args = arguments; - Backbone.Relational.eventQueue.add( function() { - Backbone.Model.prototype.change.apply( dit, args ); - }); - }, clone: function() { var attributes = _.clone( this.attributes ); @@ -1314,87 +1420,97 @@ } _.each( this.getRelations(), function( rel ) { - delete attributes[ rel.key ]; - }); + delete attributes[ rel.key ]; + }); return new this.constructor( attributes ); }, - + /** * Convert relations to JSON, omits them when required */ - toJSON: function() { + toJSON: function( options ) { // If this Model has already been fully serialized in this branch once, return to avoid loops if ( this.isLocked() ) { return this.id; } - + this.acquire(); - var json = Backbone.Model.prototype.toJSON.call( this ); - + var json = Backbone.Model.prototype.toJSON.call( this, options ); + if ( this.constructor._superModel && !( this.constructor._subModelTypeAttribute in json ) ) { json[ this.constructor._subModelTypeAttribute ] = this.constructor._subModelTypeValue; } - + _.each( this._relations, function( rel ) { - var value = json[ rel.key ]; + var related = json[ rel.key ], + includeInJSON = rel.options.includeInJSON, + value = null; - if ( rel.options.includeInJSON === true) { - if ( value && _.isFunction( value.toJSON ) ) { - json[ rel.keyDestination ] = value.toJSON(); - } - else { - json[ rel.keyDestination ] = null; + if ( includeInJSON === true ) { + if ( related && _.isFunction( related.toJSON ) ) { + value = related.toJSON( options ); + } + } + else if ( _.isString( includeInJSON ) ) { + if ( related instanceof Backbone.Collection ) { + value = related.pluck( includeInJSON ); + } + else if ( related instanceof Backbone.Model ) { + value = related.get( includeInJSON ); + } + + // Add ids for 'unfound' models if includeInJSON is equal to (only) the relatedModel's `idAttribute` + if ( includeInJSON === rel.relatedModel.prototype.idAttribute ) { + if ( rel instanceof Backbone.HasMany ) { + value = value.concat( rel.keyIds ); } - } - else if ( _.isString( rel.options.includeInJSON ) ) { - if ( value instanceof Backbone.Collection ) { - json[ rel.keyDestination ] = value.pluck( rel.options.includeInJSON ); - } - else if ( value instanceof Backbone.Model ) { - json[ rel.keyDestination ] = value.get( rel.options.includeInJSON ); - } - else { - json[ rel.keyDestination ] = null; + else if ( rel instanceof Backbone.HasOne ) { + value = value || rel.keyId; } } - else if ( _.isArray( rel.options.includeInJSON ) ) { - if ( value instanceof Backbone.Collection ) { - var valueSub = []; - value.each( function( model ) { - var curJson = {}; - _.each( rel.options.includeInJSON, function( key ) { - curJson[ key ] = model.get( key ); - }); - valueSub.push( curJson ); + } + else if ( _.isArray( includeInJSON ) ) { + if ( related instanceof Backbone.Collection ) { + value = []; + related.each( function( model ) { + var curJson = {}; + _.each( includeInJSON, function( key ) { + curJson[ key ] = model.get( key ); }); - json[ rel.keyDestination ] = valueSub; - } - else if ( value instanceof Backbone.Model ) { - var valueSub = {}; - _.each( rel.options.includeInJSON, function( key ) { - valueSub[ key ] = value.get( key ); - }); - json[ rel.keyDestination ] = valueSub; - } - else { - json[ rel.keyDestination ] = null; - } + value.push( curJson ); + }); + } + else if ( related instanceof Backbone.Model ) { + value = {}; + _.each( includeInJSON, function( key ) { + value[ key ] = related.get( key ); + }); } - else { - delete json[ rel.key ]; - } + } + else { + delete json[ rel.key ]; + } - if ( rel.keyDestination !== rel.key ) { - delete json[ rel.key ]; - } - }); + if ( includeInJSON ) { + json[ rel.keyDestination ] = value; + } + + if ( rel.keyDestination !== rel.key ) { + delete json[ rel.key ]; + } + }); this.release(); return json; } }, { + /** + * + * @param superModel + * @returns {Backbone.RelationalModel.constructor} + */ setup: function( superModel ) { // We don't want to share a relations array with a parent, as this will cause problems with // reverse relations. @@ -1413,30 +1529,35 @@ } // Initialize all reverseRelations that belong to this new model. - _.each( this.prototype.relations, function( rel ) { - if ( !rel.model ) { - rel.model = this; + _.each( this.prototype.relations || [], function( rel ) { + if ( !rel.model ) { + rel.model = this; + } + + if ( rel.reverseRelation && rel.model === this ) { + var preInitialize = true; + if ( _.isString( rel.relatedModel ) ) { + /** + * The related model might not be defined for two reasons + * 1. it is related to itself + * 2. it never gets defined, e.g. a typo + * 3. the model hasn't been defined yet, but will be later + * In neither of these cases do we need to pre-initialize reverse relations. + * However, for 3. (which is, to us, indistinguishable from 2.), we do need to attempt + * setting up this relation again later, in case the related model is defined later. + */ + var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel ); + preInitialize = relatedModel && ( relatedModel.prototype instanceof Backbone.RelationalModel ); } - if ( rel.reverseRelation && rel.model === this ) { - var preInitialize = true; - if ( _.isString( rel.relatedModel ) ) { - /** - * The related model might not be defined for two reasons - * 1. it never gets defined, e.g. a typo - * 2. it is related to itself - * In neither of these cases do we need to pre-initialize reverse relations. - */ - var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel ); - preInitialize = relatedModel && ( relatedModel.prototype instanceof Backbone.RelationalModel ); - } - - var type = !_.isString( rel.type ) ? rel.type : Backbone[ rel.type ] || Backbone.Relational.store.getObjectByName( rel.type ); - if ( preInitialize && type && type.prototype instanceof Backbone.Relation ) { - new type( null, rel ); - } + if ( preInitialize ) { + Backbone.Relational.store.initializeRelation( null, rel ); } - }, this ); + else if ( _.isString( rel.relatedModel ) ) { + Backbone.Relational.store.addOrphanRelation( rel ); + } + } + }, this ); return this; }, @@ -1466,6 +1587,9 @@ return new model( attributes, options ); }, + /** + * + */ initializeModelHierarchy: function() { // If we're here for the first time, try to determine if this modelType has a 'superModel'. if ( _.isUndefined( this._superModel ) || _.isNull( this._superModel ) ) { @@ -1475,17 +1599,15 @@ // inherited automatically (due to a redefinition of 'relations'). // Otherwise, make sure we don't get here again for this type by making '_superModel' false so we fail // the isUndefined/isNull check next time. - if ( this._superModel ) { - // - if ( this._superModel.prototype.relations ) { - var supermodelRelationsExist = _.any( this.prototype.relations, function( rel ) { - return rel.model && rel.model !== this; + if ( this._superModel && this._superModel.prototype.relations ) { + // Find relations that exist on the `_superModel`, but not yet on this model. + var inheritedRelations = _.select( this._superModel.prototype.relations || [], function( superRel ) { + return !_.any( this.prototype.relations || [], function( rel ) { + return superRel.relatedModel === rel.relatedModel && superRel.key === rel.key; }, this ); + }, this ); - if ( !supermodelRelationsExist ) { - this.prototype.relations = this._superModel.prototype.relations.concat( this.prototype.relations ); - } - } + this.prototype.relations = inheritedRelations.concat( this.prototype.relations ); } else { this._superModel = false; @@ -1494,7 +1616,7 @@ // If we came here through 'build' for a model that has 'subModelTypes', and not all of them have been resolved yet, try to resolve each. if ( this.prototype.subModelTypes && _.keys( this.prototype.subModelTypes ).length !== _.keys( this._subModels ).length ) { - _.each( this.prototype.subModelTypes, function( subModelTypeName ) { + _.each( this.prototype.subModelTypes || [], function( subModelTypeName ) { var subModelType = Backbone.Relational.store.getObjectByName( subModelTypeName ); subModelType && subModelType.initializeModelHierarchy(); }); @@ -1504,24 +1626,33 @@ /** * Find an instance of `this` type in 'Backbone.Relational.store'. * - If `attributes` is a string or a number, `findOrCreate` will just query the `store` and return a model if found. - * - If `attributes` is an object, the model will be updated with `attributes` if found. + * - If `attributes` is an object and is found in the store, the model will be updated with `attributes` unless `options.update` is `false`. * Otherwise, a new model is created with `attributes` (unless `options.create` is explicitly set to `false`). * @param {Object|String|Number} attributes Either a model's id, or the attributes used to create or update a model. * @param {Object} [options] * @param {Boolean} [options.create=true] + * @param {Boolean} [options.merge=true] + * @param {Boolean} [options.parse=false] * @return {Backbone.RelationalModel} */ findOrCreate: function( attributes, options ) { + options || ( options = {} ); + var parsedAttributes = ( _.isObject( attributes ) && options.parse && this.prototype.parse ) ? + this.prototype.parse( attributes ) : attributes; + // Try to find an instance of 'this' model type in the store - var model = Backbone.Relational.store.find( this, attributes ); + var model = Backbone.Relational.store.find( this, parsedAttributes ); - // If we found an instance, update it with the data in 'item'; if not, create an instance - // (unless 'options.create' is false). + // If we found an instance, update it with the data in 'item' (unless 'options.merge' is false). + // If not, create an instance (unless 'options.create' is false). if ( _.isObject( attributes ) ) { - if ( model ) { - model.set( model.parse ? model.parse( attributes ) : attributes, options ); + if ( model && options.merge !== false ) { + // Make sure `options.collection` doesn't cascade to nested models + delete options.collection; + + model.set( parsedAttributes, options ); } - else if ( !options || ( options && options.create !== false ) ) { + else if ( !model && options.create !== false ) { model = this.build( attributes, options ); } } @@ -1530,18 +1661,27 @@ } }); _.extend( Backbone.RelationalModel.prototype, Backbone.Semaphore ); - + /** * Override Backbone.Collection._prepareModel, so objects will be built using the correct type * if the collection.model has subModels. + * Attempts to find a model for `attrs` in Backbone.store through `findOrCreate` + * (which sets the new properties on it if found), or instantiates a new model. */ Backbone.Collection.prototype.__prepareModel = Backbone.Collection.prototype._prepareModel; - Backbone.Collection.prototype._prepareModel = function ( model, options ) { - options || (options = {}); - if ( !( model instanceof Backbone.Model ) ) { - var attrs = model; + Backbone.Collection.prototype._prepareModel = function ( attrs, options ) { + var model; + + if ( attrs instanceof Backbone.Model ) { + if ( !attrs.collection ) { + attrs.collection = this; + } + model = attrs; + } + else { + options || ( options = {} ); options.collection = this; - + if ( typeof this.model.findOrCreate !== 'undefined' ) { model = this.model.findOrCreate( attrs, options ); } @@ -1549,78 +1689,100 @@ model = new this.model( attrs, options ); } - if ( !model._validate( model.attributes, options ) ) { + if ( model && model.isNew() && !model._validate( attrs, options ) ) { + this.trigger( 'invalid', this, attrs, options ); model = false; } } - else if ( !model.collection ) { - model.collection = this; - } return model; - } - + }; + + /** - * Override Backbone.Collection.add, so objects fetched from the server multiple times will - * update the existing Model. Also, trigger 'relational:add'. + * Override Backbone.Collection.set, so we'll create objects from attributes where required, + * and update the existing models. Also, trigger 'relational:add'. */ - var add = Backbone.Collection.prototype.__add = Backbone.Collection.prototype.add; - Backbone.Collection.prototype.add = function( models, options ) { - options || (options = {}); - if ( !_.isArray( models ) ) { - models = [ models ]; + var set = Backbone.Collection.prototype.__set = Backbone.Collection.prototype.set; + Backbone.Collection.prototype.set = function( models, options ) { + // Short-circuit if this Collection doesn't hold RelationalModels + if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) { + return set.apply( this, arguments ); } - var modelsToAdd = []; + if ( options && options.parse ) { + models = this.parse( models, options ); + } + + if ( !_.isArray( models ) ) { + models = models ? [ models ] : []; + } + + var newModels = [], + toAdd = []; //console.debug( 'calling add on coll=%o; model=%o, options=%o', this, models, options ); _.each( models, function( model ) { if ( !( model instanceof Backbone.Model ) ) { - // `_prepareModel` attempts to find `model` in Backbone.store through `findOrCreate`, - // and sets the new properties on it if is found. Otherwise, a new model is instantiated. model = Backbone.Collection.prototype._prepareModel.call( this, model, options ); } - if ( model instanceof Backbone.Model && !this.get( model ) && !this.getByCid( model ) ) { - modelsToAdd.push( model ); + if ( model ) { + toAdd.push( model ); + + if ( !( this.get( model ) || this.get( model.cid ) ) ) { + newModels.push( model ); + } + // If we arrive in `add` while performing a `set` (after a create, so the model gains an `id`), + // we may get here before `_onModelEvent` has had the chance to update `_byId`. + else if ( model.id != null ) { + this._byId[ model.id ] = model; + } } }, this ); - // Add 'models' in a single batch, so the original add will only be called once (and thus 'sort', etc). - if ( modelsToAdd.length ) { - add.call( this, modelsToAdd, options ); + // If `parse` was specified, the collection and contained models have been parsed now. + set.call( this, toAdd, _.defaults( { parse: false }, options ) ); - _.each( modelsToAdd, function( model ) { + _.each( newModels, function( model ) { + // Fire a `relational:add` event for any model in `newModels` that has actually been added to the collection. + if ( this.get( model ) || this.get( model.cid ) ) { this.trigger( 'relational:add', model, this, options ); - }, this ); - } + } + }, this ); return this; }; - + /** * Override 'Backbone.Collection.remove' to trigger 'relational:remove'. */ var remove = Backbone.Collection.prototype.__remove = Backbone.Collection.prototype.remove; Backbone.Collection.prototype.remove = function( models, options ) { - options || (options = {}); - if ( !_.isArray( models ) ) { - models = [ models ]; + // Short-circuit if this Collection doesn't hold RelationalModels + if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) { + return remove.apply( this, arguments ); } - else { - models = models.slice( 0 ); - } + + models = _.isArray( models ) ? models.slice() : [ models ]; + options || ( options = {} ); + + var toRemove = []; //console.debug('calling remove on coll=%o; models=%o, options=%o', this, models, options ); _.each( models, function( model ) { - model = this.getByCid( model ) || this.get( model ); + model = this.get( model ) || this.get( model.cid ); + model && toRemove.push( model ); + }, this ); - if ( model instanceof Backbone.Model ) { - remove.call( this, model, options ); - this.trigger('relational:remove', model, this, options); - } + if ( toRemove.length ) { + remove.call( this, toRemove, options ); + + _.each( toRemove, function( model ) { + this.trigger('relational:remove', model, this, options); }, this ); + } return this; }; @@ -1630,8 +1792,12 @@ */ var reset = Backbone.Collection.prototype.__reset = Backbone.Collection.prototype.reset; Backbone.Collection.prototype.reset = function( models, options ) { + options = _.extend( { merge: true }, options ); reset.call( this, models, options ); - this.trigger( 'relational:reset', this, options ); + + if ( this.model.prototype instanceof Backbone.RelationalModel ) { + this.trigger( 'relational:reset', this, options ); + } return this; }; @@ -1642,32 +1808,39 @@ var sort = Backbone.Collection.prototype.__sort = Backbone.Collection.prototype.sort; Backbone.Collection.prototype.sort = function( options ) { sort.call( this, options ); - this.trigger( 'relational:reset', this, options ); + + if ( this.model.prototype instanceof Backbone.RelationalModel ) { + this.trigger( 'relational:reset', this, options ); + } return this; }; - + /** * Override 'Backbone.Collection.trigger' so 'add', 'remove' and 'reset' events are queued until relations * are ready. */ var trigger = Backbone.Collection.prototype.__trigger = Backbone.Collection.prototype.trigger; Backbone.Collection.prototype.trigger = function( eventName ) { + // Short-circuit if this Collection doesn't hold RelationalModels + if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) { + return trigger.apply( this, arguments ); + } + if ( eventName === 'add' || eventName === 'remove' || eventName === 'reset' ) { - var dit = this, args = arguments; + var dit = this, + args = arguments; - if (eventName === 'add') { - args = _.toArray(args); - // the fourth argument in case of a regular add is the option object. + if ( _.isObject( args[ 3 ] ) ) { + args = _.toArray( args ); + // the fourth argument is the option object. // we need to clone it, as it could be modified while we wait on the eventQueue to be unblocked - if (_.isObject(args[3])) { - args[3] = _.clone(args[3]); - } + args[ 3 ] = _.clone( args[ 3 ] ); } Backbone.Relational.eventQueue.add( function() { - trigger.apply( dit, args ); - }); + trigger.apply( dit, args ); + }); } else { trigger.apply( this, arguments );
--- a/src/js/libs/backbone.js Wed Apr 03 15:44:17 2013 +0200 +++ b/src/js/libs/backbone.js Tue Apr 23 15:23:20 2013 +0200 @@ -1,1431 +1,4 @@ -// Backbone.js 0.9.2 - -// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc. -// Backbone may be freely distributed under the MIT license. -// For all details and documentation: -// http://backbonejs.org - -(function(){ - - // Initial Setup - // ------------- - - // Save a reference to the global object (`window` in the browser, `global` - // on the server). - var root = this; - - // Save the previous value of the `Backbone` variable, so that it can be - // restored later on, if `noConflict` is used. - var previousBackbone = root.Backbone; - - // Create a local reference to slice/splice. - var slice = Array.prototype.slice; - var splice = Array.prototype.splice; - - // The top-level namespace. All public Backbone classes and modules will - // be attached to this. Exported for both CommonJS and the browser. - var Backbone; - if (typeof exports !== 'undefined') { - Backbone = exports; - } else { - Backbone = root.Backbone = {}; - } - - // Current version of the library. Keep in sync with `package.json`. - Backbone.VERSION = '0.9.2'; - - // Require Underscore, if we're on the server, and it's not already present. - var _ = root._; - if (!_ && (typeof require !== 'undefined')) _ = require('underscore'); - - // For Backbone's purposes, jQuery, Zepto, or Ender owns the `$` variable. - var $ = root.jQuery || root.Zepto || root.ender; - - // Set the JavaScript library that will be used for DOM manipulation and - // Ajax calls (a.k.a. the `$` variable). By default Backbone will use: jQuery, - // Zepto, or Ender; but the `setDomLibrary()` method lets you inject an - // alternate JavaScript library (or a mock library for testing your views - // outside of a browser). - Backbone.setDomLibrary = function(lib) { - $ = lib; - }; - - // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable - // to its previous owner. Returns a reference to this Backbone object. - Backbone.noConflict = function() { - root.Backbone = previousBackbone; - return this; - }; - - // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option - // will fake `"PUT"` and `"DELETE"` requests via the `_method` parameter and - // set a `X-Http-Method-Override` header. - Backbone.emulateHTTP = false; - - // Turn on `emulateJSON` to support legacy servers that can't deal with direct - // `application/json` requests ... will encode the body as - // `application/x-www-form-urlencoded` instead and will send the model in a - // form param named `model`. - Backbone.emulateJSON = false; - - // Backbone.Events - // ----------------- - - // Regular expression used to split event strings - var eventSplitter = /\s+/; - - // A module that can be mixed in to *any object* in order to provide it with - // custom events. You may bind with `on` or remove with `off` callback functions - // to an event; trigger`-ing an event fires all callbacks in succession. - // - // var object = {}; - // _.extend(object, Backbone.Events); - // object.on('expand', function(){ alert('expanded'); }); - // object.trigger('expand'); - // - var Events = Backbone.Events = { - - // Bind one or more space separated events, `events`, to a `callback` - // function. Passing `"all"` will bind the callback to all events fired. - on: function(events, callback, context) { - - var calls, event, node, tail, list; - if (!callback) return this; - events = events.split(eventSplitter); - calls = this._callbacks || (this._callbacks = {}); - - // Create an immutable callback list, allowing traversal during - // modification. The tail is an empty object that will always be used - // as the next node. - while (event = events.shift()) { - list = calls[event]; - node = list ? list.tail : {}; - node.next = tail = {}; - node.context = context; - node.callback = callback; - calls[event] = {tail: tail, next: list ? list.next : node}; - } - - return this; - }, - - // Remove one or many callbacks. If `context` is null, removes all callbacks - // with that function. If `callback` is null, removes all callbacks for the - // event. If `events` is null, removes all bound callbacks for all events. - off: function(events, callback, context) { - var event, calls, node, tail, cb, ctx; - - // No events, or removing *all* events. - if (!(calls = this._callbacks)) return; - if (!(events || callback || context)) { - delete this._callbacks; - return this; - } - - // Loop through the listed events and contexts, splicing them out of the - // linked list of callbacks if appropriate. - events = events ? events.split(eventSplitter) : _.keys(calls); - while (event = events.shift()) { - node = calls[event]; - delete calls[event]; - if (!node || !(callback || context)) continue; - // Create a new list, omitting the indicated callbacks. - tail = node.tail; - while ((node = node.next) !== tail) { - cb = node.callback; - ctx = node.context; - if ((callback && cb !== callback) || (context && ctx !== context)) { - this.on(event, cb, ctx); - } - } - } - - return this; - }, - - // Trigger one or many events, firing all bound callbacks. Callbacks are - // passed the same arguments as `trigger` is, apart from the event name - // (unless you're listening on `"all"`, which will cause your callback to - // receive the true name of the event as the first argument). - trigger: function(events) { - var event, node, calls, tail, args, all, rest; - if (!(calls = this._callbacks)) return this; - all = calls.all; - events = events.split(eventSplitter); - rest = slice.call(arguments, 1); - - // For each event, walk through the linked list of callbacks twice, - // first to trigger the event, then to trigger any `"all"` callbacks. - while (event = events.shift()) { - if (node = calls[event]) { - tail = node.tail; - while ((node = node.next) !== tail) { - node.callback.apply(node.context || this, rest); - } - } - if (node = all) { - tail = node.tail; - args = [event].concat(rest); - while ((node = node.next) !== tail) { - node.callback.apply(node.context || this, args); - } - } - } - - return this; - } - - }; - - // Aliases for backwards compatibility. - Events.bind = Events.on; - Events.unbind = Events.off; - - // Backbone.Model - // -------------- - - // Create a new model, with defined attributes. A client id (`cid`) - // is automatically generated and assigned for you. - var Model = Backbone.Model = function(attributes, options) { - var defaults; - attributes || (attributes = {}); - if (options && options.parse) attributes = this.parse(attributes); - if (defaults = getValue(this, 'defaults')) { - attributes = _.extend({}, defaults, attributes); - } - if (options && options.collection) this.collection = options.collection; - this.attributes = {}; - this._escapedAttributes = {}; - this.cid = _.uniqueId('c'); - this.changed = {}; - this._silent = {}; - this._pending = {}; - this.set(attributes, {silent: true}); - // Reset change tracking. - this.changed = {}; - this._silent = {}; - this._pending = {}; - this._previousAttributes = _.clone(this.attributes); - this.initialize.apply(this, arguments); - }; - - // Attach all inheritable methods to the Model prototype. - _.extend(Model.prototype, Events, { - - // A hash of attributes whose current and previous value differ. - changed: null, - - // A hash of attributes that have silently changed since the last time - // `change` was called. Will become pending attributes on the next call. - _silent: null, - - // A hash of attributes that have changed since the last `'change'` event - // began. - _pending: null, - - // The default name for the JSON `id` attribute is `"id"`. MongoDB and - // CouchDB users may want to set this to `"_id"`. - idAttribute: 'id', - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // Return a copy of the model's `attributes` object. - toJSON: function(options) { - return _.clone(this.attributes); - }, - - // Get the value of an attribute. - get: function(attr) { - return this.attributes[attr]; - }, - - // Get the HTML-escaped value of an attribute. - escape: function(attr) { - var html; - if (html = this._escapedAttributes[attr]) return html; - var val = this.get(attr); - return this._escapedAttributes[attr] = _.escape(val == null ? '' : '' + val); - }, - - // Returns `true` if the attribute contains a value that is not null - // or undefined. - has: function(attr) { - return this.get(attr) != null; - }, - - // Set a hash of model attributes on the object, firing `"change"` unless - // you choose to silence it. - set: function(key, value, options) { - var attrs, attr, val; - - // Handle both `"key", value` and `{key: value}` -style arguments. - if (_.isObject(key) || key == null) { - attrs = key; - options = value; - } else { - attrs = {}; - attrs[key] = value; - } - - // Extract attributes and options. - options || (options = {}); - if (!attrs) return this; - if (attrs instanceof Model) attrs = attrs.attributes; - if (options.unset) for (attr in attrs) attrs[attr] = void 0; - - // Run validation. - if (!this._validate(attrs, options)) return false; - - // Check for changes of `id`. - if (this.idAttribute in attrs) this.id = attrs[this.idAttribute]; - - var changes = options.changes = {}; - var now = this.attributes; - var escaped = this._escapedAttributes; - var prev = this._previousAttributes || {}; - - // For each `set` attribute... - for (attr in attrs) { - val = attrs[attr]; - - // If the new and current value differ, record the change. - if (!_.isEqual(now[attr], val) || (options.unset && _.has(now, attr))) { - delete escaped[attr]; - (options.silent ? this._silent : changes)[attr] = true; - } - - // Update or delete the current value. - options.unset ? delete now[attr] : now[attr] = val; - - // If the new and previous value differ, record the change. If not, - // then remove changes for this attribute. - if (!_.isEqual(prev[attr], val) || (_.has(now, attr) != _.has(prev, attr))) { - this.changed[attr] = val; - if (!options.silent) this._pending[attr] = true; - } else { - delete this.changed[attr]; - delete this._pending[attr]; - } - } - - // Fire the `"change"` events. - if (!options.silent) this.change(options); - return this; - }, - - // Remove an attribute from the model, firing `"change"` unless you choose - // to silence it. `unset` is a noop if the attribute doesn't exist. - unset: function(attr, options) { - (options || (options = {})).unset = true; - return this.set(attr, null, options); - }, - - // Clear all attributes on the model, firing `"change"` unless you choose - // to silence it. - clear: function(options) { - (options || (options = {})).unset = true; - return this.set(_.clone(this.attributes), options); - }, - - // Fetch the model from the server. If the server's representation of the - // model differs from its current attributes, they will be overriden, - // triggering a `"change"` event. - fetch: function(options) { - options = options ? _.clone(options) : {}; - var model = this; - var success = options.success; - options.success = function(resp, status, xhr) { - if (!model.set(model.parse(resp, xhr), options)) return false; - if (success) success(model, resp); - }; - options.error = Backbone.wrapError(options.error, model, options); - return (this.sync || Backbone.sync).call(this, 'read', this, options); - }, - - // Set a hash of model attributes, and sync the model to the server. - // If the server returns an attributes hash that differs, the model's - // state will be `set` again. - save: function(key, value, options) { - var attrs, current; - - // Handle both `("key", value)` and `({key: value})` -style calls. - if (_.isObject(key) || key == null) { - attrs = key; - options = value; - } else { - attrs = {}; - attrs[key] = value; - } - options = options ? _.clone(options) : {}; - - // If we're "wait"-ing to set changed attributes, validate early. - if (options.wait) { - if (!this._validate(attrs, options)) return false; - current = _.clone(this.attributes); - } - - // Regular saves `set` attributes before persisting to the server. - var silentOptions = _.extend({}, options, {silent: true}); - if (attrs && !this.set(attrs, options.wait ? silentOptions : options)) { - return false; - } - - // After a successful server-side save, the client is (optionally) - // updated with the server-side state. - var model = this; - var success = options.success; - options.success = function(resp, status, xhr) { - var serverAttrs = model.parse(resp, xhr); - if (options.wait) { - delete options.wait; - serverAttrs = _.extend(attrs || {}, serverAttrs); - } - if (!model.set(serverAttrs, options)) return false; - if (success) { - success(model, resp); - } else { - model.trigger('sync', model, resp, options); - } - }; - - // Finish configuring and sending the Ajax request. - options.error = Backbone.wrapError(options.error, model, options); - var method = this.isNew() ? 'create' : 'update'; - var xhr = (this.sync || Backbone.sync).call(this, method, this, options); - if (options.wait) this.set(current, silentOptions); - return xhr; - }, - - // Destroy this model on the server if it was already persisted. - // Optimistically removes the model from its collection, if it has one. - // If `wait: true` is passed, waits for the server to respond before removal. - destroy: function(options) { - options = options ? _.clone(options) : {}; - var model = this; - var success = options.success; - - var triggerDestroy = function() { - model.trigger('destroy', model, model.collection, options); - }; - - if (this.isNew()) { - triggerDestroy(); - return false; - } - - options.success = function(resp) { - if (options.wait) triggerDestroy(); - if (success) { - success(model, resp); - } else { - model.trigger('sync', model, resp, options); - } - }; - - options.error = Backbone.wrapError(options.error, model, options); - var xhr = (this.sync || Backbone.sync).call(this, 'delete', this, options); - if (!options.wait) triggerDestroy(); - return xhr; - }, - - // Default URL for the model's representation on the server -- if you're - // using Backbone's restful methods, override this to change the endpoint - // that will be called. - url: function() { - var base = getValue(this, 'urlRoot') || getValue(this.collection, 'url') || urlError(); - if (this.isNew()) return base; - return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + encodeURIComponent(this.id); - }, - - // **parse** converts a response into the hash of attributes to be `set` on - // the model. The default implementation is just to pass the response along. - parse: function(resp, xhr) { - return resp; - }, - - // Create a new model with identical attributes to this one. - clone: function() { - return new this.constructor(this.attributes); - }, - - // A model is new if it has never been saved to the server, and lacks an id. - isNew: function() { - return this.id == null; - }, - - // Call this method to manually fire a `"change"` event for this model and - // a `"change:attribute"` event for each changed attribute. - // Calling this will cause all objects observing the model to update. - change: function(options) { - options || (options = {}); - var changing = this._changing; - this._changing = true; - - // Silent changes become pending changes. - for (var attr in this._silent) this._pending[attr] = true; - - // Silent changes are triggered. - var changes = _.extend({}, options.changes, this._silent); - this._silent = {}; - for (var attr in changes) { - this.trigger('change:' + attr, this, this.get(attr), options); - } - if (changing) return this; - - // Continue firing `"change"` events while there are pending changes. - while (!_.isEmpty(this._pending)) { - this._pending = {}; - this.trigger('change', this, options); - // Pending and silent changes still remain. - for (var attr in this.changed) { - if (this._pending[attr] || this._silent[attr]) continue; - delete this.changed[attr]; - } - this._previousAttributes = _.clone(this.attributes); - } - - this._changing = false; - return this; - }, - - // Determine if the model has changed since the last `"change"` event. - // If you specify an attribute name, determine if that attribute has changed. - hasChanged: function(attr) { - if (!arguments.length) return !_.isEmpty(this.changed); - return _.has(this.changed, attr); - }, - - // Return an object containing all the attributes that have changed, or - // false if there are no changed attributes. Useful for determining what - // parts of a view need to be updated and/or what attributes need to be - // persisted to the server. Unset attributes will be set to undefined. - // You can also pass an attributes object to diff against the model, - // determining if there *would be* a change. - changedAttributes: function(diff) { - if (!diff) return this.hasChanged() ? _.clone(this.changed) : false; - var val, changed = false, old = this._previousAttributes; - for (var attr in diff) { - if (_.isEqual(old[attr], (val = diff[attr]))) continue; - (changed || (changed = {}))[attr] = val; - } - return changed; - }, - - // Get the previous value of an attribute, recorded at the time the last - // `"change"` event was fired. - previous: function(attr) { - if (!arguments.length || !this._previousAttributes) return null; - return this._previousAttributes[attr]; - }, - - // Get all of the attributes of the model at the time of the previous - // `"change"` event. - previousAttributes: function() { - return _.clone(this._previousAttributes); - }, - - // Check if the model is currently in a valid state. It's only possible to - // get into an *invalid* state if you're using silent changes. - isValid: function() { - return !this.validate(this.attributes); - }, - - // Run validation against the next complete set of model attributes, - // returning `true` if all is well. If a specific `error` callback has - // been passed, call that instead of firing the general `"error"` event. - _validate: function(attrs, options) { - if (options.silent || !this.validate) return true; - attrs = _.extend({}, this.attributes, attrs); - var error = this.validate(attrs, options); - if (!error) return true; - if (options && options.error) { - options.error(this, error, options); - } else { - this.trigger('error', this, error, options); - } - return false; - } - - }); - - // Backbone.Collection - // ------------------- - - // Provides a standard collection class for our sets of models, ordered - // or unordered. If a `comparator` is specified, the Collection will maintain - // its models in sort order, as they're added and removed. - var Collection = Backbone.Collection = function(models, options) { - options || (options = {}); - if (options.model) this.model = options.model; - if (options.comparator) this.comparator = options.comparator; - this._reset(); - this.initialize.apply(this, arguments); - if (models) this.reset(models, {silent: true, parse: options.parse}); - }; - - // Define the Collection's inheritable methods. - _.extend(Collection.prototype, Events, { - - // The default model for a collection is just a **Backbone.Model**. - // This should be overridden in most cases. - model: Model, - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // The JSON representation of a Collection is an array of the - // models' attributes. - toJSON: function(options) { - return this.map(function(model){ return model.toJSON(options); }); - }, - - // Add a model, or list of models to the set. Pass **silent** to avoid - // firing the `add` event for every new model. - add: function(models, options) { - var i, index, length, model, cid, id, cids = {}, ids = {}, dups = []; - options || (options = {}); - models = _.isArray(models) ? models.slice() : [models]; - - // Begin by turning bare objects into model references, and preventing - // invalid models or duplicate models from being added. - for (i = 0, length = models.length; i < length; i++) { - if (!(model = models[i] = this._prepareModel(models[i], options))) { - throw new Error("Can't add an invalid model to a collection"); - } - cid = model.cid; - id = model.id; - if (cids[cid] || this._byCid[cid] || ((id != null) && (ids[id] || this._byId[id]))) { - dups.push(i); - continue; - } - cids[cid] = ids[id] = model; - } - - // Remove duplicates. - i = dups.length; - while (i--) { - models.splice(dups[i], 1); - } - - // Listen to added models' events, and index models for lookup by - // `id` and by `cid`. - for (i = 0, length = models.length; i < length; i++) { - (model = models[i]).on('all', this._onModelEvent, this); - this._byCid[model.cid] = model; - if (model.id != null) this._byId[model.id] = model; - } - - // Insert models into the collection, re-sorting if needed, and triggering - // `add` events unless silenced. - this.length += length; - index = options.at != null ? options.at : this.models.length; - splice.apply(this.models, [index, 0].concat(models)); - if (this.comparator) this.sort({silent: true}); - if (options.silent) return this; - for (i = 0, length = this.models.length; i < length; i++) { - if (!cids[(model = this.models[i]).cid]) continue; - options.index = i; - model.trigger('add', model, this, options); - } - return this; - }, - - // Remove a model, or a list of models from the set. Pass silent to avoid - // firing the `remove` event for every model removed. - remove: function(models, options) { - var i, l, index, model; - options || (options = {}); - models = _.isArray(models) ? models.slice() : [models]; - for (i = 0, l = models.length; i < l; i++) { - model = this.getByCid(models[i]) || this.get(models[i]); - if (!model) continue; - delete this._byId[model.id]; - delete this._byCid[model.cid]; - index = this.indexOf(model); - this.models.splice(index, 1); - this.length--; - if (!options.silent) { - options.index = index; - model.trigger('remove', model, this, options); - } - this._removeReference(model); - } - return this; - }, - - // Add a model to the end of the collection. - push: function(model, options) { - model = this._prepareModel(model, options); - this.add(model, options); - return model; - }, - - // Remove a model from the end of the collection. - pop: function(options) { - var model = this.at(this.length - 1); - this.remove(model, options); - return model; - }, - - // Add a model to the beginning of the collection. - unshift: function(model, options) { - model = this._prepareModel(model, options); - this.add(model, _.extend({at: 0}, options)); - return model; - }, - - // Remove a model from the beginning of the collection. - shift: function(options) { - var model = this.at(0); - this.remove(model, options); - return model; - }, - - // Get a model from the set by id. - get: function(id) { - if (id == null) return void 0; - return this._byId[id.id != null ? id.id : id]; - }, - - // Get a model from the set by client id. - getByCid: function(cid) { - return cid && this._byCid[cid.cid || cid]; - }, - - // Get the model at the given index. - at: function(index) { - return this.models[index]; - }, - - // Return models with matching attributes. Useful for simple cases of `filter`. - where: function(attrs) { - if (_.isEmpty(attrs)) return []; - return this.filter(function(model) { - for (var key in attrs) { - if (attrs[key] !== model.get(key)) return false; - } - return true; - }); - }, - - // Force the collection to re-sort itself. You don't need to call this under - // normal circumstances, as the set will maintain sort order as each item - // is added. - sort: function(options) { - options || (options = {}); - if (!this.comparator) throw new Error('Cannot sort a set without a comparator'); - var boundComparator = _.bind(this.comparator, this); - if (this.comparator.length == 1) { - this.models = this.sortBy(boundComparator); - } else { - this.models.sort(boundComparator); - } - if (!options.silent) this.trigger('reset', this, options); - return this; - }, - - // Pluck an attribute from each model in the collection. - pluck: function(attr) { - return _.map(this.models, function(model){ return model.get(attr); }); - }, - - // When you have more items than you want to add or remove individually, - // you can reset the entire set with a new list of models, without firing - // any `add` or `remove` events. Fires `reset` when finished. - reset: function(models, options) { - models || (models = []); - options || (options = {}); - for (var i = 0, l = this.models.length; i < l; i++) { - this._removeReference(this.models[i]); - } - this._reset(); - this.add(models, _.extend({silent: true}, options)); - if (!options.silent) this.trigger('reset', this, options); - return this; - }, - - // Fetch the default set of models for this collection, resetting the - // collection when they arrive. If `add: true` is passed, appends the - // models to the collection instead of resetting. - fetch: function(options) { - options = options ? _.clone(options) : {}; - if (options.parse === undefined) options.parse = true; - var collection = this; - var success = options.success; - options.success = function(resp, status, xhr) { - collection[options.add ? 'add' : 'reset'](collection.parse(resp, xhr), options); - if (success) success(collection, resp); - }; - options.error = Backbone.wrapError(options.error, collection, options); - return (this.sync || Backbone.sync).call(this, 'read', this, options); - }, - - // Create a new instance of a model in this collection. Add the model to the - // collection immediately, unless `wait: true` is passed, in which case we - // wait for the server to agree. - create: function(model, options) { - var coll = this; - options = options ? _.clone(options) : {}; - model = this._prepareModel(model, options); - if (!model) return false; - if (!options.wait) coll.add(model, options); - var success = options.success; - options.success = function(nextModel, resp, xhr) { - if (options.wait) coll.add(nextModel, options); - if (success) { - success(nextModel, resp); - } else { - nextModel.trigger('sync', model, resp, options); - } - }; - model.save(null, options); - return model; - }, - - // **parse** converts a response into a list of models to be added to the - // collection. The default implementation is just to pass it through. - parse: function(resp, xhr) { - return resp; - }, - - // Proxy to _'s chain. Can't be proxied the same way the rest of the - // underscore methods are proxied because it relies on the underscore - // constructor. - chain: function () { - return _(this.models).chain(); - }, - - // Reset all internal state. Called when the collection is reset. - _reset: function(options) { - this.length = 0; - this.models = []; - this._byId = {}; - this._byCid = {}; - }, - - // Prepare a model or hash of attributes to be added to this collection. - _prepareModel: function(model, options) { - options || (options = {}); - if (!(model instanceof Model)) { - var attrs = model; - options.collection = this; - model = new this.model(attrs, options); - if (!model._validate(model.attributes, options)) model = false; - } else if (!model.collection) { - model.collection = this; - } - return model; - }, - - // Internal method to remove a model's ties to a collection. - _removeReference: function(model) { - if (this == model.collection) { - delete model.collection; - } - model.off('all', this._onModelEvent, this); - }, - - // Internal method called every time a model in the set fires an event. - // Sets need to update their indexes when models change ids. All other - // events simply proxy through. "add" and "remove" events that originate - // in other collections are ignored. - _onModelEvent: function(event, model, collection, options) { - if ((event == 'add' || event == 'remove') && collection != this) return; - if (event == 'destroy') { - this.remove(model, options); - } - if (model && event === 'change:' + model.idAttribute) { - delete this._byId[model.previous(model.idAttribute)]; - this._byId[model.id] = model; - } - this.trigger.apply(this, arguments); - } - - }); - - // Underscore methods that we want to implement on the Collection. - var methods = ['forEach', 'each', 'map', 'reduce', 'reduceRight', 'find', - 'detect', 'filter', 'select', 'reject', 'every', 'all', 'some', 'any', - 'include', 'contains', 'invoke', 'max', 'min', 'sortBy', 'sortedIndex', - 'toArray', 'size', 'first', 'initial', 'rest', 'last', 'without', 'indexOf', - 'shuffle', 'lastIndexOf', 'isEmpty', 'groupBy']; - - // Mix in each Underscore method as a proxy to `Collection#models`. - _.each(methods, function(method) { - Collection.prototype[method] = function() { - return _[method].apply(_, [this.models].concat(_.toArray(arguments))); - }; - }); - - // Backbone.Router - // ------------------- - - // Routers map faux-URLs to actions, and fire events when routes are - // matched. Creating a new one sets its `routes` hash, if not set statically. - var Router = Backbone.Router = function(options) { - options || (options = {}); - if (options.routes) this.routes = options.routes; - this._bindRoutes(); - this.initialize.apply(this, arguments); - }; - - // Cached regular expressions for matching named param parts and splatted - // parts of route strings. - var namedParam = /:\w+/g; - var splatParam = /\*\w+/g; - var escapeRegExp = /[-[\]{}()+?.,\\^$|#\s]/g; - - // Set up all inheritable **Backbone.Router** properties and methods. - _.extend(Router.prototype, Events, { - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // Manually bind a single named route to a callback. For example: - // - // this.route('search/:query/p:num', 'search', function(query, num) { - // ... - // }); - // - route: function(route, name, callback) { - Backbone.history || (Backbone.history = new History); - if (!_.isRegExp(route)) route = this._routeToRegExp(route); - if (!callback) callback = this[name]; - Backbone.history.route(route, _.bind(function(fragment) { - var args = this._extractParameters(route, fragment); - callback && callback.apply(this, args); - this.trigger.apply(this, ['route:' + name].concat(args)); - Backbone.history.trigger('route', this, name, args); - }, this)); - return this; - }, - - // Simple proxy to `Backbone.history` to save a fragment into the history. - navigate: function(fragment, options) { - Backbone.history.navigate(fragment, options); - }, - - // Bind all defined routes to `Backbone.history`. We have to reverse the - // order of the routes here to support behavior where the most general - // routes can be defined at the bottom of the route map. - _bindRoutes: function() { - if (!this.routes) return; - var routes = []; - for (var route in this.routes) { - routes.unshift([route, this.routes[route]]); - } - for (var i = 0, l = routes.length; i < l; i++) { - this.route(routes[i][0], routes[i][1], this[routes[i][1]]); - } - }, - - // Convert a route string into a regular expression, suitable for matching - // against the current location hash. - _routeToRegExp: function(route) { - route = route.replace(escapeRegExp, '\\$&') - .replace(namedParam, '([^\/]+)') - .replace(splatParam, '(.*?)'); - return new RegExp('^' + route + '$'); - }, - - // Given a route, and a URL fragment that it matches, return the array of - // extracted parameters. - _extractParameters: function(route, fragment) { - return route.exec(fragment).slice(1); - } - - }); - - // Backbone.History - // ---------------- - - // Handles cross-browser history management, based on URL fragments. If the - // browser does not support `onhashchange`, falls back to polling. - var History = Backbone.History = function() { - this.handlers = []; - _.bindAll(this, 'checkUrl'); - }; - - // Cached regex for cleaning leading hashes and slashes . - var routeStripper = /^[#\/]/; - - // Cached regex for detecting MSIE. - var isExplorer = /msie [\w.]+/; - - // Has the history handling already been started? - History.started = false; - - // Set up all inheritable **Backbone.History** properties and methods. - _.extend(History.prototype, Events, { - - // The default interval to poll for hash changes, if necessary, is - // twenty times a second. - interval: 50, - - // Gets the true hash value. Cannot use location.hash directly due to bug - // in Firefox where location.hash will always be decoded. - getHash: function(windowOverride) { - var loc = windowOverride ? windowOverride.location : window.location; - var match = loc.href.match(/#(.*)$/); - return match ? match[1] : ''; - }, - - // Get the cross-browser normalized URL fragment, either from the URL, - // the hash, or the override. - getFragment: function(fragment, forcePushState) { - if (fragment == null) { - if (this._hasPushState || forcePushState) { - fragment = window.location.pathname; - var search = window.location.search; - if (search) fragment += search; - } else { - fragment = this.getHash(); - } - } - if (!fragment.indexOf(this.options.root)) fragment = fragment.substr(this.options.root.length); - return fragment.replace(routeStripper, ''); - }, - - // Start the hash change handling, returning `true` if the current URL matches - // an existing route, and `false` otherwise. - start: function(options) { - if (History.started) throw new Error("Backbone.history has already been started"); - History.started = true; - - // Figure out the initial configuration. Do we need an iframe? - // Is pushState desired ... is it available? - this.options = _.extend({}, {root: '/'}, this.options, options); - this._wantsHashChange = this.options.hashChange !== false; - this._wantsPushState = !!this.options.pushState; - this._hasPushState = !!(this.options.pushState && window.history && window.history.pushState); - var fragment = this.getFragment(); - var docMode = document.documentMode; - var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7)); - - if (oldIE) { - this.iframe = $('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow; - this.navigate(fragment); - } - - // Depending on whether we're using pushState or hashes, and whether - // 'onhashchange' is supported, determine how we check the URL state. - if (this._hasPushState) { - $(window).bind('popstate', this.checkUrl); - } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) { - $(window).bind('hashchange', this.checkUrl); - } else if (this._wantsHashChange) { - this._checkUrlInterval = setInterval(this.checkUrl, this.interval); - } - - // Determine if we need to change the base url, for a pushState link - // opened by a non-pushState browser. - this.fragment = fragment; - var loc = window.location; - var atRoot = loc.pathname == this.options.root; - - // If we've started off with a route from a `pushState`-enabled browser, - // but we're currently in a browser that doesn't support it... - if (this._wantsHashChange && this._wantsPushState && !this._hasPushState && !atRoot) { - this.fragment = this.getFragment(null, true); - window.location.replace(this.options.root + '#' + this.fragment); - // Return immediately as browser will do redirect to new url - return true; - - // Or if we've started out with a hash-based route, but we're currently - // in a browser where it could be `pushState`-based instead... - } else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) { - this.fragment = this.getHash().replace(routeStripper, ''); - window.history.replaceState({}, document.title, loc.protocol + '//' + loc.host + this.options.root + this.fragment); - } - - if (!this.options.silent) { - return this.loadUrl(); - } - }, - - // Disable Backbone.history, perhaps temporarily. Not useful in a real app, - // but possibly useful for unit testing Routers. - stop: function() { - $(window).unbind('popstate', this.checkUrl).unbind('hashchange', this.checkUrl); - clearInterval(this._checkUrlInterval); - History.started = false; - }, - - // Add a route to be tested when the fragment changes. Routes added later - // may override previous routes. - route: function(route, callback) { - this.handlers.unshift({route: route, callback: callback}); - }, - - // Checks the current URL to see if it has changed, and if it has, - // calls `loadUrl`, normalizing across the hidden iframe. - checkUrl: function(e) { - var current = this.getFragment(); - if (current == this.fragment && this.iframe) current = this.getFragment(this.getHash(this.iframe)); - if (current == this.fragment) return false; - if (this.iframe) this.navigate(current); - this.loadUrl() || this.loadUrl(this.getHash()); - }, - - // Attempt to load the current URL fragment. If a route succeeds with a - // match, returns `true`. If no defined routes matches the fragment, - // returns `false`. - loadUrl: function(fragmentOverride) { - var fragment = this.fragment = this.getFragment(fragmentOverride); - var matched = _.any(this.handlers, function(handler) { - if (handler.route.test(fragment)) { - handler.callback(fragment); - return true; - } - }); - return matched; - }, - - // Save a fragment into the hash history, or replace the URL state if the - // 'replace' option is passed. You are responsible for properly URL-encoding - // the fragment in advance. - // - // The options object can contain `trigger: true` if you wish to have the - // route callback be fired (not usually desirable), or `replace: true`, if - // you wish to modify the current URL without adding an entry to the history. - navigate: function(fragment, options) { - if (!History.started) return false; - if (!options || options === true) options = {trigger: options}; - var frag = (fragment || '').replace(routeStripper, ''); - if (this.fragment == frag) return; - - // If pushState is available, we use it to set the fragment as a real URL. - if (this._hasPushState) { - if (frag.indexOf(this.options.root) != 0) frag = this.options.root + frag; - this.fragment = frag; - window.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, frag); - - // If hash changes haven't been explicitly disabled, update the hash - // fragment to store history. - } else if (this._wantsHashChange) { - this.fragment = frag; - this._updateHash(window.location, frag, options.replace); - if (this.iframe && (frag != this.getFragment(this.getHash(this.iframe)))) { - // Opening and closing the iframe tricks IE7 and earlier to push a history entry on hash-tag change. - // When replace is true, we don't want this. - if(!options.replace) this.iframe.document.open().close(); - this._updateHash(this.iframe.location, frag, options.replace); - } - - // If you've told us that you explicitly don't want fallback hashchange- - // based history, then `navigate` becomes a page refresh. - } else { - window.location.assign(this.options.root + fragment); - } - if (options.trigger) this.loadUrl(fragment); - }, - - // Update the hash location, either replacing the current entry, or adding - // a new one to the browser history. - _updateHash: function(location, fragment, replace) { - if (replace) { - location.replace(location.toString().replace(/(javascript:|#).*$/, '') + '#' + fragment); - } else { - location.hash = fragment; - } - } - }); - - // Backbone.View - // ------------- - - // Creating a Backbone.View creates its initial element outside of the DOM, - // if an existing element is not provided... - var View = Backbone.View = function(options) { - this.cid = _.uniqueId('view'); - this._configure(options || {}); - this._ensureElement(); - this.initialize.apply(this, arguments); - this.delegateEvents(); - }; - - // Cached regex to split keys for `delegate`. - var delegateEventSplitter = /^(\S+)\s*(.*)$/; - - // List of view options to be merged as properties. - var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName']; - - // Set up all inheritable **Backbone.View** properties and methods. - _.extend(View.prototype, Events, { - - // The default `tagName` of a View's element is `"div"`. - tagName: 'div', - - // jQuery delegate for element lookup, scoped to DOM elements within the - // current view. This should be prefered to global lookups where possible. - $: function(selector) { - return this.$el.find(selector); - }, - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // **render** is the core function that your view should override, in order - // to populate its element (`this.el`), with the appropriate HTML. The - // convention is for **render** to always return `this`. - render: function() { - return this; - }, - - // Remove this view from the DOM. Note that the view isn't present in the - // DOM by default, so calling this method may be a no-op. - remove: function() { - this.$el.remove(); - return this; - }, - - // For small amounts of DOM Elements, where a full-blown template isn't - // needed, use **make** to manufacture elements, one at a time. - // - // var el = this.make('li', {'class': 'row'}, this.model.escape('title')); - // - make: function(tagName, attributes, content) { - var el = document.createElement(tagName); - if (attributes) $(el).attr(attributes); - if (content) $(el).html(content); - return el; - }, - - // Change the view's element (`this.el` property), including event - // re-delegation. - setElement: function(element, delegate) { - if (this.$el) this.undelegateEvents(); - this.$el = (element instanceof $) ? element : $(element); - this.el = this.$el[0]; - if (delegate !== false) this.delegateEvents(); - return this; - }, - - // Set callbacks, where `this.events` is a hash of - // - // *{"event selector": "callback"}* - // - // { - // 'mousedown .title': 'edit', - // 'click .button': 'save' - // 'click .open': function(e) { ... } - // } - // - // pairs. Callbacks will be bound to the view, with `this` set properly. - // Uses event delegation for efficiency. - // Omitting the selector binds the event to `this.el`. - // This only works for delegate-able events: not `focus`, `blur`, and - // not `change`, `submit`, and `reset` in Internet Explorer. - delegateEvents: function(events) { - if (!(events || (events = getValue(this, 'events')))) return; - this.undelegateEvents(); - for (var key in events) { - var method = events[key]; - if (!_.isFunction(method)) method = this[events[key]]; - if (!method) throw new Error('Method "' + events[key] + '" does not exist'); - var match = key.match(delegateEventSplitter); - var eventName = match[1], selector = match[2]; - method = _.bind(method, this); - eventName += '.delegateEvents' + this.cid; - if (selector === '') { - this.$el.bind(eventName, method); - } else { - this.$el.delegate(selector, eventName, method); - } - } - }, - - // Clears all callbacks previously bound to the view with `delegateEvents`. - // You usually don't need to use this, but may wish to if you have multiple - // Backbone views attached to the same DOM element. - undelegateEvents: function() { - this.$el.unbind('.delegateEvents' + this.cid); - }, - - // Performs the initial configuration of a View with a set of options. - // Keys with special meaning *(model, collection, id, className)*, are - // attached directly to the view. - _configure: function(options) { - if (this.options) options = _.extend({}, this.options, options); - for (var i = 0, l = viewOptions.length; i < l; i++) { - var attr = viewOptions[i]; - if (options[attr]) this[attr] = options[attr]; - } - this.options = options; - }, - - // Ensure that the View has a DOM element to render into. - // If `this.el` is a string, pass it through `$()`, take the first - // matching element, and re-assign it to `el`. Otherwise, create - // an element from the `id`, `className` and `tagName` properties. - _ensureElement: function() { - if (!this.el) { - var attrs = getValue(this, 'attributes') || {}; - if (this.id) attrs.id = this.id; - if (this.className) attrs['class'] = this.className; - this.setElement(this.make(this.tagName, attrs), false); - } else { - this.setElement(this.el, false); - } - } - - }); - - // The self-propagating extend function that Backbone classes use. - var extend = function (protoProps, classProps) { - var child = inherits(this, protoProps, classProps); - child.extend = this.extend; - return child; - }; - - // Set up inheritance for the model, collection, and view. - Model.extend = Collection.extend = Router.extend = View.extend = extend; - - // Backbone.sync - // ------------- - - // Map from CRUD to HTTP for our default `Backbone.sync` implementation. - var methodMap = { - 'create': 'POST', - 'update': 'PUT', - 'delete': 'DELETE', - 'read': 'GET' - }; - - // Override this function to change the manner in which Backbone persists - // models to the server. You will be passed the type of request, and the - // model in question. By default, makes a RESTful Ajax request - // to the model's `url()`. Some possible customizations could be: - // - // * Use `setTimeout` to batch rapid-fire updates into a single request. - // * Send up the models as XML instead of JSON. - // * Persist models via WebSockets instead of Ajax. - // - // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests - // as `POST`, with a `_method` parameter containing the true HTTP method, - // as well as all requests with the body as `application/x-www-form-urlencoded` - // instead of `application/json` with the model in a param named `model`. - // Useful when interfacing with server-side languages like **PHP** that make - // it difficult to read the body of `PUT` requests. - Backbone.sync = function(method, model, options) { - var type = methodMap[method]; - - // Default options, unless specified. - options || (options = {}); - - // Default JSON-request options. - var params = {type: type, dataType: 'json'}; - - // Ensure that we have a URL. - if (!options.url) { - params.url = getValue(model, 'url') || urlError(); - } - - // Ensure that we have the appropriate request data. - if (!options.data && model && (method == 'create' || method == 'update')) { - params.contentType = 'application/json'; - params.data = JSON.stringify(model.toJSON()); - } - - // For older servers, emulate JSON by encoding the request into an HTML-form. - if (Backbone.emulateJSON) { - params.contentType = 'application/x-www-form-urlencoded'; - params.data = params.data ? {model: params.data} : {}; - } - - // For older servers, emulate HTTP by mimicking the HTTP method with `_method` - // And an `X-HTTP-Method-Override` header. - if (Backbone.emulateHTTP) { - if (type === 'PUT' || type === 'DELETE') { - if (Backbone.emulateJSON) params.data._method = type; - params.type = 'POST'; - params.beforeSend = function(xhr) { - xhr.setRequestHeader('X-HTTP-Method-Override', type); - }; - } - } - - // Don't process data on a non-GET request. - if (params.type !== 'GET' && !Backbone.emulateJSON) { - params.processData = false; - } - - // Make the request, allowing the user to override any Ajax options. - return $.ajax(_.extend(params, options)); - }; - - // Wrap an optional error callback with a fallback error event. - Backbone.wrapError = function(onError, originalModel, options) { - return function(model, resp) { - resp = model === originalModel ? resp : model; - if (onError) { - onError(originalModel, resp, options); - } else { - originalModel.trigger('error', originalModel, resp, options); - } - }; - }; - - // Helpers - // ------- - - // Shared empty constructor function to aid in prototype-chain creation. - var ctor = function(){}; - - // Helper function to correctly set up the prototype chain, for subclasses. - // Similar to `goog.inherits`, but uses a hash of prototype properties and - // class properties to be extended. - var inherits = function(parent, protoProps, staticProps) { - var child; - - // The constructor function for the new subclass is either defined by you - // (the "constructor" property in your `extend` definition), or defaulted - // by us to simply call the parent's constructor. - if (protoProps && protoProps.hasOwnProperty('constructor')) { - child = protoProps.constructor; - } else { - child = function(){ parent.apply(this, arguments); }; - } - - // Inherit class (static) properties from parent. - _.extend(child, parent); - - // Set the prototype chain to inherit from `parent`, without calling - // `parent`'s constructor function. - ctor.prototype = parent.prototype; - child.prototype = new ctor(); - - // Add prototype properties (instance properties) to the subclass, - // if supplied. - if (protoProps) _.extend(child.prototype, protoProps); - - // Add static properties to the constructor function, if supplied. - if (staticProps) _.extend(child, staticProps); - - // Correctly set child's `prototype.constructor`. - child.prototype.constructor = child; - - // Set a convenience property in case the parent's prototype is needed later. - child.__super__ = parent.prototype; - - return child; - }; - - // Helper function to get a value from a Backbone object as a property - // or as a function. - var getValue = function(object, prop) { - if (!(object && object[prop])) return null; - return _.isFunction(object[prop]) ? object[prop]() : object[prop]; - }; - - // Throw an error when a URL is needed, and none is supplied. - var urlError = function() { - throw new Error('A "url" property or function must be specified'); - }; - -}).call(this); +(function(){var t=this;var e=t.Backbone;var i=[];var r=i.push;var s=i.slice;var n=i.splice;var a;if(typeof exports!=="undefined"){a=exports}else{a=t.Backbone={}}a.VERSION="1.0.0";var h=t._;if(!h&&typeof require!=="undefined")h=require("underscore");a.$=t.jQuery||t.Zepto||t.ender||t.$;a.noConflict=function(){t.Backbone=e;return this};a.emulateHTTP=false;a.emulateJSON=false;var o=a.Events={on:function(t,e,i){if(!l(this,"on",t,[e,i])||!e)return this;this._events||(this._events={});var r=this._events[t]||(this._events[t]=[]);r.push({callback:e,context:i,ctx:i||this});return this},once:function(t,e,i){if(!l(this,"once",t,[e,i])||!e)return this;var r=this;var s=h.once(function(){r.off(t,s);e.apply(this,arguments)});s._callback=e;return this.on(t,s,i)},off:function(t,e,i){var r,s,n,a,o,u,c,f;if(!this._events||!l(this,"off",t,[e,i]))return this;if(!t&&!e&&!i){this._events={};return this}a=t?[t]:h.keys(this._events);for(o=0,u=a.length;o<u;o++){t=a[o];if(n=this._events[t]){this._events[t]=r=[];if(e||i){for(c=0,f=n.length;c<f;c++){s=n[c];if(e&&e!==s.callback&&e!==s.callback._callback||i&&i!==s.context){r.push(s)}}}if(!r.length)delete this._events[t]}}return this},trigger:function(t){if(!this._events)return this;var e=s.call(arguments,1);if(!l(this,"trigger",t,e))return this;var i=this._events[t];var r=this._events.all;if(i)c(i,e);if(r)c(r,arguments);return this},stopListening:function(t,e,i){var r=this._listeners;if(!r)return this;var s=!e&&!i;if(typeof e==="object")i=this;if(t)(r={})[t._listenerId]=t;for(var n in r){r[n].off(e,i,this);if(s)delete this._listeners[n]}return this}};var u=/\s+/;var l=function(t,e,i,r){if(!i)return true;if(typeof i==="object"){for(var s in i){t[e].apply(t,[s,i[s]].concat(r))}return false}if(u.test(i)){var n=i.split(u);for(var a=0,h=n.length;a<h;a++){t[e].apply(t,[n[a]].concat(r))}return false}return true};var c=function(t,e){var i,r=-1,s=t.length,n=e[0],a=e[1],h=e[2];switch(e.length){case 0:while(++r<s)(i=t[r]).callback.call(i.ctx);return;case 1:while(++r<s)(i=t[r]).callback.call(i.ctx,n);return;case 2:while(++r<s)(i=t[r]).callback.call(i.ctx,n,a);return;case 3:while(++r<s)(i=t[r]).callback.call(i.ctx,n,a,h);return;default:while(++r<s)(i=t[r]).callback.apply(i.ctx,e)}};var f={listenTo:"on",listenToOnce:"once"};h.each(f,function(t,e){o[e]=function(e,i,r){var s=this._listeners||(this._listeners={});var n=e._listenerId||(e._listenerId=h.uniqueId("l"));s[n]=e;if(typeof i==="object")r=this;e[t](i,r,this);return this}});o.bind=o.on;o.unbind=o.off;h.extend(a,o);var d=a.Model=function(t,e){var i;var r=t||{};e||(e={});this.cid=h.uniqueId("c");this.attributes={};h.extend(this,h.pick(e,p));if(e.parse)r=this.parse(r,e)||{};if(i=h.result(this,"defaults")){r=h.defaults({},r,i)}this.set(r,e);this.changed={};this.initialize.apply(this,arguments)};var p=["url","urlRoot","collection"];h.extend(d.prototype,o,{changed:null,validationError:null,idAttribute:"id",initialize:function(){},toJSON:function(t){return h.clone(this.attributes)},sync:function(){return a.sync.apply(this,arguments)},get:function(t){return this.attributes[t]},escape:function(t){return h.escape(this.get(t))},has:function(t){return this.get(t)!=null},set:function(t,e,i){var r,s,n,a,o,u,l,c;if(t==null)return this;if(typeof t==="object"){s=t;i=e}else{(s={})[t]=e}i||(i={});if(!this._validate(s,i))return false;n=i.unset;o=i.silent;a=[];u=this._changing;this._changing=true;if(!u){this._previousAttributes=h.clone(this.attributes);this.changed={}}c=this.attributes,l=this._previousAttributes;if(this.idAttribute in s)this.id=s[this.idAttribute];for(r in s){e=s[r];if(!h.isEqual(c[r],e))a.push(r);if(!h.isEqual(l[r],e)){this.changed[r]=e}else{delete this.changed[r]}n?delete c[r]:c[r]=e}if(!o){if(a.length)this._pending=true;for(var f=0,d=a.length;f<d;f++){this.trigger("change:"+a[f],this,c[a[f]],i)}}if(u)return this;if(!o){while(this._pending){this._pending=false;this.trigger("change",this,i)}}this._pending=false;this._changing=false;return this},unset:function(t,e){return this.set(t,void 0,h.extend({},e,{unset:true}))},clear:function(t){var e={};for(var i in this.attributes)e[i]=void 0;return this.set(e,h.extend({},t,{unset:true}))},hasChanged:function(t){if(t==null)return!h.isEmpty(this.changed);return h.has(this.changed,t)},changedAttributes:function(t){if(!t)return this.hasChanged()?h.clone(this.changed):false;var e,i=false;var r=this._changing?this._previousAttributes:this.attributes;for(var s in t){if(h.isEqual(r[s],e=t[s]))continue;(i||(i={}))[s]=e}return i},previous:function(t){if(t==null||!this._previousAttributes)return null;return this._previousAttributes[t]},previousAttributes:function(){return h.clone(this._previousAttributes)},fetch:function(t){t=t?h.clone(t):{};if(t.parse===void 0)t.parse=true;var e=this;var i=t.success;t.success=function(r){if(!e.set(e.parse(r,t),t))return false;if(i)i(e,r,t);e.trigger("sync",e,r,t)};R(this,t);return this.sync("read",this,t)},save:function(t,e,i){var r,s,n,a=this.attributes;if(t==null||typeof t==="object"){r=t;i=e}else{(r={})[t]=e}if(r&&(!i||!i.wait)&&!this.set(r,i))return false;i=h.extend({validate:true},i);if(!this._validate(r,i))return false;if(r&&i.wait){this.attributes=h.extend({},a,r)}if(i.parse===void 0)i.parse=true;var o=this;var u=i.success;i.success=function(t){o.attributes=a;var e=o.parse(t,i);if(i.wait)e=h.extend(r||{},e);if(h.isObject(e)&&!o.set(e,i)){return false}if(u)u(o,t,i);o.trigger("sync",o,t,i)};R(this,i);s=this.isNew()?"create":i.patch?"patch":"update";if(s==="patch")i.attrs=r;n=this.sync(s,this,i);if(r&&i.wait)this.attributes=a;return n},destroy:function(t){t=t?h.clone(t):{};var e=this;var i=t.success;var r=function(){e.trigger("destroy",e,e.collection,t)};t.success=function(s){if(t.wait||e.isNew())r();if(i)i(e,s,t);if(!e.isNew())e.trigger("sync",e,s,t)};if(this.isNew()){t.success();return false}R(this,t);var s=this.sync("delete",this,t);if(!t.wait)r();return s},url:function(){var t=h.result(this,"urlRoot")||h.result(this.collection,"url")||U();if(this.isNew())return t;return t+(t.charAt(t.length-1)==="/"?"":"/")+encodeURIComponent(this.id)},parse:function(t,e){return t},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return this.id==null},isValid:function(t){return this._validate({},h.extend(t||{},{validate:true}))},_validate:function(t,e){if(!e.validate||!this.validate)return true;t=h.extend({},this.attributes,t);var i=this.validationError=this.validate(t,e)||null;if(!i)return true;this.trigger("invalid",this,i,h.extend(e||{},{validationError:i}));return false}});var v=["keys","values","pairs","invert","pick","omit"];h.each(v,function(t){d.prototype[t]=function(){var e=s.call(arguments);e.unshift(this.attributes);return h[t].apply(h,e)}});var g=a.Collection=function(t,e){e||(e={});if(e.url)this.url=e.url;if(e.model)this.model=e.model;if(e.comparator!==void 0)this.comparator=e.comparator;this._reset();this.initialize.apply(this,arguments);if(t)this.reset(t,h.extend({silent:true},e))};var m={add:true,remove:true,merge:true};var y={add:true,merge:false,remove:false};h.extend(g.prototype,o,{model:d,initialize:function(){},toJSON:function(t){return this.map(function(e){return e.toJSON(t)})},sync:function(){return a.sync.apply(this,arguments)},add:function(t,e){return this.set(t,h.defaults(e||{},y))},remove:function(t,e){t=h.isArray(t)?t.slice():[t];e||(e={});var i,r,s,n;for(i=0,r=t.length;i<r;i++){n=this.get(t[i]);if(!n)continue;delete this._byId[n.id];delete this._byId[n.cid];s=this.indexOf(n);this.models.splice(s,1);this.length--;if(!e.silent){e.index=s;n.trigger("remove",n,this,e)}this._removeReference(n)}return this},set:function(t,e){e=h.defaults(e||{},m);if(e.parse)t=this.parse(t,e);if(!h.isArray(t))t=t?[t]:[];var i,s,a,o,u,l;var c=e.at;var f=this.comparator&&c==null&&e.sort!==false;var d=h.isString(this.comparator)?this.comparator:null;var p=[],v=[],g={};for(i=0,s=t.length;i<s;i++){if(!(a=this._prepareModel(t[i],e)))continue;if(u=this.get(a)){if(e.remove)g[u.cid]=true;if(e.merge){u.set(a.attributes,e);if(f&&!l&&u.hasChanged(d))l=true}}else if(e.add){p.push(a);a.on("all",this._onModelEvent,this);this._byId[a.cid]=a;if(a.id!=null)this._byId[a.id]=a}}if(e.remove){for(i=0,s=this.length;i<s;++i){if(!g[(a=this.models[i]).cid])v.push(a)}if(v.length)this.remove(v,e)}if(p.length){if(f)l=true;this.length+=p.length;if(c!=null){n.apply(this.models,[c,0].concat(p))}else{r.apply(this.models,p)}}if(l)this.sort({silent:true});if(e.silent)return this;for(i=0,s=p.length;i<s;i++){(a=p[i]).trigger("add",a,this,e)}if(l)this.trigger("sort",this,e);return this},reset:function(t,e){e||(e={});for(var i=0,r=this.models.length;i<r;i++){this._removeReference(this.models[i])}e.previousModels=this.models;this._reset();this.add(t,h.extend({silent:true},e));if(!e.silent)this.trigger("reset",this,e);return this},push:function(t,e){t=this._prepareModel(t,e);this.add(t,h.extend({at:this.length},e));return t},pop:function(t){var e=this.at(this.length-1);this.remove(e,t);return e},unshift:function(t,e){t=this._prepareModel(t,e);this.add(t,h.extend({at:0},e));return t},shift:function(t){var e=this.at(0);this.remove(e,t);return e},slice:function(t,e){return this.models.slice(t,e)},get:function(t){if(t==null)return void 0;return this._byId[t.id!=null?t.id:t.cid||t]},at:function(t){return this.models[t]},where:function(t,e){if(h.isEmpty(t))return e?void 0:[];return this[e?"find":"filter"](function(e){for(var i in t){if(t[i]!==e.get(i))return false}return true})},findWhere:function(t){return this.where(t,true)},sort:function(t){if(!this.comparator)throw new Error("Cannot sort a set without a comparator");t||(t={});if(h.isString(this.comparator)||this.comparator.length===1){this.models=this.sortBy(this.comparator,this)}else{this.models.sort(h.bind(this.comparator,this))}if(!t.silent)this.trigger("sort",this,t);return this},sortedIndex:function(t,e,i){e||(e=this.comparator);var r=h.isFunction(e)?e:function(t){return t.get(e)};return h.sortedIndex(this.models,t,r,i)},pluck:function(t){return h.invoke(this.models,"get",t)},fetch:function(t){t=t?h.clone(t):{};if(t.parse===void 0)t.parse=true;var e=t.success;var i=this;t.success=function(r){var s=t.reset?"reset":"set";i[s](r,t);if(e)e(i,r,t);i.trigger("sync",i,r,t)};R(this,t);return this.sync("read",this,t)},create:function(t,e){e=e?h.clone(e):{};if(!(t=this._prepareModel(t,e)))return false;if(!e.wait)this.add(t,e);var i=this;var r=e.success;e.success=function(s){if(e.wait)i.add(t,e);if(r)r(t,s,e)};t.save(null,e);return t},parse:function(t,e){return t},clone:function(){return new this.constructor(this.models)},_reset:function(){this.length=0;this.models=[];this._byId={}},_prepareModel:function(t,e){if(t instanceof d){if(!t.collection)t.collection=this;return t}e||(e={});e.collection=this;var i=new this.model(t,e);if(!i._validate(t,e)){this.trigger("invalid",this,t,e);return false}return i},_removeReference:function(t){if(this===t.collection)delete t.collection;t.off("all",this._onModelEvent,this)},_onModelEvent:function(t,e,i,r){if((t==="add"||t==="remove")&&i!==this)return;if(t==="destroy")this.remove(e,r);if(e&&t==="change:"+e.idAttribute){delete this._byId[e.previous(e.idAttribute)];if(e.id!=null)this._byId[e.id]=e}this.trigger.apply(this,arguments)}});var _=["forEach","each","map","collect","reduce","foldl","inject","reduceRight","foldr","find","detect","filter","select","reject","every","all","some","any","include","contains","invoke","max","min","toArray","size","first","head","take","initial","rest","tail","drop","last","without","indexOf","shuffle","lastIndexOf","isEmpty","chain"];h.each(_,function(t){g.prototype[t]=function(){var e=s.call(arguments);e.unshift(this.models);return h[t].apply(h,e)}});var w=["groupBy","countBy","sortBy"];h.each(w,function(t){g.prototype[t]=function(e,i){var r=h.isFunction(e)?e:function(t){return t.get(e)};return h[t](this.models,r,i)}});var b=a.View=function(t){this.cid=h.uniqueId("view");this._configure(t||{});this._ensureElement();this.initialize.apply(this,arguments);this.delegateEvents()};var x=/^(\S+)\s*(.*)$/;var E=["model","collection","el","id","attributes","className","tagName","events"];h.extend(b.prototype,o,{tagName:"div",$:function(t){return this.$el.find(t)},initialize:function(){},render:function(){return this},remove:function(){this.$el.remove();this.stopListening();return this},setElement:function(t,e){if(this.$el)this.undelegateEvents();this.$el=t instanceof a.$?t:a.$(t);this.el=this.$el[0];if(e!==false)this.delegateEvents();return this},delegateEvents:function(t){if(!(t||(t=h.result(this,"events"))))return this;this.undelegateEvents();for(var e in t){var i=t[e];if(!h.isFunction(i))i=this[t[e]];if(!i)continue;var r=e.match(x);var s=r[1],n=r[2];i=h.bind(i,this);s+=".delegateEvents"+this.cid;if(n===""){this.$el.on(s,i)}else{this.$el.on(s,n,i)}}return this},undelegateEvents:function(){this.$el.off(".delegateEvents"+this.cid);return this},_configure:function(t){if(this.options)t=h.extend({},h.result(this,"options"),t);h.extend(this,h.pick(t,E));this.options=t},_ensureElement:function(){if(!this.el){var t=h.extend({},h.result(this,"attributes"));if(this.id)t.id=h.result(this,"id");if(this.className)t["class"]=h.result(this,"className");var e=a.$("<"+h.result(this,"tagName")+">").attr(t);this.setElement(e,false)}else{this.setElement(h.result(this,"el"),false)}}});a.sync=function(t,e,i){var r=k[t];h.defaults(i||(i={}),{emulateHTTP:a.emulateHTTP,emulateJSON:a.emulateJSON});var s={type:r,dataType:"json"};if(!i.url){s.url=h.result(e,"url")||U()}if(i.data==null&&e&&(t==="create"||t==="update"||t==="patch")){s.contentType="application/json";s.data=JSON.stringify(i.attrs||e.toJSON(i))}if(i.emulateJSON){s.contentType="application/x-www-form-urlencoded";s.data=s.data?{model:s.data}:{}}if(i.emulateHTTP&&(r==="PUT"||r==="DELETE"||r==="PATCH")){s.type="POST";if(i.emulateJSON)s.data._method=r;var n=i.beforeSend;i.beforeSend=function(t){t.setRequestHeader("X-HTTP-Method-Override",r);if(n)return n.apply(this,arguments)}}if(s.type!=="GET"&&!i.emulateJSON){s.processData=false}if(s.type==="PATCH"&&window.ActiveXObject&&!(window.external&&window.external.msActiveXFilteringEnabled)){s.xhr=function(){return new ActiveXObject("Microsoft.XMLHTTP")}}var o=i.xhr=a.ajax(h.extend(s,i));e.trigger("request",e,o,i);return o};var k={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};a.ajax=function(){return a.$.ajax.apply(a.$,arguments)};var S=a.Router=function(t){t||(t={});if(t.routes)this.routes=t.routes;this._bindRoutes();this.initialize.apply(this,arguments)};var $=/\((.*?)\)/g;var T=/(\(\?)?:\w+/g;var H=/\*\w+/g;var A=/[\-{}\[\]+?.,\\\^$|#\s]/g;h.extend(S.prototype,o,{initialize:function(){},route:function(t,e,i){if(!h.isRegExp(t))t=this._routeToRegExp(t);if(h.isFunction(e)){i=e;e=""}if(!i)i=this[e];var r=this;a.history.route(t,function(s){var n=r._extractParameters(t,s);i&&i.apply(r,n);r.trigger.apply(r,["route:"+e].concat(n));r.trigger("route",e,n);a.history.trigger("route",r,e,n)});return this},navigate:function(t,e){a.history.navigate(t,e);return this},_bindRoutes:function(){if(!this.routes)return;this.routes=h.result(this,"routes");var t,e=h.keys(this.routes);while((t=e.pop())!=null){this.route(t,this.routes[t])}},_routeToRegExp:function(t){t=t.replace(A,"\\$&").replace($,"(?:$1)?").replace(T,function(t,e){return e?t:"([^/]+)"}).replace(H,"(.*?)");return new RegExp("^"+t+"$")},_extractParameters:function(t,e){var i=t.exec(e).slice(1);return h.map(i,function(t){return t?decodeURIComponent(t):null})}});var I=a.History=function(){this.handlers=[];h.bindAll(this,"checkUrl");if(typeof window!=="undefined"){this.location=window.location;this.history=window.history}};var N=/^[#\/]|\s+$/g;var P=/^\/+|\/+$/g;var O=/msie [\w.]+/;var C=/\/$/;I.started=false;h.extend(I.prototype,o,{interval:50,getHash:function(t){var e=(t||this).location.href.match(/#(.*)$/);return e?e[1]:""},getFragment:function(t,e){if(t==null){if(this._hasPushState||!this._wantsHashChange||e){t=this.location.pathname;var i=this.root.replace(C,"");if(!t.indexOf(i))t=t.substr(i.length)}else{t=this.getHash()}}return t.replace(N,"")},start:function(t){if(I.started)throw new Error("Backbone.history has already been started");I.started=true;this.options=h.extend({},{root:"/"},this.options,t);this.root=this.options.root;this._wantsHashChange=this.options.hashChange!==false;this._wantsPushState=!!this.options.pushState;this._hasPushState=!!(this.options.pushState&&this.history&&this.history.pushState);var e=this.getFragment();var i=document.documentMode;var r=O.exec(navigator.userAgent.toLowerCase())&&(!i||i<=7);this.root=("/"+this.root+"/").replace(P,"/");if(r&&this._wantsHashChange){this.iframe=a.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow;this.navigate(e)}if(this._hasPushState){a.$(window).on("popstate",this.checkUrl)}else if(this._wantsHashChange&&"onhashchange"in window&&!r){a.$(window).on("hashchange",this.checkUrl)}else if(this._wantsHashChange){this._checkUrlInterval=setInterval(this.checkUrl,this.interval)}this.fragment=e;var s=this.location;var n=s.pathname.replace(/[^\/]$/,"$&/")===this.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!n){this.fragment=this.getFragment(null,true);this.location.replace(this.root+this.location.search+"#"+this.fragment);return true}else if(this._wantsPushState&&this._hasPushState&&n&&s.hash){this.fragment=this.getHash().replace(N,"");this.history.replaceState({},document.title,this.root+this.fragment+s.search)}if(!this.options.silent)return this.loadUrl()},stop:function(){a.$(window).off("popstate",this.checkUrl).off("hashchange",this.checkUrl);clearInterval(this._checkUrlInterval);I.started=false},route:function(t,e){this.handlers.unshift({route:t,callback:e})},checkUrl:function(t){var e=this.getFragment();if(e===this.fragment&&this.iframe){e=this.getFragment(this.getHash(this.iframe))}if(e===this.fragment)return false;if(this.iframe)this.navigate(e);this.loadUrl()||this.loadUrl(this.getHash())},loadUrl:function(t){var e=this.fragment=this.getFragment(t);var i=h.any(this.handlers,function(t){if(t.route.test(e)){t.callback(e);return true}});return i},navigate:function(t,e){if(!I.started)return false;if(!e||e===true)e={trigger:e};t=this.getFragment(t||"");if(this.fragment===t)return;this.fragment=t;var i=this.root+t;if(this._hasPushState){this.history[e.replace?"replaceState":"pushState"]({},document.title,i)}else if(this._wantsHashChange){this._updateHash(this.location,t,e.replace);if(this.iframe&&t!==this.getFragment(this.getHash(this.iframe))){if(!e.replace)this.iframe.document.open().close();this._updateHash(this.iframe.location,t,e.replace)}}else{return this.location.assign(i)}if(e.trigger)this.loadUrl(t)},_updateHash:function(t,e,i){if(i){var r=t.href.replace(/(javascript:|#).*$/,"");t.replace(r+"#"+e)}else{t.hash="#"+e}}});a.history=new I;var j=function(t,e){var i=this;var r;if(t&&h.has(t,"constructor")){r=t.constructor}else{r=function(){return i.apply(this,arguments)}}h.extend(r,i,e);var s=function(){this.constructor=r};s.prototype=i.prototype;r.prototype=new s;if(t)h.extend(r.prototype,t);r.__super__=i.prototype;return r};d.extend=g.extend=S.extend=b.extend=I.extend=j;var U=function(){throw new Error('A "url" property or function must be specified')};var R=function(t,e){var i=e.error;e.error=function(r){if(i)i(t,r,e);t.trigger("error",t,r,e)}}}).call(this); +/* +//@ sourceMappingURL=backbone-min.map +*/ \ No newline at end of file
--- a/src/js/libs/jquery.min.js Wed Apr 03 15:44:17 2013 +0200 +++ b/src/js/libs/jquery.min.js Tue Apr 23 15:23:20 2013 +0200 @@ -1,5 +1,6 @@ -/*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license +/*! jQuery v2.0.0 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license //@ sourceMappingURL=jquery.min.map -*/(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav></:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj; -return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="<a name='"+x+"'></a><div name='"+x+"'></div>",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="<input type='hidden' i=''/>",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&>(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Nt=/^(?:checkbox|radio)$/i,Ct=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l) -}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("<div>").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window); \ No newline at end of file +*/ +(function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],f="2.0.0",p=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=f.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return p.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,f,p,h,d,g,m,y="sizzle"+-new Date,v=e.document,b={},w=0,T=0,C=ot(),k=ot(),N=ot(),E=!1,S=function(){return 0},j=typeof undefined,D=1<<31,A=[],L=A.pop,q=A.push,H=A.push,O=A.slice,F=A.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},P="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",R="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=M.replace("w","w#"),$="\\["+R+"*("+M+")"+R+"*(?:([*^$|!~]?=)"+R+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+R+"*\\]",B=":("+M+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",I=RegExp("^"+R+"+|((?:^|[^\\\\])(?:\\\\.)*)"+R+"+$","g"),z=RegExp("^"+R+"*,"+R+"*"),_=RegExp("^"+R+"*([>+~]|"+R+")"+R+"*"),X=RegExp(R+"*[+~]"),U=RegExp("="+R+"*([^\\]'\"]*)"+R+"*\\]","g"),Y=RegExp(B),V=RegExp("^"+W+"$"),G={ID:RegExp("^#("+M+")"),CLASS:RegExp("^\\.("+M+")"),TAG:RegExp("^("+M.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+B),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+R+"*(even|odd|(([+-]|)(\\d*)n|)"+R+"*(?:([+-]|)"+R+"*(\\d+)|))"+R+"*\\)|)","i"),"boolean":RegExp("^(?:"+P+")$","i"),needsContext:RegExp("^"+R+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+R+"*((?:-\\d)?\\d*)"+R+"*\\)|)(?=[^-]|$)","i")},J=/^[^{]+\{\s*\[native \w/,Q=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,et=/'|\\/g,tt=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,nt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{H.apply(A=O.call(v.childNodes),v.childNodes),A[v.childNodes.length].nodeType}catch(rt){H={apply:A.length?function(e,t){q.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function it(e){return J.test(e+"")}function ot(){var e,t=[];return e=function(n,i){return t.push(n+=" ")>r.cacheLength&&delete e[t.shift()],e[n]=i}}function st(e){return e[y]=!0,e}function at(e){var t=c.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ut(e,t,n,r){var i,o,s,a,u,f,d,g,x,w;if((t?t.ownerDocument||t:v)!==c&&l(t),t=t||c,n=n||[],!e||"string"!=typeof e)return n;if(1!==(a=t.nodeType)&&9!==a)return[];if(p&&!r){if(i=Q.exec(e))if(s=i[1]){if(9===a){if(o=t.getElementById(s),!o||!o.parentNode)return n;if(o.id===s)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(s))&&m(t,o)&&o.id===s)return n.push(o),n}else{if(i[2])return H.apply(n,t.getElementsByTagName(e)),n;if((s=i[3])&&b.getElementsByClassName&&t.getElementsByClassName)return H.apply(n,t.getElementsByClassName(s)),n}if(b.qsa&&(!h||!h.test(e))){if(g=d=y,x=t,w=9===a&&e,1===a&&"object"!==t.nodeName.toLowerCase()){f=gt(e),(d=t.getAttribute("id"))?g=d.replace(et,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=f.length;while(u--)f[u]=g+mt(f[u]);x=X.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return H.apply(n,x.querySelectorAll(w)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(I,"$1"),t,n,r)}o=ut.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},l=ut.setDocument=function(e){var t=e?e.ownerDocument||e:v;return t!==c&&9===t.nodeType&&t.documentElement?(c=t,f=t.documentElement,p=!o(t),b.getElementsByTagName=at(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),b.attributes=at(function(e){return e.className="i",!e.getAttribute("className")}),b.getElementsByClassName=at(function(e){return e.innerHTML="<div class='a'></div><div class='a i'></div>",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),b.sortDetached=at(function(e){return 1&e.compareDocumentPosition(c.createElement("div"))}),b.getById=at(function(e){return f.appendChild(e).id=y,!t.getElementsByName||!t.getElementsByName(y).length}),b.getById?(r.find.ID=function(e,t){if(typeof t.getElementById!==j&&p){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},r.filter.ID=function(e){var t=e.replace(tt,nt);return function(e){return e.getAttribute("id")===t}}):(r.find.ID=function(e,t){if(typeof t.getElementById!==j&&p){var n=t.getElementById(e);return n?n.id===e||typeof n.getAttributeNode!==j&&n.getAttributeNode("id").value===e?[n]:undefined:[]}},r.filter.ID=function(e){var t=e.replace(tt,nt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),r.find.TAG=b.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=b.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&p?t.getElementsByClassName(e):undefined},d=[],h=[],(b.qsa=it(t.querySelectorAll))&&(at(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||h.push("\\["+R+"*(?:value|"+P+")"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){var t=c.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&h.push("[*^$]="+R+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(b.matchesSelector=it(g=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){b.disconnectedMatch=g.call(e,"div"),g.call(e,"[s!='']:x"),d.push("!=",B)}),h=h.length&&RegExp(h.join("|")),d=d.length&&RegExp(d.join("|")),m=it(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},S=f.compareDocumentPosition?function(e,n){if(e===n)return E=!0,0;var r=n.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(n);return r?1&r||!b.sortDetached&&n.compareDocumentPosition(e)===r?e===t||m(v,e)?-1:n===t||m(v,n)?1:u?F.call(u,e)-F.call(u,n):0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],l=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:u?F.call(u,e)-F.call(u,n):0;if(o===s)return lt(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)l.unshift(r);while(a[i]===l[i])i++;return i?lt(a[i],l[i]):a[i]===v?-1:l[i]===v?1:0},c):c},ut.matches=function(e,t){return ut(e,null,null,t)},ut.matchesSelector=function(e,t){if((e.ownerDocument||e)!==c&&l(e),t=t.replace(U,"='$1']"),!(!b.matchesSelector||!p||d&&d.test(t)||h&&h.test(t)))try{var n=g.call(e,t);if(n||b.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return ut(t,c,null,[e]).length>0},ut.contains=function(e,t){return(e.ownerDocument||e)!==c&&l(e),m(e,t)},ut.attr=function(e,t){(e.ownerDocument||e)!==c&&l(e);var n=r.attrHandle[t.toLowerCase()],i=n&&n(e,t,!p);return i===undefined?b.attributes||!p?e.getAttribute(t):(i=e.getAttributeNode(t))&&i.specified?i.value:null:i},ut.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ut.uniqueSort=function(e){var t,n=[],r=0,i=0;if(E=!b.detectDuplicates,u=!b.sortStable&&e.slice(0),e.sort(S),E){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return e};function lt(e,t){var n=t&&e,r=n&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ct(e,t,n){var r;return n?undefined:(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===!0?t.toLowerCase():null}function ft(e,t,n){var r;return n?undefined:r=e.getAttribute(t,"type"===t.toLowerCase()?1:2)}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ht(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function dt(e){return st(function(t){return t=+t,st(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}i=ut.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else for(;t=e[r];r++)n+=i(t);return n},r=ut.selectors={cacheLength:50,createPseudo:st,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(tt,nt),e[3]=(e[4]||e[5]||"").replace(tt,nt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ut.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ut.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return G.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&Y.test(n)&&(t=gt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(tt,nt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+R+")"+e+"("+R+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ut.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,v=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){f=t;while(f=f[g])if(a?f.nodeName.toLowerCase()===v:1===f.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[y]||(m[y]={}),l=c[e]||[],h=l[0]===w&&l[1],p=l[0]===w&&l[2],f=h&&m.childNodes[h];while(f=++h&&f&&f[g]||(p=h=0)||d.pop())if(1===f.nodeType&&++p&&f===t){c[e]=[w,h,p];break}}else if(x&&(l=(t[y]||(t[y]={}))[e])&&l[0]===w)p=l[1];else while(f=++h&&f&&f[g]||(p=h=0)||d.pop())if((a?f.nodeName.toLowerCase()===v:1===f.nodeType)&&++p&&(x&&((f[y]||(f[y]={}))[e]=[w,p]),f===t))break;return p-=i,p===r||0===p%r&&p/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||ut.error("unsupported pseudo: "+e);return i[y]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?st(function(e,n){var r,o=i(e,t),s=o.length;while(s--)r=F.call(e,o[s]),e[r]=!(n[r]=o[s])}):function(e){return i(e,0,n)}):i}},pseudos:{not:st(function(e){var t=[],n=[],r=s(e.replace(I,"$1"));return r[y]?st(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:st(function(e){return function(t){return ut(e,t).length>0}}),contains:st(function(e){return function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:st(function(e){return V.test(e||"")||ut.error("unsupported lang: "+e),e=e.replace(tt,nt).toLowerCase(),function(t){var n;do if(n=p?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===c.activeElement&&(!c.hasFocus||c.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Z.test(e.nodeName)},input:function(e){return K.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:dt(function(){return[0]}),last:dt(function(e,t){return[t-1]}),eq:dt(function(e,t,n){return[0>n?n+t:n]}),even:dt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:dt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:dt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:dt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})r.pseudos[t]=pt(t);for(t in{submit:!0,reset:!0})r.pseudos[t]=ht(t);function gt(e,t){var n,i,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=r.preFilter;while(a){(!n||(i=z.exec(a)))&&(i&&(a=a.slice(i[0].length)||a),u.push(o=[])),n=!1,(i=_.exec(a))&&(n=i.shift(),o.push({value:n,type:i[0].replace(I," ")}),a=a.slice(n.length));for(s in r.filter)!(i=G[s].exec(a))||l[s]&&!(i=l[s](i))||(n=i.shift(),o.push({value:n,type:s,matches:i}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ut.error(e):k(e,u).slice(0)}function mt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function yt(e,t,r){var i=t.dir,o=r&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,r,a){var u,l,c,f=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,r,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[y]||(t[y]={}),(l=c[i])&&l[0]===f){if((u=l[1])===!0||u===n)return u===!0}else if(l=c[i]=[f],l[1]=e(t,r,a)||n,l[1]===!0)return!0}}function vt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function bt(e,t,n,r,i,o){return r&&!r[y]&&(r=bt(r)),i&&!i[y]&&(i=bt(i,o)),st(function(o,s,a,u){var l,c,f,p=[],h=[],d=s.length,g=o||Ct(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:xt(g,p,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=xt(y,h),r(l,[],a,u),c=l.length;while(c--)(f=l[c])&&(y[h[c]]=!(m[h[c]]=f))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(f=y[c])&&l.push(m[c]=f);i(null,y=[],l,u)}c=y.length;while(c--)(f=y[c])&&(l=i?F.call(o,f):p[c])>-1&&(o[l]=!(s[l]=f))}}else y=xt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):H.apply(s,y)})}function wt(e){var t,n,i,o=e.length,s=r.relative[e[0].type],u=s||r.relative[" "],l=s?1:0,c=yt(function(e){return e===t},u,!0),f=yt(function(e){return F.call(t,e)>-1},u,!0),p=[function(e,n,r){return!s&&(r||n!==a)||((t=n).nodeType?c(e,n,r):f(e,n,r))}];for(;o>l;l++)if(n=r.relative[e[l].type])p=[yt(vt(p),n)];else{if(n=r.filter[e[l].type].apply(null,e[l].matches),n[y]){for(i=++l;o>i;i++)if(r.relative[e[i].type])break;return bt(l>1&&vt(p),l>1&&mt(e.slice(0,l-1)).replace(I,"$1"),n,i>l&&wt(e.slice(l,i)),o>i&&wt(e=e.slice(i)),o>i&&mt(e))}p.push(n)}return vt(p)}function Tt(e,t){var i=0,o=t.length>0,s=e.length>0,u=function(u,l,f,p,h){var d,g,m,y=[],v=0,x="0",b=u&&[],T=null!=h,C=a,k=u||s&&r.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(a=l!==c&&l,n=i);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,f)){p.push(d);break}T&&(w=N,n=++i)}o&&((d=!m&&d)&&v--,u&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,f);if(u){if(v>0)while(x--)b[x]||y[x]||(y[x]=L.call(p));y=xt(y)}H.apply(p,y),T&&!u&&y.length>0&&v+t.length>1&&ut.uniqueSort(p)}return T&&(w=N,a=C),b};return o?st(u):u}s=ut.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=gt(e)),n=t.length;while(n--)o=wt(t[n]),o[y]?r.push(o):i.push(o);o=N(e,Tt(i,r))}return o};function Ct(e,t,n){var r=0,i=t.length;for(;i>r;r++)ut(e,t[r],n);return n}function kt(e,t,n,i){var o,a,u,l,c,f=gt(e);if(!i&&1===f.length){if(a=f[0]=f[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&p&&r.relative[a[1].type]){if(t=(r.find.ID(u.matches[0].replace(tt,nt),t)||[])[0],!t)return n;e=e.slice(a.shift().value.length)}o=G.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],r.relative[l=u.type])break;if((c=r.find[l])&&(i=c(u.matches[0].replace(tt,nt),X.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=i.length&&mt(a),!e)return H.apply(n,i),n;break}}}return s(e,f)(i,t,!p,n,X.test(e)),n}r.pseudos.nth=r.pseudos.eq;function Nt(){}Nt.prototype=r.filters=r.pseudos,r.setFilters=new Nt,b.sortStable=y.split("").sort(S).join("")===y,l(),[0,0].sort(S),b.detectDuplicates=E,at(function(e){if(e.innerHTML="<a href='#'></a>","#"!==e.firstChild.getAttribute("href")){var t="type|href|height|width".split("|"),n=t.length;while(n--)r.attrHandle[t[n]]=ft}}),at(function(e){if(null!=e.getAttribute("disabled")){var t=P.split("|"),n=t.length;while(n--)r.attrHandle[t[n]]=ct}}),x.find=ut,x.expr=ut.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ut.uniqueSort,x.text=ut.getText,x.isXMLDoc=ut.isXML,x.contains=ut.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(f){for(t=e.memory&&f,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(f[0],f[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!a||n&&!u||(r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,q,H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))this.cache[i]=t;else for(r in t)o[r]=t[r]},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){return t===undefined||t&&"string"==typeof t&&n===undefined?this.get(e,t):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i=this.key(e),o=this.cache[i];if(t===undefined)this.cache[i]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):t in o?r=[t]:(r=x.camelCase(t),r=r in o?[r]:r.match(w)||[]),n=r.length;while(n--)delete o[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){delete this.cache[this.key(e)]}},L=new F,q=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||q.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return q.access(e,t,n)},_removeData:function(e,t){q.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!q.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.substring(5)),P(i,r,s[r]));q.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:H.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=q.get(e,t),n&&(!r||x.isArray(n)?r=q.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return q.get(e,n)||q.access(e,n,{empty:x.Callbacks("once memory").add(function(){q.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t); +x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=q.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,i="boolean"==typeof t;return x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,s=0,a=x(this),u=t,l=e.match(w)||[];while(o=l[s++])u=i?u:!a.hasClass(o),a[u?"addClass":"removeClass"](o)}else(n===r||"boolean"===n)&&(this.className&&q.set(this,"__className__",this.className),this.className=this.className||e===!1?"":q.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i,o=x(this);1===this.nodeType&&(i=r?e.call(this,n,o.val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.boolean.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.boolean.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.boolean.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,f,p,h,d,g,m,y=q.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(p=x.event.special[d]||{},d=(o?p.delegateType:p.bindType)||d,p=x.event.special[d]||{},f=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,p.setup&&p.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),p.add&&(p.add.call(e,f),f.handler.guid||(f.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,f):h.push(f),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,f,p,h,d,g,m=q.hasData(e)&&q.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){f=x.event.special[h]||{},h=(r?f.delegateType:f.bindType)||h,p=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));s&&!p.length&&(f.teardown&&f.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,q.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,f,p,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),p=x.event.special[d]||{},i||!p.trigger||p.trigger.apply(r,n)!==!1)){if(!i&&!p.noBubble&&!x.isWindow(r)){for(l=p.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:p.bindType||d,f=(q.get(a,"events")||{})[t.type]&&q.get(a,"handle"),f&&f.apply(a,n),f=c&&a[c],f&&x.acceptData(a)&&f.apply&&f.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||p._default&&p._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(q.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return 3===e.target.nodeType&&(e.target=e.target.parentNode),s.filter?s.filter(e,o):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=x.expr.match.needsContext,Q={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return t=this,this.pushStack(x(e).filter(function(){for(r=0;i>r;r++)if(x.contains(t[r],this))return!0}));for(n=[],r=0;i>r;r++)x.find(e,this[r],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(Z(this,e||[],!0))},filter:function(e){return this.pushStack(Z(this,e||[],!1))},is:function(e){return!!e&&("string"==typeof e?J.test(e)?x(e,this.context).index(this[0])>=0:x.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],s=J.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function K(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return K(e,"nextSibling")},prev:function(e){return K(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(Q[e]||x.unique(i),"p"===e[0]&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function Z(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var et=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,tt=/<([\w:]+)/,nt=/<|&#?\w+;/,rt=/<(?:script|style|link)/i,it=/^(?:checkbox|radio)$/i,ot=/checked\s*(?:[^=]|=\s*.checked.)/i,st=/^$|\/(?:java|ecma)script/i,at=/^true\/(.*)/,ut=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,lt={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};lt.optgroup=lt.option,lt.tbody=lt.tfoot=lt.colgroup=lt.caption=lt.col=lt.thead,lt.th=lt.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=ct(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=ct(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(gt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&ht(gt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(gt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!rt.test(e)&&!lt[(tt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(et,"<$1></$2>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(gt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=p.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,f=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&ot.test(d))return this.each(function(r){var i=f.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(gt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,gt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,pt),l=0;s>l;l++)a=o[l],st.test(a.type||"")&&!q.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(ut,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=gt(a),o=gt(e),r=0,i=o.length;i>r;r++)mt(o[r],s[r]);if(t)if(n)for(o=o||gt(e),s=s||gt(a),r=0,i=o.length;i>r;r++)dt(o[r],s[r]);else dt(e,a);return s=gt(a,"script"),s.length>0&&ht(s,!u&>(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,f=e.length,p=t.createDocumentFragment(),h=[];for(;f>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(nt.test(i)){o=o||p.appendChild(t.createElement("div")),s=(tt.exec(i)||["",""])[1].toLowerCase(),a=lt[s]||lt._default,o.innerHTML=a[1]+i.replace(et,"<$1></$2>")+a[2],l=a[0];while(l--)o=o.firstChild;x.merge(h,o.childNodes),o=p.firstChild,o.textContent=""}else h.push(t.createTextNode(i));p.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=gt(p.appendChild(i),"script"),u&&ht(o),n)){l=0;while(i=o[l++])st.test(i.type||"")&&n.push(i)}return p},cleanData:function(e){var t,n,r,i=e.length,o=0,s=x.event.special;for(;i>o;o++){if(n=e[o],x.acceptData(n)&&(t=q.access(n)))for(r in t.events)s[r]?x.event.remove(n,r):x.removeEvent(n,r,t.handle);L.discard(n),q.discard(n)}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"text",async:!1,global:!1,success:x.globalEval})}});function ct(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function pt(e){var t=at.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function ht(e,t){var n=e.length,r=0;for(;n>r;r++)q.set(e[r],"globalEval",!t||q.get(t[r],"globalEval"))}function dt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),s=x.extend({},o),l=o.events,q.set(t,s),l)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function gt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function mt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&it.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var yt,vt,xt=/^(none|table(?!-c[ea]).+)/,bt=/^margin/,wt=RegExp("^("+b+")(.*)$","i"),Tt=RegExp("^("+b+")(?!px)[a-z%]+$","i"),Ct=RegExp("^([+-])=("+b+")","i"),kt={BODY:"block"},Nt={position:"absolute",visibility:"hidden",display:"block"},Et={letterSpacing:0,fontWeight:400},St=["Top","Right","Bottom","Left"],jt=["Webkit","O","Moz","ms"];function Dt(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=jt.length;while(i--)if(t=jt[i]+n,t in e)return t;return r}function At(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function Lt(t){return e.getComputedStyle(t,null)}function qt(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=q.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&At(r)&&(o[s]=q.access(r,"olddisplay",Pt(r.nodeName)))):o[s]||(i=At(r),(n&&"none"!==n||!i)&&q.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=Lt(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return qt(this,!0)},hide:function(){return qt(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:At(this))?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=yt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=Dt(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=Ct.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=Dt(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=yt(e,t,r)),"normal"===i&&t in Et&&(i=Et[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),yt=function(e,t,n){var r,i,o,s=n||Lt(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Tt.test(a)&&bt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ht(e,t,n){var r=wt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ot(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+St[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+St[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+St[o]+"Width",!0,i))):(s+=x.css(e,"padding"+St[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+St[o]+"Width",!0,i)));return s}function Ft(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Lt(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=yt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Tt.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ot(e,t,n||(s?"border":"content"),r,o)+"px"}function Pt(e){var t=o,n=kt[e];return n||(n=Rt(e,t),"none"!==n&&n||(vt=(vt||x("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(vt[0].contentWindow||vt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=Rt(e,t),vt.detach()),kt[e]=n),n}function Rt(e,t){var n=x(t.createElement(e)).appendTo(t.body),r=x.css(n[0],"display");return n.remove(),r}x.each(["height","width"],function(e,t){x.cssHooks[t]={get:function(e,n,r){return n?0===e.offsetWidth&&xt.test(x.css(e,"display"))?x.swap(e,Nt,function(){return Ft(e,t,r)}):Ft(e,t,r):undefined},set:function(e,n,r){var i=r&&Lt(e);return Ht(e,n,r?Ot(e,t,r,x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,i),i):0)}}}),x(function(){x.support.reliableMarginRight||(x.cssHooks.marginRight={get:function(e,t){return t?x.swap(e,{display:"inline-block"},yt,[e,"marginRight"]):undefined}}),!x.support.pixelPosition&&x.fn.position&&x.each(["top","left"],function(e,t){x.cssHooks[t]={get:function(e,n){return n?(n=yt(e,t),Tt.test(n)?x(e).position()[t]+"px":n):undefined}}})}),x.expr&&x.expr.filters&&(x.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight},x.expr.filters.visible=function(e){return!x.expr.filters.hidden(e)}),x.each({margin:"",padding:"",border:"Width"},function(e,t){x.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+St[r]+t]=o[r]||o[r-2]||o[0];return i}},bt.test(e)||(x.cssHooks[e+t].set=Ht)});var Mt=/%20/g,Wt=/\[\]$/,$t=/\r?\n/g,Bt=/^(?:submit|button|image|reset|file)$/i,It=/^(?:input|select|textarea|keygen)/i;x.fn.extend({serialize:function(){return x.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=x.prop(this,"elements");return e?x.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!x(this).is(":disabled")&&It.test(this.nodeName)&&!Bt.test(e)&&(this.checked||!it.test(e))}).map(function(e,t){var n=x(this).val();return null==n?null:x.isArray(n)?x.map(n,function(e){return{name:t.name,value:e.replace($t,"\r\n")}}):{name:t.name,value:n.replace($t,"\r\n")}}).get()}}),x.param=function(e,t){var n,r=[],i=function(e,t){t=x.isFunction(t)?t():null==t?"":t,r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(t===undefined&&(t=x.ajaxSettings&&x.ajaxSettings.traditional),x.isArray(e)||e.jquery&&!x.isPlainObject(e))x.each(e,function(){i(this.name,this.value)});else for(n in e)zt(n,e[n],t,i);return r.join("&").replace(Mt,"+")};function zt(e,t,n,r){var i;if(x.isArray(t))x.each(t,function(t,i){n||Wt.test(e)?r(e,i):zt(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==x.type(t))r(e,t);else for(i in t)zt(e+"["+i+"]",t[i],n,r)}x.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){x.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),x.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}});var _t,Xt,Ut=x.now(),Yt=/\?/,Vt=/#.*$/,Gt=/([?&])_=[^&]*/,Jt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Qt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Kt=/^(?:GET|HEAD)$/,Zt=/^\/\//,en=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,tn=x.fn.load,nn={},rn={},on="*/".concat("*");try{Xt=i.href}catch(sn){Xt=o.createElement("a"),Xt.href="",Xt=Xt.href}_t=en.exec(Xt.toLowerCase())||[];function an(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[]; +if(x.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function un(e,t,n,r){var i={},o=e===rn;function s(a){var u;return i[a]=!0,x.each(e[a]||[],function(e,a){var l=a(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):undefined:(t.dataTypes.unshift(l),s(l),!1)}),u}return s(t.dataTypes[0])||!i["*"]&&s("*")}function ln(e,t){var n,r,i=x.ajaxSettings.flatOptions||{};for(n in t)t[n]!==undefined&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&x.extend(!0,e,r),e}x.fn.load=function(e,t,n){if("string"!=typeof e&&tn)return tn.apply(this,arguments);var r,i,o,s=this,a=e.indexOf(" ");return a>=0&&(r=e.slice(a),e=e.slice(0,a)),x.isFunction(t)?(n=t,t=undefined):t&&"object"==typeof t&&(i="POST"),s.length>0&&x.ajax({url:e,type:i,dataType:"html",data:t}).done(function(e){o=arguments,s.html(r?x("<div>").append(x.parseHTML(e)).find(r):e)}).complete(n&&function(e,t){s.each(n,o||[e.responseText,t,e])}),this},x.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){x.fn[t]=function(e){return this.on(t,e)}}),x.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Xt,type:"GET",isLocal:Qt.test(_t[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":on,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":x.parseJSON,"text xml":x.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?ln(ln(e,x.ajaxSettings),t):ln(x.ajaxSettings,e)},ajaxPrefilter:an(nn),ajaxTransport:an(rn),ajax:function(e,t){"object"==typeof e&&(t=e,e=undefined),t=t||{};var n,r,i,o,s,a,u,l,c=x.ajaxSetup({},t),f=c.context||c,p=c.context&&(f.nodeType||f.jquery)?x(f):x.event,h=x.Deferred(),d=x.Callbacks("once memory"),g=c.statusCode||{},m={},y={},v=0,b="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(2===v){if(!o){o={};while(t=Jt.exec(i))o[t[1].toLowerCase()]=t[2]}t=o[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===v?i:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return v||(e=y[n]=y[n]||e,m[e]=t),this},overrideMimeType:function(e){return v||(c.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>v)for(t in e)g[t]=[g[t],e[t]];else T.always(e[T.status]);return this},abort:function(e){var t=e||b;return n&&n.abort(t),k(0,t),this}};if(h.promise(T).complete=d.add,T.success=T.done,T.error=T.fail,c.url=((e||c.url||Xt)+"").replace(Vt,"").replace(Zt,_t[1]+"//"),c.type=t.method||t.type||c.method||c.type,c.dataTypes=x.trim(c.dataType||"*").toLowerCase().match(w)||[""],null==c.crossDomain&&(a=en.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===_t[1]&&a[2]===_t[2]&&(a[3]||("http:"===a[1]?"80":"443"))===(_t[3]||("http:"===_t[1]?"80":"443")))),c.data&&c.processData&&"string"!=typeof c.data&&(c.data=x.param(c.data,c.traditional)),un(nn,c,t,T),2===v)return T;u=c.global,u&&0===x.active++&&x.event.trigger("ajaxStart"),c.type=c.type.toUpperCase(),c.hasContent=!Kt.test(c.type),r=c.url,c.hasContent||(c.data&&(r=c.url+=(Yt.test(r)?"&":"?")+c.data,delete c.data),c.cache===!1&&(c.url=Gt.test(r)?r.replace(Gt,"$1_="+Ut++):r+(Yt.test(r)?"&":"?")+"_="+Ut++)),c.ifModified&&(x.lastModified[r]&&T.setRequestHeader("If-Modified-Since",x.lastModified[r]),x.etag[r]&&T.setRequestHeader("If-None-Match",x.etag[r])),(c.data&&c.hasContent&&c.contentType!==!1||t.contentType)&&T.setRequestHeader("Content-Type",c.contentType),T.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+("*"!==c.dataTypes[0]?", "+on+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)T.setRequestHeader(l,c.headers[l]);if(c.beforeSend&&(c.beforeSend.call(f,T,c)===!1||2===v))return T.abort();b="abort";for(l in{success:1,error:1,complete:1})T[l](c[l]);if(n=un(rn,c,t,T)){T.readyState=1,u&&p.trigger("ajaxSend",[T,c]),c.async&&c.timeout>0&&(s=setTimeout(function(){T.abort("timeout")},c.timeout));try{v=1,n.send(m,k)}catch(C){if(!(2>v))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,t,o,a){var l,m,y,b,w,C=t;2!==v&&(v=2,s&&clearTimeout(s),n=undefined,i=a||"",T.readyState=e>0?4:0,l=e>=200&&300>e||304===e,o&&(b=cn(c,T,o)),b=fn(c,b,T,l),l?(c.ifModified&&(w=T.getResponseHeader("Last-Modified"),w&&(x.lastModified[r]=w),w=T.getResponseHeader("etag"),w&&(x.etag[r]=w)),204===e?C="nocontent":304===e?C="notmodified":(C=b.state,m=b.data,y=b.error,l=!y)):(y=C,(e||!C)&&(C="error",0>e&&(e=0))),T.status=e,T.statusText=(t||C)+"",l?h.resolveWith(f,[m,C,T]):h.rejectWith(f,[T,C,y]),T.statusCode(g),g=undefined,u&&p.trigger(l?"ajaxSuccess":"ajaxError",[T,c,l?m:y]),d.fireWith(f,[T,C]),u&&(p.trigger("ajaxComplete",[T,c]),--x.active||x.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return x.get(e,t,n,"json")},getScript:function(e,t){return x.get(e,undefined,t,"script")}}),x.each(["get","post"],function(e,t){x[t]=function(e,n,r,i){return x.isFunction(n)&&(i=i||r,r=n,n=undefined),x.ajax({url:e,type:t,dataType:i,data:n,success:r})}});function cn(e,t,n){var r,i,o,s,a=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),r===undefined&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in a)if(a[i]&&a[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}s||(s=i)}o=o||s}return o?(o!==u[0]&&u.unshift(o),n[o]):undefined}function fn(e,t,n,r){var i,o,s,a,u,l={},c=e.dataTypes.slice();if(c[1])for(s in e.converters)l[s.toLowerCase()]=e.converters[s];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(s=l[u+" "+o]||l["* "+o],!s)for(i in l)if(a=i.split(" "),a[1]===o&&(s=l[u+" "+a[0]]||l["* "+a[0]])){s===!0?s=l[i]:l[i]!==!0&&(o=a[0],c.unshift(a[1]));break}if(s!==!0)if(s&&e["throws"])t=s(t);else try{t=s(t)}catch(f){return{state:"parsererror",error:s?f:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}x.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return x.globalEval(e),e}}}),x.ajaxPrefilter("script",function(e){e.cache===undefined&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),x.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(r,i){t=x("<script>").prop({async:!0,charset:e.scriptCharset,src:e.url}).on("load error",n=function(e){t.remove(),n=null,e&&i("error"===e.type?404:200,e.type)}),o.head.appendChild(t[0])},abort:function(){n&&n()}}}});var pn=[],hn=/(=)\?(?=&|$)|\?\?/;x.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=pn.pop()||x.expando+"_"+Ut++;return this[e]=!0,e}}),x.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,s,a=t.jsonp!==!1&&(hn.test(t.url)?"url":"string"==typeof t.data&&!(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&hn.test(t.data)&&"data");return a||"jsonp"===t.dataTypes[0]?(i=t.jsonpCallback=x.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,a?t[a]=t[a].replace(hn,"$1"+i):t.jsonp!==!1&&(t.url+=(Yt.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return s||x.error(i+" was not called"),s[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){s=arguments},r.always(function(){e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,pn.push(i)),s&&x.isFunction(o)&&o(s[0]),s=o=undefined}),"script"):undefined}),x.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(e){}};var dn=x.ajaxSettings.xhr(),gn={0:200,1223:204},mn=0,yn={};e.ActiveXObject&&x(e).on("unload",function(){for(var e in yn)yn[e]();yn=undefined}),x.support.cors=!!dn&&"withCredentials"in dn,x.support.ajax=dn=!!dn,x.ajaxTransport(function(e){var t;return x.support.cors||dn&&!e.crossDomain?{send:function(n,r){var i,o,s=e.xhr();if(s.open(e.type,e.url,e.async,e.username,e.password),e.xhrFields)for(i in e.xhrFields)s[i]=e.xhrFields[i];e.mimeType&&s.overrideMimeType&&s.overrideMimeType(e.mimeType),e.crossDomain||n["X-Requested-With"]||(n["X-Requested-With"]="XMLHttpRequest");for(i in n)s.setRequestHeader(i,n[i]);t=function(e){return function(){t&&(delete yn[o],t=s.onload=s.onerror=null,"abort"===e?s.abort():"error"===e?r(s.status||404,s.statusText):r(gn[s.status]||s.status,s.statusText,"string"==typeof s.responseText?{text:s.responseText}:undefined,s.getAllResponseHeaders()))}},s.onload=t(),s.onerror=t("error"),t=yn[o=mn++]=t("abort"),s.send(e.hasContent&&e.data||null)},abort:function(){t&&t()}}:undefined});var vn,xn,bn=/^(?:toggle|show|hide)$/,wn=RegExp("^(?:([+-])=|)("+b+")([a-z%]*)$","i"),Tn=/queueHooks$/,Cn=[Dn],kn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=wn.exec(t),s=i.cur(),a=+s||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(x.cssNumber[e]?"":"px"),"px"!==r&&a){a=x.css(i.elem,e,!0)||n||1;do u=u||".5",a/=u,x.style(i.elem,e,a+r);while(u!==(u=i.cur()/s)&&1!==u&&--l)}i.unit=r,i.start=a,i.end=o[1]?a+(o[1]+1)*n:n}return i}]};function Nn(){return setTimeout(function(){vn=undefined}),vn=x.now()}function En(e,t){x.each(t,function(t,n){var r=(kn[t]||[]).concat(kn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function Sn(e,t,n){var r,i,o=0,s=Cn.length,a=x.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=vn||Nn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,s=0,u=l.tweens.length;for(;u>s;s++)l.tweens[s].run(o);return a.notifyWith(e,[l,o,n]),1>o&&u?n:(a.resolveWith(e,[l]),!1)},l=a.promise({elem:e,props:x.extend({},t),opts:x.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:vn||Nn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=x.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?a.resolveWith(e,[l,t]):a.rejectWith(e,[l,t]),this}}),c=l.props;for(jn(c,l.opts.specialEasing);s>o;o++)if(r=Cn[o].call(l,e,c,l.opts))return r;return En(l,c),x.isFunction(l.opts.start)&&l.opts.start.call(e,l),x.fx.timer(x.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function jn(e,t){var n,r,i,o,s;for(n in e)if(r=x.camelCase(n),i=t[r],o=e[n],x.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),s=x.cssHooks[r],s&&"expand"in s){o=s.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}x.Animation=x.extend(Sn,{tweener:function(e,t){x.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],kn[n]=kn[n]||[],kn[n].unshift(t)},prefilter:function(e,t){t?Cn.unshift(e):Cn.push(e)}});function Dn(e,t,n){var r,i,o,s,a,u,l,c,f,p=this,h=e.style,d={},g=[],m=e.nodeType&&At(e);n.queue||(c=x._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,f=c.empty.fire,c.empty.fire=function(){c.unqueued||f()}),c.unqueued++,p.always(function(){p.always(function(){c.unqueued--,x.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],"inline"===x.css(e,"display")&&"none"===x.css(e,"float")&&(h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),a=q.get(e,"fxshow");for(r in t)if(o=t[r],bn.exec(o)){if(delete t[r],u=u||"toggle"===o,o===(m?"hide":"show")){if("show"!==o||a===undefined||a[r]===undefined)continue;m=!0}g.push(r)}if(s=g.length){a=q.get(e,"fxshow")||q.access(e,"fxshow",{}),"hidden"in a&&(m=a.hidden),u&&(a.hidden=!m),m?x(e).show():p.done(function(){x(e).hide()}),p.done(function(){var t;q.remove(e,"fxshow");for(t in d)x.style(e,t,d[t])});for(r=0;s>r;r++)i=g[r],l=p.createTween(i,m?a[i]:0),d[i]=a[i]||x.style(e,i),i in a||(a[i]=l.start,m&&(l.end=l.start,l.start="width"===i||"height"===i?1:0))}}function An(e,t,n,r,i){return new An.prototype.init(e,t,n,r,i)}x.Tween=An,An.prototype={constructor:An,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(x.cssNumber[n]?"":"px")},cur:function(){var e=An.propHooks[this.prop];return e&&e.get?e.get(this):An.propHooks._default.get(this)},run:function(e){var t,n=An.propHooks[this.prop];return this.pos=t=this.options.duration?x.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):An.propHooks._default.set(this),this}},An.prototype.init.prototype=An.prototype,An.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=x.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){x.fx.step[e.prop]?x.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[x.cssProps[e.prop]]||x.cssHooks[e.prop])?x.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},An.propHooks.scrollTop=An.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},x.each(["toggle","show","hide"],function(e,t){var n=x.fn[t];x.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(Ln(t,!0),e,r,i)}}),x.fn.extend({fadeTo:function(e,t,n,r){return this.filter(At).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=x.isEmptyObject(e),o=x.speed(t,n,r),s=function(){var t=Sn(this,x.extend({},e),o);s.finish=function(){t.stop(!0)},(i||q.get(this,"finish"))&&t.stop(!0)};return s.finish=s,i||o.queue===!1?this.each(s):this.queue(o.queue,s)},stop:function(e,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return"string"!=typeof e&&(n=t,t=e,e=undefined),t&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,i=null!=e&&e+"queueHooks",o=x.timers,s=q.get(this);if(i)s[i]&&s[i].stop&&r(s[i]);else for(i in s)s[i]&&s[i].stop&&Tn.test(i)&&r(s[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));(t||!n)&&x.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=q.get(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=x.timers,s=r?r.length:0;for(n.finish=!0,x.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;s>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function Ln(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=St[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}x.each({slideDown:Ln("show"),slideUp:Ln("hide"),slideToggle:Ln("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){x.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),x.speed=function(e,t,n){var r=e&&"object"==typeof e?x.extend({},e):{complete:n||!n&&t||x.isFunction(e)&&e,duration:e,easing:n&&t||t&&!x.isFunction(t)&&t};return r.duration=x.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in x.fx.speeds?x.fx.speeds[r.duration]:x.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){x.isFunction(r.old)&&r.old.call(this),r.queue&&x.dequeue(this,r.queue)},r},x.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},x.timers=[],x.fx=An.prototype.init,x.fx.tick=function(){var e,t=x.timers,n=0;for(vn=x.now();t.length>n;n++)e=t[n],e()||t[n]!==e||t.splice(n--,1);t.length||x.fx.stop(),vn=undefined},x.fx.timer=function(e){e()&&x.timers.push(e)&&x.fx.start()},x.fx.interval=13,x.fx.start=function(){xn||(xn=setInterval(x.fx.tick,x.fx.interval))},x.fx.stop=function(){clearInterval(xn),xn=null},x.fx.speeds={slow:600,fast:200,_default:400},x.fx.step={},x.expr&&x.expr.filters&&(x.expr.filters.animated=function(e){return x.grep(x.timers,function(t){return e===t.elem}).length}),x.fn.offset=function(e){if(arguments.length)return e===undefined?this:this.each(function(t){x.offset.setOffset(this,e,t)});var t,n,i=this[0],o={top:0,left:0},s=i&&i.ownerDocument;if(s)return t=s.documentElement,x.contains(t,i)?(typeof i.getBoundingClientRect!==r&&(o=i.getBoundingClientRect()),n=qn(s),{top:o.top+n.pageYOffset-t.clientTop,left:o.left+n.pageXOffset-t.clientLeft}):o},x.offset={setOffset:function(e,t,n){var r,i,o,s,a,u,l,c=x.css(e,"position"),f=x(e),p={};"static"===c&&(e.style.position="relative"),a=f.offset(),o=x.css(e,"top"),u=x.css(e,"left"),l=("absolute"===c||"fixed"===c)&&(o+u).indexOf("auto")>-1,l?(r=f.position(),s=r.top,i=r.left):(s=parseFloat(o)||0,i=parseFloat(u)||0),x.isFunction(t)&&(t=t.call(e,n,a)),null!=t.top&&(p.top=t.top-a.top+s),null!=t.left&&(p.left=t.left-a.left+i),"using"in t?t.using.call(e,p):f.css(p)}},x.fn.extend({position:function(){if(this[0]){var e,t,n=this[0],r={top:0,left:0};return"fixed"===x.css(n,"position")?t=n.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),x.nodeName(e[0],"html")||(r=e.offset()),r.top+=x.css(e[0],"borderTopWidth",!0),r.left+=x.css(e[0],"borderLeftWidth",!0)),{top:t.top-r.top-x.css(n,"marginTop",!0),left:t.left-r.left-x.css(n,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||s;while(e&&!x.nodeName(e,"html")&&"static"===x.css(e,"position"))e=e.offsetParent;return e||s})}}),x.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,n){var r="pageYOffset"===n;x.fn[t]=function(i){return x.access(this,function(t,i,o){var s=qn(t);return o===undefined?s?s[n]:t[i]:(s?s.scrollTo(r?e.pageXOffset:o,r?o:e.pageYOffset):t[i]=o,undefined)},t,i,arguments.length,null)}});function qn(e){return x.isWindow(e)?e:9===e.nodeType&&e.defaultView}x.each({Height:"height",Width:"width"},function(e,t){x.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){x.fn[r]=function(r,i){var o=arguments.length&&(n||"boolean"!=typeof r),s=n||(r===!0||i===!0?"margin":"border");return x.access(this,function(t,n,r){var i;return x.isWindow(t)?t.document.documentElement["client"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body["scroll"+e],i["scroll"+e],t.body["offset"+e],i["offset"+e],i["client"+e])):r===undefined?x.css(t,n,s):x.style(t,n,r,s)},t,o?r:undefined,o,null)}})}),x.fn.size=function(){return this.length},x.fn.andSelf=x.fn.addBack,"object"==typeof module&&"object"==typeof module.exports?module.exports=x:"function"==typeof define&&define.amd&&define("jquery",[],function(){return x}),"object"==typeof e&&"object"==typeof e.document&&(e.jQuery=e.$=x)})(window); \ No newline at end of file
--- a/src/js/libs/renkan-publish.js Wed Apr 03 15:44:17 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1079 +0,0 @@ -/* - * Copyright 2012 Institut de recherche et d'innovation - * contributor(s) : Yves-Marie Haussonne, Raphael Velt, Samuel Huron - * - * contact@iri.centrepompidou.fr - * http://www.iri.centrepompidou.fr - * - * This software is a computer program whose purpose is to show and add annotations on a video . - * This software is governed by the CeCILL-C license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/ or redistribute the software under the terms of the CeCILL-C - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL-C license and that you accept its terms. -*/ - -if (typeof Rkns !== "object") { - Rkns = {} -} - -Rkns.$ = jQuery; - -Rkns._ = _; - -Rkns.i18n = { - en: { - zoom_in: "Zoom In", - zoom_out: "Zoom Out", - see_in_project: 'See also <b>"{node}"</b> in <b>"{project}"</b>' - } -} - -Rkns.Utils = { - inherit : function(_baseClass) { - var _class = function() { - _baseClass.apply(this, Array.prototype.slice.call(arguments, 0)); - if (typeof this._init == "function") { - this._init.apply(this, Array.prototype.slice.call(arguments, 0)); - } - } - _class.prototype = new _baseClass(); - return _class; - } -} - -Rkns.Models = {}; - -Rkns.Models.getUID = function(obj) { - var guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); - return v.toString(16); - }); - return obj.type + "-" + guid; -}; - -Rkns.Models.RenkanModel = Backbone.RelationalModel.extend({ - idAttribute : "_id", - constructor: function(options) { - - if (typeof options !== "undefined") { - options._id = options._id || options.id || Rkns.Models.getUID(this); - options.title = options.title || "(untitled " + this.type + ")"; - options.description = options.description || ""; - options.uri = options.uri || ""; - - if(typeof this.prepare === "function") { - options = this.prepare(options); - } - } - Backbone.RelationalModel.prototype.constructor.call(this, options); - }, - validate: function() { - if(!this.type) { - return "object has no type"; - } - }, - addReference : function(_options, _propName, _list, _id, _default) { - var _element = _list.get(_id); - if (typeof _element === "undefined" && typeof _default !== "undefined") { - _options[_propName ] = _default; - } - else { - _options[_propName ] = _element; - } - } -}); - -// USER -Rkns.Models.User = Rkns.Models.RenkanModel.extend({ - type: "user", - prepare: function(options) { - options.color = options.color || "#666666"; - return options; - }, - toJSON: function() { - return { - id: this.get("_id"), - title: this.get("title"), - uri: this.get("uri"), - description: this.get("description"), - color: this.get("color"), - } - }, -}); - -// NODE -Rkns.Models.Node = Rkns.Models.RenkanModel.extend({ - type: "node", - relations: [{ - type: Backbone.HasOne, - key: "created_by", - relatedModel: Rkns.Models.User - }], - prepare: function(options) { - project = options.project; - this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user); - options.description = options.description || ""; - return options; - }, - toJSON: function() { - return { - id: this.get("_id"), - title: this.get("title"), - uri: this.get("uri"), - description: this.get("description"), - position: this.get("position"), - image: this.get("image"), - created_by: this.get("created_by").get("_id") - } - }, -}); - -// EDGE -Rkns.Models.Edge = Rkns.Models.RenkanModel.extend({ - type: "edge", - relations: [ - { - type: Backbone.HasOne, - key: "created_by", - relatedModel: Rkns.Models.User - }, - { - type: Backbone.HasOne, - key: "from", - relatedModel: Rkns.Models.Node - }, - { - type: Backbone.HasOne, - key: "to", - relatedModel: Rkns.Models.Node - }, - ], - prepare: function(options) { - project = options.project; - this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user); - this.addReference(options, "from", project.get("nodes"), options.from); - this.addReference(options, "to", project.get("nodes"), options.to); - return options; - }, - toJSON: function() { - return { - id: this.get("_id"), - title: this.get("title"), - uri: this.get("uri"), - description: this.get("description"), - from: this.get("from").get("_id"), - to: this.get("to").get("_id"), - created_by: this.get("created_by").get("_id"), - } - }, -}); - -// PROJECT -Rkns.Models.Project = Rkns.Models.RenkanModel.extend({ - type: "project", - relations: [ - { - type: Backbone.HasMany, - key: "users", - relatedModel: Rkns.Models.User, - reverseRelation: { - key: 'project', - includeInJSON: '_id' - }, - }, - { - type: Backbone.HasMany, - key: "nodes", - relatedModel: Rkns.Models.Node, - reverseRelation: { - key: 'project', - includeInJSON: '_id' - }, - }, - { - type: Backbone.HasMany, - key: "edges", - relatedModel: Rkns.Models.Edge, - reverseRelation: { - key: 'project', - includeInJSON: '_id' - }, - } - ], - addUser: function(_props) { - _props.project = this; - var _user = new Rkns.Models.User(_props); - this.get("users").push(_user); - return _user; - }, - addNode: function(_props) { - _props.project = this; - var _node = new Rkns.Models.Node(_props); - this.get("nodes").push(_node); - return _node; - }, - addEdge: function(_props) { - _props.project = this; - var _edge = new Rkns.Models.Edge(_props); - this.get("edges").push(_edge); - return _edge; - }, - removeNode: function(_model) { - this.get("nodes").remove(_model); - }, - removeEdge: function(_model) { - this.get("edges").remove(_model); - }, - validate: function(options) { - var _project = this; - Rkns._(options.users).each(function(_item) { - _item.project = _project; - }); - Rkns._(options.nodes).each(function(_item) { - _item.project = _project; - }); - Rkns._(options.edges).each(function(_item) { - _item.project = _project; - }); - }, - // Add event handler to remove edges when a node is removed - initialize: function() { - var _this = this; - this.on("remove:nodes", function(_node) { - _this.get("edges").remove( - _this.get("edges").filter(function(_edge) { - return _edge.get("from") == _node || _edge.get("to") == _node; - }) - ); - }); - } -}); - -/* Point of entry */ - -Rkns.Renkan = function(_opts) { - if (typeof _opts.language !== "string" || typeof Rkns.i18n[_opts.language] == "undefined") { - _opts.language = "en"; - } - if (typeof _opts.container !== "string") { - _opts.container = "renkan"; - } - if (typeof _opts.search !== "object" || !_opts.search) { - _opts.search = []; - } - this.projects = []; - this.l10n = Rkns.i18n[_opts.language]; - this.$ = Rkns.$("#" + _opts.container); - this.$.html(this.template()); - this.uris = {}; - this.active_project = null; - this.renderer = null; -} - -Rkns.Renkan.prototype.template = Rkns._.template( - '<div class="Rk-Render"></div><ul class="Rk-Project-List"></ul>' -); - -Rkns.Renkan.prototype.addProject = function(_opts) { - var _proj = new Rkns.Models.Project(), - _li = Rkns.$("<li>").addClass("Rk-Project").text("Untitled #" + (1+this.projects.length)); - this.$.find(".Rk-Project-List").append(_li); - Rkns.loadJson(_proj, _opts); - var _this = this; - _li.click(function() { - _this.renderProject(_proj); - }); - _proj.on("change:title", function() { - _li.html(_proj.get("title")); - }); - _proj.on("select", function() { - _this.$.find(".Rk-Project").removeClass("active"); - _li.addClass("active"); - }); - _proj.on("add:nodes", function(_node) { - var _uri = _node.get("uri"); - if (_uri) { - if (typeof _this.uris[_uri] === "undefined") { - _this.uris[_uri] = []; - } - _this.uris[_uri].push(_node); - } - }); - this.projects.push(_proj); - return _proj; -} - -Rkns.Renkan.prototype.renderProject = function(_project) { - if (_project) { - if (this.renderer) { - this.renderer.destroy(); - } - this.active_project = _project; - this.renderer = new Rkns.Renderer.Scene(this, _project); - this.renderer.autoScale(); - _project.trigger("select"); - } -} - -Rkns.Renkan.prototype.renderProjectAt = function(_index) { - this.renderProject(this.projects[_index]); -} - -Rkns.loadJson = function(_proj, _opts) { - if (typeof _opts.http_method == "undefined") { - _opts.http_method = 'PUT'; - } - var _load = function() { - Rkns.$.getJSON(_opts.url, function(_data) { - _proj.set(_data); - if (typeof _opts.callback === "function") { - _opts.callback(_proj); - } - }); - } - _load(); -} - -Rkns.Renderer = { - _MARGIN_X: 80, - _MARGIN_Y: 50, - _MIN_DRAG_DISTANCE: 2, - _NODE_RADIUS: 20, - _NODE_FONT_SIZE: 10, - _EDGE_FONT_SIZE: 9, - _NODE_MAX_CHAR: 30, - _EDGE_MAX_CHAR: 20, - _ARROW_LENGTH: 16, - _ARROW_WIDTH: 8, - _TOOLTIP_ARROW_LENGTH : 15, - _TOOLTIP_ARROW_WIDTH : 26, - _TOOLTIP_MARGIN : 10, - _TOOLTIP_PADDING : 8, - _TOOLTIP_GRADIENT : new paper.Gradient(['#f0f0f0', '#d0d0d0']) -} - -Rkns.Renderer.Utils = { - shortenText : function(_text,_length) { - var _rgxp = new RegExp('^(.{' + _length + '}).+$'); - return _text.replace(/(\n|\r|\r\n)/mg,' ').replace(_rgxp,'$1…'); - }, - drawTooltip : function(_coords, _path, _width, _xmargin, _selector) { - _selector.css({ - width: (_width - 2* Rkns.Renderer._TOOLTIP_PADDING), - }); - var _height = _selector.outerHeight() + 2* Rkns.Renderer._TOOLTIP_PADDING, - _isLeft = (_coords.x < paper.view.center.x ? 1 : -1), - _left = _coords.x + _isLeft * ( _xmargin + Rkns.Renderer._TOOLTIP_ARROW_LENGTH ), - _right = _coords.x + _isLeft * ( _xmargin + Rkns.Renderer._TOOLTIP_ARROW_LENGTH + _width ), - _top = _coords.y - _height / 2; - if (_top < Rkns.Renderer._TOOLTIP_MARGIN) { - _top = Math.min( Rkns.Renderer._TOOLTIP_MARGIN, _coords.y - Rkns.Renderer._TOOLTIP_ARROW_WIDTH / 2 ); - } - var _bottom = _top + _height; - if (_bottom > (paper.view.size.height - Rkns.Renderer._TOOLTIP_MARGIN)) { - _bottom = Math.max( paper.view.size.height - Rkns.Renderer._TOOLTIP_MARGIN, _coords.y + Rkns.Renderer._TOOLTIP_ARROW_WIDTH / 2 ); - _top = _bottom - _height; - } - _path.segments[0].point - = _path.segments[7].point - = _coords.add([_isLeft * _xmargin, 0]); - _path.segments[1].point.x - = _path.segments[2].point.x - = _path.segments[5].point.x - = _path.segments[6].point.x - = _left; - _path.segments[3].point.x - = _path.segments[4].point.x - = _right; - _path.segments[2].point.y - = _path.segments[3].point.y - = _top; - _path.segments[4].point.y - = _path.segments[5].point.y - = _bottom; - _path.segments[1].point.y = _coords.y - Rkns.Renderer._TOOLTIP_ARROW_WIDTH / 2; - _path.segments[6].point.y = _coords.y + Rkns.Renderer._TOOLTIP_ARROW_WIDTH / 2; - _path.closed = true; - _path.fillColor = new paper.GradientColor(Rkns.Renderer._TOOLTIP_GRADIENT, [0,_top], [0, _bottom]); - _selector.css({ - left: (Rkns.Renderer._TOOLTIP_PADDING + Math.min(_left, _right)), - top: (Rkns.Renderer._TOOLTIP_PADDING + _top) - }); - } -} - -Rkns.Renderer._BaseRepresentation = function(_renderer, _model) { - if (typeof _renderer !== "undefined") { - this.renderer = _renderer; - this.project = _renderer.project; - this.model = _model; - if (this.model) { - var _this = this; - this._selectBinding = function() { - _this.select(); - }; - this._unselectBinding = function() { - _this.unselect(); - } - this._changeBinding = function() { - _this.redraw(); - } - this._removeBinding = function() { - _renderer.removeRepresentation(_this); - _renderer.redraw(); - } - this.model.on("change", this._changeBinding ); - this.model.on("remove", this._removeBinding ); - this.model.on("select", this._selectBinding ); - this.model.on("unselect", this._unselectBinding ); - } - } -} - -Rkns.Renderer._BaseRepresentation.prototype.super = function(_func) { - Rkns.Renderer._BaseRepresentation.prototype[_func].apply(this, Array.prototype.slice.call(arguments, 1)); -} - -Rkns.Renderer._BaseRepresentation.prototype.select = function() {} - -Rkns.Renderer._BaseRepresentation.prototype.unselect = function() {} - -Rkns.Renderer._BaseRepresentation.prototype.mouseup = function() {} - -Rkns.Renderer._BaseRepresentation.prototype.destroy = function() { - if (this.model) { - this.model.off("change", this._changeBinding ); - this.model.off("remove", this._removeBinding ); - this.model.off("select", this._selectBinding); - this.model.off("unselect", this._unselectBinding); - } -} - -Rkns.Renderer.Node = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation); - -Rkns.Renderer.Node.prototype._init = function() { - this.renderer.node_layer.activate(); - this.type = "Node"; - this.circle = new paper.Path.Circle([0, 0], Rkns.Renderer._NODE_RADIUS); - this.circle.fillColor = '#ffffff'; - this.circle.__representation = this; - this.title = new paper.PointText([0,0]); - this.title.characterStyle = { - fontSize: Rkns.Renderer._NODE_FONT_SIZE, - fillColor: 'black' - }; - this.title.paragraphStyle.justification = 'center'; - this.title.__representation = this; - this.model_coords = new paper.Point(this.model.get("position")); -} - -Rkns.Renderer.Node.prototype.redraw = function() { - this.paper_coords = this.renderer.toPaperCoords(this.model_coords); - this.circle.position = this.paper_coords; - this.title.content = Rkns.Renderer.Utils.shortenText(this.model.get("title"), Rkns.Renderer._NODE_MAX_CHAR); - this.title.position = this.paper_coords.add([0, 2 * Rkns.Renderer._NODE_RADIUS]); - this.circle.strokeColor = this.model.get("created_by").get("color"); - var _img = this.model.get("image"); - if (_img && _img !== this.img) { - var _image = new Image(), - _this = this; - _image.onload = function() { - if (_this.node_image) { - _this.node_image.remove(); - } - _this.renderer.node_layer.activate(); - var _ratio = Math.min(1, 2 * Rkns.Renderer._NODE_RADIUS / _image.width, 2 * Rkns.Renderer._NODE_RADIUS / _image.height ); - var _raster = new paper.Raster(_image); - var _clip = new paper.Path.Circle([0, 0], Rkns.Renderer._NODE_RADIUS); - _raster.scale(_ratio); - _this.node_image = new paper.Group(_clip, _raster); - _this.node_image.opacity = _this.selected ? .5 : .9; - /* This is a workaround to allow clipping at group level */ - _this.node_image.clipped = true; - _this.node_image.position = _this.paper_coords; - _this.node_image.__representation = _this; - paper.view.draw(); - } - _image.src = _img; - } - this.img = _img; - if (this.node_image) { - if (!this.img) { - this.node_image.remove(); - delete this.node_image; - } else { - this.node_image.position = this.paper_coords; - } - } -} - -Rkns.Renderer.Node.prototype.paperShift = function(_delta) { - this.paper_coords = this.paper_coords.add(_delta); - this.model_coords = this.renderer.toModelCoords(this.paper_coords); - this.renderer.redraw(); -} - -Rkns.Renderer.Node.prototype.openTooltip = function() { - this.renderer.removeRepresentationsOfType("tooltip"); - var _tooltip = this.renderer.addRepresentation("NodeTooltip",null); - _tooltip.node_representation = this; - _tooltip.draw(); -} - -Rkns.Renderer.Node.prototype.select = function() { - this.selected = true; - this.circle.strokeWidth = 3; - this.openTooltip(); - this.circle.fillColor = "#ffff80"; - if (this.node_image) { - this.node_image.opacity = .5; - } - paper.view.draw(); -} - -Rkns.Renderer.Node.prototype.unselect = function() { - this.selected = false; - this.circle.strokeWidth = 1; - this.circle.fillColor = "#ffffff"; - if (this.node_image) { - this.node_image.opacity = .9; - } - paper.view.draw(); -} - -Rkns.Renderer.Node.prototype.mouseup = function(_event) { -} - -Rkns.Renderer.Node.prototype.destroy = function(_event) { - this.super("destroy"); - this.circle.remove(); - this.title.remove(); - if (this.node_image) { - this.node_image.remove(); - } -} - -/* */ - -Rkns.Renderer.Edge = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation); - -Rkns.Renderer.Edge.prototype._init = function() { - this.renderer.edge_layer.activate(); - this.type = "Edge"; - this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from")); - this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to")); - this.bundle = this.renderer.addToBundles(this); - this.line = new paper.Path(); - this.line.add([0,0],[0,0],[0,0]); - this.line.__representation = this; - this.arrow = new paper.Path(); - this.arrow.add([0,0],[Rkns.Renderer._ARROW_LENGTH,Rkns.Renderer._ARROW_WIDTH / 2],[0,Rkns.Renderer._ARROW_WIDTH]); - this.arrow.__representation = this; - this.text = new paper.PointText(); - this.text.characterStyle = { - fontSize: Rkns.Renderer._EDGE_FONT_SIZE, - fillColor: 'black' - }; - this.text.paragraphStyle.justification = 'center'; - this.text.__representation = this; - this.text_angle = 0; - this.arrow_angle = 0; -} - -Rkns.Renderer.Edge.prototype.redraw = function() { - var _p0a = this.from_representation.paper_coords, - _p1a = this.to_representation.paper_coords, - _v = _p1a.subtract(_p0a), - _r = _v.length, - _u = _v.divide(_r), - _group_pos = this.bundle.getPosition(this), - _delta = new paper.Point([- _u.y, _u.x]).multiply( 12 * _group_pos ), - _p0b = _p0a.add(_delta), /* Adding a 4 px difference */ - _p1b = _p1a.add(_delta), /* to differentiate inbound and outbound links */ - _a = _v.angle, - _handle = _v.divide(3), - _color = this.model.get("created_by").get("color"); - this.paper_coords = _p0b.add(_p1b).divide(2); - this.line.strokeColor = _color; - this.line.segments[0].point = _p0a; - this.line.segments[1].point = this.paper_coords; - this.line.segments[1].handleIn = _handle.multiply(-1); - this.line.segments[1].handleOut = _handle; - this.line.segments[2].point = _p1a; - this.arrow.rotate(_a - this.arrow_angle); - this.arrow.fillColor = _color; - this.arrow.position = this.paper_coords.subtract(_u.multiply(4)); - this.arrow_angle = _a; - if (_a > 90) { - _a -= 180; - } - if (_a < -90) { - _a += 180; - } - this.text.rotate(_a - this.text_angle); - this.text.content = Rkns.Renderer.Utils.shortenText(this.model.get("title"), Rkns.Renderer._EDGE_MAX_CHAR); - this.text.position = this.paper_coords; - this.text_angle = _a; -} - -Rkns.Renderer.Edge.prototype.openTooltip = function() { - this.renderer.removeRepresentationsOfType("tooltip"); - var _tooltip = this.renderer.addRepresentation("EdgeTooltip",null); - _tooltip.edge_representation = this; - _tooltip.draw(); -} - -Rkns.Renderer.Edge.prototype.select = function() { - this.line.strokeWidth = 3; - this.openTooltip(); - paper.view.draw(); -} - -Rkns.Renderer.Edge.prototype.unselect = function() { - this.line.strokeWidth = 1; - paper.view.draw(); -} - -Rkns.Renderer.Edge.prototype.mouseup = function(_event) { -} - -Rkns.Renderer.Edge.prototype.paperShift = function(_delta) { - this.from_representation.paperShift(_delta); - this.to_representation.paperShift(_delta); - this.renderer.redraw(); -} - -Rkns.Renderer.Edge.prototype.destroy = function() { - this.super("destroy"); - this.line.remove(); - this.arrow.remove(); - this.text.remove(); - var _this = this; - this.bundle.edges = Rkns._(this.bundle.edges).reject(function(_edge) { - return _edge === _this; - }); -} - -/* */ - -Rkns.Renderer.NodeTooltip = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation); - -Rkns.Renderer.NodeTooltip.prototype._init = function() { - this.renderer.overlay_layer.activate(); - this.type = "tooltip"; - this.tooltip_block = new paper.Path(); - var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]}); - this.tooltip_block.add.apply(this.tooltip_block, _pts); - this.tooltip_block.strokeWidth = 2; - this.tooltip_block.strokeColor = "#999999"; - this.tooltip_block.fillColor = "#e0e0e0"; - this.tooltip_block.opacity = .8; - this.tooltip_$ = Rkns.$('<div>') - .appendTo(this.renderer.tooltip_$) - .css({ - position: "absolute", - opacity: .8 - }) - .hide(); -} - -Rkns.Renderer.NodeTooltip.prototype.template = Rkns._.template( - '<h2><span class="Rk-CloseX">×</span><%=a%></h2>' - + '<p><%-description%></p>' - + '<ul class="Rk-Related-List"></ul>' -); - -Rkns.Renderer.NodeTooltip.prototype.draw = function() { - var _model = this.node_representation.model, - _title = _model.get("title"), - _uri = _model.get("uri"); - this.tooltip_$ - .html(this.template({ - a: (_uri ? '<a href="' + _uri + '" target="_blank">' : '' ) + _title + (_uri ? '</a>' : '' ), - description: _model.get("description").replace(/(\n|\r|\r\n)/mg,' ').substr(0,180).replace(/(^.{150,179})[\s].+$/m,'$1…') - })) - var _this = this, - _renkan = this.renderer.renkan, - _uris = _renkan.uris[_uri]; - Rkns._(_uris).each(function(_othernode) { - if (_othernode !== _model && _othernode.get("project") !== _this.project) { - var _otherproj = _othernode.get("project"), - _nodetitle = _othernode.get("title") || "Untitled node" - _projtitle = _otherproj.get("title") || "Untitled node", - _html = _renkan.l10n.see_in_project.replace('{node}',Rkns._.escape(_nodetitle)).replace('{project}',Rkns._.escape(_projtitle)), - _li = Rkns.$("<li>").addClass("Rk-Related").html(_html); - _li.click(function() { - _renkan.renderProject(_otherproj); - Rkns._.defer(function() { - _othernode.trigger("select"); - }); - }); - _this.tooltip_$.append(_li); - } - }); - this.tooltip_$.find(".Rk-CloseX").click(function() { - _this.renderer.removeRepresentation(_this); - paper.view.draw(); - }); - this.redraw(); -} - -Rkns.Renderer.NodeTooltip.prototype.redraw = function() { - var _coords = this.node_representation.paper_coords; - Rkns.Renderer.Utils.drawTooltip(_coords, this.tooltip_block, 250, 15, this.tooltip_$); - this.tooltip_$.show(); -} - -Rkns.Renderer.NodeTooltip.prototype.destroy = function() { - this.tooltip_block.remove(); - this.tooltip_$.detach(); -} - -/* */ - -Rkns.Renderer.EdgeTooltip = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation); - -Rkns.Renderer.EdgeTooltip.prototype._init = function() { - this.renderer.overlay_layer.activate(); - this.type = "tooltip"; - this.tooltip_block = new paper.Path(); - var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]}); - this.tooltip_block.add.apply(this.tooltip_block, _pts); - this.tooltip_block.strokeWidth = 2; - this.tooltip_block.strokeColor = "#999999"; - this.tooltip_block.fillColor = "#e0e0e0"; - this.tooltip_block.opacity = .8; - this.tooltip_$ = Rkns.$('<div>') - .appendTo(this.renderer.tooltip_$) - .css({ - position: "absolute", - opacity: .8 - }) - .hide(); -} - -Rkns.Renderer.EdgeTooltip.prototype.template = Rkns._.template( - '<h2><span class="Rk-CloseX">×</span><%=a%></h2>' - + '<p><%-description%></p>' -); - -Rkns.Renderer.EdgeTooltip.prototype.draw = function() { - var _model = this.edge_representation.model, - _title = _model.get("title"), - _uri = _model.get("uri"); - this.tooltip_$ - .html(this.template({ - a: (_uri ? '<a href="' + _uri + '" target="_blank">' : '' ) + _title + (_uri ? '</a>' : '' ), - description: _model.get("description").replace(/(\n|\r|\r\n)/mg,' ').substr(0,180).replace(/(^.{150,179})[\s].+$/m,'$1…') - })); - this.redraw(); - var _this = this; - this.tooltip_$.find(".Rk-CloseX").click(function() { - _this.renderer.removeRepresentation(_this); - paper.view.draw(); - }); -} - -Rkns.Renderer.EdgeTooltip.prototype.redraw = function() { - var _coords = this.edge_representation.paper_coords; - Rkns.Renderer.Utils.drawTooltip(_coords, this.tooltip_block, 250, 5, this.tooltip_$); - this.tooltip_$.show(); - paper.view.draw(); -} - -Rkns.Renderer.EdgeTooltip.prototype.destroy = function() { - this.tooltip_block.remove(); - this.tooltip_$.detach(); -} - -/* */ - -Rkns.Renderer.Scene = function(_renkan, _project) { - this.renkan = _renkan; - this.project = _project; - this.$ = Rkns.$(".Rk-Render"); - this.representations = []; - this.$.html(this.template({ - width: this.$.width(), - height: this.$.height(), - l10n: _renkan.l10n - })) - this.canvas_$ = this.$.find(".Rk-Canvas"); - this.tooltip_$ = this.$.find(".Rk-Editor"); - paper.setup(this.canvas_$[0]); - this.scale = 1; - this.offset = paper.view.center; - this.totalScroll = 0; - this.click_target = null; - this.selected_target = null; - this.edge_layer = new paper.Layer(); - this.node_layer = new paper.Layer(); - this.overlay_layer = new paper.Layer(); - this.bundles = []; - var _tool = new paper.Tool(), - _this = this; - _tool.minDistance = Rkns.Renderer._MIN_DRAG_DISTANCE; - _tool.onMouseMove = function(_event) { - _this.onMouseMove(_event); - } - _tool.onMouseDown = function(_event) { - _this.onMouseDown(_event); - } - _tool.onMouseDrag = function(_event) { - _this.onMouseDrag(_event); - } - this.canvas_$.mouseup(function(_event) { - _this.onMouseUp(_event); - }); - this.canvas_$.mousewheel(function(_event, _delta) { - _this.onScroll(_event, _delta); - }); - this.tooltip_$.find(".Rk-ZoomOut").click(function() { - _this.offset = new paper.Point([ - _this.canvas_$.width(), - _this.canvas_$.height() - ]).multiply( .5 * ( 1 - Math.SQRT1_2 ) ).add(_this.offset.multiply( Math.SQRT1_2 )); - _this.scale *= Math.SQRT1_2; - _this.redraw(); - }); - this.tooltip_$.find(".Rk-ZoomIn").click(function() { - _this.offset = new paper.Point([ - _this.canvas_$.width(), - _this.canvas_$.height() - ]).multiply( .5 * ( 1 - Math.SQRT2 ) ).add(_this.offset.multiply( Math.SQRT2 )); - _this.scale *= Math.SQRT2; - _this.redraw(); - }); - paper.view.onResize = function(_event) { - _this.offset = _this.offset.add(_event.delta.divide(2)); - _this.redraw(); - } - - var _thRedraw = Rkns._.throttle(function() { - _this.redraw(); - },50); - - this.addRepresentations("Node", this.project.get("nodes")); - this.addRepresentations("Edge", this.project.get("edges")); - - this._addNodesBinding = function(_node) { - _this.addRepresentation("Node", _node); - _thRedraw(); - } - this._addEdgesBinding = function(_edge) { - _this.addRepresentation("Edge", _edge); - _thRedraw(); - } - - this.project.on("add:nodes", this._addNodesBinding ); - this.project.on("add:edges", this._addEdgesBinding ); - this.redraw(); -} - -Rkns.Renderer.Scene.prototype.template = Rkns._.template( - '<canvas class="Rk-Canvas" width="<%-width%>" height="<%-height%>"></canvas><div class="Rk-Editor">' - + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%-l10n.zoom_in%>"></div><div class="Rk-ZoomOut" title="<%-l10n.zoom_out%>"></div></div>' - + '</div>' -); - -Rkns.Renderer.Scene.prototype.addToBundles = function(_edgeRepr) { - var _bundle = Rkns._(this.bundles).find(function(_bundle) { - return ( - ( _bundle.from === _edgeRepr.from_representation && _bundle.to === _edgeRepr.to_representation ) - || ( _bundle.from === _edgeRepr.to_representation && _bundle.to === _edgeRepr.from_representation ) - ); - }); - if (typeof _bundle !== "undefined") { - _bundle.edges.push(_edgeRepr) - } else { - _bundle = { - from: _edgeRepr.from_representation, - to: _edgeRepr.to_representation, - edges: [ _edgeRepr ], - getPosition: function(_er) { - var _dir = (_er.from_representation === this.from) ? 1 : -1; - return _dir * ( Rkns._(this.edges).indexOf(_er) - (this.edges.length - 1) / 2 ); - } - } - this.bundles.push(_bundle); - } - return _bundle; -} - -Rkns.Renderer.Scene.prototype.autoScale = function() { - if (this.project.get("nodes").length) { - var _xx = this.project.get("nodes").map(function(_node) { return _node.get("position").x }), - _yy = this.project.get("nodes").map(function(_node) { return _node.get("position").y }), - _minx = Math.min.apply(Math, _xx), - _miny = Math.min.apply(Math, _yy), - _maxx = Math.max.apply(Math, _xx), - _maxy = Math.max.apply(Math, _yy); - this.scale = Math.min((paper.view.size.width - 2 * Rkns.Renderer._MARGIN_X) / (_maxx - _minx), (paper.view.size.height - 2 * Rkns.Renderer._MARGIN_Y) / (_maxy - _miny)); - this.offset = paper.view.center.subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(this.scale)); - this.redraw(); - } -} - -Rkns.Renderer.Scene.prototype.toPaperCoords = function(_point) { - return _point.multiply(this.scale).add(this.offset); -} - - -Rkns.Renderer.Scene.prototype.toModelCoords = function(_point) { - return _point.subtract(this.offset).divide(this.scale); -} - -Rkns.Renderer.Scene.prototype.addRepresentation = function(_type, _model) { - var _repr = new Rkns.Renderer[_type](this, _model); - this.representations.push(_repr); - return _repr; -} - -Rkns.Renderer.Scene.prototype.addRepresentations = function(_type, _collection) { - var _this = this; - _collection.forEach(function(_model) { - _this.addRepresentation(_type, _model); - }); -} - -Rkns.Renderer.Scene.prototype.removeRepresentation = function(_representation) { - _representation.destroy(); - this.representations = Rkns._(this.representations).reject( - function(_repr) { - return _repr == _representation - } - ); -} - -Rkns.Renderer.Scene.prototype.getRepresentationByModel = function(_model) { - return Rkns._(this.representations).find(function(_repr) { - return _repr.model === _model; - }); -} - -Rkns.Renderer.Scene.prototype.removeRepresentationsOfType = function(_type) { - var _representations = Rkns._(this.representations).filter(function(_repr) { - return _repr.type == _type; - }), - _this = this; - Rkns._(_representations).each(function(_repr) { - _this.removeRepresentation(_repr); - }); -} - -Rkns.Renderer.Scene.prototype.unselectAll = function() { - Rkns._(this.representations).each(function(_repr) { - _repr.model.trigger("unselect"); - }); -} - -Rkns.Renderer.Scene.prototype.redraw = function() { - Rkns._(this.representations).each(function(_representation) { - _representation.redraw(); - }); - paper.view.draw(); -} - -Rkns.Renderer.Scene.prototype.addTempEdge = function(_from, _point) { - var _tmpEdge = this.addRepresentation("TempEdge",null); - _tmpEdge.end_pos = _point; - _tmpEdge.from_representation = _from; - _tmpEdge.redraw(); - this.click_target = _tmpEdge; -} - -Rkns.Renderer.Scene.prototype.findTarget = function(_hitResult) { - if (_hitResult && typeof _hitResult.item.__representation !== "undefined") { - var _newTarget = _hitResult.item.__representation; - if (this.selected_target !== _newTarget && _newTarget.model) { - if (this.selected_target) { - this.selected_target.model.trigger("unselect"); - } - _newTarget.model.trigger("select"); - this.selected_target = _newTarget; - } - } else { - if (!_hitResult) { - this.removeRepresentationsOfType("tooltip"); - } - if (this.selected_target) { - this.selected_target.model.trigger("unselect"); - } - this.selected_target = null; - } -} - -Rkns.Renderer.Scene.prototype.onMouseMove = function(_event) { - var _hitResult = paper.project.hitTest(_event.point); - if (this.is_dragging) { - if (this.click_target && typeof this.click_target.paperShift === "function") { - this.click_target.paperShift(_event.delta); - } else { - this.offset = this.offset.add(_event.delta); - this.redraw(); - } - } else { - this.findTarget(_hitResult); - } -} - -Rkns.Renderer.Scene.prototype.onMouseDown = function(_event) { - this.is_dragging = false; - var _hitResult = paper.project.hitTest(_event.point); - if (_hitResult && typeof _hitResult.item.__representation !== "undefined") { - this.click_target = _hitResult.item.__representation; - } else { - this.click_target = null; - } -} - -Rkns.Renderer.Scene.prototype.onMouseDrag = function(_event) { - this.is_dragging = true; - this.onMouseMove(_event); -} - -Rkns.Renderer.Scene.prototype.onMouseUp = function(_event) { - if (this.click_target) { - var _off = this.canvas_$.offset(); - if (this.click_target.model) { - this.click_target.model.trigger("click"); - } - } - this.is_dragging = false; - this.click_target = null; -} - -Rkns.Renderer.Scene.prototype.onScroll = function(_event, _scrolldelta) { - this.totalScroll += _scrolldelta; - if (Math.abs(this.totalScroll) >= 1) { - var _off = this.canvas_$.offset(), - _delta = new paper.Point([ - _event.pageX - _off.left, - _event.pageY - _off.top - ]).subtract(this.offset).multiply( Math.SQRT2 - 1 ); - if (this.totalScroll > 0) { - this.offset = this.offset.subtract(_delta); - this.scale *= Math.SQRT2; - } else { - this.offset = this.offset.add(_delta.divide( Math.SQRT2 )); - this.scale *= Math.SQRT1_2; - } - this.totalScroll = 0; - this.redraw(); - } -} - -Rkns.Renderer.Scene.prototype.destroy = function() { - this.project.off("add:nodes", this._addNodesBinding ); - this.project.off("add:edges", this._addEdgesBinding ); - Rkns._(this.representations).each(function(_repr) { - _repr.destroy(); - }); - this.$.html(""); - paper.remove(); -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/js/libs/renkan.js Tue Apr 23 15:23:20 2013 +0200 @@ -0,0 +1,3232 @@ +/* + * Copyright 2012-2013 Institut de recherche et d'innovation + * contributor(s) : Yves-Marie Haussonne, Raphael Velt, Samuel Huron + * + * contact@iri.centrepompidou.fr + * http://www.iri.centrepompidou.fr + * + * This software is a computer program whose purpose is to show and add annotations on a video . + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. +*/ + +/* Declaring the Renkan Namespace Rkns and Default values */ + +if (typeof Rkns !== "object") { + Rkns = {} +} + +Rkns.$ = jQuery; + +Rkns._ = _; + +Rkns.VERSION = '0.2'; + +Rkns.pickerColors = ["#8f1919", "#a80000", "#d82626", "#ff0000", "#e87c7c", "#ff6565", "#f7d3d3", "#fecccc", + "#8f5419", "#a85400", "#d87f26", "#ff7f00", "#e8b27c", "#ffb265", "#f7e5d3", "#fee5cc", + "#8f8f19", "#a8a800", "#d8d826", "#feff00", "#e8e87c", "#feff65", "#f7f7d3", "#fefecc", + "#198f19", "#00a800", "#26d826", "#00ff00", "#7ce87c", "#65ff65", "#d3f7d3", "#ccfecc", + "#198f8f", "#00a8a8", "#26d8d8", "#00feff", "#7ce8e8", "#65feff", "#d3f7f7", "#ccfefe", + "#19198f", "#0000a8", "#2626d8", "#0000ff", "#7c7ce8", "#6565ff", "#d3d3f7", "#ccccfe", + "#8f198f", "#a800a8", "#d826d8", "#ff00fe", "#e87ce8", "#ff65fe", "#f7d3f7", "#feccfe", + "#000000", "#242424", "#484848", "#6d6d6d", "#919191", "#b6b6b6", "#dadada", "#ffffff"]; + +Rkns._BaseBin = function(_renkan, _opts) { + if (typeof _renkan !== "undefined") { + this.renkan = _renkan; + this.renkan.$.find(".Rk-Bin-Main").hide(); + this.$ = Rkns.$('<li>') + .addClass("Rk-Bin") + .appendTo(_renkan.$.find(".Rk-Bin-List")); + this.title_icon_$ = Rkns.$('<span>') + .addClass("Rk-Bin-Title-Icon") + .appendTo(this.$); + + var _this = this; + + Rkns.$('<a>') + .attr({ + href: "#", + title: _renkan.translate("Close bin") + }) + .addClass("Rk-Bin-Close") + .html('×') + .appendTo(this.$) + .click(function() { + _this.destroy(); + if (!_renkan.$.find(".Rk-Bin-Main:visible").length) { + _renkan.$.find(".Rk-Bin-Main:last").slideDown(); + } + _renkan.resizeBins(); + return false; + }); + Rkns.$('<a>') + .attr({ + href: "#", + title: _renkan.translate("Refresh bin") + }) + .addClass("Rk-Bin-Refresh") + .appendTo(this.$) + .click(function() { + _this.refresh(); + return false; + }); + this.count_$ = Rkns.$('<div>') + .addClass("Rk-Bin-Count") + .appendTo(this.$); + this.title_$ = Rkns.$('<h2>') + .addClass("Rk-Bin-Title") + .appendTo(this.$); + this.main_$ = Rkns.$('<div>') + .addClass("Rk-Bin-Main") + .appendTo(this.$) + .html('<h4 class="Rk-Bin-Loading">' + _renkan.translate("Loading, please wait") + '</h4>'); + this.title_$.html(_opts.title || '(new bin)'); + this.renkan.resizeBins(); + + if (_opts.auto_refresh) { + window.setInterval(function() { + _this.refresh(); + },_opts.auto_refresh) + } + } +}; + +Rkns._BaseBin.prototype.destroy = function() { + this.$.detach(); + this.renkan.resizeBins(); +}; + +/* Point of entry */ + +Rkns.Renkan = function(_opts) { + var _this = this; + + this.options = _.defaults(_opts, Rkns.defaults); + + Rkns._(this.options.property_files).each(function(f) { + Rkns.$.getJSON(f, function(data) { + _this.options.properties = _this.options.properties.concat(data); + }); + }); + + this.read_only = this.options.read_only || !this.options.editor_mode; + + this.project = new Rkns.Models.Project(); + + if (typeof this.options.user_id !== "undefined") { + this.current_user = this.options.user_id; + } + this.$ = Rkns.$("#" + this.options.container); + this.$ + .addClass("Rk-Main") + .html(this.template(this)); + this.renderer = new Rkns.Renderer.Scene(this); + this.tabs = []; + this.search_engines = []; + + this.current_user_list = new Rkns.Models.UsersList(); + + if (!this.options.search.length) { + this.$.find(".Rk-Web-Search-Form").detach(); + } else { + var _tmpl = Rkns._.template('<li class="<%= className %>" data-key="<%= key %>"><%= title %></li>'), + _select = this.$.find(".Rk-Search-List"), + _input = this.$.find(".Rk-Web-Search-Input") + _form = this.$.find(".Rk-Web-Search-Form"); + Rkns._(this.options.search).each(function(_search, _key) { + if (Rkns[_search.type] && Rkns[_search.type].Search) { + _this.search_engines.push(new Rkns[_search.type].Search(_this, _search)); + } + }); + _select.html( + Rkns._(this.search_engines).map(function(_search, _key) { + return _tmpl({ + key: _key, + title: _search.getSearchTitle(), + className: _search.getBgClass() + }); + }).join("") + ); + _select.find("li").click(function() { + var _el = Rkns.$(this); + _this.setSearchEngine(_el.attr("data-key")); + _form.submit(); + }); + _form.submit(function() { + if (_input.val()) { + var _search = _this.search_engine; + _search.search(_input.val()); + } + return false; + }); + this.$.find(".Rk-Search-Current").mouseenter( + function() { _select.slideDown(); } + ); + this.$.find(".Rk-Search-Select").mouseleave( + function() { _select.hide(); } + ); + this.setSearchEngine(0); + } + Rkns._(this.options.bins).each(function(_bin) { + if (Rkns[_bin.type] && Rkns[_bin.type].Bin) { + _this.tabs.push(new Rkns[_bin.type].Bin(_this, _bin)); + } + }); + + var elementDropped = false; + + this.$.find(".Rk-Bins") + .on("click",".Rk-Bin-Title,.Rk-Bin-Title-Icon", function() { + var _mainDiv = Rkns.$(this).siblings(".Rk-Bin-Main"); + if (_mainDiv.is(":hidden")) { + _this.$.find(".Rk-Bin-Main").slideUp(); + _mainDiv.slideDown(); + } + }).on("mouseover", ".Rk-Bin-Item", function(_e) { + var _t = Rkns.$(this); + if (_t && $(_t).attr("data-uri")) { + var _models = _this.project.get("nodes").where({ + uri: $(_t).attr("data-uri") + }); + Rkns._(_models).each(function(_model) { + _this.renderer.highlightModel(_model); + }); + } + }).mouseout(function() { + _this.renderer.unhighlightAll(); + }).on("mousemove", ".Rk-Bin-Item", function(e) { + try { + this.dragDrop(); + } + catch(err) {} + }).on("touchstart", ".Rk-Bin-Item", function(e) { + elementDropped = false; + }).on("touchmove", ".Rk-Bin-Item", function(e) { + e.preventDefault(); + var touch = e.originalEvent.changedTouches[0], + off = _this.renderer.canvas_$.offset(), + w = _this.renderer.canvas_$.width(), + h = _this.renderer.canvas_$.height(); + if (touch.pageX >= off.left && touch.pageX < (off.left + w) && touch.pageY >= off.top && touch.pageY < (off.top + h)) { + if (elementDropped) { + _this.renderer.onMouseMove(touch, true); + } else { + elementDropped = true; + var div = document.createElement('div'); + div.appendChild(this.cloneNode(true)); + _this.renderer.dropData({"text/html": div.innerHTML}, touch); + _this.renderer.onMouseDown(touch, true); + } + } + }).on("touchend", ".Rk-Bin-Item", function(e) { + if (elementDropped) { + _this.renderer.onMouseUp(e.originalEvent.changedTouches[0], true); + } + elementDropped = false; + }).on("dragstart", ".Rk-Bin-Item", function(e) { + var div = document.createElement('div'); + div.appendChild(this.cloneNode(true)); + try { + e.originalEvent.dataTransfer.setData("text/html",div.innerHTML); + } + catch(err) { + e.originalEvent.dataTransfer.setData("text",div.innerHTML); + } + }); + Rkns.$(window).resize(function() { + _this.resizeBins(); + }); + + this.$.find(".Rk-Bins-Search-Input").on("change keyup paste input", function() { + var val = Rkns.$(this).val(); + Rkns._(_this.tabs).each(function(tab) { + tab.render(val); + }); + }); + this.$.find(".Rk-Bins-Search-Form").submit(function() { + return false + }); +}; + +Rkns.Renkan.prototype.template = Rkns._.template( + '<% if (options.show_bins) { %><div class="Rk-Bins"><div class="Rk-Bins-Head"><h2 class="Rk-Bins-Title"><%- translate("Select contents:")%></h2>' + + '<form class="Rk-Web-Search-Form Rk-Search-Form"><input class="Rk-Web-Search-Input Rk-Search-Input" type="search" placeholder="<%- translate("Search the Web") %>" />' + + '<div class="Rk-Search-Select"><div class="Rk-Search-Current"></div><ul class="Rk-Search-List"></ul></div>' + + '<input type="submit" value="" class="Rk-Web-Search-Submit Rk-Search-Submit" title="<%- translate("Search the Web") %>" /></form>' + + '<form class="Rk-Bins-Search-Form Rk-Search-Form"><input class="Rk-Bins-Search-Input Rk-Search-Input" type="search" placeholder="<%- translate("Search in Bins") %>" />' + + '<input type="submit" value="" class="Rk-Bins-Search-Submit Rk-Search-Submit" title="<%- translate("Search in Bins") %>" /></form></div>' + + '<ul class="Rk-Bin-List"></ul></div><% } %><div class="Rk-Render Rk-Render-<% if (options.show_bins) { %>Panel<% } else { %>Full<% } %>"></div>' +); + +Rkns.Renkan.prototype.translate = function(_text) { + if (Rkns.i18n[this.options.language] && Rkns.i18n[this.options.language][_text]) { + return Rkns.i18n[this.options.language][_text]; + } + if (this.options.language.length > 2 && Rkns.i18n[this.options.language.substr(0,2)] && Rkns.i18n[this.options.language.substr(0,2)][_text]) { + return Rkns.i18n[this.options.language.substr(0,2)][_text]; + } + return _text; +}; + +Rkns.Renkan.prototype.onStatusChange = function() { + this.renderer.onStatusChange(); +}; + +Rkns.Renkan.prototype.setSearchEngine = function(_key) { + this.search_engine = this.search_engines[_key]; + this.$.find(".Rk-Search-Current").attr("class","Rk-Search-Current " + this.search_engine.getBgClass()); +}; + +Rkns.Renkan.prototype.resizeBins = function() { + var _d = + this.$.find(".Rk-Bins-Head").outerHeight(); + this.$.find(".Rk-Bin-Title:visible").each(function() { + _d += Rkns.$(this).outerHeight(); + }); + this.$.find(".Rk-Bin-Main").css({ + height: this.$.find(".Rk-Bins").height() - _d + }); +}; + +/* Utility functions */ + +Rkns.Utils = { + _ID_AUTO_INCREMENT : 0, + _ID_BASE : (function(_d) { + + function pad(n){return n<10 ? '0'+n : n} + function fillrand(n) { + var _res = '' + for (var i=0; i<n; i++) { + _res += Math.floor(16*Math.random()).toString(16); + } + return _res; + } + return _d.getUTCFullYear() + '-' + + pad(_d.getUTCMonth()+1) + '-' + + pad(_d.getUTCDate()) + '-' + + fillrand(16); + + })(new Date()), + getUID : function(_base) { + + var _n = (++this._ID_AUTO_INCREMENT).toString(16), + _base = (typeof _base === "undefined" ? "" : _base + "-" ); + while (_n.length < 4) { + _n = '0' + _n + } + return _base + this._ID_BASE + '-' + _n; + + }, + getFullURL : function(url) { + + if(typeof(url) == 'undefined' || url == null ) { + return ""; + } + if(/https?:\/\//.test(url)) { + return url; + } + var img = new Image(); + img.src = url; + var res = img.src; + img.src = null; + return res; + + }, + inherit : function(_baseClass, _callbefore) { + + var _class = function(_arg) { + if (typeof _callbefore === "function") { + _callbefore.apply(this, Array.prototype.slice.call(arguments, 0)); + } + _baseClass.apply(this, Array.prototype.slice.call(arguments, 0)); + if (typeof this._init == "function" && !this._initialized) { + this._init.apply(this, Array.prototype.slice.call(arguments, 0)); + this._initialized = true; + } + } + Rkns._(_class.prototype).extend(_baseClass.prototype); + return _class; + + } +}; + +Rkns.defaults = { + + language: (navigator.language || navigator.userLanguage || "en"), + /* GUI Language */ + container: "renkan", + /* GUI Container DOM element ID */ + search: [], + /* List of Search Engines */ + bins: [], + /* List of Bins */ + static_url: "", + /* URL for static resources */ + show_bins: true, + /* Show bins in left column */ + properties: [], + /* Semantic properties for edges */ + read_only: false, + /* Allows editing of renkan without changing the rest of the GUI. Can be switched on/off on the fly to block/enable editing */ + editor_mode: true, + /* Switch for Publish/Edit GUI. If editor_mode is false, read_only will be true. */ + snapshot_mode: false, + /* In snapshot mode, clicking on the floppy will save a snapshot. Otherwise, it will show the connection status */ + show_top_bar: true, + /* Show the top bar, (title, buttons, users) */ + default_user_color: "#303030", + size_bug_fix: true, + /* Resize the canvas after load (fixes a bug on iPad and FF Mac) */ + force_resize: false, + allow_double_click: true, + /* Allows Double Click to create a node on an empty background */ + element_delete_delay: 5000, + + /* MINI-MAP OPTIONS */ + + show_minimap: true, + /* Show a small map at the bottom right */ + minimap_width: 160, + minimap_height: 120, + minimap_background_color: "#ffffff", + minimap_border_color: "#cccccc", + minimap_highlight_color: "#ffff00", + minimap_highlight_weight: 5, + + /* EDGE/NODE COMMON OPTIONS */ + + buttons_background: "#202020", + buttons_label_color: "#c000c0", + buttons_label_font_size: 9, + + /* NODE DISPLAY OPTIONS */ + + show_node_circles: true, + /* Show circles for nodes */ + clip_node_images: true, + /* Constraint node images to circles */ + node_size_base: 25, + node_stroke_width: 2, + selected_node_stroke_width: 4, + node_fill_color: "#ffffff", + highlighted_node_fill_color: "#ffff00", + node_label_distance: 5, + /* Vertical distance between node and label */ + node_label_max_length: 60, + /* Maximum displayed text length */ + label_untitled_nodes: "(untitled)", + /* Label to display on untitled nodes */ + + /* EDGE DISPLAY OPTIONS */ + + edge_stroke_width: 2, + selected_edge_stroke_width: 4, + edge_label_distance: 0, + edge_label_max_length: 20, + edge_arrow_length: 18, + edge_arrow_width: 12, + edge_gap_in_bundles: 12, + label_untitled_edges: "", + + /* CONTEXTUAL DISPLAY (TOOLTIP OR EDITOR) OPTIONS */ + + tooltip_width: 275, + tooltip_padding: 10, + tooltip_margin: 15, + tooltip_arrow_length : 20, + tooltip_arrow_width : 40, + tooltip_top_color: "#f0f0f0", + tooltip_bottom_color: "#d0d0d0", + tooltip_border_color: "#808080", + tooltip_border_width: 1 + +}; + +(function() { + + var root = this; + + var Backbone = root.Backbone; + + var Models = root.Rkns.Models = {}; + + + Models.getUID = function(obj) { + var guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); + return v.toString(16); + }); + return obj.type + "-" + guid; + }; + + + var RenkanModel = Backbone.RelationalModel.extend({ + idAttribute : "_id", + constructor: function(options) { + + if (typeof options !== "undefined") { + options._id = options._id || options.id || Models.getUID(this); + options.title = options.title || ""; + options.description = options.description || ""; + options.uri = options.uri || ""; + + if(typeof this.prepare === "function") { + options = this.prepare(options); + } + } + Backbone.RelationalModel.prototype.constructor.call(this, options); + }, + validate: function() { + if(!this.type) { + return "object has no type"; + } + }, + addReference : function(_options, _propName, _list, _id, _default) { + var _element = _list.get(_id); + if (typeof _element === "undefined" && typeof _default !== "undefined") { + _options[_propName ] = _default; + } + else { + _options[_propName ] = _element; + } + } + }); + + // USER + var User = Models.User = RenkanModel.extend({ + type: "user", + prepare: function(options) { + options.color = options.color || "#666666"; + return options; + }, + toJSON: function() { + return { + _id: this.get("_id"), + title: this.get("title"), + uri: this.get("uri"), + description: this.get("description"), + color: this.get("color"), + }; + }, + }); + + // NODE + var Node = Models.Node = RenkanModel.extend({ + type: "node", + relations: [{ + type: Backbone.HasOne, + key: "created_by", + relatedModel: User + }], + prepare: function(options) { + project = options.project; + this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user); + options.description = options.description || ""; + return options; + }, + toJSON: function() { + return { + _id: this.get("_id"), + title: this.get("title"), + uri: this.get("uri"), + description: this.get("description"), + position: this.get("position"), + image: this.get("image"), + color: this.get("color"), + created_by: this.get("created_by") ? this.get("created_by").get("_id") : null, + size: this.get("size") + }; + }, + }); + + // EDGE + var Edge = Models.Edge = RenkanModel.extend({ + type: "edge", + relations: [ + { + type: Backbone.HasOne, + key: "created_by", + relatedModel: User + }, + { + type: Backbone.HasOne, + key: "from", + relatedModel: Node + }, + { + type: Backbone.HasOne, + key: "to", + relatedModel: Node + }, + ], + prepare: function(options) { + project = options.project; + this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user); + this.addReference(options, "from", project.get("nodes"), options.from); + this.addReference(options, "to", project.get("nodes"), options.to); + return options; + }, + toJSON: function() { + return { + _id: this.get("_id"), + title: this.get("title"), + uri: this.get("uri"), + description: this.get("description"), + from: this.get("from") ? this.get("from").get("_id") : null, + to: this.get("to") ? this.get("to").get("_id") : null, + color: this.get("color"), + created_by: this.get("created_by") ? this.get("created_by").get("_id") : null + }; + }, + }); + + // PROJECT + var Project = Models.Project = RenkanModel.extend({ + type: "project", + relations: [ + { + type: Backbone.HasMany, + key: "users", + relatedModel: User, + reverseRelation: { + key: 'project', + includeInJSON: '_id' + }, + }, + { + type: Backbone.HasMany, + key: "nodes", + relatedModel: Node, + reverseRelation: { + key: 'project', + includeInJSON: '_id' + }, + }, + { + type: Backbone.HasMany, + key: "edges", + relatedModel: Edge, + reverseRelation: { + key: 'project', + includeInJSON: '_id' + }, + } + ], + addUser: function(_props, _options) { + _props.project = this; + var _user = User.findOrCreate(_props); + this.get("users").push(_user, _options); + return _user; + }, + addNode: function(_props, _options) { + _props.project = this; + var _node = Node.findOrCreate(_props); + this.get("nodes").push(_node, _options); + return _node; + }, + addEdge: function(_props, _options) { + _props.project = this; + var _edge = Edge.findOrCreate(_props); + this.get("edges").push(_edge, _options); + return _edge; + }, + removeNode: function(_model) { + this.get("nodes").remove(_model); + }, + removeEdge: function(_model) { + this.get("edges").remove(_model); + }, + validate: function(options) { + var _project = this; + _(options.users).each(function(_item) { + _item.project = _project; + }); + _(options.nodes).each(function(_item) { + _item.project = _project; + }); + _(options.edges).each(function(_item) { + _item.project = _project; + }); + }, + // Add event handler to remove edges when a node is removed + initialize: function() { + var _this = this; + this.on("remove:nodes", function(_node) { + _this.get("edges").remove( + _this.get("edges").filter(function(_edge) { + return _edge.get("from") == _node || _edge.get("to") == _node; + }) + ); + }); + } + }); + + var RosterUser = Models.RosterUser = Backbone.Model.extend({ + type: "roster_user", + idAttribute : "_id", + + constructor: function(options) { + + if (typeof options !== "undefined") { + options._id = options._id || options.id || Models.getUID(this); + options.title = options.title || "(untitled " + this.type + ")"; + options.description = options.description || ""; + options.uri = options.uri || ""; + options.project = options.project || null; + options.site_id = options.site_id || 0; + + if(typeof this.prepare === "function") { + options = this.prepare(options); + } + } + Backbone.Model.prototype.constructor.call(this, options); + }, + + validate: function() { + if(!this.type) { + return "object has no type"; + } + }, + + prepare: function(options) { + options.color = options.color || "#666666"; + return options; + }, + + toJSON: function() { + return { + _id: this.get("_id"), + title: this.get("title"), + uri: this.get("uri"), + description: this.get("description"), + color: this.get("color"), + project: (this.get("project") != null)?this.get("project").get("id"):null, + site_id: this.get("site_id") + }; + }, + }); + + var UsersList = Models.UsersList = Backbone.Collection.extend({ + model: RosterUser + }); + + +}).call(window); + +Rkns.i18n = { + fr: { + "Edit Node": "Édition d’un nÅ“ud", + "Edit Edge": "Édition d’un lien", + "Title:": "Titre :", + "URI:": "URI :", + "Description:": "Description :", + "From:": "De :", + "To:": "Vers :", + "Image": "Image", + "Image URL:": "URL d'Image", + "Choose Image File:": "Choisir un fichier image", + "Full Screen": "Mode plein écran", + "Add Node": "Ajouter un nÅ“ud", + "Add Edge": "Ajouter un lien", + "Archive Project": "Archiver le projet", + "Auto-save enabled": "Enregistrement automatique activé", + "Connection lost": "Connexion perdue", + "Created by:": "Créé par :", + "Zoom In": "Agrandir l’échelle", + "Zoom Out": "Rapetisser l’échelle", + "Edit": "Éditer", + "Remove": "Supprimer", + "Cancel deletion": "Annuler la suppression", + "Link to another node": "Créer un lien", + "Enlarge": "Agrandir", + "Shrink": "Rétrécir", + "Click on the background canvas to add a node": "Cliquer sur le fond du graphe pour rajouter un nÅ“ud", + "Click on a first node to start the edge": "Cliquer sur un premier nÅ“ud pour commencer le lien", + "Click on a second node to complete the edge": "Cliquer sur un second nÅ“ud pour terminer le lien", + "Twitter": "Twitter", + "Wikipedia": "Wikipédia", + "Wikipedia in ": "Wikipédia en ", + "French": "Français", + "English": "Anglais", + "Japanese": "Japonais", + "Untitled project": "Projet sans titre", + "Lignes de Temps": "Lignes de Temps", + "Loading, please wait": "Chargement en cours, merci de patienter", + "Edge color:": "Couleur :", + "Node color:": "Couleur :", + "Choose color": "Choisir une couleur", + "Change edge direction": "Changer le sens du lien", + "Do you really wish to remove node ": "Voulez-vous réellement supprimer le nÅ“ud ", + "Do you really wish to remove edge ": "Voulez-vous réellement supprimer le lien ", + "This file is not an image": "Ce fichier n'est pas une image", + "Image size must be under ": "L'image doit peser moins de ", + "Size:": "Taille :", + "KB": "ko", + "Choose from vocabulary:": "Choisir dans un vocabulaire :", + "SKOS Documentation properties": "SKOS: Propriétés documentaires", + "has note": "a pour note", + "has example": "a pour exemple", + "has definition": "a pour définition", + "SKOS Semantic relations": "SKOS: Relations sémantiques", + "has broader": "a pour concept plus large", + "has narrower": "a pour concept plus étroit", + "has related": "a pour concept apparenté", + "Dublin Core Metadata": "Métadonnées Dublin Core", + "has contributor": "a pour contributeur", + "covers": "couvre", + "created by": "créé par", + "has date": "a pour date", + "published by": "édité par", + "has source": "a pour source", + "has subject": "a pour sujet", + "Dragged resource": "Ressource glisée-déposée", + "Search the Web": "Rechercher en ligne", + "Search in Bins": "Rechercher dans les chutiers", + "Close bin": "Fermer le chutier", + "Refresh bin": "Rafraîchir le chutier", + "(untitled)": "(sans titre)", + "Select contents:": "Sélectionner des contenus :", + "Drag items from this website, drop them in Renkan": "Glissez des éléments de ce site web vers Renkan", + "Drag this button to your bookmark bar. When on a third-party website, click it to enable drag-and-drop from the website to Renkan.": "Glissez ce bouton vers votre barre de favoris. Ensuite, depuis un site tiers, cliquez dessus pour activer 'Drag-to-Add' puis glissez des éléments de ce site vers Renkan" + } +} + +/* Loads a JSON File */ + +Rkns.jsonIO = function(_renkan, _opts) { + var _proj = _renkan.project; + if (typeof _opts.http_method == "undefined") { + _opts.http_method = 'PUT'; + } + var _load = function() { + Rkns.$.getJSON(_opts.url, function(_data) { + _proj.set(_data, {validate: true}); + _renkan.renderer.autoScale(); + }); + } + + _load(); +} + +Rkns.Renderer = { + _MINIMAP_MARGIN: 20, + _MIN_DRAG_DISTANCE: 2, + _NODE_BUTTON_WIDTH: 40, + _EDGE_BUTTON_INNER: 2, + _EDGE_BUTTON_OUTER: 40, + _CLICKMODE_ADDNODE : 1, + _CLICKMODE_STARTEDGE : 2, + _CLICKMODE_ENDEDGE : 3, + _IMAGE_MAX_KB : 500, + _NODE_SIZE_STEP: Math.LN2/4, + _MIN_SCALE: 1/20, + _MAX_SCALE: 20, + _AUTOSCALE_MARGIN: 50, + _MOUSEMOVE_RATE: 80, + _DOUBLETAP_DELAY: 800, + _DOUBLETAP_DISTANCE: 20*20, + _USER_PLACEHOLDER : function(_renkan) { + return { + color: _renkan.options.default_user_color, + title: _renkan.translate("(unknown user)"), + get: function(attr) { + return this[attr] || false; + } + } + }, + _BOOKMARKLET_CODE: function(_renkan) { + return "(function(a,b,c,d,e,f,h,i,j,k,l,m,n,o,p,q,r){a=document;b=a.body;c=a.location.href;j='draggable';m='text/x-iri-';d=a.createElement('div');d.innerHTML='<p_style=\"position:fixed;top:0;right:0;font:bold_18px_sans-serif;color:#fff;background:#909;padding:10px;z-index:100000;\">" + + _renkan.translate("Drag items from this website, drop them in Renkan").replace(/ /g,"_") + + "</p>'.replace(/_/g,String.fromCharCode(32));b.appendChild(d);e=[{r:/https?:\\/\\/[^\\/]*twitter\\.com\\//,s:'.tweet',n:'twitter'},{r:/https?:\\/\\/[^\\/]*google\\.[^\\/]+\\//,s:'.g',n:'google'},{r:/https?:\\/\\/[^\\/]*lemonde\\.fr\\//,s:'[data-vr-contentbox]',n:'lemonde'}];f=false;e.forEach(function(g){if(g.r.test(c)){f=g;}});if(f){h=function(){Array.prototype.forEach.call(a.querySelectorAll(f.s),function(i){i[j]=true;k=i.style;k.borderWidth='2px';k.borderColor='#909';k.borderStyle='solid';k.backgroundColor='rgba(200,0,180,.1)';})};window.setInterval(h,500);h();};a.addEventListener('dragstart',function(k){l=k.dataTransfer;l.setData(m+'source-uri',c);l.setData(m+'source-title',a.title);n=k.target;if(f){o=n;while(!o.attributes[j]){o=o.parentNode;if(o==b){break;}}}if(f&&o.attributes[j]){p=o.cloneNode(true);l.setData(m+'specific-site',f.n)}else{q=a.getSelection();if(q.type==='Range'||!q.type){p=q.getRangeAt(0).cloneContents();}else{p=n.cloneNode();}}r=a.createElement('div');r.appendChild(p);l.setData('text/x-iri-selected-text',r.textContent.trim());l.setData('text/x-iri-selected-html',r.innerHTML);},false);})();" + }, + shortenText : function(_text, _maxlength) { + return (_text.length > _maxlength ? (_text.substr(0,_maxlength) + '…') : _text); + }, + drawEditBox : function(_options, _coords, _path, _xmargin, _selector) { + _selector.css({ + width: ( _options.tooltip_width - 2* _options.tooltip_padding ), + }) + var _height = _selector.outerHeight() + 2* _options.tooltip_padding, + _isLeft = (_coords.x < paper.view.center.x ? 1 : -1), + _left = _coords.x + _isLeft * ( _xmargin + _options.tooltip_arrow_length ), + _right = _coords.x + _isLeft * ( _xmargin + _options.tooltip_arrow_length + _options.tooltip_width ), + _top = _coords.y - _height / 2; + if (_top + _height > (paper.view.size.height - _options.tooltip_margin)) { + _top = Math.max( paper.view.size.height - _options.tooltip_margin, _coords.y + _options.tooltip_arrow_width / 2 ) - _height; + } + if (_top < _options.tooltip_margin) { + _top = Math.min( _options.tooltip_margin, _coords.y - _options.tooltip_arrow_width / 2 ); + } + var _bottom = _top + _height; + _path.segments[0].point + = _path.segments[7].point + = _coords.add([_isLeft * _xmargin, 0]); + _path.segments[1].point.x + = _path.segments[2].point.x + = _path.segments[5].point.x + = _path.segments[6].point.x + = _left; + _path.segments[3].point.x + = _path.segments[4].point.x + = _right; + _path.segments[2].point.y + = _path.segments[3].point.y + = _top; + _path.segments[4].point.y + = _path.segments[5].point.y + = _bottom; + _path.segments[1].point.y = _coords.y - _options.tooltip_arrow_width / 2; + _path.segments[6].point.y = _coords.y + _options.tooltip_arrow_width / 2; + _path.closed = true; + _path.fillColor = new paper.GradientColor(new paper.Gradient([_options.tooltip_top_color, _options.tooltip_bottom_color]), [0,_top], [0, _bottom]); + _selector.css({ + left: (_options.tooltip_padding + Math.min(_left, _right)), + top: (_options.tooltip_padding + _top) + }); + return _path; + } +} + +Rkns.Renderer._BaseRepresentation = function(_renderer, _model) { + if (typeof _renderer !== "undefined") { + this.renderer = _renderer; + this.renkan = _renderer.renkan; + this.project = _renderer.renkan.project; + this.options = _renderer.renkan.options; + this.model = _model; + if (this.model) { + var _this = this; + this._changeBinding = function() { + _this.redraw(); + } + this._removeBinding = function() { + _renderer.removeRepresentation(_this); + _(function() { + _renderer.redraw() + }).defer(); + } + this._selectBinding = function() { + _this.select(); + } + this._unselectBinding = function() { + _this.unselect(); + } + this.model.on("change", this._changeBinding ); + this.model.on("remove", this._removeBinding ); + this.model.on("select", this._selectBinding ); + this.model.on("unselect", this._unselectBinding ); + } + } +} + +Rkns.Renderer._BaseRepresentation.prototype.super = function(_func) { + Rkns.Renderer._BaseRepresentation.prototype[_func].apply(this, Array.prototype.slice.call(arguments, 1)); +} + +Rkns.Renderer._BaseRepresentation.prototype.redraw = function() {} + +Rkns.Renderer._BaseRepresentation.prototype.moveTo = function() {} + +Rkns.Renderer._BaseRepresentation.prototype.show = function() {} + +Rkns.Renderer._BaseRepresentation.prototype.hide = function() {} + +Rkns.Renderer._BaseRepresentation.prototype.select = function() { + if (this.model) { + this.model.trigger("selected"); + } +} + +Rkns.Renderer._BaseRepresentation.prototype.unselect = function() { + if (this.model) { + this.model.trigger("unselected"); + } +} + +Rkns.Renderer._BaseRepresentation.prototype.highlight = function() {} + +Rkns.Renderer._BaseRepresentation.prototype.unhighlight = function() {} + +Rkns.Renderer._BaseRepresentation.prototype.mousedown = function() {} + +Rkns.Renderer._BaseRepresentation.prototype.mouseup = function() { + if (this.model) { + this.model.trigger("clicked"); + } +} + +Rkns.Renderer._BaseRepresentation.prototype.destroy = function() { + if (this.model) { + this.model.off("change", this._changeBinding ); + this.model.off("remove", this._removeBinding ); + this.model.off("select", this._selectBinding ); + this.model.off("unselect", this._unselectBinding ); + } +} + +/* */ + +Rkns.Renderer._BaseButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation); + +Rkns.Renderer._BaseButton.prototype.moveTo = function(_pos) { + this.sector.moveTo(_pos); +} + +Rkns.Renderer._BaseButton.prototype.show = function() { + this.sector.show(); +} + +Rkns.Renderer._BaseButton.prototype.hide = function() { + this.sector.hide(); +} + +Rkns.Renderer._BaseButton.prototype.select = function() { + this.sector.select(); +} + +Rkns.Renderer._BaseButton.prototype.unselect = function(_newTarget) { + this.sector.unselect(); + if (!_newTarget || (_newTarget !== this.source_representation && _newTarget.source_representation !== this.source_representation)) { + this.source_representation.unselect(); + } +} + +Rkns.Renderer._BaseButton.prototype.destroy = function() { + this.sector.destroy(); +} + +/* */ + +Rkns.Renderer.Node = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation); + +Rkns.Renderer.Node.prototype._init = function() { + this.renderer.node_layer.activate(); + this.type = "Node"; + this.circle = new paper.Path.Circle([0, 0], 1); + this.circle.__representation = this; + if (this.options.show_node_circles) { + this.circle.strokeWidth = this.options.node_stroke_width; + this.h_ratio = 1; + } else { + this.h_ratio = 0; + } + this.title = Rkns.$('<div class="Rk-Label">').appendTo(this.renderer.labels_$); + if (this.options.editor_mode) { + this.normal_buttons = [ + new Rkns.Renderer.NodeEditButton(this.renderer, null), + new Rkns.Renderer.NodeRemoveButton(this.renderer, null), + new Rkns.Renderer.NodeLinkButton(this.renderer, null), + new Rkns.Renderer.NodeEnlargeButton(this.renderer, null), + new Rkns.Renderer.NodeShrinkButton(this.renderer, null) + ]; + this.pending_delete_buttons = [ + new Rkns.Renderer.NodeRevertButton(this.renderer, null) + ]; + this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons) + for (var i = 0; i < this.all_buttons.length; i++) { + this.all_buttons[i].source_representation = this; + } + this.active_buttons = []; + } else { + this.active_buttons = this.all_buttons = []; + } + this.last_circle_radius = 1; + + if (this.renderer.minimap) { + this.renderer.minimap.node_layer.activate(); + this.minimap_circle = new paper.Path.Circle([0, 0], 1); + this.minimap_circle.__representation = this.renderer.minimap.miniframe.__representation; + this.renderer.minimap.node_group.addChild(this.minimap_circle); + } +} + +Rkns.Renderer.Node.prototype.redraw = function(_dontRedrawEdges) { + var _model_coords = new paper.Point(this.model.get("position")), + _baseRadius = this.options.node_size_base * Math.exp((this.model.get("size") || 0) * Rkns.Renderer._NODE_SIZE_STEP); + if (!this.is_dragging || !this.paper_coords) { + this.paper_coords = this.renderer.toPaperCoords(_model_coords); + } + this.circle_radius = _baseRadius * this.renderer.scale; + if (this.last_circle_radius !== this.circle_radius) { + this.all_buttons.forEach(function(b) { + b.setSectorSize(); + }); + var square = new paper.Size(this.circle_radius, this.circle_radius), + topleft = this.paper_coords.subtract(square), + bounds = new paper.Rectangle(topleft, square.multiply(2)); + this.circle.fitBounds(bounds); + if (this.node_image) { + this.node_image.fitBounds(bounds); + } + } else { + this.circle.position = this.paper_coords; + if (this.node_image) { + this.node_image.position = this.paper_coords; + } + } + this.last_circle_radius = this.circle_radius; + + var old_act_btn = this.active_buttons; + + if (this.model.get("delete_scheduled")) { + var opacity = .5; + this.active_buttons = this.pending_delete_buttons; + this.circle.dashArray = [2,2]; + } else { + var opacity = 1; + this.active_buttons = this.normal_buttons; + this.circle.dashArray = null; + } + + if (this.selected && this.renderer.isEditable()) { + if (old_act_btn !== this.active_buttons) { + old_act_btn.forEach(function(b) { + b.hide(); + }); + } + this.active_buttons.forEach(function(b) { + b.show(); + }); + } + + if (this.node_image) { + this.node_image.opacity = this.highlighted ? opacity * .5 : (opacity - .01); + } + + this.circle.fillColor = this.highlighted ? this.options.highlighted_node_fill_color : this.options.node_fill_color; + + this.circle.opacity = this.options.show_node_circles ? opacity : .01; + + var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_nodes) || ""; + _text = Rkns.Renderer.shortenText(_text, this.options.node_label_max_length); + this.title.text(_text); + this.title.css({ + left: this.paper_coords.x, + top: this.paper_coords.y + this.circle_radius * this.h_ratio + this.options.node_label_distance, + opacity: opacity + }) + var _color = this.model.get("color") || (this.model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color"); + this.circle.strokeColor = _color; + var _pc = this.paper_coords; + this.all_buttons.forEach(function(b) { + b.moveTo(_pc); + }); + var _img = this.model.get("image"); + if (_img && _img !== this.img) { + var _image = new Image(), + _this = this; + _image.onload = function() { + if (_this.node_image) { + _this.node_image.remove(); + } + _this.renderer.node_layer.activate(); + var _ratio = Math.min(2 / _image.width, 2 / _image.height ); + if (!_this.options.show_node_circles) { + _this.h_ratio = Math.min(1, _image.height / _image.width); + } + var _raster = new paper.Raster(_image); + if (_this.options.clip_node_images) { + var _clip = new paper.Path.Circle([0, 0], 1); + _raster.scale(_ratio); + _this.node_image = new paper.Group(_clip, _raster); + _this.node_image.opacity = .99; + /* This is a workaround to allow clipping at group level + * If opacity was set to 1, paper.js would merge all clipping groups in one (known bug). + */ + _this.node_image.clipped = true; + _clip.__representation = _this; + } else { + _this.node_image = _raster; + } + _this.node_image.__representation = _this; + var square = new paper.Size(_this.circle_radius, _this.circle_radius), + topleft = _this.paper_coords.subtract(square), + bounds = new paper.Rectangle(topleft, square.multiply(2)); + _this.node_image.fitBounds(bounds); + _this.redraw(); + paper.view.draw(); + } + _image.src = _img; + } + this.img = _img; + if (this.node_image && !this.img) { + this.node_image.remove(); + delete this.node_image; + } + + if (this.renderer.minimap) { + this.minimap_circle.fillColor = _color; + var minipos = this.renderer.toMinimapCoords(_model_coords), + miniradius = this.renderer.minimap.scale * _baseRadius, + minisize = new paper.Size([miniradius, miniradius]); + this.minimap_circle.fitBounds(minipos.subtract(minisize), minisize.multiply(2)); + } + + if (!_dontRedrawEdges) { + Rkns._.each(this.project.get("edges").filter(function (ed) { return ((ed.to === this.model) || (ed.from === this.model));}), function(edge, index, list){ + var repr = this.renderer.getRepresentationByModel(edge); + if(repr != null && typeof repr.from_representation.paper_coords !== "undefined" && typeof repr.to_representation.paper_coords !== "undefined") { + repr.redraw(); + } + }, this); + } + +} + +Rkns.Renderer.Node.prototype.paperShift = function(_delta) { + if (this.options.editor_mode) { + if (!this.renkan.read_only) { + this.is_dragging = true; + this.paper_coords = this.paper_coords.add(_delta); + this.redraw(); + } + } else { + this.renderer.paperShift(_delta); + } +} + +Rkns.Renderer.Node.prototype.openEditor = function() { + this.renderer.removeRepresentationsOfType("editor"); + var _editor = this.renderer.addRepresentation("NodeEditor",null); + _editor.source_representation = this; + _editor.draw(); +} + +Rkns.Renderer.Node.prototype.select = function() { + this.selected = true; + this.circle.strokeWidth = this.options.selected_node_stroke_width; + if (this.renderer.isEditable()) { + this.active_buttons.forEach(function(b) { + b.show(); + }); + } + var _uri = this.model.get("uri"); + if (_uri) { + Rkns.$('.Rk-Bin-Item').each(function() { + var _el = Rkns.$(this); + if (_el.attr("data-uri") == _uri) { + _el.addClass("selected"); + } + }); + } + if (!this.options.editor_mode) { + this.openEditor(); + } + + if (this.renderer.minimap) { + this.minimap_circle.strokeWidth = this.options.minimap_highlight_weight; + this.minimap_circle.strokeColor = this.options.minimap_highlight_color; + } + this.super("select"); +} + +Rkns.Renderer.Node.prototype.unselect = function(_newTarget) { + if (!_newTarget || _newTarget.source_representation !== this) { + this.selected = false; + this.all_buttons.forEach(function(b) { + b.hide(); + }); + this.circle.strokeWidth = this.options.node_stroke_width; + Rkns.$('.Rk-Bin-Item').removeClass("selected"); + if (this.renderer.minimap) { + this.minimap_circle.strokeColor = undefined; + } + this.super("unselect"); + } +} + +Rkns.Renderer.Node.prototype.highlight = function() { + if (this.highlighted) { + return; + } + this.highlighted = true; + this.redraw(); + this.renderer.throttledPaperDraw(); +} + +Rkns.Renderer.Node.prototype.unhighlight = function() { + if (!this.highlighted) { + return; + } + this.highlighted = false; + this.redraw(); + this.renderer.throttledPaperDraw(); +} + +Rkns.Renderer.Node.prototype.saveCoords = function() { + var _coords = this.renderer.toModelCoords(this.paper_coords), + _data = { + position: { + x: _coords.x, + y: _coords.y + } + }; + if (this.renderer.isEditable()) { + this.model.set(_data); + } +} + +Rkns.Renderer.Node.prototype.mousedown = function(_event, _isTouch) { + if (_isTouch) { + this.renderer.unselectAll(); + this.select(); + } +} + +Rkns.Renderer.Node.prototype.mouseup = function(_event, _isTouch) { + if (this.renderer.is_dragging && this.renderer.isEditable()) { + this.saveCoords(); + } else { + if (!_isTouch && !this.model.get("delete_scheduled")) { + this.openEditor(); + } + this.model.trigger("clicked"); + } + this.renderer.click_target = null; + this.renderer.is_dragging = false; + this.is_dragging = false; +} + +Rkns.Renderer.Node.prototype.destroy = function(_event) { + this.super("destroy"); + this.all_buttons.forEach(function(b) { + b.destroy(); + }); + this.circle.remove(); + this.title.remove(); + if (this.renderer.minimap) { + this.minimap_circle.remove(); + } + if (this.node_image) { + this.node_image.remove(); + } +} + +/* */ + +Rkns.Renderer.Edge = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation); + +Rkns.Renderer.Edge.prototype._init = function() { + this.renderer.edge_layer.activate(); + this.type = "Edge"; + this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from")); + this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to")); + this.bundle = this.renderer.addToBundles(this); + this.line = new paper.Path(); + this.line.add([0,0],[0,0],[0,0]); + this.line.__representation = this; + this.line.strokeWidth = this.options.edge_stroke_width; + this.arrow = new paper.Path(); + this.arrow.add( + [ 0, 0 ], + [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ], + [ 0, this.options.edge_arrow_width ] + ); + this.arrow.__representation = this; + this.text = Rkns.$('<div class="Rk-Label Rk-Edge-Label">').appendTo(this.renderer.labels_$); + this.arrow_angle = 0; + if (this.options.editor_mode) { + this.normal_buttons = [ + new Rkns.Renderer.EdgeEditButton(this.renderer, null), + new Rkns.Renderer.EdgeRemoveButton(this.renderer, null), + ]; + this.pending_delete_buttons = [ + new Rkns.Renderer.EdgeRevertButton(this.renderer, null) + ]; + this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons) + for (var i = 0; i < this.all_buttons.length; i++) { + this.all_buttons[i].source_representation = this; + } + this.active_buttons = []; + } else { + this.active_buttons = this.all_buttons = []; + } + + if (this.renderer.minimap) { + this.renderer.minimap.edge_layer.activate(); + this.minimap_line = new paper.Path(); + this.minimap_line.add([0,0],[0,0]); + this.minimap_line.__representation = this.renderer.minimap.miniframe.__representation; + this.minimap_line.strokeWidth = 1; + } +} + +Rkns.Renderer.Edge.prototype.redraw = function() { + this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from")); + this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to")); + if (!this.from_representation || !this.to_representation) { + return; + } + var _p0a = this.from_representation.paper_coords, + _p1a = this.to_representation.paper_coords, + _v = _p1a.subtract(_p0a), + _r = _v.length, + _u = _v.divide(_r), + _ortho = new paper.Point([- _u.y, _u.x]), + _group_pos = this.bundle.getPosition(this), + _delta = _ortho.multiply( this.options.edge_gap_in_bundles * _group_pos ), + _p0b = _p0a.add(_delta), /* Adding a 4 px difference */ + _p1b = _p1a.add(_delta), /* to differentiate bundled links */ + _a = _v.angle, + _textdelta = _ortho.multiply(this.options.edge_label_distance), + _handle = _v.divide(3), + _color = this.model.get("color") || this.model.get("color") || (this.model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color"); + + if (this.model.get("delete_scheduled") || this.from_representation.model.get("delete_scheduled") || this.to_representation.model.get("delete_scheduled")) { + var opacity = .5; + this.line.dashArray = [2, 2]; + } else { + var opacity = 1; + this.line.dashArray = null; + } + + var old_act_btn = this.active_buttons; + + this.active_buttons = this.model.get("delete_scheduled") ? this.pending_delete_buttons : this.normal_buttons; + + if (this.selected && this.renderer.isEditable() && old_act_btn !== this.active_buttons) { + old_act_btn.forEach(function(b) { + b.hide(); + }); + this.active_buttons.forEach(function(b) { + b.show(); + }); + } + + this.paper_coords = _p0b.add(_p1b).divide(2); + this.line.strokeColor = _color; + this.line.opacity = opacity; + this.line.segments[0].point = _p0a; + this.line.segments[1].point = this.paper_coords; + this.line.segments[1].handleIn = _handle.multiply(-1); + this.line.segments[1].handleOut = _handle; + this.line.segments[2].point = _p1a; + this.arrow.rotate(_a - this.arrow_angle); + this.arrow.fillColor = _color; + this.arrow.opacity = opacity; + this.arrow.position = this.paper_coords; + this.arrow_angle = _a; + if (_a > 90) { + _a -= 180; + _textdelta = _textdelta.multiply(-1); + } + if (_a < -90) { + _a += 180; + _textdelta = _textdelta.multiply(-1); + } + var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_edges) || ""; + _text = Rkns.Renderer.shortenText(_text, this.options.node_label_max_length); + this.text.text(_text); + var _textpos = this.paper_coords.add(_textdelta); + this.text.css({ + left: _textpos.x, + top: _textpos.y, + transform: "rotate(" + _a + "deg)", + "-moz-transform": "rotate(" + _a + "deg)", + "-webkit-transform": "rotate(" + _a + "deg)", + opacity: opacity + }); + this.text_angle = _a; + + var _pc = this.paper_coords; + this.all_buttons.forEach(function(b) { + b.moveTo(_pc); + }); + + if (this.renderer.minimap) { + this.minimap_line.strokeColor = _color; + this.minimap_line.segments[0].point = this.renderer.toMinimapCoords(new paper.Point(this.from_representation.model.get("position"))); + this.minimap_line.segments[1].point = this.renderer.toMinimapCoords(new paper.Point(this.to_representation.model.get("position"))); + } +} + +Rkns.Renderer.Edge.prototype.openEditor = function() { + this.renderer.removeRepresentationsOfType("editor"); + var _editor = this.renderer.addRepresentation("EdgeEditor",null); + _editor.source_representation = this; + _editor.draw(); +} + +Rkns.Renderer.Edge.prototype.select = function() { + this.selected = true; + this.line.strokeWidth = this.options.selected_edge_stroke_width; + if (this.renderer.isEditable()) { + this.active_buttons.forEach(function(b) { + b.show(); + }); + } + if (!this.options.editor_mode) { + this.openEditor(); + } + this.super("select"); +} + +Rkns.Renderer.Edge.prototype.unselect = function(_newTarget) { + if (!_newTarget || _newTarget.source_representation !== this) { + this.selected = false; + if (this.options.editor_mode) { + this.all_buttons.forEach(function(b) { + b.hide(); + }); + } + this.line.strokeWidth = this.options.edge_stroke_width; + this.super("unselect"); + } +} + +Rkns.Renderer.Edge.prototype.mousedown = function(_event, _isTouch) { + if (_isTouch) { + this.renderer.unselectAll(); + this.select(); + } +} + +Rkns.Renderer.Edge.prototype.mouseup = function(_event, _isTouch) { + if (!this.renkan.read_only && this.renderer.is_dragging) { + this.from_representation.saveCoords(); + this.to_representation.saveCoords(); + this.from_representation.is_dragging = false; + this.to_representation.is_dragging = false; + } else { + if (!_isTouch) { + this.openEditor(); + } + this.model.trigger("clicked"); + } + this.renderer.click_target = null; + this.renderer.is_dragging = false; +} + +Rkns.Renderer.Edge.prototype.paperShift = function(_delta) { + if (this.options.editor_mode) { + if (!this.options.read_only) { + this.from_representation.paperShift(_delta); + this.to_representation.paperShift(_delta); + } + } else { + this.renderer.paperShift(_delta); + } +} + +Rkns.Renderer.Edge.prototype.destroy = function() { + this.super("destroy"); + this.line.remove(); + this.arrow.remove(); + this.text.remove(); + if (this.renderer.minimap) { + this.minimap_line.remove(); + } + this.all_buttons.forEach(function(b) { + b.destroy(); + }); + var _this = this; + this.bundle.edges = Rkns._(this.bundle.edges).reject(function(_edge) { + return _edge === _this; + }); +} + +/* */ + +Rkns.Renderer.TempEdge = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation); + +Rkns.Renderer.TempEdge.prototype._init = function() { + this.renderer.edge_layer.activate(); + this.type = "Temp-edge"; + + var _color = (this.project.get("users").get(this.renkan.current_user) || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color"); + this.line = new paper.Path(); + this.line.strokeColor = _color; + this.line.dashArray = [4, 2]; + this.line.strokeWidth = this.options.selected_edge_stroke_width; + this.line.add([0,0],[0,0]); + this.line.__representation = this; + this.arrow = new paper.Path(); + this.arrow.fillColor = _color; + this.arrow.add( + [ 0, 0 ], + [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ], + [ 0, this.options.edge_arrow_width ] + ); + this.arrow.__representation = this; + this.arrow_angle = 0; +} + +Rkns.Renderer.TempEdge.prototype.redraw = function() { + var _p0 = this.from_representation.paper_coords, + _p1 = this.end_pos, + _a = _p1.subtract(_p0).angle, + _c = _p0.add(_p1).divide(2); + this.line.segments[0].point = _p0; + this.line.segments[1].point = _p1; + this.arrow.rotate(_a - this.arrow_angle); + this.arrow.position = _c; + this.arrow_angle = _a; +} + +Rkns.Renderer.TempEdge.prototype.paperShift = function(_delta) { + if (!this.renderer.isEditable()) { + this.renderer.removeRepresentation(_this); + paper.view.draw(); + return; + } + this.end_pos = this.end_pos.add(_delta); + var _hitResult = paper.project.hitTest(this.end_pos); + this.renderer.findTarget(_hitResult); + this.redraw(); +} + +Rkns.Renderer.TempEdge.prototype.mouseup = function(_event, _isTouch) { + var _hitResult = paper.project.hitTest(_event.point), + _model = this.from_representation.model, + _endDrag = true; + if (_hitResult && typeof _hitResult.item.__representation !== "undefined") { + var _target = _hitResult.item.__representation; + if (_target.type.substr(0,4) === "Node") { + var _destmodel = _target.model || _target.source_representation.model; + if (_model !== _destmodel) { + var _data = { + id: Rkns.Utils.getUID('edge'), + created_by: this.renkan.current_user, + from: _model, + to: _destmodel + }; + if (this.renderer.isEditable()) { + this.project.addEdge(_data); + } + } + } + + if (_model === _target.model || (_target.source_representation && _target.source_representation.model === _model)) { + _endDrag = false; + this.renderer.is_dragging = true; + } + } + if (_endDrag) { + this.renderer.click_target = null; + this.renderer.is_dragging = false; + this.renderer.removeRepresentation(this); + paper.view.draw(); + } +} + +Rkns.Renderer.TempEdge.prototype.destroy = function() { + this.arrow.remove(); + this.line.remove(); +} + +/* */ + +Rkns.Renderer._BaseEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation); + +Rkns.Renderer._BaseEditor.prototype._init = function() { + this.renderer.buttons_layer.activate(); + this.type = "editor"; + this.editor_block = new paper.Path(); + var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]}); + this.editor_block.add.apply(this.editor_block, _pts); + this.editor_block.strokeWidth = this.options.tooltip_border_width; + this.editor_block.strokeColor = this.options.tooltip_border_color; + this.editor_block.opacity = .8; + this.editor_$ = Rkns.$('<div>') + .appendTo(this.renderer.editor_$) + .css({ + position: "absolute", + opacity: .8 + }) + .hide(); +} + +Rkns.Renderer._BaseEditor.prototype.destroy = function() { + this.editor_block.remove(); + this.editor_$.remove(); +} + +/* */ + +Rkns.Renderer.NodeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseEditor); + +Rkns.Renderer.NodeEditor.prototype.template = Rkns._.template( + '<h2><span class="Rk-CloseX">×</span><%-renkan.translate("Edit Node")%></span></h2>' + + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-node.title%>"/></p>' + + '<p><label><%-renkan.translate("URI:")%></label><input class="Rk-Edit-URI" type="text" value="<%-node.uri%>"/><a class="Rk-Edit-Goto" href="<%-node.uri%>" target="_blank"></a></p>' + + '<p><label><%-renkan.translate("Description:")%></label><textarea class="Rk-Edit-Description"><%-node.description%></textarea></p>' + + '<p><span class="Rk-Editor-Label"><%-renkan.translate("Size:")%></span><a href="#" class="Rk-Edit-Size-Down">-</a><span class="Rk-Edit-Size-Value"><%-node.size%></span><a href="#" class="Rk-Edit-Size-Up">+</a></p>' + + '<div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-renkan.translate("Node color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%-node.color%>;"><span class="Rk-Edit-ColorTip"></span></span><ul class="Rk-Edit-ColorPicker">' + + '<% _(Rkns.pickerColors).each(function(c) { %><li data-color="<%=c%>" style="background: <%=c%>"></li><% }); %></ul><span class="Rk-Edit-ColorPicker-Text"><%- renkan.translate("Choose color") %></span></div></div>' + + '<img class="Rk-Edit-ImgPreview" src="<%-node.image || node.image_placeholder%>" />' + + '<p><label><%-renkan.translate("Image URL:")%></label><input class="Rk-Edit-Image" type="text" value="<%-node.image%>"/></p>' + + '<p><label><%-renkan.translate("Choose Image File:")%></label><input class="Rk-Edit-Image-File" type="file" accept="image/*"/></p>' + + '<% if (node.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span> <span class="Rk-UserColor" style="background:<%-node.created_by_color%>;"></span><%- Rkns.Renderer.shortenText(node.created_by_title, 25) %></p><% } %>' +); + +Rkns.Renderer.NodeEditor.prototype.readOnlyTemplate = Rkns._.template( + '<h2><span class="Rk-CloseX">×</span><span class="Rk-UserColor" style="background:<%-node.color%>;"></span>' + + '<span class="Rk-Display-Title"><% if (node.uri) { %><a href="<%-node.uri%>" target="_blank"><% } %><%-node.title%><% if (node.uri) { %></a><% } %></span></h2>' + + '<% if (node.uri) { %><p class="Rk-Display-URI"><a href="<%-node.uri%>" target="_blank"><%-node.short_uri%></a></p><% } %>' + + '<p><%-node.description%></p>' + + '<% if (node.image) { %><img class="Rk-Display-ImgPreview" src="<%-node.image%>" /><% } %>' + + '<% if (node.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-node.created_by_color%>;"></span><%- Rkns.Renderer.shortenText(node.created_by_title, 25) %></p><% } %>' +); + +Rkns.Renderer.NodeEditor.prototype.draw = function() { + var _model = this.source_representation.model, + _created_by = _model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan), + _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate ), + _image_placeholder = this.options.static_url + "img/image-placeholder.png", + _size = (_model.get("size") || 0); + this.editor_$ + .html(_template({ + node: { + has_creator: !!_model.get("created_by"), + title: _model.get("title"), + uri: _model.get("uri"), + short_uri: Rkns.Renderer.shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40), + description: _model.get("description"), + image: _model.get("image") || "", + image_placeholder: _image_placeholder, + color: _model.get("color") || _created_by.get("color"), + created_by_color: _created_by.get("color"), + created_by_title: _created_by.get("title"), + size: (_size > 0 ? "+" : "") + _size + }, + renkan: this.renkan + })); + this.redraw(); + var _this = this, + closeEditor = function() { + _this.renderer.removeRepresentation(_this); + paper.view.draw(); + } + + this.editor_$.find(".Rk-CloseX").click(closeEditor); + + if (this.renderer.isEditable()) { + + var onFieldChange = Rkns._(function() { + Rkns._(function() { + if (_this.renderer.isEditable()) { + var _uri = _this.editor_$.find(".Rk-Edit-URI").val(), + _image = _this.editor_$.find(".Rk-Edit-Image").val(); + _this.editor_$.find(".Rk-Edit-ImgPreview").attr("src", _image || _image_placeholder); + _this.editor_$.find(".Rk-Edit-Goto").attr("href",_uri); + var _data = { + title: _this.editor_$.find(".Rk-Edit-Title").val(), + description: _this.editor_$.find(".Rk-Edit-Description").val(), + uri: _uri, + image: _image + } + _model.set(_data); + _this.redraw(); + } else { + closeEditor(); + } + + }).defer(); + }).throttle(500); + + this.editor_$.on("keyup", function(_e) { + if (_e.keyCode === 27) { + closeEditor(); + } + }); + + this.editor_$.find("input, textarea").on("change keyup paste", onFieldChange); + + this.editor_$.find(".Rk-Edit-Image-File").change(function() { + if (this.files.length) { + var f = this.files[0], + fr = new FileReader(); + if (f.type.substr(0,5) !== "image") { + alert(_this.renkan.translate("This file is not an image")); + return; + } + if (f.size > (Rkns.Renderer._IMAGE_MAX_KB * 1024)) { + alert(_this.renkan.translate("Image size must be under ")+Rkns.Renderer._IMAGE_MAX_KB+_this.renkan.translate("KB")); + return; + } + fr.onload = function(e) { + _this.editor_$.find(".Rk-Edit-Image").val(e.target.result); + onFieldChange(); + } + fr.readAsDataURL(f); + } + }); + this.editor_$.find(".Rk-Edit-Title")[0].focus(); + + var _picker = _this.editor_$.find(".Rk-Edit-ColorPicker"); + + this.editor_$.find(".Rk-Edit-ColorPicker-Wrapper").hover( + function(_e) { + _e.preventDefault(); + _picker.show(); + }, + function(_e) { + _e.preventDefault(); + _picker.hide(); + } + ); + + _picker.find("li").hover( + function(_e) { + _e.preventDefault(); + _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color")); + }, + function(_e) { + _e.preventDefault(); + _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(_this.renkan)).get("color")) + } + ).click(function(_e) { + _e.preventDefault(); + if (_this.renderer.isEditable()) { + _model.set("color", $(this).attr("data-color")); + _picker.hide(); + paper.view.draw(); + } else { + closeEditor(); + } + }); + + function shiftSize(n) { + if (_this.renderer.isEditable()) { + var _newsize = n+(_model.get("size") || 0); + _this.editor_$.find(".Rk-Edit-Size-Value").text((_newsize > 0 ? "+" : "") + _newsize); + _model.set("size", _newsize); + paper.view.draw(); + } else { + closeEditor(); + } + } + + this.editor_$.find(".Rk-Edit-Size-Down").click(function() { + shiftSize(-1); + return false; + }); + this.editor_$.find(".Rk-Edit-Size-Up").click(function() { + shiftSize(1); + return false; + }); + } + this.editor_$.find("img").load(function() { + _this.redraw(); + }); +} + +Rkns.Renderer.NodeEditor.prototype.redraw = function() { + var _coords = this.source_representation.paper_coords; + Rkns.Renderer.drawEditBox(this.options, _coords, this.editor_block, this.source_representation.circle_radius * .75, this.editor_$); + this.editor_$.show(); + paper.view.draw(); +} + +/* */ + +Rkns.Renderer.EdgeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseEditor); + +Rkns.Renderer.EdgeEditor.prototype.template = Rkns._.template( + '<h2><span class="Rk-CloseX">×</span><%-renkan.translate("Edit Edge")%></span></h2>' + + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-edge.title%>"/></p>' + + '<p><label><%-renkan.translate("URI:")%></label><input class="Rk-Edit-URI" type="text" value="<%-edge.uri%>"/><a class="Rk-Edit-Goto" href="<%-edge.uri%>" target="_blank"></a></p>' + + '<% if (properties.length) { %><p><label><%-renkan.translate("Choose from vocabulary:")%></label><select class="Rk-Edit-Vocabulary">' + + '<% _(properties).each(function(ontology) { %><option class="Rk-Edit-Vocabulary-Class" value=""><%- renkan.translate(ontology.label) %></option>' + + '<% _(ontology.properties).each(function(property) { var uri = ontology["base-uri"] + property.uri; %><option class="Rk-Edit-Vocabulary-Property" value="<%- uri %>' + + '"<% if (uri === edge.uri) { %> selected<% } %>><%- renkan.translate(property.label) %></option>' + + '<% }) %><% }) %></select></p><% } %>' + + '<div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-renkan.translate("Edge color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%-edge.color%>;"><span class="Rk-Edit-ColorTip"></span></span><ul class="Rk-Edit-ColorPicker">' + + '<% _(Rkns.pickerColors).each(function(c) { %><li data-color="<%=c%>" style="background: <%=c%>"></li><% }); %></ul><span class="Rk-Edit-ColorPicker-Text"><%- renkan.translate("Choose color") %></span></div></div>' + + '<p><span class="Rk-Edit-Direction"><%- renkan.translate("Change edge direction") %></span></p>' + + '<p><span class="Rk-Editor-Label"><%-renkan.translate("From:")%></span><span class="Rk-UserColor" style="background:<%-edge.from_color%>;"></span><%- Rkns.Renderer.shortenText(edge.from_title, 25) %></p>' + + '<p><span class="Rk-Editor-Label"><%-renkan.translate("To:")%></span><span class="Rk-UserColor" style="background:<%-edge.to_color%>;"></span><%- Rkns.Renderer.shortenText(edge.to_title, 25) %></p>' + + '<% if (edge.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-edge.created_by_color%>;"></span><%- Rkns.Renderer.shortenText(edge.created_by_title, 25) %></p><% } %>' +); + +Rkns.Renderer.EdgeEditor.prototype.readOnlyTemplate = Rkns._.template( + '<h2><span class="Rk-CloseX">×</span><span class="Rk-UserColor" style="background:<%-edge.color%>;"></span>' + + '<span class="Rk-Display-Title"><% if (edge.uri) { %><a href="<%-edge.uri%>" target="_blank"><% } %><%-edge.title%><% if (edge.uri) { %></a><% } %></span></h2>' + + '<% if (edge.uri) { %><p class="Rk-Display-URI"><a href="<%-edge.uri%>" target="_blank"><%-edge.short_uri%></a></p><% } %>' + + '<p><%-edge.description%></p>' + + '<p><span class="Rk-Editor-Label"><%-renkan.translate("From:")%></span><span class="Rk-UserColor" style="background:<%-edge.from_color%>;"></span><%- Rkns.Renderer.shortenText(edge.from_title, 25) %></p>' + + '<p><span class="Rk-Editor-Label"><%-renkan.translate("To:")%></span><span class="Rk-UserColor" style="background:<%-edge.to_color%>;"></span><%- Rkns.Renderer.shortenText(edge.to_title, 25) %></p>' + + '<% if (edge.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-edge.created_by_color%>;"></span><%- Rkns.Renderer.shortenText(edge.created_by_title, 25) %></p><% } %>' +); + +Rkns.Renderer.EdgeEditor.prototype.draw = function() { + var _model = this.source_representation.model, + _from_model = _model.get("from"), + _to_model = _model.get("to"), + _created_by = _model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan), + _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate); + this.editor_$ + .html(_template({ + edge: { + has_creator: !!_model.get("created_by"), + title: _model.get("title"), + uri: _model.get("uri"), + short_uri: Rkns.Renderer.shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40), + description: _model.get("description"), + color: _model.get("color") || _created_by.get("color"), + from_title: _from_model.get("title"), + to_title: _to_model.get("title"), + from_color: _from_model.get("color") || (_from_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color"), + to_color: _to_model.get("color") || (_to_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color"), + created_by_color: _created_by.get("color"), + created_by_title: _created_by.get("title") + }, + renkan: this.renkan, + properties: this.options.properties + })); + this.redraw(); + var _this = this, + closeEditor = function() { + _this.renderer.removeRepresentation(_this); + paper.view.draw(); + } + this.editor_$.find(".Rk-CloseX").click(closeEditor); + + if (this.renderer.isEditable()) { + + var onFieldChange = Rkns._(function() { + Rkns._(function() { + if (_this.renderer.isEditable()) { + _this.editor_$.find(".Rk-Edit-Goto").attr("href",_this.editor_$.find(".Rk-Edit-URI").val()); + var _data = { + title: _this.editor_$.find(".Rk-Edit-Title").val(), + uri: _this.editor_$.find(".Rk-Edit-URI").val() + } + _model.set(_data); + paper.view.draw(); + } else { + closeEditor(); + } + }).defer(); + }).throttle(500); + + this.editor_$.on("keyup", function(_e) { + if (_e.keyCode === 27) { + closeEditor(); + } + }); + + this.editor_$.find("input").on("keyup change paste", onFieldChange); + + this.editor_$.find(".Rk-Edit-Vocabulary").change(function() { + var e = $(this), + v = e.val(); + if (v) { + _this.editor_$.find(".Rk-Edit-Title").val(e.find(":selected").text()); + _this.editor_$.find(".Rk-Edit-URI").val(v); + onFieldChange(); + } + }); + this.editor_$.find(".Rk-Edit-Direction").click(function() { + if (_this.renderer.isEditable()) { + _model.set({ + from: _model.get("to"), + to: _model.get("from") + }); + _this.draw(); + } else { + closeEditor(); + } + }); + + var _picker = _this.editor_$.find(".Rk-Edit-ColorPicker"); + + this.editor_$.find(".Rk-Edit-ColorPicker-Wrapper").hover( + function(_e) { + _e.preventDefault(); + _picker.show(); + }, + function(_e) { + _e.preventDefault(); + _picker.hide(); + } + ); + + _picker.find("li").hover( + function(_e) { + _e.preventDefault(); + _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color")); + }, + function(_e) { + _e.preventDefault(); + _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(_this.renkan)).get("color")) + } + ).click(function(_e) { + _e.preventDefault(); + if (_this.renderer.isEditable()) { + _model.set("color", $(this).attr("data-color")); + _picker.hide(); + paper.view.draw(); + } else { + closeEditor(); + } + }); + } +} + +Rkns.Renderer.EdgeEditor.prototype.redraw = function() { + var _coords = this.source_representation.paper_coords; + Rkns.Renderer.drawEditBox(this.options, _coords, this.editor_block, 5, this.editor_$); + this.editor_$.show(); + paper.view.draw(); +} + +/* */ + +Rkns.Renderer._NodeButton = Rkns.Utils.inherit(Rkns.Renderer._BaseButton); + +Rkns.Renderer._NodeButton.prototype.setSectorSize = function() { + var sectorInner = this.source_representation.circle_radius; + if (sectorInner !== this.lastSectorInner) { + if (this.sector) { + this.sector.destroy(); + } + this.sector = this.renderer.drawSector( + this, 1 + sectorInner, + Rkns.Renderer._NODE_BUTTON_WIDTH + sectorInner, + this.startAngle, + this.endAngle, + 1, + this.imageName, + this.renkan.translate(this.text) + ); + this.lastSectorInner = sectorInner; + } +} + +/* */ + +Rkns.Renderer.NodeEditButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton); + +Rkns.Renderer.NodeEditButton.prototype._init = function() { + this.type = "Node-edit-button"; + this.lastSectorInner = 0; + this.startAngle = -135; + this.endAngle = -45; + this.imageName = "edit"; + this.text = "Edit"; +} + +Rkns.Renderer.NodeEditButton.prototype.mouseup = function() { + if (!this.renderer.is_dragging) { + this.source_representation.openEditor(); + } +} + +/* */ + +Rkns.Renderer.NodeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton); + +Rkns.Renderer.NodeRemoveButton.prototype._init = function() { + this.type = "Node-remove-button"; + this.lastSectorInner = 0; + this.startAngle = 0; + this.endAngle = 90; + this.imageName = "remove"; + this.text = "Remove"; +} + +Rkns.Renderer.NodeRemoveButton.prototype.mouseup = function() { + this.renderer.click_target = null; + this.renderer.is_dragging = false; + this.renderer.removeRepresentationsOfType("editor"); + if (this.renderer.isEditable()) { + var delid = Rkns.Utils.getUID("delete"); + this.renderer.delete_list.push({ + id: delid, + time: new Date().valueOf() + this.options.element_delete_delay + }); + this.source_representation.model.set("delete_scheduled", delid); + } +} + +/* */ + +Rkns.Renderer.NodeRevertButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton); + +Rkns.Renderer.NodeRevertButton.prototype._init = function() { + this.type = "Node-revert-button"; + this.lastSectorInner = 0; + this.startAngle = -135; + this.endAngle = 135; + this.imageName = "revert"; + this.text = "Cancel deletion"; +} + +Rkns.Renderer.NodeRevertButton.prototype.mouseup = function() { + this.renderer.click_target = null; + this.renderer.is_dragging = false; + if (this.renderer.isEditable()) { + this.source_representation.model.unset("delete_scheduled"); + } +} + +/* */ + +Rkns.Renderer.NodeLinkButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton); + +Rkns.Renderer.NodeLinkButton.prototype._init = function() { + this.type = "Node-link-button"; + this.lastSectorInner = 0; + this.startAngle = 90; + this.endAngle = 180; + this.imageName = "link"; + this.text = "Link to another node"; +} + +Rkns.Renderer.NodeLinkButton.prototype.mousedown = function(_event, _isTouch) { + if (this.renderer.isEditable()) { + var _off = this.renderer.canvas_$.offset(), + _point = new paper.Point([ + _event.pageX - _off.left, + _event.pageY - _off.top + ]); + this.renderer.click_target = null; + this.renderer.removeRepresentationsOfType("editor"); + this.renderer.addTempEdge(this.source_representation, _point); + } +} + +/* */ + +Rkns.Renderer.NodeEnlargeButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton); + +Rkns.Renderer.NodeEnlargeButton.prototype._init = function() { + this.type = "Node-enlarge-button"; + this.lastSectorInner = 0; + this.startAngle = -45; + this.endAngle = 0; + this.imageName = "enlarge"; + this.text = "Enlarge"; +} + +Rkns.Renderer.NodeEnlargeButton.prototype.mouseup = function() { + var _newsize = 1 + (this.source_representation.model.get("size") || 0); + this.source_representation.model.set("size", _newsize); + this.source_representation.select(); + this.select(); + paper.view.draw(); +} + +/* */ + +Rkns.Renderer.NodeShrinkButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton); + +Rkns.Renderer.NodeShrinkButton.prototype._init = function() { + this.type = "Node-shrink-button"; + this.lastSectorInner = 0; + this.startAngle = -180; + this.endAngle = -135; + this.imageName = "shrink"; + this.text = "Shrink"; +} + +Rkns.Renderer.NodeShrinkButton.prototype.mouseup = function() { + var _newsize = -1 + (this.source_representation.model.get("size") || 0); + this.source_representation.model.set("size", _newsize); + this.source_representation.select(); + this.select(); + paper.view.draw(); +} + +/* */ + +Rkns.Renderer.EdgeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseButton); + +Rkns.Renderer.EdgeEditButton.prototype._init = function() { + this.type = "Edge-edit-button"; + this.sector = this.renderer.drawSector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, -270, -90, 1, "edit", this.renkan.translate("Edit")); +} + +Rkns.Renderer.EdgeEditButton.prototype.mouseup = function() { + if (!this.renderer.is_dragging) { + this.source_representation.openEditor(); + } +} + +/* */ + +Rkns.Renderer.EdgeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseButton); + +Rkns.Renderer.EdgeRemoveButton.prototype._init = function() { + this.type = "Edge-remove-button"; + this.sector = this.renderer.drawSector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, -90, 90, 1, "remove", this.renkan.translate("Remove")); +} + +Rkns.Renderer.EdgeRemoveButton.prototype.mouseup = function() { + this.renderer.click_target = null; + this.renderer.is_dragging = false; + this.renderer.removeRepresentationsOfType("editor"); + if (this.renderer.isEditable()) { + var delid = Rkns.Utils.getUID("delete"); + this.renderer.delete_list.push({ + id: delid, + time: new Date().valueOf() + this.options.element_delete_delay + }); + this.source_representation.model.set("delete_scheduled", delid); + } +} + +/* */ + +Rkns.Renderer.EdgeRevertButton = Rkns.Utils.inherit(Rkns.Renderer._BaseButton); + +Rkns.Renderer.EdgeRevertButton.prototype._init = function() { + this.type = "Edge-revert-button"; + this.sector = this.renderer.drawSector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, -135, 135, 1, "revert", this.renkan.translate("Cancel deletion")); +} + +Rkns.Renderer.EdgeRevertButton.prototype.mouseup = function() { + this.renderer.click_target = null; + this.renderer.is_dragging = false; + if (this.renderer.isEditable()) { + this.source_representation.model.unset("delete_scheduled"); + } +} + +/* */ + +Rkns.Renderer.MiniFrame = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation); + +Rkns.Renderer.MiniFrame.prototype.paperShift = function(_delta) { + this.renderer.offset = this.renderer.offset.subtract(_delta.divide(this.renderer.minimap.scale).multiply(this.renderer.scale)); + this.renderer.redraw(); +} + +Rkns.Renderer.MiniFrame.prototype.mouseup = function(_delta) { + this.renderer.click_target = null; + this.renderer.is_dragging = false; +} + +/* */ + +Rkns.Renderer.Scene = function(_renkan) { + this.renkan = _renkan; + this.$ = Rkns.$(".Rk-Render"); + this.representations = []; + this.$.html(this.template(_renkan)); + this.onStatusChange(); + this.canvas_$ = this.$.find(".Rk-Canvas"); + this.labels_$ = this.$.find(".Rk-Labels"); + this.editor_$ = this.$.find(".Rk-Editor"); + this.notif_$ = this.$.find(".Rk-Notifications"); + paper.setup(this.canvas_$[0]); + this.scale = 1; + this.offset = paper.view.center; + this.totalScroll = 0; + this.mouse_down = false; + this.click_target = null; + this.selected_target = null; + this.edge_layer = new paper.Layer(); + this.node_layer = new paper.Layer(); + this.buttons_layer = new paper.Layer(); + this.delete_list = []; + + if (_renkan.options.show_minimap) { + this.minimap = { + background_layer: new paper.Layer(), + edge_layer: new paper.Layer(), + node_layer: new paper.Layer(), + node_group: new paper.Group(), + size: new paper.Size( _renkan.options.minimap_width, _renkan.options.minimap_height ) + } + + this.minimap.background_layer.activate(); + this.minimap.topleft = paper.view.bounds.bottomRight.subtract(this.minimap.size); + this.minimap.rectangle = new paper.Path.Rectangle(this.minimap.topleft.subtract([2,2]), this.minimap.size.add([4,4])); + this.minimap.rectangle.fillColor = _renkan.options.minimap_background_color; + this.minimap.rectangle.strokeColor = _renkan.options.minimap_border_color; + this.minimap.rectangle.strokeWidth = 4; + this.minimap.offset = new paper.Point(this.minimap.size.divide(2)); + this.minimap.scale = .1; + + this.minimap.node_layer.activate(); + this.minimap.cliprectangle = new paper.Path.Rectangle(this.minimap.topleft, this.minimap.size); + this.minimap.node_group.addChild(this.minimap.cliprectangle); + this.minimap.node_group.clipped = true; + this.minimap.miniframe = new paper.Path.Rectangle(this.minimap.topleft, this.minimap.size); + this.minimap.node_group.addChild(this.minimap.miniframe); + this.minimap.miniframe.fillColor = '#c0c0ff'; + this.minimap.miniframe.opacity = .3; + this.minimap.miniframe.strokeColor = '#000080'; + this.minimap.miniframe.strokeWidth = 3; + this.minimap.miniframe.__representation = new Rkns.Renderer.MiniFrame(this, null); + } + + this.throttledPaperDraw = Rkns._(function() { + paper.view.draw(); + }).throttle(100); + + this.bundles = []; + this.click_mode = false; + + var _this = this, + _allowScroll = true, + _originalScale, + _zooming = false, + _lastTapDate, + _lastTapX, + _lastTapY; + + this.imageCache = {}; + + ['edit', 'remove', 'link', 'enlarge', 'shrink', 'revert' ].forEach(function(imgname) { + var img = new Image(); + img.src = _renkan.options.static_url + 'img/' + imgname + '.png'; + _this.imageCache[imgname] = img; + }); + + var throttledMouseMove = _.throttle(function(_event, _isTouch) { + _this.onMouseMove(_event, _isTouch); + }, Rkns.Renderer._MOUSEMOVE_RATE); + + this.canvas_$.on({ + mousedown: function(_event) { + _event.preventDefault(); + _this.onMouseDown(_event, false); + }, + mousemove: function(_event) { + _event.preventDefault(); + throttledMouseMove(_event, false); + }, + mouseup: function(_event) { + _event.preventDefault(); + _this.onMouseUp(_event, false); + }, + mousewheel: function(_event, _delta) { + _event.preventDefault(); + if (_allowScroll) { + _this.onScroll(_event, _delta); + } + }, + touchstart: function(_event) { + _event.preventDefault(); + var _touches = _event.originalEvent.touches[0]; + if ( + _renkan.options.allow_double_click + && new Date() - _lastTap < Rkns.Renderer._DOUBLETAP_DELAY + && ( Math.pow(_lastTapX - _touches.pageX, 2) + Math.pow(_lastTapY - _touches.pageY, 2) < Rkns.Renderer._DOUBLETAP_DISTANCE ) + ) { + _lastTap = 0; + _this.onDoubleClick(_touches); + } else { + _lastTap = new Date(); + _lastTapX = _touches.pageX; + _lastTapY = _touches.pageY; + _originalScale = _this.scale; + _zooming = false; + _this.onMouseDown(_touches, true); + } + }, + touchmove: function(_event) { + _event.preventDefault(); + _lastTap = 0; + if (_event.originalEvent.touches.length == 1) { + _this.onMouseMove(_event.originalEvent.touches[0], true); + } else { + if (!_zooming) { + _this.onMouseUp(_event.originalEvent.touches[0], true); + _this.click_target = null; + _this.is_dragging = false; + _zooming = true; + } + if (_event.originalEvent.scale === "undefined") { + return; + } + var _newScale = _event.originalEvent.scale * _originalScale, + _scaleRatio = _newScale / _this.scale, + _newOffset = new paper.Point([ + _this.canvas_$.width(), + _this.canvas_$.height() + ]).multiply( .5 * ( 1 - _scaleRatio ) ).add(_this.offset.multiply( _scaleRatio )); + _this.setScale(_newScale, _this.offset); + } + }, + touchend: function(_event) { + _event.preventDefault(); + _this.onMouseUp(_event.originalEvent.changedTouches[0], true); + }, + dblclick: function(_event) { + _event.preventDefault(); + if (_renkan.options.allow_double_click) { + _this.onDoubleClick(_event); + } + }, + mouseleave: function(_event) { + _event.preventDefault(); + _this.onMouseUp(_event, false); + _this.click_target = null; + _this.is_dragging = false; + }, + dragover: function(_event) { + _event.preventDefault(); + }, + dragenter: function(_event) { + _event.preventDefault(); + _allowScroll = false; + }, + dragleave: function(_event) { + _event.preventDefault(); + _allowScroll = true; + }, + drop: function(_event) { + _event.preventDefault(); + _allowScroll = true; + var res = {}; + Rkns._(_event.originalEvent.dataTransfer.types).each(function(t) { + try { + res[t] = _event.originalEvent.dataTransfer.getData(t); + } catch(e) {} + }); + var text = _event.originalEvent.dataTransfer.getData("Text"); + if (typeof text === "string") { + switch(text[0]) { + case "{": + case "[": + try { + var data = JSON.parse(text); + _(res).extend(data); + } + catch(e) { + if (!res["text/plain"]) { + res["text/plain"] = text; + } + } + break; + case "<": + if (!res["text/html"]) { + res["text/html"] = text; + } + break; + default: + if (!res["text/plain"]) { + res["text/plain"] = text; + } + } + } + var url = _event.originalEvent.dataTransfer.getData("URL"); + if (url && !res["text/uri-list"]) { + res["text/uri-list"] = url; + } + _this.dropData(res, _event.originalEvent); + } + }); + this.editor_$.find(".Rk-ZoomOut").click(function() { + var _newScale = _this.scale * Math.SQRT1_2, + _offset = new paper.Point([ + _this.canvas_$.width(), + _this.canvas_$.height() + ]).multiply( .5 * ( 1 - Math.SQRT1_2 ) ).add(_this.offset.multiply( Math.SQRT1_2 )); + _this.setScale( _newScale, _offset ); + }); + this.editor_$.find(".Rk-ZoomIn").click(function() { + var _newScale = _this.scale * Math.SQRT2, + _offset = new paper.Point([ + _this.canvas_$.width(), + _this.canvas_$.height() + ]).multiply( .5 * ( 1 - Math.SQRT2 ) ).add(_this.offset.multiply( Math.SQRT2 )); + _this.setScale( _newScale, _offset ); + }); + this.$.find(".Rk-CurrentUser").mouseenter( + function() { _this.$.find(".Rk-UserList").slideDown() } + ); + this.$.find(".Rk-Users").mouseleave( + function() { _this.$.find(".Rk-UserList").slideUp(); } + ); + this.$.find(".Rk-FullScreen-Button").click(function() { + var _isFull = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen, + _el = _this.renkan.$[0], + _requestMethods = ["requestFullScreen","mozRequestFullScreen","webkitRequestFullScreen"], + _cancelMethods = ["cancelFullScreen","mozCancelFullScreen","webkitCancelFullScreen"]; + if (_isFull) { + for (var i = 0; i < _cancelMethods.length; i++) { + if (typeof document[_cancelMethods[i]] === "function") { + document[_cancelMethods[i]](); + break; + } + } + } else { + for (var i = 0; i < _requestMethods.length; i++) { + if (typeof _el[_requestMethods[i]] === "function") { + _el[_requestMethods[i]](); + break; + } + } + } + }); + this.$.find(".Rk-AddNode-Button").click(function() { + if (_this.click_mode === Rkns.Renderer._CLICKMODE_ADDNODE) { + _this.click_mode = false; + _this.notif_$.hide(); + } else { + _this.click_mode = Rkns.Renderer._CLICKMODE_ADDNODE; + _this.notif_$.text(_renkan.translate("Click on the background canvas to add a node")).fadeIn(); + } + }); + this.$.find(".Rk-AddEdge-Button").click(function() { + if (_this.click_mode === Rkns.Renderer._CLICKMODE_STARTEDGE || _this.click_mode === Rkns.Renderer._CLICKMODE_ENDEDGE) { + _this.click_mode = false; + _this.notif_$.hide(); + } else { + _this.click_mode = Rkns.Renderer._CLICKMODE_STARTEDGE; + _this.notif_$.text(_renkan.translate("Click on a first node to start the edge")).fadeIn(); + } + }); + this.$.find(".Rk-Bookmarklet-Button") + .attr("href","javascript:" + Rkns.Renderer._BOOKMARKLET_CODE(_renkan)) + .click(function(){ + _this.notif_$ + .text(_renkan.translate("Drag this button to your bookmark bar. When on a third-party website, click it to enable drag-and-drop from the website to Renkan.")) + .fadeIn() + .delay(5000) + .fadeOut(); + return false; + }); + this.$.find(".Rk-TopBar-Button").mouseover(function() { + Rkns.$(this).find(".Rk-TopBar-Tooltip").show(); + }).mouseout(function() { + Rkns.$(this).find(".Rk-TopBar-Tooltip").hide(); + }); + this.$.find(".Rk-Fold-Bins").click(function() { + var bins = _renkan.$.find(".Rk-Bins"); + if (bins.offset().left < 0) { + bins.animate({left: 0},250); + _this.$.animate({left: 300},250,function() { + var w = _this.$.width(); + paper.view.viewSize = new paper.Size([w, _this.canvas_$.height()]); + }); + $(this).html("«"); + } else { + bins.animate({left: -300},250); + _this.$.animate({left: 0},250,function() { + var w = _this.$.width(); + paper.view.viewSize = new paper.Size([w, _this.canvas_$.height()]); + }); + $(this).html("»"); + } + }); + + paper.view.onResize = function(_event) { + _this.offset = _this.offset.add(_event.delta.divide(2)); + if (_this.minimap) { + _this.minimap.topleft = paper.view.bounds.bottomRight.subtract(_this.minimap.size) + _this.minimap.rectangle.fitBounds(_this.minimap.topleft.subtract([2,2]), _this.minimap.size.add([4,4])); + _this.minimap.cliprectangle.fitBounds(_this.minimap.topleft, _this.minimap.size); + } + _this.redraw(); + } + + var _thRedraw = Rkns._.throttle(function() { + _this.redraw(); + },50); + + this.addRepresentations("Node", this.renkan.project.get("nodes")); + this.addRepresentations("Edge", this.renkan.project.get("edges")); + this.renkan.project.on("change:title", function() { + _this.$.find(".Rk-PadTitle").val(_renkan.project.get("title")); + }); + + this.$.find(".Rk-PadTitle").on("keyup input paste", function() { + _renkan.project.set({"title": $(this).val()}); + }) + + this.renkan.project.get("users").each(function(_user) { + _this.addUser(_user); + }); + + this.renkan.project.on("add:users", function(_user) { + _this.addUser(_user); + }); + this.renkan.project.on("add:nodes", function(_node) { + _this.addRepresentation("Node", _node); + _thRedraw(); + }); + this.renkan.project.on("add:edges", function(_edge) { + _this.addRepresentation("Edge", _edge); + _thRedraw(); + }); + this.renkan.project.on("change:title", function(_model, _title) { + var el = _this.$.find(".Rk-PadTitle"); + if (el.is("input")) { + if (el.val() !== _title) { + el.val(_title); + } + } else { + el.text(_title); + } + }); + + if (_renkan.options.size_bug_fix) { + var _delay = ( + typeof _renkan.options.size_bug_fix === "number" + ? _renkan.options.size_bug_fix + : 500 + ); + window.setTimeout( + function() { + _this.fixSize(true); + }, + _delay + ); + } + + if (_renkan.options.force_resize) { + $(window).resize(function() { + _this.fixSize(false); + }); + } + + this.redraw(); + + window.setInterval(function() { + var _now = new Date().valueOf(); + _this.delete_list.forEach(function(d) { + if (_now >= d.time) { + var el = _renkan.project.get("nodes").findWhere({"delete_scheduled":d.id}); + if (el) { + project.removeNode(el); + } + el = _renkan.project.get("edges").findWhere({"delete_scheduled":d.id}); + if (el) { + project.removeEdge(el); + } + } + }); + _this.delete_list = _this.delete_list.filter(function(d) { + return _renkan.project.get("nodes").findWhere({"delete_scheduled":d.id}) || _renkan.project.get("edges").findWhere({"delete_scheduled":d.id}) + }); + }, 500); + + if (this.minimap) { + window.setInterval(function() { + _this.rescaleMinimap() + }, 2000); + } + +} + +Rkns.Renderer.Scene.prototype.template = Rkns._.template( + '<% if (options.show_top_bar) { %><div class="Rk-TopBar"><% if (!options.editor_mode) { %><h2 class="Rk-PadTitle"><%- project.get("title") || translate("Untitled project")%></h2>' + + '<% } else { %><input type="text" class="Rk-PadTitle" value="<%- project.get("title") || "" %>" placeholder="<%-translate("Untitled project")%>" /><% } %>' + + '<div class="Rk-Users"><div class="Rk-CurrentUser"><span class="Rk-CurrentUser-Color"></span><span class="Rk-CurrentUser-Name"><unknown user></span></div><ul class="Rk-UserList"></ul></div>' + + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-FullScreen-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Full Screen")%></div></div></div>' + + '<% if (options.editor_mode) { %>' + + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddNode-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Add Node")%></div></div></div>' + + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddEdge-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Add Edge")%></div></div></div>' + + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-Save-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"> </div></div></div>' + + '<div class="Rk-TopBar-Separator"></div><a class="Rk-TopBar-Button Rk-Bookmarklet-Button" href="#"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents">' + + '<%-translate("Renkan \'Drag-to-Add\' bookmarklet")%></div></div></a>' + + '<div class="Rk-TopBar-Separator"></div>' + + '<% } %></div><% } %>' + + '<div class="Rk-Editing-Space<% if (!options.show_top_bar) { %> Rk-Editing-Space-Full<% } %>">' + + '<div class="Rk-Labels"></div><canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor"><div class="Rk-Notifications"></div>' + + '<% if (options.show_bins) { %><div class="Rk-Fold-Bins">«</div><% } %>' + + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%-translate("Zoom In")%>"></div><div class="Rk-ZoomOut" title="<%-translate("Zoom Out")%>"></div></div>' + + '</div></div>' +); + +Rkns.Renderer.Scene.prototype.fixSize = function(_autoscale) { + var w = this.$.width(), + h = this.$.height(); + if (this.renkan.options.show_top_bar) { + h -= this.$.find(".Rk-TopBar").height(); + } + this.canvas_$.attr({ + width: w, + height: h + }); + + paper.view.viewSize = new paper.Size([w, h]); + + if (_autoscale) { + this.autoScale(); + } +} + +Rkns.Renderer.Scene.prototype.drawSector = function(_repr, _inR, _outR, _startAngle, _endAngle, _padding, _imgname, _caption) { + var _options = this.renkan.options, + _startRads = _startAngle * Math.PI / 180, + _endRads = _endAngle * Math.PI / 180, + _img = this.imageCache[_imgname], + _span = _endRads - _startRads, + _startdx = - Math.sin(_startRads), + _startdy = Math.cos(_startRads), + _startXIn = Math.cos(_startRads) * _inR + _padding * _startdx, + _startYIn = Math.sin(_startRads) * _inR + _padding * _startdy, + _startXOut = Math.cos(_startRads) * _outR + _padding * _startdx, + _startYOut = Math.sin(_startRads) * _outR + _padding * _startdy, + _enddx = - Math.sin(_endRads), + _enddy = Math.cos(_endRads), + _endXIn = Math.cos(_endRads) * _inR - _padding * _enddx, + _endYIn = Math.sin(_endRads) * _inR - _padding * _enddy, + _endXOut = Math.cos(_endRads) * _outR - _padding * _enddx, + _endYOut = Math.sin(_endRads) * _outR - _padding * _enddy, + _centerR = (_inR + _outR)/2, + _centerRads = (_startRads + _endRads) / 2, + _centerX = Math.cos(_centerRads) * _centerR, + _centerY = Math.sin(_centerRads) * _centerR, + _centerXIn = Math.cos(_centerRads) * _inR, + _centerXOut = Math.cos(_centerRads) * _outR, + _centerYIn = Math.sin(_centerRads) * _inR, + _centerYOut = Math.sin(_centerRads) * _outR, + _textX = Math.cos(_centerRads) * (_outR + 3), + _textY = Math.sin(_centerRads) * (_outR + _options.buttons_label_font_size) + _options.buttons_label_font_size / 2, + _segments = []; + this.buttons_layer.activate(); + var _path = new paper.Path(); + _path.add([_startXIn, _startYIn]); + _path.arcTo([_centerXIn, _centerYIn], [_endXIn, _endYIn]); + _path.lineTo([_endXOut, _endYOut]); + _path.arcTo([_centerXOut, _centerYOut], [_startXOut, _startYOut]); + _path.fillColor = _options.buttons_background; + _path.opacity = .5; + _path.closed = true; + _path.__representation = _repr; + var _text = new paper.PointText(_textX,_textY); + _text.characterStyle = { + fontSize: _options.buttons_label_font_size, + fillColor: _options.buttons_label_color + }; + if (_textX > 2) { + _text.paragraphStyle.justification = 'left'; + } else if (_textX < -2) { + _text.paragraphStyle.justification = 'right'; + } else { + _text.paragraphStyle.justification = 'center'; + } + _text.visible = false; + var _visible = false, + _restPos = new paper.Point(-200, -200), + _grp = new paper.Group([_path, _text]), + _delta = _grp.position, + _imgdelta = new paper.Point([_centerX, _centerY]), + _currentPos = new paper.Point(0,0); + _text.content = _caption; + _grp.visible = false; + _grp.position = _restPos; + var _res = { + show: function() { + _visible = true; + _grp.position = _currentPos.add(_delta); + _grp.visible = true; + }, + moveTo: function(_point) { + _currentPos = _point; + if (_visible) { + _grp.position = _point.add(_delta); + } + }, + hide: function() { + _visible = false; + _grp.visible = false; + _grp.position = _restPos; + }, + select: function() { + _path.opacity = .8; + _text.visible = true; + }, + unselect: function() { + _path.opacity = .5; + _text.visible = false; + }, + destroy: function() { + _grp.remove(); + } + } + function showImage() { + var _raster = new paper.Raster(_img); + _raster.position = _imgdelta.add(_grp.position).subtract(_delta); + _grp.addChild(_raster); + } + if (_img.width) { + showImage(); + } else { + Rkns.$(_img).on("load",showImage); + } + + return _res +} + +Rkns.Renderer.Scene.prototype.addToBundles = function(_edgeRepr) { + var _bundle = Rkns._(this.bundles).find(function(_bundle) { + return ( + ( _bundle.from === _edgeRepr.from_representation && _bundle.to === _edgeRepr.to_representation ) + || ( _bundle.from === _edgeRepr.to_representation && _bundle.to === _edgeRepr.from_representation ) + ); + }); + if (typeof _bundle !== "undefined") { + _bundle.edges.push(_edgeRepr) + } else { + _bundle = { + from: _edgeRepr.from_representation, + to: _edgeRepr.to_representation, + edges: [ _edgeRepr ], + getPosition: function(_er) { + var _dir = (_er.from_representation === this.from) ? 1 : -1; + return _dir * ( Rkns._(this.edges).indexOf(_er) - (this.edges.length - 1) / 2 ); + } + } + this.bundles.push(_bundle); + } + return _bundle; +} + +Rkns.Renderer.Scene.prototype.isEditable = function() { + return (this.renkan.options.editor_mode && !this.renkan.read_only) +} + +Rkns.Renderer.Scene.prototype.onStatusChange = function() { + var savebtn = this.$.find(".Rk-Save-Button"), + tip = savebtn.find(".Rk-TopBar-Tooltip-Contents"); + if (this.renkan.read_only) { + savebtn.removeClass("disabled Rk-Save-Online").addClass("Rk-Save-ReadOnly"); + tip.text(this.renkan.translate("Connection lost")); + } else { + if (this.renkan.options.snapshot_mode) { + savebtn.removeClass("Rk-Save-ReadOnly Rk-Save-Online"); + tip.text(this.renkan.translate("Archive Project")); + } else { + savebtn.removeClass("disabled Rk-Save-ReadOnly").addClass("Rk-Save-Online"); + tip.text(this.renkan.translate("Auto-save enabled")); + } + } +} + +Rkns.Renderer.Scene.prototype.setScale = function(_newScale, _offset) { + if (_newScale > Rkns.Renderer._MIN_SCALE && _newScale < Rkns.Renderer._MAX_SCALE) { + this.scale = _newScale; + if (_offset) { + this.offset = _offset + } + this.redraw(); + } +} + +Rkns.Renderer.Scene.prototype.autoScale = function() { + var nodes = this.renkan.project.get("nodes") + if (nodes.length > 1) { + var _xx = nodes.map(function(_node) { return _node.get("position").x }), + _yy = nodes.map(function(_node) { return _node.get("position").y }), + _minx = Math.min.apply(Math, _xx), + _miny = Math.min.apply(Math, _yy), + _maxx = Math.max.apply(Math, _xx), + _maxy = Math.max.apply(Math, _yy); + var _scale = Math.max(Rkns.Renderer._MIN_SCALE, Math.min(Rkns.Renderer._MAX_SCALE, (paper.view.size.width - 2 * Rkns.Renderer._AUTOSCALE_MARGIN) / (_maxx - _minx), (paper.view.size.height - 2 * Rkns.Renderer._AUTOSCALE_MARGIN) / (_maxy - _miny))); + this.setScale(_scale, paper.view.center.subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale))); + } + if (nodes.length === 1) { + this.setScale(1, paper.view.center.subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y]))); + } +} + +Rkns.Renderer.Scene.prototype.redrawMiniframe = function() { + var topleft = this.toMinimapCoords(this.toModelCoords(new paper.Point([0,0]))), + bottomright = this.toMinimapCoords(this.toModelCoords(paper.view.bounds.bottomRight)); + this.minimap.miniframe.fitBounds(topleft, bottomright); +} + +Rkns.Renderer.Scene.prototype.rescaleMinimap = function() { + var nodes = this.renkan.project.get("nodes") + if (nodes.length > 1) { + var _xx = nodes.map(function(_node) { return _node.get("position").x }), + _yy = nodes.map(function(_node) { return _node.get("position").y }), + _minx = Math.min.apply(Math, _xx), + _miny = Math.min.apply(Math, _yy), + _maxx = Math.max.apply(Math, _xx), + _maxy = Math.max.apply(Math, _yy); + var _scale = Math.min( + this.scale * .8 * this.renkan.options.minimap_width / paper.view.bounds.width, + this.scale * .8 * this.renkan.options.minimap_height / paper.view.bounds.height, + ( this.renkan.options.minimap_width - 2 * Rkns.Renderer._MINIMAP_MARGIN ) / (_maxx - _minx), + ( this.renkan.options.minimap_height - 2 * Rkns.Renderer._MINIMAP_MARGIN ) / (_maxy - _miny) + ); + this.minimap.offset = this.minimap.size.divide(2).subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale)); + this.minimap.scale = _scale; + } + if (nodes.length === 1) { + this.minimap.scale = .1; + this.minimap.offset = this.minimap.size.divide(2).subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y]).multiply(this.minimap.scale)); + } + this.redraw(); +} + +Rkns.Renderer.Scene.prototype.toPaperCoords = function(_point) { + return _point.multiply(this.scale).add(this.offset); +} + +Rkns.Renderer.Scene.prototype.toMinimapCoords = function(_point) { + return _point.multiply(this.minimap.scale).add(this.minimap.offset).add(this.minimap.topleft); +} + +Rkns.Renderer.Scene.prototype.toModelCoords = function(_point) { + return _point.subtract(this.offset).divide(this.scale); +} + +Rkns.Renderer.Scene.prototype.addRepresentation = function(_type, _model) { + var _repr = new Rkns.Renderer[_type](this, _model); + this.representations.push(_repr); + return _repr; +} + +Rkns.Renderer.Scene.prototype.addRepresentations = function(_type, _collection) { + var _this = this; + _collection.forEach(function(_model) { + _this.addRepresentation(_type, _model); + }); +} + +Rkns.Renderer.Scene.prototype.userTemplate = Rkns._.template( + '<li class="Rk-User"><span class="Rk-UserColor" style="background:<%=background%>;"></span><%=name%></li>' +); + +Rkns.Renderer.Scene.prototype.addUser = function(_user) { + if (_user.get("_id") === this.renkan.current_user) { + this.$.find(".Rk-CurrentUser-Name").text(_user.get("title")); + this.$.find(".Rk-CurrentUser-Color").css("background", _user.get("color")); + } else { + this.$.find(".Rk-UserList").append( + Rkns.$( + this.userTemplate({ + name: _user.get("title"), + background: _user.get("color") + }) + ) + ); + } +} + +Rkns.Renderer.Scene.prototype.removeRepresentation = function(_representation) { + _representation.destroy(); + this.representations = Rkns._(this.representations).reject( + function(_repr) { + return _repr == _representation + } + ); +} + +Rkns.Renderer.Scene.prototype.getRepresentationByModel = function(_model) { + return Rkns._(this.representations).find(function(_repr) { + return _repr.model === _model; + }); +} + +Rkns.Renderer.Scene.prototype.removeRepresentationsOfType = function(_type) { + var _representations = Rkns._(this.representations).filter(function(_repr) { + return _repr.type == _type; + }), + _this = this; + Rkns._(_representations).each(function(_repr) { + _this.removeRepresentation(_repr); + }); +} + +Rkns.Renderer.Scene.prototype.highlightModel = function(_model) { + var _repr = this.getRepresentationByModel(_model); + if (_repr) { + _repr.highlight(); + } +} + +Rkns.Renderer.Scene.prototype.unhighlightAll = function(_model) { + Rkns._(this.representations).each(function(_repr) { + _repr.unhighlight(); + }); +} + +Rkns.Renderer.Scene.prototype.unselectAll = function(_model) { + Rkns._(this.representations).each(function(_repr) { + _repr.unselect(); + }); +} + +Rkns.Renderer.Scene.prototype.redraw = function() { + Rkns._(this.representations).each(function(_representation) { + _representation.redraw(true); + }); + if (this.minimap) { + this.redrawMiniframe(); + } + paper.view.draw(); +} + +Rkns.Renderer.Scene.prototype.addTempEdge = function(_from, _point) { + var _tmpEdge = this.addRepresentation("TempEdge",null); + _tmpEdge.end_pos = _point; + _tmpEdge.from_representation = _from; + _tmpEdge.redraw(); + this.click_target = _tmpEdge; +} + +Rkns.Renderer.Scene.prototype.findTarget = function(_hitResult) { + if (_hitResult && typeof _hitResult.item.__representation !== "undefined") { + var _newTarget = _hitResult.item.__representation; + if (this.selected_target !== _hitResult.item.__representation) { + if (this.selected_target) { + this.selected_target.unselect(_newTarget); + } + _newTarget.select(this.selected_target); + this.selected_target = _newTarget; + } + } else { + if (this.selected_target) { + this.selected_target.unselect(); + } + this.selected_target = null; + } +} + +Rkns.Renderer.Scene.prototype.paperShift = function(_delta) { + this.offset = this.offset.add(_delta); + this.redraw(); +} + +Rkns.Renderer.Scene.prototype.onMouseMove = function(_event) { + var _off = this.canvas_$.offset(), + _point = new paper.Point([ + _event.pageX - _off.left, + _event.pageY - _off.top + ]), + _delta = _point.subtract(this.last_point); + this.last_point = _point; + if (!this.is_dragging && this.mouse_down && _delta.length > Rkns.Renderer._MIN_DRAG_DISTANCE) { + this.is_dragging = true; + } + var _hitResult = paper.project.hitTest(_point); + if (this.is_dragging) { + if (this.click_target && typeof this.click_target.paperShift === "function") { + this.click_target.paperShift(_delta); + } else { + this.paperShift(_delta); + } + } else { + this.findTarget(_hitResult); + } + paper.view.draw(); +} + +Rkns.Renderer.Scene.prototype.onMouseDown = function(_event, _isTouch) { + var _off = this.canvas_$.offset(), + _point = new paper.Point([ + _event.pageX - _off.left, + _event.pageY - _off.top + ]); + this.last_point = _point; + this.mouse_down = true; + if (!this.click_target || this.click_target.type !== "Temp-edge") { + this.removeRepresentationsOfType("editor"); + this.is_dragging = false; + var _hitResult = paper.project.hitTest(_point); + if (_hitResult && typeof _hitResult.item.__representation !== "undefined") { + this.click_target = _hitResult.item.__representation; + this.click_target.mousedown(_event, _isTouch); + } else { + this.click_target = null; + if (this.isEditable() && this.click_mode === Rkns.Renderer._CLICKMODE_ADDNODE) { + var _coords = this.toModelCoords(_point), + _data = { + id: Rkns.Utils.getUID('node'), + created_by: this.renkan.current_user, + position: { + x: _coords.x, + y: _coords.y + } + }; + _node = this.renkan.project.addNode(_data); + this.getRepresentationByModel(_node).openEditor(); + } + } + } + if (this.click_mode) { + if (this.isEditable() && this.click_mode === Rkns.Renderer._CLICKMODE_STARTEDGE && this.click_target && this.click_target.type === "Node") { + this.removeRepresentationsOfType("editor"); + this.addTempEdge(this.click_target, _point); + this.click_mode = Rkns.Renderer._CLICKMODE_ENDEDGE; + this.notif_$.fadeOut(function() { + Rkns.$(this).html(_renkan.translate("Click on a second node to complete the edge")).fadeIn(); + }); + } else { + this.notif_$.hide(); + this.click_mode = false; + } + } + paper.view.draw(); +} + +Rkns.Renderer.Scene.prototype.onMouseUp = function(_event, _isTouch) { + this.mouse_down = false; + if (this.click_target) { + var _off = this.canvas_$.offset(); + this.click_target.mouseup( + { + point: new paper.Point([ + _event.pageX - _off.left, + _event.pageY - _off.top + ]) + }, + _isTouch + ); + } else { + this.click_target = null; + this.is_dragging = false; + if (_isTouch) { + this.unselectAll(); + } + } + paper.view.draw(); +} + +Rkns.Renderer.Scene.prototype.onScroll = function(_event, _scrolldelta) { + this.totalScroll += _scrolldelta; + if (Math.abs(this.totalScroll) >= 1) { + var _off = this.canvas_$.offset(), + _delta = new paper.Point([ + _event.pageX - _off.left, + _event.pageY - _off.top + ]).subtract(this.offset).multiply( Math.SQRT2 - 1 ); + if (this.totalScroll > 0) { + this.setScale( this.scale * Math.SQRT2, this.offset.subtract(_delta) ); + } else { + this.setScale( this.scale * Math.SQRT1_2, this.offset.add(_delta.divide(Math.SQRT2))); + } + this.totalScroll = 0; + } +} + +Rkns.Renderer.Scene.prototype.onDoubleClick = function(_event) { + if (!this.isEditable()) { + return; + } + var _off = this.canvas_$.offset(), + _point = new paper.Point([ + _event.pageX - _off.left, + _event.pageY - _off.top + ]); + var _hitResult = paper.project.hitTest(_point); + if (this.isEditable() && (!_hitResult || typeof _hitResult.item.__representation === "undefined")) { + var _coords = this.toModelCoords(_point), + _data = { + id: Rkns.Utils.getUID('node'), + created_by: this.renkan.current_user, + position: { + x: _coords.x, + y: _coords.y + } + }; + _node = this.renkan.project.addNode(_data); + this.getRepresentationByModel(_node).openEditor(); + } + paper.view.draw(); +} + +Rkns.Renderer.Scene.prototype.dropData = function(_data, _event) { + if (!this.isEditable()) { + return; + } + if (_data["text/json"] || _data["application/json"]) { + try { + var jsondata = JSON.parse(_data["text/json"] || _data["application/json"]); + _(_data).extend(jsondata); + } + catch(e) {} + } + var newNode = {}; + switch(_data["text/x-iri-specific-site"]) { + case "twitter": + var snippet = Rkns.$('<div>').html(_data["text/x-iri-selected-html"]), + tweetdiv = snippet.find(".tweet") + newNode.title = _renkan.translate("Tweet by ") + tweetdiv.attr("data-name"); + newNode.uri = "http://twitter.com/" + tweetdiv.attr("data-screen-name") + "/status/" + tweetdiv.attr("data-tweet-id"); + newNode.image = tweetdiv.find(".avatar").attr("src"); + newNode.description = tweetdiv.find(".js-tweet-text:first").text(); + break; + case "google": + var snippet = Rkns.$('<div>').html(_data["text/x-iri-selected-html"]); + newNode.title = snippet.find("h3:first").text().trim(); + newNode.uri = snippet.find("h3 a").attr("href"); + newNode.description = snippet.find(".st:first").text().trim(); + break; + case undefined: + default: + if (_data["text/x-iri-source-uri"]) { + newNode.uri = _data["text/x-iri-source-uri"]; + } + if (_data["text/plain"] || _data["text/x-iri-selected-text"]) { + newNode.description = (_data["text/plain"] || _data["text/x-iri-selected-text"]).replace(/[\s\n]+/gm,' ').trim(); + } + if (_data["text/html"] || _data["text/x-iri-selected-html"]) { + var snippet = Rkns.$('<div>').html(_data["text/html"] || _data["text/x-iri-selected-html"]); + var _imgs = snippet.find("img"); + if (_imgs.length) { + newNode.image = _imgs[0].src; + } + var _as = snippet.find("a"); + if (_as.length) { + newNode.uri = _as[0].href; + } + newNode.title = snippet.find("[title]").attr("title") || newNode.title; + newNode.description = snippet.text().replace(/[\s\n]+/gm,' ').trim(); + } + if (_data["text/uri-list"]) { + newNode.uri = _data["text/uri-list"]; + } + if (_data["text/x-moz-url"] && !newNode.title) { + newNode.title = (_data["text/x-moz-url"].split("\n")[1] || "").trim(); + if (newNode.title === newNode.uri) { + newNode.title = false; + } + } + if (_data["text/x-iri-source-title"] && !newNode.title) { + newNode.title = _data["text/x-iri-source-title"]; + } + if (_data["text/html"] || _data["text/x-iri-selected-html"]) { + newNode.image = snippet.find("[data-image]").attr("data-image") || newNode.image; + newNode.uri = snippet.find("[data-uri]").attr("data-uri") || newNode.uri; + newNode.title = snippet.find("[data-title]").attr("data-title") || newNode.title; + newNode.description = snippet.find("[data-description]").attr("data-description") || newNode.description; + } + } + if (!newNode.title) { + newNode.title = this.renkan.translate("Dragged resource"); + } + var fields = ["title", "description", "uri", "image"]; + for (var i = 0; i < fields.length; i++) { + var f = fields[i]; + if (_data["text/x-iri-" + f] || _data[f]) { + newNode[f] = _data["text/x-iri-" + f] || _data[f]; + } + if (newNode[f] === "none" || newNode[f] === "null") { + newNode[f] = undefined; + } + } + var _off = this.canvas_$.offset(), + _point = new paper.Point([ + _event.pageX - _off.left, + _event.pageY - _off.top + ]), + _coords = this.toModelCoords(_point), + _nodedata = { + id: Rkns.Utils.getUID('node'), + created_by: this.renkan.current_user, + uri: newNode.uri || "", + title: newNode.title || "", + description: newNode.description || "", + image: newNode.image || "", + color: newNode.color || undefined, + position: { + x: _coords.x, + y: _coords.y + } + }; + var _node = this.renkan.project.addNode(_nodedata), + _repr = this.getRepresentationByModel(_node); + if (_event.type === "drop") { + _repr.openEditor(); + } +}
--- a/src/js/libs/underscore-min.js Wed Apr 03 15:44:17 2013 +0200 +++ b/src/js/libs/underscore-min.js Tue Apr 23 15:23:20 2013 +0200 @@ -1,32 +1,1 @@ -// Underscore.js 1.3.3 -// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. -// Underscore is freely distributable under the MIT license. -// Portions of Underscore are inspired or borrowed from Prototype, -// Oliver Steele's Functional, and John Resig's Micro-Templating. -// For all details and documentation: -// http://documentcloud.github.com/underscore -(function(){function r(a,c,d){if(a===c)return 0!==a||1/a==1/c;if(null==a||null==c)return a===c;a._chain&&(a=a._wrapped);c._chain&&(c=c._wrapped);if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return!1;switch(e){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:0==a?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== -c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if("object"!=typeof a||"object"!=typeof c)return!1;for(var f=d.length;f--;)if(d[f]==a)return!0;d.push(a);var f=0,g=!0;if("[object Array]"==e){if(f=a.length,g=f==c.length)for(;f--&&(g=f in a==f in c&&r(a[f],c[f],d)););}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return!1;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,h)&&!f--)break; -g=!f}}d.pop();return g}var s=this,I=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,J=k.unshift,l=p.toString,K=p.hasOwnProperty,y=k.forEach,z=k.map,A=k.reduce,B=k.reduceRight,C=k.filter,D=k.every,E=k.some,q=k.indexOf,F=k.lastIndexOf,p=Array.isArray,L=Object.keys,t=Function.prototype.bind,b=function(a){return new m(a)};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._=b):s._=b;b.VERSION="1.3.3";var j=b.each=b.forEach=function(a, -c,d){if(a!=null)if(y&&a.forEach===y)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(e in a&&c.call(d,a[e],e,a)===o)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===o)break};b.map=b.collect=function(a,c,b){var e=[];if(a==null)return e;if(z&&a.map===z)return a.map(c,b);j(a,function(a,g,h){e[e.length]=c.call(b,a,g,h)});if(a.length===+a.length)e.length=a.length;return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(A&& -a.reduce===A){e&&(c=b.bind(c,e));return f?a.reduce(c,d):a.reduce(c)}j(a,function(a,b,i){if(f)d=c.call(e,d,a,b,i);else{d=a;f=true}});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(B&&a.reduceRight===B){e&&(c=b.bind(c,e));return f?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a, -c,b){var e;G(a,function(a,g,h){if(c.call(b,a,g,h)){e=a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(C&&a.filter===C)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(D&&a.every===D)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b, -a,g,h)))return o});return!!e};var G=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(E&&a.some===E)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(q&&a.indexOf===q)return a.indexOf(c)!=-1;return b=G(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= -function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&& -(e={value:a,computed:b})});return e.value};b.shuffle=function(a){var b=[],d;j(a,function(a,f){d=Math.floor(Math.random()*(f+1));b[f]=b[d];b[d]=a});return b};b.sortBy=function(a,c,d){var e=b.isFunction(c)?c:function(a){return a[c]};return b.pluck(b.map(a,function(a,b,c){return{value:a,criteria:e.call(d,a,b,c)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c===void 0?1:d===void 0?-1:c<d?-1:c>d?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]}; -j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:b.isArray(a)||b.isArguments(a)?i.call(a):a.toArray&&b.isFunction(a.toArray)?a.toArray():b.values(a)};b.size=function(a){return b.isArray(a)?a.length:b.keys(a).length};b.first=b.head=b.take=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};b.initial=function(a,b,d){return i.call(a, -0,a.length-(b==null||d?1:b))};b.last=function(a,b,d){return b!=null&&!d?i.call(a,Math.max(a.length-b,0)):a[a.length-1]};b.rest=b.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};b.compact=function(a){return b.filter(a,function(a){return!!a})};b.flatten=function(a,c){return b.reduce(a,function(a,e){if(b.isArray(e))return a.concat(c?e:b.flatten(e));a[a.length]=e;return a},[])};b.without=function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a, -e=[];a.length<3&&(c=true);b.reduce(d,function(d,g,h){if(c?b.last(d)!==g||!d.length:!b.include(d,g)){d.push(g);e.push(a[h])}return d},[]);return e};b.union=function(){return b.uniq(b.flatten(arguments,true))};b.intersection=b.intersect=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1),true);return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a= -i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,c,d){if(a==null)return-1;var e;if(d){d=b.sortedIndex(a,c);return a[d]===c?d:-1}if(q&&a.indexOf===q)return a.indexOf(c);d=0;for(e=a.length;d<e;d++)if(d in a&&a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(F&&a.lastIndexOf===F)return a.lastIndexOf(b);for(var d=a.length;d--;)if(d in a&&a[d]===b)return d;return-1};b.range=function(a,b,d){if(arguments.length<= -1){b=a||0;a=0}for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;){g[f++]=a;a=a+d}return g};var H=function(){};b.bind=function(a,c){var d,e;if(a.bind===t&&t)return t.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));H.prototype=a.prototype;var b=new H,g=a.apply(b,e.concat(i.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c= -i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(null,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,h,i,j=b.debounce(function(){h= -g=false},c);return function(){d=this;e=arguments;f||(f=setTimeout(function(){f=null;h&&a.apply(d,e);j()},c));g?h=true:i=a.apply(d,e);j();g=true;return i}};b.debounce=function(a,b,d){var e;return function(){var f=this,g=arguments;d&&!e&&a.apply(f,g);clearTimeout(e);e=setTimeout(function(){e=null;d||a.apply(f,g)},b)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments,0)); -return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=L||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&& -c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.pick=function(a){var c={};j(b.flatten(i.call(arguments,1)),function(b){b in a&&(c[b]=a[b])});return c};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty= -function(a){if(a==null)return true;if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFunction=function(a){return l.call(a)=="[object Function]"}; -b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isFinite=function(a){return b.isNumber(a)&&isFinite(a)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a, -b){return K.call(a,b)};b.noConflict=function(){s._=I;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.escape=function(a){return(""+a).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){M(c,b[c]=a[c])})};var N=0;b.uniqueId= -function(a){var b=N++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var u=/.^/,n={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},v;for(v in n)n[n[v]]=v;var O=/\\|'|\r|\n|\t|\u2028|\u2029/g,P=/\\(\\|'|r|n|t|u2028|u2029)/g,w=function(a){return a.replace(P,function(a,b){return n[b]})};b.template=function(a,c,d){d=b.defaults(d||{},b.templateSettings);a="__p+='"+a.replace(O,function(a){return"\\"+n[a]}).replace(d.escape|| -u,function(a,b){return"'+\n_.escape("+w(b)+")+\n'"}).replace(d.interpolate||u,function(a,b){return"'+\n("+w(b)+")+\n'"}).replace(d.evaluate||u,function(a,b){return"';\n"+w(b)+"\n;__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+a+"}\n");var a="var __p='';var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n"+a+"return __p;\n",e=new Function(d.variable||"obj","_",a);if(c)return e(c,b);c=function(a){return e.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c}; -b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var x=function(a,c){return c?b(a).chain():a},M=function(a,c){m.prototype[a]=function(){var a=i.call(arguments);J.call(a,this._wrapped);return x(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return x(d, -this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return x(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); +(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,d=e.filter,g=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.4";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:d&&n.filter===d?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:g&&n.every===g?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2),e=w.isFunction(t);return w.map(n,function(n){return(e?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t,r){return w.isEmpty(t)?r?null:[]:w[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.findWhere=function(n,t){return w.where(n,t,!0)},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var k=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=k(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index<t.index?-1:1}),"value")};var F=function(n,t,r,e){var u={},i=k(t||w.identity);return A(n,function(t,a){var o=i.call(r,t,a,n);e(u,o,t)}),u};w.groupBy=function(n,t,r){return F(n,t,r,function(n,t,r){(w.has(n,t)?n[t]:n[t]=[]).push(r)})},w.countBy=function(n,t,r){return F(n,t,r,function(n,t){w.has(n,t)||(n[t]=0),n[t]++})},w.sortedIndex=function(n,t,r,e){r=null==r?w.identity:k(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i},w.bind=function(n,t){if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));var r=o.call(arguments,2);return function(){return n.apply(t,r.concat(o.call(arguments)))}},w.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},w.bindAll=function(n){var t=o.call(arguments,1);return 0===t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var I=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=I(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&I(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return I(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),"function"!=typeof/./&&(w.isFunction=function(n){return"function"==typeof n}),w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return n===void 0},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var M={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};M.unescape=w.invert(M.escape);var S={escape:RegExp("["+w.keys(M.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(M.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(S[n],function(t){return M[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),D.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=++N+"";return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,q={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},B=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){var e;r=w.defaults({},r,w.templateSettings);var u=RegExp([(r.escape||T).source,(r.interpolate||T).source,(r.evaluate||T).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(B,function(n){return"\\"+q[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,w);var c=function(n){return e.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},w.chain=function(n){return w(n).chain()};var D=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],D.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return D.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); \ No newline at end of file
--- a/src/widgets/Renkan.css Wed Apr 03 15:44:17 2013 +0200 +++ b/src/widgets/Renkan.css Tue Apr 23 15:23:20 2013 +0200 @@ -1,51 +1,70 @@ -.Ldt-Renkan { - position: relative; +.Ldt-Renkan-Container { + position: relative; width: 100%; height: 100%; } .Ldt-Renkan a { color: #303080; } -.Rk-ProjectList { - position: absolute; left: 0; top: 0; list-style: none; padding: 0; margin: 0; -} -.Rk-Project { - list-style: none; margin-right: 5px; padding: 5px; height: 15px; font-size: 13px; font-weight: bold; - float: left; border-top-left-radius: 8px; border-top-right-radius: 8px; - background: #505050; color: #E0E0E0; cursor: pointer; - background: -moz-linear-gradient(top, #333333 20%, #666666 80%); -} - -.Rk-Project:hover { - background: -moz-linear-gradient(bottom, #333333 20%, #666666 80%); -} - -.Rk-Project.active { - background: #505080; - color: #ffffc0; - background: -moz-linear-gradient(bottom, #333366 20%, #666699 80%); -} -.Rk-Render, .Rk-Canvas { - position: absolute; left: 0; top: 0; width: 600px; height: 500px; - overflow: hidden; +.Rk-Main { + position: absolute; left: 0; top: 0; right: 0; bottom: 0; } .Rk-Render { - top: 25px; - background: -moz-linear-gradient(top, rgba(180,180,180,.2) 0, rgba(255,255,255,.2) 30%, rgba(255,255,255,.2) 70%, rgba(180,180,180,.2) 100%); - background: -webkit-linear-gradient(top, rgba(180,180,180,.2) 0, rgba(255,255,255,.2) 30%, rgba(255,255,255,.2) 70%, rgba(180,180,180,.2) 100%); + position: absolute; left: 0; top: 0; right: 0; bottom: 0; + background: #ffffff; +} + +/* Canvas */ + +.Rk-Editing-Space { + position: absolute; left: 0; top: 35px; right: 0; bottom: 0; overflow: hidden; + background: -moz-radial-gradient( center, circle, #ffffff 40%, #e0e0e0 90%); + background: -webkit-radial-gradient( center, circle, #ffffff 40%, #e0e0e0 90%); + background: -ms-radial-gradient( center, circle, #ffffff 40%, #e0e0e0 90%); +} + +.Rk-Editing-Space-Full { + top: 0; } .Rk-Canvas { - top: 0; - background: -moz-linear-gradient(left, rgba(180,180,180,.2) 0, rgba(255,255,255,.2) 30%, rgba(255,255,255,.2) 70%, rgba(180,180,180,.2) 100%); - background: -webkit-linear-gradient(left, rgba(180,180,180,.2) 0, rgba(255,255,255,.2) 30%, rgba(255,255,255,.2) 70%, rgba(180,180,180,.2) 100%); + position: absolute; left: 0; top: 0; right: 0; bottom: 0; z-index: 2; +} + +/* Node Labels */ + +.Rk-Labels { + position: absolute; left: 0; top: 0; z-index: 1; + font-family: "Segoe UI", "Helvetica Neue", Arial, Helvetica, sans-serif; +} + +.Rk-Label { + position: absolute; width: 160px; margin-left: -80px; text-align: center; font-size: 13px; line-height: 13px; } +.Rk-Edge-Label { + font-size: 11px; transform-origin: 50% 0; -moz-transform-origin: 50% 0; + -webkit-transform-origin: 50% 0; -ms-transform-origin: 50% 0; +} + +/* Editors */ + .Rk-Editor { - position: absolute; left: 0; top: 0; + position: absolute; left: 0; top: 0; z-index: 3; +} + +.Rk-Notifications { + position: absolute; right: 15px; top: 15px; width: 200px; + padding: 10px; border-radius: 8px; display: none; + color: #ffffff; font-size: 13px; text-align: center; font-weight: bold; + background: rgba(20,20,20,.7); + background: -moz-linear-gradient(top, rgba(40,40,40,.7) 20%, rgba(0,0,0,.7) 80%); + background: -webkit-linear-gradient(top, rgba(40,40,40,.7) 20%, rgba(0,0,0,.7) 80%); + background: -ms-linear-gradient(top, rgba(40,40,40,.7) 20%, rgba(0,0,0,.7) 80%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#202020', endColorstr='#000000',GradientType=0 ); } .Rk-CloseX { @@ -53,31 +72,43 @@ } .Rk-Editor h2 { - font-size: 16px; font-weight: bold; + font-size: 16px; font-weight: bold; padding: 0; } -.Rk-Editor p { - margin: 5px 0; font-size: 12px; +.Rk-Editor p, .Rk-Editor-p { + margin: 5px 0; font-size: 12px; clear: both; padding: 0; } -.Rk-RelatedList { - list-style: none; padding: 0; margin: 0; +.Rk-Editor-Label { + float: left; width: 80px; } -.Rk-Related { - list-style: none; color: #a000c0; cursor: pointer; margin: 5px 0; +.Rk-UserColor { + display: inline-block; width: 12px; height: 12px; border: 1px solid #666666; margin: -2px 2px; } -.Rk-Related b { - font-weight: bolder; +.Rk-Display-Title a { + text-decoration: none; color: #000000; } -.Rk-Related:hover { +.Rk-Display-Title a:hover { text-decoration: underline; } +.Rk-Display-URI { + font-style: italic; +} + +.Rk-Display-ImgPreview { + margin: 5px auto; display: block; max-width: 255px !important; max-height: 120px !important; +} + +.Rk-ZoomButtons { + position: absolute; left: 0; top: 35px; cursor: pointer; +} + .Rk-ZoomIn, .Rk-ZoomOut { - width: 21px; height: 20px; background: url(img/zoombuttons.png); margin: 5px; cursor: pointer; + width: 21px; height: 20px; background: url(../img/zoombuttons.png); margin: 5px; } .Rk-ZoomIn:hover { @@ -91,3 +122,4 @@ .Rk-ZoomOut:hover { background-position: -21px -20px; } +
--- a/src/widgets/Renkan.js Wed Apr 03 15:44:17 2013 +0200 +++ b/src/widgets/Renkan.js Tue Apr 23 15:23:20 2013 +0200 @@ -18,87 +18,100 @@ } IriSP.Widgets.Renkan.prototype.template = - '<div class="Ldt-Renkan"></div>'; + '<div class="Ldt-Renkan-Container"><div class="Ldt-Renkan"></div></div>'; IriSP.Widgets.Renkan.prototype.draw = function() { this.renderTemplate(); var _id = IriSP.Model.getUID(); this.$.find(".Ldt-Renkan").attr("id", _id); this.renkan = new Rkns.Renkan({ - container: _id + container: _id, + editor_mode: false, + show_bins: false, + show_top_bar: false, + force_resize: true, + language: IriSP.language }); - if (typeof this.data === "string") { - this.data = [ this.data ]; - } + this.node_times = []; var _this = this, _list = this.getWidgetAnnotations(); - this.node_times = []; - Rkns._(this.data).each(function(_url, _key) { - var _opts = { - url: _url - } - if (!_key) { - _opts.callback = function(_p) { - _this.renkan.renderProject(_p); - } - } - var _proj = _this.renkan.addProject(_opts); - _proj.on("add:nodes", function(_node) { - var _uri = _node.get("uri"), - _annmatch = _uri.match(_this.annotation_regexp); - if (_annmatch) { - var _annotations = _list.filter(function(_ann) { - return _ann.getMedia().id == _annmatch[1] && _ann.id == _annmatch[2]; + this.renkan.project.on("add:nodes", function(_node) { + var _uri = _node.get("uri"), + _annmatch = _uri.match(_this.annotation_regexp); + if (_annmatch) { + var _annotations = _list.filter(function(_ann) { + return _ann.getMedia().id == _annmatch[1] && _ann.id == _annmatch[2]; + }); + _annotations.forEach(function(_ann) { + var _duration = _ann.getDuration(), + _preroll = + ( _duration < _this.min_duration ) * ( _this.min_duration / 2); + var _nt = { + uri: _uri, + selected: false, + node: _node, + begin: _ann.begin - _preroll, + end: _ann.end + _preroll + } + _this.node_times.push(_nt); + var _annselected = false, + _nodeselected = false; + _ann.on("select", function() { + _annselected = true; + if (!_nodeselected) { + _node.trigger("select",true); + } }); - _annotations.forEach(function(_ann) { - var _duration = _ann.getDuration(), - _preroll = + ( _duration < _this.min_duration ) * ( _this.min_duration / 2); - var _nt = { - selected: false, - node: _node, - begin: _ann.begin - _preroll, - end: _ann.end + _preroll + _node.on("selected", function() { + _nodeselected = true; + if (!_annselected) { + _ann.trigger("select",true); + } + }); + _ann.on("unselect", function() { + _annselected = false; + if (_nodeselected) { + _node.trigger("unselect",true); } - _this.node_times.push(_nt); - _ann.on("select", function(_stop) { - if (!_stop) { - _node.trigger("select",true); - } - }); - _node.on("select", function(_stop) { - if (!_stop) { - _ann.trigger("select",true); - } - }); - _ann.on("unselect", function(_stop) { - if (!_stop) { - _node.trigger("unselect",true); - } - }); - _node.on("unselect", function(_stop) { - _nt.selected = false; - if (!_stop) { - _ann.trigger("unselect",true); - } - }); - _node.on("click", function() { - _this.media.setCurrentTime(_ann.begin); - _this.player.trigger("Mediafragment.setHashToAnnotation", _ann.id); - }); + }); + _node.on("unselected", function() { + _nodeselected = false; + _nt.selected = false; + if (_annselected) { + _ann.trigger("unselect",true); + } + }); + _node.on("clicked", function() { + _this.media.setCurrentTime(_ann.begin); + _this.player.trigger("Mediafragment.setHashToAnnotation", _ann.id); }); - } - var _tagmatch = _uri.match(_this.tag_regexp); - if (_tagmatch) { - _node.on("select", function() { - _this.source.getAnnotations().search(_tagmatch[1]); - }) - _node.on("unselect", function() { - _this.source.getAnnotations().search(""); - }) - } - }); - }) + }); + } + var _tagmatch = _uri.match(_this.tag_regexp); + if (_tagmatch) { + _node.on("select", function() { + _this.source.getAnnotations().search(_tagmatch[1]); + }) + _node.on("unselect", function() { + _this.source.getAnnotations().search(""); + }) + } + }); + Rkns.jsonIO(this.renkan, { + url: this.data + }); + this.onMediaEvent("timeupdate","onTimeupdate"); + + this.$.find(".Rk-Editor").on("click", "a", function() { + var href = this.href, + times = _this.node_times.filter(function(t) { + return t.uri == href; + }); + if (times.length) { + _this.media.setCurrentTime(times[0].begin); + return false; + } + }); } IriSP.Widgets.Renkan.prototype.onTimeupdate = function(_time) { @@ -106,11 +119,11 @@ if (_nt.begin <= _time && _nt.end >= _time) { if (!_nt.selected) { _nt.selected = true; - _nt.node.trigger("select", true); + _nt.node.trigger("select"); } } else { if (_nt.selected) { - _nt.node.trigger("unselect", true); + _nt.node.trigger("unselect"); } } });