Add non-submodule vendor directory.
Former-commit-id: 392cdade55487e774e959013d8d25ae0b1dfe93b
22
vendor/backbone/LICENSE
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Copyright (c) 2010-2012 Jeremy Ashkenas, DocumentCloud
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use,
|
||||||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
26
vendor/backbone/README.md
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
____ __ __
|
||||||
|
/\ _`\ /\ \ /\ \ __
|
||||||
|
\ \ \ \ \ __ ___\ \ \/'\\ \ \____ ___ ___ __ /\_\ ____
|
||||||
|
\ \ _ <' /'__`\ /'___\ \ , < \ \ '__`\ / __`\ /' _ `\ /'__`\ \/\ \ /',__\
|
||||||
|
\ \ \ \ \/\ \ \.\_/\ \__/\ \ \\`\\ \ \ \ \/\ \ \ \/\ \/\ \/\ __/ __ \ \ \/\__, `\
|
||||||
|
\ \____/\ \__/.\_\ \____\\ \_\ \_\ \_,__/\ \____/\ \_\ \_\ \____\/\_\_\ \ \/\____/
|
||||||
|
\/___/ \/__/\/_/\/____/ \/_/\/_/\/___/ \/___/ \/_/\/_/\/____/\/_/\ \_\ \/___/
|
||||||
|
\ \____/
|
||||||
|
\/___/
|
||||||
|
(_'_______________________________________________________________________________'_)
|
||||||
|
(_.———————————————————————————————————————————————————————————————————————————————._)
|
||||||
|
|
||||||
|
|
||||||
|
Backbone supplies structure to JavaScript-heavy applications by providing models key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing application over a RESTful JSON interface.
|
||||||
|
|
||||||
|
For Docs, License, Tests, pre-packed downloads, and everything else, really, see:
|
||||||
|
http://backbonejs.org
|
||||||
|
|
||||||
|
To suggest a feature, report a bug, or general discussion:
|
||||||
|
http://github.com/documentcloud/backbone/issues/
|
||||||
|
|
||||||
|
All contributors are listed here:
|
||||||
|
http://github.com/documentcloud/backbone/contributors
|
||||||
|
|
||||||
|
Special thanks to Robert Kieffer for the original philosophy behind Backbone.
|
||||||
|
http://github.com/broofa
|
||||||
1461
vendor/backbone/backbone.js
vendored
Normal file
669
vendor/backbone/test/collection.js
vendored
Normal file
@@ -0,0 +1,669 @@
|
|||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
var lastRequest = null;
|
||||||
|
var sync = Backbone.sync;
|
||||||
|
|
||||||
|
var a, b, c, d, e, col, otherCol;
|
||||||
|
|
||||||
|
module("Backbone.Collection", {
|
||||||
|
|
||||||
|
setup: function() {
|
||||||
|
a = new Backbone.Model({id: 3, label: 'a'});
|
||||||
|
b = new Backbone.Model({id: 2, label: 'b'});
|
||||||
|
c = new Backbone.Model({id: 1, label: 'c'});
|
||||||
|
d = new Backbone.Model({id: 0, label: 'd'});
|
||||||
|
e = null;
|
||||||
|
col = new Backbone.Collection([a,b,c,d]);
|
||||||
|
otherCol = new Backbone.Collection();
|
||||||
|
|
||||||
|
Backbone.sync = function(method, model, options) {
|
||||||
|
lastRequest = {
|
||||||
|
method: method,
|
||||||
|
model: model,
|
||||||
|
options: options
|
||||||
|
};
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
teardown: function() {
|
||||||
|
Backbone.sync = sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: new and sort", 7, function() {
|
||||||
|
equal(col.first(), a, "a should be first");
|
||||||
|
equal(col.last(), d, "d should be last");
|
||||||
|
col.comparator = function(a, b) {
|
||||||
|
return a.id > b.id ? -1 : 1;
|
||||||
|
};
|
||||||
|
col.sort();
|
||||||
|
equal(col.first(), a, "a should be first");
|
||||||
|
equal(col.last(), d, "d should be last");
|
||||||
|
col.comparator = function(model) { return model.id; };
|
||||||
|
col.sort();
|
||||||
|
equal(col.first(), d, "d should be first");
|
||||||
|
equal(col.last(), a, "a should be last");
|
||||||
|
equal(col.length, 4);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: get, getByCid", 3, function() {
|
||||||
|
equal(col.get(0), d);
|
||||||
|
equal(col.get(2), b);
|
||||||
|
equal(col.getByCid(col.first().cid), col.first());
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: get with non-default ids", 2, function() {
|
||||||
|
var col = new Backbone.Collection();
|
||||||
|
var MongoModel = Backbone.Model.extend({
|
||||||
|
idAttribute: '_id'
|
||||||
|
});
|
||||||
|
var model = new MongoModel({_id: 100});
|
||||||
|
col.push(model);
|
||||||
|
equal(col.get(100), model);
|
||||||
|
model.set({_id: 101});
|
||||||
|
equal(col.get(101), model);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: update index when id changes", 3, function() {
|
||||||
|
var col = new Backbone.Collection();
|
||||||
|
col.add([
|
||||||
|
{id : 0, name : 'one'},
|
||||||
|
{id : 1, name : 'two'}
|
||||||
|
]);
|
||||||
|
var one = col.get(0);
|
||||||
|
equal(one.get('name'), 'one');
|
||||||
|
one.set({id : 101});
|
||||||
|
equal(col.get(0), null);
|
||||||
|
equal(col.get(101).get('name'), 'one');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: at", 1, function() {
|
||||||
|
equal(col.at(2), c);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: pluck", 1, function() {
|
||||||
|
equal(col.pluck('label').join(' '), 'a b c d');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: add", 11, function() {
|
||||||
|
var added, opts, secondAdded;
|
||||||
|
added = opts = secondAdded = null;
|
||||||
|
e = new Backbone.Model({id: 10, label : 'e'});
|
||||||
|
otherCol.add(e);
|
||||||
|
otherCol.on('add', function() {
|
||||||
|
secondAdded = true;
|
||||||
|
});
|
||||||
|
col.on('add', function(model, collection, options){
|
||||||
|
added = model.get('label');
|
||||||
|
equal(options.index, 4);
|
||||||
|
opts = options;
|
||||||
|
});
|
||||||
|
col.add(e, {amazing: true});
|
||||||
|
equal(added, 'e');
|
||||||
|
equal(col.length, 5);
|
||||||
|
equal(col.last(), e);
|
||||||
|
equal(otherCol.length, 1);
|
||||||
|
equal(secondAdded, null);
|
||||||
|
ok(opts.amazing);
|
||||||
|
|
||||||
|
var f = new Backbone.Model({id: 20, label : 'f'});
|
||||||
|
var g = new Backbone.Model({id: 21, label : 'g'});
|
||||||
|
var h = new Backbone.Model({id: 22, label : 'h'});
|
||||||
|
var atCol = new Backbone.Collection([f, g, h]);
|
||||||
|
equal(atCol.length, 3);
|
||||||
|
atCol.add(e, {at: 1});
|
||||||
|
equal(atCol.length, 4);
|
||||||
|
equal(atCol.at(1), e);
|
||||||
|
equal(atCol.last(), h);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: add multiple models", 6, function() {
|
||||||
|
var col = new Backbone.Collection([{at: 0}, {at: 1}, {at: 9}]);
|
||||||
|
col.add([{at: 2}, {at: 3}, {at: 4}, {at: 5}, {at: 6}, {at: 7}, {at: 8}], {at: 2});
|
||||||
|
for (var i = 0; i <= 5; i++) {
|
||||||
|
equal(col.at(i).get('at'), i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: add; at should have preference over comparator", 1, function() {
|
||||||
|
var Col = Backbone.Collection.extend({
|
||||||
|
comparator: function(a,b) {
|
||||||
|
return a.id > b.id ? -1 : 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var col = new Col([{id: 2}, {id: 3}]);
|
||||||
|
col.add(new Backbone.Model({id: 1}), {at: 1});
|
||||||
|
|
||||||
|
equal(col.pluck('id').join(' '), '3 1 2');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: can't add model to collection twice", function() {
|
||||||
|
var col = new Backbone.Collection([{id: 1}, {id: 2}, {id: 1}, {id: 2}, {id: 3}]);
|
||||||
|
equal(col.pluck('id').join(' '), '1 2 3');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: can't add different model with same id to collection twice", 1, function() {
|
||||||
|
var col = new Backbone.Collection;
|
||||||
|
col.unshift({id: 101});
|
||||||
|
col.add({id: 101});
|
||||||
|
equal(col.length, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: merge in duplicate models with {merge: true}", 3, function() {
|
||||||
|
var col = new Backbone.Collection;
|
||||||
|
col.add([{id: 1, name: 'Moe'}, {id: 2, name: 'Curly'}, {id: 3, name: 'Larry'}]);
|
||||||
|
col.add({id: 1, name: 'Moses'});
|
||||||
|
equal(col.first().get('name'), 'Moe');
|
||||||
|
col.add({id: 1, name: 'Moses'}, {merge: true});
|
||||||
|
equal(col.first().get('name'), 'Moses');
|
||||||
|
col.add({id: 1, name: 'Tim'}, {merge: true, silent: true});
|
||||||
|
equal(col.first().get('name'), 'Tim');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: add model to multiple collections", 10, function() {
|
||||||
|
var counter = 0;
|
||||||
|
var e = new Backbone.Model({id: 10, label : 'e'});
|
||||||
|
e.on('add', function(model, collection) {
|
||||||
|
counter++;
|
||||||
|
equal(e, model);
|
||||||
|
if (counter > 1) {
|
||||||
|
equal(collection, colF);
|
||||||
|
} else {
|
||||||
|
equal(collection, colE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var colE = new Backbone.Collection([]);
|
||||||
|
colE.on('add', function(model, collection) {
|
||||||
|
equal(e, model);
|
||||||
|
equal(colE, collection);
|
||||||
|
});
|
||||||
|
var colF = new Backbone.Collection([]);
|
||||||
|
colF.on('add', function(model, collection) {
|
||||||
|
equal(e, model);
|
||||||
|
equal(colF, collection);
|
||||||
|
});
|
||||||
|
colE.add(e);
|
||||||
|
equal(e.collection, colE);
|
||||||
|
colF.add(e);
|
||||||
|
equal(e.collection, colE);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: add model with parse", 1, function() {
|
||||||
|
var Model = Backbone.Model.extend({
|
||||||
|
parse: function(obj) {
|
||||||
|
obj.value += 1;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Col = Backbone.Collection.extend({model: Model});
|
||||||
|
var col = new Col;
|
||||||
|
col.add({value: 1}, {parse: true});
|
||||||
|
equal(col.at(0).get('value'), 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: add model to collection with sort()-style comparator", 3, function() {
|
||||||
|
var col = new Backbone.Collection;
|
||||||
|
col.comparator = function(a, b) {
|
||||||
|
return a.get('name') < b.get('name') ? -1 : 1;
|
||||||
|
};
|
||||||
|
var tom = new Backbone.Model({name: 'Tom'});
|
||||||
|
var rob = new Backbone.Model({name: 'Rob'});
|
||||||
|
var tim = new Backbone.Model({name: 'Tim'});
|
||||||
|
col.add(tom);
|
||||||
|
col.add(rob);
|
||||||
|
col.add(tim);
|
||||||
|
equal(col.indexOf(rob), 0);
|
||||||
|
equal(col.indexOf(tim), 1);
|
||||||
|
equal(col.indexOf(tom), 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: comparator that depends on `this`", 1, function() {
|
||||||
|
var col = new Backbone.Collection;
|
||||||
|
col.negative = function(num) {
|
||||||
|
return -num;
|
||||||
|
};
|
||||||
|
col.comparator = function(a) {
|
||||||
|
return this.negative(a.id);
|
||||||
|
};
|
||||||
|
col.add([{id: 1}, {id: 2}, {id: 3}]);
|
||||||
|
equal(col.pluck('id').join(' '), '3 2 1');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: remove", 5, function() {
|
||||||
|
var removed = null;
|
||||||
|
var otherRemoved = null;
|
||||||
|
col.on('remove', function(model, col, options) {
|
||||||
|
removed = model.get('label');
|
||||||
|
equal(options.index, 3);
|
||||||
|
});
|
||||||
|
otherCol.on('remove', function(model, col, options) {
|
||||||
|
otherRemoved = true;
|
||||||
|
});
|
||||||
|
col.remove(d);
|
||||||
|
equal(removed, 'd');
|
||||||
|
equal(col.length, 3);
|
||||||
|
equal(col.first(), a);
|
||||||
|
equal(otherRemoved, null);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: shift and pop", 2, function() {
|
||||||
|
var col = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]);
|
||||||
|
equal(col.shift().get('a'), 'a');
|
||||||
|
equal(col.pop().get('c'), 'c');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: slice", 2, function() {
|
||||||
|
var col = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]);
|
||||||
|
var array = col.slice(1, 3);
|
||||||
|
equal(array.length, 2);
|
||||||
|
equal(array[0].get('b'), 'b');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: events are unbound on remove", 3, function() {
|
||||||
|
var counter = 0;
|
||||||
|
var dj = new Backbone.Model();
|
||||||
|
var emcees = new Backbone.Collection([dj]);
|
||||||
|
emcees.on('change', function(){ counter++; });
|
||||||
|
dj.set({name : 'Kool'});
|
||||||
|
equal(counter, 1);
|
||||||
|
emcees.reset([]);
|
||||||
|
equal(dj.collection, undefined);
|
||||||
|
dj.set({name : 'Shadow'});
|
||||||
|
equal(counter, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: remove in multiple collections", 7, function() {
|
||||||
|
var modelData = {
|
||||||
|
id : 5,
|
||||||
|
title : 'Othello'
|
||||||
|
};
|
||||||
|
var passed = false;
|
||||||
|
var e = new Backbone.Model(modelData);
|
||||||
|
var f = new Backbone.Model(modelData);
|
||||||
|
f.on('remove', function() {
|
||||||
|
passed = true;
|
||||||
|
});
|
||||||
|
var colE = new Backbone.Collection([e]);
|
||||||
|
var colF = new Backbone.Collection([f]);
|
||||||
|
ok(e != f);
|
||||||
|
ok(colE.length == 1);
|
||||||
|
ok(colF.length == 1);
|
||||||
|
colE.remove(e);
|
||||||
|
equal(passed, false);
|
||||||
|
ok(colE.length == 0);
|
||||||
|
colF.remove(e);
|
||||||
|
ok(colF.length == 0);
|
||||||
|
equal(passed, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: remove same model in multiple collection", 16, function() {
|
||||||
|
var counter = 0;
|
||||||
|
var e = new Backbone.Model({id: 5, title: 'Othello'});
|
||||||
|
e.on('remove', function(model, collection) {
|
||||||
|
counter++;
|
||||||
|
equal(e, model);
|
||||||
|
if (counter > 1) {
|
||||||
|
equal(collection, colE);
|
||||||
|
} else {
|
||||||
|
equal(collection, colF);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var colE = new Backbone.Collection([e]);
|
||||||
|
colE.on('remove', function(model, collection) {
|
||||||
|
equal(e, model);
|
||||||
|
equal(colE, collection);
|
||||||
|
});
|
||||||
|
var colF = new Backbone.Collection([e]);
|
||||||
|
colF.on('remove', function(model, collection) {
|
||||||
|
equal(e, model);
|
||||||
|
equal(colF, collection);
|
||||||
|
});
|
||||||
|
equal(colE, e.collection);
|
||||||
|
colF.remove(e);
|
||||||
|
ok(colF.length == 0);
|
||||||
|
ok(colE.length == 1);
|
||||||
|
equal(counter, 1);
|
||||||
|
equal(colE, e.collection);
|
||||||
|
colE.remove(e);
|
||||||
|
equal(null, e.collection);
|
||||||
|
ok(colE.length == 0);
|
||||||
|
equal(counter, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: model destroy removes from all collections", 3, function() {
|
||||||
|
var e = new Backbone.Model({id: 5, title: 'Othello'});
|
||||||
|
e.sync = function(method, model, options) { options.success({}); };
|
||||||
|
var colE = new Backbone.Collection([e]);
|
||||||
|
var colF = new Backbone.Collection([e]);
|
||||||
|
e.destroy();
|
||||||
|
ok(colE.length == 0);
|
||||||
|
ok(colF.length == 0);
|
||||||
|
equal(undefined, e.collection);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Colllection: non-persisted model destroy removes from all collections", 3, function() {
|
||||||
|
var e = new Backbone.Model({title: 'Othello'});
|
||||||
|
e.sync = function(method, model, options) { throw "should not be called"; };
|
||||||
|
var colE = new Backbone.Collection([e]);
|
||||||
|
var colF = new Backbone.Collection([e]);
|
||||||
|
e.destroy();
|
||||||
|
ok(colE.length == 0);
|
||||||
|
ok(colF.length == 0);
|
||||||
|
equal(undefined, e.collection);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: fetch", 4, function() {
|
||||||
|
col.fetch();
|
||||||
|
equal(lastRequest.method, 'read');
|
||||||
|
equal(lastRequest.model, col);
|
||||||
|
equal(lastRequest.options.parse, true);
|
||||||
|
|
||||||
|
col.fetch({parse: false});
|
||||||
|
equal(lastRequest.options.parse, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: create", 4, function() {
|
||||||
|
var model = col.create({label: 'f'}, {wait: true});
|
||||||
|
equal(lastRequest.method, 'create');
|
||||||
|
equal(lastRequest.model, model);
|
||||||
|
equal(model.get('label'), 'f');
|
||||||
|
equal(model.collection, col);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: create enforces validation", 1, function() {
|
||||||
|
var ValidatingModel = Backbone.Model.extend({
|
||||||
|
validate: function(attrs) {
|
||||||
|
return "fail";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var ValidatingCollection = Backbone.Collection.extend({
|
||||||
|
model: ValidatingModel
|
||||||
|
});
|
||||||
|
var col = new ValidatingCollection();
|
||||||
|
equal(col.create({"foo":"bar"}), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: a failing create runs the error callback", 1, function() {
|
||||||
|
var ValidatingModel = Backbone.Model.extend({
|
||||||
|
validate: function(attrs) {
|
||||||
|
return "fail";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var ValidatingCollection = Backbone.Collection.extend({
|
||||||
|
model: ValidatingModel
|
||||||
|
});
|
||||||
|
var flag = false;
|
||||||
|
var callback = function(model, error) { flag = true; };
|
||||||
|
var col = new ValidatingCollection();
|
||||||
|
col.create({"foo":"bar"}, { error: callback });
|
||||||
|
equal(flag, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("collection: initialize", 1, function() {
|
||||||
|
var Collection = Backbone.Collection.extend({
|
||||||
|
initialize: function() {
|
||||||
|
this.one = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var coll = new Collection;
|
||||||
|
equal(coll.one, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: toJSON", 1, function() {
|
||||||
|
equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: where", 6, function() {
|
||||||
|
var coll = new Backbone.Collection([
|
||||||
|
{a: 1},
|
||||||
|
{a: 1},
|
||||||
|
{a: 1, b: 2},
|
||||||
|
{a: 2, b: 2},
|
||||||
|
{a: 3}
|
||||||
|
]);
|
||||||
|
equal(coll.where({a: 1}).length, 3);
|
||||||
|
equal(coll.where({a: 2}).length, 1);
|
||||||
|
equal(coll.where({a: 3}).length, 1);
|
||||||
|
equal(coll.where({b: 1}).length, 0);
|
||||||
|
equal(coll.where({b: 2}).length, 2);
|
||||||
|
equal(coll.where({a: 1, b: 2}).length, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: Underscore methods", 13, function() {
|
||||||
|
equal(col.map(function(model){ return model.get('label'); }).join(' '), 'a b c d');
|
||||||
|
equal(col.any(function(model){ return model.id === 100; }), false);
|
||||||
|
equal(col.any(function(model){ return model.id === 0; }), true);
|
||||||
|
equal(col.indexOf(b), 1);
|
||||||
|
equal(col.size(), 4);
|
||||||
|
equal(col.rest().length, 3);
|
||||||
|
ok(!_.include(col.rest()), a);
|
||||||
|
ok(!_.include(col.rest()), d);
|
||||||
|
ok(!col.isEmpty());
|
||||||
|
ok(!_.include(col.without(d)), d);
|
||||||
|
equal(col.max(function(model){ return model.id; }).id, 3);
|
||||||
|
equal(col.min(function(model){ return model.id; }).id, 0);
|
||||||
|
deepEqual(col.chain()
|
||||||
|
.filter(function(o){ return o.id % 2 === 0; })
|
||||||
|
.map(function(o){ return o.id * 2; })
|
||||||
|
.value(),
|
||||||
|
[4, 0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: reset", 10, function() {
|
||||||
|
var resetCount = 0;
|
||||||
|
var models = col.models;
|
||||||
|
col.on('reset', function() { resetCount += 1; });
|
||||||
|
col.reset([]);
|
||||||
|
equal(resetCount, 1);
|
||||||
|
equal(col.length, 0);
|
||||||
|
equal(col.last(), null);
|
||||||
|
col.reset(models);
|
||||||
|
equal(resetCount, 2);
|
||||||
|
equal(col.length, 4);
|
||||||
|
equal(col.last(), d);
|
||||||
|
col.reset(_.map(models, function(m){ return m.attributes; }));
|
||||||
|
equal(resetCount, 3);
|
||||||
|
equal(col.length, 4);
|
||||||
|
ok(col.last() !== d);
|
||||||
|
ok(_.isEqual(col.last().attributes, d.attributes));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: reset passes caller options", 3, function() {
|
||||||
|
var Model = Backbone.Model.extend({
|
||||||
|
initialize: function(attrs, options) {
|
||||||
|
this.model_parameter = options.model_parameter;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var col = new (Backbone.Collection.extend({ model: Model }))();
|
||||||
|
col.reset([{ astring: "green", anumber: 1 }, { astring: "blue", anumber: 2 }], { model_parameter: 'model parameter' });
|
||||||
|
equal(col.length, 2);
|
||||||
|
col.each(function(model) {
|
||||||
|
equal(model.model_parameter, 'model parameter');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: trigger custom events on models", 1, function() {
|
||||||
|
var fired = null;
|
||||||
|
a.on("custom", function() { fired = true; });
|
||||||
|
a.trigger("custom");
|
||||||
|
equal(fired, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: add does not alter arguments", 2, function(){
|
||||||
|
var attrs = {};
|
||||||
|
var models = [attrs];
|
||||||
|
new Backbone.Collection().add(models);
|
||||||
|
equal(models.length, 1);
|
||||||
|
ok(attrs === models[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#714: access `model.collection` in a brand new model.", 2, function() {
|
||||||
|
var col = new Backbone.Collection;
|
||||||
|
var Model = Backbone.Model.extend({
|
||||||
|
set: function(attrs) {
|
||||||
|
equal(attrs.prop, 'value');
|
||||||
|
equal(this.collection, col);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
col.model = Model;
|
||||||
|
col.create({prop: 'value'});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#574, remove its own reference to the .models array.", 2, function() {
|
||||||
|
var col = new Backbone.Collection([
|
||||||
|
{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}
|
||||||
|
]);
|
||||||
|
equal(col.length, 6);
|
||||||
|
col.remove(col.models);
|
||||||
|
equal(col.length, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#861, adding models to a collection which do not pass validation", 1, function() {
|
||||||
|
raises(function() {
|
||||||
|
var Model = Backbone.Model.extend({
|
||||||
|
validate: function(attrs) {
|
||||||
|
if (attrs.id == 3) return "id can't be 3";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Collection = Backbone.Collection.extend({
|
||||||
|
model: Model
|
||||||
|
});
|
||||||
|
|
||||||
|
var col = new Collection;
|
||||||
|
|
||||||
|
col.add([{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}]);
|
||||||
|
}, function(e) {
|
||||||
|
return e.message === "Can't add an invalid model to a collection";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: index with comparator", 4, function() {
|
||||||
|
var counter = 0;
|
||||||
|
var col = new Backbone.Collection([{id: 2}, {id: 4}], {
|
||||||
|
comparator: function(model){ return model.id; }
|
||||||
|
}).on('add', function(model, colleciton, options){
|
||||||
|
if (model.id == 1) {
|
||||||
|
equal(options.index, 0);
|
||||||
|
equal(counter++, 0);
|
||||||
|
}
|
||||||
|
if (model.id == 3) {
|
||||||
|
equal(options.index, 2);
|
||||||
|
equal(counter++, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
col.add([{id: 3}, {id: 1}]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: throwing during add leaves consistent state", 4, function() {
|
||||||
|
var col = new Backbone.Collection();
|
||||||
|
col.on('test', function() { ok(false); });
|
||||||
|
col.model = Backbone.Model.extend({
|
||||||
|
validate: function(attrs){ if (!attrs.valid) return 'invalid'; }
|
||||||
|
});
|
||||||
|
var model = new col.model({id: 1, valid: true});
|
||||||
|
raises(function() { col.add([model, {id: 2}]); });
|
||||||
|
model.trigger('test');
|
||||||
|
ok(!col.getByCid(model.cid));
|
||||||
|
ok(!col.get(1));
|
||||||
|
equal(col.length, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: multiple copies of the same model", 3, function() {
|
||||||
|
var col = new Backbone.Collection();
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
col.add([model, model]);
|
||||||
|
equal(col.length, 1);
|
||||||
|
col.add([{id: 1}, {id: 1}]);
|
||||||
|
equal(col.length, 2);
|
||||||
|
equal(col.last().id, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#964 - collection.get return inconsistent", 2, function() {
|
||||||
|
var c = new Backbone.Collection();
|
||||||
|
ok(c.get(null) === undefined);
|
||||||
|
ok(c.get() === undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1112 - passing options.model sets collection.model", 2, function() {
|
||||||
|
var Model = Backbone.Model.extend({});
|
||||||
|
var c = new Backbone.Collection([{id: 1}], {model: Model});
|
||||||
|
ok(c.model === Model);
|
||||||
|
ok(c.at(0) instanceof Model);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("null and undefined are invalid ids.", 2, function() {
|
||||||
|
var model = new Backbone.Model({id: 1});
|
||||||
|
var collection = new Backbone.Collection([model]);
|
||||||
|
model.set({id: null});
|
||||||
|
ok(!collection.get('null'));
|
||||||
|
model.set({id: 1});
|
||||||
|
model.set({id: undefined});
|
||||||
|
ok(!collection.get('undefined'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Collection: falsy comparator", 4, function(){
|
||||||
|
var Col = Backbone.Collection.extend({
|
||||||
|
comparator: function(model){ return model.id; }
|
||||||
|
});
|
||||||
|
var col = new Col();
|
||||||
|
var colFalse = new Col(null, {comparator: false});
|
||||||
|
var colNull = new Col(null, {comparator: null});
|
||||||
|
var colUndefined = new Col(null, {comparator: undefined});
|
||||||
|
ok(col.comparator);
|
||||||
|
ok(!colFalse.comparator);
|
||||||
|
ok(!colNull.comparator);
|
||||||
|
ok(colUndefined.comparator);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1355 - `options` is passed to success callbacks", 2, function(){
|
||||||
|
var m = new Backbone.Model({x:1});
|
||||||
|
var col = new Backbone.Collection();
|
||||||
|
var opts = {
|
||||||
|
success: function(collection, resp, options){
|
||||||
|
ok(options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
col.sync = m.sync = function( method, collection, options ){
|
||||||
|
options.success();
|
||||||
|
};
|
||||||
|
col.fetch(opts);
|
||||||
|
col.create(m, opts);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1412 - Trigger 'sync' event.", 2, function() {
|
||||||
|
var collection = new Backbone.Collection([], {
|
||||||
|
model: Backbone.Model.extend({
|
||||||
|
sync: function(method, model, options) {
|
||||||
|
options.success();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
collection.sync = function(method, model, options) { options.success(); };
|
||||||
|
collection.on('sync', function() { ok(true); });
|
||||||
|
collection.fetch();
|
||||||
|
collection.create({id: 1});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1447 - create with wait adds model.", function() {
|
||||||
|
var collection = new Backbone.Collection;
|
||||||
|
var model = new Backbone.Model;
|
||||||
|
model.sync = function(method, model, options){ options.success(); };
|
||||||
|
collection.on('add', function(){ ok(true); });
|
||||||
|
collection.create(model, {wait: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1448 - add sorts collection after merge.", function() {
|
||||||
|
var collection = new Backbone.Collection([
|
||||||
|
{id: 1, x: 1},
|
||||||
|
{id: 2, x: 2}
|
||||||
|
]);
|
||||||
|
collection.comparator = function(model){ return model.get('x'); };
|
||||||
|
collection.add({id: 1, x: 3}, {merge: true});
|
||||||
|
deepEqual(collection.pluck('id'), [2, 1]);
|
||||||
|
});
|
||||||
|
});
|
||||||
195
vendor/backbone/test/events.js
vendored
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
module("Backbone.Events");
|
||||||
|
|
||||||
|
test("Events: on and trigger", 2, function() {
|
||||||
|
var obj = { counter: 0 };
|
||||||
|
_.extend(obj,Backbone.Events);
|
||||||
|
obj.on('event', function() { obj.counter += 1; });
|
||||||
|
obj.trigger('event');
|
||||||
|
equal(obj.counter,1,'counter should be incremented.');
|
||||||
|
obj.trigger('event');
|
||||||
|
obj.trigger('event');
|
||||||
|
obj.trigger('event');
|
||||||
|
obj.trigger('event');
|
||||||
|
equal(obj.counter, 5, 'counter should be incremented five times.');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Events: binding and triggering multiple events", 4, function() {
|
||||||
|
var obj = { counter: 0 };
|
||||||
|
_.extend(obj,Backbone.Events);
|
||||||
|
|
||||||
|
obj.on('a b c', function() { obj.counter += 1; });
|
||||||
|
|
||||||
|
obj.trigger('a');
|
||||||
|
equal(obj.counter, 1);
|
||||||
|
|
||||||
|
obj.trigger('a b');
|
||||||
|
equal(obj.counter, 3);
|
||||||
|
|
||||||
|
obj.trigger('c');
|
||||||
|
equal(obj.counter, 4);
|
||||||
|
|
||||||
|
obj.off('a c');
|
||||||
|
obj.trigger('a b c');
|
||||||
|
equal(obj.counter, 5);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Events: trigger all for each event", 3, function() {
|
||||||
|
var a, b, obj = { counter: 0 };
|
||||||
|
_.extend(obj, Backbone.Events);
|
||||||
|
obj.on('all', function(event) {
|
||||||
|
obj.counter++;
|
||||||
|
if (event == 'a') a = true;
|
||||||
|
if (event == 'b') b = true;
|
||||||
|
})
|
||||||
|
.trigger('a b');
|
||||||
|
ok(a);
|
||||||
|
ok(b);
|
||||||
|
equal(obj.counter, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Events: on, then unbind all functions", 1, function() {
|
||||||
|
var obj = { counter: 0 };
|
||||||
|
_.extend(obj,Backbone.Events);
|
||||||
|
var callback = function() { obj.counter += 1; };
|
||||||
|
obj.on('event', callback);
|
||||||
|
obj.trigger('event');
|
||||||
|
obj.off('event');
|
||||||
|
obj.trigger('event');
|
||||||
|
equal(obj.counter, 1, 'counter should have only been incremented once.');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Events: bind two callbacks, unbind only one", 2, function() {
|
||||||
|
var obj = { counterA: 0, counterB: 0 };
|
||||||
|
_.extend(obj,Backbone.Events);
|
||||||
|
var callback = function() { obj.counterA += 1; };
|
||||||
|
obj.on('event', callback);
|
||||||
|
obj.on('event', function() { obj.counterB += 1; });
|
||||||
|
obj.trigger('event');
|
||||||
|
obj.off('event', callback);
|
||||||
|
obj.trigger('event');
|
||||||
|
equal(obj.counterA, 1, 'counterA should have only been incremented once.');
|
||||||
|
equal(obj.counterB, 2, 'counterB should have been incremented twice.');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Events: unbind a callback in the midst of it firing", 1, function() {
|
||||||
|
var obj = {counter: 0};
|
||||||
|
_.extend(obj, Backbone.Events);
|
||||||
|
var callback = function() {
|
||||||
|
obj.counter += 1;
|
||||||
|
obj.off('event', callback);
|
||||||
|
};
|
||||||
|
obj.on('event', callback);
|
||||||
|
obj.trigger('event');
|
||||||
|
obj.trigger('event');
|
||||||
|
obj.trigger('event');
|
||||||
|
equal(obj.counter, 1, 'the callback should have been unbound.');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Events: two binds that unbind themeselves", 2, function() {
|
||||||
|
var obj = { counterA: 0, counterB: 0 };
|
||||||
|
_.extend(obj,Backbone.Events);
|
||||||
|
var incrA = function(){ obj.counterA += 1; obj.off('event', incrA); };
|
||||||
|
var incrB = function(){ obj.counterB += 1; obj.off('event', incrB); };
|
||||||
|
obj.on('event', incrA);
|
||||||
|
obj.on('event', incrB);
|
||||||
|
obj.trigger('event');
|
||||||
|
obj.trigger('event');
|
||||||
|
obj.trigger('event');
|
||||||
|
equal(obj.counterA, 1, 'counterA should have only been incremented once.');
|
||||||
|
equal(obj.counterB, 1, 'counterB should have only been incremented once.');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Events: bind a callback with a supplied context", 1, function () {
|
||||||
|
var TestClass = function () {
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
TestClass.prototype.assertTrue = function () {
|
||||||
|
ok(true, '`this` was bound to the callback');
|
||||||
|
};
|
||||||
|
|
||||||
|
var obj = _.extend({},Backbone.Events);
|
||||||
|
obj.on('event', function () { this.assertTrue(); }, (new TestClass));
|
||||||
|
obj.trigger('event');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Events: nested trigger with unbind", 1, function () {
|
||||||
|
var obj = { counter: 0 };
|
||||||
|
_.extend(obj, Backbone.Events);
|
||||||
|
var incr1 = function(){ obj.counter += 1; obj.off('event', incr1); obj.trigger('event'); };
|
||||||
|
var incr2 = function(){ obj.counter += 1; };
|
||||||
|
obj.on('event', incr1);
|
||||||
|
obj.on('event', incr2);
|
||||||
|
obj.trigger('event');
|
||||||
|
equal(obj.counter, 3, 'counter should have been incremented three times');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Events: callback list is not altered during trigger", 2, function () {
|
||||||
|
var counter = 0, obj = _.extend({}, Backbone.Events);
|
||||||
|
var incr = function(){ counter++; };
|
||||||
|
obj.on('event', function(){ obj.on('event', incr).on('all', incr); })
|
||||||
|
.trigger('event');
|
||||||
|
equal(counter, 0, 'bind does not alter callback list');
|
||||||
|
obj.off()
|
||||||
|
.on('event', function(){ obj.off('event', incr).off('all', incr); })
|
||||||
|
.on('event', incr)
|
||||||
|
.on('all', incr)
|
||||||
|
.trigger('event');
|
||||||
|
equal(counter, 2, 'unbind does not alter callback list');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1282 - 'all' callback list is retrieved after each event.", 1, function() {
|
||||||
|
var counter = 0;
|
||||||
|
var obj = _.extend({}, Backbone.Events);
|
||||||
|
var incr = function(){ counter++; };
|
||||||
|
obj.on('x', function() {
|
||||||
|
obj.on('y', incr).on('all', incr);
|
||||||
|
})
|
||||||
|
.trigger('x y');
|
||||||
|
strictEqual(counter, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("if no callback is provided, `on` is a noop", 0, function() {
|
||||||
|
_.extend({}, Backbone.Events).on('test').trigger('test');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("remove all events for a specific context", 4, function() {
|
||||||
|
var obj = _.extend({}, Backbone.Events);
|
||||||
|
obj.on('x y all', function() { ok(true); });
|
||||||
|
obj.on('x y all', function() { ok(false); }, obj);
|
||||||
|
obj.off(null, null, obj);
|
||||||
|
obj.trigger('x y');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("remove all events for a specific callback", 4, function() {
|
||||||
|
var obj = _.extend({}, Backbone.Events);
|
||||||
|
var success = function() { ok(true); };
|
||||||
|
var fail = function() { ok(false); };
|
||||||
|
obj.on('x y all', success);
|
||||||
|
obj.on('x y all', fail);
|
||||||
|
obj.off(null, fail);
|
||||||
|
obj.trigger('x y');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("off is chainable", 3, function() {
|
||||||
|
var obj = _.extend({}, Backbone.Events);
|
||||||
|
// With no events
|
||||||
|
ok(obj.off() === obj);
|
||||||
|
// When removing all events
|
||||||
|
obj.on('event', function(){}, obj);
|
||||||
|
ok(obj.off() === obj);
|
||||||
|
// When removing some events
|
||||||
|
obj.on('event', function(){}, obj);
|
||||||
|
ok(obj.off('event') === obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1310 - off does not skip consecutive events", 0, function() {
|
||||||
|
var obj = _.extend({}, Backbone.Events);
|
||||||
|
obj.on('event', function() { ok(false); }, obj);
|
||||||
|
obj.on('event', function() { ok(false); }, obj);
|
||||||
|
obj.off(null, null, obj);
|
||||||
|
obj.trigger('event');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
855
vendor/backbone/test/model.js
vendored
Normal file
@@ -0,0 +1,855 @@
|
|||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
// Variable to catch the last request.
|
||||||
|
var lastRequest = null;
|
||||||
|
// Variable to catch ajax params.
|
||||||
|
var ajaxParams = null;
|
||||||
|
var sync = Backbone.sync;
|
||||||
|
var ajax = Backbone.ajax;
|
||||||
|
var urlRoot = null;
|
||||||
|
|
||||||
|
var proxy = Backbone.Model.extend();
|
||||||
|
var klass = Backbone.Collection.extend({
|
||||||
|
url : function() { return '/collection'; }
|
||||||
|
});
|
||||||
|
var doc, collection;
|
||||||
|
|
||||||
|
module("Backbone.Model", {
|
||||||
|
|
||||||
|
setup: function() {
|
||||||
|
doc = new proxy({
|
||||||
|
id : '1-the-tempest',
|
||||||
|
title : "The Tempest",
|
||||||
|
author : "Bill Shakespeare",
|
||||||
|
length : 123
|
||||||
|
});
|
||||||
|
collection = new klass();
|
||||||
|
collection.add(doc);
|
||||||
|
|
||||||
|
Backbone.sync = function(method, model, options) {
|
||||||
|
lastRequest = {
|
||||||
|
method: method,
|
||||||
|
model: model,
|
||||||
|
options: options
|
||||||
|
};
|
||||||
|
sync.apply(this, arguments);
|
||||||
|
};
|
||||||
|
Backbone.ajax = function(params) { ajaxParams = params; };
|
||||||
|
urlRoot = Backbone.Model.prototype.urlRoot;
|
||||||
|
Backbone.Model.prototype.urlRoot = '/';
|
||||||
|
},
|
||||||
|
|
||||||
|
teardown: function() {
|
||||||
|
Backbone.sync = sync;
|
||||||
|
Backbone.ajax = ajax;
|
||||||
|
Backbone.Model.prototype.urlRoot = urlRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: initialize", 3, function() {
|
||||||
|
var Model = Backbone.Model.extend({
|
||||||
|
initialize: function() {
|
||||||
|
this.one = 1;
|
||||||
|
equal(this.collection, collection);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var model = new Model({}, {collection: collection});
|
||||||
|
equal(model.one, 1);
|
||||||
|
equal(model.collection, collection);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: initialize with attributes and options", 1, function() {
|
||||||
|
var Model = Backbone.Model.extend({
|
||||||
|
initialize: function(attributes, options) {
|
||||||
|
this.one = options.one;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var model = new Model({}, {one: 1});
|
||||||
|
equal(model.one, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: initialize with parsed attributes", 1, function() {
|
||||||
|
var Model = Backbone.Model.extend({
|
||||||
|
parse: function(obj) {
|
||||||
|
obj.value += 1;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var model = new Model({value: 1}, {parse: true});
|
||||||
|
equal(model.get('value'), 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: url", 3, function() {
|
||||||
|
doc.urlRoot = null;
|
||||||
|
equal(doc.url(), '/collection/1-the-tempest');
|
||||||
|
doc.collection.url = '/collection/';
|
||||||
|
equal(doc.url(), '/collection/1-the-tempest');
|
||||||
|
doc.collection = null;
|
||||||
|
raises(function() { doc.url(); });
|
||||||
|
doc.collection = collection;
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: url when using urlRoot, and uri encoding", 2, function() {
|
||||||
|
var Model = Backbone.Model.extend({
|
||||||
|
urlRoot: '/collection'
|
||||||
|
});
|
||||||
|
var model = new Model();
|
||||||
|
equal(model.url(), '/collection');
|
||||||
|
model.set({id: '+1+'});
|
||||||
|
equal(model.url(), '/collection/%2B1%2B');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: url when using urlRoot as a function to determine urlRoot at runtime", 2, function() {
|
||||||
|
var Model = Backbone.Model.extend({
|
||||||
|
urlRoot: function() {
|
||||||
|
return '/nested/' + this.get('parent_id') + '/collection';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var model = new Model({parent_id: 1});
|
||||||
|
equal(model.url(), '/nested/1/collection');
|
||||||
|
model.set({id: 2});
|
||||||
|
equal(model.url(), '/nested/1/collection/2');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: clone", 8, function() {
|
||||||
|
var a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3});
|
||||||
|
var b = a.clone();
|
||||||
|
equal(a.get('foo'), 1);
|
||||||
|
equal(a.get('bar'), 2);
|
||||||
|
equal(a.get('baz'), 3);
|
||||||
|
equal(b.get('foo'), a.get('foo'), "Foo should be the same on the clone.");
|
||||||
|
equal(b.get('bar'), a.get('bar'), "Bar should be the same on the clone.");
|
||||||
|
equal(b.get('baz'), a.get('baz'), "Baz should be the same on the clone.");
|
||||||
|
a.set({foo : 100});
|
||||||
|
equal(a.get('foo'), 100);
|
||||||
|
equal(b.get('foo'), 1, "Changing a parent attribute does not change the clone.");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: isNew", 6, function() {
|
||||||
|
var a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3});
|
||||||
|
ok(a.isNew(), "it should be new");
|
||||||
|
a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3, 'id': -5 });
|
||||||
|
ok(!a.isNew(), "any defined ID is legal, negative or positive");
|
||||||
|
a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3, 'id': 0 });
|
||||||
|
ok(!a.isNew(), "any defined ID is legal, including zero");
|
||||||
|
ok( new Backbone.Model({ }).isNew(), "is true when there is no id");
|
||||||
|
ok(!new Backbone.Model({ 'id': 2 }).isNew(), "is false for a positive integer");
|
||||||
|
ok(!new Backbone.Model({ 'id': -5 }).isNew(), "is false for a negative integer");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: get", 2, function() {
|
||||||
|
equal(doc.get('title'), 'The Tempest');
|
||||||
|
equal(doc.get('author'), 'Bill Shakespeare');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: escape", 5, function() {
|
||||||
|
equal(doc.escape('title'), 'The Tempest');
|
||||||
|
doc.set({audience: 'Bill & Bob'});
|
||||||
|
equal(doc.escape('audience'), 'Bill & Bob');
|
||||||
|
doc.set({audience: 'Tim > Joan'});
|
||||||
|
equal(doc.escape('audience'), 'Tim > Joan');
|
||||||
|
doc.set({audience: 10101});
|
||||||
|
equal(doc.escape('audience'), '10101');
|
||||||
|
doc.unset('audience');
|
||||||
|
equal(doc.escape('audience'), '');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: has", 10, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
|
||||||
|
strictEqual(model.has('name'), false);
|
||||||
|
|
||||||
|
model.set({
|
||||||
|
'0': 0,
|
||||||
|
'1': 1,
|
||||||
|
'true': true,
|
||||||
|
'false': false,
|
||||||
|
'empty': '',
|
||||||
|
'name': 'name',
|
||||||
|
'null': null,
|
||||||
|
'undefined': undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
strictEqual(model.has('0'), true);
|
||||||
|
strictEqual(model.has('1'), true);
|
||||||
|
strictEqual(model.has('true'), true);
|
||||||
|
strictEqual(model.has('false'), true);
|
||||||
|
strictEqual(model.has('empty'), true);
|
||||||
|
strictEqual(model.has('name'), true);
|
||||||
|
|
||||||
|
model.unset('name');
|
||||||
|
|
||||||
|
strictEqual(model.has('name'), false);
|
||||||
|
strictEqual(model.has('null'), false);
|
||||||
|
strictEqual(model.has('undefined'), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: set and unset", 8, function() {
|
||||||
|
var a = new Backbone.Model({id: 'id', foo: 1, bar: 2, baz: 3});
|
||||||
|
var changeCount = 0;
|
||||||
|
a.on("change:foo", function() { changeCount += 1; });
|
||||||
|
a.set({'foo': 2});
|
||||||
|
ok(a.get('foo') == 2, "Foo should have changed.");
|
||||||
|
ok(changeCount == 1, "Change count should have incremented.");
|
||||||
|
a.set({'foo': 2}); // set with value that is not new shouldn't fire change event
|
||||||
|
ok(a.get('foo') == 2, "Foo should NOT have changed, still 2");
|
||||||
|
ok(changeCount == 1, "Change count should NOT have incremented.");
|
||||||
|
|
||||||
|
a.validate = function(attrs) {
|
||||||
|
equal(attrs.foo, void 0, "don't ignore values when unsetting");
|
||||||
|
};
|
||||||
|
a.unset('foo');
|
||||||
|
equal(a.get('foo'), void 0, "Foo should have changed");
|
||||||
|
delete a.validate;
|
||||||
|
ok(changeCount == 2, "Change count should have incremented for unset.");
|
||||||
|
|
||||||
|
a.unset('id');
|
||||||
|
equal(a.id, undefined, "Unsetting the id should remove the id property.");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: multiple unsets", 1, function() {
|
||||||
|
var i = 0;
|
||||||
|
var counter = function(){ i++; };
|
||||||
|
var model = new Backbone.Model({a: 1});
|
||||||
|
model.on("change:a", counter);
|
||||||
|
model.set({a: 2});
|
||||||
|
model.unset('a');
|
||||||
|
model.unset('a');
|
||||||
|
equal(i, 2, 'Unset does not fire an event for missing attributes.');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: unset and changedAttributes", 2, function() {
|
||||||
|
var model = new Backbone.Model({a: 1});
|
||||||
|
model.unset('a', {silent: true});
|
||||||
|
var changedAttributes = model.changedAttributes();
|
||||||
|
ok('a' in changedAttributes, 'changedAttributes should contain unset properties');
|
||||||
|
|
||||||
|
changedAttributes = model.changedAttributes();
|
||||||
|
ok('a' in changedAttributes, 'changedAttributes should contain unset properties when running changedAttributes again after an unset.');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: using a non-default id attribute.", 5, function() {
|
||||||
|
var MongoModel = Backbone.Model.extend({idAttribute : '_id'});
|
||||||
|
var model = new MongoModel({id: 'eye-dee', _id: 25, title: 'Model'});
|
||||||
|
equal(model.get('id'), 'eye-dee');
|
||||||
|
equal(model.id, 25);
|
||||||
|
equal(model.isNew(), false);
|
||||||
|
model.unset('_id');
|
||||||
|
equal(model.id, undefined);
|
||||||
|
equal(model.isNew(), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: set an empty string", 1, function() {
|
||||||
|
var model = new Backbone.Model({name : "Model"});
|
||||||
|
model.set({name : ''});
|
||||||
|
equal(model.get('name'), '');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: clear", 3, function() {
|
||||||
|
var changed;
|
||||||
|
var model = new Backbone.Model({id: 1, name : "Model"});
|
||||||
|
model.on("change:name", function(){ changed = true; });
|
||||||
|
model.on("change", function() {
|
||||||
|
var changedAttrs = model.changedAttributes();
|
||||||
|
ok('name' in changedAttrs);
|
||||||
|
});
|
||||||
|
model.clear();
|
||||||
|
equal(changed, true);
|
||||||
|
equal(model.get('name'), undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: defaults", 4, function() {
|
||||||
|
var Defaulted = Backbone.Model.extend({
|
||||||
|
defaults: {
|
||||||
|
"one": 1,
|
||||||
|
"two": 2
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var model = new Defaulted({two: null});
|
||||||
|
equal(model.get('one'), 1);
|
||||||
|
equal(model.get('two'), null);
|
||||||
|
Defaulted = Backbone.Model.extend({
|
||||||
|
defaults: function() {
|
||||||
|
return {
|
||||||
|
"one": 3,
|
||||||
|
"two": 4
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var model = new Defaulted({two: null});
|
||||||
|
equal(model.get('one'), 3);
|
||||||
|
equal(model.get('two'), null);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: change, hasChanged, changedAttributes, previous, previousAttributes", 12, function() {
|
||||||
|
var model = new Backbone.Model({name : "Tim", age : 10});
|
||||||
|
equal(model.changedAttributes(), false);
|
||||||
|
model.on('change', function() {
|
||||||
|
ok(model.hasChanged('name'), 'name changed');
|
||||||
|
ok(!model.hasChanged('age'), 'age did not');
|
||||||
|
ok(_.isEqual(model.changedAttributes(), {name : 'Rob'}), 'changedAttributes returns the changed attrs');
|
||||||
|
equal(model.previous('name'), 'Tim');
|
||||||
|
ok(_.isEqual(model.previousAttributes(), {name : "Tim", age : 10}), 'previousAttributes is correct');
|
||||||
|
});
|
||||||
|
equal(model.hasChanged(), false);
|
||||||
|
equal(model.hasChanged(undefined), false);
|
||||||
|
model.set({name : 'Rob'}, {silent : true});
|
||||||
|
equal(model.hasChanged(), true);
|
||||||
|
equal(model.hasChanged(undefined), true);
|
||||||
|
equal(model.hasChanged('name'), true);
|
||||||
|
model.change();
|
||||||
|
equal(model.get('name'), 'Rob');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: changedAttributes", 3, function() {
|
||||||
|
var model = new Backbone.Model({a: 'a', b: 'b'});
|
||||||
|
equal(model.changedAttributes(), false);
|
||||||
|
equal(model.changedAttributes({a: 'a'}), false);
|
||||||
|
equal(model.changedAttributes({a: 'b'}).a, 'b');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: change with options", 2, function() {
|
||||||
|
var value;
|
||||||
|
var model = new Backbone.Model({name: 'Rob'});
|
||||||
|
model.on('change', function(model, options) {
|
||||||
|
value = options.prefix + model.get('name');
|
||||||
|
});
|
||||||
|
model.set({name: 'Bob'}, {silent: true});
|
||||||
|
model.change({prefix: 'Mr. '});
|
||||||
|
equal(value, 'Mr. Bob');
|
||||||
|
model.set({name: 'Sue'}, {prefix: 'Ms. '});
|
||||||
|
equal(value, 'Ms. Sue');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: change after initialize", 1, function () {
|
||||||
|
var changed = 0;
|
||||||
|
var attrs = {id: 1, label: 'c'};
|
||||||
|
var obj = new Backbone.Model(attrs);
|
||||||
|
obj.on('change', function() { changed += 1; });
|
||||||
|
obj.set(attrs);
|
||||||
|
equal(changed, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: save within change event", 1, function () {
|
||||||
|
var model = new Backbone.Model({firstName : "Taylor", lastName: "Swift"});
|
||||||
|
model.on('change', function () {
|
||||||
|
model.save();
|
||||||
|
ok(_.isEqual(lastRequest.model, model));
|
||||||
|
});
|
||||||
|
model.set({lastName: 'Hicks'});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: validate after save", 1, function() {
|
||||||
|
var lastError, model = new Backbone.Model();
|
||||||
|
model.validate = function(attrs) {
|
||||||
|
if (attrs.admin) return "Can't change admin status.";
|
||||||
|
};
|
||||||
|
model.sync = function(method, model, options) {
|
||||||
|
options.success.call(this, {admin: true});
|
||||||
|
};
|
||||||
|
model.save(null, {error: function(model, error) {
|
||||||
|
lastError = error;
|
||||||
|
}});
|
||||||
|
|
||||||
|
equal(lastError, "Can't change admin status.");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: isValid", 5, function() {
|
||||||
|
var model = new Backbone.Model({valid: true});
|
||||||
|
model.validate = function(attrs) {
|
||||||
|
if (!attrs.valid) return "invalid";
|
||||||
|
};
|
||||||
|
equal(model.isValid(), true);
|
||||||
|
equal(model.set({valid: false}), false);
|
||||||
|
equal(model.isValid(), true);
|
||||||
|
ok(model.set('valid', false, {silent: true}));
|
||||||
|
equal(model.isValid(), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: save", 2, function() {
|
||||||
|
doc.save({title : "Henry V"});
|
||||||
|
equal(lastRequest.method, 'update');
|
||||||
|
ok(_.isEqual(lastRequest.model, doc));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: save in positional style", 1, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.sync = function(method, model, options) {
|
||||||
|
options.success();
|
||||||
|
};
|
||||||
|
model.save('title', 'Twelfth Night');
|
||||||
|
equal(model.get('title'), 'Twelfth Night');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
test("Model: fetch", 2, function() {
|
||||||
|
doc.fetch();
|
||||||
|
equal(lastRequest.method, 'read');
|
||||||
|
ok(_.isEqual(lastRequest.model, doc));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: destroy", 3, function() {
|
||||||
|
doc.destroy();
|
||||||
|
equal(lastRequest.method, 'delete');
|
||||||
|
ok(_.isEqual(lastRequest.model, doc));
|
||||||
|
|
||||||
|
var newModel = new Backbone.Model;
|
||||||
|
equal(newModel.destroy(), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: non-persisted destroy", 1, function() {
|
||||||
|
var a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3});
|
||||||
|
a.sync = function() { throw "should not be called"; };
|
||||||
|
a.destroy();
|
||||||
|
ok(true, "non-persisted model should not call sync");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: validate", 7, function() {
|
||||||
|
var lastError;
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.validate = function(attrs) {
|
||||||
|
if (attrs.admin != this.get('admin')) return "Can't change admin status.";
|
||||||
|
};
|
||||||
|
model.on('error', function(model, error) {
|
||||||
|
lastError = error;
|
||||||
|
});
|
||||||
|
var result = model.set({a: 100});
|
||||||
|
equal(result, model);
|
||||||
|
equal(model.get('a'), 100);
|
||||||
|
equal(lastError, undefined);
|
||||||
|
result = model.set({admin: true}, {silent: true});
|
||||||
|
equal(model.get('admin'), true);
|
||||||
|
result = model.set({a: 200, admin: false});
|
||||||
|
equal(lastError, "Can't change admin status.");
|
||||||
|
equal(result, false);
|
||||||
|
equal(model.get('a'), 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: validate on unset and clear", 6, function() {
|
||||||
|
var error;
|
||||||
|
var model = new Backbone.Model({name: "One"});
|
||||||
|
model.validate = function(attrs) {
|
||||||
|
if (!attrs.name) {
|
||||||
|
error = true;
|
||||||
|
return "No thanks.";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
model.set({name: "Two"});
|
||||||
|
equal(model.get('name'), 'Two');
|
||||||
|
equal(error, undefined);
|
||||||
|
model.unset('name');
|
||||||
|
equal(error, true);
|
||||||
|
equal(model.get('name'), 'Two');
|
||||||
|
model.clear();
|
||||||
|
equal(model.get('name'), 'Two');
|
||||||
|
delete model.validate;
|
||||||
|
model.clear();
|
||||||
|
equal(model.get('name'), undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: validate with error callback", 8, function() {
|
||||||
|
var lastError, boundError;
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.validate = function(attrs) {
|
||||||
|
if (attrs.admin) return "Can't change admin status.";
|
||||||
|
};
|
||||||
|
var callback = function(model, error) {
|
||||||
|
lastError = error;
|
||||||
|
};
|
||||||
|
model.on('error', function(model, error) {
|
||||||
|
boundError = true;
|
||||||
|
});
|
||||||
|
var result = model.set({a: 100}, {error: callback});
|
||||||
|
equal(result, model);
|
||||||
|
equal(model.get('a'), 100);
|
||||||
|
equal(lastError, undefined);
|
||||||
|
equal(boundError, undefined);
|
||||||
|
result = model.set({a: 200, admin: true}, {error: callback});
|
||||||
|
equal(result, false);
|
||||||
|
equal(model.get('a'), 100);
|
||||||
|
equal(lastError, "Can't change admin status.");
|
||||||
|
equal(boundError, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: defaults always extend attrs (#459)", 2, function() {
|
||||||
|
var Defaulted = Backbone.Model.extend({
|
||||||
|
defaults: {one: 1},
|
||||||
|
initialize : function(attrs, opts) {
|
||||||
|
equal(this.attributes.one, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var providedattrs = new Defaulted({});
|
||||||
|
var emptyattrs = new Defaulted();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: Inherit class properties", 6, function() {
|
||||||
|
var Parent = Backbone.Model.extend({
|
||||||
|
instancePropSame: function() {},
|
||||||
|
instancePropDiff: function() {}
|
||||||
|
}, {
|
||||||
|
classProp: function() {}
|
||||||
|
});
|
||||||
|
var Child = Parent.extend({
|
||||||
|
instancePropDiff: function() {}
|
||||||
|
});
|
||||||
|
|
||||||
|
var adult = new Parent;
|
||||||
|
var kid = new Child;
|
||||||
|
|
||||||
|
equal(Child.classProp, Parent.classProp);
|
||||||
|
notEqual(Child.classProp, undefined);
|
||||||
|
|
||||||
|
equal(kid.instancePropSame, adult.instancePropSame);
|
||||||
|
notEqual(kid.instancePropSame, undefined);
|
||||||
|
|
||||||
|
notEqual(Child.prototype.instancePropDiff, Parent.prototype.instancePropDiff);
|
||||||
|
notEqual(Child.prototype.instancePropDiff, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Model: Nested change events don't clobber previous attributes", 4, function() {
|
||||||
|
new Backbone.Model()
|
||||||
|
.on('change:state', function(model, newState) {
|
||||||
|
equal(model.previous('state'), undefined);
|
||||||
|
equal(newState, 'hello');
|
||||||
|
// Fire a nested change event.
|
||||||
|
model.set({other: 'whatever'});
|
||||||
|
})
|
||||||
|
.on('change:state', function(model, newState) {
|
||||||
|
equal(model.previous('state'), undefined);
|
||||||
|
equal(newState, 'hello');
|
||||||
|
})
|
||||||
|
.set({state: 'hello'});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("hasChanged/set should use same comparison", 2, function() {
|
||||||
|
var changed = 0, model = new Backbone.Model({a: null});
|
||||||
|
model.on('change', function() {
|
||||||
|
ok(this.hasChanged('a'));
|
||||||
|
})
|
||||||
|
.on('change:a', function() {
|
||||||
|
changed++;
|
||||||
|
})
|
||||||
|
.set({a: undefined});
|
||||||
|
equal(changed, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#582, #425, change:attribute callbacks should fire after all changes have occurred", 9, function() {
|
||||||
|
var model = new Backbone.Model;
|
||||||
|
|
||||||
|
var assertion = function() {
|
||||||
|
equal(model.get('a'), 'a');
|
||||||
|
equal(model.get('b'), 'b');
|
||||||
|
equal(model.get('c'), 'c');
|
||||||
|
};
|
||||||
|
|
||||||
|
model.on('change:a', assertion);
|
||||||
|
model.on('change:b', assertion);
|
||||||
|
model.on('change:c', assertion);
|
||||||
|
|
||||||
|
model.set({a: 'a', b: 'b', c: 'c'});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#871, set with attributes property", 1, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.set({attributes: true});
|
||||||
|
ok(model.has('attributes'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("set value regardless of equality/change", 1, function() {
|
||||||
|
var model = new Backbone.Model({x: []});
|
||||||
|
var a = [];
|
||||||
|
model.set({x: a});
|
||||||
|
ok(model.get('x') === a);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("unset fires change for undefined attributes", 1, function() {
|
||||||
|
var model = new Backbone.Model({x: undefined});
|
||||||
|
model.on('change:x', function(){ ok(true); });
|
||||||
|
model.unset('x');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("set: undefined values", 1, function() {
|
||||||
|
var model = new Backbone.Model({x: undefined});
|
||||||
|
ok('x' in model.attributes);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("change fires change:attr", 1, function() {
|
||||||
|
var model = new Backbone.Model({x: 1});
|
||||||
|
model.set({x: 2}, {silent: true});
|
||||||
|
model.on('change:x', function(){ ok(true); });
|
||||||
|
model.change();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("hasChanged is false after original values are set", 2, function() {
|
||||||
|
var model = new Backbone.Model({x: 1});
|
||||||
|
model.on('change:x', function(){ ok(false); });
|
||||||
|
model.set({x: 2}, {silent: true});
|
||||||
|
ok(model.hasChanged());
|
||||||
|
model.set({x: 1}, {silent: true});
|
||||||
|
ok(!model.hasChanged());
|
||||||
|
});
|
||||||
|
|
||||||
|
test("save with `wait` succeeds without `validate`", 1, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.save({x: 1}, {wait: true});
|
||||||
|
ok(lastRequest.model === model);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("`hasChanged` for falsey keys", 2, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.set({x: true}, {silent: true});
|
||||||
|
ok(!model.hasChanged(0));
|
||||||
|
ok(!model.hasChanged(''));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("`previous` for falsey keys", 2, function() {
|
||||||
|
var model = new Backbone.Model({0: true, '': true});
|
||||||
|
model.set({0: false, '': false}, {silent: true});
|
||||||
|
equal(model.previous(0), true);
|
||||||
|
equal(model.previous(''), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("`save` with `wait` sends correct attributes", 5, function() {
|
||||||
|
var changed = 0;
|
||||||
|
var model = new Backbone.Model({x: 1, y: 2});
|
||||||
|
model.on('change:x', function() { changed++; });
|
||||||
|
model.save({x: 3}, {wait: true});
|
||||||
|
deepEqual(JSON.parse(ajaxParams.data), {x: 3, y: 2});
|
||||||
|
equal(model.get('x'), 1);
|
||||||
|
equal(changed, 0);
|
||||||
|
lastRequest.options.success({});
|
||||||
|
equal(model.get('x'), 3);
|
||||||
|
equal(changed, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("a failed `save` with `wait` doesn't leave attributes behind", 1, function() {
|
||||||
|
var model = new Backbone.Model;
|
||||||
|
model.save({x: 1}, {wait: true});
|
||||||
|
equal(model.get('x'), void 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1030 - `save` with `wait` results in correct attributes if success is called during sync", 2, function() {
|
||||||
|
var model = new Backbone.Model({x: 1, y: 2});
|
||||||
|
model.sync = function(method, model, options) {
|
||||||
|
options.success();
|
||||||
|
};
|
||||||
|
model.on("change:x", function() { ok(true); });
|
||||||
|
model.save({x: 3}, {wait: true});
|
||||||
|
equal(model.get('x'), 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("save with wait validates attributes", 1, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.validate = function() { ok(true); };
|
||||||
|
model.save({x: 1}, {wait: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("nested `set` during `'change:attr'`", 2, function() {
|
||||||
|
var events = [];
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.on('all', function(event) { events.push(event); });
|
||||||
|
model.on('change', function() {
|
||||||
|
model.set({z: true}, {silent:true});
|
||||||
|
});
|
||||||
|
model.on('change:x', function() {
|
||||||
|
model.set({y: true});
|
||||||
|
});
|
||||||
|
model.set({x: true});
|
||||||
|
deepEqual(events, ['change:y', 'change:x', 'change']);
|
||||||
|
events = [];
|
||||||
|
model.change();
|
||||||
|
deepEqual(events, ['change:z', 'change']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("nested `change` only fires once", 1, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.on('change', function() {
|
||||||
|
ok(true);
|
||||||
|
model.change();
|
||||||
|
});
|
||||||
|
model.set({x: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("no `'change'` event if no changes", 0, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.on('change', function() { ok(false); });
|
||||||
|
model.change();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("nested `set` during `'change'`", 6, function() {
|
||||||
|
var count = 0;
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.on('change', function() {
|
||||||
|
switch(count++) {
|
||||||
|
case 0:
|
||||||
|
deepEqual(this.changedAttributes(), {x: true});
|
||||||
|
equal(model.previous('x'), undefined);
|
||||||
|
model.set({y: true});
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
deepEqual(this.changedAttributes(), {y: true});
|
||||||
|
equal(model.previous('x'), true);
|
||||||
|
model.set({z: true});
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
deepEqual(this.changedAttributes(), {z: true});
|
||||||
|
equal(model.previous('y'), true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ok(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
model.set({x: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("nested `'change'` with silent", 3, function() {
|
||||||
|
var count = 0;
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.on('change:y', function() { ok(true); });
|
||||||
|
model.on('change', function() {
|
||||||
|
switch(count++) {
|
||||||
|
case 0:
|
||||||
|
deepEqual(this.changedAttributes(), {x: true});
|
||||||
|
model.set({y: true}, {silent: true});
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
deepEqual(this.changedAttributes(), {y: true, z: true});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ok(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
model.set({x: true});
|
||||||
|
model.set({z: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("nested `'change:attr'` with silent", 1, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.on('change:y', function(){ ok(true); });
|
||||||
|
model.on('change', function() {
|
||||||
|
model.set({y: true}, {silent: true});
|
||||||
|
model.set({z: true});
|
||||||
|
});
|
||||||
|
model.set({x: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("multiple nested changes with silent", 1, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.on('change:x', function() {
|
||||||
|
model.set({y: 1}, {silent: true});
|
||||||
|
model.set({y: 2});
|
||||||
|
});
|
||||||
|
model.on('change:y', function(model, val) {
|
||||||
|
equal(val, 2);
|
||||||
|
});
|
||||||
|
model.set({x: true});
|
||||||
|
model.change();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("multiple nested changes with silent", 2, function() {
|
||||||
|
var changes = [];
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.on('change:b', function(model, val) { changes.push(val); });
|
||||||
|
model.on('change', function() {
|
||||||
|
model.set({b: 1});
|
||||||
|
model.set({b: 2}, {silent: true});
|
||||||
|
});
|
||||||
|
model.set({b: 0});
|
||||||
|
deepEqual(changes, [0, 1, 1]);
|
||||||
|
model.change();
|
||||||
|
deepEqual(changes, [0, 1, 1, 2, 1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("nested set multiple times", 1, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.on('change:b', function() {
|
||||||
|
ok(true);
|
||||||
|
});
|
||||||
|
model.on('change:a', function() {
|
||||||
|
model.set({b: true});
|
||||||
|
model.set({b: true});
|
||||||
|
});
|
||||||
|
model.set({a: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Backbone.wrapError triggers `'error'`", 12, function() {
|
||||||
|
var resp = {};
|
||||||
|
var options = {};
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.on('error', error);
|
||||||
|
var callback = Backbone.wrapError(null, model, options);
|
||||||
|
callback(model, resp);
|
||||||
|
callback(resp);
|
||||||
|
callback = Backbone.wrapError(error, model, options);
|
||||||
|
callback(model, resp);
|
||||||
|
callback(resp);
|
||||||
|
function error(_model, _resp, _options) {
|
||||||
|
ok(model === _model);
|
||||||
|
ok(resp === _resp);
|
||||||
|
ok(options === _options);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1179 - isValid returns true in the absence of validate.", 1, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.validate = null;
|
||||||
|
ok(model.isValid());
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1122 - clear does not alter options.", 1, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
var options = {};
|
||||||
|
model.clear(options);
|
||||||
|
ok(!options.unset);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1122 - unset does not alter options.", 1, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
var options = {};
|
||||||
|
model.unset('x', options);
|
||||||
|
ok(!options.unset);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1355 - `options` is passed to success callbacks", 3, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
var opts = {
|
||||||
|
success: function( model, resp, options ) {
|
||||||
|
ok(options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
model.sync = function(method, model, options) {
|
||||||
|
options.success();
|
||||||
|
};
|
||||||
|
model.save({id: 1}, opts);
|
||||||
|
model.fetch(opts);
|
||||||
|
model.destroy(opts);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1412 - Trigger 'sync' event.", 3, function() {
|
||||||
|
var model = new Backbone.Model({id: 1});
|
||||||
|
model.sync = function(method, model, options) { options.success(); };
|
||||||
|
model.on('sync', function() { ok(true); });
|
||||||
|
model.fetch();
|
||||||
|
model.save();
|
||||||
|
model.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1365 - Destroy: New models execute success callback.", 2, function() {
|
||||||
|
new Backbone.Model()
|
||||||
|
.on('sync', function() { ok(false); })
|
||||||
|
.on('destroy', function(){ ok(true); })
|
||||||
|
.destroy({ success: function(){ ok(true); }});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1433 - Save: An invalid model cannot be persisted.", 1, function() {
|
||||||
|
var model = new Backbone.Model;
|
||||||
|
model.validate = function(){ return 'invalid'; };
|
||||||
|
model.sync = function(){ ok(false); };
|
||||||
|
strictEqual(model.save(), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
12
vendor/backbone/test/noconflict.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
module("Backbone.noConflict");
|
||||||
|
|
||||||
|
test('Backbone.noConflict', 2, function() {
|
||||||
|
var noconflictBackbone = Backbone.noConflict();
|
||||||
|
equal(window.Backbone, undefined, 'Returned window.Backbone');
|
||||||
|
window.Backbone = noconflictBackbone;
|
||||||
|
equal(window.Backbone, noconflictBackbone, 'Backbone is still pointing to the original Backbone');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
321
vendor/backbone/test/router.js
vendored
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
var router = null;
|
||||||
|
var location = null;
|
||||||
|
var lastRoute = null;
|
||||||
|
var lastArgs = [];
|
||||||
|
|
||||||
|
function onRoute(router, route, args) {
|
||||||
|
lastRoute = route;
|
||||||
|
lastArgs = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
var Location = function(href) {
|
||||||
|
this.replace(href);
|
||||||
|
};
|
||||||
|
|
||||||
|
_.extend(Location.prototype, {
|
||||||
|
|
||||||
|
replace: function(href) {
|
||||||
|
_.extend(this, _.pick($('<a></a>', {href: href})[0],
|
||||||
|
'href',
|
||||||
|
'hash',
|
||||||
|
'search',
|
||||||
|
'fragment',
|
||||||
|
'pathname'
|
||||||
|
));
|
||||||
|
// In IE, anchor.pathname does not contain a leading slash though
|
||||||
|
// window.location.pathname does.
|
||||||
|
if (!/^\//.test(this.pathname)) this.pathname = '/' + this.pathname;
|
||||||
|
},
|
||||||
|
|
||||||
|
toString: function() {
|
||||||
|
return this.href;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
module("Backbone.Router", {
|
||||||
|
|
||||||
|
setup: function() {
|
||||||
|
location = new Location('http://example.com');
|
||||||
|
Backbone.history = new Backbone.History({location: location});
|
||||||
|
router = new Router({testing: 101});
|
||||||
|
Backbone.history.interval = 9;
|
||||||
|
Backbone.history.start({pushState: false});
|
||||||
|
lastRoute = null;
|
||||||
|
lastArgs = [];
|
||||||
|
Backbone.history.on('route', onRoute);
|
||||||
|
},
|
||||||
|
|
||||||
|
teardown: function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
Backbone.history.off('route', onRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var Router = Backbone.Router.extend({
|
||||||
|
|
||||||
|
count: 0,
|
||||||
|
|
||||||
|
routes: {
|
||||||
|
"noCallback": "noCallback",
|
||||||
|
"counter": "counter",
|
||||||
|
"search/:query": "search",
|
||||||
|
"search/:query/p:page": "search",
|
||||||
|
"contacts": "contacts",
|
||||||
|
"contacts/new": "newContact",
|
||||||
|
"contacts/:id": "loadContact",
|
||||||
|
"splat/*args/end": "splat",
|
||||||
|
"*first/complex-:part/*rest": "complex",
|
||||||
|
":entity?*args": "query",
|
||||||
|
"*anything": "anything"
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize : function(options) {
|
||||||
|
this.testing = options.testing;
|
||||||
|
this.route('implicit', 'implicit');
|
||||||
|
},
|
||||||
|
|
||||||
|
counter: function() {
|
||||||
|
this.count++;
|
||||||
|
},
|
||||||
|
|
||||||
|
implicit: function() {
|
||||||
|
this.count++;
|
||||||
|
},
|
||||||
|
|
||||||
|
search : function(query, page) {
|
||||||
|
this.query = query;
|
||||||
|
this.page = page;
|
||||||
|
},
|
||||||
|
|
||||||
|
contacts: function(){
|
||||||
|
this.contact = 'index';
|
||||||
|
},
|
||||||
|
|
||||||
|
newContact: function(){
|
||||||
|
this.contact = 'new';
|
||||||
|
},
|
||||||
|
|
||||||
|
loadContact: function(){
|
||||||
|
this.contact = 'load';
|
||||||
|
},
|
||||||
|
|
||||||
|
splat : function(args) {
|
||||||
|
this.args = args;
|
||||||
|
},
|
||||||
|
|
||||||
|
complex : function(first, part, rest) {
|
||||||
|
this.first = first;
|
||||||
|
this.part = part;
|
||||||
|
this.rest = rest;
|
||||||
|
},
|
||||||
|
|
||||||
|
query : function(entity, args) {
|
||||||
|
this.entity = entity;
|
||||||
|
this.queryArgs = args;
|
||||||
|
},
|
||||||
|
|
||||||
|
anything : function(whatever) {
|
||||||
|
this.anything = whatever;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: initialize", 1, function() {
|
||||||
|
equal(router.testing, 101);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: routes (simple)", 4, function() {
|
||||||
|
location.replace('http://example.com#search/news');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
equal(router.query, 'news');
|
||||||
|
equal(router.page, undefined);
|
||||||
|
equal(lastRoute, 'search');
|
||||||
|
equal(lastArgs[0], 'news');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: routes (two part)", 2, function() {
|
||||||
|
location.replace('http://example.com#search/nyc/p10');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
equal(router.query, 'nyc');
|
||||||
|
equal(router.page, '10');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: routes via navigate", 2, function() {
|
||||||
|
Backbone.history.navigate('search/manhattan/p20', {trigger: true});
|
||||||
|
equal(router.query, 'manhattan');
|
||||||
|
equal(router.page, '20');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: routes via navigate for backwards-compatibility", 2, function() {
|
||||||
|
Backbone.history.navigate('search/manhattan/p20', true);
|
||||||
|
equal(router.query, 'manhattan');
|
||||||
|
equal(router.page, '20');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: route precedence via navigate", 6, function(){
|
||||||
|
// check both 0.9.x and backwards-compatibility options
|
||||||
|
_.each([ { trigger: true }, true ], function( options ){
|
||||||
|
Backbone.history.navigate('contacts', options);
|
||||||
|
equal(router.contact, 'index');
|
||||||
|
Backbone.history.navigate('contacts/new', options);
|
||||||
|
equal(router.contact, 'new');
|
||||||
|
Backbone.history.navigate('contacts/foo', options);
|
||||||
|
equal(router.contact, 'load');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("loadUrl is not called for identical routes.", 0, function() {
|
||||||
|
Backbone.history.loadUrl = function(){ ok(false); };
|
||||||
|
location.replace('http://example.com#route');
|
||||||
|
Backbone.history.navigate('route');
|
||||||
|
Backbone.history.navigate('/route');
|
||||||
|
Backbone.history.navigate('/route');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: use implicit callback if none provided", 1, function() {
|
||||||
|
router.count = 0;
|
||||||
|
router.navigate('implicit', {trigger: true});
|
||||||
|
equal(router.count, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: routes via navigate with {replace: true}", 1, function() {
|
||||||
|
location.replace('http://example.com#start_here');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
location.replace = function(href) {
|
||||||
|
strictEqual(href, new Location('http://example.com#end_here').href);
|
||||||
|
};
|
||||||
|
Backbone.history.navigate('end_here', {replace: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: routes (splats)", 1, function() {
|
||||||
|
location.replace('http://example.com#splat/long-list/of/splatted_99args/end');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
equal(router.args, 'long-list/of/splatted_99args');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: routes (complex)", 3, function() {
|
||||||
|
location.replace('http://example.com#one/two/three/complex-part/four/five/six/seven');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
equal(router.first, 'one/two/three');
|
||||||
|
equal(router.part, 'part');
|
||||||
|
equal(router.rest, 'four/five/six/seven');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: routes (query)", 5, function() {
|
||||||
|
location.replace('http://example.com#mandel?a=b&c=d');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
equal(router.entity, 'mandel');
|
||||||
|
equal(router.queryArgs, 'a=b&c=d');
|
||||||
|
equal(lastRoute, 'query');
|
||||||
|
equal(lastArgs[0], 'mandel');
|
||||||
|
equal(lastArgs[1], 'a=b&c=d');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: routes (anything)", 1, function() {
|
||||||
|
location.replace('http://example.com#doesnt-match-a-route');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
equal(router.anything, 'doesnt-match-a-route');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: fires event when router doesn't have callback on it", 1, function() {
|
||||||
|
router.on("route:noCallback", function(){ ok(true); });
|
||||||
|
location.replace('http://example.com#noCallback');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#933, #908 - leading slash", 2, function() {
|
||||||
|
location.replace('http://example.com/root/foo');
|
||||||
|
|
||||||
|
Backbone.history.stop();
|
||||||
|
Backbone.history = new Backbone.History({location: location});
|
||||||
|
Backbone.history.start({root: '/root', hashChange: false, silent: true});
|
||||||
|
strictEqual(Backbone.history.getFragment(), 'foo');
|
||||||
|
|
||||||
|
Backbone.history.stop();
|
||||||
|
Backbone.history = new Backbone.History({location: location});
|
||||||
|
Backbone.history.start({root: '/root/', hashChange: false, silent: true});
|
||||||
|
strictEqual(Backbone.history.getFragment(), 'foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1003 - History is started before navigate is called", 1, function() {
|
||||||
|
var history = new Backbone.History();
|
||||||
|
history.navigate = function(){
|
||||||
|
ok(Backbone.History.started);
|
||||||
|
};
|
||||||
|
Backbone.history.stop();
|
||||||
|
history.start();
|
||||||
|
// If this is not an old IE navigate will not be called.
|
||||||
|
if (!history.iframe) ok(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: route callback gets passed decoded values", 3, function() {
|
||||||
|
var route = 'has%2Fslash/complex-has%23hash/has%20space';
|
||||||
|
Backbone.history.navigate(route, {trigger: true});
|
||||||
|
equal(router.first, 'has/slash');
|
||||||
|
equal(router.part, 'has#hash');
|
||||||
|
equal(router.rest, 'has space');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: correctly handles URLs with % (#868)", 3, function() {
|
||||||
|
location.replace('http://example.com#search/fat%3A1.5%25');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
location.replace('http://example.com#search/fat');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
equal(router.query, 'fat');
|
||||||
|
equal(router.page, undefined);
|
||||||
|
equal(lastRoute, 'search');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1185 - Use pathname when hashChange is not wanted.", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/path/name#hash');
|
||||||
|
Backbone.history = new Backbone.History({location: location});
|
||||||
|
Backbone.history.start({hashChange: false});
|
||||||
|
var fragment = Backbone.history.getFragment();
|
||||||
|
strictEqual(fragment, location.pathname.replace(/^\//, ''));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1206 - Strip leading slash before location.assign.", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/root/');
|
||||||
|
Backbone.history = new Backbone.History({location: location});
|
||||||
|
Backbone.history.start({hashChange: false, root: '/root/'});
|
||||||
|
location.assign = function(pathname) {
|
||||||
|
strictEqual(pathname, '/root/fragment');
|
||||||
|
};
|
||||||
|
Backbone.history.navigate('/fragment');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1387 - Root fragment without trailing slash.", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/root');
|
||||||
|
Backbone.history = new Backbone.History({location: location});
|
||||||
|
Backbone.history.start({hashChange: false, root: '/root/', silent: true});
|
||||||
|
strictEqual(Backbone.history.getFragment(), '');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1366 - History does not prepend root to fragment.", 2, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/root/');
|
||||||
|
Backbone.history = new Backbone.History({
|
||||||
|
location: location,
|
||||||
|
history: {
|
||||||
|
pushState: function(state, title, url) {
|
||||||
|
strictEqual(url, '/root/x');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Backbone.history.start({
|
||||||
|
root: '/root/',
|
||||||
|
pushState: true,
|
||||||
|
hashChange: false
|
||||||
|
});
|
||||||
|
Backbone.history.navigate('x');
|
||||||
|
strictEqual(Backbone.history.fragment, 'x');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
160
vendor/backbone/test/sync.js
vendored
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
var ajax = Backbone.ajax;
|
||||||
|
var lastRequest = null;
|
||||||
|
|
||||||
|
var Library = Backbone.Collection.extend({
|
||||||
|
url : function() { return '/library'; }
|
||||||
|
});
|
||||||
|
var library;
|
||||||
|
|
||||||
|
var attrs = {
|
||||||
|
title : "The Tempest",
|
||||||
|
author : "Bill Shakespeare",
|
||||||
|
length : 123
|
||||||
|
};
|
||||||
|
|
||||||
|
module("Backbone.sync", {
|
||||||
|
|
||||||
|
setup : function() {
|
||||||
|
library = new Library();
|
||||||
|
Backbone.ajax = function(obj) {
|
||||||
|
lastRequest = obj;
|
||||||
|
};
|
||||||
|
library.create(attrs, {wait: false});
|
||||||
|
},
|
||||||
|
|
||||||
|
teardown: function() {
|
||||||
|
Backbone.ajax = ajax;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sync: read", 4, function() {
|
||||||
|
library.fetch();
|
||||||
|
equal(lastRequest.url, '/library');
|
||||||
|
equal(lastRequest.type, 'GET');
|
||||||
|
equal(lastRequest.dataType, 'json');
|
||||||
|
ok(_.isEmpty(lastRequest.data));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sync: passing data", 3, function() {
|
||||||
|
library.fetch({data: {a: 'a', one: 1}});
|
||||||
|
equal(lastRequest.url, '/library');
|
||||||
|
equal(lastRequest.data.a, 'a');
|
||||||
|
equal(lastRequest.data.one, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sync: create", 6, function() {
|
||||||
|
equal(lastRequest.url, '/library');
|
||||||
|
equal(lastRequest.type, 'POST');
|
||||||
|
equal(lastRequest.dataType, 'json');
|
||||||
|
var data = JSON.parse(lastRequest.data);
|
||||||
|
equal(data.title, 'The Tempest');
|
||||||
|
equal(data.author, 'Bill Shakespeare');
|
||||||
|
equal(data.length, 123);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sync: update", 7, function() {
|
||||||
|
library.first().save({id: '1-the-tempest', author: 'William Shakespeare'});
|
||||||
|
equal(lastRequest.url, '/library/1-the-tempest');
|
||||||
|
equal(lastRequest.type, 'PUT');
|
||||||
|
equal(lastRequest.dataType, 'json');
|
||||||
|
var data = JSON.parse(lastRequest.data);
|
||||||
|
equal(data.id, '1-the-tempest');
|
||||||
|
equal(data.title, 'The Tempest');
|
||||||
|
equal(data.author, 'William Shakespeare');
|
||||||
|
equal(data.length, 123);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sync: update with emulateHTTP and emulateJSON", 7, function() {
|
||||||
|
Backbone.emulateHTTP = Backbone.emulateJSON = true;
|
||||||
|
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||||
|
equal(lastRequest.url, '/library/2-the-tempest');
|
||||||
|
equal(lastRequest.type, 'POST');
|
||||||
|
equal(lastRequest.dataType, 'json');
|
||||||
|
equal(lastRequest.data._method, 'PUT');
|
||||||
|
var data = JSON.parse(lastRequest.data.model);
|
||||||
|
equal(data.id, '2-the-tempest');
|
||||||
|
equal(data.author, 'Tim Shakespeare');
|
||||||
|
equal(data.length, 123);
|
||||||
|
Backbone.emulateHTTP = Backbone.emulateJSON = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sync: update with just emulateHTTP", 6, function() {
|
||||||
|
Backbone.emulateHTTP = true;
|
||||||
|
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||||
|
equal(lastRequest.url, '/library/2-the-tempest');
|
||||||
|
equal(lastRequest.type, 'POST');
|
||||||
|
equal(lastRequest.contentType, 'application/json');
|
||||||
|
var data = JSON.parse(lastRequest.data);
|
||||||
|
equal(data.id, '2-the-tempest');
|
||||||
|
equal(data.author, 'Tim Shakespeare');
|
||||||
|
equal(data.length, 123);
|
||||||
|
Backbone.emulateHTTP = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sync: update with just emulateJSON", 6, function() {
|
||||||
|
Backbone.emulateJSON = true;
|
||||||
|
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||||
|
equal(lastRequest.url, '/library/2-the-tempest');
|
||||||
|
equal(lastRequest.type, 'PUT');
|
||||||
|
equal(lastRequest.contentType, 'application/x-www-form-urlencoded');
|
||||||
|
var data = JSON.parse(lastRequest.data.model);
|
||||||
|
equal(data.id, '2-the-tempest');
|
||||||
|
equal(data.author, 'Tim Shakespeare');
|
||||||
|
equal(data.length, 123);
|
||||||
|
Backbone.emulateJSON = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sync: read model", 3, function() {
|
||||||
|
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||||
|
library.first().fetch();
|
||||||
|
equal(lastRequest.url, '/library/2-the-tempest');
|
||||||
|
equal(lastRequest.type, 'GET');
|
||||||
|
ok(_.isEmpty(lastRequest.data));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sync: destroy", 3, function() {
|
||||||
|
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||||
|
library.first().destroy({wait: true});
|
||||||
|
equal(lastRequest.url, '/library/2-the-tempest');
|
||||||
|
equal(lastRequest.type, 'DELETE');
|
||||||
|
equal(lastRequest.data, null);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sync: destroy with emulateHTTP", 3, function() {
|
||||||
|
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||||
|
Backbone.emulateHTTP = Backbone.emulateJSON = true;
|
||||||
|
library.first().destroy();
|
||||||
|
equal(lastRequest.url, '/library/2-the-tempest');
|
||||||
|
equal(lastRequest.type, 'POST');
|
||||||
|
equal(JSON.stringify(lastRequest.data), '{"_method":"DELETE"}');
|
||||||
|
Backbone.emulateHTTP = Backbone.emulateJSON = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sync: urlError", 2, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
raises(function() {
|
||||||
|
model.fetch();
|
||||||
|
});
|
||||||
|
model.fetch({url: '/one/two'});
|
||||||
|
equal(lastRequest.url, '/one/two');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1052 - `options` is optional.", 0, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.url = '/test';
|
||||||
|
Backbone.sync('create', model);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Backbone.ajax", 1, function() {
|
||||||
|
Backbone.ajax = function(settings){
|
||||||
|
strictEqual(settings.url, '/test');
|
||||||
|
};
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
model.url = '/test';
|
||||||
|
Backbone.sync('create', model);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
9266
vendor/backbone/test/vendor/jquery-1.7.1.js
vendored
Normal file
649
vendor/backbone/test/vendor/jslitmus.js
vendored
Normal file
@@ -0,0 +1,649 @@
|
|||||||
|
// JSLitmus.js
|
||||||
|
//
|
||||||
|
// Copyright (c) 2010, Robert Kieffer, http://broofa.com
|
||||||
|
// Available under MIT license (http://en.wikipedia.org/wiki/MIT_License)
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
// Private methods and state
|
||||||
|
|
||||||
|
// Get platform info but don't go crazy trying to recognize everything
|
||||||
|
// that's out there. This is just for the major platforms and OSes.
|
||||||
|
var platform = 'unknown platform', ua = navigator.userAgent;
|
||||||
|
|
||||||
|
// Detect OS
|
||||||
|
var oses = ['Windows','iPhone OS','(Intel |PPC )?Mac OS X','Linux'].join('|');
|
||||||
|
var pOS = new RegExp('((' + oses + ') [^ \);]*)').test(ua) ? RegExp.$1 : null;
|
||||||
|
if (!pOS) pOS = new RegExp('((' + oses + ')[^ \);]*)').test(ua) ? RegExp.$1 : null;
|
||||||
|
|
||||||
|
// Detect browser
|
||||||
|
var pName = /(Chrome|MSIE|Safari|Opera|Firefox)/.test(ua) ? RegExp.$1 : null;
|
||||||
|
|
||||||
|
// Detect version
|
||||||
|
var vre = new RegExp('(Version|' + pName + ')[ \/]([^ ;]*)');
|
||||||
|
var pVersion = (pName && vre.test(ua)) ? RegExp.$2 : null;
|
||||||
|
var platform = (pOS && pName && pVersion) ? pName + ' ' + pVersion + ' on ' + pOS : 'unknown platform';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A smattering of methods that are needed to implement the JSLitmus testbed.
|
||||||
|
*/
|
||||||
|
var jsl = {
|
||||||
|
/**
|
||||||
|
* Enhanced version of escape()
|
||||||
|
*/
|
||||||
|
escape: function(s) {
|
||||||
|
s = s.replace(/,/g, '\\,');
|
||||||
|
s = escape(s);
|
||||||
|
s = s.replace(/\+/g, '%2b');
|
||||||
|
s = s.replace(/ /g, '+');
|
||||||
|
return s;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an element by ID.
|
||||||
|
*/
|
||||||
|
$: function(id) {
|
||||||
|
return document.getElementById(id);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null function
|
||||||
|
*/
|
||||||
|
F: function() {},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the status shown in the UI
|
||||||
|
*/
|
||||||
|
status: function(msg) {
|
||||||
|
var el = jsl.$('jsl_status');
|
||||||
|
if (el) el.innerHTML = msg || '';
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a number to an abbreviated string like, "15K" or "10M"
|
||||||
|
*/
|
||||||
|
toLabel: function(n) {
|
||||||
|
if (n == Infinity) {
|
||||||
|
return 'Infinity';
|
||||||
|
} else if (n > 1e9) {
|
||||||
|
n = Math.round(n/1e8);
|
||||||
|
return n/10 + 'B';
|
||||||
|
} else if (n > 1e6) {
|
||||||
|
n = Math.round(n/1e5);
|
||||||
|
return n/10 + 'M';
|
||||||
|
} else if (n > 1e3) {
|
||||||
|
n = Math.round(n/1e2);
|
||||||
|
return n/10 + 'K';
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy properties from src to dst
|
||||||
|
*/
|
||||||
|
extend: function(dst, src) {
|
||||||
|
for (var k in src) dst[k] = src[k]; return dst;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like Array.join(), but for the key-value pairs in an object
|
||||||
|
*/
|
||||||
|
join: function(o, delimit1, delimit2) {
|
||||||
|
if (o.join) return o.join(delimit1); // If it's an array
|
||||||
|
var pairs = [];
|
||||||
|
for (var k in o) pairs.push(k + delimit1 + o[k]);
|
||||||
|
return pairs.join(delimit2);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array#indexOf isn't supported in IE, so we use this as a cross-browser solution
|
||||||
|
*/
|
||||||
|
indexOf: function(arr, o) {
|
||||||
|
if (arr.indexOf) return arr.indexOf(o);
|
||||||
|
for (var i = 0; i < this.length; i++) if (arr[i] === o) return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test manages a single test (created with
|
||||||
|
* JSLitmus.test())
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var Test = function (name, f) {
|
||||||
|
if (!f) throw new Error('Undefined test function');
|
||||||
|
if (!/function[^\(]*\(([^,\)]*)/.test(f.toString())) {
|
||||||
|
throw new Error('"' + name + '" test: Test is not a valid Function object');
|
||||||
|
}
|
||||||
|
this.loopArg = RegExp.$1;
|
||||||
|
this.name = name;
|
||||||
|
this.f = f;
|
||||||
|
};
|
||||||
|
|
||||||
|
jsl.extend(Test, /** @lends Test */ {
|
||||||
|
/** Calibration tests for establishing iteration loop overhead */
|
||||||
|
CALIBRATIONS: [
|
||||||
|
new Test('calibrating loop', function(count) {while (count--);}),
|
||||||
|
new Test('calibrating function', jsl.F)
|
||||||
|
],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run calibration tests. Returns true if calibrations are not yet
|
||||||
|
* complete (in which case calling code should run the tests yet again).
|
||||||
|
* onCalibrated - Callback to invoke when calibrations have finished
|
||||||
|
*/
|
||||||
|
calibrate: function(onCalibrated) {
|
||||||
|
for (var i = 0; i < Test.CALIBRATIONS.length; i++) {
|
||||||
|
var cal = Test.CALIBRATIONS[i];
|
||||||
|
if (cal.running) return true;
|
||||||
|
if (!cal.count) {
|
||||||
|
cal.isCalibration = true;
|
||||||
|
cal.onStop = onCalibrated;
|
||||||
|
//cal.MIN_TIME = .1; // Do calibrations quickly
|
||||||
|
cal.run(2e4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
jsl.extend(Test.prototype, {/** @lends Test.prototype */
|
||||||
|
/** Initial number of iterations */
|
||||||
|
INIT_COUNT: 10,
|
||||||
|
/** Max iterations allowed (i.e. used to detect bad looping functions) */
|
||||||
|
MAX_COUNT: 1e9,
|
||||||
|
/** Minimum time a test should take to get valid results (secs) */
|
||||||
|
MIN_TIME: .5,
|
||||||
|
|
||||||
|
/** Callback invoked when test state changes */
|
||||||
|
onChange: jsl.F,
|
||||||
|
|
||||||
|
/** Callback invoked when test is finished */
|
||||||
|
onStop: jsl.F,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset test state
|
||||||
|
*/
|
||||||
|
reset: function() {
|
||||||
|
delete this.count;
|
||||||
|
delete this.time;
|
||||||
|
delete this.running;
|
||||||
|
delete this.error;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the test (in a timeout). We use a timeout to make sure the browser
|
||||||
|
* has a chance to finish rendering any UI changes we've made, like
|
||||||
|
* updating the status message.
|
||||||
|
*/
|
||||||
|
run: function(count) {
|
||||||
|
count = count || this.INIT_COUNT;
|
||||||
|
jsl.status(this.name + ' x ' + count);
|
||||||
|
this.running = true;
|
||||||
|
var me = this;
|
||||||
|
setTimeout(function() {me._run(count);}, 200);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The nuts and bolts code that actually runs a test
|
||||||
|
*/
|
||||||
|
_run: function(count) {
|
||||||
|
var me = this;
|
||||||
|
|
||||||
|
// Make sure calibration tests have run
|
||||||
|
if (!me.isCalibration && Test.calibrate(function() {me.run(count);})) return;
|
||||||
|
this.error = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
var start, f = this.f, now, i = count;
|
||||||
|
|
||||||
|
// Start the timer
|
||||||
|
start = new Date();
|
||||||
|
|
||||||
|
// Now for the money shot. If this is a looping function ...
|
||||||
|
if (this.loopArg) {
|
||||||
|
// ... let it do the iteration itself
|
||||||
|
f(count);
|
||||||
|
} else {
|
||||||
|
// ... otherwise do the iteration for it
|
||||||
|
while (i--) f();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get time test took (in secs)
|
||||||
|
this.time = Math.max(1,new Date() - start)/1000;
|
||||||
|
|
||||||
|
// Store iteration count and per-operation time taken
|
||||||
|
this.count = count;
|
||||||
|
this.period = this.time/count;
|
||||||
|
|
||||||
|
// Do we need to do another run?
|
||||||
|
this.running = this.time <= this.MIN_TIME;
|
||||||
|
|
||||||
|
// ... if so, compute how many times we should iterate
|
||||||
|
if (this.running) {
|
||||||
|
// Bump the count to the nearest power of 2
|
||||||
|
var x = this.MIN_TIME/this.time;
|
||||||
|
var pow = Math.pow(2, Math.max(1, Math.ceil(Math.log(x)/Math.log(2))));
|
||||||
|
count *= pow;
|
||||||
|
if (count > this.MAX_COUNT) {
|
||||||
|
throw new Error('Max count exceeded. If this test uses a looping function, make sure the iteration loop is working properly.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Exceptions are caught and displayed in the test UI
|
||||||
|
this.reset();
|
||||||
|
this.error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out what to do next
|
||||||
|
if (this.running) {
|
||||||
|
me.run(count);
|
||||||
|
} else {
|
||||||
|
jsl.status('');
|
||||||
|
me.onStop(me);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish up
|
||||||
|
this.onChange(this);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of operations per second for this test.
|
||||||
|
*
|
||||||
|
* @param normalize if true, iteration loop overhead taken into account
|
||||||
|
*/
|
||||||
|
getHz: function(/**Boolean*/ normalize) {
|
||||||
|
var p = this.period;
|
||||||
|
|
||||||
|
// Adjust period based on the calibration test time
|
||||||
|
if (normalize && !this.isCalibration) {
|
||||||
|
var cal = Test.CALIBRATIONS[this.loopArg ? 0 : 1];
|
||||||
|
|
||||||
|
// If the period is within 20% of the calibration time, then zero the
|
||||||
|
// it out
|
||||||
|
p = p < cal.period*1.2 ? 0 : p - cal.period;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.round(1/p);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a friendly string describing the test
|
||||||
|
*/
|
||||||
|
toString: function() {
|
||||||
|
return this.name + ' - ' + this.time/this.count + ' secs';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// CSS we need for the UI
|
||||||
|
var STYLESHEET = '<style> \
|
||||||
|
#jslitmus {font-family:sans-serif; font-size: 12px;} \
|
||||||
|
#jslitmus a {text-decoration: none;} \
|
||||||
|
#jslitmus a:hover {text-decoration: underline;} \
|
||||||
|
#jsl_status { \
|
||||||
|
margin-top: 10px; \
|
||||||
|
font-size: 10px; \
|
||||||
|
color: #888; \
|
||||||
|
} \
|
||||||
|
A IMG {border:none} \
|
||||||
|
#test_results { \
|
||||||
|
margin-top: 10px; \
|
||||||
|
font-size: 12px; \
|
||||||
|
font-family: sans-serif; \
|
||||||
|
border-collapse: collapse; \
|
||||||
|
border-spacing: 0px; \
|
||||||
|
} \
|
||||||
|
#test_results th, #test_results td { \
|
||||||
|
border: solid 1px #ccc; \
|
||||||
|
vertical-align: top; \
|
||||||
|
padding: 3px; \
|
||||||
|
} \
|
||||||
|
#test_results th { \
|
||||||
|
vertical-align: bottom; \
|
||||||
|
background-color: #ccc; \
|
||||||
|
padding: 1px; \
|
||||||
|
font-size: 10px; \
|
||||||
|
} \
|
||||||
|
#test_results #test_platform { \
|
||||||
|
color: #444; \
|
||||||
|
text-align:center; \
|
||||||
|
} \
|
||||||
|
#test_results .test_row { \
|
||||||
|
color: #006; \
|
||||||
|
cursor: pointer; \
|
||||||
|
} \
|
||||||
|
#test_results .test_nonlooping { \
|
||||||
|
border-left-style: dotted; \
|
||||||
|
border-left-width: 2px; \
|
||||||
|
} \
|
||||||
|
#test_results .test_looping { \
|
||||||
|
border-left-style: solid; \
|
||||||
|
border-left-width: 2px; \
|
||||||
|
} \
|
||||||
|
#test_results .test_name {white-space: nowrap;} \
|
||||||
|
#test_results .test_pending { \
|
||||||
|
} \
|
||||||
|
#test_results .test_running { \
|
||||||
|
font-style: italic; \
|
||||||
|
} \
|
||||||
|
#test_results .test_done {} \
|
||||||
|
#test_results .test_done { \
|
||||||
|
text-align: right; \
|
||||||
|
font-family: monospace; \
|
||||||
|
} \
|
||||||
|
#test_results .test_error {color: #600;} \
|
||||||
|
#test_results .test_error .error_head {font-weight:bold;} \
|
||||||
|
#test_results .test_error .error_body {font-size:85%;} \
|
||||||
|
#test_results .test_row:hover td { \
|
||||||
|
background-color: #ffc; \
|
||||||
|
text-decoration: underline; \
|
||||||
|
} \
|
||||||
|
#chart { \
|
||||||
|
margin: 10px 0px; \
|
||||||
|
width: 250px; \
|
||||||
|
} \
|
||||||
|
#chart img { \
|
||||||
|
border: solid 1px #ccc; \
|
||||||
|
margin-bottom: 5px; \
|
||||||
|
} \
|
||||||
|
#chart #tiny_url { \
|
||||||
|
height: 40px; \
|
||||||
|
width: 250px; \
|
||||||
|
} \
|
||||||
|
#jslitmus_credit { \
|
||||||
|
font-size: 10px; \
|
||||||
|
color: #888; \
|
||||||
|
margin-top: 8px; \
|
||||||
|
} \
|
||||||
|
</style>';
|
||||||
|
|
||||||
|
// HTML markup for the UI
|
||||||
|
var MARKUP = '<div id="jslitmus"> \
|
||||||
|
<button onclick="JSLitmus.runAll(event)">Run Tests</button> \
|
||||||
|
<button id="stop_button" disabled="disabled" onclick="JSLitmus.stop()">Stop Tests</button> \
|
||||||
|
<br \> \
|
||||||
|
<br \> \
|
||||||
|
<input type="checkbox" style="vertical-align: middle" id="test_normalize" checked="checked" onchange="JSLitmus.renderAll()""> Normalize results \
|
||||||
|
<table id="test_results"> \
|
||||||
|
<colgroup> \
|
||||||
|
<col /> \
|
||||||
|
<col width="100" /> \
|
||||||
|
</colgroup> \
|
||||||
|
<tr><th id="test_platform" colspan="2">' + platform + '</th></tr> \
|
||||||
|
<tr><th>Test</th><th>Ops/sec</th></tr> \
|
||||||
|
<tr id="test_row_template" class="test_row" style="display:none"> \
|
||||||
|
<td class="test_name"></td> \
|
||||||
|
<td class="test_result">Ready</td> \
|
||||||
|
</tr> \
|
||||||
|
</table> \
|
||||||
|
<div id="jsl_status"></div> \
|
||||||
|
<div id="chart" style="display:none"> \
|
||||||
|
<a id="chart_link" target="_blank"><img id="chart_image"></a> \
|
||||||
|
TinyURL (for chart): \
|
||||||
|
<iframe id="tiny_url" frameBorder="0" scrolling="no" src=""></iframe> \
|
||||||
|
</div> \
|
||||||
|
<a id="jslitmus_credit" title="JSLitmus home page" href="http://code.google.com/p/jslitmus" target="_blank">Powered by JSLitmus</a> \
|
||||||
|
</div>';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The public API for creating and running tests
|
||||||
|
*/
|
||||||
|
window.JSLitmus = {
|
||||||
|
/** The list of all tests that have been registered with JSLitmus.test */
|
||||||
|
_tests: [],
|
||||||
|
/** The queue of tests that need to be run */
|
||||||
|
_queue: [],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parsed query parameters the current page URL. This is provided as a
|
||||||
|
* convenience for test functions - it's not used by JSLitmus proper
|
||||||
|
*/
|
||||||
|
params: {},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize
|
||||||
|
*/
|
||||||
|
_init: function() {
|
||||||
|
// Parse query params into JSLitmus.params[] hash
|
||||||
|
var match = (location + '').match(/([^?#]*)(#.*)?$/);
|
||||||
|
if (match) {
|
||||||
|
var pairs = match[1].split('&');
|
||||||
|
for (var i = 0; i < pairs.length; i++) {
|
||||||
|
var pair = pairs[i].split('=');
|
||||||
|
if (pair.length > 1) {
|
||||||
|
var key = pair.shift();
|
||||||
|
var value = pair.length > 1 ? pair.join('=') : pair[0];
|
||||||
|
this.params[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write out the stylesheet. We have to do this here because IE
|
||||||
|
// doesn't honor sheets written after the document has loaded.
|
||||||
|
document.write(STYLESHEET);
|
||||||
|
|
||||||
|
// Setup the rest of the UI once the document is loaded
|
||||||
|
if (window.addEventListener) {
|
||||||
|
window.addEventListener('load', this._setup, false);
|
||||||
|
} else if (document.addEventListener) {
|
||||||
|
document.addEventListener('load', this._setup, false);
|
||||||
|
} else if (window.attachEvent) {
|
||||||
|
window.attachEvent('onload', this._setup);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the UI
|
||||||
|
*/
|
||||||
|
_setup: function() {
|
||||||
|
var el = jsl.$('jslitmus_container');
|
||||||
|
if (!el) document.body.appendChild(el = document.createElement('div'));
|
||||||
|
|
||||||
|
el.innerHTML = MARKUP;
|
||||||
|
|
||||||
|
// Render the UI for all our tests
|
||||||
|
for (var i=0; i < JSLitmus._tests.length; i++)
|
||||||
|
JSLitmus.renderTest(JSLitmus._tests[i]);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re)render all the test results
|
||||||
|
*/
|
||||||
|
renderAll: function() {
|
||||||
|
for (var i = 0; i < JSLitmus._tests.length; i++)
|
||||||
|
JSLitmus.renderTest(JSLitmus._tests[i]);
|
||||||
|
JSLitmus.renderChart();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re)render the chart graphics
|
||||||
|
*/
|
||||||
|
renderChart: function() {
|
||||||
|
var url = JSLitmus.chartUrl();
|
||||||
|
jsl.$('chart_link').href = url;
|
||||||
|
jsl.$('chart_image').src = url;
|
||||||
|
jsl.$('chart').style.display = '';
|
||||||
|
|
||||||
|
// Update the tiny URL
|
||||||
|
jsl.$('tiny_url').src = 'http://tinyurl.com/api-create.php?url='+escape(url);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re)render the results for a specific test
|
||||||
|
*/
|
||||||
|
renderTest: function(test) {
|
||||||
|
// Make a new row if needed
|
||||||
|
if (!test._row) {
|
||||||
|
var trow = jsl.$('test_row_template');
|
||||||
|
if (!trow) return;
|
||||||
|
|
||||||
|
test._row = trow.cloneNode(true);
|
||||||
|
test._row.style.display = '';
|
||||||
|
test._row.id = '';
|
||||||
|
test._row.onclick = function() {JSLitmus._queueTest(test);};
|
||||||
|
test._row.title = 'Run ' + test.name + ' test';
|
||||||
|
trow.parentNode.appendChild(test._row);
|
||||||
|
test._row.cells[0].innerHTML = test.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cell = test._row.cells[1];
|
||||||
|
var cns = [test.loopArg ? 'test_looping' : 'test_nonlooping'];
|
||||||
|
|
||||||
|
if (test.error) {
|
||||||
|
cns.push('test_error');
|
||||||
|
cell.innerHTML =
|
||||||
|
'<div class="error_head">' + test.error + '</div>' +
|
||||||
|
'<ul class="error_body"><li>' +
|
||||||
|
jsl.join(test.error, ': ', '</li><li>') +
|
||||||
|
'</li></ul>';
|
||||||
|
} else {
|
||||||
|
if (test.running) {
|
||||||
|
cns.push('test_running');
|
||||||
|
cell.innerHTML = 'running';
|
||||||
|
} else if (jsl.indexOf(JSLitmus._queue, test) >= 0) {
|
||||||
|
cns.push('test_pending');
|
||||||
|
cell.innerHTML = 'pending';
|
||||||
|
} else if (test.count) {
|
||||||
|
cns.push('test_done');
|
||||||
|
var hz = test.getHz(jsl.$('test_normalize').checked);
|
||||||
|
cell.innerHTML = hz != Infinity ? hz : '∞';
|
||||||
|
cell.title = 'Looped ' + test.count + ' times in ' + test.time + ' seconds';
|
||||||
|
} else {
|
||||||
|
cell.innerHTML = 'ready';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cell.className = cns.join(' ');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new test
|
||||||
|
*/
|
||||||
|
test: function(name, f) {
|
||||||
|
// Create the Test object
|
||||||
|
var test = new Test(name, f);
|
||||||
|
JSLitmus._tests.push(test);
|
||||||
|
|
||||||
|
// Re-render if the test state changes
|
||||||
|
test.onChange = JSLitmus.renderTest;
|
||||||
|
|
||||||
|
// Run the next test if this one finished
|
||||||
|
test.onStop = function(test) {
|
||||||
|
if (JSLitmus.onTestFinish) JSLitmus.onTestFinish(test);
|
||||||
|
JSLitmus.currentTest = null;
|
||||||
|
JSLitmus._nextTest();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render the new test
|
||||||
|
this.renderTest(test);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all tests to the run queue
|
||||||
|
*/
|
||||||
|
runAll: function(e) {
|
||||||
|
e = e || window.event;
|
||||||
|
var reverse = e && e.shiftKey, len = JSLitmus._tests.length;
|
||||||
|
for (var i = 0; i < len; i++) {
|
||||||
|
JSLitmus._queueTest(JSLitmus._tests[!reverse ? i : (len - i - 1)]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all tests from the run queue. The current test has to finish on
|
||||||
|
* it's own though
|
||||||
|
*/
|
||||||
|
stop: function() {
|
||||||
|
while (JSLitmus._queue.length) {
|
||||||
|
var test = JSLitmus._queue.shift();
|
||||||
|
JSLitmus.renderTest(test);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the next test in the run queue
|
||||||
|
*/
|
||||||
|
_nextTest: function() {
|
||||||
|
if (!JSLitmus.currentTest) {
|
||||||
|
var test = JSLitmus._queue.shift();
|
||||||
|
if (test) {
|
||||||
|
jsl.$('stop_button').disabled = false;
|
||||||
|
JSLitmus.currentTest = test;
|
||||||
|
test.run();
|
||||||
|
JSLitmus.renderTest(test);
|
||||||
|
if (JSLitmus.onTestStart) JSLitmus.onTestStart(test);
|
||||||
|
} else {
|
||||||
|
jsl.$('stop_button').disabled = true;
|
||||||
|
JSLitmus.renderChart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a test to the run queue
|
||||||
|
*/
|
||||||
|
_queueTest: function(test) {
|
||||||
|
if (jsl.indexOf(JSLitmus._queue, test) >= 0) return;
|
||||||
|
JSLitmus._queue.push(test);
|
||||||
|
JSLitmus.renderTest(test);
|
||||||
|
JSLitmus._nextTest();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a Google Chart URL that shows the data for all tests
|
||||||
|
*/
|
||||||
|
chartUrl: function() {
|
||||||
|
var n = JSLitmus._tests.length, markers = [], data = [];
|
||||||
|
var d, min = 0, max = -1e10;
|
||||||
|
var normalize = jsl.$('test_normalize').checked;
|
||||||
|
|
||||||
|
// Gather test data
|
||||||
|
for (var i=0; i < JSLitmus._tests.length; i++) {
|
||||||
|
var test = JSLitmus._tests[i];
|
||||||
|
if (test.count) {
|
||||||
|
var hz = test.getHz(normalize);
|
||||||
|
var v = hz != Infinity ? hz : 0;
|
||||||
|
data.push(v);
|
||||||
|
markers.push('t' + jsl.escape(test.name + '(' + jsl.toLabel(hz)+ ')') + ',000000,0,' +
|
||||||
|
markers.length + ',10');
|
||||||
|
max = Math.max(v, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (markers.length <= 0) return null;
|
||||||
|
|
||||||
|
// Build chart title
|
||||||
|
var title = document.getElementsByTagName('title');
|
||||||
|
title = (title && title.length) ? title[0].innerHTML : null;
|
||||||
|
var chart_title = [];
|
||||||
|
if (title) chart_title.push(title);
|
||||||
|
chart_title.push('Ops/sec (' + platform + ')');
|
||||||
|
|
||||||
|
// Build labels
|
||||||
|
var labels = [jsl.toLabel(min), jsl.toLabel(max)];
|
||||||
|
|
||||||
|
var w = 250, bw = 15;
|
||||||
|
var bs = 5;
|
||||||
|
var h = markers.length*(bw + bs) + 30 + chart_title.length*20;
|
||||||
|
|
||||||
|
var params = {
|
||||||
|
chtt: escape(chart_title.join('|')),
|
||||||
|
chts: '000000,10',
|
||||||
|
cht: 'bhg', // chart type
|
||||||
|
chd: 't:' + data.join(','), // data set
|
||||||
|
chds: min + ',' + max, // max/min of data
|
||||||
|
chxt: 'x', // label axes
|
||||||
|
chxl: '0:|' + labels.join('|'), // labels
|
||||||
|
chsp: '0,1',
|
||||||
|
chm: markers.join('|'), // test names
|
||||||
|
chbh: [bw, 0, bs].join(','), // bar widths
|
||||||
|
// chf: 'bg,lg,0,eeeeee,0,eeeeee,.5,ffffff,1', // gradient
|
||||||
|
chs: w + 'x' + h
|
||||||
|
};
|
||||||
|
return 'http://chart.apis.google.com/chart?' + jsl.join(params, '=', '&');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
JSLitmus._init();
|
||||||
|
})();
|
||||||
481
vendor/backbone/test/vendor/json2.js
vendored
Normal file
@@ -0,0 +1,481 @@
|
|||||||
|
/*
|
||||||
|
http://www.JSON.org/json2.js
|
||||||
|
2009-09-29
|
||||||
|
|
||||||
|
Public Domain.
|
||||||
|
|
||||||
|
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||||
|
|
||||||
|
See http://www.JSON.org/js.html
|
||||||
|
|
||||||
|
|
||||||
|
This code should be minified before deployment.
|
||||||
|
See http://javascript.crockford.com/jsmin.html
|
||||||
|
|
||||||
|
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
||||||
|
NOT CONTROL.
|
||||||
|
|
||||||
|
|
||||||
|
This file creates a global JSON object containing two methods: stringify
|
||||||
|
and parse.
|
||||||
|
|
||||||
|
JSON.stringify(value, replacer, space)
|
||||||
|
value any JavaScript value, usually an object or array.
|
||||||
|
|
||||||
|
replacer an optional parameter that determines how object
|
||||||
|
values are stringified for objects. It can be a
|
||||||
|
function or an array of strings.
|
||||||
|
|
||||||
|
space an optional parameter that specifies the indentation
|
||||||
|
of nested structures. If it is omitted, the text will
|
||||||
|
be packed without extra whitespace. If it is a number,
|
||||||
|
it will specify the number of spaces to indent at each
|
||||||
|
level. If it is a string (such as '\t' or ' '),
|
||||||
|
it contains the characters used to indent at each level.
|
||||||
|
|
||||||
|
This method produces a JSON text from a JavaScript value.
|
||||||
|
|
||||||
|
When an object value is found, if the object contains a toJSON
|
||||||
|
method, its toJSON method will be called and the result will be
|
||||||
|
stringified. A toJSON method does not serialize: it returns the
|
||||||
|
value represented by the name/value pair that should be serialized,
|
||||||
|
or undefined if nothing should be serialized. The toJSON method
|
||||||
|
will be passed the key associated with the value, and this will be
|
||||||
|
bound to the value
|
||||||
|
|
||||||
|
For example, this would serialize Dates as ISO strings.
|
||||||
|
|
||||||
|
Date.prototype.toJSON = function (key) {
|
||||||
|
function f(n) {
|
||||||
|
// Format integers to have at least two digits.
|
||||||
|
return n < 10 ? '0' + n : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.getUTCFullYear() + '-' +
|
||||||
|
f(this.getUTCMonth() + 1) + '-' +
|
||||||
|
f(this.getUTCDate()) + 'T' +
|
||||||
|
f(this.getUTCHours()) + ':' +
|
||||||
|
f(this.getUTCMinutes()) + ':' +
|
||||||
|
f(this.getUTCSeconds()) + 'Z';
|
||||||
|
};
|
||||||
|
|
||||||
|
You can provide an optional replacer method. It will be passed the
|
||||||
|
key and value of each member, with this bound to the containing
|
||||||
|
object. The value that is returned from your method will be
|
||||||
|
serialized. If your method returns undefined, then the member will
|
||||||
|
be excluded from the serialization.
|
||||||
|
|
||||||
|
If the replacer parameter is an array of strings, then it will be
|
||||||
|
used to select the members to be serialized. It filters the results
|
||||||
|
such that only members with keys listed in the replacer array are
|
||||||
|
stringified.
|
||||||
|
|
||||||
|
Values that do not have JSON representations, such as undefined or
|
||||||
|
functions, will not be serialized. Such values in objects will be
|
||||||
|
dropped; in arrays they will be replaced with null. You can use
|
||||||
|
a replacer function to replace those with JSON values.
|
||||||
|
JSON.stringify(undefined) returns undefined.
|
||||||
|
|
||||||
|
The optional space parameter produces a stringification of the
|
||||||
|
value that is filled with line breaks and indentation to make it
|
||||||
|
easier to read.
|
||||||
|
|
||||||
|
If the space parameter is a non-empty string, then that string will
|
||||||
|
be used for indentation. If the space parameter is a number, then
|
||||||
|
the indentation will be that many spaces.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
||||||
|
// text is '["e",{"pluribus":"unum"}]'
|
||||||
|
|
||||||
|
|
||||||
|
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
||||||
|
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
||||||
|
|
||||||
|
text = JSON.stringify([new Date()], function (key, value) {
|
||||||
|
return this[key] instanceof Date ?
|
||||||
|
'Date(' + this[key] + ')' : value;
|
||||||
|
});
|
||||||
|
// text is '["Date(---current time---)"]'
|
||||||
|
|
||||||
|
|
||||||
|
JSON.parse(text, reviver)
|
||||||
|
This method parses a JSON text to produce an object or array.
|
||||||
|
It can throw a SyntaxError exception.
|
||||||
|
|
||||||
|
The optional reviver parameter is a function that can filter and
|
||||||
|
transform the results. It receives each of the keys and values,
|
||||||
|
and its return value is used instead of the original value.
|
||||||
|
If it returns what it received, then the structure is not modified.
|
||||||
|
If it returns undefined then the member is deleted.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
// Parse the text. Values that look like ISO date strings will
|
||||||
|
// be converted to Date objects.
|
||||||
|
|
||||||
|
myData = JSON.parse(text, function (key, value) {
|
||||||
|
var a;
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
a =
|
||||||
|
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
||||||
|
if (a) {
|
||||||
|
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
||||||
|
+a[5], +a[6]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
|
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
||||||
|
var d;
|
||||||
|
if (typeof value === 'string' &&
|
||||||
|
value.slice(0, 5) === 'Date(' &&
|
||||||
|
value.slice(-1) === ')') {
|
||||||
|
d = new Date(value.slice(5, -1));
|
||||||
|
if (d) {
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
This is a reference implementation. You are free to copy, modify, or
|
||||||
|
redistribute.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*jslint evil: true, strict: false */
|
||||||
|
|
||||||
|
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
||||||
|
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
||||||
|
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
||||||
|
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
||||||
|
test, toJSON, toString, valueOf
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Create a JSON object only if one does not already exist. We create the
|
||||||
|
// methods in a closure to avoid creating global variables.
|
||||||
|
|
||||||
|
if (!this.JSON) {
|
||||||
|
this.JSON = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
function f(n) {
|
||||||
|
// Format integers to have at least two digits.
|
||||||
|
return n < 10 ? '0' + n : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof Date.prototype.toJSON !== 'function') {
|
||||||
|
|
||||||
|
Date.prototype.toJSON = function (key) {
|
||||||
|
|
||||||
|
return isFinite(this.valueOf()) ?
|
||||||
|
this.getUTCFullYear() + '-' +
|
||||||
|
f(this.getUTCMonth() + 1) + '-' +
|
||||||
|
f(this.getUTCDate()) + 'T' +
|
||||||
|
f(this.getUTCHours()) + ':' +
|
||||||
|
f(this.getUTCMinutes()) + ':' +
|
||||||
|
f(this.getUTCSeconds()) + 'Z' : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
String.prototype.toJSON =
|
||||||
|
Number.prototype.toJSON =
|
||||||
|
Boolean.prototype.toJSON = function (key) {
|
||||||
|
return this.valueOf();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||||
|
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||||
|
gap,
|
||||||
|
indent,
|
||||||
|
meta = { // table of character substitutions
|
||||||
|
'\b': '\\b',
|
||||||
|
'\t': '\\t',
|
||||||
|
'\n': '\\n',
|
||||||
|
'\f': '\\f',
|
||||||
|
'\r': '\\r',
|
||||||
|
'"' : '\\"',
|
||||||
|
'\\': '\\\\'
|
||||||
|
},
|
||||||
|
rep;
|
||||||
|
|
||||||
|
|
||||||
|
function quote(string) {
|
||||||
|
|
||||||
|
// If the string contains no control characters, no quote characters, and no
|
||||||
|
// backslash characters, then we can safely slap some quotes around it.
|
||||||
|
// Otherwise we must also replace the offending characters with safe escape
|
||||||
|
// sequences.
|
||||||
|
|
||||||
|
escapable.lastIndex = 0;
|
||||||
|
return escapable.test(string) ?
|
||||||
|
'"' + string.replace(escapable, function (a) {
|
||||||
|
var c = meta[a];
|
||||||
|
return typeof c === 'string' ? c :
|
||||||
|
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||||
|
}) + '"' :
|
||||||
|
'"' + string + '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function str(key, holder) {
|
||||||
|
|
||||||
|
// Produce a string from holder[key].
|
||||||
|
|
||||||
|
var i, // The loop counter.
|
||||||
|
k, // The member key.
|
||||||
|
v, // The member value.
|
||||||
|
length,
|
||||||
|
mind = gap,
|
||||||
|
partial,
|
||||||
|
value = holder[key];
|
||||||
|
|
||||||
|
// If the value has a toJSON method, call it to obtain a replacement value.
|
||||||
|
|
||||||
|
if (value && typeof value === 'object' &&
|
||||||
|
typeof value.toJSON === 'function') {
|
||||||
|
value = value.toJSON(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we were called with a replacer function, then call the replacer to
|
||||||
|
// obtain a replacement value.
|
||||||
|
|
||||||
|
if (typeof rep === 'function') {
|
||||||
|
value = rep.call(holder, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// What happens next depends on the value's type.
|
||||||
|
|
||||||
|
switch (typeof value) {
|
||||||
|
case 'string':
|
||||||
|
return quote(value);
|
||||||
|
|
||||||
|
case 'number':
|
||||||
|
|
||||||
|
// JSON numbers must be finite. Encode non-finite numbers as null.
|
||||||
|
|
||||||
|
return isFinite(value) ? String(value) : 'null';
|
||||||
|
|
||||||
|
case 'boolean':
|
||||||
|
case 'null':
|
||||||
|
|
||||||
|
// If the value is a boolean or null, convert it to a string. Note:
|
||||||
|
// typeof null does not produce 'null'. The case is included here in
|
||||||
|
// the remote chance that this gets fixed someday.
|
||||||
|
|
||||||
|
return String(value);
|
||||||
|
|
||||||
|
// If the type is 'object', we might be dealing with an object or an array or
|
||||||
|
// null.
|
||||||
|
|
||||||
|
case 'object':
|
||||||
|
|
||||||
|
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
||||||
|
// so watch out for that case.
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
return 'null';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make an array to hold the partial results of stringifying this object value.
|
||||||
|
|
||||||
|
gap += indent;
|
||||||
|
partial = [];
|
||||||
|
|
||||||
|
// Is the value an array?
|
||||||
|
|
||||||
|
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
||||||
|
|
||||||
|
// The value is an array. Stringify every element. Use null as a placeholder
|
||||||
|
// for non-JSON values.
|
||||||
|
|
||||||
|
length = value.length;
|
||||||
|
for (i = 0; i < length; i += 1) {
|
||||||
|
partial[i] = str(i, value) || 'null';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join all of the elements together, separated with commas, and wrap them in
|
||||||
|
// brackets.
|
||||||
|
|
||||||
|
v = partial.length === 0 ? '[]' :
|
||||||
|
gap ? '[\n' + gap +
|
||||||
|
partial.join(',\n' + gap) + '\n' +
|
||||||
|
mind + ']' :
|
||||||
|
'[' + partial.join(',') + ']';
|
||||||
|
gap = mind;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the replacer is an array, use it to select the members to be stringified.
|
||||||
|
|
||||||
|
if (rep && typeof rep === 'object') {
|
||||||
|
length = rep.length;
|
||||||
|
for (i = 0; i < length; i += 1) {
|
||||||
|
k = rep[i];
|
||||||
|
if (typeof k === 'string') {
|
||||||
|
v = str(k, value);
|
||||||
|
if (v) {
|
||||||
|
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Otherwise, iterate through all of the keys in the object.
|
||||||
|
|
||||||
|
for (k in value) {
|
||||||
|
if (Object.hasOwnProperty.call(value, k)) {
|
||||||
|
v = str(k, value);
|
||||||
|
if (v) {
|
||||||
|
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join all of the member texts together, separated with commas,
|
||||||
|
// and wrap them in braces.
|
||||||
|
|
||||||
|
v = partial.length === 0 ? '{}' :
|
||||||
|
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
||||||
|
mind + '}' : '{' + partial.join(',') + '}';
|
||||||
|
gap = mind;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the JSON object does not yet have a stringify method, give it one.
|
||||||
|
|
||||||
|
if (typeof JSON.stringify !== 'function') {
|
||||||
|
JSON.stringify = function (value, replacer, space) {
|
||||||
|
|
||||||
|
// The stringify method takes a value and an optional replacer, and an optional
|
||||||
|
// space parameter, and returns a JSON text. The replacer can be a function
|
||||||
|
// that can replace values, or an array of strings that will select the keys.
|
||||||
|
// A default replacer method can be provided. Use of the space parameter can
|
||||||
|
// produce text that is more easily readable.
|
||||||
|
|
||||||
|
var i;
|
||||||
|
gap = '';
|
||||||
|
indent = '';
|
||||||
|
|
||||||
|
// If the space parameter is a number, make an indent string containing that
|
||||||
|
// many spaces.
|
||||||
|
|
||||||
|
if (typeof space === 'number') {
|
||||||
|
for (i = 0; i < space; i += 1) {
|
||||||
|
indent += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the space parameter is a string, it will be used as the indent string.
|
||||||
|
|
||||||
|
} else if (typeof space === 'string') {
|
||||||
|
indent = space;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is a replacer, it must be a function or an array.
|
||||||
|
// Otherwise, throw an error.
|
||||||
|
|
||||||
|
rep = replacer;
|
||||||
|
if (replacer && typeof replacer !== 'function' &&
|
||||||
|
(typeof replacer !== 'object' ||
|
||||||
|
typeof replacer.length !== 'number')) {
|
||||||
|
throw new Error('JSON.stringify');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a fake root object containing our value under the key of ''.
|
||||||
|
// Return the result of stringifying the value.
|
||||||
|
|
||||||
|
return str('', {'': value});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// If the JSON object does not yet have a parse method, give it one.
|
||||||
|
|
||||||
|
if (typeof JSON.parse !== 'function') {
|
||||||
|
JSON.parse = function (text, reviver) {
|
||||||
|
|
||||||
|
// The parse method takes a text and an optional reviver function, and returns
|
||||||
|
// a JavaScript value if the text is a valid JSON text.
|
||||||
|
|
||||||
|
var j;
|
||||||
|
|
||||||
|
function walk(holder, key) {
|
||||||
|
|
||||||
|
// The walk method is used to recursively walk the resulting structure so
|
||||||
|
// that modifications can be made.
|
||||||
|
|
||||||
|
var k, v, value = holder[key];
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
for (k in value) {
|
||||||
|
if (Object.hasOwnProperty.call(value, k)) {
|
||||||
|
v = walk(value, k);
|
||||||
|
if (v !== undefined) {
|
||||||
|
value[k] = v;
|
||||||
|
} else {
|
||||||
|
delete value[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reviver.call(holder, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parsing happens in four stages. In the first stage, we replace certain
|
||||||
|
// Unicode characters with escape sequences. JavaScript handles many characters
|
||||||
|
// incorrectly, either silently deleting them, or treating them as line endings.
|
||||||
|
|
||||||
|
cx.lastIndex = 0;
|
||||||
|
if (cx.test(text)) {
|
||||||
|
text = text.replace(cx, function (a) {
|
||||||
|
return '\\u' +
|
||||||
|
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the second stage, we run the text against regular expressions that look
|
||||||
|
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
||||||
|
// because they can cause invocation, and '=' because it can cause mutation.
|
||||||
|
// But just to be safe, we want to reject all unexpected forms.
|
||||||
|
|
||||||
|
// We split the second stage into 4 regexp operations in order to work around
|
||||||
|
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
||||||
|
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
||||||
|
// replace all simple value tokens with ']' characters. Third, we delete all
|
||||||
|
// open brackets that follow a colon or comma or that begin the text. Finally,
|
||||||
|
// we look to see that the remaining characters are only whitespace or ']' or
|
||||||
|
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
||||||
|
|
||||||
|
if (/^[\],:{}\s]*$/.
|
||||||
|
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
|
||||||
|
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
|
||||||
|
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
||||||
|
|
||||||
|
// In the third stage we use the eval function to compile the text into a
|
||||||
|
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
||||||
|
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
||||||
|
// in parens to eliminate the ambiguity.
|
||||||
|
|
||||||
|
j = eval('(' + text + ')');
|
||||||
|
|
||||||
|
// In the optional fourth stage, we recursively walk the new structure, passing
|
||||||
|
// each name/value pair to a reviver function for possible transformation.
|
||||||
|
|
||||||
|
return typeof reviver === 'function' ?
|
||||||
|
walk({'': j}, '') : j;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
||||||
|
|
||||||
|
throw new SyntaxError('JSON.parse');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}());
|
||||||
236
vendor/backbone/test/vendor/qunit.css
vendored
Executable file
@@ -0,0 +1,236 @@
|
|||||||
|
/**
|
||||||
|
* QUnit v1.8.0 - A JavaScript Unit Testing Framework
|
||||||
|
*
|
||||||
|
* http://docs.jquery.com/QUnit
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 John Resig, Jörn Zaefferer
|
||||||
|
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||||
|
* or GPL (GPL-LICENSE.txt) licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Font Family and Sizes */
|
||||||
|
|
||||||
|
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
|
||||||
|
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
|
||||||
|
#qunit-tests { font-size: smaller; }
|
||||||
|
|
||||||
|
|
||||||
|
/** Resets */
|
||||||
|
|
||||||
|
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Header */
|
||||||
|
|
||||||
|
#qunit-header {
|
||||||
|
padding: 0.5em 0 0.5em 1em;
|
||||||
|
|
||||||
|
color: #8699a4;
|
||||||
|
background-color: #0d3349;
|
||||||
|
|
||||||
|
font-size: 1.5em;
|
||||||
|
line-height: 1em;
|
||||||
|
font-weight: normal;
|
||||||
|
|
||||||
|
border-radius: 15px 15px 0 0;
|
||||||
|
-moz-border-radius: 15px 15px 0 0;
|
||||||
|
-webkit-border-top-right-radius: 15px;
|
||||||
|
-webkit-border-top-left-radius: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-header a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #c2ccd1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-header a:hover,
|
||||||
|
#qunit-header a:focus {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-header label {
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-banner {
|
||||||
|
height: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-testrunner-toolbar {
|
||||||
|
padding: 0.5em 0 0.5em 2em;
|
||||||
|
color: #5E740B;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-userAgent {
|
||||||
|
padding: 0.5em 0 0.5em 2.5em;
|
||||||
|
background-color: #2b81af;
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Tests: Pass/Fail */
|
||||||
|
|
||||||
|
#qunit-tests {
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests li {
|
||||||
|
padding: 0.4em 0.5em 0.4em 2.5em;
|
||||||
|
border-bottom: 1px solid #fff;
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests li strong {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests li a {
|
||||||
|
padding: 0.5em;
|
||||||
|
color: #c2ccd1;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
#qunit-tests li a:hover,
|
||||||
|
#qunit-tests li a:focus {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests ol {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
padding: 0.5em;
|
||||||
|
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
border-radius: 15px;
|
||||||
|
-moz-border-radius: 15px;
|
||||||
|
-webkit-border-radius: 15px;
|
||||||
|
|
||||||
|
box-shadow: inset 0px 2px 13px #999;
|
||||||
|
-moz-box-shadow: inset 0px 2px 13px #999;
|
||||||
|
-webkit-box-shadow: inset 0px 2px 13px #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: .2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests th {
|
||||||
|
text-align: right;
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 0 .5em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests pre {
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests del {
|
||||||
|
background-color: #e0f2be;
|
||||||
|
color: #374e0c;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests ins {
|
||||||
|
background-color: #ffcaca;
|
||||||
|
color: #500;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Test Counts */
|
||||||
|
|
||||||
|
#qunit-tests b.counts { color: black; }
|
||||||
|
#qunit-tests b.passed { color: #5E740B; }
|
||||||
|
#qunit-tests b.failed { color: #710909; }
|
||||||
|
|
||||||
|
#qunit-tests li li {
|
||||||
|
margin: 0.5em;
|
||||||
|
padding: 0.4em 0.5em 0.4em 0.5em;
|
||||||
|
background-color: #fff;
|
||||||
|
border-bottom: none;
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Passing Styles */
|
||||||
|
|
||||||
|
#qunit-tests li li.pass {
|
||||||
|
color: #5E740B;
|
||||||
|
background-color: #fff;
|
||||||
|
border-left: 26px solid #C6E746;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
||||||
|
#qunit-tests .pass .test-name { color: #366097; }
|
||||||
|
|
||||||
|
#qunit-tests .pass .test-actual,
|
||||||
|
#qunit-tests .pass .test-expected { color: #999999; }
|
||||||
|
|
||||||
|
#qunit-banner.qunit-pass { background-color: #C6E746; }
|
||||||
|
|
||||||
|
/*** Failing Styles */
|
||||||
|
|
||||||
|
#qunit-tests li li.fail {
|
||||||
|
color: #710909;
|
||||||
|
background-color: #fff;
|
||||||
|
border-left: 26px solid #EE5757;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests > li:last-child {
|
||||||
|
border-radius: 0 0 15px 15px;
|
||||||
|
-moz-border-radius: 0 0 15px 15px;
|
||||||
|
-webkit-border-bottom-right-radius: 15px;
|
||||||
|
-webkit-border-bottom-left-radius: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
|
||||||
|
#qunit-tests .fail .test-name,
|
||||||
|
#qunit-tests .fail .module-name { color: #000000; }
|
||||||
|
|
||||||
|
#qunit-tests .fail .test-actual { color: #EE5757; }
|
||||||
|
#qunit-tests .fail .test-expected { color: green; }
|
||||||
|
|
||||||
|
#qunit-banner.qunit-fail { background-color: #EE5757; }
|
||||||
|
|
||||||
|
|
||||||
|
/** Result */
|
||||||
|
|
||||||
|
#qunit-testresult {
|
||||||
|
padding: 0.5em 0.5em 0.5em 2.5em;
|
||||||
|
|
||||||
|
color: #2b81af;
|
||||||
|
background-color: #D2E0E6;
|
||||||
|
|
||||||
|
border-bottom: 1px solid white;
|
||||||
|
}
|
||||||
|
#qunit-testresult .module-name {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fixture */
|
||||||
|
|
||||||
|
#qunit-fixture {
|
||||||
|
position: absolute;
|
||||||
|
top: -10000px;
|
||||||
|
left: -10000px;
|
||||||
|
width: 1000px;
|
||||||
|
height: 1000px;
|
||||||
|
}
|
||||||
1863
vendor/backbone/test/vendor/qunit.js
vendored
Executable file
230
vendor/backbone/test/view.js
vendored
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
var view;
|
||||||
|
|
||||||
|
module("Backbone.View", {
|
||||||
|
|
||||||
|
setup: function() {
|
||||||
|
view = new Backbone.View({
|
||||||
|
id : 'test-view',
|
||||||
|
className : 'test-view'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: constructor", 4, function() {
|
||||||
|
equal(view.el.id, 'test-view');
|
||||||
|
equal(view.el.className, 'test-view');
|
||||||
|
equal(view.options.id, 'test-view');
|
||||||
|
equal(view.options.className, 'test-view');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: jQuery", 2, function() {
|
||||||
|
view.setElement(document.body);
|
||||||
|
ok(view.$('#qunit-header a').get(0).innerHTML.match(/Backbone Test Suite/));
|
||||||
|
ok(view.$('#qunit-header a').get(1).innerHTML.match(/Backbone Speed Suite/));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: make", 3, function() {
|
||||||
|
var div = view.make('div', {id: 'test-div'}, "one two three");
|
||||||
|
equal(div.tagName.toLowerCase(), 'div');
|
||||||
|
equal(div.id, 'test-div');
|
||||||
|
equal($(div).text(), 'one two three');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: make can take falsy values for content", 2, function() {
|
||||||
|
var div = view.make('div', {id: 'test-div'}, 0);
|
||||||
|
equal($(div).text(), '0');
|
||||||
|
|
||||||
|
var div = view.make('div', {id: 'test-div'}, '');
|
||||||
|
equal($(div).text(), '');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: initialize", 1, function() {
|
||||||
|
var View = Backbone.View.extend({
|
||||||
|
initialize: function() {
|
||||||
|
this.one = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var view = new View;
|
||||||
|
equal(view.one, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: delegateEvents", 6, function() {
|
||||||
|
var counter = 0;
|
||||||
|
var counter2 = 0;
|
||||||
|
view.setElement(document.body);
|
||||||
|
view.increment = function(){ counter++; };
|
||||||
|
view.$el.bind('click', function(){ counter2++; });
|
||||||
|
var events = {"click #qunit-banner": "increment"};
|
||||||
|
view.delegateEvents(events);
|
||||||
|
$('#qunit-banner').trigger('click');
|
||||||
|
equal(counter, 1);
|
||||||
|
equal(counter2, 1);
|
||||||
|
$('#qunit-banner').trigger('click');
|
||||||
|
equal(counter, 2);
|
||||||
|
equal(counter2, 2);
|
||||||
|
view.delegateEvents(events);
|
||||||
|
$('#qunit-banner').trigger('click');
|
||||||
|
equal(counter, 3);
|
||||||
|
equal(counter2, 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: delegateEvents allows functions for callbacks", 3, function() {
|
||||||
|
view.counter = 0;
|
||||||
|
view.setElement("#qunit-banner");
|
||||||
|
var events = {"click": function() { this.counter++; }};
|
||||||
|
view.delegateEvents(events);
|
||||||
|
$('#qunit-banner').trigger('click');
|
||||||
|
equal(view.counter, 1);
|
||||||
|
$('#qunit-banner').trigger('click');
|
||||||
|
equal(view.counter, 2);
|
||||||
|
view.delegateEvents(events);
|
||||||
|
$('#qunit-banner').trigger('click');
|
||||||
|
equal(view.counter, 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: undelegateEvents", 6, function() {
|
||||||
|
var counter = 0;
|
||||||
|
var counter2 = 0;
|
||||||
|
view.setElement(document.body);
|
||||||
|
view.increment = function(){ counter++; };
|
||||||
|
$(view.el).unbind('click');
|
||||||
|
$(view.el).bind('click', function(){ counter2++; });
|
||||||
|
var events = {"click #qunit-userAgent": "increment"};
|
||||||
|
view.delegateEvents(events);
|
||||||
|
$('#qunit-userAgent').trigger('click');
|
||||||
|
equal(counter, 1);
|
||||||
|
equal(counter2, 1);
|
||||||
|
view.undelegateEvents();
|
||||||
|
$('#qunit-userAgent').trigger('click');
|
||||||
|
equal(counter, 1);
|
||||||
|
equal(counter2, 2);
|
||||||
|
view.delegateEvents(events);
|
||||||
|
$('#qunit-userAgent').trigger('click');
|
||||||
|
equal(counter, 2);
|
||||||
|
equal(counter2, 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: _ensureElement with DOM node el", 1, function() {
|
||||||
|
var ViewClass = Backbone.View.extend({
|
||||||
|
el: document.body
|
||||||
|
});
|
||||||
|
var view = new ViewClass;
|
||||||
|
equal(view.el, document.body);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: _ensureElement with string el", 3, function() {
|
||||||
|
var ViewClass = Backbone.View.extend({
|
||||||
|
el: "body"
|
||||||
|
});
|
||||||
|
var view = new ViewClass;
|
||||||
|
strictEqual(view.el, document.body);
|
||||||
|
|
||||||
|
ViewClass = Backbone.View.extend({
|
||||||
|
el: "#testElement > h1"
|
||||||
|
});
|
||||||
|
view = new ViewClass;
|
||||||
|
strictEqual(view.el, $("#testElement > h1").get(0));
|
||||||
|
|
||||||
|
ViewClass = Backbone.View.extend({
|
||||||
|
el: "#nonexistent"
|
||||||
|
});
|
||||||
|
view = new ViewClass;
|
||||||
|
ok(!view.el);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: with attributes", 2, function() {
|
||||||
|
var view = new Backbone.View({attributes : {'class': 'one', id: 'two'}});
|
||||||
|
equal(view.el.className, 'one');
|
||||||
|
equal(view.el.id, 'two');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: with attributes as a function", 1, function() {
|
||||||
|
var viewClass = Backbone.View.extend({
|
||||||
|
attributes: function() {
|
||||||
|
return {'class': 'dynamic'};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
equal((new viewClass).el.className, 'dynamic');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: multiple views per element", 3, function() {
|
||||||
|
var count = 0, ViewClass = Backbone.View.extend({
|
||||||
|
el: $("body"),
|
||||||
|
events: {
|
||||||
|
"click": "click"
|
||||||
|
},
|
||||||
|
click: function() {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var view1 = new ViewClass;
|
||||||
|
$("body").trigger("click");
|
||||||
|
equal(1, count);
|
||||||
|
|
||||||
|
var view2 = new ViewClass;
|
||||||
|
$("body").trigger("click");
|
||||||
|
equal(3, count);
|
||||||
|
|
||||||
|
view1.delegateEvents();
|
||||||
|
$("body").trigger("click");
|
||||||
|
equal(5, count);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View: custom events, with namespaces", 2, function() {
|
||||||
|
var count = 0;
|
||||||
|
var ViewClass = Backbone.View.extend({
|
||||||
|
el: $('body'),
|
||||||
|
events: function() {
|
||||||
|
return {"fake$event.namespaced": "run"};
|
||||||
|
},
|
||||||
|
run: function() {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var view = new ViewClass;
|
||||||
|
$('body').trigger('fake$event').trigger('fake$event');
|
||||||
|
equal(count, 2);
|
||||||
|
$('body').unbind('.namespaced');
|
||||||
|
$('body').trigger('fake$event');
|
||||||
|
equal(count, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1048 - setElement uses provided object.", 2, function() {
|
||||||
|
var $el = $('body');
|
||||||
|
var view = new Backbone.View({el: $el});
|
||||||
|
ok(view.$el === $el);
|
||||||
|
view.setElement($el = $($el));
|
||||||
|
ok(view.$el === $el);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#986 - Undelegate before changing element.", 1, function() {
|
||||||
|
var a = $('<button></button>');
|
||||||
|
var b = $('<button></button>');
|
||||||
|
var View = Backbone.View.extend({
|
||||||
|
events: {click: function(e) { ok(view.el === e.target); }}
|
||||||
|
});
|
||||||
|
var view = new View({el: a});
|
||||||
|
view.setElement(b);
|
||||||
|
a.trigger('click');
|
||||||
|
b.trigger('click');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1172 - Clone attributes object", 2, function() {
|
||||||
|
var View = Backbone.View.extend({attributes: {foo: 'bar'}});
|
||||||
|
var v1 = new View({id: 'foo'});
|
||||||
|
strictEqual(v1.el.id, 'foo');
|
||||||
|
var v2 = new View();
|
||||||
|
ok(!v2.el.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1228 - tagName can be provided as a function", 1, function() {
|
||||||
|
var View = Backbone.View.extend({tagName: function(){ return 'p'; }});
|
||||||
|
ok(new View().$el.is('p'));
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
22
vendor/benchmark.js/LICENSE.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Copyright 2010-2012 Mathias Bynens <http://mathiasbynens.be/>
|
||||||
|
Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
|
||||||
|
Modified by John-David Dalton <http://allyoucanleet.com/>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
151
vendor/benchmark.js/README.md
vendored
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
# Benchmark.js <sup>v1.0.0-pre</sup>
|
||||||
|
|
||||||
|
A [robust](http://calendar.perfplanet.com/2010/bulletproof-javascript-benchmarks/ "Bulletproof JavaScript benchmarks") benchmarking library that works on nearly all JavaScript platforms<sup><a name="fnref1" href="#fn1">1</a></sup>, supports high-resolution timers, and returns statistically significant results. As seen on [jsPerf](http://jsperf.com/).
|
||||||
|
|
||||||
|
## BestieJS
|
||||||
|
|
||||||
|
Benchmark.js is part of the BestieJS *"Best in Class"* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
The documentation for Benchmark.js can be viewed here: <http://benchmarkjs.com/docs>
|
||||||
|
|
||||||
|
For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/benchmark.js/wiki/Roadmap).
|
||||||
|
|
||||||
|
## Installation and usage
|
||||||
|
|
||||||
|
In a browser or Adobe AIR:
|
||||||
|
|
||||||
|
~~~ html
|
||||||
|
<script src="benchmark.js"></script>
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Optionally, expose Java’s nanosecond timer by adding the `nano` applet to the `<body>`:
|
||||||
|
|
||||||
|
~~~ html
|
||||||
|
<applet code="nano" archive="nano.jar"></applet>
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Or enable Chrome’s microsecond timer by using the [command line switch](http://peter.sh/experiments/chromium-command-line-switches/#enable-benchmarking):
|
||||||
|
|
||||||
|
--enable-benchmarking
|
||||||
|
|
||||||
|
Via [npm](http://npmjs.org/):
|
||||||
|
|
||||||
|
~~~ bash
|
||||||
|
npm install benchmark
|
||||||
|
~~~
|
||||||
|
|
||||||
|
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
|
||||||
|
|
||||||
|
~~~ js
|
||||||
|
var Benchmark = require('benchmark');
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Optionally, use the [microtime module](https://github.com/wadey/node-microtime) by Wade Simmons:
|
||||||
|
|
||||||
|
~~~ bash
|
||||||
|
npm install microtime
|
||||||
|
~~~
|
||||||
|
|
||||||
|
In [Narwhal](http://narwhaljs.org/) and [RingoJS v0.7.0-](http://ringojs.org/):
|
||||||
|
|
||||||
|
~~~ js
|
||||||
|
var Benchmark = require('benchmark').Benchmark;
|
||||||
|
~~~
|
||||||
|
|
||||||
|
In [Rhino](http://www.mozilla.org/rhino/):
|
||||||
|
|
||||||
|
~~~ js
|
||||||
|
load('benchmark.js');
|
||||||
|
~~~
|
||||||
|
|
||||||
|
In an AMD loader like [RequireJS](http://requirejs.org/):
|
||||||
|
|
||||||
|
~~~ js
|
||||||
|
require({
|
||||||
|
'paths': {
|
||||||
|
'benchmark': 'path/to/benchmark'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
['benchmark'], function(Benchmark) {
|
||||||
|
console.log(Benchmark.version);
|
||||||
|
});
|
||||||
|
|
||||||
|
// or with platform.js
|
||||||
|
// https://github.com/bestiejs/platform.js
|
||||||
|
require({
|
||||||
|
'paths': {
|
||||||
|
'benchmark': 'path/to/benchmark',
|
||||||
|
'platform': 'path/to/platform'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
['benchmark', 'platform'], function(Benchmark, platform) {
|
||||||
|
Benchmark.platform = platform;
|
||||||
|
console.log(Benchmark.platform.name);
|
||||||
|
});
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Usage example:
|
||||||
|
|
||||||
|
~~~ js
|
||||||
|
var suite = new Benchmark.Suite;
|
||||||
|
|
||||||
|
// add tests
|
||||||
|
suite.add('RegExp#test', function() {
|
||||||
|
/o/.test('Hello World!');
|
||||||
|
})
|
||||||
|
.add('String#indexOf', function() {
|
||||||
|
'Hello World!'.indexOf('o') > -1;
|
||||||
|
})
|
||||||
|
// add listeners
|
||||||
|
.on('cycle', function(event) {
|
||||||
|
console.log(String(event.target));
|
||||||
|
})
|
||||||
|
.on('complete', function() {
|
||||||
|
console.log('Fastest is ' + this.filter('fastest').pluck('name'));
|
||||||
|
})
|
||||||
|
// run async
|
||||||
|
.run({ 'async': true });
|
||||||
|
|
||||||
|
// logs:
|
||||||
|
// > RegExp#test x 4,161,532 +-0.99% (59 cycles)
|
||||||
|
// > String#indexOf x 6,139,623 +-1.00% (131 cycles)
|
||||||
|
// > Fastest is String#indexOf
|
||||||
|
~~~
|
||||||
|
|
||||||
|
## Cloning this repo
|
||||||
|
|
||||||
|
To clone this repository including all submodules, using Git 1.6.5 or later:
|
||||||
|
|
||||||
|
~~~ bash
|
||||||
|
git clone --recursive https://github.com/bestiejs/benchmark.js.git
|
||||||
|
cd benchmark.js
|
||||||
|
~~~
|
||||||
|
|
||||||
|
For older Git versions, just use:
|
||||||
|
|
||||||
|
~~~ bash
|
||||||
|
git clone https://github.com/bestiejs/benchmark.js.git
|
||||||
|
cd benchmark.js
|
||||||
|
git submodule update --init
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Feel free to fork and send pull requests if you see improvements!
|
||||||
|
|
||||||
|
## Footnotes
|
||||||
|
|
||||||
|
1. Benchmark.js has been tested in at least Adobe AIR 2.6, Chrome 5-15, Firefox 1.5-8, IE 6-10, Opera 9.25-11.52, Safari 2-5.1.1, Node.js 0.4.8-0.6.1, Narwhal 0.3.2, RingoJS 0.7-0.8, and Rhino 1.7RC3.
|
||||||
|
<a name="fn1" title="Jump back to footnote 1 in the text." href="#fnref1">↩</a>
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
* [Mathias Bynens](http://mathiasbynens.be/)
|
||||||
|
[](https://twitter.com/mathias "Follow @mathias on Twitter")
|
||||||
|
* [John-David Dalton](http://allyoucanleet.com/)
|
||||||
|
[](https://twitter.com/jdalton "Follow @jdalton on Twitter")
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
* [Kit Cambridge](http://kitcambridge.github.com/)
|
||||||
|
[](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter")
|
||||||
3830
vendor/benchmark.js/benchmark.js
vendored
Normal file
BIN
vendor/benchmark.js/nano.jar
vendored
Normal file
20
vendor/docdown/LICENSE.txt
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
44
vendor/docdown/README.md
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# Docdown <sup>v1.0.0-pre</sup>
|
||||||
|
|
||||||
|
A simple JSDoc to Markdown documentation generator.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
The documentation for Docdown can be viewed here: [/doc/README.md](https://github.com/jdalton/docdown/blob/master/doc/README.md#readme)
|
||||||
|
|
||||||
|
For a list of upcoming features, check out our [roadmap](https://github.com/jdalton/docdown/wiki/Roadmap).
|
||||||
|
|
||||||
|
## Installation and usage
|
||||||
|
|
||||||
|
Usage example:
|
||||||
|
|
||||||
|
~~~ php
|
||||||
|
require("docdown.php");
|
||||||
|
|
||||||
|
// generate Markdown
|
||||||
|
$markdown = docdown(array(
|
||||||
|
"path" => $filepath,
|
||||||
|
"url" => "https://github.com/username/project/blob/master/my.js"
|
||||||
|
));
|
||||||
|
~~~
|
||||||
|
|
||||||
|
## Cloning this repo
|
||||||
|
|
||||||
|
To clone this repository just use:
|
||||||
|
|
||||||
|
~~~ bash
|
||||||
|
git clone https://github.com/docdown/docdown.git
|
||||||
|
cd docdown
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Feel free to fork and send pull requests if you see improvements!
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
* [John-David Dalton](http://allyoucanleet.com/)
|
||||||
|
[](https://twitter.com/jdalton "Follow @jdalton on Twitter")
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
* [Mathias Bynens](http://mathiasbynens.be/)
|
||||||
|
[](https://twitter.com/mathias "Follow @mathias on Twitter")
|
||||||
38
vendor/docdown/docdown.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
/*!
|
||||||
|
* Docdown v1.0.0-pre
|
||||||
|
* Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
||||||
|
* Available under MIT license <http://mths.be/mit>
|
||||||
|
*/
|
||||||
|
require(dirname(__FILE__) . '/src/DocDown/Generator.php');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates Markdown from JSDoc entries in a given file.
|
||||||
|
*
|
||||||
|
* @param {Array} [$options=array()] The options array.
|
||||||
|
* @returns {String} The generated Markdown.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* // specify a file path
|
||||||
|
* $markdown = docdown(array(
|
||||||
|
* // path to js file
|
||||||
|
* 'path' => $filepath,
|
||||||
|
* // url used to reference line numbers in code
|
||||||
|
* 'url' => 'https://github.com/username/project/blob/master/my.js'
|
||||||
|
* ));
|
||||||
|
*
|
||||||
|
* // or pass raw js
|
||||||
|
* $markdown = docdown(array(
|
||||||
|
* // raw JavaScript source
|
||||||
|
* 'source' => $rawJS,
|
||||||
|
* // documentation title
|
||||||
|
* 'title' => 'My API Documentation',
|
||||||
|
* // url used to reference line numbers in code
|
||||||
|
* 'url' => 'https://github.com/username/project/blob/master/my.js'
|
||||||
|
* ));
|
||||||
|
*/
|
||||||
|
function docdown( $options = array() ) {
|
||||||
|
$gen = new Generator($options);
|
||||||
|
return $gen->generate();
|
||||||
|
}
|
||||||
|
?>
|
||||||
304
vendor/docdown/src/DocDown/Entry.php
vendored
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class to simplify parsing a single JSDoc entry.
|
||||||
|
*/
|
||||||
|
class Entry {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The documentation entry.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
public $entry = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The language highlighter used for code examples.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
public $lang = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The source code.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
public $source = '';
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Entry constructor.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {String} $entry The documentation entry to analyse.
|
||||||
|
* @param {String} $source The source code.
|
||||||
|
* @param {String} $lang The language highlighter used for code examples.
|
||||||
|
*/
|
||||||
|
public function __construct( $entry, $source, $lang = 'js' ) {
|
||||||
|
$this->entry = $entry;
|
||||||
|
$this->lang = $lang;
|
||||||
|
$this->source = str_replace(PHP_EOL, "\n", $source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the documentation entries from source code.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf Entry
|
||||||
|
* @param {String} $source The source code.
|
||||||
|
* @returns {Array} The array of entries.
|
||||||
|
*/
|
||||||
|
public static function getEntries( $source ) {
|
||||||
|
preg_match_all('#/\*\*(?![-!])[\s\S]*?\*/\s*[^\n]+#', $source, $result);
|
||||||
|
return array_pop($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the entry is a function reference.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {Boolean} Returns `true` if the entry is a function reference, else `false`.
|
||||||
|
*/
|
||||||
|
private function isFunction() {
|
||||||
|
return !!(
|
||||||
|
$this->isCtor() ||
|
||||||
|
count($this->getParams()) ||
|
||||||
|
count($this->getReturns()) ||
|
||||||
|
preg_match('/\*\s*@function\b/', $this->entry)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the function call from the entry.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {String} The function call.
|
||||||
|
*/
|
||||||
|
public function getCall() {
|
||||||
|
preg_match('#\*/\s*(?:function ([^(]*)|(.*?)(?=[:=,]|return\b))#', $this->entry, $result);
|
||||||
|
if ($result = array_pop($result)) {
|
||||||
|
$result = array_pop(explode('var ', trim(trim(array_pop(explode('.', $result))), "'")));
|
||||||
|
}
|
||||||
|
// resolve name
|
||||||
|
// avoid $this->getName() because it calls $this->getCall()
|
||||||
|
preg_match('#\*\s*@name\s+([^\n]+)#', $this->entry, $name);
|
||||||
|
if (count($name)) {
|
||||||
|
$name = trim($name[1]);
|
||||||
|
} else {
|
||||||
|
$name = $result;
|
||||||
|
}
|
||||||
|
// compile function call syntax
|
||||||
|
if ($this->isFunction()) {
|
||||||
|
// compose parts
|
||||||
|
$result = array($result);
|
||||||
|
$params = $this->getParams();
|
||||||
|
foreach ($params as $param) {
|
||||||
|
$result[] = $param[1];
|
||||||
|
}
|
||||||
|
// format
|
||||||
|
$result = $name .'('. implode(array_slice($result, 1), ', ') .')';
|
||||||
|
$result = str_replace(', [', ' [, ', str_replace('], [', ', ', $result));
|
||||||
|
}
|
||||||
|
return $result ? $result : $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry description.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {String} The entry description.
|
||||||
|
*/
|
||||||
|
public function getDesc() {
|
||||||
|
preg_match('#/\*\*(?:\s*\*)?([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
|
||||||
|
if (count($result)) {
|
||||||
|
$type = $this->getType();
|
||||||
|
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
||||||
|
$result = ($type == 'Function' ? '' : '(' . str_replace('|', ', ', trim($type, '{}')) . '): ') . $result;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry `example` data.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {String} The entry `example` data.
|
||||||
|
*/
|
||||||
|
public function getExample() {
|
||||||
|
preg_match('#\*\s*@example\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
|
||||||
|
if (count($result)) {
|
||||||
|
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', "\n", $result[1]));
|
||||||
|
$result = '~~~ ' . $this->lang . "\n" . $result . "\n~~~";
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the line number of the entry.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {Number} The line number.
|
||||||
|
*/
|
||||||
|
public function getLineNumber() {
|
||||||
|
preg_match_all('/\n/', substr($this->source, 0, strrpos($this->source, $this->entry) + strlen($this->entry)), $lines);
|
||||||
|
return count(array_pop($lines)) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry `member` data.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @param {Number} $index The index of the array value to return.
|
||||||
|
* @returns {Array|String} The entry `member` data.
|
||||||
|
*/
|
||||||
|
public function getMembers( $index = null ) {
|
||||||
|
preg_match('#\*\s*@member(?:Of)?\s+([^\n]+)#', $this->entry, $result);
|
||||||
|
if (count($result)) {
|
||||||
|
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
||||||
|
$result = preg_split('/,\s*/', $result);
|
||||||
|
}
|
||||||
|
return $index !== null ? @$result[$index] : $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry `name` data.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {String} The entry `name` data.
|
||||||
|
*/
|
||||||
|
public function getName() {
|
||||||
|
preg_match('#\*\s*@name\s+([^\n]+)#', $this->entry, $result);
|
||||||
|
if (count($result)) {
|
||||||
|
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
||||||
|
} else {
|
||||||
|
$result = array_shift(explode('(', $this->getCall()));
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry `param` data.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @param {Number} $index The index of the array value to return.
|
||||||
|
* @returns {Array} The entry `param` data.
|
||||||
|
*/
|
||||||
|
public function getParams( $index = null ) {
|
||||||
|
preg_match_all('#\*\s*@param\s+\{([^}]+)\}\s+(\[[^]]+\]|[$\w]+)\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#i', $this->entry, $result);
|
||||||
|
if (count($result = array_filter(array_slice($result, 1)))) {
|
||||||
|
// repurpose array
|
||||||
|
foreach ($result as $param) {
|
||||||
|
foreach ($param as $key => $value) {
|
||||||
|
if (!is_array($result[0][$key])) {
|
||||||
|
$result[0][$key] = array();
|
||||||
|
}
|
||||||
|
$result[0][$key][] = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result = $result[0];
|
||||||
|
}
|
||||||
|
return $index !== null ? @$result[$index] : $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry `returns` data.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {String} The entry `returns` data.
|
||||||
|
*/
|
||||||
|
public function getReturns() {
|
||||||
|
preg_match('#\*\s*@returns\s+\{([^}]+)\}\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
|
||||||
|
if (count($result)) {
|
||||||
|
$result = array_map('trim', array_slice($result, 1));
|
||||||
|
$result[0] = str_replace('|', ', ', $result[0]);
|
||||||
|
$result[1] = preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry `type` data.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {String} The entry `type` data.
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
preg_match('#\*\s*@type\s+([^\n]+)#', $this->entry, $result);
|
||||||
|
if (count($result)) {
|
||||||
|
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
||||||
|
} else {
|
||||||
|
$result = $this->isFunction() ? 'Function' : 'Unknown';
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an entry is a constructor.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {Boolean} Returns true if a constructor, else false.
|
||||||
|
*/
|
||||||
|
public function isCtor() {
|
||||||
|
return !!preg_match('/\*\s*@constructor\b/', $this->entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an entry *is* assigned to a prototype.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {Boolean} Returns true if assigned to a prototype, else false.
|
||||||
|
*/
|
||||||
|
public function isPlugin() {
|
||||||
|
return !$this->isCtor() && !$this->isPrivate() && !$this->isStatic();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an entry is private.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {Boolean} Returns true if private, else false.
|
||||||
|
*/
|
||||||
|
public function isPrivate() {
|
||||||
|
return !!preg_match('/\*\s*@private\b/', $this->entry) || strrpos($this->entry, '@') === false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an entry is *not* assigned to a prototype.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {Boolean} Returns true if not assigned to a prototype, else false.
|
||||||
|
*/
|
||||||
|
public function isStatic() {
|
||||||
|
$public = !$this->isPrivate();
|
||||||
|
$result = $public && !!preg_match('/\*\s*@static\b/', $this->entry);
|
||||||
|
|
||||||
|
// set in cases where it isn't explicitly stated
|
||||||
|
if ($public && !$result) {
|
||||||
|
if ($parent = array_pop(preg_split('/[#.]/', $this->getMembers(0)))) {
|
||||||
|
foreach (Entry::getEntries($this->source) as $entry) {
|
||||||
|
$entry = new Entry($entry, $this->source);
|
||||||
|
if ($entry->getName() == $parent) {
|
||||||
|
$result = !$entry->isCtor();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
391
vendor/docdown/src/DocDown/Generator.php
vendored
Normal file
@@ -0,0 +1,391 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require(dirname(__FILE__) . "/Entry.php");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates Markdown from JSDoc entries.
|
||||||
|
*/
|
||||||
|
class Generator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of JSDoc entries.
|
||||||
|
*
|
||||||
|
* @memberOf Generator
|
||||||
|
* @type Array
|
||||||
|
*/
|
||||||
|
public $entries = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An options array used to configure the generator.
|
||||||
|
*
|
||||||
|
* @memberOf Generator
|
||||||
|
* @type Array
|
||||||
|
*/
|
||||||
|
public $options = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entire file's source code.
|
||||||
|
*
|
||||||
|
* @memberOf Generator
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
public $source = '';
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Generator constructor.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {String} $source The source code to parse.
|
||||||
|
* @param {Array} $options The options array.
|
||||||
|
*/
|
||||||
|
public function __construct( $source, $options = array() ) {
|
||||||
|
// juggle arguments
|
||||||
|
if (is_array($source)) {
|
||||||
|
$options = $source;
|
||||||
|
} else {
|
||||||
|
$options['source'] = $source;
|
||||||
|
}
|
||||||
|
if (isset($options['source']) && realpath($options['source'])) {
|
||||||
|
$options['path'] = $options['source'];
|
||||||
|
}
|
||||||
|
if (isset($options['path'])) {
|
||||||
|
preg_match('/(?<=\.)[a-z]+$/', $options['path'], $ext);
|
||||||
|
$options['source'] = file_get_contents($options['path']);
|
||||||
|
$ext = array_pop($ext);
|
||||||
|
|
||||||
|
if (!isset($options['lang']) && $ext) {
|
||||||
|
$options['lang'] = $ext;
|
||||||
|
}
|
||||||
|
if (!isset($options['title'])) {
|
||||||
|
$options['title'] = ucfirst(basename($options['path'])) . ' API documentation';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isset($options['lang'])) {
|
||||||
|
$options['lang'] = 'js';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->options = $options;
|
||||||
|
$this->source = str_replace(PHP_EOL, "\n", $options['source']);
|
||||||
|
$this->entries = Entry::getEntries($this->source);
|
||||||
|
|
||||||
|
foreach ($this->entries as $index => $value) {
|
||||||
|
$this->entries[$index] = new Entry($value, $this->source, $options['lang']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs common string formatting operations.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @static
|
||||||
|
* @memberOf Generator
|
||||||
|
* @param {String} $string The string to format.
|
||||||
|
* @returns {String} The formatted string.
|
||||||
|
*/
|
||||||
|
private static function format($string) {
|
||||||
|
// mark numbers as code and italicize parentheses
|
||||||
|
return trim(preg_replace('/(^|\s)(\([^)]+\))/', '$1*$2*',
|
||||||
|
preg_replace('/ (-?\d+(?:.\d+)?)(?!\.[^\n])/', ' `$1`', $string)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify a string by replacing named tokens with matching assoc. array values.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @static
|
||||||
|
* @memberOf Generator
|
||||||
|
* @param {String} $string The string to modify.
|
||||||
|
* @param {Array|Object} $object The template object.
|
||||||
|
* @returns {String} The modified string.
|
||||||
|
*/
|
||||||
|
private static function interpolate($string, $object) {
|
||||||
|
preg_match_all('/#\{([^}]+)\}/', $string, $tokens);
|
||||||
|
$tokens = array_unique(array_pop($tokens));
|
||||||
|
|
||||||
|
foreach ($tokens as $token) {
|
||||||
|
$pattern = '/#\{' . $token . '\}/';
|
||||||
|
$replacement = '';
|
||||||
|
|
||||||
|
if (is_object($object)) {
|
||||||
|
preg_match('/\(([^)]+?)\)$/', $token, $args);
|
||||||
|
$args = preg_split('/,\s*/', array_pop($args));
|
||||||
|
$method = 'get' . ucfirst(str_replace('/\([^)]+?\)$/', '', $token));
|
||||||
|
|
||||||
|
if (method_exists($object, $method)) {
|
||||||
|
$replacement = (string) call_user_func_array(array($object, $method), $args);
|
||||||
|
} else if (isset($object->{$token})) {
|
||||||
|
$replacement = (string) $object->{$token};
|
||||||
|
}
|
||||||
|
} else if (isset($object[$token])) {
|
||||||
|
$replacement = (string) $object[$token];
|
||||||
|
}
|
||||||
|
$string = preg_replace($pattern, trim($replacement), $string);
|
||||||
|
}
|
||||||
|
return Generator::format($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the entry's hash used to navigate the documentation.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @memberOf Generator
|
||||||
|
* @param {Number|Object} $entry The entry object.
|
||||||
|
* @param {String} $member The name of the member.
|
||||||
|
* @returns {String} The url hash.
|
||||||
|
*/
|
||||||
|
private function getHash( $entry, $member = '' ) {
|
||||||
|
$entry = is_numeric($entry) ? $this->entries[$entry] : $entry;
|
||||||
|
$member = !$member ? $entry->getMembers(0) : $member;
|
||||||
|
$result = ($member ? $member . ($entry->isPlugin() ? 'prototype' : '') : '') . $entry->getCall();
|
||||||
|
$result = preg_replace('/\(\[|\[\]/', '', $result);
|
||||||
|
$result = preg_replace('/[ =\'"{}.()\]]/', '', $result);
|
||||||
|
$result = preg_replace('/[[#,]/', '-', $result);
|
||||||
|
return strtolower($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the entry's url for the specific line number.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @memberOf Generator
|
||||||
|
* @param {Number|Object} $entry The entry object.
|
||||||
|
* @returns {String} The url.
|
||||||
|
*/
|
||||||
|
private function getLineUrl( $entry ) {
|
||||||
|
$entry = is_numeric($entry) ? $this->entries($entry) : $entry;
|
||||||
|
return $this->options['url'] . '#L' . $entry->getLineNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the character used to separate the entry's name from its member.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @memberOf Generator
|
||||||
|
* @param {Number|Object} $entry The entry object.
|
||||||
|
* @returns {String} The separator.
|
||||||
|
*/
|
||||||
|
private function getSeparator( $entry ) {
|
||||||
|
$entry = is_numeric($entry) ? $this->entries($entry) : $entry;
|
||||||
|
return $entry->isPlugin() ? '.prototype.' : '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates Markdown from JSDoc entries.
|
||||||
|
*
|
||||||
|
* @memberOf Generator
|
||||||
|
* @returns {String} The rendered Markdown.
|
||||||
|
*/
|
||||||
|
public function generate() {
|
||||||
|
$api = array();
|
||||||
|
$compiling = false;
|
||||||
|
$openTag = "\n<!-- div -->\n";
|
||||||
|
$closeTag = "\n<!-- /div -->\n";
|
||||||
|
$result = array('# ' . $this->options['title']);
|
||||||
|
|
||||||
|
// initialize $api array
|
||||||
|
foreach ($this->entries as $entry) {
|
||||||
|
|
||||||
|
if (!$entry->isPrivate()) {
|
||||||
|
$name = $entry->getName();
|
||||||
|
$members = $entry->getMembers();
|
||||||
|
$members = count($members) ? $members : array('');
|
||||||
|
|
||||||
|
foreach ($members as $member) {
|
||||||
|
// create api category arrays
|
||||||
|
if (!isset($api[$member]) && $member) {
|
||||||
|
$api[$member] = new Entry('', '', $entry->lang);
|
||||||
|
$api[$member]->static = array();
|
||||||
|
$api[$member]->plugin = array();
|
||||||
|
}
|
||||||
|
// append entry to api category
|
||||||
|
if (!$member || $entry->isCtor() || ($entry->getType() == 'Object' &&
|
||||||
|
!preg_match('/[=:]\s*null\s*[,;]?$/', $entry->entry))) {
|
||||||
|
$member = ($member ? $member . ($entry->isPlugin() ? '#' : '.') : '') . $name;
|
||||||
|
$entry->static = @$api[$member] ? $api[$member]->static : array();
|
||||||
|
$entry->plugin = @$api[$member] ? $api[$member]->plugin : array();
|
||||||
|
$api[$member] = $entry;
|
||||||
|
}
|
||||||
|
else if ($entry->isStatic()) {
|
||||||
|
$api[$member]->static[] = $entry;
|
||||||
|
} else if (!$entry->isCtor()) {
|
||||||
|
$api[$member]->plugin[] = $entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// custom sort for root level entries
|
||||||
|
// TODO: see how well it handles deeper namespace traversal
|
||||||
|
function sortCompare($a, $b) {
|
||||||
|
$score = array( 'a' => 0, 'b' => 0);
|
||||||
|
foreach (array( 'a' => $a, 'b' => $b) as $key => $value) {
|
||||||
|
// capitalized keys that represent constructor properties are last
|
||||||
|
if (preg_match('/[#.][A-Z]/', $value)) {
|
||||||
|
$score[$key] = 0;
|
||||||
|
}
|
||||||
|
// lowercase keys with prototype properties are next to last
|
||||||
|
else if (preg_match('/#[a-z]/', $value)) {
|
||||||
|
$score[$key] = 1;
|
||||||
|
}
|
||||||
|
// lowercase keys with static properties next to first
|
||||||
|
else if (preg_match('/\.[a-z]/', $value)) {
|
||||||
|
$score[$key] = 2;
|
||||||
|
}
|
||||||
|
// lowercase keys with no properties are first
|
||||||
|
else if (preg_match('/^[^#.]+$/', $value)) {
|
||||||
|
$score[$key] = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$score = $score['b'] - $score['a'];
|
||||||
|
return $score ? $score : strcasecmp($a, $b);
|
||||||
|
}
|
||||||
|
|
||||||
|
uksort($api, 'sortCompare');
|
||||||
|
|
||||||
|
// sort static and plugin sub-entries
|
||||||
|
foreach ($api as $entry) {
|
||||||
|
foreach (array('static', 'plugin') as $kind) {
|
||||||
|
$sortBy = array( 'a' => array(), 'b' => array(), 'c' => array() );
|
||||||
|
foreach ($entry->{$kind} as $subentry) {
|
||||||
|
$name = $subentry->getName();
|
||||||
|
// functions w/o ALL-CAPs names are last
|
||||||
|
$sortBy['a'][] = $subentry->getType() == 'Function' && !preg_match('/^[A-Z_]+$/', $name);
|
||||||
|
// ALL-CAPs properties first
|
||||||
|
$sortBy['b'][] = preg_match('/^[A-Z_]+$/', $name);
|
||||||
|
// lowercase alphanumeric sort
|
||||||
|
$sortBy['c'][] = strtolower($name);
|
||||||
|
}
|
||||||
|
array_multisort($sortBy['a'], SORT_ASC, $sortBy['b'], SORT_DESC, $sortBy['c'], SORT_ASC, $entry->{$kind});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// compile TOC
|
||||||
|
$result[] = $openTag;
|
||||||
|
|
||||||
|
foreach ($api as $key => $entry) {
|
||||||
|
$entry->hash = $this->getHash($entry);
|
||||||
|
$entry->href = $this->getLineUrl($entry);
|
||||||
|
|
||||||
|
$member = $entry->getMembers(0);
|
||||||
|
$member = ($member ? $member . ($entry->isPlugin() ? '.prototype.' : '.') : '') . $entry->getName();
|
||||||
|
|
||||||
|
$entry->member = preg_replace('/' . $entry->getName() . '$/', '', $member);
|
||||||
|
|
||||||
|
$compiling = $compiling ? ($result[] = $closeTag) : true;
|
||||||
|
|
||||||
|
// add root entry
|
||||||
|
array_push(
|
||||||
|
$result,
|
||||||
|
$openTag, '## ' . (count($result) == 2 ? '<a id="toc"></a>' : '') . '`' . $member . '`',
|
||||||
|
Generator::interpolate('* [`' . $member . '`](##{hash})', $entry)
|
||||||
|
);
|
||||||
|
|
||||||
|
// add static and plugin sub-entries
|
||||||
|
foreach (array('static', 'plugin') as $kind) {
|
||||||
|
if ($kind == 'plugin' && count($entry->plugin)) {
|
||||||
|
array_push(
|
||||||
|
$result,
|
||||||
|
$closeTag,
|
||||||
|
$openTag,
|
||||||
|
'## `' . $member . ($entry->isCtor() ? '.prototype`' : '`')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
foreach ($entry->{$kind} as $subentry) {
|
||||||
|
$subentry->hash = $this->getHash($subentry);
|
||||||
|
$subentry->href = $this->getLineUrl($subentry);
|
||||||
|
$subentry->member = $member;
|
||||||
|
$subentry->separator = $this->getSeparator($subentry);
|
||||||
|
$result[] = Generator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $subentry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($result, $closeTag, $closeTag);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// compile content
|
||||||
|
$compiling = false;
|
||||||
|
$result[] = $openTag;
|
||||||
|
|
||||||
|
foreach ($api as $entry) {
|
||||||
|
// add root entry
|
||||||
|
$member = $entry->member . $entry->getName();
|
||||||
|
$compiling = $compiling ? ($result[] = $closeTag) : true;
|
||||||
|
|
||||||
|
array_push($result, $openTag, '## `' . $member . '`');
|
||||||
|
|
||||||
|
foreach (array($entry, 'static', 'plugin') as $kind) {
|
||||||
|
$subentries = is_string($kind) ? $entry->{$kind} : array($kind);
|
||||||
|
|
||||||
|
// title
|
||||||
|
if ($kind != 'static' && $entry->getType() != 'Object' &&
|
||||||
|
count($subentries) && $subentries[0] != $kind) {
|
||||||
|
if ($kind == 'plugin') {
|
||||||
|
$result[] = $closeTag;
|
||||||
|
}
|
||||||
|
array_push(
|
||||||
|
$result,
|
||||||
|
$openTag,
|
||||||
|
'## `' . $member . ($kind == 'plugin' ? '.prototype`' : '`')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// body
|
||||||
|
foreach ($subentries as $subentry) {
|
||||||
|
// description
|
||||||
|
array_push(
|
||||||
|
$result,
|
||||||
|
$openTag,
|
||||||
|
Generator::interpolate("### <a id=\"#{hash}\"></a>`#{member}#{separator}#{call}`\n<a href=\"##{hash}\">#</a> [Ⓢ](#{href} \"View in source\") [Ⓣ][1]\n\n#{desc}", $subentry)
|
||||||
|
);
|
||||||
|
|
||||||
|
// @param
|
||||||
|
if (count($params = $subentry->getParams())) {
|
||||||
|
array_push($result, '', '#### Arguments');
|
||||||
|
foreach ($params as $index => $param) {
|
||||||
|
$result[] = Generator::interpolate('#{num}. `#{name}` (#{type}): #{desc}', array(
|
||||||
|
'desc' => $param[2],
|
||||||
|
'name' => $param[1],
|
||||||
|
'num' => $index + 1,
|
||||||
|
'type' => $param[0]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// @returns
|
||||||
|
if (count($returns = $subentry->getReturns())) {
|
||||||
|
array_push(
|
||||||
|
$result, '',
|
||||||
|
'#### Returns',
|
||||||
|
Generator::interpolate('(#{type}): #{desc}', array('desc' => $returns[1], 'type' => $returns[0]))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// @example
|
||||||
|
if ($example = $subentry->getExample()) {
|
||||||
|
array_push($result, '', '#### Example', $example);
|
||||||
|
}
|
||||||
|
array_push($result, "\n* * *", $closeTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// close tags add TOC link reference
|
||||||
|
array_push($result, $closeTag, $closeTag, '', ' [1]: #toc "Jump back to the TOC."');
|
||||||
|
|
||||||
|
// cleanup whitespace
|
||||||
|
return trim(preg_replace('/ +\n/', "\n", join($result, "\n")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
1049
vendor/firebug-lite/changelog.txt
vendored
Normal file
30
vendor/firebug-lite/license.txt
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2007, Parakey Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Parakey Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of Parakey Inc.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||||
|
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
BIN
vendor/firebug-lite/skin/xp/blank.gif
vendored
Normal file
|
After Width: | Height: | Size: 43 B |
BIN
vendor/firebug-lite/skin/xp/buttonBg.png
vendored
Normal file
|
After Width: | Height: | Size: 167 B |
BIN
vendor/firebug-lite/skin/xp/buttonBgHover.png
vendored
Normal file
|
After Width: | Height: | Size: 171 B |
331
vendor/firebug-lite/skin/xp/debugger.css
vendored
Normal file
@@ -0,0 +1,331 @@
|
|||||||
|
/* See license.txt for terms of usage */
|
||||||
|
|
||||||
|
.panelNode-script {
|
||||||
|
overflow: hidden;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
|
||||||
|
.scriptTooltip {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 2147483647;
|
||||||
|
padding: 2px 3px;
|
||||||
|
border: 1px solid #CBE087;
|
||||||
|
background: LightYellow;
|
||||||
|
font-family: monospace;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
|
||||||
|
.sourceBox {
|
||||||
|
/* TODO: xxxpedro problem with sourceBox and scrolling elements */
|
||||||
|
/*overflow: scroll; /* see issue 1479 */
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceRow {
|
||||||
|
white-space: nowrap;
|
||||||
|
-moz-user-select: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceRow.hovered {
|
||||||
|
background-color: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
|
||||||
|
.sourceLine {
|
||||||
|
-moz-user-select: none;
|
||||||
|
margin-right: 10px;
|
||||||
|
border-right: 1px solid #CCCCCC;
|
||||||
|
padding: 0px 4px 0 20px;
|
||||||
|
background: #EEEEEE no-repeat 2px 0px;
|
||||||
|
color: #888888;
|
||||||
|
white-space: pre;
|
||||||
|
font-family: monospace; /* see issue 2953 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.noteInToolTip { /* below sourceLine, so it overrides it */
|
||||||
|
background-color: #FFD472;
|
||||||
|
}
|
||||||
|
|
||||||
|
.useA11y .sourceBox .sourceViewport:focus .sourceLine {
|
||||||
|
background-color: #FFFFC0;
|
||||||
|
color: navy;
|
||||||
|
border-right: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.useA11y .sourceBox .sourceViewport:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.a11y1emSize {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.useA11y .panelStatusLabel:focus {
|
||||||
|
outline-offset: -2px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceBox > .sourceRow > .sourceLine {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceLine:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceRowText {
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceRow[exe_line="true"] {
|
||||||
|
outline: 1px solid #D9D9B6;
|
||||||
|
margin-right: 1px;
|
||||||
|
background-color: lightgoldenrodyellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceRow[executable="true"] > .sourceLine {
|
||||||
|
content: "-";
|
||||||
|
color: #4AA02C; /* Spring Green */
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceRow[exe_line="true"] > .sourceLine {
|
||||||
|
background-image: url(chrome://firebug/skin/exe.png);
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceRow[breakpoint="true"] > .sourceLine {
|
||||||
|
background-image: url(chrome://firebug/skin/breakpoint.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceRow[breakpoint="true"][condition="true"] > .sourceLine {
|
||||||
|
background-image: url(chrome://firebug/skin/breakpointCondition.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceRow[breakpoint="true"][disabledBreakpoint="true"] > .sourceLine {
|
||||||
|
background-image: url(chrome://firebug/skin/breakpointDisabled.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceRow[breakpoint="true"][exe_line="true"] > .sourceLine {
|
||||||
|
background-image: url(chrome://firebug/skin/breakpointExe.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceRow[breakpoint="true"][exe_line="true"][disabledBreakpoint="true"] > .sourceLine {
|
||||||
|
background-image: url(chrome://firebug/skin/breakpointDisabledExe.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceLine.editing {
|
||||||
|
background-image: url(chrome://firebug/skin/breakpoint.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
|
||||||
|
.conditionEditor {
|
||||||
|
z-index: 2147483647;
|
||||||
|
position: absolute;
|
||||||
|
margin-top: 0;
|
||||||
|
left: 2px;
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conditionEditorInner {
|
||||||
|
position: relative;
|
||||||
|
top: -26px;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conditionCaption {
|
||||||
|
margin-bottom: 2px;
|
||||||
|
font-family: Lucida Grande, sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #226679;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conditionInput {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #0096C0;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conditionEditorInner1 {
|
||||||
|
padding-left: 37px;
|
||||||
|
background: url(condBorders.png) repeat-y;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conditionEditorInner2 {
|
||||||
|
padding-right: 25px;
|
||||||
|
background: url(condBorders.png) repeat-y 100% 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conditionEditorTop1 {
|
||||||
|
background: url(condCorners.png) no-repeat 100% 0;
|
||||||
|
margin-left: 37px;
|
||||||
|
height: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conditionEditorTop2 {
|
||||||
|
position: relative;
|
||||||
|
left: -37px;
|
||||||
|
width: 37px;
|
||||||
|
height: 35px;
|
||||||
|
background: url(condCorners.png) no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conditionEditorBottom1 {
|
||||||
|
background: url(condCorners.png) no-repeat 100% 100%;
|
||||||
|
margin-left: 37px;
|
||||||
|
height: 33px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conditionEditorBottom2 {
|
||||||
|
position: relative; left: -37px;
|
||||||
|
width: 37px;
|
||||||
|
height: 33px;
|
||||||
|
background: url(condCorners.png) no-repeat 0 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
.upsideDown {
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upsideDown .conditionEditorInner {
|
||||||
|
top: -8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upsideDown .conditionEditorInner1 {
|
||||||
|
padding-left: 33px;
|
||||||
|
background: url(condBordersUps.png) repeat-y;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upsideDown .conditionEditorInner2 {
|
||||||
|
padding-right: 25px;
|
||||||
|
background: url(condBordersUps.png) repeat-y 100% 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upsideDown .conditionEditorTop1 {
|
||||||
|
background: url(condCornersUps.png) no-repeat 100% 0;
|
||||||
|
margin-left: 33px;
|
||||||
|
height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upsideDown .conditionEditorTop2 {
|
||||||
|
position: relative;
|
||||||
|
left: -33px;
|
||||||
|
width: 33px;
|
||||||
|
height: 25px;
|
||||||
|
background: url(condCornersUps.png) no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upsideDown .conditionEditorBottom1 {
|
||||||
|
background: url(condCornersUps.png) no-repeat 100% 100%;
|
||||||
|
margin-left: 33px;
|
||||||
|
height: 43px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upsideDown .conditionEditorBottom2 {
|
||||||
|
position: relative;
|
||||||
|
left: -33px;
|
||||||
|
width: 33px;
|
||||||
|
height: 43px;
|
||||||
|
background: url(condCornersUps.png) no-repeat 0 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
|
||||||
|
.breakpointsGroupListBox {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointBlockHead {
|
||||||
|
position: relative;
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointBlockHead > .checkbox {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointBlockHead > .objectLink-sourceLink {
|
||||||
|
top: 4px;
|
||||||
|
right: 20px;
|
||||||
|
background-color: #FFFFFF; /* issue 3308 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointBlockHead > .closeButton {
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointCheckbox {
|
||||||
|
margin-top: 0;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointName {
|
||||||
|
margin-left: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointRow[aria-checked="false"] > .breakpointBlockHead > *,
|
||||||
|
.breakpointRow[aria-checked="false"] > .breakpointCode {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointRow[aria-checked="false"] .breakpointCheckbox,
|
||||||
|
.breakpointRow[aria-checked="false"] .objectLink-sourceLink,
|
||||||
|
.breakpointRow[aria-checked="false"] .closeButton,
|
||||||
|
.breakpointRow[aria-checked="false"] .breakpointMutationType {
|
||||||
|
opacity: 1.0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointCode {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding-left: 24px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
border-bottom: 1px solid #D7D7D7;
|
||||||
|
font-family: monospace;
|
||||||
|
color: DarkGreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointCondition {
|
||||||
|
white-space: nowrap;
|
||||||
|
padding-left: 24px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
border-bottom: 1px solid #D7D7D7;
|
||||||
|
font-family: monospace;
|
||||||
|
color: Gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointBlock-breakpoints > .groupHeader {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointBlock-monitors > .breakpointCode {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointBlock-errorBreakpoints .breakpointCheckbox,
|
||||||
|
.breakpointBlock-monitors .breakpointCheckbox {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointHeader {
|
||||||
|
margin: 0 !important;
|
||||||
|
border-top: none !important;
|
||||||
|
}
|
||||||
BIN
vendor/firebug-lite/skin/xp/detach.png
vendored
Normal file
|
After Width: | Height: | Size: 655 B |
BIN
vendor/firebug-lite/skin/xp/detachHover.png
vendored
Normal file
|
After Width: | Height: | Size: 586 B |
BIN
vendor/firebug-lite/skin/xp/disable.gif
vendored
Normal file
|
After Width: | Height: | Size: 340 B |
BIN
vendor/firebug-lite/skin/xp/disable.png
vendored
Normal file
|
After Width: | Height: | Size: 543 B |
BIN
vendor/firebug-lite/skin/xp/disableHover.gif
vendored
Normal file
|
After Width: | Height: | Size: 344 B |
BIN
vendor/firebug-lite/skin/xp/disableHover.png
vendored
Normal file
|
After Width: | Height: | Size: 512 B |
BIN
vendor/firebug-lite/skin/xp/down.png
vendored
Normal file
|
After Width: | Height: | Size: 637 B |
BIN
vendor/firebug-lite/skin/xp/downActive.png
vendored
Normal file
|
After Width: | Height: | Size: 543 B |
BIN
vendor/firebug-lite/skin/xp/downHover.png
vendored
Normal file
|
After Width: | Height: | Size: 526 B |
BIN
vendor/firebug-lite/skin/xp/errorIcon-sm.png
vendored
Normal file
|
After Width: | Height: | Size: 447 B |
BIN
vendor/firebug-lite/skin/xp/errorIcon.gif
vendored
Normal file
|
After Width: | Height: | Size: 365 B |
BIN
vendor/firebug-lite/skin/xp/errorIcon.png
vendored
Normal file
|
After Width: | Height: | Size: 457 B |
817
vendor/firebug-lite/skin/xp/firebug-1.3a2.css
vendored
Normal file
@@ -0,0 +1,817 @@
|
|||||||
|
.fbBtnPressed {
|
||||||
|
background: #ECEBE3;
|
||||||
|
padding: 3px 6px 2px 7px !important;
|
||||||
|
margin: 1px 0 0 1px;
|
||||||
|
_margin: 1px -1px 0 1px;
|
||||||
|
border: 1px solid #ACA899 !important;
|
||||||
|
border-color: #ACA899 #ECEBE3 #ECEBE3 #ACA899 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fbToolbarButtons {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbStatusBarBox {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************
|
||||||
|
Error Popup
|
||||||
|
*************************************************************************************************/
|
||||||
|
#fbErrorPopup {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
height: 19px;
|
||||||
|
width: 75px;
|
||||||
|
background: url(sprite.png) #f1f2ee 0 0;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbErrorPopupContent {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 1px;
|
||||||
|
height: 18px;
|
||||||
|
width: 75px;
|
||||||
|
_width: 74px;
|
||||||
|
border-left: 1px solid #aca899;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbErrorIndicator {
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.fbBtnInspectActive {
|
||||||
|
background: #aaa;
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************
|
||||||
|
General
|
||||||
|
*************************************************************************************************/
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Lucida Grande, Tahoma, sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************
|
||||||
|
Mini Chrome
|
||||||
|
*************************************************************************************************/
|
||||||
|
#fbMiniChrome {
|
||||||
|
display: none;
|
||||||
|
right: 0;
|
||||||
|
height: 27px;
|
||||||
|
background: url(sprite.png) #f1f2ee 0 0;
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbMiniContent {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
left: -1px;
|
||||||
|
right: 0;
|
||||||
|
top: 1px;
|
||||||
|
height: 25px;
|
||||||
|
border-left: 1px solid #aca899;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbToolbarSearch {
|
||||||
|
float: right;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
margin: 0 5px 0 0;
|
||||||
|
background: #fff url(search.png) no-repeat 4px 2px;
|
||||||
|
padding-left: 20px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbToolbarErrors {
|
||||||
|
float: right;
|
||||||
|
margin: 1px 4px 0 0;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbLeftToolbarErrors {
|
||||||
|
float: left;
|
||||||
|
margin: 7px 0px 0 5px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fbErrors {
|
||||||
|
padding-left: 20px;
|
||||||
|
height: 14px;
|
||||||
|
background: url(errorIcon.png) no-repeat;
|
||||||
|
color: #f00;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbMiniErrors {
|
||||||
|
display: inline;
|
||||||
|
display: none;
|
||||||
|
float: right;
|
||||||
|
margin: 5px 2px 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbMiniIcon {
|
||||||
|
float: right;
|
||||||
|
margin: 3px 4px 0;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
float: right;
|
||||||
|
background: url(sprite.png) 0 -135px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************************************
|
||||||
|
Master Layout
|
||||||
|
*************************************************************************************************/
|
||||||
|
#fbChrome {
|
||||||
|
position: fixed;
|
||||||
|
overflow: hidden;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbTop {
|
||||||
|
height: 49px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbToolbar {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 5;
|
||||||
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
background: url(sprite.png) #f1f2ee 0 0;
|
||||||
|
height: 27px;
|
||||||
|
font-size: 11px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbPanelBarBox {
|
||||||
|
top: 27px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 8;
|
||||||
|
width: 100%;
|
||||||
|
background: url(sprite.png) #dbd9c9 0 -27px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbContent {
|
||||||
|
height: 100%;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbBottom {
|
||||||
|
height: 18px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************
|
||||||
|
Sub-Layout
|
||||||
|
*************************************************************************************************/
|
||||||
|
|
||||||
|
/* fbToolbar
|
||||||
|
*************************************************************************************************/
|
||||||
|
#fbToolbarIcon {
|
||||||
|
float: left;
|
||||||
|
padding: 4px 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbToolbarIcon a {
|
||||||
|
display: block;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
background: url(sprite.png) 0 -135px;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbToolbarButtons {
|
||||||
|
float: left;
|
||||||
|
padding: 4px 2px 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbToolbarButtons a {
|
||||||
|
text-decoration: none;
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
color: #000;
|
||||||
|
padding: 4px 8px 4px;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbToolbarButtons a:hover {
|
||||||
|
color: #333;
|
||||||
|
padding: 3px 7px 3px;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
border-bottom: 1px solid #bbb;
|
||||||
|
border-right: 1px solid #bbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbStatusBarBox {
|
||||||
|
position: relative;
|
||||||
|
top: 5px;
|
||||||
|
line-height: 19px;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fbToolbarSeparator{
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid;
|
||||||
|
border-color: transparent #fff transparent #777;
|
||||||
|
_border-color: #eee #fff #eee #777;
|
||||||
|
height: 7px;
|
||||||
|
margin: 10px 6px 0 0;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fbStatusBar span {
|
||||||
|
color: #808080;
|
||||||
|
padding: 0 4px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fbStatusBar span a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fbStatusBar span a:hover {
|
||||||
|
color: blue;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#fbWindowButtons {
|
||||||
|
position: absolute;
|
||||||
|
white-space: nowrap;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
height: 17px;
|
||||||
|
_width: 50px;
|
||||||
|
padding: 5px 0 5px 5px;
|
||||||
|
z-index: 6;
|
||||||
|
background: url(sprite.png) #f1f2ee 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fbPanelBarBox
|
||||||
|
*************************************************************************************************/
|
||||||
|
|
||||||
|
#fbPanelBar1 {
|
||||||
|
width: 255px; /* fixed width to avoid tabs breaking line */
|
||||||
|
z-index: 8;
|
||||||
|
left: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
background: url(sprite.png) #dbd9c9 0 -27px;
|
||||||
|
position: absolute;
|
||||||
|
left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbPanelBar2Box {
|
||||||
|
background: url(sprite.png) #dbd9c9 0 -27px;
|
||||||
|
position: absolute;
|
||||||
|
height: 22px;
|
||||||
|
width: 300px; /* fixed width to avoid tabs breaking line */
|
||||||
|
z-index: 9;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbPanelBar2 {
|
||||||
|
position: absolute;
|
||||||
|
width: 290px; /* fixed width to avoid tabs breaking line */
|
||||||
|
height: 22px;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* body
|
||||||
|
*************************************************************************************************/
|
||||||
|
.fbPanel {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbPanelBox1, #fbPanelBox2 {
|
||||||
|
max-height: inherit;
|
||||||
|
height: 100%;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbPanelBox2 {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbPanelBox2 {
|
||||||
|
width: 300px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbPanel2 {
|
||||||
|
padding-left: 6px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide {
|
||||||
|
overflow: hidden !important;
|
||||||
|
position: fixed !important;
|
||||||
|
display: none !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fbBottom
|
||||||
|
*************************************************************************************************/
|
||||||
|
|
||||||
|
#fbCommand {
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbCommandBox {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 18px;
|
||||||
|
bottom: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 9;
|
||||||
|
background: #fff;
|
||||||
|
border: 0;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbCommandIcon {
|
||||||
|
position: absolute;
|
||||||
|
color: #00f;
|
||||||
|
top: 2px;
|
||||||
|
left: 7px;
|
||||||
|
display: inline;
|
||||||
|
font: 11px Monaco, monospace;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbCommandLine {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 2px 0 2px 32px;
|
||||||
|
font: 11px Monaco, monospace;
|
||||||
|
z-index: 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.fbFitHeight {
|
||||||
|
overflow: auto;
|
||||||
|
_position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************************************
|
||||||
|
Layout Controls
|
||||||
|
*************************************************************************************************/
|
||||||
|
|
||||||
|
/* fbToolbar buttons
|
||||||
|
*************************************************************************************************/
|
||||||
|
#fbWindowButtons a {
|
||||||
|
font-size: 1px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
display: block;
|
||||||
|
float: right;
|
||||||
|
margin-right: 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbWindow_btClose {
|
||||||
|
background: url(sprite.png) 0 -119px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbWindow_btClose:hover {
|
||||||
|
background: url(sprite.png) -16px -119px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbWindow_btDetach {
|
||||||
|
background: url(sprite.png) -32px -119px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbWindow_btDetach:hover {
|
||||||
|
background: url(sprite.png) -48px -119px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fbPanelBarBox tabs
|
||||||
|
*************************************************************************************************/
|
||||||
|
.fbTab {
|
||||||
|
text-decoration: none;
|
||||||
|
display: none;
|
||||||
|
float: left;
|
||||||
|
width: auto;
|
||||||
|
float: left;
|
||||||
|
cursor: default;
|
||||||
|
font-family: Lucida Grande, Tahoma, sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
height: 22px;
|
||||||
|
color: #565656;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fbPanelBar span {
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fbPanelBar .fbTabL,.fbPanelBar .fbTabR {
|
||||||
|
height: 22px;
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fbPanelBar .fbTabText {
|
||||||
|
padding: 4px 1px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.fbTab:hover {
|
||||||
|
background: url(sprite.png) 0 -73px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.fbTab:hover .fbTabL {
|
||||||
|
background: url(sprite.png) -16px -96px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.fbTab:hover .fbTabR {
|
||||||
|
background: url(sprite.png) -24px -96px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fbSelectedTab {
|
||||||
|
background: url(sprite.png) #f1f2ee 0 -50px !important;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fbSelectedTab .fbTabL {
|
||||||
|
background: url(sprite.png) 0 -96px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fbSelectedTab .fbTabR {
|
||||||
|
background: url(sprite.png) -8px -96px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* splitters
|
||||||
|
*************************************************************************************************/
|
||||||
|
#fbHSplitter {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: n-resize !important;
|
||||||
|
background: url(pixel_transparent.gif);
|
||||||
|
z-index: 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fbHSplitter.fbOnMovingHSplitter {
|
||||||
|
height: 100%;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fbVSplitter {
|
||||||
|
background: #ece9d8;
|
||||||
|
color: #000;
|
||||||
|
border: 1px solid #716f64;
|
||||||
|
border-width: 0 1px;
|
||||||
|
border-left-color: #aca899;
|
||||||
|
width: 4px;
|
||||||
|
cursor: e-resize;
|
||||||
|
overflow: hidden;
|
||||||
|
right: 294px;
|
||||||
|
text-decoration: none;
|
||||||
|
z-index: 9;
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
top: 27px;
|
||||||
|
_width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
div.lineNo {
|
||||||
|
font: 11px Monaco, monospace;
|
||||||
|
float: left;
|
||||||
|
display: inline;
|
||||||
|
position: relative;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 5px 0 20px;
|
||||||
|
background: #eee;
|
||||||
|
color: #888;
|
||||||
|
border-right: 1px solid #ccc;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.nodeCode {
|
||||||
|
font: 11px Monaco, monospace;
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
/*
|
||||||
|
_width: 100%;
|
||||||
|
/**/
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
.nodeControl {
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-left: -14px;
|
||||||
|
float: left;
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: default;
|
||||||
|
background: url(tree_open.gif);
|
||||||
|
_float: none;
|
||||||
|
_display: inline;
|
||||||
|
_position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.nodeMaximized {
|
||||||
|
background: url(tree_close.gif);
|
||||||
|
}
|
||||||
|
|
||||||
|
div.objectBox-element {
|
||||||
|
padding: 1px 3px;
|
||||||
|
}
|
||||||
|
.objectBox-selector{
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectedElement{
|
||||||
|
background: highlight;
|
||||||
|
/* background: url(roundCorner.svg); Opera */
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
.selectedElement span{
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Webkit CSS Hack - bug in "highlight" named color */
|
||||||
|
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||||
|
.selectedElement{
|
||||||
|
background: #316AC5;
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
/************************************************************************************************/
|
||||||
|
.logRow * {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logRow {
|
||||||
|
position: relative;
|
||||||
|
border-bottom: 1px solid #D7D7D7;
|
||||||
|
padding: 2px 4px 1px 6px;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logRow-command {
|
||||||
|
font-family: Monaco, monospace;
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objectBox-string,
|
||||||
|
.objectBox-text,
|
||||||
|
.objectBox-number,
|
||||||
|
.objectBox-function,
|
||||||
|
.objectLink-element,
|
||||||
|
.objectLink-textNode,
|
||||||
|
.objectLink-function,
|
||||||
|
.objectBox-stackTrace,
|
||||||
|
.objectLink-profile {
|
||||||
|
font-family: Monaco, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objectBox-null {
|
||||||
|
padding: 0 2px;
|
||||||
|
border: 1px solid #666666;
|
||||||
|
background-color: #888888;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objectBox-string {
|
||||||
|
color: red;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objectBox-number {
|
||||||
|
color: #000088;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objectBox-function {
|
||||||
|
color: DarkGreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objectBox-object {
|
||||||
|
color: DarkGreen;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: Lucida Grande, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objectBox-array {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
.logRow-info,.logRow-error,.logRow-warning {
|
||||||
|
background: #fff no-repeat 2px 2px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logRow-info {
|
||||||
|
background-image: url(infoIcon.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logRow-warning {
|
||||||
|
background-color: cyan;
|
||||||
|
background-image: url(warningIcon.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logRow-error {
|
||||||
|
background-color: LightYellow;
|
||||||
|
background-image: url(errorIcon.png);
|
||||||
|
color: #f00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.errorMessage {
|
||||||
|
vertical-align: top;
|
||||||
|
color: #f00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objectBox-sourceLink {
|
||||||
|
position: absolute;
|
||||||
|
right: 4px;
|
||||||
|
top: 2px;
|
||||||
|
padding-left: 8px;
|
||||||
|
font-family: Lucida Grande, sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #0000FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
.logRow-group {
|
||||||
|
background: #EEEEEE;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logGroup {
|
||||||
|
background: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logGroupBox {
|
||||||
|
margin-left: 24px;
|
||||||
|
border-top: 1px solid #D7D7D7;
|
||||||
|
border-left: 1px solid #D7D7D7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
.selectorTag,.selectorId,.selectorClass {
|
||||||
|
font-family: Monaco, monospace;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectorTag {
|
||||||
|
color: #0000FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectorId {
|
||||||
|
color: DarkBlue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectorClass {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
.objectBox-element {
|
||||||
|
font-family: Monaco, monospace;
|
||||||
|
color: #000088;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeChildren {
|
||||||
|
padding-left: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeTag {
|
||||||
|
color: blue;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeValue {
|
||||||
|
color: #FF0000;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeText,.nodeComment {
|
||||||
|
margin: 0 2px;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeText {
|
||||||
|
color: #333333;
|
||||||
|
font-family: Monaco, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeComment {
|
||||||
|
color: DarkGreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
.nodeHidden, .nodeHidden * {
|
||||||
|
color: #888888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeHidden .nodeTag {
|
||||||
|
color: #5F82D9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeHidden .nodeValue {
|
||||||
|
color: #D86060;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectedElement .nodeHidden, .selectedElement .nodeHidden * {
|
||||||
|
color: SkyBlue !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
.log-object {
|
||||||
|
/*
|
||||||
|
_position: relative;
|
||||||
|
_height: 100%;
|
||||||
|
/**/
|
||||||
|
}
|
||||||
|
|
||||||
|
.property {
|
||||||
|
position: relative;
|
||||||
|
clear: both;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propertyNameCell {
|
||||||
|
vertical-align: top;
|
||||||
|
float: left;
|
||||||
|
width: 28%;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propertyValueCell {
|
||||||
|
float: right;
|
||||||
|
width: 68%;
|
||||||
|
background: #fff;
|
||||||
|
position: absolute;
|
||||||
|
padding-left: 5px;
|
||||||
|
display: table-cell;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1;
|
||||||
|
/*
|
||||||
|
_position: relative;
|
||||||
|
/**/
|
||||||
|
}
|
||||||
|
|
||||||
|
.propertyName {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FirebugPopup {
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FirebugPopup #fbWindowButtons {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FirebugPopup #fbHSplitter {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
20
vendor/firebug-lite/skin/xp/firebug.IE6.css
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/************************************************************************************************/
|
||||||
|
#fbToolbarSearch {
|
||||||
|
background-image: url(search.gif) !important;
|
||||||
|
}
|
||||||
|
/************************************************************************************************/
|
||||||
|
.fbErrors {
|
||||||
|
background-image: url(errorIcon.gif) !important;
|
||||||
|
}
|
||||||
|
/************************************************************************************************/
|
||||||
|
.logRow-info {
|
||||||
|
background-image: url(infoIcon.gif) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logRow-warning {
|
||||||
|
background-image: url(warningIcon.gif) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logRow-error {
|
||||||
|
background-image: url(errorIcon.gif) !important;
|
||||||
|
}
|
||||||
3147
vendor/firebug-lite/skin/xp/firebug.css
vendored
Normal file
215
vendor/firebug-lite/skin/xp/firebug.html
vendored
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||||
|
<title>Firebug Lite</title>
|
||||||
|
<!-- An empty script to avoid FOUC when loading the stylesheet -->
|
||||||
|
<script type="text/javascript"></script>
|
||||||
|
<style type="text/css" media="screen">@import "firebug.css";</style>
|
||||||
|
<style>html,body{margin:0;padding:0;overflow:hidden;}</style>
|
||||||
|
</head>
|
||||||
|
<body class="fbBody">
|
||||||
|
<table id="fbChrome" cellpadding="0" cellspacing="0" border="0">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<!-- Interface - Top Area -->
|
||||||
|
<td id="fbTop" colspan="2">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<div>
|
||||||
|
--><!-- <span id="fbToolbarErrors" class="fbErrors">2 errors</span> --><!--
|
||||||
|
<input type="text" id="fbToolbarSearch" />
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Window Buttons -->
|
||||||
|
<div id="fbWindowButtons">
|
||||||
|
<a id="fbWindow_btDeactivate" class="fbSmallButton fbHover" title="Deactivate Firebug for this web page"> </a>
|
||||||
|
<a id="fbWindow_btDetach" class="fbSmallButton fbHover" title="Open Firebug in popup window"> </a>
|
||||||
|
<a id="fbWindow_btClose" class="fbSmallButton fbHover" title="Minimize Firebug"> </a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Toolbar buttons and Status Bar -->
|
||||||
|
<div id="fbToolbar">
|
||||||
|
<div id="fbToolbarContent">
|
||||||
|
|
||||||
|
<!-- Firebug Button -->
|
||||||
|
<span id="fbToolbarIcon">
|
||||||
|
<a id="fbFirebugButton" class="fbIconButton" class="fbHover" target="_blank"> </a>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<span id="fbLeftToolbarErrors" class="fbErrors">2 errors</span>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Toolbar Buttons -->
|
||||||
|
<span id="fbToolbarButtons">
|
||||||
|
<!-- Fixed Toolbar Buttons -->
|
||||||
|
<span id="fbFixedButtons">
|
||||||
|
<a id="fbChrome_btInspect" class="fbButton fbHover" title="Click an element in the page to inspect">Inspect</a>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- Console Panel Toolbar Buttons -->
|
||||||
|
<span id="fbConsoleButtons" class="fbToolbarButtons">
|
||||||
|
<a id="fbConsole_btClear" class="fbButton fbHover" title="Clear the console">Clear</a>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- HTML Panel Toolbar Buttons -->
|
||||||
|
<!--
|
||||||
|
<span id="fbHTMLButtons" class="fbToolbarButtons">
|
||||||
|
<a id="fbHTML_btEdit" class="fbHover" title="Edit this HTML">Edit</a>
|
||||||
|
</span>
|
||||||
|
-->
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- Status Bar -->
|
||||||
|
<span id="fbStatusBarBox">
|
||||||
|
<span class="fbToolbarSeparator"></span>
|
||||||
|
<!-- HTML Panel Status Bar -->
|
||||||
|
<!--
|
||||||
|
<span id="fbHTMLStatusBar" class="fbStatusBar fbToolbarButtons">
|
||||||
|
</span>
|
||||||
|
-->
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- PanelBars -->
|
||||||
|
<div id="fbPanelBarBox">
|
||||||
|
|
||||||
|
<!-- Main PanelBar -->
|
||||||
|
<div id="fbPanelBar1" class="fbPanelBar">
|
||||||
|
<a id="fbConsoleTab" class="fbTab fbHover">
|
||||||
|
<span class="fbTabL"></span>
|
||||||
|
<span class="fbTabText">Console</span>
|
||||||
|
<span class="fbTabMenuTarget"></span>
|
||||||
|
<span class="fbTabR"></span>
|
||||||
|
</a>
|
||||||
|
<a id="fbHTMLTab" class="fbTab fbHover">
|
||||||
|
<span class="fbTabL"></span>
|
||||||
|
<span class="fbTabText">HTML</span>
|
||||||
|
<span class="fbTabR"></span>
|
||||||
|
</a>
|
||||||
|
<a class="fbTab fbHover">
|
||||||
|
<span class="fbTabL"></span>
|
||||||
|
<span class="fbTabText">CSS</span>
|
||||||
|
<span class="fbTabR"></span>
|
||||||
|
</a>
|
||||||
|
<a class="fbTab fbHover">
|
||||||
|
<span class="fbTabL"></span>
|
||||||
|
<span class="fbTabText">Script</span>
|
||||||
|
<span class="fbTabR"></span>
|
||||||
|
</a>
|
||||||
|
<a class="fbTab fbHover">
|
||||||
|
<span class="fbTabL"></span>
|
||||||
|
<span class="fbTabText">DOM</span>
|
||||||
|
<span class="fbTabR"></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Side PanelBars -->
|
||||||
|
<div id="fbPanelBar2Box" class="hide">
|
||||||
|
<div id="fbPanelBar2" class="fbPanelBar">
|
||||||
|
<!--
|
||||||
|
<a class="fbTab fbHover">
|
||||||
|
<span class="fbTabL"></span>
|
||||||
|
<span class="fbTabText">Style</span>
|
||||||
|
<span class="fbTabR"></span>
|
||||||
|
</a>
|
||||||
|
<a class="fbTab fbHover">
|
||||||
|
<span class="fbTabL"></span>
|
||||||
|
<span class="fbTabText">Layout</span>
|
||||||
|
<span class="fbTabR"></span>
|
||||||
|
</a>
|
||||||
|
<a class="fbTab fbHover">
|
||||||
|
<span class="fbTabL"></span>
|
||||||
|
<span class="fbTabText">DOM</span>
|
||||||
|
<span class="fbTabR"></span>
|
||||||
|
</a>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Horizontal Splitter -->
|
||||||
|
<div id="fbHSplitter"> </div>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- Interface - Main Area -->
|
||||||
|
<tr id="fbContent">
|
||||||
|
|
||||||
|
<!-- Panels -->
|
||||||
|
<td id="fbPanelBox1">
|
||||||
|
<div id="fbPanel1" class="fbFitHeight">
|
||||||
|
<div id="fbConsole" class="fbPanel"></div>
|
||||||
|
<div id="fbHTML" class="fbPanel"></div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<!-- Side Panel Box -->
|
||||||
|
<td id="fbPanelBox2" class="hide">
|
||||||
|
|
||||||
|
<!-- VerticalSplitter -->
|
||||||
|
<div id="fbVSplitter" class="fbVSplitter"> </div>
|
||||||
|
|
||||||
|
<!-- Side Panels -->
|
||||||
|
<div id="fbPanel2" class="fbFitHeight">
|
||||||
|
|
||||||
|
<!-- HTML Side Panels -->
|
||||||
|
<div id="fbHTML_Style" class="fbPanel"></div>
|
||||||
|
<div id="fbHTML_Layout" class="fbPanel"></div>
|
||||||
|
<div id="fbHTML_DOM" class="fbPanel"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Large Command Line -->
|
||||||
|
<textarea id="fbLargeCommandLine" class="fbFitHeight"></textarea>
|
||||||
|
|
||||||
|
<!-- Large Command Line Buttons -->
|
||||||
|
<div id="fbLargeCommandButtons">
|
||||||
|
<a id="fbCommand_btRun" class="fbButton fbHover">Run</a>
|
||||||
|
<a id="fbCommand_btClear" class="fbButton fbHover">Clear</a>
|
||||||
|
|
||||||
|
<a id="fbSmallCommandLineIcon" class="fbSmallButton fbHover"></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- Interface - Bottom Area -->
|
||||||
|
<tr id="fbBottom" class="hide">
|
||||||
|
|
||||||
|
<!-- Command Line -->
|
||||||
|
<td id="fbCommand" colspan="2">
|
||||||
|
<div id="fbCommandBox">
|
||||||
|
<div id="fbCommandIcon">>>></div>
|
||||||
|
<input id="fbCommandLine" name="fbCommandLine" type="text" />
|
||||||
|
<a id="fbLargeCommandLineIcon" class="fbSmallButton fbHover"></a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<span id="fbMiniChrome">
|
||||||
|
<span id="fbMiniContent">
|
||||||
|
<span id="fbMiniIcon" title="Open Firebug Lite"></span>
|
||||||
|
<span id="fbMiniErrors" class="fbErrors"><!-- 2 errors --></span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<!--
|
||||||
|
<div id="fbErrorPopup">
|
||||||
|
<div id="fbErrorPopupContent">
|
||||||
|
<div id="fbErrorIndicator" class="fbErrors">2 errors</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
vendor/firebug-lite/skin/xp/firebug.png
vendored
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
vendor/firebug-lite/skin/xp/group.gif
vendored
Normal file
|
After Width: | Height: | Size: 158 B |
272
vendor/firebug-lite/skin/xp/html.css
vendored
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
/* See license.txt for terms of usage */
|
||||||
|
|
||||||
|
.panelNode-html {
|
||||||
|
-moz-box-sizing: padding-box;
|
||||||
|
padding: 4px 0 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeBox {
|
||||||
|
position: relative;
|
||||||
|
font-family: Monaco, monospace;
|
||||||
|
padding-left: 13px;
|
||||||
|
-moz-user-select: -moz-none;
|
||||||
|
}
|
||||||
|
.nodeBox.search-selection {
|
||||||
|
-moz-user-select: text;
|
||||||
|
}
|
||||||
|
.twisty {
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeChildBox {
|
||||||
|
margin-left: 12px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeLabel,
|
||||||
|
.nodeCloseLabel {
|
||||||
|
margin: -2px 2px 0 2px;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
-moz-border-radius: 3px;
|
||||||
|
padding: 0 2px;
|
||||||
|
color: #000088;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeCloseLabel {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeTag {
|
||||||
|
cursor: pointer;
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeValue {
|
||||||
|
color: #FF0000;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeText,
|
||||||
|
.nodeComment {
|
||||||
|
margin: 0 2px;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeText {
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeWhiteSpace {
|
||||||
|
border: 1px solid LightGray;
|
||||||
|
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
|
||||||
|
margin-left: 1px;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.nodeWhiteSpace_Space {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeTextEntity {
|
||||||
|
border: 1px solid gray;
|
||||||
|
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeComment {
|
||||||
|
color: DarkGreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
.nodeBox.highlightOpen > .nodeLabel {
|
||||||
|
background-color: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeBox.highlightOpen > .nodeCloseLabel,
|
||||||
|
.nodeBox.highlightOpen > .nodeChildBox,
|
||||||
|
.nodeBox.open > .nodeCloseLabel,
|
||||||
|
.nodeBox.open > .nodeChildBox {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||||
|
.nodeBox.selected > .nodeLabel {
|
||||||
|
border-color: Highlight;
|
||||||
|
background-color: Highlight;
|
||||||
|
color: HighlightText !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||||
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||||
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||||
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||||
|
color: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
.nodeBox.highlighted > .nodeLabel {
|
||||||
|
border-color: Highlight !important;
|
||||||
|
background-color: cyan !important;
|
||||||
|
color: #000000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox,
|
||||||
|
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||||
|
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||||
|
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||||
|
color: #000000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox,
|
||||||
|
.nodeBox.nodeHidden .nodeCloseLabel,
|
||||||
|
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeText,
|
||||||
|
.nodeBox.nodeHidden .nodeText {
|
||||||
|
color: #888888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||||
|
.nodeBox.nodeHidden .nodeCloseLabel > .nodeCloseLabelBox > .nodeTag {
|
||||||
|
color: #5F82D9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue {
|
||||||
|
color: #D86060;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox,
|
||||||
|
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||||
|
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||||
|
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||||
|
color: SkyBlue !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
.nodeBox.mutated > .nodeLabel,
|
||||||
|
.nodeAttr.mutated,
|
||||||
|
.nodeValue.mutated,
|
||||||
|
.nodeText.mutated,
|
||||||
|
.nodeBox.mutated > .nodeText {
|
||||||
|
background-color: #EFFF79;
|
||||||
|
color: #FF0000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeBox.selected.mutated > .nodeLabel,
|
||||||
|
.nodeBox.selected.mutated > .nodeLabel > .nodeLabelBox,
|
||||||
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr.mutated > .nodeValue,
|
||||||
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue.mutated,
|
||||||
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText.mutated {
|
||||||
|
background-color: #EFFF79;
|
||||||
|
border-color: #EFFF79;
|
||||||
|
color: #FF0000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
|
||||||
|
.logRow-dirxml {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.soloElement > .nodeBox {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.useA11y .nodeLabel.focused {
|
||||||
|
outline: 2px solid #FF9933;
|
||||||
|
-moz-outline-radius: 3px;
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.useA11y .nodeLabelBox:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
|
||||||
|
.breakpointCode .twisty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointCode .nodeBox.containerNodeBox,
|
||||||
|
.breakpointCode .nodeLabel {
|
||||||
|
padding-left: 0px;
|
||||||
|
margin-left: 0px;
|
||||||
|
font-family: Monaco, monospace !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointCode .nodeTag,
|
||||||
|
.breakpointCode .nodeAttr,
|
||||||
|
.breakpointCode .nodeText,
|
||||||
|
.breakpointCode .nodeValue,
|
||||||
|
.breakpointCode .nodeLabel {
|
||||||
|
color: DarkGreen !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakpointMutationType {
|
||||||
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
right: 20px;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
/************************************************************************************************/
|
||||||
|
/************************************************************************************************/
|
||||||
|
/************************************************************************************************/
|
||||||
|
/************************************************************************************************/
|
||||||
|
/************************************************************************************************/
|
||||||
|
/************************************************************************************************/
|
||||||
|
/************************************************************************************************/
|
||||||
|
/************************************************************************************************/
|
||||||
|
/************************************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************************************/
|
||||||
|
/* Twisties */
|
||||||
|
|
||||||
|
.twisty,
|
||||||
|
.logRow-errorMessage > .hasTwisty > .errorTitle,
|
||||||
|
.logRow-log > .objectBox-array.hasTwisty,
|
||||||
|
.logRow-spy .spyHead .spyTitle,
|
||||||
|
.logGroup > .logRow,
|
||||||
|
.memberRow.hasChildren > .memberLabelCell > .memberLabel,
|
||||||
|
.hasHeaders .netHrefLabel,
|
||||||
|
.netPageRow > .netCol > .netPageTitle {
|
||||||
|
background-image: url(twistyClosed.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 2px 2px;
|
||||||
|
min-height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logRow-errorMessage > .hasTwisty.opened > .errorTitle,
|
||||||
|
.logRow-log > .objectBox-array.hasTwisty.opened,
|
||||||
|
.logRow-spy.opened .spyHead .spyTitle,
|
||||||
|
.logGroup.opened > .logRow,
|
||||||
|
.memberRow.hasChildren.opened > .memberLabelCell > .memberLabel,
|
||||||
|
.nodeBox.highlightOpen > .nodeLabel > .twisty,
|
||||||
|
.nodeBox.open > .nodeLabel > .twisty,
|
||||||
|
.netRow.opened > .netCol > .netHrefLabel,
|
||||||
|
.netPageRow.opened > .netCol > .netPageTitle {
|
||||||
|
background-image: url(twistyOpen.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.twisty {
|
||||||
|
background-position: 4px 4px;
|
||||||
|
}
|
||||||
BIN
vendor/firebug-lite/skin/xp/infoIcon.gif
vendored
Normal file
|
After Width: | Height: | Size: 359 B |
BIN
vendor/firebug-lite/skin/xp/infoIcon.png
vendored
Normal file
|
After Width: | Height: | Size: 524 B |
BIN
vendor/firebug-lite/skin/xp/loading_16.gif
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
vendor/firebug-lite/skin/xp/min.png
vendored
Normal file
|
After Width: | Height: | Size: 552 B |
BIN
vendor/firebug-lite/skin/xp/minHover.png
vendored
Normal file
|
After Width: | Height: | Size: 485 B |
BIN
vendor/firebug-lite/skin/xp/off.png
vendored
Normal file
|
After Width: | Height: | Size: 742 B |
BIN
vendor/firebug-lite/skin/xp/offHover.png
vendored
Normal file
|
After Width: | Height: | Size: 680 B |
BIN
vendor/firebug-lite/skin/xp/pixel_transparent.gif
vendored
Normal file
|
After Width: | Height: | Size: 43 B |
6
vendor/firebug-lite/skin/xp/roundCorner.svg
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect fill="white" x="0" y="0" width="100%" height="100%" />
|
||||||
|
<rect fill="highlight" x="0" y="0" width="100%" height="100%" rx="2px"/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 234 B |
BIN
vendor/firebug-lite/skin/xp/search.gif
vendored
Normal file
|
After Width: | Height: | Size: 550 B |
BIN
vendor/firebug-lite/skin/xp/search.png
vendored
Normal file
|
After Width: | Height: | Size: 685 B |
BIN
vendor/firebug-lite/skin/xp/shadow.gif
vendored
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
vendor/firebug-lite/skin/xp/shadow2.gif
vendored
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
vendor/firebug-lite/skin/xp/shadowAlpha.png
vendored
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
vendor/firebug-lite/skin/xp/sprite.png
vendored
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
vendor/firebug-lite/skin/xp/tabHoverLeft.png
vendored
Normal file
|
After Width: | Height: | Size: 438 B |
BIN
vendor/firebug-lite/skin/xp/tabHoverMid.png
vendored
Normal file
|
After Width: | Height: | Size: 261 B |
BIN
vendor/firebug-lite/skin/xp/tabHoverRight.png
vendored
Normal file
|
After Width: | Height: | Size: 436 B |
BIN
vendor/firebug-lite/skin/xp/tabLeft.png
vendored
Normal file
|
After Width: | Height: | Size: 449 B |
BIN
vendor/firebug-lite/skin/xp/tabMenuCheckbox.png
vendored
Normal file
|
After Width: | Height: | Size: 220 B |
BIN
vendor/firebug-lite/skin/xp/tabMenuPin.png
vendored
Normal file
|
After Width: | Height: | Size: 207 B |
BIN
vendor/firebug-lite/skin/xp/tabMenuRadio.png
vendored
Normal file
|
After Width: | Height: | Size: 192 B |
BIN
vendor/firebug-lite/skin/xp/tabMenuTarget.png
vendored
Normal file
|
After Width: | Height: | Size: 142 B |
BIN
vendor/firebug-lite/skin/xp/tabMenuTargetHover.png
vendored
Normal file
|
After Width: | Height: | Size: 148 B |
BIN
vendor/firebug-lite/skin/xp/tabMid.png
vendored
Normal file
|
After Width: | Height: | Size: 262 B |
BIN
vendor/firebug-lite/skin/xp/tabRight.png
vendored
Normal file
|
After Width: | Height: | Size: 448 B |
BIN
vendor/firebug-lite/skin/xp/textEditorBorders.gif
vendored
Normal file
|
After Width: | Height: | Size: 117 B |
BIN
vendor/firebug-lite/skin/xp/textEditorBorders.png
vendored
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
vendor/firebug-lite/skin/xp/textEditorCorners.gif
vendored
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
vendor/firebug-lite/skin/xp/textEditorCorners.png
vendored
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
vendor/firebug-lite/skin/xp/titlebarMid.png
vendored
Normal file
|
After Width: | Height: | Size: 273 B |
BIN
vendor/firebug-lite/skin/xp/toolbarMid.png
vendored
Normal file
|
After Width: | Height: | Size: 242 B |
BIN
vendor/firebug-lite/skin/xp/tree_close.gif
vendored
Normal file
|
After Width: | Height: | Size: 300 B |
BIN
vendor/firebug-lite/skin/xp/tree_open.gif
vendored
Normal file
|
After Width: | Height: | Size: 202 B |
BIN
vendor/firebug-lite/skin/xp/twistyClosed.png
vendored
Normal file
|
After Width: | Height: | Size: 334 B |
BIN
vendor/firebug-lite/skin/xp/twistyOpen.png
vendored
Normal file
|
After Width: | Height: | Size: 309 B |
BIN
vendor/firebug-lite/skin/xp/up.png
vendored
Normal file
|
After Width: | Height: | Size: 619 B |
BIN
vendor/firebug-lite/skin/xp/upActive.png
vendored
Normal file
|
After Width: | Height: | Size: 551 B |
BIN
vendor/firebug-lite/skin/xp/upHover.png
vendored
Normal file
|
After Width: | Height: | Size: 526 B |
BIN
vendor/firebug-lite/skin/xp/warningIcon.gif
vendored
Normal file
|
After Width: | Height: | Size: 357 B |
BIN
vendor/firebug-lite/skin/xp/warningIcon.png
vendored
Normal file
|
After Width: | Height: | Size: 516 B |
31176
vendor/firebug-lite/src/firebug-lite-debug.js
vendored
Normal file
20
vendor/qunit-clib/LICENSE.txt
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
65
vendor/qunit-clib/README.md
vendored
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# QUnit CLIB <sup>v1.0.0-pre</sup>
|
||||||
|
## command-line interface boilerplate
|
||||||
|
|
||||||
|
QUnit CLIB helps extend QUnit's CLI support to many common CLI environments<sup><a name="fnref1" href="#fn1">1</a></sup>.
|
||||||
|
|
||||||
|
## Screenshot
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
~~~ js
|
||||||
|
(function(window) {
|
||||||
|
|
||||||
|
// use a single load function
|
||||||
|
var load = typeof require == 'function' ? require : window.load;
|
||||||
|
|
||||||
|
// load QUnit and CLIB if needed
|
||||||
|
var QUnit =
|
||||||
|
window.QUnit || (
|
||||||
|
window.setTimeout || (window.addEventListener = window.setTimeout = / /),
|
||||||
|
window.QUnit = load('path/to/qunit.js') || window.QUnit,
|
||||||
|
load('path/to/qunit-clib.js'),
|
||||||
|
(window.addEventListener || 0).test && delete window.addEventListener,
|
||||||
|
window.QUnit
|
||||||
|
);
|
||||||
|
|
||||||
|
// explicitly call `QUnit.module()` instead of `module()`
|
||||||
|
// in case we are in a CLI environment
|
||||||
|
QUnit.module('A Test Module');
|
||||||
|
|
||||||
|
test('A Test', function() {
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
|
||||||
|
// must call `QUnit.start()` if using QUnit < 1.3.0 with Node.js or any
|
||||||
|
// version of QUnit with Narwhal, Rhino, or RingoJS
|
||||||
|
if (!window.document) {
|
||||||
|
QUnit.start();
|
||||||
|
}
|
||||||
|
}(typeof global == 'object' && global || this));
|
||||||
|
~~~
|
||||||
|
|
||||||
|
## Cloning this repo
|
||||||
|
|
||||||
|
To clone this repository just use:
|
||||||
|
|
||||||
|
~~~ bash
|
||||||
|
git clone https://github.com/jdalton/qunit-clib.git
|
||||||
|
cd qunit-clib
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Feel free to fork and send pull requests if you see improvements!
|
||||||
|
|
||||||
|
## Footnotes
|
||||||
|
|
||||||
|
1. QUnit CLIB has been tested in at least Node.js v0.4.8-0.6.1, Narwhal v0.3.2, RingoJS v0.7.0-0.8.0, and Rhino v1.7RC3.
|
||||||
|
<a name="fn1" title="Jump back to footnote 1 in the text." href="#fnref1">↩</a>
|
||||||
|
|
||||||
|
2. QUnit v1.3.0 does not work with Narwhal or Ringo < v0.8.0
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
* [John-David Dalton](http://allyoucanleet.com/)
|
||||||
|
[](https://twitter.com/jdalton "Follow @jdalton on Twitter")
|
||||||
311
vendor/qunit-clib/qunit-clib.js
vendored
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
/*!
|
||||||
|
* QUnit CLI Boilerplate v1.0.0-pre
|
||||||
|
* Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
||||||
|
* Based on a gist by Jörn Zaefferer <https://gist.github.com/722381>
|
||||||
|
* Available under MIT license <http://mths.be/mit>
|
||||||
|
*/
|
||||||
|
;(function(global) {
|
||||||
|
|
||||||
|
/** Add `console.log()` support for Narwhal, Rhino, and RingoJS */
|
||||||
|
global.console || (global.console = { 'log': global.print });
|
||||||
|
|
||||||
|
/** Reduce global.QUnit.QUnit -> global.QUnit */
|
||||||
|
global.QUnit && (QUnit = QUnit.QUnit || QUnit);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/** Used as a horizontal rule in console output */
|
||||||
|
var hr = '----------------------------------------';
|
||||||
|
|
||||||
|
/** Shortcut used to convert array-like objects to arrays */
|
||||||
|
var slice = [].slice;
|
||||||
|
|
||||||
|
/** Used to resolve a value's internal [[Class]] */
|
||||||
|
var toString = {}.toString;
|
||||||
|
|
||||||
|
/** Used by timer methods */
|
||||||
|
var timer,
|
||||||
|
counter = 0,
|
||||||
|
ids = {};
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An iteration utility for arrays.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} array The array to iterate over.
|
||||||
|
* @param {Function} callback The function called per iteration.
|
||||||
|
*/
|
||||||
|
function each(array, callback) {
|
||||||
|
var index = -1,
|
||||||
|
length = array.length;
|
||||||
|
|
||||||
|
while (++index < length) {
|
||||||
|
callback(array[index], index, array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the specified `value` is a function.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Mixed} value The value to check.
|
||||||
|
* @returns {Boolean} Returns `true` if `value` is a function, else `false`.
|
||||||
|
*/
|
||||||
|
function isFunction(value) {
|
||||||
|
return toString.call(value) == '[object Function]';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timeout fallbacks based on the work of Andrea Giammarchi and Weston C.
|
||||||
|
* https://github.com/WebReflection/wru/blob/master/src/rhinoTimers.js
|
||||||
|
* http://stackoverflow.com/questions/2261705/how-to-run-a-javascript-function-asynchronously-without-using-settimeout
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the delay set by `setInterval` or `setTimeout`.
|
||||||
|
*
|
||||||
|
* @memberOf global
|
||||||
|
* @param {Number} id The ID of the timeout to be cleared.
|
||||||
|
*/
|
||||||
|
function clearTimer(id) {
|
||||||
|
if (ids[id]) {
|
||||||
|
ids[id].cancel();
|
||||||
|
timer.purge();
|
||||||
|
delete ids[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules timer-based callbacks.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Function} fn The function to call.
|
||||||
|
* @oaram {Number} delay The number of milliseconds to delay the `fn` call.
|
||||||
|
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
|
||||||
|
* @param {Boolean} repeated A flag to specify whether `fn` is called repeatedly.
|
||||||
|
* @returns {Number} The the ID of the timeout.
|
||||||
|
*/
|
||||||
|
function schedule(fn, delay, args, repeated) {
|
||||||
|
var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, {
|
||||||
|
'run': function() {
|
||||||
|
fn.apply(global, args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// support non-functions
|
||||||
|
if (!isFunction(fn)) {
|
||||||
|
fn = (function(code) {
|
||||||
|
code = String(code);
|
||||||
|
return function() { eval(code); };
|
||||||
|
}(fn));
|
||||||
|
}
|
||||||
|
// used by setInterval
|
||||||
|
if (repeated) {
|
||||||
|
timer.schedule(task, delay, delay);
|
||||||
|
}
|
||||||
|
// used by setTimeout
|
||||||
|
else {
|
||||||
|
timer.schedule(task, delay);
|
||||||
|
}
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a code snippet or function repeatedly, with a delay between each call.
|
||||||
|
*
|
||||||
|
* @memberOf global
|
||||||
|
* @param {Function|String} fn The function to call or string to evaluate.
|
||||||
|
* @oaram {Number} delay The number of milliseconds to delay each `fn` call.
|
||||||
|
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
|
||||||
|
* @returns {Number} The the ID of the timeout.
|
||||||
|
*/
|
||||||
|
function setInterval(fn, delay) {
|
||||||
|
return schedule(fn, delay, slice.call(arguments, 2), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a code snippet or a function after specified delay.
|
||||||
|
*
|
||||||
|
* @memberOf global
|
||||||
|
* @param {Function|String} fn The function to call or string to evaluate.
|
||||||
|
* @oaram {Number} delay The number of milliseconds to delay the `fn` call.
|
||||||
|
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
|
||||||
|
* @returns {Number} The the ID of the timeout.
|
||||||
|
*/
|
||||||
|
function setTimeout(fn, delay) {
|
||||||
|
return schedule(fn, delay, slice.call(arguments, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A logging callback triggered when all testing is completed.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit
|
||||||
|
* @param {Object} details An object with properties `failed`, `passed`,
|
||||||
|
* `runtime`, and `total`.
|
||||||
|
*/
|
||||||
|
function done(details) {
|
||||||
|
// stop `asyncTest()` from erroneously calling `done()` twice in environments w/o timeouts
|
||||||
|
if (!QUnit.doneCalled) {
|
||||||
|
console.log(hr);
|
||||||
|
console.log(' PASS: ' + details.passed + ' FAIL: ' + details.failed + ' TOTAL: ' + details.total);
|
||||||
|
console.log(' Finished in ' + details.runtime + ' milliseconds.');
|
||||||
|
console.log(hr);
|
||||||
|
|
||||||
|
// exit out of Rhino
|
||||||
|
try {
|
||||||
|
quit();
|
||||||
|
} catch(e) { }
|
||||||
|
|
||||||
|
// exit out of Node.js
|
||||||
|
try {
|
||||||
|
process.exit();
|
||||||
|
} catch(e) { }
|
||||||
|
|
||||||
|
// prevent multiple calls to `done()`
|
||||||
|
QUnit.doneCalled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A logging callback triggered after every assertion.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit
|
||||||
|
* @param {Object} details An object with properties `actual`, `expected`,
|
||||||
|
* `message`, and `result`.
|
||||||
|
*/
|
||||||
|
function log(details) {
|
||||||
|
var expected = details.expected,
|
||||||
|
result = details.result,
|
||||||
|
type = typeof expected != 'undefined' ? 'EQ' : 'OK',
|
||||||
|
assertion = [
|
||||||
|
result ? 'PASS' : 'FAIL',
|
||||||
|
type,
|
||||||
|
details.message || 'ok'
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!result && type == 'EQ') {
|
||||||
|
assertion.push('Expected: ' + expected + ', Actual: ' + details.actual);
|
||||||
|
}
|
||||||
|
QUnit.config.testStats.assertions.push(assertion.join(' | '));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A logging callback triggered at the start of every test module.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit
|
||||||
|
* @param {Object} details An object with property `name`.
|
||||||
|
*/
|
||||||
|
function moduleStart(details) {
|
||||||
|
console.log(hr);
|
||||||
|
console.log(details.name);
|
||||||
|
console.log(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an object into a string representation.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit
|
||||||
|
* @type Function
|
||||||
|
* @param {Object} object The object to stringify.
|
||||||
|
* @returns {String} The result string.
|
||||||
|
*/
|
||||||
|
var parseObject = (function() {
|
||||||
|
var _parseObject = QUnit.jsDump.parsers.object;
|
||||||
|
return function(object) {
|
||||||
|
// fork to support Rhino's error objects
|
||||||
|
if (typeof object.rhinoException == 'object') {
|
||||||
|
return object.name +
|
||||||
|
' { message: "' + object.message +
|
||||||
|
'", fileName: "' + object.fileName +
|
||||||
|
'", lineNumber: ' + object.lineNumber + ' }';
|
||||||
|
}
|
||||||
|
return _parseObject(object);
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A logging callback triggered after a test is completed.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit
|
||||||
|
* @param {Object} details An object with properties `failed`, `name`,
|
||||||
|
* `passed`, and `total`.
|
||||||
|
*/
|
||||||
|
function testDone(details) {
|
||||||
|
var assertions = QUnit.config.testStats.assertions,
|
||||||
|
name = details.name;
|
||||||
|
|
||||||
|
if (details.failed > 0) {
|
||||||
|
console.log(' FAIL - '+ name);
|
||||||
|
each(assertions, function(value) {
|
||||||
|
console.log(' ' + value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(' PASS - ' + name);
|
||||||
|
}
|
||||||
|
assertions.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object used to hold information about the current running test.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit.config
|
||||||
|
* @type Object
|
||||||
|
*/
|
||||||
|
QUnit.config.testStats = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of test summaries (pipe separated).
|
||||||
|
*
|
||||||
|
* @memberOf QUnit.config.testStats
|
||||||
|
* @type Array
|
||||||
|
*/
|
||||||
|
'assertions': []
|
||||||
|
};
|
||||||
|
|
||||||
|
// add shortcuts to the global
|
||||||
|
// exclude `module` because some environments have it as a built-in object
|
||||||
|
each(['asyncTest', 'deepEqual', 'equal', 'equals', 'expect', 'notDeepEqual',
|
||||||
|
'notEqual', 'notStrictEqual', 'ok', 'raises', 'same', 'start', 'stop',
|
||||||
|
'strictEqual', 'test'], function(name) {
|
||||||
|
global[name] = QUnit[name];
|
||||||
|
});
|
||||||
|
|
||||||
|
// expose timer methods to global
|
||||||
|
try {
|
||||||
|
timer = new java.util.Timer;
|
||||||
|
if (!isFunction(global.clearInterval)) {
|
||||||
|
global.clearInterval = clearTimer;
|
||||||
|
}
|
||||||
|
if (!isFunction(global.clearTimeout)) {
|
||||||
|
global.clearTimeout = clearTimer;
|
||||||
|
}
|
||||||
|
if (!isFunction(global.setInterval)) {
|
||||||
|
global.setInterval = setInterval;
|
||||||
|
}
|
||||||
|
if (!isFunction(global.setTimeout)) {
|
||||||
|
global.setTimeout = setTimeout;
|
||||||
|
}
|
||||||
|
} catch(e) { }
|
||||||
|
|
||||||
|
// add callbacks
|
||||||
|
QUnit.done(done);
|
||||||
|
QUnit.log(log);
|
||||||
|
QUnit.moduleStart(moduleStart);
|
||||||
|
QUnit.testDone(testDone);
|
||||||
|
|
||||||
|
// wrap `parseObject`
|
||||||
|
QUnit.jsDump.parsers.object = parseObject;
|
||||||
|
|
||||||
|
// must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with Node.js
|
||||||
|
// or any version of QUnit with Narwhal, Rhino, or RingoJS
|
||||||
|
QUnit.init();
|
||||||
|
|
||||||
|
}(typeof global == 'object' && global || this));
|
||||||
48
vendor/qunit/README.md
vendored
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
[QUnit](http://docs.jquery.com/QUnit) - A JavaScript Unit Testing framework.
|
||||||
|
================================
|
||||||
|
|
||||||
|
QUnit is a powerful, easy-to-use, JavaScript test suite. It's used by the jQuery
|
||||||
|
project to test its code and plugins but is capable of testing any generic
|
||||||
|
JavaScript code (and even capable of testing JavaScript code on the server-side).
|
||||||
|
|
||||||
|
QUnit is especially useful for regression testing: Whenever a bug is reported,
|
||||||
|
write a test that asserts the existence of that particular bug. Then fix it and
|
||||||
|
commit both. Every time you work on the code again, run the tests. If the bug
|
||||||
|
comes up again - a regression - you'll spot it immediately and know how to fix
|
||||||
|
it, because you know what code you just changed.
|
||||||
|
|
||||||
|
Having good unit test coverage makes safe refactoring easy and cheap. You can
|
||||||
|
run the tests after each small refactoring step and always know what change
|
||||||
|
broke something.
|
||||||
|
|
||||||
|
QUnit is similar to other unit testing frameworks like JUnit, but makes use of
|
||||||
|
the features JavaScript provides and helps with testing code in the browser, e.g.
|
||||||
|
with its stop/start facilities for testing asynchronous code.
|
||||||
|
|
||||||
|
If you are interested in helping developing QUnit, you are in the right place.
|
||||||
|
For related discussions, visit the
|
||||||
|
[QUnit and Testing forum](http://forum.jquery.com/qunit-and-testing).
|
||||||
|
|
||||||
|
Planning for a qunitjs.com site and other testing tools related work now happens
|
||||||
|
on the [jQuery Testing Team planning wiki](http://jquerytesting.pbworks.com/w/page/41556026/FrontPage).
|
||||||
|
|
||||||
|
Development
|
||||||
|
-----------
|
||||||
|
|
||||||
|
To submit patches, fork the repository, create a branch for the change. Then implement
|
||||||
|
the change, run `grunt` to lint and test it, then commit, push and create a pull request.
|
||||||
|
|
||||||
|
Include some background for the change in the commit message and `Fixes #nnn`, referring
|
||||||
|
to the issue number you're addressing.
|
||||||
|
|
||||||
|
To run `grunt`, you need `node` and `npm`, then `npm install grunt -g`.
|
||||||
|
|
||||||
|
Releases
|
||||||
|
--------
|
||||||
|
|
||||||
|
Install git-extras and run `git changelog` to update History.md.
|
||||||
|
Update qunit/qunit.js|css to the release version, commit and tag, update them
|
||||||
|
again to the next version, commit and push commits and tags.
|
||||||
|
|
||||||
|
Put the 'v' in front of the tag (unlike the 1.1.0 release). Clean up the changelog,
|
||||||
|
removing merge commits or whitespace cleanups.
|
||||||
236
vendor/qunit/qunit/qunit.css
vendored
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
/**
|
||||||
|
* QUnit v1.8.0 - A JavaScript Unit Testing Framework
|
||||||
|
*
|
||||||
|
* http://docs.jquery.com/QUnit
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 John Resig, Jörn Zaefferer
|
||||||
|
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||||
|
* or GPL (GPL-LICENSE.txt) licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Font Family and Sizes */
|
||||||
|
|
||||||
|
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
|
||||||
|
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
|
||||||
|
#qunit-tests { font-size: smaller; }
|
||||||
|
|
||||||
|
|
||||||
|
/** Resets */
|
||||||
|
|
||||||
|
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Header */
|
||||||
|
|
||||||
|
#qunit-header {
|
||||||
|
padding: 0.5em 0 0.5em 1em;
|
||||||
|
|
||||||
|
color: #8699a4;
|
||||||
|
background-color: #0d3349;
|
||||||
|
|
||||||
|
font-size: 1.5em;
|
||||||
|
line-height: 1em;
|
||||||
|
font-weight: normal;
|
||||||
|
|
||||||
|
border-radius: 15px 15px 0 0;
|
||||||
|
-moz-border-radius: 15px 15px 0 0;
|
||||||
|
-webkit-border-top-right-radius: 15px;
|
||||||
|
-webkit-border-top-left-radius: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-header a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #c2ccd1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-header a:hover,
|
||||||
|
#qunit-header a:focus {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-header label {
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-banner {
|
||||||
|
height: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-testrunner-toolbar {
|
||||||
|
padding: 0.5em 0 0.5em 2em;
|
||||||
|
color: #5E740B;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-userAgent {
|
||||||
|
padding: 0.5em 0 0.5em 2.5em;
|
||||||
|
background-color: #2b81af;
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Tests: Pass/Fail */
|
||||||
|
|
||||||
|
#qunit-tests {
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests li {
|
||||||
|
padding: 0.4em 0.5em 0.4em 2.5em;
|
||||||
|
border-bottom: 1px solid #fff;
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests li strong {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests li a {
|
||||||
|
padding: 0.5em;
|
||||||
|
color: #c2ccd1;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
#qunit-tests li a:hover,
|
||||||
|
#qunit-tests li a:focus {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests ol {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
padding: 0.5em;
|
||||||
|
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
border-radius: 15px;
|
||||||
|
-moz-border-radius: 15px;
|
||||||
|
-webkit-border-radius: 15px;
|
||||||
|
|
||||||
|
box-shadow: inset 0px 2px 13px #999;
|
||||||
|
-moz-box-shadow: inset 0px 2px 13px #999;
|
||||||
|
-webkit-box-shadow: inset 0px 2px 13px #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: .2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests th {
|
||||||
|
text-align: right;
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 0 .5em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests pre {
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests del {
|
||||||
|
background-color: #e0f2be;
|
||||||
|
color: #374e0c;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests ins {
|
||||||
|
background-color: #ffcaca;
|
||||||
|
color: #500;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Test Counts */
|
||||||
|
|
||||||
|
#qunit-tests b.counts { color: black; }
|
||||||
|
#qunit-tests b.passed { color: #5E740B; }
|
||||||
|
#qunit-tests b.failed { color: #710909; }
|
||||||
|
|
||||||
|
#qunit-tests li li {
|
||||||
|
margin: 0.5em;
|
||||||
|
padding: 0.4em 0.5em 0.4em 0.5em;
|
||||||
|
background-color: #fff;
|
||||||
|
border-bottom: none;
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Passing Styles */
|
||||||
|
|
||||||
|
#qunit-tests li li.pass {
|
||||||
|
color: #5E740B;
|
||||||
|
background-color: #fff;
|
||||||
|
border-left: 26px solid #C6E746;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
||||||
|
#qunit-tests .pass .test-name { color: #366097; }
|
||||||
|
|
||||||
|
#qunit-tests .pass .test-actual,
|
||||||
|
#qunit-tests .pass .test-expected { color: #999999; }
|
||||||
|
|
||||||
|
#qunit-banner.qunit-pass { background-color: #C6E746; }
|
||||||
|
|
||||||
|
/*** Failing Styles */
|
||||||
|
|
||||||
|
#qunit-tests li li.fail {
|
||||||
|
color: #710909;
|
||||||
|
background-color: #fff;
|
||||||
|
border-left: 26px solid #EE5757;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests > li:last-child {
|
||||||
|
border-radius: 0 0 15px 15px;
|
||||||
|
-moz-border-radius: 0 0 15px 15px;
|
||||||
|
-webkit-border-bottom-right-radius: 15px;
|
||||||
|
-webkit-border-bottom-left-radius: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
|
||||||
|
#qunit-tests .fail .test-name,
|
||||||
|
#qunit-tests .fail .module-name { color: #000000; }
|
||||||
|
|
||||||
|
#qunit-tests .fail .test-actual { color: #EE5757; }
|
||||||
|
#qunit-tests .fail .test-expected { color: green; }
|
||||||
|
|
||||||
|
#qunit-banner.qunit-fail { background-color: #EE5757; }
|
||||||
|
|
||||||
|
|
||||||
|
/** Result */
|
||||||
|
|
||||||
|
#qunit-testresult {
|
||||||
|
padding: 0.5em 0.5em 0.5em 2.5em;
|
||||||
|
|
||||||
|
color: #2b81af;
|
||||||
|
background-color: #D2E0E6;
|
||||||
|
|
||||||
|
border-bottom: 1px solid white;
|
||||||
|
}
|
||||||
|
#qunit-testresult .module-name {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fixture */
|
||||||
|
|
||||||
|
#qunit-fixture {
|
||||||
|
position: absolute;
|
||||||
|
top: -10000px;
|
||||||
|
left: -10000px;
|
||||||
|
width: 1000px;
|
||||||
|
height: 1000px;
|
||||||
|
}
|
||||||
1863
vendor/qunit/qunit/qunit.js
vendored
Normal file
58
vendor/requirejs/LICENSE
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
RequireJS is released under two licenses: new BSD, and MIT. You may pick the
|
||||||
|
license that best suits your development needs. The text of both licenses are
|
||||||
|
provided below.
|
||||||
|
|
||||||
|
|
||||||
|
The "New" BSD License:
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Copyright (c) 2010-2011, The Dojo Foundation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the Dojo Foundation nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Copyright (c) 2010-2011, The Dojo Foundation
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
51
vendor/requirejs/README.md
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# RequireJS
|
||||||
|
|
||||||
|
RequireJS loads plain JavaScript files as well as more defined modules. It is
|
||||||
|
optimized for in-browser use, including in
|
||||||
|
[a Web Worker](http://requirejs.org/docs/api.html#webworker), but it can be used
|
||||||
|
in other JavaScript environments, like Rhino and
|
||||||
|
[Node](http://requirejs.org/docs/node.html). It implements the
|
||||||
|
[Asynchronous Module](https://github.com/amdjs/amdjs-api/wiki/AMD)
|
||||||
|
API.
|
||||||
|
|
||||||
|
RequireJS uses plain script tags to load modules/files, so it should allow for
|
||||||
|
easy debugging. It can be used
|
||||||
|
[simply to load existing JavaScript files](http://requirejs.org/docs/api.html#jsfiles),
|
||||||
|
so you can add it to your existing project without having to re-write your
|
||||||
|
JavaScript files.
|
||||||
|
|
||||||
|
RequireJS includes [an optimization tool](http://requirejs.org/docs/optimization.html)
|
||||||
|
you can run as part of your packaging steps for deploying your code. The
|
||||||
|
optimization tool can combine and minify your JavaScript files to allow for
|
||||||
|
better performance.
|
||||||
|
|
||||||
|
If the JavaScript file defines a JavaScript module via
|
||||||
|
[define()](http://requirejs.org/docs/api.html#define), then there are other benefits
|
||||||
|
RequireJS can offer: [improvements over traditional CommonJS modules](http://requirejs.org/docs/commonjs.html)
|
||||||
|
and [loading multiple versions](http://requirejs.org/docs/api.html#multiversion)
|
||||||
|
of a module in a page. RequireJS also has a plugin system that supports features like
|
||||||
|
[i18n string bundles](http://requirejs.org/docs/api.html#i18n), and
|
||||||
|
[text file dependencies](http://requirejs.org/docs/api.html#text).
|
||||||
|
|
||||||
|
RequireJS does not have any dependencies on a JavaScript framework.
|
||||||
|
It is dual-licensed -- new BSD or MIT.
|
||||||
|
|
||||||
|
The standard require.js file is around 5.5KB when minified via Closure Compiler
|
||||||
|
and gzipped.
|
||||||
|
|
||||||
|
RequireJS works in IE 6+, Firefox 2+, Safari 3.2+, Chrome 3+, and Opera 10+.
|
||||||
|
|
||||||
|
[Latest Release](http://requirejs.org/docs/download.html)
|
||||||
|
|
||||||
|
## Directories
|
||||||
|
|
||||||
|
* **dist**: Scripts and assets to generate the requirejs.org docs, and for
|
||||||
|
generating a require.js release.
|
||||||
|
* **docs**: The raw HTML files for the requirejs.org docs. Only includes the
|
||||||
|
body of each page. Files in **dist** are used to generate a complete HTML page.
|
||||||
|
* **tests**: Tests for require.js.
|
||||||
|
* **testBaseUrl.js**: A file used in the tests inside **tests**. Purposely
|
||||||
|
placed outside the tests directory for testing paths that go outside a baseUrl.
|
||||||
|
* **updatesubs.sh**: Updates projects that depend on require.js Assumes the
|
||||||
|
projects are siblings to this directory and have specific names. Useful to
|
||||||
|
copy require.js to dependent projects easily while in development.
|
||||||