Backbone initial check-in.
|
@ -0,0 +1,6 @@
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*#
|
||||||
|
.#*
|
||||||
|
.DS_Store
|
||||||
|
*~
|
|
@ -0,0 +1,84 @@
|
||||||
|
// A simple module to replace `Backbone.sync` with *localStorage*-based
|
||||||
|
// persistence. Models are given GUIDS, and saved into a JSON object. Simple
|
||||||
|
// as that.
|
||||||
|
|
||||||
|
// Generate four random hex digits.
|
||||||
|
function S4() {
|
||||||
|
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate a pseudo-GUID by concatenating random hexadecimal.
|
||||||
|
function guid() {
|
||||||
|
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
|
||||||
|
};
|
||||||
|
|
||||||
|
// Our Store is represented by a single JS object in *localStorage*. Create it
|
||||||
|
// with a meaningful name, like the name you'd give a table.
|
||||||
|
var Store = function(name) {
|
||||||
|
this.name = name;
|
||||||
|
var store = localStorage.getItem(this.name);
|
||||||
|
this.data = (store && JSON.parse(store)) || {};
|
||||||
|
};
|
||||||
|
|
||||||
|
_.extend(Store.prototype, {
|
||||||
|
|
||||||
|
// Save the current state of the **Store** to *localStorage*.
|
||||||
|
save: function() {
|
||||||
|
localStorage.setItem(this.name, JSON.stringify(this.data));
|
||||||
|
},
|
||||||
|
|
||||||
|
// Add a model, giving it a (hopefully)-unique GUID, if it doesn't already
|
||||||
|
// have an id of it's own.
|
||||||
|
create: function(model) {
|
||||||
|
if (!model.id) model.id = model.attributes.id = guid();
|
||||||
|
this.data[model.id] = model;
|
||||||
|
this.save();
|
||||||
|
return model;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Update a model by replacing its copy in `this.data`.
|
||||||
|
update: function(model) {
|
||||||
|
this.data[model.id] = model;
|
||||||
|
this.save();
|
||||||
|
return model;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Retrieve a model from `this.data` by id.
|
||||||
|
find: function(model) {
|
||||||
|
return this.data[model.id];
|
||||||
|
},
|
||||||
|
|
||||||
|
// Return the array of all models currently in storage.
|
||||||
|
findAll: function() {
|
||||||
|
return _.values(this.data);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Delete a model from `this.data`, returning it.
|
||||||
|
destroy: function(model) {
|
||||||
|
delete this.data[model.id];
|
||||||
|
this.save();
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Override `Backbone.sync` to use delegate to the model or collection's
|
||||||
|
// *localStorage* property, which should be an instance of `Store`.
|
||||||
|
Backbone.sync = function(method, model, success, error) {
|
||||||
|
|
||||||
|
var resp;
|
||||||
|
var store = model.localStorage || model.collection.localStorage;
|
||||||
|
|
||||||
|
switch (method) {
|
||||||
|
case "read": resp = model.id ? store.find(model) : store.findAll(); break;
|
||||||
|
case "create": resp = store.create(model); break;
|
||||||
|
case "update": resp = store.update(model); break;
|
||||||
|
case "delete": resp = store.destroy(model); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp) {
|
||||||
|
success(resp);
|
||||||
|
} else {
|
||||||
|
error("Record not found");
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,985 @@
|
||||||
|
// Backbone.js 0.3.2
|
||||||
|
// (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
|
||||||
|
// Backbone may be freely distributed under the MIT license.
|
||||||
|
// For all details and documentation:
|
||||||
|
// http://documentcloud.github.com/backbone
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
// Initial Setup
|
||||||
|
// -------------
|
||||||
|
|
||||||
|
// 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 = this.Backbone = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current version of the library. Keep in sync with `package.json`.
|
||||||
|
Backbone.VERSION = '0.3.2';
|
||||||
|
|
||||||
|
// Require Underscore, if we're on the server, and it's not already present.
|
||||||
|
var _ = this._;
|
||||||
|
if (!_ && (typeof require !== 'undefined')) _ = require("underscore")._;
|
||||||
|
|
||||||
|
// For Backbone's purposes, jQuery owns the `$` variable.
|
||||||
|
var $ = this.jQuery;
|
||||||
|
|
||||||
|
// Turn on `emulateHTTP` to use 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
|
||||||
|
// -----------------
|
||||||
|
|
||||||
|
// A module that can be mixed in to *any object* in order to provide it with
|
||||||
|
// custom events. You may `bind` or `unbind` a callback function to an event;
|
||||||
|
// `trigger`-ing an event fires all callbacks in succession.
|
||||||
|
//
|
||||||
|
// var object = {};
|
||||||
|
// _.extend(object, Backbone.Events);
|
||||||
|
// object.bind('expand', function(){ alert('expanded'); });
|
||||||
|
// object.trigger('expand');
|
||||||
|
//
|
||||||
|
Backbone.Events = {
|
||||||
|
|
||||||
|
// Bind an event, specified by a string name, `ev`, to a `callback` function.
|
||||||
|
// Passing `"all"` will bind the callback to all events fired.
|
||||||
|
bind : function(ev, callback) {
|
||||||
|
var calls = this._callbacks || (this._callbacks = {});
|
||||||
|
var list = this._callbacks[ev] || (this._callbacks[ev] = []);
|
||||||
|
list.push(callback);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Remove one or many callbacks. If `callback` is null, removes all
|
||||||
|
// callbacks for the event. If `ev` is null, removes all bound callbacks
|
||||||
|
// for all events.
|
||||||
|
unbind : function(ev, callback) {
|
||||||
|
var calls;
|
||||||
|
if (!ev) {
|
||||||
|
this._callbacks = {};
|
||||||
|
} else if (calls = this._callbacks) {
|
||||||
|
if (!callback) {
|
||||||
|
calls[ev] = [];
|
||||||
|
} else {
|
||||||
|
var list = calls[ev];
|
||||||
|
if (!list) return this;
|
||||||
|
for (var i = 0, l = list.length; i < l; i++) {
|
||||||
|
if (callback === list[i]) {
|
||||||
|
list.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Trigger an event, firing all bound callbacks. Callbacks are passed the
|
||||||
|
// same arguments as `trigger` is, apart from the event name.
|
||||||
|
// Listening for `"all"` passes the true event name as the first argument.
|
||||||
|
trigger : function(ev) {
|
||||||
|
var list, calls, i, l;
|
||||||
|
if (!(calls = this._callbacks)) return this;
|
||||||
|
if (list = calls[ev]) {
|
||||||
|
for (i = 0, l = list.length; i < l; i++) {
|
||||||
|
list[i].apply(this, Array.prototype.slice.call(arguments, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (list = calls['all']) {
|
||||||
|
for (i = 0, l = list.length; i < l; i++) {
|
||||||
|
list[i].apply(this, arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Backbone.Model
|
||||||
|
// --------------
|
||||||
|
|
||||||
|
// Create a new model, with defined attributes. A client id (`cid`)
|
||||||
|
// is automatically generated and assigned for you.
|
||||||
|
Backbone.Model = function(attributes, options) {
|
||||||
|
attributes || (attributes = {});
|
||||||
|
if (this.defaults) attributes = _.extend({}, this.defaults, attributes);
|
||||||
|
this.attributes = {};
|
||||||
|
this.cid = _.uniqueId('c');
|
||||||
|
this.set(attributes, {silent : true});
|
||||||
|
this._previousAttributes = _.clone(this.attributes);
|
||||||
|
if (options && options.collection) this.collection = options.collection;
|
||||||
|
this.initialize(attributes, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Attach all inheritable methods to the Model prototype.
|
||||||
|
_.extend(Backbone.Model.prototype, Backbone.Events, {
|
||||||
|
|
||||||
|
// A snapshot of the model's previous attributes, taken immediately
|
||||||
|
// after the last `"change"` event was fired.
|
||||||
|
_previousAttributes : null,
|
||||||
|
|
||||||
|
// Has the item been changed since the last `"change"` event?
|
||||||
|
_changed : false,
|
||||||
|
|
||||||
|
// 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() {
|
||||||
|
return _.clone(this.attributes);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get the value of an attribute.
|
||||||
|
get : function(attr) {
|
||||||
|
return this.attributes[attr];
|
||||||
|
},
|
||||||
|
|
||||||
|
// Set a hash of model attributes on the object, firing `"change"` unless you
|
||||||
|
// choose to silence it.
|
||||||
|
set : function(attrs, options) {
|
||||||
|
|
||||||
|
// Extract attributes and options.
|
||||||
|
options || (options = {});
|
||||||
|
if (!attrs) return this;
|
||||||
|
if (attrs.attributes) attrs = attrs.attributes;
|
||||||
|
var now = this.attributes;
|
||||||
|
|
||||||
|
// Run validation.
|
||||||
|
if (!options.silent && this.validate && !this._performValidation(attrs, options)) return false;
|
||||||
|
|
||||||
|
// Check for changes of `id`.
|
||||||
|
if ('id' in attrs) this.id = attrs.id;
|
||||||
|
|
||||||
|
// Update attributes.
|
||||||
|
for (var attr in attrs) {
|
||||||
|
var val = attrs[attr];
|
||||||
|
if (!_.isEqual(now[attr], val)) {
|
||||||
|
now[attr] = val;
|
||||||
|
if (!options.silent) {
|
||||||
|
this._changed = true;
|
||||||
|
this.trigger('change:' + attr, this, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire the `"change"` event, if the model has been changed.
|
||||||
|
if (!options.silent && this._changed) this.change();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Remove an attribute from the model, firing `"change"` unless you choose
|
||||||
|
// to silence it.
|
||||||
|
unset : function(attr, options) {
|
||||||
|
options || (options = {});
|
||||||
|
var value = this.attributes[attr];
|
||||||
|
|
||||||
|
// Run validation.
|
||||||
|
var validObj = {};
|
||||||
|
validObj[attr] = void 0;
|
||||||
|
if (!options.silent && this.validate && !this._performValidation(validObj, options)) return false;
|
||||||
|
|
||||||
|
// Remove the attribute.
|
||||||
|
delete this.attributes[attr];
|
||||||
|
if (!options.silent) {
|
||||||
|
this._changed = true;
|
||||||
|
this.trigger('change:' + attr, this);
|
||||||
|
this.change();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Clear all attributes on the model, firing `"change"` unless you choose
|
||||||
|
// to silence it.
|
||||||
|
clear : function(options) {
|
||||||
|
options || (options = {});
|
||||||
|
var old = this.attributes;
|
||||||
|
|
||||||
|
// Run validation.
|
||||||
|
var validObj = {};
|
||||||
|
for (attr in old) validObj[attr] = void 0;
|
||||||
|
if (!options.silent && this.validate && !this._performValidation(validObj, options)) return false;
|
||||||
|
|
||||||
|
this.attributes = {};
|
||||||
|
if (!options.silent) {
|
||||||
|
this._changed = true;
|
||||||
|
for (attr in old) {
|
||||||
|
this.trigger('change:' + attr, this);
|
||||||
|
}
|
||||||
|
this.change();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 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 = {});
|
||||||
|
var model = this;
|
||||||
|
var success = function(resp) {
|
||||||
|
if (!model.set(model.parse(resp), options)) return false;
|
||||||
|
if (options.success) options.success(model, resp);
|
||||||
|
};
|
||||||
|
var error = options.error && _.bind(options.error, null, model);
|
||||||
|
(this.sync || Backbone.sync)('read', this, success, error);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 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(attrs, options) {
|
||||||
|
options || (options = {});
|
||||||
|
if (attrs && !this.set(attrs, options)) return false;
|
||||||
|
var model = this;
|
||||||
|
var success = function(resp) {
|
||||||
|
if (!model.set(model.parse(resp), options)) return false;
|
||||||
|
if (options.success) options.success(model, resp);
|
||||||
|
};
|
||||||
|
var error = options.error && _.bind(options.error, null, model);
|
||||||
|
var method = this.isNew() ? 'create' : 'update';
|
||||||
|
(this.sync || Backbone.sync)(method, this, success, error);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Destroy this model on the server. Upon success, the model is removed
|
||||||
|
// from its collection, if it has one.
|
||||||
|
destroy : function(options) {
|
||||||
|
options || (options = {});
|
||||||
|
var model = this;
|
||||||
|
var success = function(resp) {
|
||||||
|
if (model.collection) model.collection.remove(model);
|
||||||
|
if (options.success) options.success(model, resp);
|
||||||
|
};
|
||||||
|
var error = options.error && _.bind(options.error, null, model);
|
||||||
|
(this.sync || Backbone.sync)('delete', this, success, error);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 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 = getUrl(this.collection);
|
||||||
|
if (this.isNew()) return base;
|
||||||
|
return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + 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) {
|
||||||
|
return resp;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Create a new model with identical attributes to this one.
|
||||||
|
clone : function() {
|
||||||
|
return new this.constructor(this);
|
||||||
|
},
|
||||||
|
|
||||||
|
// A model is new if it has never been saved to the server, and has a negative
|
||||||
|
// ID.
|
||||||
|
isNew : function() {
|
||||||
|
return !this.id;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Call this method to manually fire a `change` event for this model.
|
||||||
|
// Calling this will cause all objects observing the model to update.
|
||||||
|
change : function() {
|
||||||
|
this.trigger('change', this);
|
||||||
|
this._previousAttributes = _.clone(this.attributes);
|
||||||
|
this._changed = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 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 (attr) return this._previousAttributes[attr] != this.attributes[attr];
|
||||||
|
return this._changed;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
changedAttributes : function(now) {
|
||||||
|
now || (now = this.attributes);
|
||||||
|
var old = this._previousAttributes;
|
||||||
|
var changed = false;
|
||||||
|
for (var attr in now) {
|
||||||
|
if (!_.isEqual(old[attr], now[attr])) {
|
||||||
|
changed = changed || {};
|
||||||
|
changed[attr] = now[attr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get the previous value of an attribute, recorded at the time the last
|
||||||
|
// `"change"` event was fired.
|
||||||
|
previous : function(attr) {
|
||||||
|
if (!attr || !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);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Run validation against a set of incoming attributes, returning `true`
|
||||||
|
// if all is well. If a specific `error` callback has been passed,
|
||||||
|
// call that instead of firing the general `"error"` event.
|
||||||
|
_performValidation : function(attrs, options) {
|
||||||
|
var error = this.validate(attrs);
|
||||||
|
if (error) {
|
||||||
|
if (options.error) {
|
||||||
|
options.error(this, error);
|
||||||
|
} else {
|
||||||
|
this.trigger('error', this, error);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
Backbone.Collection = function(models, options) {
|
||||||
|
options || (options = {});
|
||||||
|
if (options.comparator) {
|
||||||
|
this.comparator = options.comparator;
|
||||||
|
delete options.comparator;
|
||||||
|
}
|
||||||
|
this._boundOnModelEvent = _.bind(this._onModelEvent, this);
|
||||||
|
this._reset();
|
||||||
|
if (models) this.refresh(models, {silent: true});
|
||||||
|
this.initialize(models, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define the Collection's inheritable methods.
|
||||||
|
_.extend(Backbone.Collection.prototype, Backbone.Events, {
|
||||||
|
|
||||||
|
// The default model for a collection is just a **Backbone.Model**.
|
||||||
|
// This should be overridden in most cases.
|
||||||
|
model : Backbone.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() {
|
||||||
|
return this.map(function(model){ return model.toJSON(); });
|
||||||
|
},
|
||||||
|
|
||||||
|
// Add a model, or list of models to the set. Pass **silent** to avoid
|
||||||
|
// firing the `added` event for every new model.
|
||||||
|
add : function(models, options) {
|
||||||
|
if (_.isArray(models)) {
|
||||||
|
for (var i = 0, l = models.length; i < l; i++) {
|
||||||
|
this._add(models[i], options);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this._add(models, options);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Remove a model, or a list of models from the set. Pass silent to avoid
|
||||||
|
// firing the `removed` event for every model removed.
|
||||||
|
remove : function(models, options) {
|
||||||
|
if (_.isArray(models)) {
|
||||||
|
for (var i = 0, l = models.length; i < l; i++) {
|
||||||
|
this._remove(models[i], options);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this._remove(models, options);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get a model from the set by id.
|
||||||
|
get : function(id) {
|
||||||
|
if (id == null) return null;
|
||||||
|
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];
|
||||||
|
},
|
||||||
|
|
||||||
|
// 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');
|
||||||
|
this.models = this.sortBy(this.comparator);
|
||||||
|
if (!options.silent) this.trigger('refresh', this);
|
||||||
|
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 refresh the entire set with a new list of models, without firing
|
||||||
|
// any `added` or `removed` events. Fires `refresh` when finished.
|
||||||
|
refresh : function(models, options) {
|
||||||
|
models || (models = []);
|
||||||
|
options || (options = {});
|
||||||
|
this._reset();
|
||||||
|
this.add(models, {silent: true});
|
||||||
|
if (!options.silent) this.trigger('refresh', this);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Fetch the default set of models for this collection, refreshing the
|
||||||
|
// collection when they arrive.
|
||||||
|
fetch : function(options) {
|
||||||
|
options || (options = {});
|
||||||
|
var collection = this;
|
||||||
|
var success = function(resp) {
|
||||||
|
collection.refresh(collection.parse(resp));
|
||||||
|
if (options.success) options.success(collection, resp);
|
||||||
|
};
|
||||||
|
var error = options.error && _.bind(options.error, null, collection);
|
||||||
|
(this.sync || Backbone.sync)('read', this, success, error);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Create a new instance of a model in this collection. After the model
|
||||||
|
// has been created on the server, it will be added to the collection.
|
||||||
|
create : function(model, options) {
|
||||||
|
var coll = this;
|
||||||
|
options || (options = {});
|
||||||
|
if (!(model instanceof Backbone.Model)) {
|
||||||
|
model = new this.model(model, {collection: coll});
|
||||||
|
} else {
|
||||||
|
model.collection = coll;
|
||||||
|
}
|
||||||
|
var success = function(nextModel, resp) {
|
||||||
|
coll.add(nextModel);
|
||||||
|
if (options.success) options.success(nextModel, resp);
|
||||||
|
};
|
||||||
|
return model.save(null, {success : success, error : options.error});
|
||||||
|
},
|
||||||
|
|
||||||
|
// **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) {
|
||||||
|
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 refreshed.
|
||||||
|
_reset : function(options) {
|
||||||
|
this.length = 0;
|
||||||
|
this.models = [];
|
||||||
|
this._byId = {};
|
||||||
|
this._byCid = {};
|
||||||
|
},
|
||||||
|
|
||||||
|
// Internal implementation of adding a single model to the set, updating
|
||||||
|
// hash indexes for `id` and `cid` lookups.
|
||||||
|
_add : function(model, options) {
|
||||||
|
options || (options = {});
|
||||||
|
if (!(model instanceof Backbone.Model)) {
|
||||||
|
model = new this.model(model, {collection: this});
|
||||||
|
}
|
||||||
|
var already = this.getByCid(model);
|
||||||
|
if (already) throw new Error(["Can't add the same model to a set twice", already.id]);
|
||||||
|
this._byId[model.id] = model;
|
||||||
|
this._byCid[model.cid] = model;
|
||||||
|
model.collection = this;
|
||||||
|
var index = this.comparator ? this.sortedIndex(model, this.comparator) : this.length;
|
||||||
|
this.models.splice(index, 0, model);
|
||||||
|
model.bind('all', this._boundOnModelEvent);
|
||||||
|
this.length++;
|
||||||
|
if (!options.silent) model.trigger('add', model, this);
|
||||||
|
return model;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Internal implementation of removing a single model from the set, updating
|
||||||
|
// hash indexes for `id` and `cid` lookups.
|
||||||
|
_remove : function(model, options) {
|
||||||
|
options || (options = {});
|
||||||
|
model = this.getByCid(model) || this.get(model);
|
||||||
|
if (!model) return null;
|
||||||
|
delete this._byId[model.id];
|
||||||
|
delete this._byCid[model.cid];
|
||||||
|
delete model.collection;
|
||||||
|
this.models.splice(this.indexOf(model), 1);
|
||||||
|
this.length--;
|
||||||
|
if (!options.silent) model.trigger('remove', model, this);
|
||||||
|
model.unbind('all', this._boundOnModelEvent);
|
||||||
|
return model;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
_onModelEvent : function(ev, model) {
|
||||||
|
if (ev === 'change:id') {
|
||||||
|
delete this._byId[model.previous('id')];
|
||||||
|
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',
|
||||||
|
'invoke', 'max', 'min', 'sortBy', 'sortedIndex', 'toArray', 'size',
|
||||||
|
'first', 'rest', 'last', 'without', 'indexOf', 'lastIndexOf', 'isEmpty'];
|
||||||
|
|
||||||
|
// Mix in each Underscore method as a proxy to `Collection#models`.
|
||||||
|
_.each(methods, function(method) {
|
||||||
|
Backbone.Collection.prototype[method] = function() {
|
||||||
|
return _[method].apply(_, [this.models].concat(_.toArray(arguments)));
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Backbone.Controller
|
||||||
|
// -------------------
|
||||||
|
|
||||||
|
// Controllers map faux-URLs to actions, and fire events when routes are
|
||||||
|
// matched. Creating a new one sets its `routes` hash, if not set statically.
|
||||||
|
Backbone.Controller = function(options) {
|
||||||
|
options || (options = {});
|
||||||
|
if (options.routes) this.routes = options.routes;
|
||||||
|
this._bindRoutes();
|
||||||
|
this.initialize(options);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cached regular expressions for matching named param parts and splatted
|
||||||
|
// parts of route strings.
|
||||||
|
var namedParam = /:([\w\d]+)/g;
|
||||||
|
var splatParam = /\*([\w\d]+)/g;
|
||||||
|
|
||||||
|
// Set up all inheritable **Backbone.Controller** properties and methods.
|
||||||
|
_.extend(Backbone.Controller.prototype, Backbone.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 Backbone.History);
|
||||||
|
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
|
||||||
|
Backbone.history.route(route, _.bind(function(fragment) {
|
||||||
|
var args = this._extractParameters(route, fragment);
|
||||||
|
callback.apply(this, args);
|
||||||
|
this.trigger.apply(this, ['route:' + name].concat(args));
|
||||||
|
}, this));
|
||||||
|
},
|
||||||
|
|
||||||
|
// Simple proxy to `Backbone.history` to save a fragment into the history,
|
||||||
|
// without triggering routes.
|
||||||
|
saveLocation : function(fragment) {
|
||||||
|
Backbone.history.saveLocation(fragment);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Bind all defined routes to `Backbone.history`.
|
||||||
|
_bindRoutes : function() {
|
||||||
|
if (!this.routes) return;
|
||||||
|
for (var route in this.routes) {
|
||||||
|
var name = this.routes[route];
|
||||||
|
this.route(route, name, this[name]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Convert a route string into a regular expression, suitable for matching
|
||||||
|
// against the current location fragment.
|
||||||
|
_routeToRegExp : function(route) {
|
||||||
|
route = route.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 hashes. If the
|
||||||
|
// browser does not support `onhashchange`, falls back to polling.
|
||||||
|
Backbone.History = function() {
|
||||||
|
this.handlers = [];
|
||||||
|
this.fragment = this.getFragment();
|
||||||
|
_.bindAll(this, 'checkUrl');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cached regex for cleaning hashes.
|
||||||
|
var hashStrip = /^#*/;
|
||||||
|
|
||||||
|
// Set up all inheritable **Backbone.History** properties and methods.
|
||||||
|
_.extend(Backbone.History.prototype, {
|
||||||
|
|
||||||
|
// The default interval to poll for hash changes, if necessary, is
|
||||||
|
// twenty times a second.
|
||||||
|
interval: 50,
|
||||||
|
|
||||||
|
// Get the cross-browser normalized URL fragment.
|
||||||
|
getFragment : function(loc) {
|
||||||
|
var frag = (loc || window.location).hash.replace(hashStrip, '');
|
||||||
|
return frag;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Start the hash change handling, returning `true` if the current URL matches
|
||||||
|
// an existing route, and `false` otherwise.
|
||||||
|
start : function() {
|
||||||
|
var docMode = document.documentMode;
|
||||||
|
var oldIE = ($.browser.msie && (!docMode || docMode <= 7));
|
||||||
|
if (oldIE) {
|
||||||
|
this.iframe = $('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow;
|
||||||
|
}
|
||||||
|
if ('onhashchange' in window && !oldIE) {
|
||||||
|
$(window).bind('hashchange', this.checkUrl);
|
||||||
|
} else {
|
||||||
|
setInterval(this.checkUrl, this.interval);
|
||||||
|
}
|
||||||
|
return this.loadUrl();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Add a route to be tested when the hash changes. Routes are matched in the
|
||||||
|
// order they are added.
|
||||||
|
route : function(route, callback) {
|
||||||
|
this.handlers.push({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() {
|
||||||
|
var current = this.getFragment();
|
||||||
|
if (current == this.fragment && this.iframe) {
|
||||||
|
current = this.getFragment(this.iframe.location);
|
||||||
|
}
|
||||||
|
if (current == this.fragment ||
|
||||||
|
current == decodeURIComponent(this.fragment)) return false;
|
||||||
|
if (this.iframe) {
|
||||||
|
window.location.hash = this.iframe.location.hash = current;
|
||||||
|
}
|
||||||
|
this.loadUrl();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 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() {
|
||||||
|
var fragment = this.fragment = this.getFragment();
|
||||||
|
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. You are responsible for properly
|
||||||
|
// URL-encoding the fragment in advance. This does not trigger
|
||||||
|
// a `hashchange` event.
|
||||||
|
saveLocation : function(fragment) {
|
||||||
|
fragment = (fragment || '').replace(hashStrip, '');
|
||||||
|
if (this.fragment == fragment) return;
|
||||||
|
window.location.hash = this.fragment = fragment;
|
||||||
|
if (this.iframe && (fragment != this.getFragment(this.iframe.location))) {
|
||||||
|
this.iframe.document.open().close();
|
||||||
|
this.iframe.location.hash = fragment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Backbone.View
|
||||||
|
// -------------
|
||||||
|
|
||||||
|
// Creating a Backbone.View creates its initial element outside of the DOM,
|
||||||
|
// if an existing element is not provided...
|
||||||
|
Backbone.View = function(options) {
|
||||||
|
this._configure(options || {});
|
||||||
|
this._ensureElement();
|
||||||
|
this.delegateEvents();
|
||||||
|
this.initialize(options);
|
||||||
|
};
|
||||||
|
|
||||||
|
// jQuery lookup, scoped to DOM elements within the current view.
|
||||||
|
// This should be prefered to global jQuery lookups, if you're dealing with
|
||||||
|
// a specific view.
|
||||||
|
var jQueryDelegate = function(selector) {
|
||||||
|
return $(selector, this.el);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cached regex to split keys for `delegate`.
|
||||||
|
var eventSplitter = /^(\w+)\s*(.*)$/;
|
||||||
|
|
||||||
|
// Set up all inheritable **Backbone.View** properties and methods.
|
||||||
|
_.extend(Backbone.View.prototype, Backbone.Events, {
|
||||||
|
|
||||||
|
// The default `tagName` of a View's element is `"div"`.
|
||||||
|
tagName : 'div',
|
||||||
|
|
||||||
|
// Attach the jQuery function as the `$` and `jQuery` properties.
|
||||||
|
$ : jQueryDelegate,
|
||||||
|
jQuery : jQueryDelegate,
|
||||||
|
|
||||||
|
// 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.get('title'));
|
||||||
|
//
|
||||||
|
make : function(tagName, attributes, content) {
|
||||||
|
var el = document.createElement(tagName);
|
||||||
|
if (attributes) $(el).attr(attributes);
|
||||||
|
if (content) $(el).html(content);
|
||||||
|
return el;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Set callbacks, where `this.callbacks` is a hash of
|
||||||
|
//
|
||||||
|
// *{"event selector": "callback"}*
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// 'mousedown .title': 'edit',
|
||||||
|
// 'click .button': 'save'
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// pairs. Callbacks will be bound to the view, with `this` set properly.
|
||||||
|
// Uses jQuery 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 = this.events))) return;
|
||||||
|
$(this.el).unbind();
|
||||||
|
for (var key in events) {
|
||||||
|
var methodName = events[key];
|
||||||
|
var match = key.match(eventSplitter);
|
||||||
|
var eventName = match[1], selector = match[2];
|
||||||
|
var method = _.bind(this[methodName], this);
|
||||||
|
if (selector === '') {
|
||||||
|
$(this.el).bind(eventName, method);
|
||||||
|
} else {
|
||||||
|
$(this.el).delegate(selector, eventName, method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
if (options.model) this.model = options.model;
|
||||||
|
if (options.collection) this.collection = options.collection;
|
||||||
|
if (options.el) this.el = options.el;
|
||||||
|
if (options.id) this.id = options.id;
|
||||||
|
if (options.className) this.className = options.className;
|
||||||
|
if (options.tagName) this.tagName = options.tagName;
|
||||||
|
this.options = options;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Ensure that the View has a DOM element to render into.
|
||||||
|
_ensureElement : function() {
|
||||||
|
if (this.el) return;
|
||||||
|
var attrs = {};
|
||||||
|
if (this.id) attrs.id = this.id;
|
||||||
|
if (this.className) attrs.className = this.className;
|
||||||
|
this.el = this.make(this.tagName, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// The self-propagating extend function that Backbone classes use.
|
||||||
|
var extend = function (protoProps, classProps) {
|
||||||
|
var child = inherits(this, protoProps, classProps);
|
||||||
|
child.extend = extend;
|
||||||
|
return child;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set up inheritance for the model, collection, and view.
|
||||||
|
Backbone.Model.extend = Backbone.Collection.extend =
|
||||||
|
Backbone.Controller.extend = Backbone.View.extend = extend;
|
||||||
|
|
||||||
|
// Map from CRUD to HTTP for our default `Backbone.sync` implementation.
|
||||||
|
var methodMap = {
|
||||||
|
'create': 'POST',
|
||||||
|
'update': 'PUT',
|
||||||
|
'delete': 'DELETE',
|
||||||
|
'read' : 'GET'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Backbone.sync
|
||||||
|
// -------------
|
||||||
|
|
||||||
|
// 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, uses jQuery to make 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, success, error) {
|
||||||
|
var type = methodMap[method];
|
||||||
|
var modelJSON = (method === 'create' || method === 'update') ?
|
||||||
|
JSON.stringify(model.toJSON()) : null;
|
||||||
|
|
||||||
|
// Default JSON-request options.
|
||||||
|
var params = {
|
||||||
|
url: getUrl(model),
|
||||||
|
type: type,
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: modelJSON,
|
||||||
|
dataType: 'json',
|
||||||
|
processData: false,
|
||||||
|
success: success,
|
||||||
|
error: error
|
||||||
|
};
|
||||||
|
|
||||||
|
// For older servers, emulate JSON by encoding the request into an HTML-form.
|
||||||
|
if (Backbone.emulateJSON) {
|
||||||
|
params.contentType = 'application/x-www-form-urlencoded';
|
||||||
|
params.processData = true;
|
||||||
|
params.data = modelJSON ? {model : modelJSON} : {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the request.
|
||||||
|
$.ajax(params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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 `super()`.
|
||||||
|
if (protoProps && protoProps.hasOwnProperty('constructor')) {
|
||||||
|
child = protoProps.constructor;
|
||||||
|
} else {
|
||||||
|
child = function(){ return parent.apply(this, arguments); };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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`, for `instanceof`.
|
||||||
|
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 URL from a Model or Collection as a property
|
||||||
|
// or as a function.
|
||||||
|
var getUrl = function(object) {
|
||||||
|
if (!(object && object.url)) throw new Error("A 'url' property or function must be specified");
|
||||||
|
return _.isFunction(object.url) ? object.url() : object.url;
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,50 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"title": "Unless You Have Been Drinking",
|
||||||
|
"artist": "Adventures in Odyssey",
|
||||||
|
"image": "images/AdventuresInOdyssey_t.jpg",
|
||||||
|
"large_image": "images/AdventuresInOdyssey.jpg",
|
||||||
|
"price": 9.98,
|
||||||
|
"url": "http://www.amazon.com/Door-Religious-Knives/dp/B001FGW0UQ/?tag=quirkey-20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Leave To Do My Utmost",
|
||||||
|
"artist": "American Attorneys",
|
||||||
|
"image": "images/AmericanAttorneys_t.jpg",
|
||||||
|
"large_image": "images/AmericanAttorneys.jpg",
|
||||||
|
"price": 13.98,
|
||||||
|
"url": "http://www.amazon.com/gp/product/B002GNOMJE?ie=UTF8&tag=quirkeycom-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=B002GNOMJE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "The Dead Sleep Encircled by The Living",
|
||||||
|
"artist": "British Civil Light Transport",
|
||||||
|
"image": "images/BritishCivilLightTransport_t.jpg",
|
||||||
|
"large_image": "images/BritishCivilLightTransport.jpg",
|
||||||
|
"price": 13.98,
|
||||||
|
"url": "http://www.amazon.com/Bitte-Orca-Dirty-Projectors/dp/B0026T4RTI/ref=pd_sim_m_12?tag=quirkey-20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Periods of Mental Assimilation",
|
||||||
|
"artist": "Grigory Szondy",
|
||||||
|
"image": "images/PeriodsofMentalAssimilation_t.jpg",
|
||||||
|
"large_image": "images/PeriodsofMentalAssimilation.jpg",
|
||||||
|
"price": 13.99,
|
||||||
|
"url": "http://www.amazon.com/Pains-Being-Pure-Heart/dp/B001LGXIDS/ref=pd_sim_m_44?tag=quirkey-20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Keenly Developed Moral Bankruptcy",
|
||||||
|
"artist": "Stealth Monkey Virus",
|
||||||
|
"image": "images/StealthMonkeyVirus_t.jpg",
|
||||||
|
"large_image": "images/StealthMonkeyVirus.png",
|
||||||
|
"price": 13.99,
|
||||||
|
"url": "http://www.amazon.com/Pains-Being-Pure-Heart/dp/B001LGXIDS/ref=pd_sim_m_44?tag=quirkey-20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "My Mistress's Sparrow is Dead",
|
||||||
|
"artist": "Sums of Mongolia",
|
||||||
|
"image": "images/SumsofMagnolia_t.jpg",
|
||||||
|
"large_image": "images/SumsofMagnolia.jpg",
|
||||||
|
"price": 13.99,
|
||||||
|
"url": "http://www.amazon.com/Pains-Being-Pure-Heart/dp/B001LGXIDS/ref=pd_sim_m_44?tag=quirkey-20"
|
||||||
|
}
|
||||||
|
]
|
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 18 KiB |
|
@ -0,0 +1,69 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
|
<head>
|
||||||
|
<meta name="generator" content="HTML Tidy for Linux/x86 (vers 25 March 2009), see www.w3.org" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
|
||||||
|
<script id="indexTmpl" type="text/x-jquery-tmpl">
|
||||||
|
<div class="item">
|
||||||
|
<div class="item-image">
|
||||||
|
<a href="#item/${cid}"><img src="${attributes.image}" alt="${attributes.title}" /></a>
|
||||||
|
</div>
|
||||||
|
<div class="item-artist">${attributes.artist}</div>
|
||||||
|
<div class="item-title">${attributes.title}</div>
|
||||||
|
<div class="item-price">$${attributes.price}</div>
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="itemTmpl" type="text/x-jquery-tmpl">
|
||||||
|
<div class="item-detail">
|
||||||
|
<div class="item-image"><img src="${attributes.large_image}" alt="${attributes.title}" /></div>
|
||||||
|
<div class="item-info">
|
||||||
|
<div class="item-artist">${attributes.artist}</div>
|
||||||
|
<div class="item-title">${attributes.title}</div>
|
||||||
|
<div class="item-price">$${attributes.price}</div>
|
||||||
|
<div class="item-form">
|
||||||
|
<form action="#/cart" method="post">
|
||||||
|
<input type="hidden" name="item_id" value="${cid}" />
|
||||||
|
<p>
|
||||||
|
<label>Quantity:</label>
|
||||||
|
<input type="text" size="2" name="quantity" value="1" class="uqf" />
|
||||||
|
</p>
|
||||||
|
<p><input type="submit" value="Add to Cart" class="uq" /></p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="item-link"><a href="${attributes.url}">Buy this item on Amazon</a></div>
|
||||||
|
<div class="back-link"><a href="#">« Back to Items</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<title>
|
||||||
|
The Backbone Store
|
||||||
|
</title>
|
||||||
|
<link rel="stylesheet" href="jsonstore.css" type="text/css" media="screen" charset="utf-8" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
<div id="header">
|
||||||
|
<h1>
|
||||||
|
The JSON Store
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div class="cart-info">
|
||||||
|
My Cart (<span class="cart-items">0</span> items)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="jquery-1.4.4.min.js" type="text/javascript"></script>
|
||||||
|
<script src="jquery.tmpl.min.js" type="text/javascript"></script>
|
||||||
|
<script src="underscore.js" type="text/javascript"></script>
|
||||||
|
<script src="backbone.js" type="text/javascript"></script>
|
||||||
|
<script src="backbone-localstorage.js" type="text/javascript"></script>
|
||||||
|
<script src="store.js" type="text/javascript"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,167 @@
|
||||||
|
/*!
|
||||||
|
* jQuery JavaScript Library v1.4.4
|
||||||
|
* http://jquery.com/
|
||||||
|
*
|
||||||
|
* Copyright 2010, John Resig
|
||||||
|
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||||
|
* http://jquery.org/license
|
||||||
|
*
|
||||||
|
* Includes Sizzle.js
|
||||||
|
* http://sizzlejs.com/
|
||||||
|
* Copyright 2010, The Dojo Foundation
|
||||||
|
* Released under the MIT, BSD, and GPL Licenses.
|
||||||
|
*
|
||||||
|
* Date: Thu Nov 11 19:04:53 2010 -0500
|
||||||
|
*/
|
||||||
|
(function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d=a.getAttribute("data-"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false"?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}function U(){return false}function ca(){return true}function la(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this.nodeType?"events":"__events__");if(typeof h==="function")h=
|
||||||
|
h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.type==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var J=h.live.slice(0);for(k=0;k<J.length;k++){h=J[k];h.origType.replace(X,"")===a.type?f.push(h.selector):J.splice(k--,1)}f=c(a.target).closest(f,a.currentTarget);o=0;for(x=f.length;o<x;o++){r=f[o];for(k=0;k<J.length;k++){h=J[k];if(r.selector===h.selector&&(!A||A.test(h.namespace))){l=r.elem;e=null;if(h.preType==="mouseenter"||
|
||||||
|
h.preType==="mouseleave"){a.type=h.preType;e=c(a.relatedTarget).closest(h.selector)[0]}if(!e||e!==l)C.push({elem:l,handleObj:h,level:r.level})}}}o=0;for(x=C.length;o<x;o++){f=C[o];if(d&&f.level>d)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La,
|
||||||
|
"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this,
|
||||||
|
e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a,
|
||||||
|
"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+
|
||||||
|
a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,
|
||||||
|
C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j,
|
||||||
|
s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this,
|
||||||
|
j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length},
|
||||||
|
toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j===
|
||||||
|
-1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false;
|
||||||
|
if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K<Q;K++)if((j=arguments[K])!=null)for(s in j){v=G[s];z=j[s];if(G!==z)if(ga&&z&&(b.isPlainObject(z)||(H=b.isArray(z)))){if(H){H=false;v=v&&b.isArray(v)?v:[]}else v=v&&b.isPlainObject(v)?v:{};G[s]=b.extend(ga,v,z)}else if(z!==B)G[s]=z}return G};b.extend({noConflict:function(j){E.$=e;if(j)E.jQuery=d;return b},isReady:false,readyWait:1,ready:function(j){j===true&&b.readyWait--;
|
||||||
|
if(!b.readyWait||j!==true&&!b.isReady){if(!t.body)return setTimeout(b.ready,1);b.isReady=true;if(!(j!==true&&--b.readyWait>0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload",
|
||||||
|
b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&&
|
||||||
|
!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&&
|
||||||
|
l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;H<G;){if(s.apply(j[H++],v)===false)break}else if(K)for(z in j){if(s.call(j[z],
|
||||||
|
z,j[z])===false)break}else for(v=j[0];H<G&&s.call(v,H,v)!==false;v=j[++H]);return j},trim:O?function(j){return j==null?"":O.call(j)}:function(j){return j==null?"":j.toString().replace(k,"").replace(o,"")},makeArray:function(j,s){var v=s||[];if(j!=null){var z=b.type(j);j.length==null||z==="string"||z==="function"||z==="regexp"||b.isWindow(j)?M.call(v,j):b.merge(v,j)}return v},inArray:function(j,s){if(s.indexOf)return s.indexOf(j);for(var v=0,z=s.length;v<z;v++)if(s[v]===j)return v;return-1},merge:function(j,
|
||||||
|
s){var v=j.length,z=0;if(typeof s.length==="number")for(var H=s.length;z<H;z++)j[v++]=s[z];else for(;s[z]!==B;)j[v++]=s[z++];j.length=v;return j},grep:function(j,s,v){var z=[],H;v=!!v;for(var G=0,K=j.length;G<K;G++){H=!!s(j[G],G);v!==H&&z.push(j[G])}return z},map:function(j,s,v){for(var z=[],H,G=0,K=j.length;G<K;G++){H=s(j[G],G,v);if(H!=null)z[z.length]=H}return z.concat.apply([],z)},guid:1,proxy:function(j,s,v){if(arguments.length===2)if(typeof s==="string"){v=j;j=v[s];s=B}else if(s&&!b.isFunction(s)){v=
|
||||||
|
s;s=B}if(!s&&j)s=function(){return j.apply(v||this,arguments)};if(j)s.guid=j.guid=j.guid||s.guid||b.guid++;return s},access:function(j,s,v,z,H,G){var K=j.length;if(typeof s==="object"){for(var Q in s)b.access(j,Q,s[Q],z,H,v);return j}if(v!==B){z=!G&&z&&b.isFunction(v);for(Q=0;Q<K;Q++)H(j[Q],s,z?v.call(j[Q],Q,H(j[Q],s)):v,G);return j}return K?H(j[0],s):B},now:function(){return(new Date).getTime()},uaMatch:function(j){j=j.toLowerCase();j=L.exec(j)||g.exec(j)||i.exec(j)||j.indexOf("compatible")<0&&n.exec(j)||
|
||||||
|
[];return{browser:j[1]||"",version:j[2]||"0"}},browser:{}});b.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(j,s){R["[object "+s+"]"]=s.toLowerCase()});m=b.uaMatch(m);if(m.browser){b.browser[m.browser]=true;b.browser.version=m.version}if(b.browser.webkit)b.browser.safari=true;if(D)b.inArray=function(j,s){return D.call(s,j)};if(!/\s/.test("\u00a0")){k=/^[\s\xA0]+/;o=/[\s\xA0]+$/}f=b(t);if(t.addEventListener)u=function(){t.removeEventListener("DOMContentLoaded",u,
|
||||||
|
false);b.ready()};else if(t.attachEvent)u=function(){if(t.readyState==="complete"){t.detachEvent("onreadystatechange",u);b.ready()}};return E.jQuery=E.$=b}();(function(){c.support={};var a=t.documentElement,b=t.createElement("script"),d=t.createElement("div"),e="script"+c.now();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"),
|
||||||
|
k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false,
|
||||||
|
scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent=
|
||||||
|
false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom=
|
||||||
|
1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="<div style='width:4px;'></div>";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display=
|
||||||
|
"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h=
|
||||||
|
c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando);
|
||||||
|
else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h<l;h++){f=e[h].name;if(f.indexOf("data-")===0){f=f.substr(5);ka(this[0],f,d[f])}}}return d}else if(typeof a==="object")return this.each(function(){c.data(this,
|
||||||
|
a)});var k=a.split(".");k[1]=k[1]?"."+k[1]:"";if(b===B){d=this.triggerHandler("getData"+k[1]+"!",[k[0]]);if(d===B&&this.length){d=c.data(this[0],a);d=ka(this[0],a,d)}return d===B&&k[1]?this.data(k[0]):d}else return this.each(function(){var o=c(this),x=[k[0],b];o.triggerHandler("setData"+k[1]+"!",x);c.data(this,a,b);o.triggerHandler("changeData"+k[1]+"!",x)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var e=
|
||||||
|
c.data(a,b);if(!d)return e||[];if(!e||c.isArray(d))e=c.data(a,b,c.makeArray(d));else e.push(d);return e}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),e=d.shift();if(e==="inprogress")e=d.shift();if(e){b==="fx"&&d.unshift("inprogress");e.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===B)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,
|
||||||
|
a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var sa=/[\n\t]/g,ha=/\s+/,Sa=/\r/g,Ta=/^(?:href|src|style)$/,Ua=/^(?:button|input)$/i,Va=/^(?:button|input|object|select|textarea)$/i,Wa=/^a(?:rea)?$/i,ta=/^(?:radio|checkbox)$/i;c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",
|
||||||
|
colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};c.fn.extend({attr:function(a,b){return c.access(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(x){var r=c(this);r.addClass(a.call(this,x,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType===
|
||||||
|
1)if(f.className){for(var h=" "+f.className+" ",l=f.className,k=0,o=b.length;k<o;k++)if(h.indexOf(" "+b[k]+" ")<0)l+=" "+b[k];f.className=c.trim(l)}else f.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(o){var x=c(this);x.removeClass(a.call(this,o,x.attr("class")))});if(a&&typeof a==="string"||a===B)for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType===1&&f.className)if(a){for(var h=(" "+f.className+" ").replace(sa," "),
|
||||||
|
l=0,k=b.length;l<k;l++)h=h.replace(" "+b[l]+" "," ");f.className=c.trim(h)}else f.className=""}return this},toggleClass:function(a,b){var d=typeof a,e=typeof b==="boolean";if(c.isFunction(a))return this.each(function(f){var h=c(this);h.toggleClass(a.call(this,f,h.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var f,h=0,l=c(this),k=b,o=a.split(ha);f=o[h++];){k=e?k:!l.hasClass(f);l[k?"addClass":"removeClass"](f)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,
|
||||||
|
"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(sa," ").indexOf(a)>-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one";
|
||||||
|
if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h<e;h++){var l=f[h];if(l.selected&&(c.support.optDisabled?!l.disabled:l.getAttribute("disabled")===null)&&(!l.parentNode.disabled||!c.nodeName(l.parentNode,"optgroup"))){a=c(l).val();if(b)return a;d.push(a)}}return d}if(ta.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Sa,"")}return B}var k=c.isFunction(a);return this.each(function(o){var x=c(this),r=a;if(this.nodeType===1){if(k)r=
|
||||||
|
a.call(this,o,x.val());if(r==null)r="";else if(typeof r==="number")r+="";else if(c.isArray(r))r=c.map(r,function(C){return C==null?"":C+""});if(c.isArray(r)&&ta.test(this.type))this.checked=c.inArray(x.val(),r)>=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},
|
||||||
|
attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&
|
||||||
|
b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0};
|
||||||
|
c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,
|
||||||
|
arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid=
|
||||||
|
d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+
|
||||||
|
c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h<A.length;h++){C=A[h];if(d.guid===C.guid){if(k||x.test(C.namespace)){e==null&&A.splice(h--,1);r.remove&&r.remove.call(a,C)}if(e!=null)break}}if(A.length===0||e!=null&&A.length===1){if(!r.teardown||r.teardown.call(a,o)===false)c.removeEvent(a,f,w.handle);delete I[f]}}else for(h=0;h<A.length;h++){C=A[h];if(k||x.test(C.namespace)){c.event.remove(a,r,C.handler,h);A.splice(h--,1)}}}if(c.isEmptyObject(I)){if(b=
|
||||||
|
w.handle)b.elem=null;delete w.events;delete w.handle;if(typeof w==="function")c.removeData(a,J);else c.isEmptyObject(w)&&c.removeData(a)}}}}},trigger:function(a,b,d,e){var f=a.type||a;if(!e){a=typeof a==="object"?a[c.expando]?a:c.extend(c.Event(f),a):c.Event(f);if(f.indexOf("!")>=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===
|
||||||
|
8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k===
|
||||||
|
"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+
|
||||||
|
d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f<l;f++){var k=d[f];if(b||e.test(k.namespace)){a.handler=k.handler;a.data=k.data;a.handleObj=k;k=k.handler.apply(this,h);if(k!==B){a.result=k;if(k===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
|
||||||
|
fix:function(a){if(a[c.expando])return a;var b=a;a=c.Event(b);for(var d=this.props.length,e;d;){e=this.props[--d];a[e]=b[e]}if(!a.target)a.target=a.srcElement||t;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=t.documentElement;d=t.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
|
||||||
|
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(a.which==null&&(a.charCode!=null||a.keyCode!=null))a.which=a.charCode!=null?a.charCode:a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==B)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,Y(a.origType,a.selector),c.extend({},a,{handler:Ka,guid:a.handler.guid}))},remove:function(a){c.event.remove(this,
|
||||||
|
Y(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,d){if(c.isWindow(this))this.onbeforeunload=d},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.removeEvent=t.removeEventListener?function(a,b,d){a.removeEventListener&&a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent&&a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=
|
||||||
|
c.now();this[c.expando]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=ca;var a=this.originalEvent;if(a)if(a.preventDefault)a.preventDefault();else a.returnValue=false},stopPropagation:function(){this.isPropagationStopped=ca;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=ca;this.stopPropagation()},isDefaultPrevented:U,isPropagationStopped:U,isImmediatePropagationStopped:U};
|
||||||
|
var va=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},wa=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?wa:va,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?wa:va)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(){if(this.nodeName.toLowerCase()!==
|
||||||
|
"form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length){a.liveFired=B;return la("submit",this,arguments)}});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13){a.liveFired=B;return la("submit",this,arguments)}})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};if(!c.support.changeBubbles){var V,
|
||||||
|
xa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired=
|
||||||
|
B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type===
|
||||||
|
"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]===
|
||||||
|
0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h<k;h++)c.event.add(this[h],d,l,e)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&!a.preventDefault)for(var d in a)this.unbind(d,
|
||||||
|
a[d]);else{d=0;for(var e=this.length;d<e;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,e){return this.live(b,d,e,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){var d=c.Event(a);d.preventDefault();d.stopPropagation();c.event.trigger(d,b,this[0]);return d.result}},toggle:function(a){for(var b=arguments,d=
|
||||||
|
1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(e){var f=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,f+1);e.preventDefault();return b[f].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var ya={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,e,f,h){var l,k=0,o,x,r=h||this.selector;h=h?this:c(this.context);if(typeof d===
|
||||||
|
"object"&&!d.preventDefault){for(l in d)h[b](l,e,d[l],r);return this}if(c.isFunction(e)){f=e;e=B}for(d=(d||"").split(" ");(l=d[k++])!=null;){o=X.exec(l);x="";if(o){x=o[0];l=l.replace(X,"")}if(l==="hover")d.push("mouseenter"+x,"mouseleave"+x);else{o=l;if(l==="focus"||l==="blur"){d.push(ya[l]+x);l+=x}else l=(ya[l]||l)+x;if(b==="live"){x=0;for(var A=h.length;x<A;x++)c.event.add(h[x],"live."+Y(l,r),{data:e,selector:r,handler:f,origType:l,origHandler:f,preType:o})}else h.unbind("live."+Y(l,r),f)}}return this}});
|
||||||
|
c.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".split(" "),function(a,b){c.fn[b]=function(d,e){if(e==null){e=d;d=null}return arguments.length>0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});
|
||||||
|
(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1&&!q){y.sizcache=n;y.sizset=p}if(y.nodeName.toLowerCase()===i){F=y;break}y=y[g]}m[p]=F}}}function b(g,i,n,m,p,q){p=0;for(var u=m.length;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1){if(!q){y.sizcache=n;y.sizset=p}if(typeof i!=="string"){if(y===i){F=true;break}}else if(k.filter(i,
|
||||||
|
[y]).length>0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3];
|
||||||
|
break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr,
|
||||||
|
q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h=
|
||||||
|
l;g.sort(w);if(h)for(var i=1;i<g.length;i++)g[i]===g[i-1]&&g.splice(i--,1)}return g};k.matches=function(g,i){return k(g,null,null,i)};k.matchesSelector=function(g,i){return k(i,null,null,[g]).length>0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p<q;p++){var u,y=o.order[p];if(u=o.leftMatch[y].exec(g)){var F=u[1];u.splice(1,1);if(F.substr(F.length-1)!=="\\"){u[1]=(u[1]||"").replace(/\\/g,"");m=o.find[y](u,i,n);if(m!=null){g=g.replace(o.match[y],"");break}}}}m||(m=i.getElementsByTagName("*"));
|
||||||
|
return{set:m,expr:g}};k.filter=function(g,i,n,m){for(var p,q,u=g,y=[],F=i,M=i&&i[0]&&k.isXML(i[0]);g&&i.length;){for(var N in o.filter)if((p=o.leftMatch[N].exec(g))!=null&&p[2]){var O,D,R=o.filter[N];D=p[1];q=false;p.splice(1,1);if(D.substr(D.length-1)!=="\\"){if(F===y)y=[];if(o.preFilter[N])if(p=o.preFilter[N](p,F,n,y,m,M)){if(p===true)continue}else q=O=true;if(p)for(var j=0;(D=F[j])!=null;j++)if(D){O=R(D,p,j,F);var s=m^!!O;if(n&&O!=null)if(s)q=true;else F[j]=false;else if(s){y.push(D);q=true}}if(O!==
|
||||||
|
B){n||(F=y);g=g.replace(o.match[N],"");if(!q)return[];break}}}if(g===u)if(q==null)k.error(g);else break;u=g}return F};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var o=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,
|
||||||
|
POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},relative:{"+":function(g,i){var n=typeof i==="string",m=n&&!/\W/.test(i);n=n&&!m;if(m)i=i.toLowerCase();m=0;for(var p=g.length,q;m<p;m++)if(q=g[m]){for(;(q=q.previousSibling)&&q.nodeType!==1;);g[m]=n||q&&q.nodeName.toLowerCase()===
|
||||||
|
i?q||false:q===i}n&&k.filter(i,g,true)},">":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p<q;p++){if(n=g[p]){n=n.parentNode;g[p]=n.nodeName.toLowerCase()===i?n:false}}else{for(;p<q;p++)if(n=g[p])g[p]=m?n.parentNode:n.parentNode===i;m&&k.filter(i,g,true)}},"":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m=i=i.toLowerCase();q=a}q("parentNode",i,p,g,m,n)},"~":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m=
|
||||||
|
i=i.toLowerCase();q=a}q("previousSibling",i,p,g,m,n)}},find:{ID:function(g,i,n){if(typeof i.getElementById!=="undefined"&&!n)return(g=i.getElementById(g[1]))&&g.parentNode?[g]:[]},NAME:function(g,i){if(typeof i.getElementsByName!=="undefined"){for(var n=[],m=i.getElementsByName(g[1]),p=0,q=m.length;p<q;p++)m[p].getAttribute("name")===g[1]&&n.push(m[p]);return n.length===0?null:n}},TAG:function(g,i){return i.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,i,n,m,p,q){g=" "+g[1].replace(/\\/g,
|
||||||
|
"")+" ";if(q)return g;q=0;for(var u;(u=i[q])!=null;q++)if(u)if(p^(u.className&&(" "+u.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n,
|
||||||
|
m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===
|
||||||
|
true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===
|
||||||
|
g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return i<n[3]-0},gt:function(g,i,n){return i>n[3]-0},nth:function(g,i,n){return n[3]-
|
||||||
|
0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n<m;n++)if(i[n]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+p)},CHILD:function(g,i){var n=i[1],m=g;switch(n){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(n===
|
||||||
|
"first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":n=i[2];var p=i[3];if(n===1&&p===0)return true;var q=i[0],u=g.parentNode;if(u&&(u.sizcache!==q||!g.nodeIndex)){var y=0;for(m=u.firstChild;m;m=m.nextSibling)if(m.nodeType===1)m.nodeIndex=++y;u.sizcache=q}m=g.nodeIndex-p;return n===0?m===0:m%n===0&&m/n>=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===
|
||||||
|
i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]];
|
||||||
|
if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m,
|
||||||
|
g);else if(typeof g.length==="number")for(var p=g.length;n<p;n++)m.push(g[n]);else for(;g[n];n++)m.push(g[n]);return m}}var w,I;if(t.documentElement.compareDocumentPosition)w=function(g,i){if(g===i){h=true;return 0}if(!g.compareDocumentPosition||!i.compareDocumentPosition)return g.compareDocumentPosition?-1:1;return g.compareDocumentPosition(i)&4?-1:1};else{w=function(g,i){var n,m,p=[],q=[];n=g.parentNode;m=i.parentNode;var u=n;if(g===i){h=true;return 0}else if(n===m)return I(g,i);else if(n){if(!m)return 1}else return-1;
|
||||||
|
for(;u;){p.unshift(u);u=u.parentNode}for(u=m;u;){q.unshift(u);u=u.parentNode}n=p.length;m=q.length;for(u=0;u<n&&u<m;u++)if(p[u]!==q[u])return I(p[u],q[u]);return u===n?I(g,q[u],-1):I(p[u],i,1)};I=function(g,i,n){if(g===i)return n;for(g=g.nextSibling;g;){if(g===i)return-1;g=g.nextSibling}return 1}}k.getText=function(g){for(var i="",n,m=0;g[m];m++){n=g[m];if(n.nodeType===3||n.nodeType===4)i+=n.nodeValue;else if(n.nodeType!==8)i+=k.getText(n.childNodes)}return i};(function(){var g=t.createElement("div"),
|
||||||
|
i="script"+(new Date).getTime(),n=t.documentElement;g.innerHTML="<a name='"+i+"'/>";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g);
|
||||||
|
n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="<a href='#'></a>";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&&
|
||||||
|
function(){var g=k,i=t.createElement("div");i.innerHTML="<p class='TEST'></p>";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F||
|
||||||
|
p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g=
|
||||||
|
t.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition?
|
||||||
|
function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n<u;n++)k(g,q[n],m);return k.filter(p,m)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=k.getText;c.isXMLDoc=k.isXML;
|
||||||
|
c.contains=k.contains})();var Za=/Until$/,$a=/^(?:parents|prevUntil|prevAll)/,ab=/,/,Na=/^.[^:#\[\.,]*$/,bb=Array.prototype.slice,cb=c.expr.match.POS;c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,e=0,f=this.length;e<f;e++){d=b.length;c.find(a,this[e],b);if(e>0)for(var h=d;h<b.length;h++)for(var l=0;l<d;l++)if(b[l]===b[h]){b.splice(h--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,e=b.length;d<e;d++)if(c.contains(this,b[d]))return true})},
|
||||||
|
not:function(a){return this.pushStack(ma(this,a,false),"not",a)},filter:function(a){return this.pushStack(ma(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e<f;e++){l=a[e];k[l]||(k[l]=c.expr.match.POS.test(l)?c(l,b||this.context):l)}for(;h&&h.ownerDocument&&h!==b;){for(l in k){e=k[l];if(e.jquery?e.index(h)>-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h=
|
||||||
|
h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e<f;e++)for(h=this[e];h;)if(l?l.index(h)>-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context):
|
||||||
|
c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,
|
||||||
|
2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,
|
||||||
|
b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&
|
||||||
|
e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/<tbody/i,eb=/<|&#?\w+;/,Ca=/<(?:script|object|embed|option|style)/i,Da=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/\=([^="'>\s]+\/)>/g,P={option:[1,
|
||||||
|
"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
|
||||||
|
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
|
||||||
|
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
|
||||||
|
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
|
||||||
|
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
|
||||||
|
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null;
|
||||||
|
else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1></$2>");try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(e){this.empty().append(a)}}else c.isFunction(a)?this.each(function(f){var h=c(this);h.html(a.call(this,f,h.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=
|
||||||
|
c(this),e=d.html();d.replaceWith(a.call(this,b,e))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){var e,f,h,l=a[0],k=[];if(!c.support.checkClone&&arguments.length===3&&typeof l==="string"&&Da.test(l))return this.each(function(){c(this).domManip(a,
|
||||||
|
b,d,true)});if(c.isFunction(l))return this.each(function(x){var r=c(this);a[0]=l.call(this,x,b?r.html():B);r.domManip(a,b,d)});if(this[0]){e=l&&l.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:c.buildFragment(a,this,k);h=e.fragment;if(f=h.childNodes.length===1?h=h.firstChild:h.firstChild){b=b&&c.nodeName(f,"tr");f=0;for(var o=this.length;f<o;f++)d.call(b?c.nodeName(this[f],"table")?this[f].getElementsByTagName("tbody")[0]||this[f].appendChild(this[f].ownerDocument.createElement("tbody")):
|
||||||
|
this[f]:this[f],f>0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append",
|
||||||
|
prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f<h;f++){var l=(f>0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument||
|
||||||
|
b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1></$2>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]==="<table>"&&!x?r.childNodes:[];for(o=k.length-
|
||||||
|
1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script"))));
|
||||||
|
d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i,
|
||||||
|
jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true,
|
||||||
|
zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b),
|
||||||
|
h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b);
|
||||||
|
if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f=
|
||||||
|
d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left;
|
||||||
|
e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
|
||||||
|
ob=/^(?:select|textarea)/i,pb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,qb=/^(?:GET|HEAD)$/,Ra=/\[\]$/,T=/\=\?(&|$)/,ja=/\?/,rb=/([?&])_=[^&]*/,sb=/^(\w+:)?\/\/([^\/?#]+)/,tb=/%20/g,ub=/#.*$/,Ha=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ha)return Ha.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b===
|
||||||
|
"object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(l,k){if(k==="success"||k==="notmodified")h.html(f?c("<div>").append(l.responseText.replace(nb,"")).find(f):l.responseText);d&&h.each(d,[l.responseText,k,l])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&
|
||||||
|
!this.disabled&&(this.checked||ob.test(this.nodeName)||pb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})},
|
||||||
|
getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html",
|
||||||
|
script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),l=qb.test(h);b.url=b.url.replace(ub,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ja.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data||
|
||||||
|
!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+mb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var k=E[d];E[d]=function(m){if(c.isFunction(k))k(m);else{E[d]=B;try{delete E[d]}catch(p){}}f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);r&&r.removeChild(A)}}if(b.dataType==="script"&&b.cache===null)b.cache=
|
||||||
|
false;if(b.cache===false&&l){var o=c.now(),x=b.url.replace(rb,"$1_="+o);b.url=x+(x===b.url?(ja.test(b.url)?"&":"?")+"_="+o:"")}if(b.data&&l)b.url+=(ja.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");o=(o=sb.exec(b.url))&&(o[1]&&o[1].toLowerCase()!==location.protocol||o[2].toLowerCase()!==location.host);if(b.dataType==="script"&&h==="GET"&&o){var r=t.getElementsByTagName("head")[0]||t.documentElement,A=t.createElement("script");if(b.scriptCharset)A.charset=b.scriptCharset;
|
||||||
|
A.src=b.url;if(!d){var C=false;A.onload=A.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);A.onload=A.onreadystatechange=null;r&&A.parentNode&&r.removeChild(A)}}}r.insertBefore(A,r.firstChild);return B}var J=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!l||a&&a.contentType)w.setRequestHeader("Content-Type",
|
||||||
|
b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}o||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(I){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&&
|
||||||
|
c.triggerGlobal(b,"ajaxSend",[w,b]);var L=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){J||c.handleComplete(b,w,e,f);J=true;if(w)w.onreadystatechange=c.noop}else if(!J&&w&&(w.readyState===4||m==="timeout")){J=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d||
|
||||||
|
c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&Function.prototype.call.call(g,w);L("abort")}}catch(i){}b.async&&b.timeout>0&&setTimeout(function(){w&&!J&&L("timeout")},b.timeout);try{w.send(l||b.data==null?null:b.data)}catch(n){c.handleError(b,w,null,n);c.handleComplete(b,w,e,f)}b.async||L();return w}},param:function(a,b){var d=[],e=function(h,l){l=c.isFunction(l)?l():l;d[d.length]=
|
||||||
|
encodeURIComponent(h)+"="+encodeURIComponent(l)};if(b===B)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)da(f,a[f],b,e);return d.join("&").replace(tb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess",
|
||||||
|
[b,a])},handleComplete:function(a,b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),
|
||||||
|
e=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}});
|
||||||
|
if(E.ActiveXObject)c.ajaxSettings.xhr=function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var ea={},vb=/^(?:toggle|show|hide)$/,wb=/^([+\-]=)?([\d+.\-]+)(.*)$/,ba,pa=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show",
|
||||||
|
3),a,b,d);else{d=0;for(var e=this.length;d<e;d++){a=this[d];b=a.style.display;if(!c.data(a,"olddisplay")&&b==="none")b=a.style.display="";b===""&&c.css(a,"display")==="none"&&c.data(a,"olddisplay",qa(a.nodeName))}for(d=0;d<e;d++){a=this[d];b=a.style.display;if(b===""||b==="none")a.style.display=c.data(a,"olddisplay")||""}return this}},hide:function(a,b,d){if(a||a===0)return this.animate(S("hide",3),a,b,d);else{a=0;for(b=this.length;a<b;a++){d=c.css(this[a],"display");d!=="none"&&c.data(this[a],"olddisplay",
|
||||||
|
d)}for(a=0;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b,d){var e=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||e?this.each(function(){var f=e?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(S("toggle",3),a,b,d);return this},fadeTo:function(a,b,d,e){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d,e)},animate:function(a,b,d,e){var f=c.speed(b,
|
||||||
|
d,e);if(c.isEmptyObject(a))return this.each(f.complete);return this[f.queue===false?"each":"queue"](function(){var h=c.extend({},f),l,k=this.nodeType===1,o=k&&c(this).is(":hidden"),x=this;for(l in a){var r=c.camelCase(l);if(l!==r){a[r]=a[l];delete a[l];l=r}if(a[l]==="hide"&&o||a[l]==="show"&&!o)return h.complete.call(this);if(k&&(l==="height"||l==="width")){h.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];if(c.css(this,"display")==="inline"&&c.css(this,"float")==="none")if(c.support.inlineBlockNeedsLayout)if(qa(this.nodeName)===
|
||||||
|
"inline")this.style.display="inline-block";else{this.style.display="inline";this.style.zoom=1}else this.style.display="inline-block"}if(c.isArray(a[l])){(h.specialEasing=h.specialEasing||{})[l]=a[l][1];a[l]=a[l][0]}}if(h.overflow!=null)this.style.overflow="hidden";h.curAnim=c.extend({},a);c.each(a,function(A,C){var J=new c.fx(x,h,A);if(vb.test(C))J[C==="toggle"?o?"show":"hide":C](a);else{var w=wb.exec(C),I=J.cur()||0;if(w){var L=parseFloat(w[2]),g=w[3]||"px";if(g!=="px"){c.style(x,A,(L||1)+g);I=(L||
|
||||||
|
1)/J.cur()*I;c.style(x,A,I+g)}if(w[1])L=(w[1]==="-="?-1:1)*L+I;J.custom(I,L,g)}else J.custom(I,C,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var e=d.length-1;e>=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b,
|
||||||
|
d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a*
|
||||||
|
Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(l){return f.step(l)}
|
||||||
|
var f=this,h=c.fx;this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;e.elem=this.elem;if(e()&&c.timers.push(e)&&!ba)ba=setInterval(h.tick,h.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;
|
||||||
|
this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(k,o){f.style["overflow"+o]=h.overflow[k]})}this.options.hide&&c(this.elem).hide();if(this.options.hide||
|
||||||
|
this.options.show)for(var l in this.options.curAnim)c.style(this.elem,l,this.options.orig[l]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=
|
||||||
|
c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},interval:13,stop:function(){clearInterval(ba);ba=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===
|
||||||
|
b.elem}).length};var xb=/^t(?:able|d|h)$/i,Ia=/^(?:body|html)$/i;c.fn.offset="getBoundingClientRect"in t.documentElement?function(a){var b=this[0],d;if(a)return this.each(function(l){c.offset.setOffset(this,a,l)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);try{d=b.getBoundingClientRect()}catch(e){}var f=b.ownerDocument,h=f.documentElement;if(!d||!c.contains(h,b))return d||{top:0,left:0};b=f.body;f=fa(f);return{top:d.top+(f.pageYOffset||c.support.boxModel&&
|
||||||
|
h.scrollTop||b.scrollTop)-(h.clientTop||b.clientTop||0),left:d.left+(f.pageXOffset||c.support.boxModel&&h.scrollLeft||b.scrollLeft)-(h.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(a)return this.each(function(x){c.offset.setOffset(this,a,x)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d,e=b.offsetParent,f=b.ownerDocument,h=f.documentElement,l=f.body;d=(f=f.defaultView)?f.getComputedStyle(b,null):b.currentStyle;
|
||||||
|
for(var k=b.offsetTop,o=b.offsetLeft;(b=b.parentNode)&&b!==l&&b!==h;){if(c.offset.supportsFixedPosition&&d.position==="fixed")break;d=f?f.getComputedStyle(b,null):b.currentStyle;k-=b.scrollTop;o-=b.scrollLeft;if(b===e){k+=b.offsetTop;o+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&xb.test(b.nodeName))){k+=parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}e=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"){k+=
|
||||||
|
parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}d=d}if(d.position==="relative"||d.position==="static"){k+=l.offsetTop;o+=l.offsetLeft}if(c.offset.supportsFixedPosition&&d.position==="fixed"){k+=Math.max(h.scrollTop,l.scrollTop);o+=Math.max(h.scrollLeft,l.scrollLeft)}return{top:k,left:o}};c.offset={initialize:function(){var a=t.body,b=t.createElement("div"),d,e,f,h=parseFloat(c.css(a,"marginTop"))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",
|
||||||
|
height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);d=b.firstChild;e=d.firstChild;f=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=e.offsetTop!==5;this.doesAddBorderForTableAndCells=
|
||||||
|
f.offsetTop===5;e.style.position="fixed";e.style.top="20px";this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15;e.style.position=e.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==h;a.removeChild(b);c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.css(a,
|
||||||
|
"marginTop"))||0;d+=parseFloat(c.css(a,"marginLeft"))||0}return{top:b,left:d}},setOffset:function(a,b,d){var e=c.css(a,"position");if(e==="static")a.style.position="relative";var f=c(a),h=f.offset(),l=c.css(a,"top"),k=c.css(a,"left"),o=e==="absolute"&&c.inArray("auto",[l,k])>-1;e={};var x={};if(o)x=f.position();l=o?x.top:parseInt(l,10)||0;k=o?x.left:parseInt(k,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+l;if(b.left!=null)e.left=b.left-h.left+k;"using"in b?b.using.call(a,
|
||||||
|
e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Ia.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||t.body;a&&!Ia.test(a.nodeName)&&
|
||||||
|
c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==B)return this.each(function(){if(h=fa(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=fa(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();
|
||||||
|
c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(l){var k=c(this);k[d](e.call(this,l,k[d]()))});if(c.isWindow(f))return f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b];else if(f.nodeType===9)return Math.max(f.documentElement["client"+
|
||||||
|
b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]);else if(e===B){f=c.css(f,d);var h=parseFloat(f);return c.isNaN(h)?f:h}else return this.css(d,typeof e==="string"?e:e+"px")}})})(window);
|
|
@ -0,0 +1,283 @@
|
||||||
|
/*
|
||||||
|
Copyright © 2008
|
||||||
|
Rob Manson <roBman@MobileOnlineBusiness.com.au>,
|
||||||
|
Sean McCarthy <sean@MobileOnlineBusiness.com.au>
|
||||||
|
and http://SOAPjr.org
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
Acknoweldgements
|
||||||
|
----------------
|
||||||
|
This jQuery plugin utilises and requires the JSONSchema Validator
|
||||||
|
which is created by and Copyright (c) 2007 Kris Zyp SitePen (www.sitepen.com)
|
||||||
|
Licensed under the MIT (MIT-LICENSE.txt) licence.
|
||||||
|
|
||||||
|
JSONSchema Validator - Validates JavaScript objects using JSON Schemas
|
||||||
|
- http://jsonschema.googlecode.com/files/jsonschema-b2.js
|
||||||
|
(but check for the latest release)
|
||||||
|
|
||||||
|
For more information visit:
|
||||||
|
- http://www.json.com/json-schema-proposal/
|
||||||
|
- http://code.google.com/p/jsonschema/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Revision history
|
||||||
|
----------------
|
||||||
|
v1.0.1 - 4 Dec 2008
|
||||||
|
- Extended $.getValidJSON(params) API so you can define
|
||||||
|
{ schema : { send : xxx, receive : zzz } } so you can
|
||||||
|
optionally validate data on the way out and on the way in.
|
||||||
|
- Added tests to ensure that the schema key defined does really
|
||||||
|
exist as a typeof "object" in validJSONSchemas.
|
||||||
|
|
||||||
|
v1.0.0 - 3 Dec 2008
|
||||||
|
- initial release
|
||||||
|
|
||||||
|
|
||||||
|
Support
|
||||||
|
-------
|
||||||
|
For support, suggestions or general discussion please visit the #SOAPjr irc
|
||||||
|
channel on freenode.net or visit http://SOAPjr.org
|
||||||
|
|
||||||
|
|
||||||
|
Implementation overview
|
||||||
|
-----------------------
|
||||||
|
NOTE: This work contributes to the SOAPjr Data Model Definition project
|
||||||
|
that is designed to encourage the adoption and use of common JSON
|
||||||
|
data models with common SOAPjr APIs.
|
||||||
|
|
||||||
|
See http://soapjr.org/specs.html#dmd for more information
|
||||||
|
|
||||||
|
1. Include the jquery.js, jsonschema-b2.js and jquery.ValidJSON.js src files
|
||||||
|
into your html page - optionally include the jquery.SOAPjr.js plugin too
|
||||||
|
|
||||||
|
2. Add a call to the $(document).ready(function() { ... }) block to load
|
||||||
|
the relevant JSON Schema definition files you require
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
- http://soapjr.org/schemas/SOAPjr_request
|
||||||
|
- see http://json-schema.org/shared.html for common formats
|
||||||
|
|
||||||
|
3. Get the JSON files/objects you require using the $.getValidJSON() API
|
||||||
|
|
||||||
|
4. Check the "result.valid" boolean and "result.errors" array for any
|
||||||
|
validation errors and if all is good then use "json" like normal.
|
||||||
|
|
||||||
|
5. Sleep well knowing your data is cleanly validated and conforms to your
|
||||||
|
chosen schema.
|
||||||
|
|
||||||
|
|
||||||
|
Code usage examples
|
||||||
|
-------------------
|
||||||
|
1. Include src files
|
||||||
|
|
||||||
|
<script type="text/javascript" src="jquery-1.2.6.js"></script>
|
||||||
|
<script type="text/javascript" src="jsonschema-b2.js"></script>
|
||||||
|
<script type="text/javascript" src="jquery.ValidJSON.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
2. Add calls to load schema files
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
//load them from a URL
|
||||||
|
$.getValidJSONSchemas({
|
||||||
|
//id //url
|
||||||
|
"card" : "http://json-schema.org/card",
|
||||||
|
"calendar" : "http://json-schema.org/calendar"
|
||||||
|
});
|
||||||
|
|
||||||
|
//import them from a local var
|
||||||
|
$.setValidJSONSchemas({
|
||||||
|
//id //pre-populated vars (possibly included in .js files)
|
||||||
|
"geo" : geoschema_var,
|
||||||
|
"address" : addressschema_var
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
NOTE: cross-domain xhr restrictions apply - look at JSONP for cross domain requests
|
||||||
|
|
||||||
|
|
||||||
|
3. Get the JSON files/objects
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
function do_your_stuff() {
|
||||||
|
//collect data from a form or setup a stub
|
||||||
|
var params = { ... };
|
||||||
|
|
||||||
|
//get your data and validate it in one call
|
||||||
|
var xhr = $.getValidJSON({
|
||||||
|
"url" : url, //required
|
||||||
|
"data" : params, //optional
|
||||||
|
"callback" : "my_callback", //required (see point 4 below)
|
||||||
|
"schema" : { "send":"schema_id1", "receive":"schema_id2" } //optional - can be defined within the response JSON object using $schema
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
4. Check the validation results/errors
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
//setup your callback to handle the json data and any validation errors
|
||||||
|
function my_callback(result, json) {
|
||||||
|
if (result.valid) {
|
||||||
|
//json contains a valid XXX data object
|
||||||
|
} else {
|
||||||
|
for (var e in result.errors) {
|
||||||
|
//e.property tells you which value is invalid
|
||||||
|
//e.message is a human readable error message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
5. Relax
|
||||||
|
|
||||||
|
This plugin will let you do field level schema based validation.
|
||||||
|
You can also connect this to your form validation for standardised form data.
|
||||||
|
And you can use it in combination with the SOAPjr plugin to make sure
|
||||||
|
your apps handle metadata and complex/multiple errors seamlessly.
|
||||||
|
|
||||||
|
Isn't technology great! 8)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
//very weak example location script 8) for instant gratification
|
||||||
|
//javascript:function f(j, v) { alert(v.valid+" : "+v.errors[0].message) };$.getValidJSON({ "url":"test.json", "data":{"longitude":333, "latitude":123},"callback":"f", "schema": {"send":"geothingy","receive":"geothingy"}});void(0)
|
||||||
|
|
||||||
|
var validJSONSchemas = {};
|
||||||
|
|
||||||
|
// Example simple JSON Schema - see http://json-schema.org/geo for latest version
|
||||||
|
var geoschema = {
|
||||||
|
"description":"A geographical coordinate",
|
||||||
|
"type":"object",
|
||||||
|
"properties":{
|
||||||
|
"latitude":{"type":"number"},
|
||||||
|
"longitude":{"type":"number"}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
jQuery.setValidJSONSchemas = function(input) {
|
||||||
|
for (var id in input) {
|
||||||
|
if (typeof input[id] == "object") {
|
||||||
|
validJSONSchemas[id] = input[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jQuery.getValidJSONSchemas = function(input) {
|
||||||
|
for (var id in input) {
|
||||||
|
var url = input[id];
|
||||||
|
if (!url) {
|
||||||
|
throw("Not even a URL or filename was supplied!");
|
||||||
|
}
|
||||||
|
var xhr = $.ajax({
|
||||||
|
"url" : url,
|
||||||
|
"complete" : gotValidJSONSchema
|
||||||
|
});
|
||||||
|
xhr.getValidJSONSchemasConfig = {
|
||||||
|
"id" : id,
|
||||||
|
"url" : input[id]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function gotValidJSONSchema(xhr, status) {
|
||||||
|
var json = eval("("+xhr.responseText+")");
|
||||||
|
if (xhr.getValidJSONSchemasConfig != null) {
|
||||||
|
if (xhr.getValidJSONSchemasConfig.id) {
|
||||||
|
//this assumes one schema per json returned
|
||||||
|
var id = xhr.getValidJSONSchemasConfig.id;
|
||||||
|
var tmp = {};
|
||||||
|
tmp[id] = json;
|
||||||
|
$.setValidJSONSchemas(tmp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw("No config data available for this schema");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jQuery.getValidJSON = function(input) { //url, data, callback and schema
|
||||||
|
//TODO: add a queue for xhr's
|
||||||
|
//var req = new Date().valueOf();
|
||||||
|
|
||||||
|
var url = input.url;
|
||||||
|
if (!url) {
|
||||||
|
throw("Not even a URL or filename was supplied!");
|
||||||
|
}
|
||||||
|
var data = input.data || null;
|
||||||
|
var callback = input.callback;
|
||||||
|
if (!callback) {
|
||||||
|
throw("No callback provided");
|
||||||
|
}
|
||||||
|
var schema = input.schema || null;
|
||||||
|
|
||||||
|
var config = {
|
||||||
|
"callback" : callback,
|
||||||
|
"schema" : schema
|
||||||
|
}
|
||||||
|
|
||||||
|
if (schema.send && data) {
|
||||||
|
if (typeof validJSONSchemas[schema.send] == "object") {
|
||||||
|
var result = JSONSchema.validate(data, validJSONSchemas[schema.send]);
|
||||||
|
if (!result.valid) {
|
||||||
|
var errors = [];
|
||||||
|
for (var e in result.errors) {
|
||||||
|
var tmp = result.errors[e].property+" : "+result.errors[e].message;
|
||||||
|
errors.push(tmp);
|
||||||
|
}
|
||||||
|
throw(errors.join(", \n"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw("Invalid send schema defined - "+schema.send);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (schema.receive && typeof validJSONSchemas[schema.receive] != "object") {
|
||||||
|
throw("Invalid receive schema defined - "+schema.receive);
|
||||||
|
}
|
||||||
|
|
||||||
|
var ajax_options = {
|
||||||
|
"url" : url,
|
||||||
|
"complete" : gotValidJSON,
|
||||||
|
};
|
||||||
|
if (data) {
|
||||||
|
ajax_options.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
var xhr = $.ajax(ajax_options);
|
||||||
|
|
||||||
|
xhr.getValidJSONConfig = config;
|
||||||
|
return xhr;
|
||||||
|
};
|
||||||
|
|
||||||
|
function gotValidJSON (xhr, status) {
|
||||||
|
var json = eval("("+xhr.responseText+")");
|
||||||
|
if (xhr.getValidJSONConfig != null) {
|
||||||
|
if (xhr.getValidJSONConfig.schema.receive) {
|
||||||
|
var valid = JSONSchema.validate(json, validJSONSchemas[xhr.getValidJSONConfig.schema.receive]);
|
||||||
|
} else {
|
||||||
|
var valid = JSONSchema.validate(json);
|
||||||
|
}
|
||||||
|
eval(xhr.getValidJSONConfig.callback+"(json,valid)");
|
||||||
|
} else {
|
||||||
|
throw("No data object was attached to the json response so no callback could be found");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/******************************************************
|
||||||
|
* json store *
|
||||||
|
\*****************************************************/
|
||||||
|
body {
|
||||||
|
font-family: "Lucida Grande", Lucida, Helvetica, Arial, sans-serif;
|
||||||
|
background: #FFF;
|
||||||
|
color: #333;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header {
|
||||||
|
background: #C97E41;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
#header h1 {
|
||||||
|
font-family: Inconsolata, Monaco, Courier, mono;
|
||||||
|
color: #FFF;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
#header .cart-info {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
right: 0px;
|
||||||
|
text-align: right;
|
||||||
|
padding: 10px;
|
||||||
|
background: #714625;
|
||||||
|
color: #FFF;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
float:left;
|
||||||
|
width: 250px;
|
||||||
|
margin-right: 3px;
|
||||||
|
padding: 2px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
text-align:center;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.item-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.item-artist {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.item-detail .item-image {
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
.item-detail .item-info {
|
||||||
|
padding: 100px 10px 0px 10px;
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
var User = Backbone.Model.extend({
|
||||||
|
schema: null
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var SpiralGeneticsLoginController = {
|
||||||
|
|
||||||
|
init: function(spec) {
|
||||||
|
sgcl.this = sgcl.User({}).fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var SpiralGenetics = Backbone.Controller.extend({
|
||||||
|
|
||||||
|
routes: {
|
||||||
|
"": "dashboard",
|
||||||
|
"!pipelines": pipelines,
|
||||||
|
"!pipeline/:pipeline", pipeline,
|
||||||
|
"!datasets": datasets,
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
dashboard: function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
pipelines: function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
pipeline: function(pipeline_url) {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
datasets: function(dataset_url) {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
jobs: function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
job: function(job_url) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
app = SpiralGenetics.init();
|
||||||
|
}
|
||||||
|
})();
|
|
@ -0,0 +1,164 @@
|
||||||
|
var Product = Backbone.Model.extend({});
|
||||||
|
|
||||||
|
var ProductCollection = Backbone.Collection.extend({
|
||||||
|
model: Product,
|
||||||
|
comparator: function(item) {
|
||||||
|
return item.get('title');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var CartItem = Backbone.Model.extend({
|
||||||
|
update: function(amount) {
|
||||||
|
this.set({'quantity': this.get('quantity') + amount});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var Cart = Backbone.Collection.extend({
|
||||||
|
model: CartItem,
|
||||||
|
getByPid: function(pid) {
|
||||||
|
return this.detect(function(obj) { return (obj.get('product').cid == pid); });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var CartView = Backbone.View.extend({
|
||||||
|
el: $('.cart-info'),
|
||||||
|
|
||||||
|
initialize: function() {
|
||||||
|
this.model.bind('change', _.bind(this.render, this));
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
var sum = this.model.reduce(function(m, n) { return m + n.get('quantity'); }, 0);
|
||||||
|
this.el
|
||||||
|
.find('.cart-items').text(sum).end()
|
||||||
|
.animate({paddingTop: '30px'})
|
||||||
|
.animate({paddingTop: '10px'});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var ProductView = Backbone.View.extend({
|
||||||
|
el: $('#main'),
|
||||||
|
itemTemplate: $("#itemTmpl").template(),
|
||||||
|
|
||||||
|
events: {
|
||||||
|
"keypress .uqf" : "updateOnEnter",
|
||||||
|
"click .uq" : "update",
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function(options) {
|
||||||
|
if (options.cart) {
|
||||||
|
this.cart = options.cart;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
update: function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var cart_item = this.cart.getByPid(this.model.cid);
|
||||||
|
if (_.isUndefined(cart_item)) {
|
||||||
|
cart_item = new CartItem({product: this.model, quantity: 0});
|
||||||
|
this.cart.add(cart_item, {silent: true});
|
||||||
|
}
|
||||||
|
cart_item.update(parseInt($('.uqf').val()));
|
||||||
|
},
|
||||||
|
|
||||||
|
updateOnEnter: function(e) {
|
||||||
|
if (e.keyCode == 13) {
|
||||||
|
return this.update(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
var sg = this;
|
||||||
|
this.el.fadeOut('fast', function() {
|
||||||
|
sg.el.empty();
|
||||||
|
$.tmpl(sg.itemTemplate, sg.model).appendTo(sg.el);
|
||||||
|
sg.el.fadeIn('fast');
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
var IndexView = Backbone.View.extend({
|
||||||
|
el: $('#main'),
|
||||||
|
indexTemplate: $("#indexTmpl").template(),
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
var sg = this;
|
||||||
|
this.el.fadeOut('fast', function() {
|
||||||
|
sg.el.empty();
|
||||||
|
$.tmpl(sg.indexTemplate, sg.model.toArray()).appendTo(sg.el);
|
||||||
|
sg.el.fadeIn('fast');
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var Workspace = Backbone.Controller.extend({
|
||||||
|
_index: null,
|
||||||
|
_products: null,
|
||||||
|
_cart :null,
|
||||||
|
|
||||||
|
routes: {
|
||||||
|
"": "index",
|
||||||
|
"item/:id": "item",
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function() {
|
||||||
|
var ws = this;
|
||||||
|
if (this._index === null) {
|
||||||
|
$.ajax({
|
||||||
|
url: 'data/items.json',
|
||||||
|
dataType: 'json',
|
||||||
|
data: {},
|
||||||
|
success: function(data) {
|
||||||
|
ws._cart = new Cart();
|
||||||
|
new CartView({model: ws._cart});
|
||||||
|
ws._products = new ProductCollection();
|
||||||
|
ws._products.refresh(data);
|
||||||
|
ws._index = new IndexView({model: ws._products});
|
||||||
|
if (Backbone.history) {
|
||||||
|
Backbone.history.loadUrl()
|
||||||
|
} else {
|
||||||
|
ws.index();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
index: function() {
|
||||||
|
/* Race sentinel. : View loaded before data ready.
|
||||||
|
* Backbone.history will load as appropriate. */
|
||||||
|
if (this._index === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._index.render();
|
||||||
|
},
|
||||||
|
|
||||||
|
item: function(id) {
|
||||||
|
if (this._products === null) {
|
||||||
|
/* Race sentinel. That's two. I'm Doing Something Wrong. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isUndefined(this._products.getByCid(id)._view)) {
|
||||||
|
this._products.getByCid(id)._view = new ProductView({model: this._products.getByCid(id),
|
||||||
|
cart: this._cart});
|
||||||
|
}
|
||||||
|
this._products.getByCid(id)._view.render();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
workspace = new Workspace();
|
||||||
|
Backbone.history.start();
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Underscore.js 1.1.2
|
||||||
|
// (c) 2010 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(){var o=this,A=o._,r=typeof StopIteration!=="undefined"?StopIteration:"__break__",k=Array.prototype,m=Object.prototype,i=k.slice,B=k.unshift,C=m.toString,p=m.hasOwnProperty,s=k.forEach,t=k.map,u=k.reduce,v=k.reduceRight,w=k.filter,x=k.every,y=k.some,n=k.indexOf,z=k.lastIndexOf;m=Array.isArray;var D=Object.keys,c=function(a){return new l(a)};if(typeof exports!=="undefined")exports._=c;o._=c;c.VERSION="1.1.2";var j=c.each=c.forEach=function(a,b,d){try{if(s&&a.forEach===s)a.forEach(b,d);else if(c.isNumber(a.length))for(var e=
|
||||||
|
0,f=a.length;e<f;e++)b.call(d,a[e],e,a);else for(e in a)p.call(a,e)&&b.call(d,a[e],e,a)}catch(g){if(g!=r)throw g;}return a};c.map=function(a,b,d){if(t&&a.map===t)return a.map(b,d);var e=[];j(a,function(f,g,h){e[e.length]=b.call(d,f,g,h)});return e};c.reduce=c.foldl=c.inject=function(a,b,d,e){var f=d!==void 0;if(u&&a.reduce===u){if(e)b=c.bind(b,e);return f?a.reduce(b,d):a.reduce(b)}j(a,function(g,h,E){d=!f&&h===0?g:b.call(e,d,g,h,E)});return d};c.reduceRight=c.foldr=function(a,b,d,e){if(v&&a.reduceRight===
|
||||||
|
v){if(e)b=c.bind(b,e);return d!==void 0?a.reduceRight(b,d):a.reduceRight(b)}a=(c.isArray(a)?a.slice():c.toArray(a)).reverse();return c.reduce(a,b,d,e)};c.find=c.detect=function(a,b,d){var e;j(a,function(f,g,h){if(b.call(d,f,g,h)){e=f;c.breakLoop()}});return e};c.filter=c.select=function(a,b,d){if(w&&a.filter===w)return a.filter(b,d);var e=[];j(a,function(f,g,h){if(b.call(d,f,g,h))e[e.length]=f});return e};c.reject=function(a,b,d){var e=[];j(a,function(f,g,h){b.call(d,f,g,h)||(e[e.length]=f)});return e};
|
||||||
|
c.every=c.all=function(a,b,d){b=b||c.identity;if(x&&a.every===x)return a.every(b,d);var e=true;j(a,function(f,g,h){(e=e&&b.call(d,f,g,h))||c.breakLoop()});return e};c.some=c.any=function(a,b,d){b=b||c.identity;if(y&&a.some===y)return a.some(b,d);var e=false;j(a,function(f,g,h){if(e=b.call(d,f,g,h))c.breakLoop()});return e};c.include=c.contains=function(a,b){if(n&&a.indexOf===n)return a.indexOf(b)!=-1;var d=false;j(a,function(e){if(d=e===b)c.breakLoop()});return d};c.invoke=function(a,b){var d=i.call(arguments,
|
||||||
|
2);return c.map(a,function(e){return(b?e[b]:e).apply(e,d)})};c.pluck=function(a,b){return c.map(a,function(d){return d[b]})};c.max=function(a,b,d){if(!b&&c.isArray(a))return Math.max.apply(Math,a);var e={computed:-Infinity};j(a,function(f,g,h){g=b?b.call(d,f,g,h):f;g>=e.computed&&(e={value:f,computed:g})});return e.value};c.min=function(a,b,d){if(!b&&c.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};j(a,function(f,g,h){g=b?b.call(d,f,g,h):f;g<e.computed&&(e={value:f,computed:g})});
|
||||||
|
return e.value};c.sortBy=function(a,b,d){return c.pluck(c.map(a,function(e,f,g){return{value:e,criteria:b.call(d,e,f,g)}}).sort(function(e,f){var g=e.criteria,h=f.criteria;return g<h?-1:g>h?1:0}),"value")};c.sortedIndex=function(a,b,d){d=d||c.identity;for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(b)?e=g+1:f=g}return e};c.toArray=function(a){if(!a)return[];if(a.toArray)return a.toArray();if(c.isArray(a))return a;if(c.isArguments(a))return i.call(a);return c.values(a)};c.size=function(a){return c.toArray(a).length};
|
||||||
|
c.first=c.head=function(a,b,d){return b&&!d?i.call(a,0,b):a[0]};c.rest=c.tail=function(a,b,d){return i.call(a,c.isUndefined(b)||d?1:b)};c.last=function(a){return a[a.length-1]};c.compact=function(a){return c.filter(a,function(b){return!!b})};c.flatten=function(a){return c.reduce(a,function(b,d){if(c.isArray(d))return b.concat(c.flatten(d));b[b.length]=d;return b},[])};c.without=function(a){var b=i.call(arguments,1);return c.filter(a,function(d){return!c.include(b,d)})};c.uniq=c.unique=function(a,
|
||||||
|
b){return c.reduce(a,function(d,e,f){if(0==f||(b===true?c.last(d)!=e:!c.include(d,e)))d[d.length]=e;return d},[])};c.intersect=function(a){var b=i.call(arguments,1);return c.filter(c.uniq(a),function(d){return c.every(b,function(e){return c.indexOf(e,d)>=0})})};c.zip=function(){for(var a=i.call(arguments),b=c.max(c.pluck(a,"length")),d=Array(b),e=0;e<b;e++)d[e]=c.pluck(a,""+e);return d};c.indexOf=function(a,b){if(n&&a.indexOf===n)return a.indexOf(b);for(var d=0,e=a.length;d<e;d++)if(a[d]===b)return d;
|
||||||
|
return-1};c.lastIndexOf=function(a,b){if(z&&a.lastIndexOf===z)return a.lastIndexOf(b);for(var d=a.length;d--;)if(a[d]===b)return d;return-1};c.range=function(a,b,d){var e=i.call(arguments),f=e.length<=1;a=f?0:e[0];b=f?e[0]:e[1];d=e[2]||1;e=Math.max(Math.ceil((b-a)/d),0);f=0;for(var g=Array(e);f<e;){g[f++]=a;a+=d}return g};c.bind=function(a,b){var d=i.call(arguments,2);return function(){return a.apply(b||{},d.concat(i.call(arguments)))}};c.bindAll=function(a){var b=i.call(arguments,1);if(b.length==
|
||||||
|
0)b=c.functions(a);j(b,function(d){a[d]=c.bind(a[d],a)});return a};c.memoize=function(a,b){var d={};b=b||c.identity;return function(){var e=b.apply(this,arguments);return e in d?d[e]:d[e]=a.apply(this,arguments)}};c.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(a,d)},b)};c.defer=function(a){return c.delay.apply(c,[a,1].concat(i.call(arguments,1)))};c.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments));return b.apply(b,d)}};c.compose=
|
||||||
|
function(){var a=i.call(arguments);return function(){for(var b=i.call(arguments),d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};c.keys=D||function(a){if(c.isArray(a))return c.range(0,a.length);var b=[],d;for(d in a)if(p.call(a,d))b[b.length]=d;return b};c.values=function(a){return c.map(a,c.identity)};c.functions=c.methods=function(a){return c.filter(c.keys(a),function(b){return c.isFunction(a[b])}).sort()};c.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});
|
||||||
|
return a};c.clone=function(a){return c.isArray(a)?a.slice():c.extend({},a)};c.tap=function(a,b){b(a);return a};c.isEqual=function(a,b){if(a===b)return true;var d=typeof a;if(d!=typeof b)return false;if(a==b)return true;if(!a&&b||a&&!b)return false;if(a.isEqual)return a.isEqual(b);if(c.isDate(a)&&c.isDate(b))return a.getTime()===b.getTime();if(c.isNaN(a)&&c.isNaN(b))return false;if(c.isRegExp(a)&&c.isRegExp(b))return a.source===b.source&&a.global===b.global&&a.ignoreCase===b.ignoreCase&&a.multiline===
|
||||||
|
b.multiline;if(d!=="object")return false;if(a.length&&a.length!==b.length)return false;d=c.keys(a);var e=c.keys(b);if(d.length!=e.length)return false;for(var f in a)if(!(f in b)||!c.isEqual(a[f],b[f]))return false;return true};c.isEmpty=function(a){if(c.isArray(a)||c.isString(a))return a.length===0;for(var b in a)if(p.call(a,b))return false;return true};c.isElement=function(a){return!!(a&&a.nodeType==1)};c.isArray=m||function(a){return!!(a&&a.concat&&a.unshift&&!a.callee)};c.isArguments=function(a){return!!(a&&
|
||||||
|
a.callee)};c.isFunction=function(a){return!!(a&&a.constructor&&a.call&&a.apply)};c.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};c.isNumber=function(a){return a===+a||C.call(a)==="[object Number]"};c.isBoolean=function(a){return a===true||a===false};c.isDate=function(a){return!!(a&&a.getTimezoneOffset&&a.setUTCFullYear)};c.isRegExp=function(a){return!!(a&&a.test&&a.exec&&(a.ignoreCase||a.ignoreCase===false))};c.isNaN=function(a){return c.isNumber(a)&&isNaN(a)};c.isNull=function(a){return a===
|
||||||
|
null};c.isUndefined=function(a){return typeof a=="undefined"};c.noConflict=function(){o._=A;return this};c.identity=function(a){return a};c.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};c.breakLoop=function(){throw r;};c.mixin=function(a){j(c.functions(a),function(b){F(b,c[b]=a[b])})};var G=0;c.uniqueId=function(a){var b=G++;return a?a+b:b};c.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g};c.template=function(a,b){var d=c.templateSettings;d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+
|
||||||
|
a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.interpolate,function(e,f){return"',"+f.replace(/\\'/g,"'")+",'"}).replace(d.evaluate||null,function(e,f){return"');"+f.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+"__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');";d=new Function("obj",d);return b?d(b):d};var l=function(a){this._wrapped=a};c.prototype=l.prototype;var q=function(a,b){return b?c(a).chain():a},F=function(a,b){l.prototype[a]=function(){var d=
|
||||||
|
i.call(arguments);B.call(d,this._wrapped);return q(b.apply(c,d),this._chain)}};c.mixin(c);j(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var b=k[a];l.prototype[a]=function(){b.apply(this._wrapped,arguments);return q(this._wrapped,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];l.prototype[a]=function(){return q(b.apply(this._wrapped,arguments),this._chain)}});l.prototype.chain=function(){this._chain=true;return this};l.prototype.value=function(){return this._wrapped}})();
|
|
@ -0,0 +1,722 @@
|
||||||
|
// Underscore.js 1.1.2
|
||||||
|
// (c) 2010 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() {
|
||||||
|
|
||||||
|
// Baseline setup
|
||||||
|
// --------------
|
||||||
|
|
||||||
|
// Establish the root object, `window` in the browser, or `global` on the server.
|
||||||
|
var root = this;
|
||||||
|
|
||||||
|
// Save the previous value of the `_` variable.
|
||||||
|
var previousUnderscore = root._;
|
||||||
|
|
||||||
|
// Establish the object that gets thrown to break out of a loop iteration.
|
||||||
|
var breaker = typeof StopIteration !== 'undefined' ? StopIteration : '__break__';
|
||||||
|
|
||||||
|
// Save bytes in the minified (but not gzipped) version:
|
||||||
|
var ArrayProto = Array.prototype, ObjProto = Object.prototype;
|
||||||
|
|
||||||
|
// Create quick reference variables for speed access to core prototypes.
|
||||||
|
var slice = ArrayProto.slice,
|
||||||
|
unshift = ArrayProto.unshift,
|
||||||
|
toString = ObjProto.toString,
|
||||||
|
hasOwnProperty = ObjProto.hasOwnProperty;
|
||||||
|
|
||||||
|
// All **ECMAScript 5** native function implementations that we hope to use
|
||||||
|
// are declared here.
|
||||||
|
var
|
||||||
|
nativeForEach = ArrayProto.forEach,
|
||||||
|
nativeMap = ArrayProto.map,
|
||||||
|
nativeReduce = ArrayProto.reduce,
|
||||||
|
nativeReduceRight = ArrayProto.reduceRight,
|
||||||
|
nativeFilter = ArrayProto.filter,
|
||||||
|
nativeEvery = ArrayProto.every,
|
||||||
|
nativeSome = ArrayProto.some,
|
||||||
|
nativeIndexOf = ArrayProto.indexOf,
|
||||||
|
nativeLastIndexOf = ArrayProto.lastIndexOf,
|
||||||
|
nativeIsArray = Array.isArray,
|
||||||
|
nativeKeys = Object.keys;
|
||||||
|
|
||||||
|
// Create a safe reference to the Underscore object for use below.
|
||||||
|
var _ = function(obj) { return new wrapper(obj); };
|
||||||
|
|
||||||
|
// Export the Underscore object for **CommonJS**.
|
||||||
|
if (typeof exports !== 'undefined') exports._ = _;
|
||||||
|
|
||||||
|
// Export Underscore to the global scope.
|
||||||
|
root._ = _;
|
||||||
|
|
||||||
|
// Current version.
|
||||||
|
_.VERSION = '1.1.2';
|
||||||
|
|
||||||
|
// Collection Functions
|
||||||
|
// --------------------
|
||||||
|
|
||||||
|
// The cornerstone, an `each` implementation, aka `forEach`.
|
||||||
|
// Handles objects implementing `forEach`, arrays, and raw objects.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `forEach` if available.
|
||||||
|
var each = _.each = _.forEach = function(obj, iterator, context) {
|
||||||
|
try {
|
||||||
|
if (nativeForEach && obj.forEach === nativeForEach) {
|
||||||
|
obj.forEach(iterator, context);
|
||||||
|
} else if (_.isNumber(obj.length)) {
|
||||||
|
for (var i = 0, l = obj.length; i < l; i++) iterator.call(context, obj[i], i, obj);
|
||||||
|
} else {
|
||||||
|
for (var key in obj) {
|
||||||
|
if (hasOwnProperty.call(obj, key)) iterator.call(context, obj[key], key, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
if (e != breaker) throw e;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the results of applying the iterator to each element.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `map` if available.
|
||||||
|
_.map = function(obj, iterator, context) {
|
||||||
|
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
|
||||||
|
var results = [];
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
results[results.length] = iterator.call(context, value, index, list);
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// **Reduce** builds up a single result from a list of values, aka `inject`,
|
||||||
|
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
|
||||||
|
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
|
||||||
|
var initial = memo !== void 0;
|
||||||
|
if (nativeReduce && obj.reduce === nativeReduce) {
|
||||||
|
if (context) iterator = _.bind(iterator, context);
|
||||||
|
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
|
||||||
|
}
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (!initial && index === 0) {
|
||||||
|
memo = value;
|
||||||
|
} else {
|
||||||
|
memo = iterator.call(context, memo, value, index, list);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return memo;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The right-associative version of reduce, also known as `foldr`.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
|
||||||
|
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
|
||||||
|
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
|
||||||
|
if (context) iterator = _.bind(iterator, context);
|
||||||
|
return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
||||||
|
}
|
||||||
|
var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();
|
||||||
|
return _.reduce(reversed, iterator, memo, context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the first value which passes a truth test. Aliased as `detect`.
|
||||||
|
_.find = _.detect = function(obj, iterator, context) {
|
||||||
|
var result;
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (iterator.call(context, value, index, list)) {
|
||||||
|
result = value;
|
||||||
|
_.breakLoop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return all the elements that pass a truth test.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `filter` if available.
|
||||||
|
// Aliased as `select`.
|
||||||
|
_.filter = _.select = function(obj, iterator, context) {
|
||||||
|
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
|
||||||
|
var results = [];
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (iterator.call(context, value, index, list)) results[results.length] = value;
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return all the elements for which a truth test fails.
|
||||||
|
_.reject = function(obj, iterator, context) {
|
||||||
|
var results = [];
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (!iterator.call(context, value, index, list)) results[results.length] = value;
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine whether all of the elements match a truth test.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `every` if available.
|
||||||
|
// Aliased as `all`.
|
||||||
|
_.every = _.all = function(obj, iterator, context) {
|
||||||
|
iterator = iterator || _.identity;
|
||||||
|
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
|
||||||
|
var result = true;
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (!(result = result && iterator.call(context, value, index, list))) _.breakLoop();
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine if at least one element in the object matches a truth test.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `some` if available.
|
||||||
|
// Aliased as `any`.
|
||||||
|
_.some = _.any = function(obj, iterator, context) {
|
||||||
|
iterator = iterator || _.identity;
|
||||||
|
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
|
||||||
|
var result = false;
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (result = iterator.call(context, value, index, list)) _.breakLoop();
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine if a given value is included in the array or object using `===`.
|
||||||
|
// Aliased as `contains`.
|
||||||
|
_.include = _.contains = function(obj, target) {
|
||||||
|
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
||||||
|
var found = false;
|
||||||
|
each(obj, function(value) {
|
||||||
|
if (found = value === target) _.breakLoop();
|
||||||
|
});
|
||||||
|
return found;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invoke a method (with arguments) on every item in a collection.
|
||||||
|
_.invoke = function(obj, method) {
|
||||||
|
var args = slice.call(arguments, 2);
|
||||||
|
return _.map(obj, function(value) {
|
||||||
|
return (method ? value[method] : value).apply(value, args);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convenience version of a common use case of `map`: fetching a property.
|
||||||
|
_.pluck = function(obj, key) {
|
||||||
|
return _.map(obj, function(value){ return value[key]; });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the maximum element or (element-based computation).
|
||||||
|
_.max = function(obj, iterator, context) {
|
||||||
|
if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
|
||||||
|
var result = {computed : -Infinity};
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||||
|
computed >= result.computed && (result = {value : value, computed : computed});
|
||||||
|
});
|
||||||
|
return result.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the minimum element (or element-based computation).
|
||||||
|
_.min = function(obj, iterator, context) {
|
||||||
|
if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
|
||||||
|
var result = {computed : Infinity};
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||||
|
computed < result.computed && (result = {value : value, computed : computed});
|
||||||
|
});
|
||||||
|
return result.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sort the object's values by a criterion produced by an iterator.
|
||||||
|
_.sortBy = function(obj, iterator, context) {
|
||||||
|
return _.pluck(_.map(obj, function(value, index, list) {
|
||||||
|
return {
|
||||||
|
value : value,
|
||||||
|
criteria : iterator.call(context, value, index, list)
|
||||||
|
};
|
||||||
|
}).sort(function(left, right) {
|
||||||
|
var a = left.criteria, b = right.criteria;
|
||||||
|
return a < b ? -1 : a > b ? 1 : 0;
|
||||||
|
}), 'value');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use a comparator function to figure out at what index an object should
|
||||||
|
// be inserted so as to maintain order. Uses binary search.
|
||||||
|
_.sortedIndex = function(array, obj, iterator) {
|
||||||
|
iterator = iterator || _.identity;
|
||||||
|
var low = 0, high = array.length;
|
||||||
|
while (low < high) {
|
||||||
|
var mid = (low + high) >> 1;
|
||||||
|
iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
|
||||||
|
}
|
||||||
|
return low;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Safely convert anything iterable into a real, live array.
|
||||||
|
_.toArray = function(iterable) {
|
||||||
|
if (!iterable) return [];
|
||||||
|
if (iterable.toArray) return iterable.toArray();
|
||||||
|
if (_.isArray(iterable)) return iterable;
|
||||||
|
if (_.isArguments(iterable)) return slice.call(iterable);
|
||||||
|
return _.values(iterable);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the number of elements in an object.
|
||||||
|
_.size = function(obj) {
|
||||||
|
return _.toArray(obj).length;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Array Functions
|
||||||
|
// ---------------
|
||||||
|
|
||||||
|
// Get the first element of an array. Passing **n** will return the first N
|
||||||
|
// values in the array. Aliased as `head`. The **guard** check allows it to work
|
||||||
|
// with `_.map`.
|
||||||
|
_.first = _.head = function(array, n, guard) {
|
||||||
|
return n && !guard ? slice.call(array, 0, n) : array[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns everything but the first entry of the array. Aliased as `tail`.
|
||||||
|
// Especially useful on the arguments object. Passing an **index** will return
|
||||||
|
// the rest of the values in the array from that index onward. The **guard**
|
||||||
|
// check allows it to work with `_.map`.
|
||||||
|
_.rest = _.tail = function(array, index, guard) {
|
||||||
|
return slice.call(array, _.isUndefined(index) || guard ? 1 : index);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the last element of an array.
|
||||||
|
_.last = function(array) {
|
||||||
|
return array[array.length - 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Trim out all falsy values from an array.
|
||||||
|
_.compact = function(array) {
|
||||||
|
return _.filter(array, function(value){ return !!value; });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return a completely flattened version of an array.
|
||||||
|
_.flatten = function(array) {
|
||||||
|
return _.reduce(array, function(memo, value) {
|
||||||
|
if (_.isArray(value)) return memo.concat(_.flatten(value));
|
||||||
|
memo[memo.length] = value;
|
||||||
|
return memo;
|
||||||
|
}, []);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return a version of the array that does not contain the specified value(s).
|
||||||
|
_.without = function(array) {
|
||||||
|
var values = slice.call(arguments, 1);
|
||||||
|
return _.filter(array, function(value){ return !_.include(values, value); });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Produce a duplicate-free version of the array. If the array has already
|
||||||
|
// been sorted, you have the option of using a faster algorithm.
|
||||||
|
// Aliased as `unique`.
|
||||||
|
_.uniq = _.unique = function(array, isSorted) {
|
||||||
|
return _.reduce(array, function(memo, el, i) {
|
||||||
|
if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo[memo.length] = el;
|
||||||
|
return memo;
|
||||||
|
}, []);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Produce an array that contains every item shared between all the
|
||||||
|
// passed-in arrays.
|
||||||
|
_.intersect = function(array) {
|
||||||
|
var rest = slice.call(arguments, 1);
|
||||||
|
return _.filter(_.uniq(array), function(item) {
|
||||||
|
return _.every(rest, function(other) {
|
||||||
|
return _.indexOf(other, item) >= 0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Zip together multiple lists into a single array -- elements that share
|
||||||
|
// an index go together.
|
||||||
|
_.zip = function() {
|
||||||
|
var args = slice.call(arguments);
|
||||||
|
var length = _.max(_.pluck(args, 'length'));
|
||||||
|
var results = new Array(length);
|
||||||
|
for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
|
||||||
|
// we need this function. Return the position of the first occurence of an
|
||||||
|
// item in an array, or -1 if the item is not included in the array.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `indexOf` if available.
|
||||||
|
_.indexOf = function(array, item) {
|
||||||
|
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
|
||||||
|
for (var i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
|
||||||
|
_.lastIndexOf = function(array, item) {
|
||||||
|
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
|
||||||
|
var i = array.length;
|
||||||
|
while (i--) if (array[i] === item) return i;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate an integer Array containing an arithmetic progression. A port of
|
||||||
|
// the native Python `range()` function. See
|
||||||
|
// [the Python documentation](http://docs.python.org/library/functions.html#range).
|
||||||
|
_.range = function(start, stop, step) {
|
||||||
|
var args = slice.call(arguments),
|
||||||
|
solo = args.length <= 1,
|
||||||
|
start = solo ? 0 : args[0],
|
||||||
|
stop = solo ? args[0] : args[1],
|
||||||
|
step = args[2] || 1,
|
||||||
|
len = Math.max(Math.ceil((stop - start) / step), 0),
|
||||||
|
idx = 0,
|
||||||
|
range = new Array(len);
|
||||||
|
while (idx < len) {
|
||||||
|
range[idx++] = start;
|
||||||
|
start += step;
|
||||||
|
}
|
||||||
|
return range;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function (ahem) Functions
|
||||||
|
// ------------------
|
||||||
|
|
||||||
|
// Create a function bound to a given object (assigning `this`, and arguments,
|
||||||
|
// optionally). Binding with arguments is also known as `curry`.
|
||||||
|
_.bind = function(func, obj) {
|
||||||
|
var args = slice.call(arguments, 2);
|
||||||
|
return function() {
|
||||||
|
return func.apply(obj || {}, args.concat(slice.call(arguments)));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bind all of an object's methods to that object. Useful for ensuring that
|
||||||
|
// all callbacks defined on an object belong to it.
|
||||||
|
_.bindAll = function(obj) {
|
||||||
|
var funcs = slice.call(arguments, 1);
|
||||||
|
if (funcs.length == 0) funcs = _.functions(obj);
|
||||||
|
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Memoize an expensive function by storing its results.
|
||||||
|
_.memoize = function(func, hasher) {
|
||||||
|
var memo = {};
|
||||||
|
hasher = hasher || _.identity;
|
||||||
|
return function() {
|
||||||
|
var key = hasher.apply(this, arguments);
|
||||||
|
return key in memo ? memo[key] : (memo[key] = func.apply(this, arguments));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delays a function for the given number of milliseconds, and then calls
|
||||||
|
// it with the arguments supplied.
|
||||||
|
_.delay = function(func, wait) {
|
||||||
|
var args = slice.call(arguments, 2);
|
||||||
|
return setTimeout(function(){ return func.apply(func, args); }, wait);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Defers a function, scheduling it to run after the current call stack has
|
||||||
|
// cleared.
|
||||||
|
_.defer = function(func) {
|
||||||
|
return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the first function passed as an argument to the second,
|
||||||
|
// allowing you to adjust arguments, run code before and after, and
|
||||||
|
// conditionally execute the original function.
|
||||||
|
_.wrap = function(func, wrapper) {
|
||||||
|
return function() {
|
||||||
|
var args = [func].concat(slice.call(arguments));
|
||||||
|
return wrapper.apply(wrapper, args);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a function that is the composition of a list of functions, each
|
||||||
|
// consuming the return value of the function that follows.
|
||||||
|
_.compose = function() {
|
||||||
|
var funcs = slice.call(arguments);
|
||||||
|
return function() {
|
||||||
|
var args = slice.call(arguments);
|
||||||
|
for (var i=funcs.length-1; i >= 0; i--) {
|
||||||
|
args = [funcs[i].apply(this, args)];
|
||||||
|
}
|
||||||
|
return args[0];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Object Functions
|
||||||
|
// ----------------
|
||||||
|
|
||||||
|
// Retrieve the names of an object's properties.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `Object.keys`
|
||||||
|
_.keys = nativeKeys || function(obj) {
|
||||||
|
if (_.isArray(obj)) return _.range(0, obj.length);
|
||||||
|
var keys = [];
|
||||||
|
for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
|
||||||
|
return keys;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Retrieve the values of an object's properties.
|
||||||
|
_.values = function(obj) {
|
||||||
|
return _.map(obj, _.identity);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return a sorted list of the function names available on the object.
|
||||||
|
// Aliased as `methods`
|
||||||
|
_.functions = _.methods = function(obj) {
|
||||||
|
return _.filter(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extend a given object with all the properties in passed-in object(s).
|
||||||
|
_.extend = function(obj) {
|
||||||
|
each(slice.call(arguments, 1), function(source) {
|
||||||
|
for (var prop in source) obj[prop] = source[prop];
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a (shallow-cloned) duplicate of an object.
|
||||||
|
_.clone = function(obj) {
|
||||||
|
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invokes interceptor with the obj, and then returns obj.
|
||||||
|
// The primary purpose of this method is to "tap into" a method chain, in
|
||||||
|
// order to perform operations on intermediate results within the chain.
|
||||||
|
_.tap = function(obj, interceptor) {
|
||||||
|
interceptor(obj);
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Perform a deep comparison to check if two objects are equal.
|
||||||
|
_.isEqual = function(a, b) {
|
||||||
|
// Check object identity.
|
||||||
|
if (a === b) return true;
|
||||||
|
// Different types?
|
||||||
|
var atype = typeof(a), btype = typeof(b);
|
||||||
|
if (atype != btype) return false;
|
||||||
|
// Basic equality test (watch out for coercions).
|
||||||
|
if (a == b) return true;
|
||||||
|
// One is falsy and the other truthy.
|
||||||
|
if ((!a && b) || (a && !b)) return false;
|
||||||
|
// One of them implements an isEqual()?
|
||||||
|
if (a.isEqual) return a.isEqual(b);
|
||||||
|
// Check dates' integer values.
|
||||||
|
if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
|
||||||
|
// Both are NaN?
|
||||||
|
if (_.isNaN(a) && _.isNaN(b)) return false;
|
||||||
|
// Compare regular expressions.
|
||||||
|
if (_.isRegExp(a) && _.isRegExp(b))
|
||||||
|
return a.source === b.source &&
|
||||||
|
a.global === b.global &&
|
||||||
|
a.ignoreCase === b.ignoreCase &&
|
||||||
|
a.multiline === b.multiline;
|
||||||
|
// If a is not an object by this point, we can't handle it.
|
||||||
|
if (atype !== 'object') return false;
|
||||||
|
// Check for different array lengths before comparing contents.
|
||||||
|
if (a.length && (a.length !== b.length)) return false;
|
||||||
|
// Nothing else worked, deep compare the contents.
|
||||||
|
var aKeys = _.keys(a), bKeys = _.keys(b);
|
||||||
|
// Different object sizes?
|
||||||
|
if (aKeys.length != bKeys.length) return false;
|
||||||
|
// Recursive comparison of contents.
|
||||||
|
for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given array or object empty?
|
||||||
|
_.isEmpty = function(obj) {
|
||||||
|
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
|
||||||
|
for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a DOM element?
|
||||||
|
_.isElement = function(obj) {
|
||||||
|
return !!(obj && obj.nodeType == 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value an array?
|
||||||
|
// Delegates to ECMA5's native Array.isArray
|
||||||
|
_.isArray = nativeIsArray || function(obj) {
|
||||||
|
return !!(obj && obj.concat && obj.unshift && !obj.callee);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given variable an arguments object?
|
||||||
|
_.isArguments = function(obj) {
|
||||||
|
return !!(obj && obj.callee);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a function?
|
||||||
|
_.isFunction = function(obj) {
|
||||||
|
return !!(obj && obj.constructor && obj.call && obj.apply);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a string?
|
||||||
|
_.isString = function(obj) {
|
||||||
|
return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a number?
|
||||||
|
_.isNumber = function(obj) {
|
||||||
|
return (obj === +obj) || (toString.call(obj) === '[object Number]');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a boolean?
|
||||||
|
_.isBoolean = function(obj) {
|
||||||
|
return obj === true || obj === false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a date?
|
||||||
|
_.isDate = function(obj) {
|
||||||
|
return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is the given value a regular expression?
|
||||||
|
_.isRegExp = function(obj) {
|
||||||
|
return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is the given value NaN -- this one is interesting. NaN != NaN, and
|
||||||
|
// isNaN(undefined) == true, so we make sure it's a number first.
|
||||||
|
_.isNaN = function(obj) {
|
||||||
|
return _.isNumber(obj) && isNaN(obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value equal to null?
|
||||||
|
_.isNull = function(obj) {
|
||||||
|
return obj === null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given variable undefined?
|
||||||
|
_.isUndefined = function(obj) {
|
||||||
|
return typeof obj == 'undefined';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Utility Functions
|
||||||
|
// -----------------
|
||||||
|
|
||||||
|
// Run Underscore.js in *noConflict* mode, returning the `_` variable to its
|
||||||
|
// previous owner. Returns a reference to the Underscore object.
|
||||||
|
_.noConflict = function() {
|
||||||
|
root._ = previousUnderscore;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Keep the identity function around for default iterators.
|
||||||
|
_.identity = function(value) {
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run a function **n** times.
|
||||||
|
_.times = function (n, iterator, context) {
|
||||||
|
for (var i = 0; i < n; i++) iterator.call(context, i);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Break out of the middle of an iteration.
|
||||||
|
_.breakLoop = function() {
|
||||||
|
throw breaker;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add your own custom functions to the Underscore object, ensuring that
|
||||||
|
// they're correctly added to the OOP wrapper as well.
|
||||||
|
_.mixin = function(obj) {
|
||||||
|
each(_.functions(obj), function(name){
|
||||||
|
addToWrapper(name, _[name] = obj[name]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate a unique integer id (unique within the entire client session).
|
||||||
|
// Useful for temporary DOM ids.
|
||||||
|
var idCounter = 0;
|
||||||
|
_.uniqueId = function(prefix) {
|
||||||
|
var id = idCounter++;
|
||||||
|
return prefix ? prefix + id : id;
|
||||||
|
};
|
||||||
|
|
||||||
|
// By default, Underscore uses ERB-style template delimiters, change the
|
||||||
|
// following template settings to use alternative delimiters.
|
||||||
|
_.templateSettings = {
|
||||||
|
evaluate : /<%([\s\S]+?)%>/g,
|
||||||
|
interpolate : /<%=([\s\S]+?)%>/g
|
||||||
|
};
|
||||||
|
|
||||||
|
// JavaScript micro-templating, similar to John Resig's implementation.
|
||||||
|
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
||||||
|
// and correctly escapes quotes within interpolated code.
|
||||||
|
_.template = function(str, data) {
|
||||||
|
var c = _.templateSettings;
|
||||||
|
var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
|
||||||
|
'with(obj||{}){__p.push(\'' +
|
||||||
|
str.replace(/\\/g, '\\\\')
|
||||||
|
.replace(/'/g, "\\'")
|
||||||
|
.replace(c.interpolate, function(match, code) {
|
||||||
|
return "'," + code.replace(/\\'/g, "'") + ",'";
|
||||||
|
})
|
||||||
|
.replace(c.evaluate || null, function(match, code) {
|
||||||
|
return "');" + code.replace(/\\'/g, "'")
|
||||||
|
.replace(/[\r\n\t]/g, ' ') + "__p.push('";
|
||||||
|
})
|
||||||
|
.replace(/\r/g, '\\r')
|
||||||
|
.replace(/\n/g, '\\n')
|
||||||
|
.replace(/\t/g, '\\t')
|
||||||
|
+ "');}return __p.join('');";
|
||||||
|
var func = new Function('obj', tmpl);
|
||||||
|
return data ? func(data) : func;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The OOP Wrapper
|
||||||
|
// ---------------
|
||||||
|
|
||||||
|
// If Underscore is called as a function, it returns a wrapped object that
|
||||||
|
// can be used OO-style. This wrapper holds altered versions of all the
|
||||||
|
// underscore functions. Wrapped objects may be chained.
|
||||||
|
var wrapper = function(obj) { this._wrapped = obj; };
|
||||||
|
|
||||||
|
// Expose `wrapper.prototype` as `_.prototype`
|
||||||
|
_.prototype = wrapper.prototype;
|
||||||
|
|
||||||
|
// Helper function to continue chaining intermediate results.
|
||||||
|
var result = function(obj, chain) {
|
||||||
|
return chain ? _(obj).chain() : obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A method to easily add functions to the OOP wrapper.
|
||||||
|
var addToWrapper = function(name, func) {
|
||||||
|
wrapper.prototype[name] = function() {
|
||||||
|
var args = slice.call(arguments);
|
||||||
|
unshift.call(args, this._wrapped);
|
||||||
|
return result(func.apply(_, args), this._chain);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add all of the Underscore functions to the wrapper object.
|
||||||
|
_.mixin(_);
|
||||||
|
|
||||||
|
// Add all mutator Array functions to the wrapper.
|
||||||
|
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
||||||
|
var method = ArrayProto[name];
|
||||||
|
wrapper.prototype[name] = function() {
|
||||||
|
method.apply(this._wrapped, arguments);
|
||||||
|
return result(this._wrapped, this._chain);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add all accessor Array functions to the wrapper.
|
||||||
|
each(['concat', 'join', 'slice'], function(name) {
|
||||||
|
var method = ArrayProto[name];
|
||||||
|
wrapper.prototype[name] = function() {
|
||||||
|
return result(method.apply(this._wrapped, arguments), this._chain);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start chaining a wrapped Underscore object.
|
||||||
|
wrapper.prototype.chain = function() {
|
||||||
|
this._chain = true;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extracts the result from a wrapped and chained object.
|
||||||
|
wrapper.prototype.value = function() {
|
||||||
|
return this._wrapped;
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|