Lots of updates
22
app/bower_components/lodash/vendor/backbone/LICENSE
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 2010-2016 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.
|
1920
app/bower_components/lodash/vendor/backbone/backbone.js
vendored
Normal file
1998
app/bower_components/lodash/vendor/backbone/test/collection.js
vendored
Normal file
706
app/bower_components/lodash/vendor/backbone/test/events.js
vendored
Normal file
|
@ -0,0 +1,706 @@
|
|||
(function() {
|
||||
|
||||
QUnit.module('Backbone.Events');
|
||||
|
||||
QUnit.test('on and trigger', function(assert) {
|
||||
assert.expect(2);
|
||||
var obj = {counter: 0};
|
||||
_.extend(obj, Backbone.Events);
|
||||
obj.on('event', function() { obj.counter += 1; });
|
||||
obj.trigger('event');
|
||||
assert.equal(obj.counter, 1, 'counter should be incremented.');
|
||||
obj.trigger('event');
|
||||
obj.trigger('event');
|
||||
obj.trigger('event');
|
||||
obj.trigger('event');
|
||||
assert.equal(obj.counter, 5, 'counter should be incremented five times.');
|
||||
});
|
||||
|
||||
QUnit.test('binding and triggering multiple events', function(assert) {
|
||||
assert.expect(4);
|
||||
var obj = {counter: 0};
|
||||
_.extend(obj, Backbone.Events);
|
||||
|
||||
obj.on('a b c', function() { obj.counter += 1; });
|
||||
|
||||
obj.trigger('a');
|
||||
assert.equal(obj.counter, 1);
|
||||
|
||||
obj.trigger('a b');
|
||||
assert.equal(obj.counter, 3);
|
||||
|
||||
obj.trigger('c');
|
||||
assert.equal(obj.counter, 4);
|
||||
|
||||
obj.off('a c');
|
||||
obj.trigger('a b c');
|
||||
assert.equal(obj.counter, 5);
|
||||
});
|
||||
|
||||
QUnit.test('binding and triggering with event maps', function(assert) {
|
||||
var obj = {counter: 0};
|
||||
_.extend(obj, Backbone.Events);
|
||||
|
||||
var increment = function() {
|
||||
this.counter += 1;
|
||||
};
|
||||
|
||||
obj.on({
|
||||
a: increment,
|
||||
b: increment,
|
||||
c: increment
|
||||
}, obj);
|
||||
|
||||
obj.trigger('a');
|
||||
assert.equal(obj.counter, 1);
|
||||
|
||||
obj.trigger('a b');
|
||||
assert.equal(obj.counter, 3);
|
||||
|
||||
obj.trigger('c');
|
||||
assert.equal(obj.counter, 4);
|
||||
|
||||
obj.off({
|
||||
a: increment,
|
||||
c: increment
|
||||
}, obj);
|
||||
obj.trigger('a b c');
|
||||
assert.equal(obj.counter, 5);
|
||||
});
|
||||
|
||||
QUnit.test('binding and triggering multiple event names with event maps', function(assert) {
|
||||
var obj = {counter: 0};
|
||||
_.extend(obj, Backbone.Events);
|
||||
|
||||
var increment = function() {
|
||||
this.counter += 1;
|
||||
};
|
||||
|
||||
obj.on({
|
||||
'a b c': increment
|
||||
});
|
||||
|
||||
obj.trigger('a');
|
||||
assert.equal(obj.counter, 1);
|
||||
|
||||
obj.trigger('a b');
|
||||
assert.equal(obj.counter, 3);
|
||||
|
||||
obj.trigger('c');
|
||||
assert.equal(obj.counter, 4);
|
||||
|
||||
obj.off({
|
||||
'a c': increment
|
||||
});
|
||||
obj.trigger('a b c');
|
||||
assert.equal(obj.counter, 5);
|
||||
});
|
||||
|
||||
QUnit.test('binding and trigger with event maps context', function(assert) {
|
||||
assert.expect(2);
|
||||
var obj = {counter: 0};
|
||||
var context = {};
|
||||
_.extend(obj, Backbone.Events);
|
||||
|
||||
obj.on({
|
||||
a: function() {
|
||||
assert.strictEqual(this, context, 'defaults `context` to `callback` param');
|
||||
}
|
||||
}, context).trigger('a');
|
||||
|
||||
obj.off().on({
|
||||
a: function() {
|
||||
assert.strictEqual(this, context, 'will not override explicit `context` param');
|
||||
}
|
||||
}, this, context).trigger('a');
|
||||
});
|
||||
|
||||
QUnit.test('listenTo and stopListening', function(assert) {
|
||||
assert.expect(1);
|
||||
var a = _.extend({}, Backbone.Events);
|
||||
var b = _.extend({}, Backbone.Events);
|
||||
a.listenTo(b, 'all', function(){ assert.ok(true); });
|
||||
b.trigger('anything');
|
||||
a.listenTo(b, 'all', function(){ assert.ok(false); });
|
||||
a.stopListening();
|
||||
b.trigger('anything');
|
||||
});
|
||||
|
||||
QUnit.test('listenTo and stopListening with event maps', function(assert) {
|
||||
assert.expect(4);
|
||||
var a = _.extend({}, Backbone.Events);
|
||||
var b = _.extend({}, Backbone.Events);
|
||||
var cb = function(){ assert.ok(true); };
|
||||
a.listenTo(b, {event: cb});
|
||||
b.trigger('event');
|
||||
a.listenTo(b, {event2: cb});
|
||||
b.on('event2', cb);
|
||||
a.stopListening(b, {event2: cb});
|
||||
b.trigger('event event2');
|
||||
a.stopListening();
|
||||
b.trigger('event event2');
|
||||
});
|
||||
|
||||
QUnit.test('stopListening with omitted args', function(assert) {
|
||||
assert.expect(2);
|
||||
var a = _.extend({}, Backbone.Events);
|
||||
var b = _.extend({}, Backbone.Events);
|
||||
var cb = function() { assert.ok(true); };
|
||||
a.listenTo(b, 'event', cb);
|
||||
b.on('event', cb);
|
||||
a.listenTo(b, 'event2', cb);
|
||||
a.stopListening(null, {event: cb});
|
||||
b.trigger('event event2');
|
||||
b.off();
|
||||
a.listenTo(b, 'event event2', cb);
|
||||
a.stopListening(null, 'event');
|
||||
a.stopListening();
|
||||
b.trigger('event2');
|
||||
});
|
||||
|
||||
QUnit.test('listenToOnce', function(assert) {
|
||||
assert.expect(2);
|
||||
// Same as the previous test, but we use once rather than having to explicitly unbind
|
||||
var obj = {counterA: 0, counterB: 0};
|
||||
_.extend(obj, Backbone.Events);
|
||||
var incrA = function(){ obj.counterA += 1; obj.trigger('event'); };
|
||||
var incrB = function(){ obj.counterB += 1; };
|
||||
obj.listenToOnce(obj, 'event', incrA);
|
||||
obj.listenToOnce(obj, 'event', incrB);
|
||||
obj.trigger('event');
|
||||
assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.');
|
||||
assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.');
|
||||
});
|
||||
|
||||
QUnit.test('listenToOnce and stopListening', function(assert) {
|
||||
assert.expect(1);
|
||||
var a = _.extend({}, Backbone.Events);
|
||||
var b = _.extend({}, Backbone.Events);
|
||||
a.listenToOnce(b, 'all', function() { assert.ok(true); });
|
||||
b.trigger('anything');
|
||||
b.trigger('anything');
|
||||
a.listenToOnce(b, 'all', function() { assert.ok(false); });
|
||||
a.stopListening();
|
||||
b.trigger('anything');
|
||||
});
|
||||
|
||||
QUnit.test('listenTo, listenToOnce and stopListening', function(assert) {
|
||||
assert.expect(1);
|
||||
var a = _.extend({}, Backbone.Events);
|
||||
var b = _.extend({}, Backbone.Events);
|
||||
a.listenToOnce(b, 'all', function() { assert.ok(true); });
|
||||
b.trigger('anything');
|
||||
b.trigger('anything');
|
||||
a.listenTo(b, 'all', function() { assert.ok(false); });
|
||||
a.stopListening();
|
||||
b.trigger('anything');
|
||||
});
|
||||
|
||||
QUnit.test('listenTo and stopListening with event maps', function(assert) {
|
||||
assert.expect(1);
|
||||
var a = _.extend({}, Backbone.Events);
|
||||
var b = _.extend({}, Backbone.Events);
|
||||
a.listenTo(b, {change: function(){ assert.ok(true); }});
|
||||
b.trigger('change');
|
||||
a.listenTo(b, {change: function(){ assert.ok(false); }});
|
||||
a.stopListening();
|
||||
b.trigger('change');
|
||||
});
|
||||
|
||||
QUnit.test('listenTo yourself', function(assert) {
|
||||
assert.expect(1);
|
||||
var e = _.extend({}, Backbone.Events);
|
||||
e.listenTo(e, 'foo', function(){ assert.ok(true); });
|
||||
e.trigger('foo');
|
||||
});
|
||||
|
||||
QUnit.test('listenTo yourself cleans yourself up with stopListening', function(assert) {
|
||||
assert.expect(1);
|
||||
var e = _.extend({}, Backbone.Events);
|
||||
e.listenTo(e, 'foo', function(){ assert.ok(true); });
|
||||
e.trigger('foo');
|
||||
e.stopListening();
|
||||
e.trigger('foo');
|
||||
});
|
||||
|
||||
QUnit.test('stopListening cleans up references', function(assert) {
|
||||
assert.expect(12);
|
||||
var a = _.extend({}, Backbone.Events);
|
||||
var b = _.extend({}, Backbone.Events);
|
||||
var fn = function() {};
|
||||
b.on('event', fn);
|
||||
a.listenTo(b, 'event', fn).stopListening();
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
assert.equal(_.size(b._events.event), 1);
|
||||
assert.equal(_.size(b._listeners), 0);
|
||||
a.listenTo(b, 'event', fn).stopListening(b);
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
assert.equal(_.size(b._events.event), 1);
|
||||
assert.equal(_.size(b._listeners), 0);
|
||||
a.listenTo(b, 'event', fn).stopListening(b, 'event');
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
assert.equal(_.size(b._events.event), 1);
|
||||
assert.equal(_.size(b._listeners), 0);
|
||||
a.listenTo(b, 'event', fn).stopListening(b, 'event', fn);
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
assert.equal(_.size(b._events.event), 1);
|
||||
assert.equal(_.size(b._listeners), 0);
|
||||
});
|
||||
|
||||
QUnit.test('stopListening cleans up references from listenToOnce', function(assert) {
|
||||
assert.expect(12);
|
||||
var a = _.extend({}, Backbone.Events);
|
||||
var b = _.extend({}, Backbone.Events);
|
||||
var fn = function() {};
|
||||
b.on('event', fn);
|
||||
a.listenToOnce(b, 'event', fn).stopListening();
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
assert.equal(_.size(b._events.event), 1);
|
||||
assert.equal(_.size(b._listeners), 0);
|
||||
a.listenToOnce(b, 'event', fn).stopListening(b);
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
assert.equal(_.size(b._events.event), 1);
|
||||
assert.equal(_.size(b._listeners), 0);
|
||||
a.listenToOnce(b, 'event', fn).stopListening(b, 'event');
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
assert.equal(_.size(b._events.event), 1);
|
||||
assert.equal(_.size(b._listeners), 0);
|
||||
a.listenToOnce(b, 'event', fn).stopListening(b, 'event', fn);
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
assert.equal(_.size(b._events.event), 1);
|
||||
assert.equal(_.size(b._listeners), 0);
|
||||
});
|
||||
|
||||
QUnit.test('listenTo and off cleaning up references', function(assert) {
|
||||
assert.expect(8);
|
||||
var a = _.extend({}, Backbone.Events);
|
||||
var b = _.extend({}, Backbone.Events);
|
||||
var fn = function() {};
|
||||
a.listenTo(b, 'event', fn);
|
||||
b.off();
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
assert.equal(_.size(b._listeners), 0);
|
||||
a.listenTo(b, 'event', fn);
|
||||
b.off('event');
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
assert.equal(_.size(b._listeners), 0);
|
||||
a.listenTo(b, 'event', fn);
|
||||
b.off(null, fn);
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
assert.equal(_.size(b._listeners), 0);
|
||||
a.listenTo(b, 'event', fn);
|
||||
b.off(null, null, a);
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
assert.equal(_.size(b._listeners), 0);
|
||||
});
|
||||
|
||||
QUnit.test('listenTo and stopListening cleaning up references', function(assert) {
|
||||
assert.expect(2);
|
||||
var a = _.extend({}, Backbone.Events);
|
||||
var b = _.extend({}, Backbone.Events);
|
||||
a.listenTo(b, 'all', function(){ assert.ok(true); });
|
||||
b.trigger('anything');
|
||||
a.listenTo(b, 'other', function(){ assert.ok(false); });
|
||||
a.stopListening(b, 'other');
|
||||
a.stopListening(b, 'all');
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
});
|
||||
|
||||
QUnit.test('listenToOnce without context cleans up references after the event has fired', function(assert) {
|
||||
assert.expect(2);
|
||||
var a = _.extend({}, Backbone.Events);
|
||||
var b = _.extend({}, Backbone.Events);
|
||||
a.listenToOnce(b, 'all', function(){ assert.ok(true); });
|
||||
b.trigger('anything');
|
||||
assert.equal(_.size(a._listeningTo), 0);
|
||||
});
|
||||
|
||||
QUnit.test('listenToOnce with event maps cleans up references', function(assert) {
|
||||
assert.expect(2);
|
||||
var a = _.extend({}, Backbone.Events);
|
||||
var b = _.extend({}, Backbone.Events);
|
||||
a.listenToOnce(b, {
|
||||
one: function() { assert.ok(true); },
|
||||
two: function() { assert.ok(false); }
|
||||
});
|
||||
b.trigger('one');
|
||||
assert.equal(_.size(a._listeningTo), 1);
|
||||
});
|
||||
|
||||
QUnit.test('listenToOnce with event maps binds the correct `this`', function(assert) {
|
||||
assert.expect(1);
|
||||
var a = _.extend({}, Backbone.Events);
|
||||
var b = _.extend({}, Backbone.Events);
|
||||
a.listenToOnce(b, {
|
||||
one: function() { assert.ok(this === a); },
|
||||
two: function() { assert.ok(false); }
|
||||
});
|
||||
b.trigger('one');
|
||||
});
|
||||
|
||||
QUnit.test("listenTo with empty callback doesn't throw an error", function(assert) {
|
||||
assert.expect(1);
|
||||
var e = _.extend({}, Backbone.Events);
|
||||
e.listenTo(e, 'foo', null);
|
||||
e.trigger('foo');
|
||||
assert.ok(true);
|
||||
});
|
||||
|
||||
QUnit.test('trigger all for each event', function(assert) {
|
||||
assert.expect(3);
|
||||
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');
|
||||
assert.ok(a);
|
||||
assert.ok(b);
|
||||
assert.equal(obj.counter, 2);
|
||||
});
|
||||
|
||||
QUnit.test('on, then unbind all functions', function(assert) {
|
||||
assert.expect(1);
|
||||
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');
|
||||
assert.equal(obj.counter, 1, 'counter should have only been incremented once.');
|
||||
});
|
||||
|
||||
QUnit.test('bind two callbacks, unbind only one', function(assert) {
|
||||
assert.expect(2);
|
||||
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');
|
||||
assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.');
|
||||
assert.equal(obj.counterB, 2, 'counterB should have been incremented twice.');
|
||||
});
|
||||
|
||||
QUnit.test('unbind a callback in the midst of it firing', function(assert) {
|
||||
assert.expect(1);
|
||||
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');
|
||||
assert.equal(obj.counter, 1, 'the callback should have been unbound.');
|
||||
});
|
||||
|
||||
QUnit.test('two binds that unbind themeselves', function(assert) {
|
||||
assert.expect(2);
|
||||
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');
|
||||
assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.');
|
||||
assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.');
|
||||
});
|
||||
|
||||
QUnit.test('bind a callback with a default context when none supplied', function(assert) {
|
||||
assert.expect(1);
|
||||
var obj = _.extend({
|
||||
assertTrue: function() {
|
||||
assert.equal(this, obj, '`this` was bound to the callback');
|
||||
}
|
||||
}, Backbone.Events);
|
||||
|
||||
obj.once('event', obj.assertTrue);
|
||||
obj.trigger('event');
|
||||
});
|
||||
|
||||
QUnit.test('bind a callback with a supplied context', function(assert) {
|
||||
assert.expect(1);
|
||||
var TestClass = function() {
|
||||
return this;
|
||||
};
|
||||
TestClass.prototype.assertTrue = function() {
|
||||
assert.ok(true, '`this` was bound to the callback');
|
||||
};
|
||||
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
obj.on('event', function() { this.assertTrue(); }, new TestClass);
|
||||
obj.trigger('event');
|
||||
});
|
||||
|
||||
QUnit.test('nested trigger with unbind', function(assert) {
|
||||
assert.expect(1);
|
||||
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');
|
||||
assert.equal(obj.counter, 3, 'counter should have been incremented three times');
|
||||
});
|
||||
|
||||
QUnit.test('callback list is not altered during trigger', function(assert) {
|
||||
assert.expect(2);
|
||||
var counter = 0, obj = _.extend({}, Backbone.Events);
|
||||
var incr = function(){ counter++; };
|
||||
var incrOn = function(){ obj.on('event all', incr); };
|
||||
var incrOff = function(){ obj.off('event all', incr); };
|
||||
|
||||
obj.on('event all', incrOn).trigger('event');
|
||||
assert.equal(counter, 0, 'on does not alter callback list');
|
||||
|
||||
obj.off().on('event', incrOff).on('event all', incr).trigger('event');
|
||||
assert.equal(counter, 2, 'off does not alter callback list');
|
||||
});
|
||||
|
||||
QUnit.test("#1282 - 'all' callback list is retrieved after each event.", function(assert) {
|
||||
assert.expect(1);
|
||||
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');
|
||||
assert.strictEqual(counter, 2);
|
||||
});
|
||||
|
||||
QUnit.test('if no callback is provided, `on` is a noop', function(assert) {
|
||||
assert.expect(0);
|
||||
_.extend({}, Backbone.Events).on('test').trigger('test');
|
||||
});
|
||||
|
||||
QUnit.test('if callback is truthy but not a function, `on` should throw an error just like jQuery', function(assert) {
|
||||
assert.expect(1);
|
||||
var view = _.extend({}, Backbone.Events).on('test', 'noop');
|
||||
assert.raises(function() {
|
||||
view.trigger('test');
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('remove all events for a specific context', function(assert) {
|
||||
assert.expect(4);
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
obj.on('x y all', function() { assert.ok(true); });
|
||||
obj.on('x y all', function() { assert.ok(false); }, obj);
|
||||
obj.off(null, null, obj);
|
||||
obj.trigger('x y');
|
||||
});
|
||||
|
||||
QUnit.test('remove all events for a specific callback', function(assert) {
|
||||
assert.expect(4);
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
var success = function() { assert.ok(true); };
|
||||
var fail = function() { assert.ok(false); };
|
||||
obj.on('x y all', success);
|
||||
obj.on('x y all', fail);
|
||||
obj.off(null, fail);
|
||||
obj.trigger('x y');
|
||||
});
|
||||
|
||||
QUnit.test('#1310 - off does not skip consecutive events', function(assert) {
|
||||
assert.expect(0);
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
obj.on('event', function() { assert.ok(false); }, obj);
|
||||
obj.on('event', function() { assert.ok(false); }, obj);
|
||||
obj.off(null, null, obj);
|
||||
obj.trigger('event');
|
||||
});
|
||||
|
||||
QUnit.test('once', function(assert) {
|
||||
assert.expect(2);
|
||||
// Same as the previous test, but we use once rather than having to explicitly unbind
|
||||
var obj = {counterA: 0, counterB: 0};
|
||||
_.extend(obj, Backbone.Events);
|
||||
var incrA = function(){ obj.counterA += 1; obj.trigger('event'); };
|
||||
var incrB = function(){ obj.counterB += 1; };
|
||||
obj.once('event', incrA);
|
||||
obj.once('event', incrB);
|
||||
obj.trigger('event');
|
||||
assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.');
|
||||
assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.');
|
||||
});
|
||||
|
||||
QUnit.test('once variant one', function(assert) {
|
||||
assert.expect(3);
|
||||
var f = function(){ assert.ok(true); };
|
||||
|
||||
var a = _.extend({}, Backbone.Events).once('event', f);
|
||||
var b = _.extend({}, Backbone.Events).on('event', f);
|
||||
|
||||
a.trigger('event');
|
||||
|
||||
b.trigger('event');
|
||||
b.trigger('event');
|
||||
});
|
||||
|
||||
QUnit.test('once variant two', function(assert) {
|
||||
assert.expect(3);
|
||||
var f = function(){ assert.ok(true); };
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
|
||||
obj
|
||||
.once('event', f)
|
||||
.on('event', f)
|
||||
.trigger('event')
|
||||
.trigger('event');
|
||||
});
|
||||
|
||||
QUnit.test('once with off', function(assert) {
|
||||
assert.expect(0);
|
||||
var f = function(){ assert.ok(true); };
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
|
||||
obj.once('event', f);
|
||||
obj.off('event', f);
|
||||
obj.trigger('event');
|
||||
});
|
||||
|
||||
QUnit.test('once with event maps', function(assert) {
|
||||
var obj = {counter: 0};
|
||||
_.extend(obj, Backbone.Events);
|
||||
|
||||
var increment = function() {
|
||||
this.counter += 1;
|
||||
};
|
||||
|
||||
obj.once({
|
||||
a: increment,
|
||||
b: increment,
|
||||
c: increment
|
||||
}, obj);
|
||||
|
||||
obj.trigger('a');
|
||||
assert.equal(obj.counter, 1);
|
||||
|
||||
obj.trigger('a b');
|
||||
assert.equal(obj.counter, 2);
|
||||
|
||||
obj.trigger('c');
|
||||
assert.equal(obj.counter, 3);
|
||||
|
||||
obj.trigger('a b c');
|
||||
assert.equal(obj.counter, 3);
|
||||
});
|
||||
|
||||
QUnit.test('bind a callback with a supplied context using once with object notation', function(assert) {
|
||||
assert.expect(1);
|
||||
var obj = {counter: 0};
|
||||
var context = {};
|
||||
_.extend(obj, Backbone.Events);
|
||||
|
||||
obj.once({
|
||||
a: function() {
|
||||
assert.strictEqual(this, context, 'defaults `context` to `callback` param');
|
||||
}
|
||||
}, context).trigger('a');
|
||||
});
|
||||
|
||||
QUnit.test('once with off only by context', function(assert) {
|
||||
assert.expect(0);
|
||||
var context = {};
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
obj.once('event', function(){ assert.ok(false); }, context);
|
||||
obj.off(null, null, context);
|
||||
obj.trigger('event');
|
||||
});
|
||||
|
||||
QUnit.test('Backbone object inherits Events', function(assert) {
|
||||
assert.ok(Backbone.on === Backbone.Events.on);
|
||||
});
|
||||
|
||||
QUnit.test('once with asynchronous events', function(assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(1);
|
||||
var func = _.debounce(function() { assert.ok(true); done(); }, 50);
|
||||
var obj = _.extend({}, Backbone.Events).once('async', func);
|
||||
|
||||
obj.trigger('async');
|
||||
obj.trigger('async');
|
||||
});
|
||||
|
||||
QUnit.test('once with multiple events.', function(assert) {
|
||||
assert.expect(2);
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
obj.once('x y', function() { assert.ok(true); });
|
||||
obj.trigger('x y');
|
||||
});
|
||||
|
||||
QUnit.test('Off during iteration with once.', function(assert) {
|
||||
assert.expect(2);
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
var f = function(){ this.off('event', f); };
|
||||
obj.on('event', f);
|
||||
obj.once('event', function(){});
|
||||
obj.on('event', function(){ assert.ok(true); });
|
||||
|
||||
obj.trigger('event');
|
||||
obj.trigger('event');
|
||||
});
|
||||
|
||||
QUnit.test('`once` on `all` should work as expected', function(assert) {
|
||||
assert.expect(1);
|
||||
Backbone.once('all', function() {
|
||||
assert.ok(true);
|
||||
Backbone.trigger('all');
|
||||
});
|
||||
Backbone.trigger('all');
|
||||
});
|
||||
|
||||
QUnit.test('once without a callback is a noop', function(assert) {
|
||||
assert.expect(0);
|
||||
_.extend({}, Backbone.Events).once('event').trigger('event');
|
||||
});
|
||||
|
||||
QUnit.test('listenToOnce without a callback is a noop', function(assert) {
|
||||
assert.expect(0);
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
obj.listenToOnce(obj, 'event').trigger('event');
|
||||
});
|
||||
|
||||
QUnit.test('event functions are chainable', function(assert) {
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
var obj2 = _.extend({}, Backbone.Events);
|
||||
var fn = function() {};
|
||||
assert.equal(obj, obj.trigger('noeventssetyet'));
|
||||
assert.equal(obj, obj.off('noeventssetyet'));
|
||||
assert.equal(obj, obj.stopListening('noeventssetyet'));
|
||||
assert.equal(obj, obj.on('a', fn));
|
||||
assert.equal(obj, obj.once('c', fn));
|
||||
assert.equal(obj, obj.trigger('a'));
|
||||
assert.equal(obj, obj.listenTo(obj2, 'a', fn));
|
||||
assert.equal(obj, obj.listenToOnce(obj2, 'b', fn));
|
||||
assert.equal(obj, obj.off('a c'));
|
||||
assert.equal(obj, obj.stopListening(obj2, 'a'));
|
||||
assert.equal(obj, obj.stopListening());
|
||||
});
|
||||
|
||||
QUnit.test('#3448 - listenToOnce with space-separated events', function(assert) {
|
||||
assert.expect(2);
|
||||
var one = _.extend({}, Backbone.Events);
|
||||
var two = _.extend({}, Backbone.Events);
|
||||
var count = 1;
|
||||
one.listenToOnce(two, 'x y', function(n) { assert.ok(n === count++); });
|
||||
two.trigger('x', 1);
|
||||
two.trigger('x', 1);
|
||||
two.trigger('y', 2);
|
||||
two.trigger('y', 2);
|
||||
});
|
||||
|
||||
})();
|
1418
app/bower_components/lodash/vendor/backbone/test/model.js
vendored
Normal file
13
app/bower_components/lodash/vendor/backbone/test/noconflict.js
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
(function() {
|
||||
|
||||
QUnit.module('Backbone.noConflict');
|
||||
|
||||
QUnit.test('noConflict', function(assert) {
|
||||
assert.expect(2);
|
||||
var noconflictBackbone = Backbone.noConflict();
|
||||
assert.equal(window.Backbone, undefined, 'Returned window.Backbone');
|
||||
window.Backbone = noconflictBackbone;
|
||||
assert.equal(window.Backbone, noconflictBackbone, 'Backbone is still pointing to the original Backbone');
|
||||
});
|
||||
|
||||
})();
|
1062
app/bower_components/lodash/vendor/backbone/test/router.js
vendored
Normal file
4
app/bower_components/lodash/vendor/backbone/test/setup/dom-setup.js
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
$('body').append(
|
||||
'<div id="qunit"></div>' +
|
||||
'<div id="qunit-fixture"></div>'
|
||||
);
|
45
app/bower_components/lodash/vendor/backbone/test/setup/environment.js
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
(function() {
|
||||
|
||||
var sync = Backbone.sync;
|
||||
var ajax = Backbone.ajax;
|
||||
var emulateHTTP = Backbone.emulateHTTP;
|
||||
var emulateJSON = Backbone.emulateJSON;
|
||||
var history = window.history;
|
||||
var pushState = history.pushState;
|
||||
var replaceState = history.replaceState;
|
||||
|
||||
QUnit.config.noglobals = true;
|
||||
|
||||
QUnit.testStart(function() {
|
||||
var env = QUnit.config.current.testEnvironment;
|
||||
|
||||
// We never want to actually call these during tests.
|
||||
history.pushState = history.replaceState = function(){};
|
||||
|
||||
// Capture ajax settings for comparison.
|
||||
Backbone.ajax = function(settings) {
|
||||
env.ajaxSettings = settings;
|
||||
};
|
||||
|
||||
// Capture the arguments to Backbone.sync for comparison.
|
||||
Backbone.sync = function(method, model, options) {
|
||||
env.syncArgs = {
|
||||
method: method,
|
||||
model: model,
|
||||
options: options
|
||||
};
|
||||
sync.apply(this, arguments);
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
QUnit.testDone(function() {
|
||||
Backbone.sync = sync;
|
||||
Backbone.ajax = ajax;
|
||||
Backbone.emulateHTTP = emulateHTTP;
|
||||
Backbone.emulateJSON = emulateJSON;
|
||||
history.pushState = pushState;
|
||||
history.replaceState = replaceState;
|
||||
});
|
||||
|
||||
})();
|
239
app/bower_components/lodash/vendor/backbone/test/sync.js
vendored
Normal file
|
@ -0,0 +1,239 @@
|
|||
(function() {
|
||||
|
||||
var Library = Backbone.Collection.extend({
|
||||
url: function() { return '/library'; }
|
||||
});
|
||||
var library;
|
||||
|
||||
var attrs = {
|
||||
title: 'The Tempest',
|
||||
author: 'Bill Shakespeare',
|
||||
length: 123
|
||||
};
|
||||
|
||||
QUnit.module('Backbone.sync', {
|
||||
|
||||
beforeEach: function(assert) {
|
||||
library = new Library;
|
||||
library.create(attrs, {wait: false});
|
||||
},
|
||||
|
||||
afterEach: function(assert) {
|
||||
Backbone.emulateHTTP = false;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
QUnit.test('read', function(assert) {
|
||||
assert.expect(4);
|
||||
library.fetch();
|
||||
assert.equal(this.ajaxSettings.url, '/library');
|
||||
assert.equal(this.ajaxSettings.type, 'GET');
|
||||
assert.equal(this.ajaxSettings.dataType, 'json');
|
||||
assert.ok(_.isEmpty(this.ajaxSettings.data));
|
||||
});
|
||||
|
||||
QUnit.test('passing data', function(assert) {
|
||||
assert.expect(3);
|
||||
library.fetch({data: {a: 'a', one: 1}});
|
||||
assert.equal(this.ajaxSettings.url, '/library');
|
||||
assert.equal(this.ajaxSettings.data.a, 'a');
|
||||
assert.equal(this.ajaxSettings.data.one, 1);
|
||||
});
|
||||
|
||||
QUnit.test('create', function(assert) {
|
||||
assert.expect(6);
|
||||
assert.equal(this.ajaxSettings.url, '/library');
|
||||
assert.equal(this.ajaxSettings.type, 'POST');
|
||||
assert.equal(this.ajaxSettings.dataType, 'json');
|
||||
var data = JSON.parse(this.ajaxSettings.data);
|
||||
assert.equal(data.title, 'The Tempest');
|
||||
assert.equal(data.author, 'Bill Shakespeare');
|
||||
assert.equal(data.length, 123);
|
||||
});
|
||||
|
||||
QUnit.test('update', function(assert) {
|
||||
assert.expect(7);
|
||||
library.first().save({id: '1-the-tempest', author: 'William Shakespeare'});
|
||||
assert.equal(this.ajaxSettings.url, '/library/1-the-tempest');
|
||||
assert.equal(this.ajaxSettings.type, 'PUT');
|
||||
assert.equal(this.ajaxSettings.dataType, 'json');
|
||||
var data = JSON.parse(this.ajaxSettings.data);
|
||||
assert.equal(data.id, '1-the-tempest');
|
||||
assert.equal(data.title, 'The Tempest');
|
||||
assert.equal(data.author, 'William Shakespeare');
|
||||
assert.equal(data.length, 123);
|
||||
});
|
||||
|
||||
QUnit.test('update with emulateHTTP and emulateJSON', function(assert) {
|
||||
assert.expect(7);
|
||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, {
|
||||
emulateHTTP: true,
|
||||
emulateJSON: true
|
||||
});
|
||||
assert.equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||
assert.equal(this.ajaxSettings.type, 'POST');
|
||||
assert.equal(this.ajaxSettings.dataType, 'json');
|
||||
assert.equal(this.ajaxSettings.data._method, 'PUT');
|
||||
var data = JSON.parse(this.ajaxSettings.data.model);
|
||||
assert.equal(data.id, '2-the-tempest');
|
||||
assert.equal(data.author, 'Tim Shakespeare');
|
||||
assert.equal(data.length, 123);
|
||||
});
|
||||
|
||||
QUnit.test('update with just emulateHTTP', function(assert) {
|
||||
assert.expect(6);
|
||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, {
|
||||
emulateHTTP: true
|
||||
});
|
||||
assert.equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||
assert.equal(this.ajaxSettings.type, 'POST');
|
||||
assert.equal(this.ajaxSettings.contentType, 'application/json');
|
||||
var data = JSON.parse(this.ajaxSettings.data);
|
||||
assert.equal(data.id, '2-the-tempest');
|
||||
assert.equal(data.author, 'Tim Shakespeare');
|
||||
assert.equal(data.length, 123);
|
||||
});
|
||||
|
||||
QUnit.test('update with just emulateJSON', function(assert) {
|
||||
assert.expect(6);
|
||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, {
|
||||
emulateJSON: true
|
||||
});
|
||||
assert.equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||
assert.equal(this.ajaxSettings.type, 'PUT');
|
||||
assert.equal(this.ajaxSettings.contentType, 'application/x-www-form-urlencoded');
|
||||
var data = JSON.parse(this.ajaxSettings.data.model);
|
||||
assert.equal(data.id, '2-the-tempest');
|
||||
assert.equal(data.author, 'Tim Shakespeare');
|
||||
assert.equal(data.length, 123);
|
||||
});
|
||||
|
||||
QUnit.test('read model', function(assert) {
|
||||
assert.expect(3);
|
||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||
library.first().fetch();
|
||||
assert.equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||
assert.equal(this.ajaxSettings.type, 'GET');
|
||||
assert.ok(_.isEmpty(this.ajaxSettings.data));
|
||||
});
|
||||
|
||||
QUnit.test('destroy', function(assert) {
|
||||
assert.expect(3);
|
||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||
library.first().destroy({wait: true});
|
||||
assert.equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||
assert.equal(this.ajaxSettings.type, 'DELETE');
|
||||
assert.equal(this.ajaxSettings.data, null);
|
||||
});
|
||||
|
||||
QUnit.test('destroy with emulateHTTP', function(assert) {
|
||||
assert.expect(3);
|
||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||
library.first().destroy({
|
||||
emulateHTTP: true,
|
||||
emulateJSON: true
|
||||
});
|
||||
assert.equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||
assert.equal(this.ajaxSettings.type, 'POST');
|
||||
assert.equal(JSON.stringify(this.ajaxSettings.data), '{"_method":"DELETE"}');
|
||||
});
|
||||
|
||||
QUnit.test('urlError', function(assert) {
|
||||
assert.expect(2);
|
||||
var model = new Backbone.Model();
|
||||
assert.raises(function() {
|
||||
model.fetch();
|
||||
});
|
||||
model.fetch({url: '/one/two'});
|
||||
assert.equal(this.ajaxSettings.url, '/one/two');
|
||||
});
|
||||
|
||||
QUnit.test('#1052 - `options` is optional.', function(assert) {
|
||||
assert.expect(0);
|
||||
var model = new Backbone.Model();
|
||||
model.url = '/test';
|
||||
Backbone.sync('create', model);
|
||||
});
|
||||
|
||||
QUnit.test('Backbone.ajax', function(assert) {
|
||||
assert.expect(1);
|
||||
Backbone.ajax = function(settings){
|
||||
assert.strictEqual(settings.url, '/test');
|
||||
};
|
||||
var model = new Backbone.Model();
|
||||
model.url = '/test';
|
||||
Backbone.sync('create', model);
|
||||
});
|
||||
|
||||
QUnit.test('Call provided error callback on error.', function(assert) {
|
||||
assert.expect(1);
|
||||
var model = new Backbone.Model;
|
||||
model.url = '/test';
|
||||
Backbone.sync('read', model, {
|
||||
error: function() { assert.ok(true); }
|
||||
});
|
||||
this.ajaxSettings.error();
|
||||
});
|
||||
|
||||
QUnit.test('Use Backbone.emulateHTTP as default.', function(assert) {
|
||||
assert.expect(2);
|
||||
var model = new Backbone.Model;
|
||||
model.url = '/test';
|
||||
|
||||
Backbone.emulateHTTP = true;
|
||||
model.sync('create', model);
|
||||
assert.strictEqual(this.ajaxSettings.emulateHTTP, true);
|
||||
|
||||
Backbone.emulateHTTP = false;
|
||||
model.sync('create', model);
|
||||
assert.strictEqual(this.ajaxSettings.emulateHTTP, false);
|
||||
});
|
||||
|
||||
QUnit.test('Use Backbone.emulateJSON as default.', function(assert) {
|
||||
assert.expect(2);
|
||||
var model = new Backbone.Model;
|
||||
model.url = '/test';
|
||||
|
||||
Backbone.emulateJSON = true;
|
||||
model.sync('create', model);
|
||||
assert.strictEqual(this.ajaxSettings.emulateJSON, true);
|
||||
|
||||
Backbone.emulateJSON = false;
|
||||
model.sync('create', model);
|
||||
assert.strictEqual(this.ajaxSettings.emulateJSON, false);
|
||||
});
|
||||
|
||||
QUnit.test('#1756 - Call user provided beforeSend function.', function(assert) {
|
||||
assert.expect(4);
|
||||
Backbone.emulateHTTP = true;
|
||||
var model = new Backbone.Model;
|
||||
model.url = '/test';
|
||||
var xhr = {
|
||||
setRequestHeader: function(header, value) {
|
||||
assert.strictEqual(header, 'X-HTTP-Method-Override');
|
||||
assert.strictEqual(value, 'DELETE');
|
||||
}
|
||||
};
|
||||
model.sync('delete', model, {
|
||||
beforeSend: function(_xhr) {
|
||||
assert.ok(_xhr === xhr);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
assert.strictEqual(this.ajaxSettings.beforeSend(xhr), false);
|
||||
});
|
||||
|
||||
QUnit.test('#2928 - Pass along `textStatus` and `errorThrown`.', function(assert) {
|
||||
assert.expect(2);
|
||||
var model = new Backbone.Model;
|
||||
model.url = '/test';
|
||||
model.on('error', function(m, xhr, options) {
|
||||
assert.strictEqual(options.textStatus, 'textStatus');
|
||||
assert.strictEqual(options.errorThrown, 'errorThrown');
|
||||
});
|
||||
model.fetch();
|
||||
this.ajaxSettings.error({}, 'textStatus', 'errorThrown');
|
||||
});
|
||||
|
||||
})();
|
495
app/bower_components/lodash/vendor/backbone/test/view.js
vendored
Normal file
|
@ -0,0 +1,495 @@
|
|||
(function() {
|
||||
|
||||
var view;
|
||||
|
||||
QUnit.module('Backbone.View', {
|
||||
|
||||
beforeEach: function(assert) {
|
||||
$('#qunit-fixture').append(
|
||||
'<div id="testElement"><h1>Test</h1></div>'
|
||||
);
|
||||
|
||||
view = new Backbone.View({
|
||||
id: 'test-view',
|
||||
className: 'test-view',
|
||||
other: 'non-special-option'
|
||||
});
|
||||
},
|
||||
|
||||
afterEach: function() {
|
||||
$('#testElement').remove();
|
||||
$('#test-view').remove();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
QUnit.test('constructor', function(assert) {
|
||||
assert.expect(3);
|
||||
assert.equal(view.el.id, 'test-view');
|
||||
assert.equal(view.el.className, 'test-view');
|
||||
assert.equal(view.el.other, void 0);
|
||||
});
|
||||
|
||||
QUnit.test('$', function(assert) {
|
||||
assert.expect(2);
|
||||
var myView = new Backbone.View;
|
||||
myView.setElement('<p><a><b>test</b></a></p>');
|
||||
var result = myView.$('a b');
|
||||
|
||||
assert.strictEqual(result[0].innerHTML, 'test');
|
||||
assert.ok(result.length === +result.length);
|
||||
});
|
||||
|
||||
QUnit.test('$el', function(assert) {
|
||||
assert.expect(3);
|
||||
var myView = new Backbone.View;
|
||||
myView.setElement('<p><a><b>test</b></a></p>');
|
||||
assert.strictEqual(myView.el.nodeType, 1);
|
||||
|
||||
assert.ok(myView.$el instanceof Backbone.$);
|
||||
assert.strictEqual(myView.$el[0], myView.el);
|
||||
});
|
||||
|
||||
QUnit.test('initialize', function(assert) {
|
||||
assert.expect(1);
|
||||
var View = Backbone.View.extend({
|
||||
initialize: function() {
|
||||
this.one = 1;
|
||||
}
|
||||
});
|
||||
|
||||
assert.strictEqual(new View().one, 1);
|
||||
});
|
||||
|
||||
QUnit.test('render', function(assert) {
|
||||
assert.expect(1);
|
||||
var myView = new Backbone.View;
|
||||
assert.equal(myView.render(), myView, '#render returns the view instance');
|
||||
});
|
||||
|
||||
QUnit.test('delegateEvents', function(assert) {
|
||||
assert.expect(6);
|
||||
var counter1 = 0, counter2 = 0;
|
||||
|
||||
var myView = new Backbone.View({el: '#testElement'});
|
||||
myView.increment = function(){ counter1++; };
|
||||
myView.$el.on('click', function(){ counter2++; });
|
||||
|
||||
var events = {'click h1': 'increment'};
|
||||
|
||||
myView.delegateEvents(events);
|
||||
myView.$('h1').trigger('click');
|
||||
assert.equal(counter1, 1);
|
||||
assert.equal(counter2, 1);
|
||||
|
||||
myView.$('h1').trigger('click');
|
||||
assert.equal(counter1, 2);
|
||||
assert.equal(counter2, 2);
|
||||
|
||||
myView.delegateEvents(events);
|
||||
myView.$('h1').trigger('click');
|
||||
assert.equal(counter1, 3);
|
||||
assert.equal(counter2, 3);
|
||||
});
|
||||
|
||||
QUnit.test('delegate', function(assert) {
|
||||
assert.expect(3);
|
||||
var myView = new Backbone.View({el: '#testElement'});
|
||||
myView.delegate('click', 'h1', function() {
|
||||
assert.ok(true);
|
||||
});
|
||||
myView.delegate('click', function() {
|
||||
assert.ok(true);
|
||||
});
|
||||
myView.$('h1').trigger('click');
|
||||
|
||||
assert.equal(myView.delegate(), myView, '#delegate returns the view instance');
|
||||
});
|
||||
|
||||
QUnit.test('delegateEvents allows functions for callbacks', function(assert) {
|
||||
assert.expect(3);
|
||||
var myView = new Backbone.View({el: '<p></p>'});
|
||||
myView.counter = 0;
|
||||
|
||||
var events = {
|
||||
click: function() {
|
||||
this.counter++;
|
||||
}
|
||||
};
|
||||
|
||||
myView.delegateEvents(events);
|
||||
myView.$el.trigger('click');
|
||||
assert.equal(myView.counter, 1);
|
||||
|
||||
myView.$el.trigger('click');
|
||||
assert.equal(myView.counter, 2);
|
||||
|
||||
myView.delegateEvents(events);
|
||||
myView.$el.trigger('click');
|
||||
assert.equal(myView.counter, 3);
|
||||
});
|
||||
|
||||
|
||||
QUnit.test('delegateEvents ignore undefined methods', function(assert) {
|
||||
assert.expect(0);
|
||||
var myView = new Backbone.View({el: '<p></p>'});
|
||||
myView.delegateEvents({'click': 'undefinedMethod'});
|
||||
myView.$el.trigger('click');
|
||||
});
|
||||
|
||||
QUnit.test('undelegateEvents', function(assert) {
|
||||
assert.expect(7);
|
||||
var counter1 = 0, counter2 = 0;
|
||||
|
||||
var myView = new Backbone.View({el: '#testElement'});
|
||||
myView.increment = function(){ counter1++; };
|
||||
myView.$el.on('click', function(){ counter2++; });
|
||||
|
||||
var events = {'click h1': 'increment'};
|
||||
|
||||
myView.delegateEvents(events);
|
||||
myView.$('h1').trigger('click');
|
||||
assert.equal(counter1, 1);
|
||||
assert.equal(counter2, 1);
|
||||
|
||||
myView.undelegateEvents();
|
||||
myView.$('h1').trigger('click');
|
||||
assert.equal(counter1, 1);
|
||||
assert.equal(counter2, 2);
|
||||
|
||||
myView.delegateEvents(events);
|
||||
myView.$('h1').trigger('click');
|
||||
assert.equal(counter1, 2);
|
||||
assert.equal(counter2, 3);
|
||||
|
||||
assert.equal(myView.undelegateEvents(), myView, '#undelegateEvents returns the view instance');
|
||||
});
|
||||
|
||||
QUnit.test('undelegate', function(assert) {
|
||||
assert.expect(1);
|
||||
var myView = new Backbone.View({el: '#testElement'});
|
||||
myView.delegate('click', function() { assert.ok(false); });
|
||||
myView.delegate('click', 'h1', function() { assert.ok(false); });
|
||||
|
||||
myView.undelegate('click');
|
||||
|
||||
myView.$('h1').trigger('click');
|
||||
myView.$el.trigger('click');
|
||||
|
||||
assert.equal(myView.undelegate(), myView, '#undelegate returns the view instance');
|
||||
});
|
||||
|
||||
QUnit.test('undelegate with passed handler', function(assert) {
|
||||
assert.expect(1);
|
||||
var myView = new Backbone.View({el: '#testElement'});
|
||||
var listener = function() { assert.ok(false); };
|
||||
myView.delegate('click', listener);
|
||||
myView.delegate('click', function() { assert.ok(true); });
|
||||
myView.undelegate('click', listener);
|
||||
myView.$el.trigger('click');
|
||||
});
|
||||
|
||||
QUnit.test('undelegate with selector', function(assert) {
|
||||
assert.expect(2);
|
||||
var myView = new Backbone.View({el: '#testElement'});
|
||||
myView.delegate('click', function() { assert.ok(true); });
|
||||
myView.delegate('click', 'h1', function() { assert.ok(false); });
|
||||
myView.undelegate('click', 'h1');
|
||||
myView.$('h1').trigger('click');
|
||||
myView.$el.trigger('click');
|
||||
});
|
||||
|
||||
QUnit.test('undelegate with handler and selector', function(assert) {
|
||||
assert.expect(2);
|
||||
var myView = new Backbone.View({el: '#testElement'});
|
||||
myView.delegate('click', function() { assert.ok(true); });
|
||||
var handler = function(){ assert.ok(false); };
|
||||
myView.delegate('click', 'h1', handler);
|
||||
myView.undelegate('click', 'h1', handler);
|
||||
myView.$('h1').trigger('click');
|
||||
myView.$el.trigger('click');
|
||||
});
|
||||
|
||||
QUnit.test('tagName can be provided as a string', function(assert) {
|
||||
assert.expect(1);
|
||||
var View = Backbone.View.extend({
|
||||
tagName: 'span'
|
||||
});
|
||||
|
||||
assert.equal(new View().el.tagName, 'SPAN');
|
||||
});
|
||||
|
||||
QUnit.test('tagName can be provided as a function', function(assert) {
|
||||
assert.expect(1);
|
||||
var View = Backbone.View.extend({
|
||||
tagName: function() {
|
||||
return 'p';
|
||||
}
|
||||
});
|
||||
|
||||
assert.ok(new View().$el.is('p'));
|
||||
});
|
||||
|
||||
QUnit.test('_ensureElement with DOM node el', function(assert) {
|
||||
assert.expect(1);
|
||||
var View = Backbone.View.extend({
|
||||
el: document.body
|
||||
});
|
||||
|
||||
assert.equal(new View().el, document.body);
|
||||
});
|
||||
|
||||
QUnit.test('_ensureElement with string el', function(assert) {
|
||||
assert.expect(3);
|
||||
var View = Backbone.View.extend({
|
||||
el: 'body'
|
||||
});
|
||||
assert.strictEqual(new View().el, document.body);
|
||||
|
||||
View = Backbone.View.extend({
|
||||
el: '#testElement > h1'
|
||||
});
|
||||
assert.strictEqual(new View().el, $('#testElement > h1').get(0));
|
||||
|
||||
View = Backbone.View.extend({
|
||||
el: '#nonexistent'
|
||||
});
|
||||
assert.ok(!new View().el);
|
||||
});
|
||||
|
||||
QUnit.test('with className and id functions', function(assert) {
|
||||
assert.expect(2);
|
||||
var View = Backbone.View.extend({
|
||||
className: function() {
|
||||
return 'className';
|
||||
},
|
||||
id: function() {
|
||||
return 'id';
|
||||
}
|
||||
});
|
||||
|
||||
assert.strictEqual(new View().el.className, 'className');
|
||||
assert.strictEqual(new View().el.id, 'id');
|
||||
});
|
||||
|
||||
QUnit.test('with attributes', function(assert) {
|
||||
assert.expect(2);
|
||||
var View = Backbone.View.extend({
|
||||
attributes: {
|
||||
'id': 'id',
|
||||
'class': 'class'
|
||||
}
|
||||
});
|
||||
|
||||
assert.strictEqual(new View().el.className, 'class');
|
||||
assert.strictEqual(new View().el.id, 'id');
|
||||
});
|
||||
|
||||
QUnit.test('with attributes as a function', function(assert) {
|
||||
assert.expect(1);
|
||||
var View = Backbone.View.extend({
|
||||
attributes: function() {
|
||||
return {'class': 'dynamic'};
|
||||
}
|
||||
});
|
||||
|
||||
assert.strictEqual(new View().el.className, 'dynamic');
|
||||
});
|
||||
|
||||
QUnit.test('should default to className/id properties', function(assert) {
|
||||
assert.expect(4);
|
||||
var View = Backbone.View.extend({
|
||||
className: 'backboneClass',
|
||||
id: 'backboneId',
|
||||
attributes: {
|
||||
'class': 'attributeClass',
|
||||
'id': 'attributeId'
|
||||
}
|
||||
});
|
||||
|
||||
var myView = new View;
|
||||
assert.strictEqual(myView.el.className, 'backboneClass');
|
||||
assert.strictEqual(myView.el.id, 'backboneId');
|
||||
assert.strictEqual(myView.$el.attr('class'), 'backboneClass');
|
||||
assert.strictEqual(myView.$el.attr('id'), 'backboneId');
|
||||
});
|
||||
|
||||
QUnit.test('multiple views per element', function(assert) {
|
||||
assert.expect(3);
|
||||
var count = 0;
|
||||
var $el = $('<p></p>');
|
||||
|
||||
var View = Backbone.View.extend({
|
||||
el: $el,
|
||||
events: {
|
||||
click: function() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var view1 = new View;
|
||||
$el.trigger('click');
|
||||
assert.equal(1, count);
|
||||
|
||||
var view2 = new View;
|
||||
$el.trigger('click');
|
||||
assert.equal(3, count);
|
||||
|
||||
view1.delegateEvents();
|
||||
$el.trigger('click');
|
||||
assert.equal(5, count);
|
||||
});
|
||||
|
||||
QUnit.test('custom events', function(assert) {
|
||||
assert.expect(2);
|
||||
var View = Backbone.View.extend({
|
||||
el: $('body'),
|
||||
events: {
|
||||
fake$event: function() { assert.ok(true); }
|
||||
}
|
||||
});
|
||||
|
||||
var myView = new View;
|
||||
$('body').trigger('fake$event').trigger('fake$event');
|
||||
|
||||
$('body').off('fake$event');
|
||||
$('body').trigger('fake$event');
|
||||
});
|
||||
|
||||
QUnit.test('#1048 - setElement uses provided object.', function(assert) {
|
||||
assert.expect(2);
|
||||
var $el = $('body');
|
||||
|
||||
var myView = new Backbone.View({el: $el});
|
||||
assert.ok(myView.$el === $el);
|
||||
|
||||
myView.setElement($el = $($el));
|
||||
assert.ok(myView.$el === $el);
|
||||
});
|
||||
|
||||
QUnit.test('#986 - Undelegate before changing element.', function(assert) {
|
||||
assert.expect(1);
|
||||
var button1 = $('<button></button>');
|
||||
var button2 = $('<button></button>');
|
||||
|
||||
var View = Backbone.View.extend({
|
||||
events: {
|
||||
click: function(e) {
|
||||
assert.ok(myView.el === e.target);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var myView = new View({el: button1});
|
||||
myView.setElement(button2);
|
||||
|
||||
button1.trigger('click');
|
||||
button2.trigger('click');
|
||||
});
|
||||
|
||||
QUnit.test('#1172 - Clone attributes object', function(assert) {
|
||||
assert.expect(2);
|
||||
var View = Backbone.View.extend({
|
||||
attributes: {foo: 'bar'}
|
||||
});
|
||||
|
||||
var view1 = new View({id: 'foo'});
|
||||
assert.strictEqual(view1.el.id, 'foo');
|
||||
|
||||
var view2 = new View();
|
||||
assert.ok(!view2.el.id);
|
||||
});
|
||||
|
||||
QUnit.test('views stopListening', function(assert) {
|
||||
assert.expect(0);
|
||||
var View = Backbone.View.extend({
|
||||
initialize: function() {
|
||||
this.listenTo(this.model, 'all x', function(){ assert.ok(false); });
|
||||
this.listenTo(this.collection, 'all x', function(){ assert.ok(false); });
|
||||
}
|
||||
});
|
||||
|
||||
var myView = new View({
|
||||
model: new Backbone.Model,
|
||||
collection: new Backbone.Collection
|
||||
});
|
||||
|
||||
myView.stopListening();
|
||||
myView.model.trigger('x');
|
||||
myView.collection.trigger('x');
|
||||
});
|
||||
|
||||
QUnit.test('Provide function for el.', function(assert) {
|
||||
assert.expect(2);
|
||||
var View = Backbone.View.extend({
|
||||
el: function() {
|
||||
return '<p><a></a></p>';
|
||||
}
|
||||
});
|
||||
|
||||
var myView = new View;
|
||||
assert.ok(myView.$el.is('p'));
|
||||
assert.ok(myView.$el.has('a'));
|
||||
});
|
||||
|
||||
QUnit.test('events passed in options', function(assert) {
|
||||
assert.expect(1);
|
||||
var counter = 0;
|
||||
|
||||
var View = Backbone.View.extend({
|
||||
el: '#testElement',
|
||||
increment: function() {
|
||||
counter++;
|
||||
}
|
||||
});
|
||||
|
||||
var myView = new View({
|
||||
events: {
|
||||
'click h1': 'increment'
|
||||
}
|
||||
});
|
||||
|
||||
myView.$('h1').trigger('click').trigger('click');
|
||||
assert.equal(counter, 2);
|
||||
});
|
||||
|
||||
QUnit.test('remove', function(assert) {
|
||||
assert.expect(2);
|
||||
var myView = new Backbone.View;
|
||||
document.body.appendChild(view.el);
|
||||
|
||||
myView.delegate('click', function() { assert.ok(false); });
|
||||
myView.listenTo(myView, 'all x', function() { assert.ok(false); });
|
||||
|
||||
assert.equal(myView.remove(), myView, '#remove returns the view instance');
|
||||
myView.$el.trigger('click');
|
||||
myView.trigger('x');
|
||||
|
||||
// In IE8 and below, parentNode still exists but is not document.body.
|
||||
assert.notEqual(myView.el.parentNode, document.body);
|
||||
});
|
||||
|
||||
QUnit.test('setElement', function(assert) {
|
||||
assert.expect(3);
|
||||
var myView = new Backbone.View({
|
||||
events: {
|
||||
click: function() { assert.ok(false); }
|
||||
}
|
||||
});
|
||||
myView.events = {
|
||||
click: function() { assert.ok(true); }
|
||||
};
|
||||
var oldEl = myView.el;
|
||||
var $oldEl = myView.$el;
|
||||
|
||||
myView.setElement(document.createElement('div'));
|
||||
|
||||
$oldEl.click();
|
||||
myView.$el.click();
|
||||
|
||||
assert.notEqual(oldEl, myView.el);
|
||||
assert.notEqual($oldEl, myView.$el);
|
||||
});
|
||||
|
||||
})();
|
30
app/bower_components/lodash/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
app/bower_components/lodash/vendor/firebug-lite/skin/xp/blank.gif
vendored
Normal file
After Width: | Height: | Size: 43 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/buttonBg.png
vendored
Normal file
After Width: | Height: | Size: 167 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/buttonBgHover.png
vendored
Normal file
After Width: | Height: | Size: 171 B |
331
app/bower_components/lodash/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
app/bower_components/lodash/vendor/firebug-lite/skin/xp/detach.png
vendored
Normal file
After Width: | Height: | Size: 655 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/detachHover.png
vendored
Normal file
After Width: | Height: | Size: 586 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/disable.gif
vendored
Normal file
After Width: | Height: | Size: 340 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/disable.png
vendored
Normal file
After Width: | Height: | Size: 543 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/disableHover.gif
vendored
Normal file
After Width: | Height: | Size: 344 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/disableHover.png
vendored
Normal file
After Width: | Height: | Size: 512 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/down.png
vendored
Normal file
After Width: | Height: | Size: 637 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/downActive.png
vendored
Normal file
After Width: | Height: | Size: 543 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/downHover.png
vendored
Normal file
After Width: | Height: | Size: 526 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/errorIcon-sm.png
vendored
Normal file
After Width: | Height: | Size: 447 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/errorIcon.gif
vendored
Normal file
After Width: | Height: | Size: 365 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/errorIcon.png
vendored
Normal file
After Width: | Height: | Size: 457 B |
817
app/bower_components/lodash/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
app/bower_components/lodash/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
app/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.css
vendored
Normal file
215
app/bower_components/lodash/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
app/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.png
vendored
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/group.gif
vendored
Normal file
After Width: | Height: | Size: 158 B |
272
app/bower_components/lodash/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
app/bower_components/lodash/vendor/firebug-lite/skin/xp/infoIcon.gif
vendored
Normal file
After Width: | Height: | Size: 359 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/infoIcon.png
vendored
Normal file
After Width: | Height: | Size: 524 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/loading_16.gif
vendored
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/min.png
vendored
Normal file
After Width: | Height: | Size: 552 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/minHover.png
vendored
Normal file
After Width: | Height: | Size: 485 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/off.png
vendored
Normal file
After Width: | Height: | Size: 742 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/offHover.png
vendored
Normal file
After Width: | Height: | Size: 680 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/pixel_transparent.gif
vendored
Normal file
After Width: | Height: | Size: 43 B |
6
app/bower_components/lodash/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: 228 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/search.gif
vendored
Normal file
After Width: | Height: | Size: 550 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/search.png
vendored
Normal file
After Width: | Height: | Size: 685 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/shadow.gif
vendored
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/shadow2.gif
vendored
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/shadowAlpha.png
vendored
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/sprite.png
vendored
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/tabHoverLeft.png
vendored
Normal file
After Width: | Height: | Size: 438 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/tabHoverMid.png
vendored
Normal file
After Width: | Height: | Size: 261 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/tabHoverRight.png
vendored
Normal file
After Width: | Height: | Size: 436 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/tabLeft.png
vendored
Normal file
After Width: | Height: | Size: 449 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuCheckbox.png
vendored
Normal file
After Width: | Height: | Size: 220 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuPin.png
vendored
Normal file
After Width: | Height: | Size: 207 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuRadio.png
vendored
Normal file
After Width: | Height: | Size: 192 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuTarget.png
vendored
Normal file
After Width: | Height: | Size: 142 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuTargetHover.png
vendored
Normal file
After Width: | Height: | Size: 148 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMid.png
vendored
Normal file
After Width: | Height: | Size: 262 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/tabRight.png
vendored
Normal file
After Width: | Height: | Size: 448 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorBorders.gif
vendored
Normal file
After Width: | Height: | Size: 117 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorBorders.png
vendored
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorCorners.gif
vendored
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorCorners.png
vendored
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/titlebarMid.png
vendored
Normal file
After Width: | Height: | Size: 273 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/toolbarMid.png
vendored
Normal file
After Width: | Height: | Size: 242 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/tree_close.gif
vendored
Normal file
After Width: | Height: | Size: 300 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/tree_open.gif
vendored
Normal file
After Width: | Height: | Size: 202 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/twistyClosed.png
vendored
Normal file
After Width: | Height: | Size: 334 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/twistyOpen.png
vendored
Normal file
After Width: | Height: | Size: 309 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/up.png
vendored
Normal file
After Width: | Height: | Size: 619 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/upActive.png
vendored
Normal file
After Width: | Height: | Size: 551 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/upHover.png
vendored
Normal file
After Width: | Height: | Size: 526 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/warningIcon.gif
vendored
Normal file
After Width: | Height: | Size: 357 B |
BIN
app/bower_components/lodash/vendor/firebug-lite/skin/xp/warningIcon.png
vendored
Normal file
After Width: | Height: | Size: 516 B |
31176
app/bower_components/lodash/vendor/firebug-lite/src/firebug-lite-debug.js
vendored
Normal file
519
app/bower_components/lodash/vendor/json-js/json2.js
vendored
Normal file
|
@ -0,0 +1,519 @@
|
|||
/*
|
||||
json2.js
|
||||
2015-05-03
|
||||
|
||||
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. This file is provides the ES5 JSON capability to ES3 systems.
|
||||
If a project might run on IE8 or earlier, then this file should be included.
|
||||
This file does nothing on ES5 systems.
|
||||
|
||||
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
|
||||
eval, for, this
|
||||
*/
|
||||
|
||||
/*property
|
||||
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 (typeof JSON !== 'object') {
|
||||
JSON = {};
|
||||
}
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var rx_one = /^[\],:{}\s]*$/,
|
||||
rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
|
||||
rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
|
||||
rx_four = /(?:^|:|,)(?:\s*\[)+/g,
|
||||
rx_escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
|
||||
|
||||
function f(n) {
|
||||
// Format integers to have at least two digits.
|
||||
return n < 10
|
||||
? '0' + n
|
||||
: n;
|
||||
}
|
||||
|
||||
function this_value() {
|
||||
return this.valueOf();
|
||||
}
|
||||
|
||||
if (typeof Date.prototype.toJSON !== 'function') {
|
||||
|
||||
Date.prototype.toJSON = function () {
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
Boolean.prototype.toJSON = this_value;
|
||||
Number.prototype.toJSON = this_value;
|
||||
String.prototype.toJSON = this_value;
|
||||
}
|
||||
|
||||
var gap,
|
||||
indent,
|
||||
meta,
|
||||
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.
|
||||
|
||||
rx_escapable.lastIndex = 0;
|
||||
return rx_escapable.test(string)
|
||||
? '"' + string.replace(rx_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) {
|
||||
if (typeof rep[i] === 'string') {
|
||||
k = rep[i];
|
||||
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.prototype.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') {
|
||||
meta = { // table of character substitutions
|
||||
'\b': '\\b',
|
||||
'\t': '\\t',
|
||||
'\n': '\\n',
|
||||
'\f': '\\f',
|
||||
'\r': '\\r',
|
||||
'"': '\\"',
|
||||
'\\': '\\\\'
|
||||
};
|
||||
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.prototype.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.
|
||||
|
||||
text = String(text);
|
||||
rx_dangerous.lastIndex = 0;
|
||||
if (rx_dangerous.test(text)) {
|
||||
text = text.replace(rx_dangerous, 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 (
|
||||
rx_one.test(
|
||||
text
|
||||
.replace(rx_two, '@')
|
||||
.replace(rx_three, ']')
|
||||
.replace(rx_four, '')
|
||||
)
|
||||
) {
|
||||
|
||||
// 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');
|
||||
};
|
||||
}
|
||||
}());
|
23
app/bower_components/lodash/vendor/underscore/LICENSE
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
Copyright (c) 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative
|
||||
Reporters & Editors
|
||||
|
||||
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.
|
555
app/bower_components/lodash/vendor/underscore/test/arrays.js
vendored
Normal file
|
@ -0,0 +1,555 @@
|
|||
(function() {
|
||||
var _ = typeof require == 'function' ? require('..') : window._;
|
||||
|
||||
QUnit.module('Arrays');
|
||||
|
||||
QUnit.test('first', function(assert) {
|
||||
assert.equal(_.first([1, 2, 3]), 1, 'can pull out the first element of an array');
|
||||
assert.equal(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"');
|
||||
assert.deepEqual(_.first([1, 2, 3], 0), [], 'returns an empty array when n <= 0 (0 case)');
|
||||
assert.deepEqual(_.first([1, 2, 3], -1), [], 'returns an empty array when n <= 0 (negative case)');
|
||||
assert.deepEqual(_.first([1, 2, 3], 2), [1, 2], 'can fetch the first n elements');
|
||||
assert.deepEqual(_.first([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length');
|
||||
var result = (function(){ return _.first(arguments); }(4, 3, 2, 1));
|
||||
assert.equal(result, 4, 'works on an arguments object');
|
||||
result = _.map([[1, 2, 3], [1, 2, 3]], _.first);
|
||||
assert.deepEqual(result, [1, 1], 'works well with _.map');
|
||||
assert.equal(_.first(null), void 0, 'returns undefined when called on null');
|
||||
});
|
||||
|
||||
QUnit.test('head', function(assert) {
|
||||
assert.strictEqual(_.head, _.first, 'is an alias for first');
|
||||
});
|
||||
|
||||
QUnit.test('take', function(assert) {
|
||||
assert.strictEqual(_.take, _.first, 'is an alias for first');
|
||||
});
|
||||
|
||||
QUnit.test('rest', function(assert) {
|
||||
var numbers = [1, 2, 3, 4];
|
||||
assert.deepEqual(_.rest(numbers), [2, 3, 4], 'fetches all but the first element');
|
||||
assert.deepEqual(_.rest(numbers, 0), [1, 2, 3, 4], 'returns the whole array when index is 0');
|
||||
assert.deepEqual(_.rest(numbers, 2), [3, 4], 'returns elements starting at the given index');
|
||||
var result = (function(){ return _(arguments).rest(); }(1, 2, 3, 4));
|
||||
assert.deepEqual(result, [2, 3, 4], 'works on an arguments object');
|
||||
result = _.map([[1, 2, 3], [1, 2, 3]], _.rest);
|
||||
assert.deepEqual(_.flatten(result), [2, 3, 2, 3], 'works well with _.map');
|
||||
});
|
||||
|
||||
QUnit.test('tail', function(assert) {
|
||||
assert.strictEqual(_.tail, _.rest, 'is an alias for rest');
|
||||
});
|
||||
|
||||
QUnit.test('drop', function(assert) {
|
||||
assert.strictEqual(_.drop, _.rest, 'is an alias for rest');
|
||||
});
|
||||
|
||||
QUnit.test('initial', function(assert) {
|
||||
assert.deepEqual(_.initial([1, 2, 3, 4, 5]), [1, 2, 3, 4], 'returns all but the last element');
|
||||
assert.deepEqual(_.initial([1, 2, 3, 4], 2), [1, 2], 'returns all but the last n elements');
|
||||
assert.deepEqual(_.initial([1, 2, 3, 4], 6), [], 'returns an empty array when n > length');
|
||||
var result = (function(){ return _(arguments).initial(); }(1, 2, 3, 4));
|
||||
assert.deepEqual(result, [1, 2, 3], 'works on an arguments object');
|
||||
result = _.map([[1, 2, 3], [1, 2, 3]], _.initial);
|
||||
assert.deepEqual(_.flatten(result), [1, 2, 1, 2], 'works well with _.map');
|
||||
});
|
||||
|
||||
QUnit.test('last', function(assert) {
|
||||
assert.equal(_.last([1, 2, 3]), 3, 'can pull out the last element of an array');
|
||||
assert.equal(_([1, 2, 3]).last(), 3, 'can perform OO-style "last()"');
|
||||
assert.deepEqual(_.last([1, 2, 3], 0), [], 'returns an empty array when n <= 0 (0 case)');
|
||||
assert.deepEqual(_.last([1, 2, 3], -1), [], 'returns an empty array when n <= 0 (negative case)');
|
||||
assert.deepEqual(_.last([1, 2, 3], 2), [2, 3], 'can fetch the last n elements');
|
||||
assert.deepEqual(_.last([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length');
|
||||
var result = (function(){ return _(arguments).last(); }(1, 2, 3, 4));
|
||||
assert.equal(result, 4, 'works on an arguments object');
|
||||
result = _.map([[1, 2, 3], [1, 2, 3]], _.last);
|
||||
assert.deepEqual(result, [3, 3], 'works well with _.map');
|
||||
assert.equal(_.last(null), void 0, 'returns undefined when called on null');
|
||||
});
|
||||
|
||||
QUnit.test('compact', function(assert) {
|
||||
assert.deepEqual(_.compact([1, false, null, 0, '', void 0, NaN, 2]), [1, 2], 'removes all falsy values');
|
||||
var result = (function(){ return _.compact(arguments); }(0, 1, false, 2, false, 3));
|
||||
assert.deepEqual(result, [1, 2, 3], 'works on an arguments object');
|
||||
result = _.map([[1, false, false], [false, false, 3]], _.compact);
|
||||
assert.deepEqual(result, [[1], [3]], 'works well with _.map');
|
||||
});
|
||||
|
||||
QUnit.test('flatten', function(assert) {
|
||||
assert.deepEqual(_.flatten(null), [], 'supports null');
|
||||
assert.deepEqual(_.flatten(void 0), [], 'supports undefined');
|
||||
|
||||
assert.deepEqual(_.flatten([[], [[]], []]), [], 'supports empty arrays');
|
||||
assert.deepEqual(_.flatten([[], [[]], []], true), [[]], 'can shallowly flatten empty arrays');
|
||||
|
||||
var list = [1, [2], [3, [[[4]]]]];
|
||||
assert.deepEqual(_.flatten(list), [1, 2, 3, 4], 'can flatten nested arrays');
|
||||
assert.deepEqual(_.flatten(list, true), [1, 2, 3, [[[4]]]], 'can shallowly flatten nested arrays');
|
||||
var result = (function(){ return _.flatten(arguments); }(1, [2], [3, [[[4]]]]));
|
||||
assert.deepEqual(result, [1, 2, 3, 4], 'works on an arguments object');
|
||||
list = [[1], [2], [3], [[4]]];
|
||||
assert.deepEqual(_.flatten(list, true), [1, 2, 3, [4]], 'can shallowly flatten arrays containing only other arrays');
|
||||
|
||||
assert.equal(_.flatten([_.range(10), _.range(10), 5, 1, 3], true).length, 23, 'can flatten medium length arrays');
|
||||
assert.equal(_.flatten([_.range(10), _.range(10), 5, 1, 3]).length, 23, 'can shallowly flatten medium length arrays');
|
||||
assert.equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3]).length, 1056003, 'can handle massive arrays');
|
||||
assert.equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3], true).length, 1056003, 'can handle massive arrays in shallow mode');
|
||||
|
||||
var x = _.range(100000);
|
||||
for (var i = 0; i < 1000; i++) x = [x];
|
||||
assert.deepEqual(_.flatten(x), _.range(100000), 'can handle very deep arrays');
|
||||
assert.deepEqual(_.flatten(x, true), x[0], 'can handle very deep arrays in shallow mode');
|
||||
});
|
||||
|
||||
QUnit.test('without', function(assert) {
|
||||
var list = [1, 2, 1, 0, 3, 1, 4];
|
||||
assert.deepEqual(_.without(list, 0, 1), [2, 3, 4], 'removes all instances of the given values');
|
||||
var result = (function(){ return _.without(arguments, 0, 1); }(1, 2, 1, 0, 3, 1, 4));
|
||||
assert.deepEqual(result, [2, 3, 4], 'works on an arguments object');
|
||||
|
||||
list = [{one: 1}, {two: 2}];
|
||||
assert.deepEqual(_.without(list, {one: 1}), list, 'compares objects by reference (value case)');
|
||||
assert.deepEqual(_.without(list, list[0]), [{two: 2}], 'compares objects by reference (reference case)');
|
||||
});
|
||||
|
||||
QUnit.test('sortedIndex', function(assert) {
|
||||
var numbers = [10, 20, 30, 40, 50];
|
||||
var indexFor35 = _.sortedIndex(numbers, 35);
|
||||
assert.equal(indexFor35, 3, 'finds the index at which a value should be inserted to retain order');
|
||||
var indexFor30 = _.sortedIndex(numbers, 30);
|
||||
assert.equal(indexFor30, 2, 'finds the smallest index at which a value could be inserted to retain order');
|
||||
|
||||
var objects = [{x: 10}, {x: 20}, {x: 30}, {x: 40}];
|
||||
var iterator = function(obj){ return obj.x; };
|
||||
assert.strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2, 'uses the result of `iterator` for order comparisons');
|
||||
assert.strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3, 'when `iterator` is a string, uses that key for order comparisons');
|
||||
|
||||
var context = {1: 2, 2: 3, 3: 4};
|
||||
iterator = function(obj){ return this[obj]; };
|
||||
assert.strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1, 'can execute its iterator in the given context');
|
||||
|
||||
var values = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287,
|
||||
1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647];
|
||||
var largeArray = Array(Math.pow(2, 32) - 1);
|
||||
var length = values.length;
|
||||
// Sparsely populate `array`
|
||||
while (length--) {
|
||||
largeArray[values[length]] = values[length];
|
||||
}
|
||||
assert.equal(_.sortedIndex(largeArray, 2147483648), 2147483648, 'works with large indexes');
|
||||
});
|
||||
|
||||
QUnit.test('uniq', function(assert) {
|
||||
var list = [1, 2, 1, 3, 1, 4];
|
||||
assert.deepEqual(_.uniq(list), [1, 2, 3, 4], 'can find the unique values of an unsorted array');
|
||||
list = [1, 1, 1, 2, 2, 3];
|
||||
assert.deepEqual(_.uniq(list, true), [1, 2, 3], 'can find the unique values of a sorted array faster');
|
||||
|
||||
list = [{name: 'Moe'}, {name: 'Curly'}, {name: 'Larry'}, {name: 'Curly'}];
|
||||
var expected = [{name: 'Moe'}, {name: 'Curly'}, {name: 'Larry'}];
|
||||
var iterator = function(stooge) { return stooge.name; };
|
||||
assert.deepEqual(_.uniq(list, false, iterator), expected, 'uses the result of `iterator` for uniqueness comparisons (unsorted case)');
|
||||
assert.deepEqual(_.uniq(list, iterator), expected, '`sorted` argument defaults to false when omitted');
|
||||
assert.deepEqual(_.uniq(list, 'name'), expected, 'when `iterator` is a string, uses that key for comparisons (unsorted case)');
|
||||
|
||||
list = [{score: 8}, {score: 10}, {score: 10}];
|
||||
expected = [{score: 8}, {score: 10}];
|
||||
iterator = function(item) { return item.score; };
|
||||
assert.deepEqual(_.uniq(list, true, iterator), expected, 'uses the result of `iterator` for uniqueness comparisons (sorted case)');
|
||||
assert.deepEqual(_.uniq(list, true, 'score'), expected, 'when `iterator` is a string, uses that key for comparisons (sorted case)');
|
||||
|
||||
assert.deepEqual(_.uniq([{0: 1}, {0: 1}, {0: 1}, {0: 2}], 0), [{0: 1}, {0: 2}], 'can use falsey pluck like iterator');
|
||||
|
||||
var result = (function(){ return _.uniq(arguments); }(1, 2, 1, 3, 1, 4));
|
||||
assert.deepEqual(result, [1, 2, 3, 4], 'works on an arguments object');
|
||||
|
||||
var a = {}, b = {}, c = {};
|
||||
assert.deepEqual(_.uniq([a, b, a, b, c]), [a, b, c], 'works on values that can be tested for equivalency but not ordered');
|
||||
|
||||
assert.deepEqual(_.uniq(null), [], 'returns an empty array when `array` is not iterable');
|
||||
|
||||
var context = {};
|
||||
list = [3];
|
||||
_.uniq(list, function(value, index, array) {
|
||||
assert.strictEqual(this, context, 'executes its iterator in the given context');
|
||||
assert.strictEqual(value, 3, 'passes its iterator the value');
|
||||
assert.strictEqual(index, 0, 'passes its iterator the index');
|
||||
assert.strictEqual(array, list, 'passes its iterator the entire array');
|
||||
}, context);
|
||||
|
||||
});
|
||||
|
||||
QUnit.test('unique', function(assert) {
|
||||
assert.strictEqual(_.unique, _.uniq, 'is an alias for uniq');
|
||||
});
|
||||
|
||||
QUnit.test('intersection', function(assert) {
|
||||
var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho'];
|
||||
assert.deepEqual(_.intersection(stooges, leaders), ['moe'], 'can find the set intersection of two arrays');
|
||||
assert.deepEqual(_(stooges).intersection(leaders), ['moe'], 'can perform an OO-style intersection');
|
||||
var result = (function(){ return _.intersection(arguments, leaders); }('moe', 'curly', 'larry'));
|
||||
assert.deepEqual(result, ['moe'], 'works on an arguments object');
|
||||
var theSixStooges = ['moe', 'moe', 'curly', 'curly', 'larry', 'larry'];
|
||||
assert.deepEqual(_.intersection(theSixStooges, leaders), ['moe'], 'returns a duplicate-free array');
|
||||
result = _.intersection([2, 4, 3, 1], [1, 2, 3]);
|
||||
assert.deepEqual(result, [2, 3, 1], 'preserves the order of the first array');
|
||||
result = _.intersection(null, [1, 2, 3]);
|
||||
assert.deepEqual(result, [], 'returns an empty array when passed null as the first argument');
|
||||
result = _.intersection([1, 2, 3], null);
|
||||
assert.deepEqual(result, [], 'returns an empty array when passed null as an argument beyond the first');
|
||||
});
|
||||
|
||||
QUnit.test('union', function(assert) {
|
||||
var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]);
|
||||
assert.deepEqual(result, [1, 2, 3, 30, 40], 'can find the union of a list of arrays');
|
||||
|
||||
result = _([1, 2, 3]).union([2, 30, 1], [1, 40]);
|
||||
assert.deepEqual(result, [1, 2, 3, 30, 40], 'can perform an OO-style union');
|
||||
|
||||
result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]);
|
||||
assert.deepEqual(result, [1, 2, 3, 30, 40, [1]], 'can find the union of a list of nested arrays');
|
||||
|
||||
result = _.union([10, 20], [1, 30, 10], [0, 40]);
|
||||
assert.deepEqual(result, [10, 20, 1, 30, 0, 40], 'orders values by their first encounter');
|
||||
|
||||
result = (function(){ return _.union(arguments, [2, 30, 1], [1, 40]); }(1, 2, 3));
|
||||
assert.deepEqual(result, [1, 2, 3, 30, 40], 'works on an arguments object');
|
||||
|
||||
assert.deepEqual(_.union([1, 2, 3], 4), [1, 2, 3], 'restricts the union to arrays only');
|
||||
});
|
||||
|
||||
QUnit.test('difference', function(assert) {
|
||||
var result = _.difference([1, 2, 3], [2, 30, 40]);
|
||||
assert.deepEqual(result, [1, 3], 'can find the difference of two arrays');
|
||||
|
||||
result = _([1, 2, 3]).difference([2, 30, 40]);
|
||||
assert.deepEqual(result, [1, 3], 'can perform an OO-style difference');
|
||||
|
||||
result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]);
|
||||
assert.deepEqual(result, [3, 4], 'can find the difference of three arrays');
|
||||
|
||||
result = _.difference([8, 9, 3, 1], [3, 8]);
|
||||
assert.deepEqual(result, [9, 1], 'preserves the order of the first array');
|
||||
|
||||
result = (function(){ return _.difference(arguments, [2, 30, 40]); }(1, 2, 3));
|
||||
assert.deepEqual(result, [1, 3], 'works on an arguments object');
|
||||
|
||||
result = _.difference([1, 2, 3], 1);
|
||||
assert.deepEqual(result, [1, 2, 3], 'restrict the difference to arrays only');
|
||||
});
|
||||
|
||||
QUnit.test('zip', function(assert) {
|
||||
var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true];
|
||||
assert.deepEqual(_.zip(names, ages, leaders), [
|
||||
['moe', 30, true],
|
||||
['larry', 40, void 0],
|
||||
['curly', 50, void 0]
|
||||
], 'zipped together arrays of different lengths');
|
||||
|
||||
var stooges = _.zip(['moe', 30, 'stooge 1'], ['larry', 40, 'stooge 2'], ['curly', 50, 'stooge 3']);
|
||||
assert.deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], ['stooge 1', 'stooge 2', 'stooge 3']], 'zipped pairs');
|
||||
|
||||
// In the case of different lengths of the tuples, undefined values
|
||||
// should be used as placeholder
|
||||
stooges = _.zip(['moe', 30], ['larry', 40], ['curly', 50, 'extra data']);
|
||||
assert.deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], [void 0, void 0, 'extra data']], 'zipped pairs with empties');
|
||||
|
||||
var empty = _.zip([]);
|
||||
assert.deepEqual(empty, [], 'unzipped empty');
|
||||
|
||||
assert.deepEqual(_.zip(null), [], 'handles null');
|
||||
assert.deepEqual(_.zip(), [], '_.zip() returns []');
|
||||
});
|
||||
|
||||
QUnit.test('unzip', function(assert) {
|
||||
assert.deepEqual(_.unzip(null), [], 'handles null');
|
||||
|
||||
assert.deepEqual(_.unzip([['a', 'b'], [1, 2]]), [['a', 1], ['b', 2]]);
|
||||
|
||||
// complements zip
|
||||
var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]);
|
||||
assert.deepEqual(_.unzip(zipped), [['fred', 'barney'], [30, 40], [true, false]]);
|
||||
|
||||
zipped = _.zip(['moe', 30], ['larry', 40], ['curly', 50, 'extra data']);
|
||||
assert.deepEqual(_.unzip(zipped), [['moe', 30, void 0], ['larry', 40, void 0], ['curly', 50, 'extra data']], 'Uses length of largest array');
|
||||
});
|
||||
|
||||
QUnit.test('object', function(assert) {
|
||||
var result = _.object(['moe', 'larry', 'curly'], [30, 40, 50]);
|
||||
var shouldBe = {moe: 30, larry: 40, curly: 50};
|
||||
assert.deepEqual(result, shouldBe, 'two arrays zipped together into an object');
|
||||
|
||||
result = _.object([['one', 1], ['two', 2], ['three', 3]]);
|
||||
shouldBe = {one: 1, two: 2, three: 3};
|
||||
assert.deepEqual(result, shouldBe, 'an array of pairs zipped together into an object');
|
||||
|
||||
var stooges = {moe: 30, larry: 40, curly: 50};
|
||||
assert.deepEqual(_.object(_.pairs(stooges)), stooges, 'an object converted to pairs and back to an object');
|
||||
|
||||
assert.deepEqual(_.object(null), {}, 'handles nulls');
|
||||
});
|
||||
|
||||
QUnit.test('indexOf', function(assert) {
|
||||
var numbers = [1, 2, 3];
|
||||
assert.equal(_.indexOf(numbers, 2), 1, 'can compute indexOf');
|
||||
var result = (function(){ return _.indexOf(arguments, 2); }(1, 2, 3));
|
||||
assert.equal(result, 1, 'works on an arguments object');
|
||||
|
||||
_.each([null, void 0, [], false], function(val) {
|
||||
var msg = 'Handles: ' + (_.isArray(val) ? '[]' : val);
|
||||
assert.equal(_.indexOf(val, 2), -1, msg);
|
||||
assert.equal(_.indexOf(val, 2, -1), -1, msg);
|
||||
assert.equal(_.indexOf(val, 2, -20), -1, msg);
|
||||
assert.equal(_.indexOf(val, 2, 15), -1, msg);
|
||||
});
|
||||
|
||||
var num = 35;
|
||||
numbers = [10, 20, 30, 40, 50];
|
||||
var index = _.indexOf(numbers, num, true);
|
||||
assert.equal(index, -1, '35 is not in the list');
|
||||
|
||||
numbers = [10, 20, 30, 40, 50]; num = 40;
|
||||
index = _.indexOf(numbers, num, true);
|
||||
assert.equal(index, 3, '40 is in the list');
|
||||
|
||||
numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40;
|
||||
assert.equal(_.indexOf(numbers, num, true), 1, '40 is in the list');
|
||||
assert.equal(_.indexOf(numbers, 6, true), -1, '6 isnt in the list');
|
||||
assert.equal(_.indexOf([1, 2, 5, 4, 6, 7], 5, true), -1, 'sorted indexOf doesn\'t uses binary search');
|
||||
assert.ok(_.every(['1', [], {}, null], function() {
|
||||
return _.indexOf(numbers, num, {}) === 1;
|
||||
}), 'non-nums as fromIndex make indexOf assume sorted');
|
||||
|
||||
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
|
||||
index = _.indexOf(numbers, 2, 5);
|
||||
assert.equal(index, 7, 'supports the fromIndex argument');
|
||||
|
||||
index = _.indexOf([,,, 0], void 0);
|
||||
assert.equal(index, 0, 'treats sparse arrays as if they were dense');
|
||||
|
||||
var array = [1, 2, 3, 1, 2, 3];
|
||||
assert.strictEqual(_.indexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index');
|
||||
assert.strictEqual(_.indexOf(array, 1, -2), -1, 'neg `fromIndex` starts at the right index');
|
||||
assert.strictEqual(_.indexOf(array, 2, -3), 4);
|
||||
_.each([-6, -8, -Infinity], function(fromIndex) {
|
||||
assert.strictEqual(_.indexOf(array, 1, fromIndex), 0);
|
||||
});
|
||||
assert.strictEqual(_.indexOf([1, 2, 3], 1, true), 0);
|
||||
|
||||
index = _.indexOf([], void 0, true);
|
||||
assert.equal(index, -1, 'empty array with truthy `isSorted` returns -1');
|
||||
});
|
||||
|
||||
QUnit.test('indexOf with NaN', function(assert) {
|
||||
assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN), 2, 'Expected [1, 2, NaN] to contain NaN');
|
||||
assert.strictEqual(_.indexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN');
|
||||
|
||||
assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, 1), 2, 'startIndex does not affect result');
|
||||
assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, -2), 2, 'startIndex does not affect result');
|
||||
|
||||
(function() {
|
||||
assert.strictEqual(_.indexOf(arguments, NaN), 2, 'Expected arguments [1, 2, NaN] to contain NaN');
|
||||
}(1, 2, NaN, NaN));
|
||||
});
|
||||
|
||||
QUnit.test('indexOf with +- 0', function(assert) {
|
||||
_.each([-0, +0], function(val) {
|
||||
assert.strictEqual(_.indexOf([1, 2, val, val], val), 2);
|
||||
assert.strictEqual(_.indexOf([1, 2, val, val], -val), 2);
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('lastIndexOf', function(assert) {
|
||||
var numbers = [1, 0, 1];
|
||||
var falsey = [void 0, '', 0, false, NaN, null, void 0];
|
||||
assert.equal(_.lastIndexOf(numbers, 1), 2);
|
||||
|
||||
numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];
|
||||
numbers.lastIndexOf = null;
|
||||
assert.equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
|
||||
assert.equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
|
||||
var result = (function(){ return _.lastIndexOf(arguments, 1); }(1, 0, 1, 0, 0, 1, 0, 0, 0));
|
||||
assert.equal(result, 5, 'works on an arguments object');
|
||||
|
||||
_.each([null, void 0, [], false], function(val) {
|
||||
var msg = 'Handles: ' + (_.isArray(val) ? '[]' : val);
|
||||
assert.equal(_.lastIndexOf(val, 2), -1, msg);
|
||||
assert.equal(_.lastIndexOf(val, 2, -1), -1, msg);
|
||||
assert.equal(_.lastIndexOf(val, 2, -20), -1, msg);
|
||||
assert.equal(_.lastIndexOf(val, 2, 15), -1, msg);
|
||||
});
|
||||
|
||||
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
|
||||
var index = _.lastIndexOf(numbers, 2, 2);
|
||||
assert.equal(index, 1, 'supports the fromIndex argument');
|
||||
|
||||
var array = [1, 2, 3, 1, 2, 3];
|
||||
|
||||
assert.strictEqual(_.lastIndexOf(array, 1, 0), 0, 'starts at the correct from idx');
|
||||
assert.strictEqual(_.lastIndexOf(array, 3), 5, 'should return the index of the last matched value');
|
||||
assert.strictEqual(_.lastIndexOf(array, 4), -1, 'should return `-1` for an unmatched value');
|
||||
|
||||
assert.strictEqual(_.lastIndexOf(array, 1, 2), 0, 'should work with a positive `fromIndex`');
|
||||
|
||||
_.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) {
|
||||
assert.strictEqual(_.lastIndexOf(array, void 0, fromIndex), -1);
|
||||
assert.strictEqual(_.lastIndexOf(array, 1, fromIndex), 3);
|
||||
assert.strictEqual(_.lastIndexOf(array, '', fromIndex), -1);
|
||||
});
|
||||
|
||||
var expected = _.map(falsey, function(value) {
|
||||
return typeof value == 'number' ? -1 : 5;
|
||||
});
|
||||
|
||||
var actual = _.map(falsey, function(fromIndex) {
|
||||
return _.lastIndexOf(array, 3, fromIndex);
|
||||
});
|
||||
|
||||
assert.deepEqual(actual, expected, 'should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`');
|
||||
assert.strictEqual(_.lastIndexOf(array, 3, '1'), 5, 'should treat non-number `fromIndex` values as `array.length`');
|
||||
assert.strictEqual(_.lastIndexOf(array, 3, true), 5, 'should treat non-number `fromIndex` values as `array.length`');
|
||||
|
||||
assert.strictEqual(_.lastIndexOf(array, 2, -3), 1, 'should work with a negative `fromIndex`');
|
||||
assert.strictEqual(_.lastIndexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index');
|
||||
|
||||
assert.deepEqual(_.map([-6, -8, -Infinity], function(fromIndex) {
|
||||
return _.lastIndexOf(array, 1, fromIndex);
|
||||
}), [0, -1, -1]);
|
||||
});
|
||||
|
||||
QUnit.test('lastIndexOf with NaN', function(assert) {
|
||||
assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN), 3, 'Expected [1, 2, NaN] to contain NaN');
|
||||
assert.strictEqual(_.lastIndexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN');
|
||||
|
||||
assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, 2), 2, 'fromIndex does not affect result');
|
||||
assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, -2), 2, 'fromIndex does not affect result');
|
||||
|
||||
(function() {
|
||||
assert.strictEqual(_.lastIndexOf(arguments, NaN), 3, 'Expected arguments [1, 2, NaN] to contain NaN');
|
||||
}(1, 2, NaN, NaN));
|
||||
});
|
||||
|
||||
QUnit.test('lastIndexOf with +- 0', function(assert) {
|
||||
_.each([-0, +0], function(val) {
|
||||
assert.strictEqual(_.lastIndexOf([1, 2, val, val], val), 3);
|
||||
assert.strictEqual(_.lastIndexOf([1, 2, val, val], -val), 3);
|
||||
assert.strictEqual(_.lastIndexOf([-1, 1, 2], -val), -1);
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('findIndex', function(assert) {
|
||||
var objects = [
|
||||
{a: 0, b: 0},
|
||||
{a: 1, b: 1},
|
||||
{a: 2, b: 2},
|
||||
{a: 0, b: 0}
|
||||
];
|
||||
|
||||
assert.equal(_.findIndex(objects, function(obj) {
|
||||
return obj.a === 0;
|
||||
}), 0);
|
||||
|
||||
assert.equal(_.findIndex(objects, function(obj) {
|
||||
return obj.b * obj.a === 4;
|
||||
}), 2);
|
||||
|
||||
assert.equal(_.findIndex(objects, 'a'), 1, 'Uses lookupIterator');
|
||||
|
||||
assert.equal(_.findIndex(objects, function(obj) {
|
||||
return obj.b * obj.a === 5;
|
||||
}), -1);
|
||||
|
||||
assert.equal(_.findIndex(null, _.noop), -1);
|
||||
assert.strictEqual(_.findIndex(objects, function(a) {
|
||||
return a.foo === null;
|
||||
}), -1);
|
||||
_.findIndex([{a: 1}], function(a, key, obj) {
|
||||
assert.equal(key, 0);
|
||||
assert.deepEqual(obj, [{a: 1}]);
|
||||
assert.strictEqual(this, objects, 'called with context');
|
||||
}, objects);
|
||||
|
||||
var sparse = [];
|
||||
sparse[20] = {a: 2, b: 2};
|
||||
assert.equal(_.findIndex(sparse, function(obj) {
|
||||
return obj && obj.b * obj.a === 4;
|
||||
}), 20, 'Works with sparse arrays');
|
||||
|
||||
var array = [1, 2, 3, 4];
|
||||
array.match = 55;
|
||||
assert.strictEqual(_.findIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys');
|
||||
});
|
||||
|
||||
QUnit.test('findLastIndex', function(assert) {
|
||||
var objects = [
|
||||
{a: 0, b: 0},
|
||||
{a: 1, b: 1},
|
||||
{a: 2, b: 2},
|
||||
{a: 0, b: 0}
|
||||
];
|
||||
|
||||
assert.equal(_.findLastIndex(objects, function(obj) {
|
||||
return obj.a === 0;
|
||||
}), 3);
|
||||
|
||||
assert.equal(_.findLastIndex(objects, function(obj) {
|
||||
return obj.b * obj.a === 4;
|
||||
}), 2);
|
||||
|
||||
assert.equal(_.findLastIndex(objects, 'a'), 2, 'Uses lookupIterator');
|
||||
|
||||
assert.equal(_.findLastIndex(objects, function(obj) {
|
||||
return obj.b * obj.a === 5;
|
||||
}), -1);
|
||||
|
||||
assert.equal(_.findLastIndex(null, _.noop), -1);
|
||||
assert.strictEqual(_.findLastIndex(objects, function(a) {
|
||||
return a.foo === null;
|
||||
}), -1);
|
||||
_.findLastIndex([{a: 1}], function(a, key, obj) {
|
||||
assert.equal(key, 0);
|
||||
assert.deepEqual(obj, [{a: 1}]);
|
||||
assert.strictEqual(this, objects, 'called with context');
|
||||
}, objects);
|
||||
|
||||
var sparse = [];
|
||||
sparse[20] = {a: 2, b: 2};
|
||||
assert.equal(_.findLastIndex(sparse, function(obj) {
|
||||
return obj && obj.b * obj.a === 4;
|
||||
}), 20, 'Works with sparse arrays');
|
||||
|
||||
var array = [1, 2, 3, 4];
|
||||
array.match = 55;
|
||||
assert.strictEqual(_.findLastIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys');
|
||||
});
|
||||
|
||||
QUnit.test('range', function(assert) {
|
||||
assert.deepEqual(_.range(0), [], 'range with 0 as a first argument generates an empty array');
|
||||
assert.deepEqual(_.range(4), [0, 1, 2, 3], 'range with a single positive argument generates an array of elements 0,1,2,...,n-1');
|
||||
assert.deepEqual(_.range(5, 8), [5, 6, 7], 'range with two arguments a & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1');
|
||||
assert.deepEqual(_.range(3, 10, 3), [3, 6, 9], 'range with three arguments a & b & c, c < b-a, a < b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) < c');
|
||||
assert.deepEqual(_.range(3, 10, 15), [3], 'range with three arguments a & b & c, c > b-a, a < b generates an array with a single element, equal to a');
|
||||
assert.deepEqual(_.range(12, 7, -2), [12, 10, 8], 'range with three arguments a & b & c, a > b, c < 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b');
|
||||
assert.deepEqual(_.range(0, -10, -1), [0, -1, -2, -3, -4, -5, -6, -7, -8, -9], 'final example in the Python docs');
|
||||
assert.strictEqual(1 / _.range(-0, 1)[0], -Infinity, 'should preserve -0');
|
||||
assert.deepEqual(_.range(8, 5), [8, 7, 6], 'negative range generates descending array');
|
||||
assert.deepEqual(_.range(-3), [0, -1, -2], 'negative range generates descending array');
|
||||
});
|
||||
|
||||
QUnit.test('chunk', function(assert) {
|
||||
assert.deepEqual(_.chunk([], 2), [], 'chunk for empty array returns an empty array');
|
||||
|
||||
assert.deepEqual(_.chunk([1, 2, 3], 0), [], 'chunk into parts of 0 elements returns empty array');
|
||||
assert.deepEqual(_.chunk([1, 2, 3], -1), [], 'chunk into parts of negative amount of elements returns an empty array');
|
||||
assert.deepEqual(_.chunk([1, 2, 3]), [], 'defaults to empty array (chunk size 0)');
|
||||
|
||||
assert.deepEqual(_.chunk([1, 2, 3], 1), [[1], [2], [3]], 'chunk into parts of 1 elements returns original array');
|
||||
|
||||
assert.deepEqual(_.chunk([1, 2, 3], 3), [[1, 2, 3]], 'chunk into parts of current array length elements returns the original array');
|
||||
assert.deepEqual(_.chunk([1, 2, 3], 5), [[1, 2, 3]], 'chunk into parts of more then current array length elements returns the original array');
|
||||
|
||||
assert.deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 2), [[10, 20], [30, 40], [50, 60], [70]], 'chunk into parts of less then current array length elements');
|
||||
assert.deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 3), [[10, 20, 30], [40, 50, 60], [70]], 'chunk into parts of less then current array length elements');
|
||||
});
|
||||
}());
|
99
app/bower_components/lodash/vendor/underscore/test/chaining.js
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
(function() {
|
||||
var _ = typeof require == 'function' ? require('..') : window._;
|
||||
|
||||
QUnit.module('Chaining');
|
||||
|
||||
QUnit.test('map/flatten/reduce', function(assert) {
|
||||
var lyrics = [
|
||||
'I\'m a lumberjack and I\'m okay',
|
||||
'I sleep all night and I work all day',
|
||||
'He\'s a lumberjack and he\'s okay',
|
||||
'He sleeps all night and he works all day'
|
||||
];
|
||||
var counts = _(lyrics).chain()
|
||||
.map(function(line) { return line.split(''); })
|
||||
.flatten()
|
||||
.reduce(function(hash, l) {
|
||||
hash[l] = hash[l] || 0;
|
||||
hash[l]++;
|
||||
return hash;
|
||||
}, {})
|
||||
.value();
|
||||
assert.equal(counts.a, 16, 'counted all the letters in the song');
|
||||
assert.equal(counts.e, 10, 'counted all the letters in the song');
|
||||
});
|
||||
|
||||
QUnit.test('select/reject/sortBy', function(assert) {
|
||||
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
numbers = _(numbers).chain().select(function(n) {
|
||||
return n % 2 === 0;
|
||||
}).reject(function(n) {
|
||||
return n % 4 === 0;
|
||||
}).sortBy(function(n) {
|
||||
return -n;
|
||||
}).value();
|
||||
assert.deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers');
|
||||
});
|
||||
|
||||
QUnit.test('select/reject/sortBy in functional style', function(assert) {
|
||||
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
numbers = _.chain(numbers).select(function(n) {
|
||||
return n % 2 === 0;
|
||||
}).reject(function(n) {
|
||||
return n % 4 === 0;
|
||||
}).sortBy(function(n) {
|
||||
return -n;
|
||||
}).value();
|
||||
assert.deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers');
|
||||
});
|
||||
|
||||
QUnit.test('reverse/concat/unshift/pop/map', function(assert) {
|
||||
var numbers = [1, 2, 3, 4, 5];
|
||||
numbers = _(numbers).chain()
|
||||
.reverse()
|
||||
.concat([5, 5, 5])
|
||||
.unshift(17)
|
||||
.pop()
|
||||
.map(function(n){ return n * 2; })
|
||||
.value();
|
||||
assert.deepEqual(numbers, [34, 10, 8, 6, 4, 2, 10, 10], 'can chain together array functions.');
|
||||
});
|
||||
|
||||
QUnit.test('splice', function(assert) {
|
||||
var instance = _([1, 2, 3, 4, 5]).chain();
|
||||
assert.deepEqual(instance.splice(1, 3).value(), [1, 5]);
|
||||
assert.deepEqual(instance.splice(1, 0).value(), [1, 5]);
|
||||
assert.deepEqual(instance.splice(1, 1).value(), [1]);
|
||||
assert.deepEqual(instance.splice(0, 1).value(), [], '#397 Can create empty array');
|
||||
});
|
||||
|
||||
QUnit.test('shift', function(assert) {
|
||||
var instance = _([1, 2, 3]).chain();
|
||||
assert.deepEqual(instance.shift().value(), [2, 3]);
|
||||
assert.deepEqual(instance.shift().value(), [3]);
|
||||
assert.deepEqual(instance.shift().value(), [], '#397 Can create empty array');
|
||||
});
|
||||
|
||||
QUnit.test('pop', function(assert) {
|
||||
var instance = _([1, 2, 3]).chain();
|
||||
assert.deepEqual(instance.pop().value(), [1, 2]);
|
||||
assert.deepEqual(instance.pop().value(), [1]);
|
||||
assert.deepEqual(instance.pop().value(), [], '#397 Can create empty array');
|
||||
});
|
||||
|
||||
QUnit.test('chaining works in small stages', function(assert) {
|
||||
var o = _([1, 2, 3, 4]).chain();
|
||||
assert.deepEqual(o.filter(function(i) { return i < 3; }).value(), [1, 2]);
|
||||
assert.deepEqual(o.filter(function(i) { return i > 2; }).value(), [3, 4]);
|
||||
});
|
||||
|
||||
QUnit.test('#1562: Engine proxies for chained functions', function(assert) {
|
||||
var wrapped = _(512);
|
||||
assert.strictEqual(wrapped.toJSON(), 512);
|
||||
assert.strictEqual(wrapped.valueOf(), 512);
|
||||
assert.strictEqual(+wrapped, 512);
|
||||
assert.strictEqual(wrapped.toString(), '512');
|
||||
assert.strictEqual('' + wrapped, '512');
|
||||
});
|
||||
|
||||
}());
|
896
app/bower_components/lodash/vendor/underscore/test/collections.js
vendored
Normal file
|
@ -0,0 +1,896 @@
|
|||
(function() {
|
||||
var _ = typeof require == 'function' ? require('..') : window._;
|
||||
|
||||
QUnit.module('Collections');
|
||||
|
||||
QUnit.test('each', function(assert) {
|
||||
_.each([1, 2, 3], function(num, i) {
|
||||
assert.equal(num, i + 1, 'each iterators provide value and iteration count');
|
||||
});
|
||||
|
||||
var answers = [];
|
||||
_.each([1, 2, 3], function(num){ answers.push(num * this.multiplier); }, {multiplier: 5});
|
||||
assert.deepEqual(answers, [5, 10, 15], 'context object property accessed');
|
||||
|
||||
answers = [];
|
||||
_.each([1, 2, 3], function(num){ answers.push(num); });
|
||||
assert.deepEqual(answers, [1, 2, 3], 'can iterate a simple array');
|
||||
|
||||
answers = [];
|
||||
var obj = {one: 1, two: 2, three: 3};
|
||||
obj.constructor.prototype.four = 4;
|
||||
_.each(obj, function(value, key){ answers.push(key); });
|
||||
assert.deepEqual(answers, ['one', 'two', 'three'], 'iterating over objects works, and ignores the object prototype.');
|
||||
delete obj.constructor.prototype.four;
|
||||
|
||||
// ensure the each function is JITed
|
||||
_(1000).times(function() { _.each([], function(){}); });
|
||||
var count = 0;
|
||||
obj = {1: 'foo', 2: 'bar', 3: 'baz'};
|
||||
_.each(obj, function(){ count++; });
|
||||
assert.equal(count, 3, 'the fun should be called only 3 times');
|
||||
|
||||
var answer = null;
|
||||
_.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; });
|
||||
assert.ok(answer, 'can reference the original collection from inside the iterator');
|
||||
|
||||
answers = 0;
|
||||
_.each(null, function(){ ++answers; });
|
||||
assert.equal(answers, 0, 'handles a null properly');
|
||||
|
||||
_.each(false, function(){});
|
||||
|
||||
var a = [1, 2, 3];
|
||||
assert.strictEqual(_.each(a, function(){}), a);
|
||||
assert.strictEqual(_.each(null, function(){}), null);
|
||||
});
|
||||
|
||||
QUnit.test('forEach', function(assert) {
|
||||
assert.strictEqual(_.forEach, _.each, 'is an alias for each');
|
||||
});
|
||||
|
||||
QUnit.test('lookupIterator with contexts', function(assert) {
|
||||
_.each([true, false, 'yes', '', 0, 1, {}], function(context) {
|
||||
_.each([1], function() {
|
||||
assert.equal(this, context);
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('Iterating objects with sketchy length properties', function(assert) {
|
||||
var functions = [
|
||||
'each', 'map', 'filter', 'find',
|
||||
'some', 'every', 'max', 'min',
|
||||
'groupBy', 'countBy', 'partition', 'indexBy'
|
||||
];
|
||||
var reducers = ['reduce', 'reduceRight'];
|
||||
|
||||
var tricks = [
|
||||
{length: '5'},
|
||||
{length: {valueOf: _.constant(5)}},
|
||||
{length: Math.pow(2, 53) + 1},
|
||||
{length: Math.pow(2, 53)},
|
||||
{length: null},
|
||||
{length: -2},
|
||||
{length: new Number(15)}
|
||||
];
|
||||
|
||||
assert.expect(tricks.length * (functions.length + reducers.length + 4));
|
||||
|
||||
_.each(tricks, function(trick) {
|
||||
var length = trick.length;
|
||||
assert.strictEqual(_.size(trick), 1, 'size on obj with length: ' + length);
|
||||
assert.deepEqual(_.toArray(trick), [length], 'toArray on obj with length: ' + length);
|
||||
assert.deepEqual(_.shuffle(trick), [length], 'shuffle on obj with length: ' + length);
|
||||
assert.deepEqual(_.sample(trick), length, 'sample on obj with length: ' + length);
|
||||
|
||||
|
||||
_.each(functions, function(method) {
|
||||
_[method](trick, function(val, key) {
|
||||
assert.strictEqual(key, 'length', method + ': ran with length = ' + val);
|
||||
});
|
||||
});
|
||||
|
||||
_.each(reducers, function(method) {
|
||||
assert.strictEqual(_[method](trick), trick.length, method);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('Resistant to collection length and properties changing while iterating', function(assert) {
|
||||
|
||||
var collection = [
|
||||
'each', 'map', 'filter', 'find',
|
||||
'some', 'every', 'max', 'min', 'reject',
|
||||
'groupBy', 'countBy', 'partition', 'indexBy',
|
||||
'reduce', 'reduceRight'
|
||||
];
|
||||
var array = [
|
||||
'findIndex', 'findLastIndex'
|
||||
];
|
||||
var object = [
|
||||
'mapObject', 'findKey', 'pick', 'omit'
|
||||
];
|
||||
|
||||
_.each(collection.concat(array), function(method) {
|
||||
var sparseArray = [1, 2, 3];
|
||||
sparseArray.length = 100;
|
||||
var answers = 0;
|
||||
_[method](sparseArray, function(){
|
||||
++answers;
|
||||
return method === 'every' ? true : null;
|
||||
}, {});
|
||||
assert.equal(answers, 100, method + ' enumerates [0, length)');
|
||||
|
||||
var growingCollection = [1, 2, 3], count = 0;
|
||||
_[method](growingCollection, function() {
|
||||
if (count < 10) growingCollection.push(count++);
|
||||
return method === 'every' ? true : null;
|
||||
}, {});
|
||||
assert.equal(count, 3, method + ' is resistant to length changes');
|
||||
});
|
||||
|
||||
_.each(collection.concat(object), function(method) {
|
||||
var changingObject = {0: 0, 1: 1}, count = 0;
|
||||
_[method](changingObject, function(val) {
|
||||
if (count < 10) changingObject[++count] = val + 1;
|
||||
return method === 'every' ? true : null;
|
||||
}, {});
|
||||
|
||||
assert.equal(count, 2, method + ' is resistant to property changes');
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('map', function(assert) {
|
||||
var doubled = _.map([1, 2, 3], function(num){ return num * 2; });
|
||||
assert.deepEqual(doubled, [2, 4, 6], 'doubled numbers');
|
||||
|
||||
var tripled = _.map([1, 2, 3], function(num){ return num * this.multiplier; }, {multiplier: 3});
|
||||
assert.deepEqual(tripled, [3, 6, 9], 'tripled numbers with context');
|
||||
|
||||
doubled = _([1, 2, 3]).map(function(num){ return num * 2; });
|
||||
assert.deepEqual(doubled, [2, 4, 6], 'OO-style doubled numbers');
|
||||
|
||||
var ids = _.map({length: 2, 0: {id: '1'}, 1: {id: '2'}}, function(n){
|
||||
return n.id;
|
||||
});
|
||||
assert.deepEqual(ids, ['1', '2'], 'Can use collection methods on Array-likes.');
|
||||
|
||||
assert.deepEqual(_.map(null, _.noop), [], 'handles a null properly');
|
||||
|
||||
assert.deepEqual(_.map([1], function() {
|
||||
return this.length;
|
||||
}, [5]), [1], 'called with context');
|
||||
|
||||
// Passing a property name like _.pluck.
|
||||
var people = [{name: 'moe', age: 30}, {name: 'curly', age: 50}];
|
||||
assert.deepEqual(_.map(people, 'name'), ['moe', 'curly'], 'predicate string map to object properties');
|
||||
});
|
||||
|
||||
QUnit.test('collect', function(assert) {
|
||||
assert.strictEqual(_.collect, _.map, 'is an alias for map');
|
||||
});
|
||||
|
||||
QUnit.test('reduce', function(assert) {
|
||||
var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
|
||||
assert.equal(sum, 6, 'can sum up an array');
|
||||
|
||||
var context = {multiplier: 3};
|
||||
sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num * this.multiplier; }, 0, context);
|
||||
assert.equal(sum, 18, 'can reduce with a context object');
|
||||
|
||||
sum = _([1, 2, 3]).reduce(function(memo, num){ return memo + num; }, 0);
|
||||
assert.equal(sum, 6, 'OO-style reduce');
|
||||
|
||||
sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; });
|
||||
assert.equal(sum, 6, 'default initial value');
|
||||
|
||||
var prod = _.reduce([1, 2, 3, 4], function(memo, num){ return memo * num; });
|
||||
assert.equal(prod, 24, 'can reduce via multiplication');
|
||||
|
||||
assert.ok(_.reduce(null, _.noop, 138) === 138, 'handles a null (with initial value) properly');
|
||||
assert.equal(_.reduce([], _.noop, void 0), void 0, 'undefined can be passed as a special case');
|
||||
assert.equal(_.reduce([_], _.noop), _, 'collection of length one with no initial value returns the first item');
|
||||
assert.equal(_.reduce([], _.noop), void 0, 'returns undefined when collection is empty and no initial value');
|
||||
});
|
||||
|
||||
QUnit.test('foldl', function(assert) {
|
||||
assert.strictEqual(_.foldl, _.reduce, 'is an alias for reduce');
|
||||
});
|
||||
|
||||
QUnit.test('inject', function(assert) {
|
||||
assert.strictEqual(_.inject, _.reduce, 'is an alias for reduce');
|
||||
});
|
||||
|
||||
QUnit.test('reduceRight', function(assert) {
|
||||
var list = _.reduceRight(['foo', 'bar', 'baz'], function(memo, str){ return memo + str; }, '');
|
||||
assert.equal(list, 'bazbarfoo', 'can perform right folds');
|
||||
|
||||
list = _.reduceRight(['foo', 'bar', 'baz'], function(memo, str){ return memo + str; });
|
||||
assert.equal(list, 'bazbarfoo', 'default initial value');
|
||||
|
||||
var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(memo, num){ return memo + num; });
|
||||
assert.equal(sum, 6, 'default initial value on object');
|
||||
|
||||
assert.ok(_.reduceRight(null, _.noop, 138) === 138, 'handles a null (with initial value) properly');
|
||||
assert.equal(_.reduceRight([_], _.noop), _, 'collection of length one with no initial value returns the first item');
|
||||
|
||||
assert.equal(_.reduceRight([], _.noop, void 0), void 0, 'undefined can be passed as a special case');
|
||||
assert.equal(_.reduceRight([], _.noop), void 0, 'returns undefined when collection is empty and no initial value');
|
||||
|
||||
// Assert that the correct arguments are being passed.
|
||||
|
||||
var args,
|
||||
init = {},
|
||||
object = {a: 1, b: 2},
|
||||
lastKey = _.keys(object).pop();
|
||||
|
||||
var expected = lastKey === 'a'
|
||||
? [init, 1, 'a', object]
|
||||
: [init, 2, 'b', object];
|
||||
|
||||
_.reduceRight(object, function() {
|
||||
if (!args) args = _.toArray(arguments);
|
||||
}, init);
|
||||
|
||||
assert.deepEqual(args, expected);
|
||||
|
||||
// And again, with numeric keys.
|
||||
|
||||
object = {2: 'a', 1: 'b'};
|
||||
lastKey = _.keys(object).pop();
|
||||
args = null;
|
||||
|
||||
expected = lastKey === '2'
|
||||
? [init, 'a', '2', object]
|
||||
: [init, 'b', '1', object];
|
||||
|
||||
_.reduceRight(object, function() {
|
||||
if (!args) args = _.toArray(arguments);
|
||||
}, init);
|
||||
|
||||
assert.deepEqual(args, expected);
|
||||
});
|
||||
|
||||
QUnit.test('foldr', function(assert) {
|
||||
assert.strictEqual(_.foldr, _.reduceRight, 'is an alias for reduceRight');
|
||||
});
|
||||
|
||||
QUnit.test('find', function(assert) {
|
||||
var array = [1, 2, 3, 4];
|
||||
assert.strictEqual(_.find(array, function(n) { return n > 2; }), 3, 'should return first found `value`');
|
||||
assert.strictEqual(_.find(array, function() { return false; }), void 0, 'should return `undefined` if `value` is not found');
|
||||
|
||||
array.dontmatch = 55;
|
||||
assert.strictEqual(_.find(array, function(x) { return x === 55; }), void 0, 'iterates array-likes correctly');
|
||||
|
||||
// Matching an object like _.findWhere.
|
||||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}];
|
||||
assert.deepEqual(_.find(list, {a: 1}), {a: 1, b: 2}, 'can be used as findWhere');
|
||||
assert.deepEqual(_.find(list, {b: 4}), {a: 1, b: 4});
|
||||
assert.ok(!_.find(list, {c: 1}), 'undefined when not found');
|
||||
assert.ok(!_.find([], {c: 1}), 'undefined when searching empty list');
|
||||
|
||||
var result = _.find([1, 2, 3], function(num){ return num * 2 === 4; });
|
||||
assert.equal(result, 2, 'found the first "2" and broke the loop');
|
||||
|
||||
var obj = {
|
||||
a: {x: 1, z: 3},
|
||||
b: {x: 2, z: 2},
|
||||
c: {x: 3, z: 4},
|
||||
d: {x: 4, z: 1}
|
||||
};
|
||||
|
||||
assert.deepEqual(_.find(obj, {x: 2}), {x: 2, z: 2}, 'works on objects');
|
||||
assert.deepEqual(_.find(obj, {x: 2, z: 1}), void 0);
|
||||
assert.deepEqual(_.find(obj, function(x) {
|
||||
return x.x === 4;
|
||||
}), {x: 4, z: 1});
|
||||
|
||||
_.findIndex([{a: 1}], function(a, key, o) {
|
||||
assert.equal(key, 0);
|
||||
assert.deepEqual(o, [{a: 1}]);
|
||||
assert.strictEqual(this, _, 'called with context');
|
||||
}, _);
|
||||
});
|
||||
|
||||
QUnit.test('detect', function(assert) {
|
||||
assert.strictEqual(_.detect, _.find, 'is an alias for find');
|
||||
});
|
||||
|
||||
QUnit.test('filter', function(assert) {
|
||||
var evenArray = [1, 2, 3, 4, 5, 6];
|
||||
var evenObject = {one: 1, two: 2, three: 3};
|
||||
var isEven = function(num){ return num % 2 === 0; };
|
||||
|
||||
assert.deepEqual(_.filter(evenArray, isEven), [2, 4, 6]);
|
||||
assert.deepEqual(_.filter(evenObject, isEven), [2], 'can filter objects');
|
||||
assert.deepEqual(_.filter([{}, evenObject, []], 'two'), [evenObject], 'predicate string map to object properties');
|
||||
|
||||
_.filter([1], function() {
|
||||
assert.equal(this, evenObject, 'given context');
|
||||
}, evenObject);
|
||||
|
||||
// Can be used like _.where.
|
||||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}];
|
||||
assert.deepEqual(_.filter(list, {a: 1}), [{a: 1, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]);
|
||||
assert.deepEqual(_.filter(list, {b: 2}), [{a: 1, b: 2}, {a: 2, b: 2}]);
|
||||
assert.deepEqual(_.filter(list, {}), list, 'Empty object accepts all items');
|
||||
assert.deepEqual(_(list).filter({}), list, 'OO-filter');
|
||||
});
|
||||
|
||||
QUnit.test('select', function(assert) {
|
||||
assert.strictEqual(_.select, _.filter, 'is an alias for filter');
|
||||
});
|
||||
|
||||
QUnit.test('reject', function(assert) {
|
||||
var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 === 0; });
|
||||
assert.deepEqual(odds, [1, 3, 5], 'rejected each even number');
|
||||
|
||||
var context = 'obj';
|
||||
|
||||
var evens = _.reject([1, 2, 3, 4, 5, 6], function(num){
|
||||
assert.equal(context, 'obj');
|
||||
return num % 2 !== 0;
|
||||
}, context);
|
||||
assert.deepEqual(evens, [2, 4, 6], 'rejected each odd number');
|
||||
|
||||
assert.deepEqual(_.reject([odds, {one: 1, two: 2, three: 3}], 'two'), [odds], 'predicate string map to object properties');
|
||||
|
||||
// Can be used like _.where.
|
||||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}];
|
||||
assert.deepEqual(_.reject(list, {a: 1}), [{a: 2, b: 2}]);
|
||||
assert.deepEqual(_.reject(list, {b: 2}), [{a: 1, b: 3}, {a: 1, b: 4}]);
|
||||
assert.deepEqual(_.reject(list, {}), [], 'Returns empty list given empty object');
|
||||
assert.deepEqual(_.reject(list, []), [], 'Returns empty list given empty array');
|
||||
});
|
||||
|
||||
QUnit.test('every', function(assert) {
|
||||
assert.ok(_.every([], _.identity), 'the empty set');
|
||||
assert.ok(_.every([true, true, true], _.identity), 'every true values');
|
||||
assert.ok(!_.every([true, false, true], _.identity), 'one false value');
|
||||
assert.ok(_.every([0, 10, 28], function(num){ return num % 2 === 0; }), 'even numbers');
|
||||
assert.ok(!_.every([0, 11, 28], function(num){ return num % 2 === 0; }), 'an odd number');
|
||||
assert.ok(_.every([1], _.identity) === true, 'cast to boolean - true');
|
||||
assert.ok(_.every([0], _.identity) === false, 'cast to boolean - false');
|
||||
assert.ok(!_.every([void 0, void 0, void 0], _.identity), 'works with arrays of undefined');
|
||||
|
||||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}];
|
||||
assert.ok(!_.every(list, {a: 1, b: 2}), 'Can be called with object');
|
||||
assert.ok(_.every(list, 'a'), 'String mapped to object property');
|
||||
|
||||
list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}];
|
||||
assert.ok(_.every(list, {b: 2}), 'Can be called with object');
|
||||
assert.ok(!_.every(list, 'c'), 'String mapped to object property');
|
||||
|
||||
assert.ok(_.every({a: 1, b: 2, c: 3, d: 4}, _.isNumber), 'takes objects');
|
||||
assert.ok(!_.every({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects');
|
||||
assert.ok(_.every(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works');
|
||||
assert.ok(!_.every(['a', 'b', 'c', 'd', 'f'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works');
|
||||
});
|
||||
|
||||
QUnit.test('all', function(assert) {
|
||||
assert.strictEqual(_.all, _.every, 'is an alias for every');
|
||||
});
|
||||
|
||||
QUnit.test('some', function(assert) {
|
||||
assert.ok(!_.some([]), 'the empty set');
|
||||
assert.ok(!_.some([false, false, false]), 'all false values');
|
||||
assert.ok(_.some([false, false, true]), 'one true value');
|
||||
assert.ok(_.some([null, 0, 'yes', false]), 'a string');
|
||||
assert.ok(!_.some([null, 0, '', false]), 'falsy values');
|
||||
assert.ok(!_.some([1, 11, 29], function(num){ return num % 2 === 0; }), 'all odd numbers');
|
||||
assert.ok(_.some([1, 10, 29], function(num){ return num % 2 === 0; }), 'an even number');
|
||||
assert.ok(_.some([1], _.identity) === true, 'cast to boolean - true');
|
||||
assert.ok(_.some([0], _.identity) === false, 'cast to boolean - false');
|
||||
assert.ok(_.some([false, false, true]));
|
||||
|
||||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}];
|
||||
assert.ok(!_.some(list, {a: 5, b: 2}), 'Can be called with object');
|
||||
assert.ok(_.some(list, 'a'), 'String mapped to object property');
|
||||
|
||||
list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}];
|
||||
assert.ok(_.some(list, {b: 2}), 'Can be called with object');
|
||||
assert.ok(!_.some(list, 'd'), 'String mapped to object property');
|
||||
|
||||
assert.ok(_.some({a: '1', b: '2', c: '3', d: '4', e: 6}, _.isNumber), 'takes objects');
|
||||
assert.ok(!_.some({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects');
|
||||
assert.ok(_.some(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works');
|
||||
assert.ok(!_.some(['x', 'y', 'z'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works');
|
||||
});
|
||||
|
||||
QUnit.test('any', function(assert) {
|
||||
assert.strictEqual(_.any, _.some, 'is an alias for some');
|
||||
});
|
||||
|
||||
QUnit.test('includes', function(assert) {
|
||||
_.each([null, void 0, 0, 1, NaN, {}, []], function(val) {
|
||||
assert.strictEqual(_.includes(val, 'hasOwnProperty'), false);
|
||||
});
|
||||
assert.strictEqual(_.includes([1, 2, 3], 2), true, 'two is in the array');
|
||||
assert.ok(!_.includes([1, 3, 9], 2), 'two is not in the array');
|
||||
|
||||
assert.strictEqual(_.includes([5, 4, 3, 2, 1], 5, true), true, 'doesn\'t delegate to binary search');
|
||||
|
||||
assert.ok(_.includes({moe: 1, larry: 3, curly: 9}, 3) === true, '_.includes on objects checks their values');
|
||||
assert.ok(_([1, 2, 3]).includes(2), 'OO-style includes');
|
||||
|
||||
var numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
|
||||
assert.strictEqual(_.includes(numbers, 1, 1), true, 'takes a fromIndex');
|
||||
assert.strictEqual(_.includes(numbers, 1, -1), false, 'takes a fromIndex');
|
||||
assert.strictEqual(_.includes(numbers, 1, -2), false, 'takes a fromIndex');
|
||||
assert.strictEqual(_.includes(numbers, 1, -3), true, 'takes a fromIndex');
|
||||
assert.strictEqual(_.includes(numbers, 1, 6), true, 'takes a fromIndex');
|
||||
assert.strictEqual(_.includes(numbers, 1, 7), false, 'takes a fromIndex');
|
||||
|
||||
assert.ok(_.every([1, 2, 3], _.partial(_.includes, numbers)), 'fromIndex is guarded');
|
||||
});
|
||||
|
||||
QUnit.test('include', function(assert) {
|
||||
assert.strictEqual(_.include, _.includes, 'is an alias for includes');
|
||||
});
|
||||
|
||||
QUnit.test('contains', function(assert) {
|
||||
assert.strictEqual(_.contains, _.includes, 'is an alias for includes');
|
||||
|
||||
});
|
||||
|
||||
QUnit.test('includes with NaN', function(assert) {
|
||||
assert.strictEqual(_.includes([1, 2, NaN, NaN], NaN), true, 'Expected [1, 2, NaN] to contain NaN');
|
||||
assert.strictEqual(_.includes([1, 2, Infinity], NaN), false, 'Expected [1, 2, NaN] to contain NaN');
|
||||
});
|
||||
|
||||
QUnit.test('includes with +- 0', function(assert) {
|
||||
_.each([-0, +0], function(val) {
|
||||
assert.strictEqual(_.includes([1, 2, val, val], val), true);
|
||||
assert.strictEqual(_.includes([1, 2, val, val], -val), true);
|
||||
assert.strictEqual(_.includes([-1, 1, 2], -val), false);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
QUnit.test('invoke', function(assert) {
|
||||
assert.expect(5);
|
||||
var list = [[5, 1, 7], [3, 2, 1]];
|
||||
var result = _.invoke(list, 'sort');
|
||||
assert.deepEqual(result[0], [1, 5, 7], 'first array sorted');
|
||||
assert.deepEqual(result[1], [1, 2, 3], 'second array sorted');
|
||||
|
||||
_.invoke([{
|
||||
method: function() {
|
||||
assert.deepEqual(_.toArray(arguments), [1, 2, 3], 'called with arguments');
|
||||
}
|
||||
}], 'method', 1, 2, 3);
|
||||
|
||||
assert.deepEqual(_.invoke([{a: null}, {}, {a: _.constant(1)}], 'a'), [null, void 0, 1], 'handles null & undefined');
|
||||
|
||||
assert.raises(function() {
|
||||
_.invoke([{a: 1}], 'a');
|
||||
}, TypeError, 'throws for non-functions');
|
||||
});
|
||||
|
||||
QUnit.test('invoke w/ function reference', function(assert) {
|
||||
var list = [[5, 1, 7], [3, 2, 1]];
|
||||
var result = _.invoke(list, Array.prototype.sort);
|
||||
assert.deepEqual(result[0], [1, 5, 7], 'first array sorted');
|
||||
assert.deepEqual(result[1], [1, 2, 3], 'second array sorted');
|
||||
|
||||
assert.deepEqual(_.invoke([1, 2, 3], function(a) {
|
||||
return a + this;
|
||||
}, 5), [6, 7, 8], 'receives params from invoke');
|
||||
});
|
||||
|
||||
// Relevant when using ClojureScript
|
||||
QUnit.test('invoke when strings have a call method', function(assert) {
|
||||
String.prototype.call = function() {
|
||||
return 42;
|
||||
};
|
||||
var list = [[5, 1, 7], [3, 2, 1]];
|
||||
var s = 'foo';
|
||||
assert.equal(s.call(), 42, 'call function exists');
|
||||
var result = _.invoke(list, 'sort');
|
||||
assert.deepEqual(result[0], [1, 5, 7], 'first array sorted');
|
||||
assert.deepEqual(result[1], [1, 2, 3], 'second array sorted');
|
||||
delete String.prototype.call;
|
||||
assert.equal(s.call, void 0, 'call function removed');
|
||||
});
|
||||
|
||||
QUnit.test('pluck', function(assert) {
|
||||
var people = [{name: 'moe', age: 30}, {name: 'curly', age: 50}];
|
||||
assert.deepEqual(_.pluck(people, 'name'), ['moe', 'curly'], 'pulls names out of objects');
|
||||
assert.deepEqual(_.pluck(people, 'address'), [void 0, void 0], 'missing properties are returned as undefined');
|
||||
//compat: most flexible handling of edge cases
|
||||
assert.deepEqual(_.pluck([{'[object Object]': 1}], {}), [1]);
|
||||
});
|
||||
|
||||
QUnit.test('where', function(assert) {
|
||||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}];
|
||||
var result = _.where(list, {a: 1});
|
||||
assert.equal(result.length, 3);
|
||||
assert.equal(result[result.length - 1].b, 4);
|
||||
result = _.where(list, {b: 2});
|
||||
assert.equal(result.length, 2);
|
||||
assert.equal(result[0].a, 1);
|
||||
result = _.where(list, {});
|
||||
assert.equal(result.length, list.length);
|
||||
|
||||
function test() {}
|
||||
test.map = _.map;
|
||||
assert.deepEqual(_.where([_, {a: 1, b: 2}, _], test), [_, _], 'checks properties given function');
|
||||
});
|
||||
|
||||
QUnit.test('findWhere', function(assert) {
|
||||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}];
|
||||
var result = _.findWhere(list, {a: 1});
|
||||
assert.deepEqual(result, {a: 1, b: 2});
|
||||
result = _.findWhere(list, {b: 4});
|
||||
assert.deepEqual(result, {a: 1, b: 4});
|
||||
|
||||
result = _.findWhere(list, {c: 1});
|
||||
assert.ok(_.isUndefined(result), 'undefined when not found');
|
||||
|
||||
result = _.findWhere([], {c: 1});
|
||||
assert.ok(_.isUndefined(result), 'undefined when searching empty list');
|
||||
|
||||
function test() {}
|
||||
test.map = _.map;
|
||||
assert.equal(_.findWhere([_, {a: 1, b: 2}, _], test), _, 'checks properties given function');
|
||||
|
||||
function TestClass() {
|
||||
this.y = 5;
|
||||
this.x = 'foo';
|
||||
}
|
||||
var expect = {c: 1, x: 'foo', y: 5};
|
||||
assert.deepEqual(_.findWhere([{y: 5, b: 6}, expect], new TestClass()), expect, 'uses class instance properties');
|
||||
});
|
||||
|
||||
QUnit.test('max', function(assert) {
|
||||
assert.equal(-Infinity, _.max(null), 'can handle null/undefined');
|
||||
assert.equal(-Infinity, _.max(void 0), 'can handle null/undefined');
|
||||
assert.equal(-Infinity, _.max(null, _.identity), 'can handle null/undefined');
|
||||
|
||||
assert.equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max');
|
||||
|
||||
var neg = _.max([1, 2, 3], function(num){ return -num; });
|
||||
assert.equal(neg, 1, 'can perform a computation-based max');
|
||||
|
||||
assert.equal(-Infinity, _.max({}), 'Maximum value of an empty object');
|
||||
assert.equal(-Infinity, _.max([]), 'Maximum value of an empty array');
|
||||
assert.equal(_.max({a: 'a'}), -Infinity, 'Maximum value of a non-numeric collection');
|
||||
|
||||
assert.equal(299999, _.max(_.range(1, 300000)), 'Maximum value of a too-big array');
|
||||
|
||||
assert.equal(3, _.max([1, 2, 3, 'test']), 'Finds correct max in array starting with num and containing a NaN');
|
||||
assert.equal(3, _.max(['test', 1, 2, 3]), 'Finds correct max in array starting with NaN');
|
||||
|
||||
assert.equal(3, _.max([1, 2, 3, null]), 'Finds correct max in array starting with num and containing a `null`');
|
||||
assert.equal(3, _.max([null, 1, 2, 3]), 'Finds correct max in array starting with a `null`');
|
||||
|
||||
assert.equal(3, _.max([1, 2, 3, '']), 'Finds correct max in array starting with num and containing an empty string');
|
||||
assert.equal(3, _.max(['', 1, 2, 3]), 'Finds correct max in array starting with an empty string');
|
||||
|
||||
assert.equal(3, _.max([1, 2, 3, false]), 'Finds correct max in array starting with num and containing a false');
|
||||
assert.equal(3, _.max([false, 1, 2, 3]), 'Finds correct max in array starting with a false');
|
||||
|
||||
assert.equal(4, _.max([0, 1, 2, 3, 4]), 'Finds correct max in array containing a zero');
|
||||
assert.equal(0, _.max([-3, -2, -1, 0]), 'Finds correct max in array containing negative numbers');
|
||||
|
||||
assert.deepEqual([3, 6], _.map([[1, 2, 3], [4, 5, 6]], _.max), 'Finds correct max in array when mapping through multiple arrays');
|
||||
|
||||
var a = {x: -Infinity};
|
||||
var b = {x: -Infinity};
|
||||
var iterator = function(o){ return o.x; };
|
||||
assert.equal(_.max([a, b], iterator), a, 'Respects iterator return value of -Infinity');
|
||||
|
||||
assert.deepEqual(_.max([{a: 1}, {a: 0, b: 3}, {a: 4}, {a: 2}], 'a'), {a: 4}, 'String keys use property iterator');
|
||||
|
||||
assert.deepEqual(_.max([0, 2], function(c){ return c * this.x; }, {x: 1}), 2, 'Iterator context');
|
||||
assert.deepEqual(_.max([[1], [2, 3], [-1, 4], [5]], 0), [5], 'Lookup falsy iterator');
|
||||
assert.deepEqual(_.max([{0: 1}, {0: 2}, {0: -1}, {a: 1}], 0), {0: 2}, 'Lookup falsy iterator');
|
||||
});
|
||||
|
||||
QUnit.test('min', function(assert) {
|
||||
assert.equal(Infinity, _.min(null), 'can handle null/undefined');
|
||||
assert.equal(Infinity, _.min(void 0), 'can handle null/undefined');
|
||||
assert.equal(Infinity, _.min(null, _.identity), 'can handle null/undefined');
|
||||
|
||||
assert.equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min');
|
||||
|
||||
var neg = _.min([1, 2, 3], function(num){ return -num; });
|
||||
assert.equal(neg, 3, 'can perform a computation-based min');
|
||||
|
||||
assert.equal(Infinity, _.min({}), 'Minimum value of an empty object');
|
||||
assert.equal(Infinity, _.min([]), 'Minimum value of an empty array');
|
||||
assert.equal(_.min({a: 'a'}), Infinity, 'Minimum value of a non-numeric collection');
|
||||
|
||||
assert.deepEqual([1, 4], _.map([[1, 2, 3], [4, 5, 6]], _.min), 'Finds correct min in array when mapping through multiple arrays');
|
||||
|
||||
var now = new Date(9999999999);
|
||||
var then = new Date(0);
|
||||
assert.equal(_.min([now, then]), then);
|
||||
|
||||
assert.equal(1, _.min(_.range(1, 300000)), 'Minimum value of a too-big array');
|
||||
|
||||
assert.equal(1, _.min([1, 2, 3, 'test']), 'Finds correct min in array starting with num and containing a NaN');
|
||||
assert.equal(1, _.min(['test', 1, 2, 3]), 'Finds correct min in array starting with NaN');
|
||||
|
||||
assert.equal(1, _.min([1, 2, 3, null]), 'Finds correct min in array starting with num and containing a `null`');
|
||||
assert.equal(1, _.min([null, 1, 2, 3]), 'Finds correct min in array starting with a `null`');
|
||||
|
||||
assert.equal(0, _.min([0, 1, 2, 3, 4]), 'Finds correct min in array containing a zero');
|
||||
assert.equal(-3, _.min([-3, -2, -1, 0]), 'Finds correct min in array containing negative numbers');
|
||||
|
||||
var a = {x: Infinity};
|
||||
var b = {x: Infinity};
|
||||
var iterator = function(o){ return o.x; };
|
||||
assert.equal(_.min([a, b], iterator), a, 'Respects iterator return value of Infinity');
|
||||
|
||||
assert.deepEqual(_.min([{a: 1}, {a: 0, b: 3}, {a: 4}, {a: 2}], 'a'), {a: 0, b: 3}, 'String keys use property iterator');
|
||||
|
||||
assert.deepEqual(_.min([0, 2], function(c){ return c * this.x; }, {x: -1}), 2, 'Iterator context');
|
||||
assert.deepEqual(_.min([[1], [2, 3], [-1, 4], [5]], 0), [-1, 4], 'Lookup falsy iterator');
|
||||
assert.deepEqual(_.min([{0: 1}, {0: 2}, {0: -1}, {a: 1}], 0), {0: -1}, 'Lookup falsy iterator');
|
||||
});
|
||||
|
||||
QUnit.test('sortBy', function(assert) {
|
||||
var people = [{name: 'curly', age: 50}, {name: 'moe', age: 30}];
|
||||
people = _.sortBy(people, function(person){ return person.age; });
|
||||
assert.deepEqual(_.pluck(people, 'name'), ['moe', 'curly'], 'stooges sorted by age');
|
||||
|
||||
var list = [void 0, 4, 1, void 0, 3, 2];
|
||||
assert.deepEqual(_.sortBy(list, _.identity), [1, 2, 3, 4, void 0, void 0], 'sortBy with undefined values');
|
||||
|
||||
list = ['one', 'two', 'three', 'four', 'five'];
|
||||
var sorted = _.sortBy(list, 'length');
|
||||
assert.deepEqual(sorted, ['one', 'two', 'four', 'five', 'three'], 'sorted by length');
|
||||
|
||||
function Pair(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
var stableArray = [
|
||||
new Pair(1, 1), new Pair(1, 2),
|
||||
new Pair(1, 3), new Pair(1, 4),
|
||||
new Pair(1, 5), new Pair(1, 6),
|
||||
new Pair(2, 1), new Pair(2, 2),
|
||||
new Pair(2, 3), new Pair(2, 4),
|
||||
new Pair(2, 5), new Pair(2, 6),
|
||||
new Pair(void 0, 1), new Pair(void 0, 2),
|
||||
new Pair(void 0, 3), new Pair(void 0, 4),
|
||||
new Pair(void 0, 5), new Pair(void 0, 6)
|
||||
];
|
||||
|
||||
var stableObject = _.object('abcdefghijklmnopqr'.split(''), stableArray);
|
||||
|
||||
var actual = _.sortBy(stableArray, function(pair) {
|
||||
return pair.x;
|
||||
});
|
||||
|
||||
assert.deepEqual(actual, stableArray, 'sortBy should be stable for arrays');
|
||||
assert.deepEqual(_.sortBy(stableArray, 'x'), stableArray, 'sortBy accepts property string');
|
||||
|
||||
actual = _.sortBy(stableObject, function(pair) {
|
||||
return pair.x;
|
||||
});
|
||||
|
||||
assert.deepEqual(actual, stableArray, 'sortBy should be stable for objects');
|
||||
|
||||
list = ['q', 'w', 'e', 'r', 't', 'y'];
|
||||
assert.deepEqual(_.sortBy(list), ['e', 'q', 'r', 't', 'w', 'y'], 'uses _.identity if iterator is not specified');
|
||||
});
|
||||
|
||||
QUnit.test('groupBy', function(assert) {
|
||||
var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; });
|
||||
assert.ok('0' in parity && '1' in parity, 'created a group for each value');
|
||||
assert.deepEqual(parity[0], [2, 4, 6], 'put each even number in the right group');
|
||||
|
||||
var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
|
||||
var grouped = _.groupBy(list, 'length');
|
||||
assert.deepEqual(grouped['3'], ['one', 'two', 'six', 'ten']);
|
||||
assert.deepEqual(grouped['4'], ['four', 'five', 'nine']);
|
||||
assert.deepEqual(grouped['5'], ['three', 'seven', 'eight']);
|
||||
|
||||
var context = {};
|
||||
_.groupBy([{}], function(){ assert.ok(this === context); }, context);
|
||||
|
||||
grouped = _.groupBy([4.2, 6.1, 6.4], function(num) {
|
||||
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';
|
||||
});
|
||||
assert.equal(grouped.constructor.length, 1);
|
||||
assert.equal(grouped.hasOwnProperty.length, 2);
|
||||
|
||||
var array = [{}];
|
||||
_.groupBy(array, function(value, index, obj){ assert.ok(obj === array); });
|
||||
|
||||
array = [1, 2, 1, 2, 3];
|
||||
grouped = _.groupBy(array);
|
||||
assert.equal(grouped['1'].length, 2);
|
||||
assert.equal(grouped['3'].length, 1);
|
||||
|
||||
var matrix = [
|
||||
[1, 2],
|
||||
[1, 3],
|
||||
[2, 3]
|
||||
];
|
||||
assert.deepEqual(_.groupBy(matrix, 0), {1: [[1, 2], [1, 3]], 2: [[2, 3]]});
|
||||
assert.deepEqual(_.groupBy(matrix, 1), {2: [[1, 2]], 3: [[1, 3], [2, 3]]});
|
||||
});
|
||||
|
||||
QUnit.test('indexBy', function(assert) {
|
||||
var parity = _.indexBy([1, 2, 3, 4, 5], function(num){ return num % 2 === 0; });
|
||||
assert.equal(parity['true'], 4);
|
||||
assert.equal(parity['false'], 5);
|
||||
|
||||
var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
|
||||
var grouped = _.indexBy(list, 'length');
|
||||
assert.equal(grouped['3'], 'ten');
|
||||
assert.equal(grouped['4'], 'nine');
|
||||
assert.equal(grouped['5'], 'eight');
|
||||
|
||||
var array = [1, 2, 1, 2, 3];
|
||||
grouped = _.indexBy(array);
|
||||
assert.equal(grouped['1'], 1);
|
||||
assert.equal(grouped['2'], 2);
|
||||
assert.equal(grouped['3'], 3);
|
||||
});
|
||||
|
||||
QUnit.test('countBy', function(assert) {
|
||||
var parity = _.countBy([1, 2, 3, 4, 5], function(num){ return num % 2 === 0; });
|
||||
assert.equal(parity['true'], 2);
|
||||
assert.equal(parity['false'], 3);
|
||||
|
||||
var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
|
||||
var grouped = _.countBy(list, 'length');
|
||||
assert.equal(grouped['3'], 4);
|
||||
assert.equal(grouped['4'], 3);
|
||||
assert.equal(grouped['5'], 3);
|
||||
|
||||
var context = {};
|
||||
_.countBy([{}], function(){ assert.ok(this === context); }, context);
|
||||
|
||||
grouped = _.countBy([4.2, 6.1, 6.4], function(num) {
|
||||
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';
|
||||
});
|
||||
assert.equal(grouped.constructor, 1);
|
||||
assert.equal(grouped.hasOwnProperty, 2);
|
||||
|
||||
var array = [{}];
|
||||
_.countBy(array, function(value, index, obj){ assert.ok(obj === array); });
|
||||
|
||||
array = [1, 2, 1, 2, 3];
|
||||
grouped = _.countBy(array);
|
||||
assert.equal(grouped['1'], 2);
|
||||
assert.equal(grouped['3'], 1);
|
||||
});
|
||||
|
||||
QUnit.test('shuffle', function(assert) {
|
||||
assert.deepEqual(_.shuffle([1]), [1], 'behaves correctly on size 1 arrays');
|
||||
var numbers = _.range(20);
|
||||
var shuffled = _.shuffle(numbers);
|
||||
assert.notDeepEqual(numbers, shuffled, 'does change the order'); // Chance of false negative: 1 in ~2.4*10^18
|
||||
assert.notStrictEqual(numbers, shuffled, 'original object is unmodified');
|
||||
assert.deepEqual(numbers, _.sortBy(shuffled), 'contains the same members before and after shuffle');
|
||||
|
||||
shuffled = _.shuffle({a: 1, b: 2, c: 3, d: 4});
|
||||
assert.equal(shuffled.length, 4);
|
||||
assert.deepEqual(shuffled.sort(), [1, 2, 3, 4], 'works on objects');
|
||||
});
|
||||
|
||||
QUnit.test('sample', function(assert) {
|
||||
assert.strictEqual(_.sample([1]), 1, 'behaves correctly when no second parameter is given');
|
||||
assert.deepEqual(_.sample([1, 2, 3], -2), [], 'behaves correctly on negative n');
|
||||
var numbers = _.range(10);
|
||||
var allSampled = _.sample(numbers, 10).sort();
|
||||
assert.deepEqual(allSampled, numbers, 'contains the same members before and after sample');
|
||||
allSampled = _.sample(numbers, 20).sort();
|
||||
assert.deepEqual(allSampled, numbers, 'also works when sampling more objects than are present');
|
||||
assert.ok(_.contains(numbers, _.sample(numbers)), 'sampling a single element returns something from the array');
|
||||
assert.strictEqual(_.sample([]), void 0, 'sampling empty array with no number returns undefined');
|
||||
assert.notStrictEqual(_.sample([], 5), [], 'sampling empty array with a number returns an empty array');
|
||||
assert.notStrictEqual(_.sample([1, 2, 3], 0), [], 'sampling an array with 0 picks returns an empty array');
|
||||
assert.deepEqual(_.sample([1, 2], -1), [], 'sampling a negative number of picks returns an empty array');
|
||||
assert.ok(_.contains([1, 2, 3], _.sample({a: 1, b: 2, c: 3})), 'sample one value from an object');
|
||||
var partialSample = _.sample(_.range(1000), 10);
|
||||
var partialSampleSorted = partialSample.sort();
|
||||
assert.notDeepEqual(partialSampleSorted, _.range(10), 'samples from the whole array, not just the beginning');
|
||||
});
|
||||
|
||||
QUnit.test('toArray', function(assert) {
|
||||
assert.ok(!_.isArray(arguments), 'arguments object is not an array');
|
||||
assert.ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array');
|
||||
var a = [1, 2, 3];
|
||||
assert.ok(_.toArray(a) !== a, 'array is cloned');
|
||||
assert.deepEqual(_.toArray(a), [1, 2, 3], 'cloned array contains same elements');
|
||||
|
||||
var numbers = _.toArray({one: 1, two: 2, three: 3});
|
||||
assert.deepEqual(numbers, [1, 2, 3], 'object flattened into array');
|
||||
|
||||
var hearts = '\uD83D\uDC95';
|
||||
var pair = hearts.split('');
|
||||
var expected = [pair[0], hearts, '&', hearts, pair[1]];
|
||||
assert.deepEqual(_.toArray(expected.join('')), expected, 'maintains astral characters');
|
||||
assert.deepEqual(_.toArray(''), [], 'empty string into empty array');
|
||||
|
||||
if (typeof document != 'undefined') {
|
||||
// test in IE < 9
|
||||
var actual;
|
||||
try {
|
||||
actual = _.toArray(document.childNodes);
|
||||
} catch (e) { /* ignored */ }
|
||||
assert.deepEqual(actual, _.map(document.childNodes, _.identity), 'works on NodeList');
|
||||
}
|
||||
});
|
||||
|
||||
QUnit.test('size', function(assert) {
|
||||
assert.equal(_.size({one: 1, two: 2, three: 3}), 3, 'can compute the size of an object');
|
||||
assert.equal(_.size([1, 2, 3]), 3, 'can compute the size of an array');
|
||||
assert.equal(_.size({length: 3, 0: 0, 1: 0, 2: 0}), 3, 'can compute the size of Array-likes');
|
||||
|
||||
var func = function() {
|
||||
return _.size(arguments);
|
||||
};
|
||||
|
||||
assert.equal(func(1, 2, 3, 4), 4, 'can test the size of the arguments object');
|
||||
|
||||
assert.equal(_.size('hello'), 5, 'can compute the size of a string literal');
|
||||
assert.equal(_.size(new String('hello')), 5, 'can compute the size of string object');
|
||||
|
||||
assert.equal(_.size(null), 0, 'handles nulls');
|
||||
assert.equal(_.size(0), 0, 'handles numbers');
|
||||
});
|
||||
|
||||
QUnit.test('partition', function(assert) {
|
||||
var list = [0, 1, 2, 3, 4, 5];
|
||||
assert.deepEqual(_.partition(list, function(x) { return x < 4; }), [[0, 1, 2, 3], [4, 5]], 'handles bool return values');
|
||||
assert.deepEqual(_.partition(list, function(x) { return x & 1; }), [[1, 3, 5], [0, 2, 4]], 'handles 0 and 1 return values');
|
||||
assert.deepEqual(_.partition(list, function(x) { return x - 3; }), [[0, 1, 2, 4, 5], [3]], 'handles other numeric return values');
|
||||
assert.deepEqual(_.partition(list, function(x) { return x > 1 ? null : true; }), [[0, 1], [2, 3, 4, 5]], 'handles null return values');
|
||||
assert.deepEqual(_.partition(list, function(x) { if (x < 2) return true; }), [[0, 1], [2, 3, 4, 5]], 'handles undefined return values');
|
||||
assert.deepEqual(_.partition({a: 1, b: 2, c: 3}, function(x) { return x > 1; }), [[2, 3], [1]], 'handles objects');
|
||||
|
||||
assert.deepEqual(_.partition(list, function(x, index) { return index % 2; }), [[1, 3, 5], [0, 2, 4]], 'can reference the array index');
|
||||
assert.deepEqual(_.partition(list, function(x, index, arr) { return x === arr.length - 1; }), [[5], [0, 1, 2, 3, 4]], 'can reference the collection');
|
||||
|
||||
// Default iterator
|
||||
assert.deepEqual(_.partition([1, false, true, '']), [[1, true], [false, '']], 'Default iterator');
|
||||
assert.deepEqual(_.partition([{x: 1}, {x: 0}, {x: 1}], 'x'), [[{x: 1}, {x: 1}], [{x: 0}]], 'Takes a string');
|
||||
|
||||
// Context
|
||||
var predicate = function(x){ return x === this.x; };
|
||||
assert.deepEqual(_.partition([1, 2, 3], predicate, {x: 2}), [[2], [1, 3]], 'partition takes a context argument');
|
||||
|
||||
assert.deepEqual(_.partition([{a: 1}, {b: 2}, {a: 1, b: 2}], {a: 1}), [[{a: 1}, {a: 1, b: 2}], [{b: 2}]], 'predicate can be object');
|
||||
|
||||
var object = {a: 1};
|
||||
_.partition(object, function(val, key, obj) {
|
||||
assert.equal(val, 1);
|
||||
assert.equal(key, 'a');
|
||||
assert.equal(obj, object);
|
||||
assert.equal(this, predicate);
|
||||
}, predicate);
|
||||
});
|
||||
|
||||
if (typeof document != 'undefined') {
|
||||
QUnit.test('Can use various collection methods on NodeLists', function(assert) {
|
||||
var parent = document.createElement('div');
|
||||
parent.innerHTML = '<span id=id1></span>textnode<span id=id2></span>';
|
||||
|
||||
var elementChildren = _.filter(parent.childNodes, _.isElement);
|
||||
assert.equal(elementChildren.length, 2);
|
||||
|
||||
assert.deepEqual(_.map(elementChildren, 'id'), ['id1', 'id2']);
|
||||
assert.deepEqual(_.map(parent.childNodes, 'nodeType'), [1, 3, 1]);
|
||||
|
||||
assert.ok(!_.every(parent.childNodes, _.isElement));
|
||||
assert.ok(_.some(parent.childNodes, _.isElement));
|
||||
|
||||
function compareNode(node) {
|
||||
return _.isElement(node) ? node.id.charAt(2) : void 0;
|
||||
}
|
||||
assert.equal(_.max(parent.childNodes, compareNode), _.last(parent.childNodes));
|
||||
assert.equal(_.min(parent.childNodes, compareNode), _.first(parent.childNodes));
|
||||
});
|
||||
}
|
||||
|
||||
}());
|
141
app/bower_components/lodash/vendor/underscore/test/cross-document.js
vendored
Normal file
|
@ -0,0 +1,141 @@
|
|||
(function() {
|
||||
if (typeof document == 'undefined') return;
|
||||
|
||||
var _ = typeof require == 'function' ? require('..') : window._;
|
||||
|
||||
QUnit.module('Cross Document');
|
||||
/* global iObject, iElement, iArguments, iFunction, iArray, iError, iString, iNumber, iBoolean, iDate, iRegExp, iNaN, iNull, iUndefined, ActiveXObject */
|
||||
|
||||
// Setup remote variables for iFrame tests.
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.frameBorder = iframe.height = iframe.width = 0;
|
||||
document.body.appendChild(iframe);
|
||||
var iDoc = (iDoc = iframe.contentDocument || iframe.contentWindow).document || iDoc;
|
||||
iDoc.write(
|
||||
[
|
||||
'<script>',
|
||||
'parent.iElement = document.createElement("div");',
|
||||
'parent.iArguments = (function(){ return arguments; })(1, 2, 3);',
|
||||
'parent.iArray = [1, 2, 3];',
|
||||
'parent.iString = new String("hello");',
|
||||
'parent.iNumber = new Number(100);',
|
||||
'parent.iFunction = (function(){});',
|
||||
'parent.iDate = new Date();',
|
||||
'parent.iRegExp = /hi/;',
|
||||
'parent.iNaN = NaN;',
|
||||
'parent.iNull = null;',
|
||||
'parent.iBoolean = new Boolean(false);',
|
||||
'parent.iUndefined = undefined;',
|
||||
'parent.iObject = {};',
|
||||
'parent.iError = new Error();',
|
||||
'</script>'
|
||||
].join('\n')
|
||||
);
|
||||
iDoc.close();
|
||||
|
||||
QUnit.test('isEqual', function(assert) {
|
||||
|
||||
assert.ok(!_.isEqual(iNumber, 101));
|
||||
assert.ok(_.isEqual(iNumber, 100));
|
||||
|
||||
// Objects from another frame.
|
||||
assert.ok(_.isEqual({}, iObject), 'Objects with equivalent members created in different documents are equal');
|
||||
|
||||
// Array from another frame.
|
||||
assert.ok(_.isEqual([1, 2, 3], iArray), 'Arrays with equivalent elements created in different documents are equal');
|
||||
});
|
||||
|
||||
QUnit.test('isEmpty', function(assert) {
|
||||
assert.ok(!_([iNumber]).isEmpty(), '[1] is not empty');
|
||||
assert.ok(!_.isEmpty(iArray), '[] is empty');
|
||||
assert.ok(_.isEmpty(iObject), '{} is empty');
|
||||
});
|
||||
|
||||
QUnit.test('isElement', function(assert) {
|
||||
assert.ok(!_.isElement('div'), 'strings are not dom elements');
|
||||
assert.ok(_.isElement(document.body), 'the body tag is a DOM element');
|
||||
assert.ok(_.isElement(iElement), 'even from another frame');
|
||||
});
|
||||
|
||||
QUnit.test('isArguments', function(assert) {
|
||||
assert.ok(_.isArguments(iArguments), 'even from another frame');
|
||||
});
|
||||
|
||||
QUnit.test('isObject', function(assert) {
|
||||
assert.ok(_.isObject(iElement), 'even from another frame');
|
||||
assert.ok(_.isObject(iFunction), 'even from another frame');
|
||||
});
|
||||
|
||||
QUnit.test('isArray', function(assert) {
|
||||
assert.ok(_.isArray(iArray), 'even from another frame');
|
||||
});
|
||||
|
||||
QUnit.test('isString', function(assert) {
|
||||
assert.ok(_.isString(iString), 'even from another frame');
|
||||
});
|
||||
|
||||
QUnit.test('isNumber', function(assert) {
|
||||
assert.ok(_.isNumber(iNumber), 'even from another frame');
|
||||
});
|
||||
|
||||
QUnit.test('isBoolean', function(assert) {
|
||||
assert.ok(_.isBoolean(iBoolean), 'even from another frame');
|
||||
});
|
||||
|
||||
QUnit.test('isFunction', function(assert) {
|
||||
assert.ok(_.isFunction(iFunction), 'even from another frame');
|
||||
});
|
||||
|
||||
QUnit.test('isDate', function(assert) {
|
||||
assert.ok(_.isDate(iDate), 'even from another frame');
|
||||
});
|
||||
|
||||
QUnit.test('isRegExp', function(assert) {
|
||||
assert.ok(_.isRegExp(iRegExp), 'even from another frame');
|
||||
});
|
||||
|
||||
QUnit.test('isNaN', function(assert) {
|
||||
assert.ok(_.isNaN(iNaN), 'even from another frame');
|
||||
});
|
||||
|
||||
QUnit.test('isNull', function(assert) {
|
||||
assert.ok(_.isNull(iNull), 'even from another frame');
|
||||
});
|
||||
|
||||
QUnit.test('isUndefined', function(assert) {
|
||||
assert.ok(_.isUndefined(iUndefined), 'even from another frame');
|
||||
});
|
||||
|
||||
QUnit.test('isError', function(assert) {
|
||||
assert.ok(_.isError(iError), 'even from another frame');
|
||||
});
|
||||
|
||||
if (typeof ActiveXObject != 'undefined') {
|
||||
QUnit.test('IE host objects', function(assert) {
|
||||
var xml = new ActiveXObject('Msxml2.DOMDocument.3.0');
|
||||
assert.ok(!_.isNumber(xml));
|
||||
assert.ok(!_.isBoolean(xml));
|
||||
assert.ok(!_.isNaN(xml));
|
||||
assert.ok(!_.isFunction(xml));
|
||||
assert.ok(!_.isNull(xml));
|
||||
assert.ok(!_.isUndefined(xml));
|
||||
});
|
||||
|
||||
QUnit.test('#1621 IE 11 compat mode DOM elements are not functions', function(assert) {
|
||||
var fn = function() {};
|
||||
var xml = new ActiveXObject('Msxml2.DOMDocument.3.0');
|
||||
var div = document.createElement('div');
|
||||
|
||||
// JIT the function
|
||||
var count = 200;
|
||||
while (count--) {
|
||||
_.isFunction(fn);
|
||||
}
|
||||
|
||||
assert.equal(_.isFunction(xml), false);
|
||||
assert.equal(_.isFunction(div), false);
|
||||
assert.equal(_.isFunction(fn), true);
|
||||
});
|
||||
}
|
||||
|
||||
}());
|
728
app/bower_components/lodash/vendor/underscore/test/functions.js
vendored
Normal file
|
@ -0,0 +1,728 @@
|
|||
(function() {
|
||||
var _ = typeof require == 'function' ? require('..') : window._;
|
||||
|
||||
QUnit.module('Functions');
|
||||
QUnit.config.asyncRetries = 3;
|
||||
|
||||
QUnit.test('bind', function(assert) {
|
||||
var context = {name: 'moe'};
|
||||
var func = function(arg) { return 'name: ' + (this.name || arg); };
|
||||
var bound = _.bind(func, context);
|
||||
assert.equal(bound(), 'name: moe', 'can bind a function to a context');
|
||||
|
||||
bound = _(func).bind(context);
|
||||
assert.equal(bound(), 'name: moe', 'can do OO-style binding');
|
||||
|
||||
bound = _.bind(func, null, 'curly');
|
||||
var result = bound();
|
||||
// Work around a PhantomJS bug when applying a function with null|undefined.
|
||||
assert.ok(result === 'name: curly' || result === 'name: ' + window.name, 'can bind without specifying a context');
|
||||
|
||||
func = function(salutation, name) { return salutation + ': ' + name; };
|
||||
func = _.bind(func, this, 'hello');
|
||||
assert.equal(func('moe'), 'hello: moe', 'the function was partially applied in advance');
|
||||
|
||||
func = _.bind(func, this, 'curly');
|
||||
assert.equal(func(), 'hello: curly', 'the function was completely applied in advance');
|
||||
|
||||
func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; };
|
||||
func = _.bind(func, this, 'hello', 'moe', 'curly');
|
||||
assert.equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments');
|
||||
|
||||
func = function(ctx, message) { assert.equal(this, ctx, message); };
|
||||
_.bind(func, 0, 0, 'can bind a function to `0`')();
|
||||
_.bind(func, '', '', 'can bind a function to an empty string')();
|
||||
_.bind(func, false, false, 'can bind a function to `false`')();
|
||||
|
||||
// These tests are only meaningful when using a browser without a native bind function
|
||||
// To test this with a modern browser, set underscore's nativeBind to undefined
|
||||
var F = function() { return this; };
|
||||
var boundf = _.bind(F, {hello: 'moe curly'});
|
||||
var Boundf = boundf; // make eslint happy.
|
||||
var newBoundf = new Boundf();
|
||||
assert.equal(newBoundf.hello, void 0, 'function should not be bound to the context, to comply with ECMAScript 5');
|
||||
assert.equal(boundf().hello, 'moe curly', "When called without the new operator, it's OK to be bound to the context");
|
||||
assert.ok(newBoundf instanceof F, 'a bound instance is an instance of the original function');
|
||||
|
||||
assert.raises(function() { _.bind('notafunction'); }, TypeError, 'throws an error when binding to a non-function');
|
||||
});
|
||||
|
||||
QUnit.test('partial', function(assert) {
|
||||
var obj = {name: 'moe'};
|
||||
var func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); };
|
||||
|
||||
obj.func = _.partial(func, 'a', 'b');
|
||||
assert.equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply');
|
||||
|
||||
obj.func = _.partial(func, _, 'b', _, 'd');
|
||||
assert.equal(obj.func('a', 'c'), 'moe a b c d', 'can partially apply with placeholders');
|
||||
|
||||
func = _.partial(function() { return arguments.length; }, _, 'b', _, 'd');
|
||||
assert.equal(func('a', 'c', 'e'), 5, 'accepts more arguments than the number of placeholders');
|
||||
assert.equal(func('a'), 4, 'accepts fewer arguments than the number of placeholders');
|
||||
|
||||
func = _.partial(function() { return typeof arguments[2]; }, _, 'b', _, 'd');
|
||||
assert.equal(func('a'), 'undefined', 'unfilled placeholders are undefined');
|
||||
|
||||
// passes context
|
||||
function MyWidget(name, options) {
|
||||
this.name = name;
|
||||
this.options = options;
|
||||
}
|
||||
MyWidget.prototype.get = function() {
|
||||
return this.name;
|
||||
};
|
||||
var MyWidgetWithCoolOpts = _.partial(MyWidget, _, {a: 1});
|
||||
var widget = new MyWidgetWithCoolOpts('foo');
|
||||
assert.ok(widget instanceof MyWidget, 'Can partially bind a constructor');
|
||||
assert.equal(widget.get(), 'foo', 'keeps prototype');
|
||||
assert.deepEqual(widget.options, {a: 1});
|
||||
|
||||
_.partial.placeholder = obj;
|
||||
func = _.partial(function() { return arguments.length; }, obj, 'b', obj, 'd');
|
||||
assert.equal(func('a'), 4, 'allows the placeholder to be swapped out');
|
||||
|
||||
_.partial.placeholder = {};
|
||||
func = _.partial(function() { return arguments.length; }, obj, 'b', obj, 'd');
|
||||
assert.equal(func('a'), 5, 'swapping the placeholder preserves previously bound arguments');
|
||||
|
||||
_.partial.placeholder = _;
|
||||
});
|
||||
|
||||
QUnit.test('bindAll', function(assert) {
|
||||
var curly = {name: 'curly'};
|
||||
var moe = {
|
||||
name: 'moe',
|
||||
getName: function() { return 'name: ' + this.name; },
|
||||
sayHi: function() { return 'hi: ' + this.name; }
|
||||
};
|
||||
curly.getName = moe.getName;
|
||||
_.bindAll(moe, 'getName', 'sayHi');
|
||||
curly.sayHi = moe.sayHi;
|
||||
assert.equal(curly.getName(), 'name: curly', 'unbound function is bound to current object');
|
||||
assert.equal(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object');
|
||||
|
||||
curly = {name: 'curly'};
|
||||
moe = {
|
||||
name: 'moe',
|
||||
getName: function() { return 'name: ' + this.name; },
|
||||
sayHi: function() { return 'hi: ' + this.name; },
|
||||
sayLast: function() { return this.sayHi(_.last(arguments)); }
|
||||
};
|
||||
|
||||
assert.raises(function() { _.bindAll(moe); }, Error, 'throws an error for bindAll with no functions named');
|
||||
assert.raises(function() { _.bindAll(moe, 'sayBye'); }, TypeError, 'throws an error for bindAll if the given key is undefined');
|
||||
assert.raises(function() { _.bindAll(moe, 'name'); }, TypeError, 'throws an error for bindAll if the given key is not a function');
|
||||
|
||||
_.bindAll(moe, 'sayHi', 'sayLast');
|
||||
curly.sayHi = moe.sayHi;
|
||||
assert.equal(curly.sayHi(), 'hi: moe');
|
||||
|
||||
var sayLast = moe.sayLast;
|
||||
assert.equal(sayLast(1, 2, 3, 4, 5, 6, 7, 'Tom'), 'hi: moe', 'createCallback works with any number of arguments');
|
||||
|
||||
_.bindAll(moe, ['getName']);
|
||||
var getName = moe.getName;
|
||||
assert.equal(getName(), 'name: moe', 'flattens arguments into a single list');
|
||||
});
|
||||
|
||||
QUnit.test('memoize', function(assert) {
|
||||
var fib = function(n) {
|
||||
return n < 2 ? n : fib(n - 1) + fib(n - 2);
|
||||
};
|
||||
assert.equal(fib(10), 55, 'a memoized version of fibonacci produces identical results');
|
||||
fib = _.memoize(fib); // Redefine `fib` for memoization
|
||||
assert.equal(fib(10), 55, 'a memoized version of fibonacci produces identical results');
|
||||
|
||||
var o = function(str) {
|
||||
return str;
|
||||
};
|
||||
var fastO = _.memoize(o);
|
||||
assert.equal(o('toString'), 'toString', 'checks hasOwnProperty');
|
||||
assert.equal(fastO('toString'), 'toString', 'checks hasOwnProperty');
|
||||
|
||||
// Expose the cache.
|
||||
var upper = _.memoize(function(s) {
|
||||
return s.toUpperCase();
|
||||
});
|
||||
assert.equal(upper('foo'), 'FOO');
|
||||
assert.equal(upper('bar'), 'BAR');
|
||||
assert.deepEqual(upper.cache, {foo: 'FOO', bar: 'BAR'});
|
||||
upper.cache = {foo: 'BAR', bar: 'FOO'};
|
||||
assert.equal(upper('foo'), 'BAR');
|
||||
assert.equal(upper('bar'), 'FOO');
|
||||
|
||||
var hashed = _.memoize(function(key) {
|
||||
//https://github.com/jashkenas/underscore/pull/1679#discussion_r13736209
|
||||
assert.ok(/[a-z]+/.test(key), 'hasher doesn\'t change keys');
|
||||
return key;
|
||||
}, function(key) {
|
||||
return key.toUpperCase();
|
||||
});
|
||||
hashed('yep');
|
||||
assert.deepEqual(hashed.cache, {YEP: 'yep'}, 'takes a hasher');
|
||||
|
||||
// Test that the hash function can be used to swizzle the key.
|
||||
var objCacher = _.memoize(function(value, key) {
|
||||
return {key: key, value: value};
|
||||
}, function(value, key) {
|
||||
return key;
|
||||
});
|
||||
var myObj = objCacher('a', 'alpha');
|
||||
var myObjAlias = objCacher('b', 'alpha');
|
||||
assert.notStrictEqual(myObj, void 0, 'object is created if second argument used as key');
|
||||
assert.strictEqual(myObj, myObjAlias, 'object is cached if second argument used as key');
|
||||
assert.strictEqual(myObj.value, 'a', 'object is not modified if second argument used as key');
|
||||
});
|
||||
|
||||
QUnit.test('delay', function(assert) {
|
||||
assert.expect(2);
|
||||
var done = assert.async();
|
||||
var delayed = false;
|
||||
_.delay(function(){ delayed = true; }, 100);
|
||||
setTimeout(function(){ assert.ok(!delayed, "didn't delay the function quite yet"); }, 50);
|
||||
setTimeout(function(){ assert.ok(delayed, 'delayed the function'); done(); }, 150);
|
||||
});
|
||||
|
||||
QUnit.test('defer', function(assert) {
|
||||
assert.expect(1);
|
||||
var done = assert.async();
|
||||
var deferred = false;
|
||||
_.defer(function(bool){ deferred = bool; }, true);
|
||||
_.delay(function(){ assert.ok(deferred, 'deferred the function'); done(); }, 50);
|
||||
});
|
||||
|
||||
QUnit.test('throttle', function(assert) {
|
||||
assert.expect(2);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 32);
|
||||
throttledIncr(); throttledIncr();
|
||||
|
||||
assert.equal(counter, 1, 'incr was called immediately');
|
||||
_.delay(function(){ assert.equal(counter, 2, 'incr was throttled'); done(); }, 64);
|
||||
});
|
||||
|
||||
QUnit.test('throttle arguments', function(assert) {
|
||||
assert.expect(2);
|
||||
var done = assert.async();
|
||||
var value = 0;
|
||||
var update = function(val){ value = val; };
|
||||
var throttledUpdate = _.throttle(update, 32);
|
||||
throttledUpdate(1); throttledUpdate(2);
|
||||
_.delay(function(){ throttledUpdate(3); }, 64);
|
||||
assert.equal(value, 1, 'updated to latest value');
|
||||
_.delay(function(){ assert.equal(value, 3, 'updated to latest value'); done(); }, 96);
|
||||
});
|
||||
|
||||
QUnit.test('throttle once', function(assert) {
|
||||
assert.expect(2);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ return ++counter; };
|
||||
var throttledIncr = _.throttle(incr, 32);
|
||||
var result = throttledIncr();
|
||||
_.delay(function(){
|
||||
assert.equal(result, 1, 'throttled functions return their value');
|
||||
assert.equal(counter, 1, 'incr was called once'); done();
|
||||
}, 64);
|
||||
});
|
||||
|
||||
QUnit.test('throttle twice', function(assert) {
|
||||
assert.expect(1);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 32);
|
||||
throttledIncr(); throttledIncr();
|
||||
_.delay(function(){ assert.equal(counter, 2, 'incr was called twice'); done(); }, 64);
|
||||
});
|
||||
|
||||
QUnit.test('more throttling', function(assert) {
|
||||
assert.expect(3);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 30);
|
||||
throttledIncr(); throttledIncr();
|
||||
assert.equal(counter, 1);
|
||||
_.delay(function(){
|
||||
assert.equal(counter, 2);
|
||||
throttledIncr();
|
||||
assert.equal(counter, 3);
|
||||
done();
|
||||
}, 85);
|
||||
});
|
||||
|
||||
QUnit.test('throttle repeatedly with results', function(assert) {
|
||||
assert.expect(6);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ return ++counter; };
|
||||
var throttledIncr = _.throttle(incr, 100);
|
||||
var results = [];
|
||||
var saveResult = function() { results.push(throttledIncr()); };
|
||||
saveResult(); saveResult();
|
||||
_.delay(saveResult, 50);
|
||||
_.delay(saveResult, 150);
|
||||
_.delay(saveResult, 160);
|
||||
_.delay(saveResult, 230);
|
||||
_.delay(function() {
|
||||
assert.equal(results[0], 1, 'incr was called once');
|
||||
assert.equal(results[1], 1, 'incr was throttled');
|
||||
assert.equal(results[2], 1, 'incr was throttled');
|
||||
assert.equal(results[3], 2, 'incr was called twice');
|
||||
assert.equal(results[4], 2, 'incr was throttled');
|
||||
assert.equal(results[5], 3, 'incr was called trailing');
|
||||
done();
|
||||
}, 300);
|
||||
});
|
||||
|
||||
QUnit.test('throttle triggers trailing call when invoked repeatedly', function(assert) {
|
||||
assert.expect(2);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var limit = 48;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 32);
|
||||
|
||||
var stamp = new Date;
|
||||
while (new Date - stamp < limit) {
|
||||
throttledIncr();
|
||||
}
|
||||
var lastCount = counter;
|
||||
assert.ok(counter > 1);
|
||||
|
||||
_.delay(function() {
|
||||
assert.ok(counter > lastCount);
|
||||
done();
|
||||
}, 96);
|
||||
});
|
||||
|
||||
QUnit.test('throttle does not trigger leading call when leading is set to false', function(assert) {
|
||||
assert.expect(2);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 60, {leading: false});
|
||||
|
||||
throttledIncr(); throttledIncr();
|
||||
assert.equal(counter, 0);
|
||||
|
||||
_.delay(function() {
|
||||
assert.equal(counter, 1);
|
||||
done();
|
||||
}, 96);
|
||||
});
|
||||
|
||||
QUnit.test('more throttle does not trigger leading call when leading is set to false', function(assert) {
|
||||
assert.expect(3);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 100, {leading: false});
|
||||
|
||||
throttledIncr();
|
||||
_.delay(throttledIncr, 50);
|
||||
_.delay(throttledIncr, 60);
|
||||
_.delay(throttledIncr, 200);
|
||||
assert.equal(counter, 0);
|
||||
|
||||
_.delay(function() {
|
||||
assert.equal(counter, 1);
|
||||
}, 250);
|
||||
|
||||
_.delay(function() {
|
||||
assert.equal(counter, 2);
|
||||
done();
|
||||
}, 350);
|
||||
});
|
||||
|
||||
QUnit.test('one more throttle with leading: false test', function(assert) {
|
||||
assert.expect(2);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 100, {leading: false});
|
||||
|
||||
var time = new Date;
|
||||
while (new Date - time < 350) throttledIncr();
|
||||
assert.ok(counter <= 3);
|
||||
|
||||
_.delay(function() {
|
||||
assert.ok(counter <= 4);
|
||||
done();
|
||||
}, 200);
|
||||
});
|
||||
|
||||
QUnit.test('throttle does not trigger trailing call when trailing is set to false', function(assert) {
|
||||
assert.expect(4);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 60, {trailing: false});
|
||||
|
||||
throttledIncr(); throttledIncr(); throttledIncr();
|
||||
assert.equal(counter, 1);
|
||||
|
||||
_.delay(function() {
|
||||
assert.equal(counter, 1);
|
||||
|
||||
throttledIncr(); throttledIncr();
|
||||
assert.equal(counter, 2);
|
||||
|
||||
_.delay(function() {
|
||||
assert.equal(counter, 2);
|
||||
done();
|
||||
}, 96);
|
||||
}, 96);
|
||||
});
|
||||
|
||||
QUnit.test('throttle continues to function after system time is set backwards', function(assert) {
|
||||
assert.expect(2);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 100);
|
||||
var origNowFunc = _.now;
|
||||
|
||||
throttledIncr();
|
||||
assert.equal(counter, 1);
|
||||
_.now = function() {
|
||||
return new Date(2013, 0, 1, 1, 1, 1);
|
||||
};
|
||||
|
||||
_.delay(function() {
|
||||
throttledIncr();
|
||||
assert.equal(counter, 2);
|
||||
done();
|
||||
_.now = origNowFunc;
|
||||
}, 200);
|
||||
});
|
||||
|
||||
QUnit.test('throttle re-entrant', function(assert) {
|
||||
assert.expect(2);
|
||||
var done = assert.async();
|
||||
var sequence = [
|
||||
['b1', 'b2'],
|
||||
['c1', 'c2']
|
||||
];
|
||||
var value = '';
|
||||
var throttledAppend;
|
||||
var append = function(arg){
|
||||
value += this + arg;
|
||||
var args = sequence.pop();
|
||||
if (args) {
|
||||
throttledAppend.call(args[0], args[1]);
|
||||
}
|
||||
};
|
||||
throttledAppend = _.throttle(append, 32);
|
||||
throttledAppend.call('a1', 'a2');
|
||||
assert.equal(value, 'a1a2');
|
||||
_.delay(function(){
|
||||
assert.equal(value, 'a1a2c1c2b1b2', 'append was throttled successfully');
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
QUnit.test('throttle cancel', function(assert) {
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 32);
|
||||
throttledIncr();
|
||||
throttledIncr.cancel();
|
||||
throttledIncr();
|
||||
throttledIncr();
|
||||
|
||||
assert.equal(counter, 2, 'incr was called immediately');
|
||||
_.delay(function(){ assert.equal(counter, 3, 'incr was throttled'); done(); }, 64);
|
||||
});
|
||||
|
||||
QUnit.test('throttle cancel with leading: false', function(assert) {
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 32, {leading: false});
|
||||
throttledIncr();
|
||||
throttledIncr.cancel();
|
||||
|
||||
assert.equal(counter, 0, 'incr was throttled');
|
||||
_.delay(function(){ assert.equal(counter, 0, 'incr was throttled'); done(); }, 64);
|
||||
});
|
||||
|
||||
QUnit.test('debounce', function(assert) {
|
||||
assert.expect(1);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var debouncedIncr = _.debounce(incr, 32);
|
||||
debouncedIncr(); debouncedIncr();
|
||||
_.delay(debouncedIncr, 16);
|
||||
_.delay(function(){ assert.equal(counter, 1, 'incr was debounced'); done(); }, 96);
|
||||
});
|
||||
|
||||
QUnit.test('debounce cancel', function(assert) {
|
||||
assert.expect(1);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var debouncedIncr = _.debounce(incr, 32);
|
||||
debouncedIncr();
|
||||
debouncedIncr.cancel();
|
||||
_.delay(function(){ assert.equal(counter, 0, 'incr was not called'); done(); }, 96);
|
||||
});
|
||||
|
||||
QUnit.test('debounce asap', function(assert) {
|
||||
assert.expect(6);
|
||||
var done = assert.async();
|
||||
var a, b, c;
|
||||
var counter = 0;
|
||||
var incr = function(){ return ++counter; };
|
||||
var debouncedIncr = _.debounce(incr, 64, true);
|
||||
a = debouncedIncr();
|
||||
b = debouncedIncr();
|
||||
assert.equal(a, 1);
|
||||
assert.equal(b, 1);
|
||||
assert.equal(counter, 1, 'incr was called immediately');
|
||||
_.delay(debouncedIncr, 16);
|
||||
_.delay(debouncedIncr, 32);
|
||||
_.delay(debouncedIncr, 48);
|
||||
_.delay(function(){
|
||||
assert.equal(counter, 1, 'incr was debounced');
|
||||
c = debouncedIncr();
|
||||
assert.equal(c, 2);
|
||||
assert.equal(counter, 2, 'incr was called again');
|
||||
done();
|
||||
}, 128);
|
||||
});
|
||||
|
||||
QUnit.test('debounce asap cancel', function(assert) {
|
||||
assert.expect(4);
|
||||
var done = assert.async();
|
||||
var a, b;
|
||||
var counter = 0;
|
||||
var incr = function(){ return ++counter; };
|
||||
var debouncedIncr = _.debounce(incr, 64, true);
|
||||
a = debouncedIncr();
|
||||
debouncedIncr.cancel();
|
||||
b = debouncedIncr();
|
||||
assert.equal(a, 1);
|
||||
assert.equal(b, 2);
|
||||
assert.equal(counter, 2, 'incr was called immediately');
|
||||
_.delay(debouncedIncr, 16);
|
||||
_.delay(debouncedIncr, 32);
|
||||
_.delay(debouncedIncr, 48);
|
||||
_.delay(function(){ assert.equal(counter, 2, 'incr was debounced'); done(); }, 128);
|
||||
});
|
||||
|
||||
QUnit.test('debounce asap recursively', function(assert) {
|
||||
assert.expect(2);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var debouncedIncr = _.debounce(function(){
|
||||
counter++;
|
||||
if (counter < 10) debouncedIncr();
|
||||
}, 32, true);
|
||||
debouncedIncr();
|
||||
assert.equal(counter, 1, 'incr was called immediately');
|
||||
_.delay(function(){ assert.equal(counter, 1, 'incr was debounced'); done(); }, 96);
|
||||
});
|
||||
|
||||
QUnit.test('debounce after system time is set backwards', function(assert) {
|
||||
assert.expect(2);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var origNowFunc = _.now;
|
||||
var debouncedIncr = _.debounce(function(){
|
||||
counter++;
|
||||
}, 100, true);
|
||||
|
||||
debouncedIncr();
|
||||
assert.equal(counter, 1, 'incr was called immediately');
|
||||
|
||||
_.now = function() {
|
||||
return new Date(2013, 0, 1, 1, 1, 1);
|
||||
};
|
||||
|
||||
_.delay(function() {
|
||||
debouncedIncr();
|
||||
assert.equal(counter, 2, 'incr was debounced successfully');
|
||||
done();
|
||||
_.now = origNowFunc;
|
||||
}, 200);
|
||||
});
|
||||
|
||||
QUnit.test('debounce re-entrant', function(assert) {
|
||||
assert.expect(2);
|
||||
var done = assert.async();
|
||||
var sequence = [
|
||||
['b1', 'b2']
|
||||
];
|
||||
var value = '';
|
||||
var debouncedAppend;
|
||||
var append = function(arg){
|
||||
value += this + arg;
|
||||
var args = sequence.pop();
|
||||
if (args) {
|
||||
debouncedAppend.call(args[0], args[1]);
|
||||
}
|
||||
};
|
||||
debouncedAppend = _.debounce(append, 32);
|
||||
debouncedAppend.call('a1', 'a2');
|
||||
assert.equal(value, '');
|
||||
_.delay(function(){
|
||||
assert.equal(value, 'a1a2b1b2', 'append was debounced successfully');
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
QUnit.test('once', function(assert) {
|
||||
var num = 0;
|
||||
var increment = _.once(function(){ return ++num; });
|
||||
increment();
|
||||
increment();
|
||||
assert.equal(num, 1);
|
||||
|
||||
assert.equal(increment(), 1, 'stores a memo to the last value');
|
||||
});
|
||||
|
||||
QUnit.test('Recursive onced function.', function(assert) {
|
||||
assert.expect(1);
|
||||
var f = _.once(function(){
|
||||
assert.ok(true);
|
||||
f();
|
||||
});
|
||||
f();
|
||||
});
|
||||
|
||||
QUnit.test('wrap', function(assert) {
|
||||
var greet = function(name){ return 'hi: ' + name; };
|
||||
var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); });
|
||||
assert.equal(backwards('moe'), 'hi: moe eom', 'wrapped the salutation function');
|
||||
|
||||
var inner = function(){ return 'Hello '; };
|
||||
var obj = {name: 'Moe'};
|
||||
obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; });
|
||||
assert.equal(obj.hi(), 'Hello Moe');
|
||||
|
||||
var noop = function(){};
|
||||
var wrapped = _.wrap(noop, function(){ return Array.prototype.slice.call(arguments, 0); });
|
||||
var ret = wrapped(['whats', 'your'], 'vector', 'victor');
|
||||
assert.deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']);
|
||||
});
|
||||
|
||||
QUnit.test('negate', function(assert) {
|
||||
var isOdd = function(n){ return n & 1; };
|
||||
assert.equal(_.negate(isOdd)(2), true, 'should return the complement of the given function');
|
||||
assert.equal(_.negate(isOdd)(3), false, 'should return the complement of the given function');
|
||||
});
|
||||
|
||||
QUnit.test('compose', function(assert) {
|
||||
var greet = function(name){ return 'hi: ' + name; };
|
||||
var exclaim = function(sentence){ return sentence + '!'; };
|
||||
var composed = _.compose(exclaim, greet);
|
||||
assert.equal(composed('moe'), 'hi: moe!', 'can compose a function that takes another');
|
||||
|
||||
composed = _.compose(greet, exclaim);
|
||||
assert.equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative');
|
||||
|
||||
// f(g(h(x, y, z)))
|
||||
function h(x, y, z) {
|
||||
assert.equal(arguments.length, 3, 'First function called with multiple args');
|
||||
return z * y;
|
||||
}
|
||||
function g(x) {
|
||||
assert.equal(arguments.length, 1, 'Composed function is called with 1 argument');
|
||||
return x;
|
||||
}
|
||||
function f(x) {
|
||||
assert.equal(arguments.length, 1, 'Composed function is called with 1 argument');
|
||||
return x * 2;
|
||||
}
|
||||
composed = _.compose(f, g, h);
|
||||
assert.equal(composed(1, 2, 3), 12);
|
||||
});
|
||||
|
||||
QUnit.test('after', function(assert) {
|
||||
var testAfter = function(afterAmount, timesCalled) {
|
||||
var afterCalled = 0;
|
||||
var after = _.after(afterAmount, function() {
|
||||
afterCalled++;
|
||||
});
|
||||
while (timesCalled--) after();
|
||||
return afterCalled;
|
||||
};
|
||||
|
||||
assert.equal(testAfter(5, 5), 1, 'after(N) should fire after being called N times');
|
||||
assert.equal(testAfter(5, 4), 0, 'after(N) should not fire unless called N times');
|
||||
assert.equal(testAfter(0, 0), 0, 'after(0) should not fire immediately');
|
||||
assert.equal(testAfter(0, 1), 1, 'after(0) should fire when first invoked');
|
||||
});
|
||||
|
||||
QUnit.test('before', function(assert) {
|
||||
var testBefore = function(beforeAmount, timesCalled) {
|
||||
var beforeCalled = 0;
|
||||
var before = _.before(beforeAmount, function() { beforeCalled++; });
|
||||
while (timesCalled--) before();
|
||||
return beforeCalled;
|
||||
};
|
||||
|
||||
assert.equal(testBefore(5, 5), 4, 'before(N) should not fire after being called N times');
|
||||
assert.equal(testBefore(5, 4), 4, 'before(N) should fire before being called N times');
|
||||
assert.equal(testBefore(0, 0), 0, 'before(0) should not fire immediately');
|
||||
assert.equal(testBefore(0, 1), 0, 'before(0) should not fire when first invoked');
|
||||
|
||||
var context = {num: 0};
|
||||
var increment = _.before(3, function(){ return ++this.num; });
|
||||
_.times(10, increment, context);
|
||||
assert.equal(increment(), 2, 'stores a memo to the last value');
|
||||
assert.equal(context.num, 2, 'provides context');
|
||||
});
|
||||
|
||||
QUnit.test('iteratee', function(assert) {
|
||||
var identity = _.iteratee();
|
||||
assert.equal(identity, _.identity, '_.iteratee is exposed as an external function.');
|
||||
|
||||
function fn() {
|
||||
return arguments;
|
||||
}
|
||||
_.each([_.iteratee(fn), _.iteratee(fn, {})], function(cb) {
|
||||
assert.equal(cb().length, 0);
|
||||
assert.deepEqual(_.toArray(cb(1, 2, 3)), _.range(1, 4));
|
||||
assert.deepEqual(_.toArray(cb(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), _.range(1, 11));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
QUnit.test('restArgs', function(assert) {
|
||||
assert.expect(10);
|
||||
_.restArgs(function(a, args) {
|
||||
assert.strictEqual(a, 1);
|
||||
assert.deepEqual(args, [2, 3], 'collects rest arguments into an array');
|
||||
})(1, 2, 3);
|
||||
|
||||
_.restArgs(function(a, args) {
|
||||
assert.strictEqual(a, void 0);
|
||||
assert.deepEqual(args, [], 'passes empty array if there are not enough arguments');
|
||||
})();
|
||||
|
||||
_.restArgs(function(a, b, c, args) {
|
||||
assert.strictEqual(arguments.length, 4);
|
||||
assert.deepEqual(args, [4, 5], 'works on functions with many named parameters');
|
||||
})(1, 2, 3, 4, 5);
|
||||
|
||||
var obj = {};
|
||||
_.restArgs(function() {
|
||||
assert.strictEqual(this, obj, 'invokes function with this context');
|
||||
}).call(obj);
|
||||
|
||||
_.restArgs(function(array, iteratee, context) {
|
||||
assert.deepEqual(array, [1, 2, 3, 4], 'startIndex can be used manually specify index of rest parameter');
|
||||
assert.strictEqual(iteratee, void 0);
|
||||
assert.strictEqual(context, void 0);
|
||||
}, 0)(1, 2, 3, 4);
|
||||
});
|
||||
|
||||
}());
|
1102
app/bower_components/lodash/vendor/underscore/test/objects.js
vendored
Normal file
420
app/bower_components/lodash/vendor/underscore/test/utility.js
vendored
Normal file
|
@ -0,0 +1,420 @@
|
|||
(function() {
|
||||
var _ = typeof require == 'function' ? require('..') : window._;
|
||||
var templateSettings;
|
||||
|
||||
QUnit.module('Utility', {
|
||||
|
||||
beforeEach: function() {
|
||||
templateSettings = _.clone(_.templateSettings);
|
||||
},
|
||||
|
||||
afterEach: function() {
|
||||
_.templateSettings = templateSettings;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if (typeof this == 'object') {
|
||||
QUnit.test('noConflict', function(assert) {
|
||||
var underscore = _.noConflict();
|
||||
assert.equal(underscore.identity(1), 1);
|
||||
if (typeof require != 'function') {
|
||||
assert.equal(this._, void 0, 'global underscore is removed');
|
||||
this._ = underscore;
|
||||
} else if (typeof global !== 'undefined') {
|
||||
delete global._;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof require == 'function') {
|
||||
QUnit.test('noConflict (node vm)', function(assert) {
|
||||
assert.expect(2);
|
||||
var done = assert.async();
|
||||
var fs = require('fs');
|
||||
var vm = require('vm');
|
||||
var filename = __dirname + '/../underscore.js';
|
||||
fs.readFile(filename, function(err, content){
|
||||
var sandbox = vm.createScript(
|
||||
content + 'this.underscore = this._.noConflict();',
|
||||
filename
|
||||
);
|
||||
var context = {_: 'oldvalue'};
|
||||
sandbox.runInNewContext(context);
|
||||
assert.equal(context._, 'oldvalue');
|
||||
assert.equal(context.underscore.VERSION, _.VERSION);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
QUnit.test('#750 - Return _ instance.', function(assert) {
|
||||
assert.expect(2);
|
||||
var instance = _([]);
|
||||
assert.ok(_(instance) === instance);
|
||||
assert.ok(new _(instance) === instance);
|
||||
});
|
||||
|
||||
QUnit.test('identity', function(assert) {
|
||||
var stooge = {name: 'moe'};
|
||||
assert.equal(_.identity(stooge), stooge, 'stooge is the same as his identity');
|
||||
});
|
||||
|
||||
QUnit.test('constant', function(assert) {
|
||||
var stooge = {name: 'moe'};
|
||||
assert.equal(_.constant(stooge)(), stooge, 'should create a function that returns stooge');
|
||||
});
|
||||
|
||||
QUnit.test('noop', function(assert) {
|
||||
assert.strictEqual(_.noop('curly', 'larry', 'moe'), void 0, 'should always return undefined');
|
||||
});
|
||||
|
||||
QUnit.test('property', function(assert) {
|
||||
var stooge = {name: 'moe'};
|
||||
assert.equal(_.property('name')(stooge), 'moe', 'should return the property with the given name');
|
||||
assert.equal(_.property('name')(null), void 0, 'should return undefined for null values');
|
||||
assert.equal(_.property('name')(void 0), void 0, 'should return undefined for undefined values');
|
||||
});
|
||||
|
||||
QUnit.test('propertyOf', function(assert) {
|
||||
var stoogeRanks = _.propertyOf({curly: 2, moe: 1, larry: 3});
|
||||
assert.equal(stoogeRanks('curly'), 2, 'should return the property with the given name');
|
||||
assert.equal(stoogeRanks(null), void 0, 'should return undefined for null values');
|
||||
assert.equal(stoogeRanks(void 0), void 0, 'should return undefined for undefined values');
|
||||
|
||||
function MoreStooges() { this.shemp = 87; }
|
||||
MoreStooges.prototype = {curly: 2, moe: 1, larry: 3};
|
||||
var moreStoogeRanks = _.propertyOf(new MoreStooges());
|
||||
assert.equal(moreStoogeRanks('curly'), 2, 'should return properties from further up the prototype chain');
|
||||
|
||||
var nullPropertyOf = _.propertyOf(null);
|
||||
assert.equal(nullPropertyOf('curly'), void 0, 'should return undefined when obj is null');
|
||||
|
||||
var undefPropertyOf = _.propertyOf(void 0);
|
||||
assert.equal(undefPropertyOf('curly'), void 0, 'should return undefined when obj is undefined');
|
||||
});
|
||||
|
||||
QUnit.test('random', function(assert) {
|
||||
var array = _.range(1000);
|
||||
var min = Math.pow(2, 31);
|
||||
var max = Math.pow(2, 62);
|
||||
|
||||
assert.ok(_.every(array, function() {
|
||||
return _.random(min, max) >= min;
|
||||
}), 'should produce a random number greater than or equal to the minimum number');
|
||||
|
||||
assert.ok(_.some(array, function() {
|
||||
return _.random(Number.MAX_VALUE) > 0;
|
||||
}), 'should produce a random number when passed `Number.MAX_VALUE`');
|
||||
});
|
||||
|
||||
QUnit.test('now', function(assert) {
|
||||
var diff = _.now() - new Date().getTime();
|
||||
assert.ok(diff <= 0 && diff > -5, 'Produces the correct time in milliseconds');//within 5ms
|
||||
});
|
||||
|
||||
QUnit.test('uniqueId', function(assert) {
|
||||
var ids = [], i = 0;
|
||||
while (i++ < 100) ids.push(_.uniqueId());
|
||||
assert.equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
|
||||
});
|
||||
|
||||
QUnit.test('times', function(assert) {
|
||||
var vals = [];
|
||||
_.times(3, function(i) { vals.push(i); });
|
||||
assert.deepEqual(vals, [0, 1, 2], 'is 0 indexed');
|
||||
//
|
||||
vals = [];
|
||||
_(3).times(function(i) { vals.push(i); });
|
||||
assert.deepEqual(vals, [0, 1, 2], 'works as a wrapper');
|
||||
// collects return values
|
||||
assert.deepEqual([0, 1, 2], _.times(3, function(i) { return i; }), 'collects return values');
|
||||
|
||||
assert.deepEqual(_.times(0, _.identity), []);
|
||||
assert.deepEqual(_.times(-1, _.identity), []);
|
||||
assert.deepEqual(_.times(parseFloat('-Infinity'), _.identity), []);
|
||||
});
|
||||
|
||||
QUnit.test('mixin', function(assert) {
|
||||
_.mixin({
|
||||
myReverse: function(string) {
|
||||
return string.split('').reverse().join('');
|
||||
}
|
||||
});
|
||||
assert.equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _');
|
||||
assert.equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');
|
||||
});
|
||||
|
||||
QUnit.test('_.escape', function(assert) {
|
||||
assert.equal(_.escape(null), '');
|
||||
});
|
||||
|
||||
QUnit.test('_.unescape', function(assert) {
|
||||
var string = 'Curly & Moe';
|
||||
assert.equal(_.unescape(null), '');
|
||||
assert.equal(_.unescape(_.escape(string)), string);
|
||||
assert.equal(_.unescape(string), string, 'don\'t unescape unnecessarily');
|
||||
});
|
||||
|
||||
// Don't care what they escape them to just that they're escaped and can be unescaped
|
||||
QUnit.test('_.escape & unescape', function(assert) {
|
||||
// test & (&) seperately obviously
|
||||
var escapeCharacters = ['<', '>', '"', '\'', '`'];
|
||||
|
||||
_.each(escapeCharacters, function(escapeChar) {
|
||||
var s = 'a ' + escapeChar + ' string escaped';
|
||||
var e = _.escape(s);
|
||||
assert.notEqual(s, e, escapeChar + ' is escaped');
|
||||
assert.equal(s, _.unescape(e), escapeChar + ' can be unescaped');
|
||||
|
||||
s = 'a ' + escapeChar + escapeChar + escapeChar + 'some more string' + escapeChar;
|
||||
e = _.escape(s);
|
||||
|
||||
assert.equal(e.indexOf(escapeChar), -1, 'can escape multiple occurances of ' + escapeChar);
|
||||
assert.equal(_.unescape(e), s, 'multiple occurrences of ' + escapeChar + ' can be unescaped');
|
||||
});
|
||||
|
||||
// handles multiple escape characters at once
|
||||
var joiner = ' other stuff ';
|
||||
var allEscaped = escapeCharacters.join(joiner);
|
||||
allEscaped += allEscaped;
|
||||
assert.ok(_.every(escapeCharacters, function(escapeChar) {
|
||||
return allEscaped.indexOf(escapeChar) !== -1;
|
||||
}), 'handles multiple characters');
|
||||
assert.ok(allEscaped.indexOf(joiner) >= 0, 'can escape multiple escape characters at the same time');
|
||||
|
||||
// test & -> &
|
||||
var str = 'some string & another string & yet another';
|
||||
var escaped = _.escape(str);
|
||||
|
||||
assert.ok(escaped.indexOf('&') !== -1, 'handles & aka &');
|
||||
assert.equal(_.unescape(str), str, 'can unescape &');
|
||||
});
|
||||
|
||||
QUnit.test('template', function(assert) {
|
||||
var basicTemplate = _.template("<%= thing %> is gettin' on my noives!");
|
||||
var result = basicTemplate({thing: 'This'});
|
||||
assert.equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation');
|
||||
|
||||
var sansSemicolonTemplate = _.template('A <% this %> B');
|
||||
assert.equal(sansSemicolonTemplate(), 'A B');
|
||||
|
||||
var backslashTemplate = _.template('<%= thing %> is \\ridanculous');
|
||||
assert.equal(backslashTemplate({thing: 'This'}), 'This is \\ridanculous');
|
||||
|
||||
var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>');
|
||||
assert.equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.');
|
||||
|
||||
var fancyTemplate = _.template('<ul><% ' +
|
||||
' for (var key in people) { ' +
|
||||
'%><li><%= people[key] %></li><% } %></ul>');
|
||||
result = fancyTemplate({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}});
|
||||
assert.equal(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates');
|
||||
|
||||
var escapedCharsInJavascriptTemplate = _.template('<ul><% _.each(numbers.split("\\n"), function(item) { %><li><%= item %></li><% }) %></ul>');
|
||||
result = escapedCharsInJavascriptTemplate({numbers: 'one\ntwo\nthree\nfour'});
|
||||
assert.equal(result, '<ul><li>one</li><li>two</li><li>three</li><li>four</li></ul>', 'Can use escaped characters (e.g. \\n) in JavaScript');
|
||||
|
||||
var namespaceCollisionTemplate = _.template('<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %><div class="thumbnail" rel="<%= p %>"></div><% }); %>');
|
||||
result = namespaceCollisionTemplate({
|
||||
pageCount: 3,
|
||||
thumbnails: {
|
||||
1: 'p1-thumbnail.gif',
|
||||
2: 'p2-thumbnail.gif',
|
||||
3: 'p3-thumbnail.gif'
|
||||
}
|
||||
});
|
||||
assert.equal(result, '3 p3-thumbnail.gif <div class="thumbnail" rel="p1-thumbnail.gif"></div><div class="thumbnail" rel="p2-thumbnail.gif"></div><div class="thumbnail" rel="p3-thumbnail.gif"></div>');
|
||||
|
||||
var noInterpolateTemplate = _.template('<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>');
|
||||
result = noInterpolateTemplate();
|
||||
assert.equal(result, '<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>');
|
||||
|
||||
var quoteTemplate = _.template("It's its, not it's");
|
||||
assert.equal(quoteTemplate({}), "It's its, not it's");
|
||||
|
||||
var quoteInStatementAndBody = _.template('<% ' +
|
||||
" if(foo == 'bar'){ " +
|
||||
"%>Statement quotes and 'quotes'.<% } %>");
|
||||
assert.equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
|
||||
|
||||
var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.');
|
||||
assert.equal(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.');
|
||||
|
||||
var template = _.template('<i><%- value %></i>');
|
||||
result = template({value: '<script>'});
|
||||
assert.equal(result, '<i><script></i>');
|
||||
|
||||
var stooge = {
|
||||
name: 'Moe',
|
||||
template: _.template("I'm <%= this.name %>")
|
||||
};
|
||||
assert.equal(stooge.template(), "I'm Moe");
|
||||
|
||||
template = _.template('\n ' +
|
||||
' <%\n ' +
|
||||
' // a comment\n ' +
|
||||
' if (data) { data += 12345; }; %>\n ' +
|
||||
' <li><%= data %></li>\n '
|
||||
);
|
||||
assert.equal(template({data: 12345}).replace(/\s/g, ''), '<li>24690</li>');
|
||||
|
||||
_.templateSettings = {
|
||||
evaluate: /\{\{([\s\S]+?)\}\}/g,
|
||||
interpolate: /\{\{=([\s\S]+?)\}\}/g
|
||||
};
|
||||
|
||||
var custom = _.template('<ul>{{ for (var key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>');
|
||||
result = custom({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}});
|
||||
assert.equal(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates');
|
||||
|
||||
var customQuote = _.template("It's its, not it's");
|
||||
assert.equal(customQuote({}), "It's its, not it's");
|
||||
|
||||
quoteInStatementAndBody = _.template("{{ if(foo == 'bar'){ }}Statement quotes and 'quotes'.{{ } }}");
|
||||
assert.equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
|
||||
|
||||
_.templateSettings = {
|
||||
evaluate: /<\?([\s\S]+?)\?>/g,
|
||||
interpolate: /<\?=([\s\S]+?)\?>/g
|
||||
};
|
||||
|
||||
var customWithSpecialChars = _.template('<ul><? for (var key in people) { ?><li><?= people[key] ?></li><? } ?></ul>');
|
||||
result = customWithSpecialChars({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}});
|
||||
assert.equal(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates');
|
||||
|
||||
var customWithSpecialCharsQuote = _.template("It's its, not it's");
|
||||
assert.equal(customWithSpecialCharsQuote({}), "It's its, not it's");
|
||||
|
||||
quoteInStatementAndBody = _.template("<? if(foo == 'bar'){ ?>Statement quotes and 'quotes'.<? } ?>");
|
||||
assert.equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
|
||||
|
||||
_.templateSettings = {
|
||||
interpolate: /\{\{(.+?)\}\}/g
|
||||
};
|
||||
|
||||
var mustache = _.template('Hello {{planet}}!');
|
||||
assert.equal(mustache({planet: 'World'}), 'Hello World!', 'can mimic mustache.js');
|
||||
|
||||
var templateWithNull = _.template('a null undefined {{planet}}');
|
||||
assert.equal(templateWithNull({planet: 'world'}), 'a null undefined world', 'can handle missing escape and evaluate settings');
|
||||
});
|
||||
|
||||
QUnit.test('_.template provides the generated function source, when a SyntaxError occurs', function(assert) {
|
||||
var source;
|
||||
try {
|
||||
_.template('<b><%= if x %></b>');
|
||||
} catch (ex) {
|
||||
source = ex.source;
|
||||
}
|
||||
assert.ok(/__p/.test(source));
|
||||
});
|
||||
|
||||
QUnit.test('_.template handles \\u2028 & \\u2029', function(assert) {
|
||||
var tmpl = _.template('<p>\u2028<%= "\\u2028\\u2029" %>\u2029</p>');
|
||||
assert.strictEqual(tmpl(), '<p>\u2028\u2028\u2029\u2029</p>');
|
||||
});
|
||||
|
||||
QUnit.test('result calls functions and returns primitives', function(assert) {
|
||||
var obj = {w: '', x: 'x', y: function(){ return this.x; }};
|
||||
assert.strictEqual(_.result(obj, 'w'), '');
|
||||
assert.strictEqual(_.result(obj, 'x'), 'x');
|
||||
assert.strictEqual(_.result(obj, 'y'), 'x');
|
||||
assert.strictEqual(_.result(obj, 'z'), void 0);
|
||||
assert.strictEqual(_.result(null, 'x'), void 0);
|
||||
});
|
||||
|
||||
QUnit.test('result returns a default value if object is null or undefined', function(assert) {
|
||||
assert.strictEqual(_.result(null, 'b', 'default'), 'default');
|
||||
assert.strictEqual(_.result(void 0, 'c', 'default'), 'default');
|
||||
assert.strictEqual(_.result(''.match('missing'), 1, 'default'), 'default');
|
||||
});
|
||||
|
||||
QUnit.test('result returns a default value if property of object is missing', function(assert) {
|
||||
assert.strictEqual(_.result({d: null}, 'd', 'default'), null);
|
||||
assert.strictEqual(_.result({e: false}, 'e', 'default'), false);
|
||||
});
|
||||
|
||||
QUnit.test('result only returns the default value if the object does not have the property or is undefined', function(assert) {
|
||||
assert.strictEqual(_.result({}, 'b', 'default'), 'default');
|
||||
assert.strictEqual(_.result({d: void 0}, 'd', 'default'), 'default');
|
||||
});
|
||||
|
||||
QUnit.test('result does not return the default if the property of an object is found in the prototype', function(assert) {
|
||||
var Foo = function(){};
|
||||
Foo.prototype.bar = 1;
|
||||
assert.strictEqual(_.result(new Foo, 'bar', 2), 1);
|
||||
});
|
||||
|
||||
QUnit.test('result does use the fallback when the result of invoking the property is undefined', function(assert) {
|
||||
var obj = {a: function() {}};
|
||||
assert.strictEqual(_.result(obj, 'a', 'failed'), void 0);
|
||||
});
|
||||
|
||||
QUnit.test('result fallback can use a function', function(assert) {
|
||||
var obj = {a: [1, 2, 3]};
|
||||
assert.strictEqual(_.result(obj, 'b', _.constant(5)), 5);
|
||||
assert.strictEqual(_.result(obj, 'b', function() {
|
||||
return this.a;
|
||||
}), obj.a, 'called with context');
|
||||
});
|
||||
|
||||
QUnit.test('_.templateSettings.variable', function(assert) {
|
||||
var s = '<%=data.x%>';
|
||||
var data = {x: 'x'};
|
||||
var tmp = _.template(s, {variable: 'data'});
|
||||
assert.strictEqual(tmp(data), 'x');
|
||||
_.templateSettings.variable = 'data';
|
||||
assert.strictEqual(_.template(s)(data), 'x');
|
||||
});
|
||||
|
||||
QUnit.test('#547 - _.templateSettings is unchanged by custom settings.', function(assert) {
|
||||
assert.ok(!_.templateSettings.variable);
|
||||
_.template('', {}, {variable: 'x'});
|
||||
assert.ok(!_.templateSettings.variable);
|
||||
});
|
||||
|
||||
QUnit.test('#556 - undefined template variables.', function(assert) {
|
||||
var template = _.template('<%=x%>');
|
||||
assert.strictEqual(template({x: null}), '');
|
||||
assert.strictEqual(template({x: void 0}), '');
|
||||
|
||||
var templateEscaped = _.template('<%-x%>');
|
||||
assert.strictEqual(templateEscaped({x: null}), '');
|
||||
assert.strictEqual(templateEscaped({x: void 0}), '');
|
||||
|
||||
var templateWithProperty = _.template('<%=x.foo%>');
|
||||
assert.strictEqual(templateWithProperty({x: {}}), '');
|
||||
assert.strictEqual(templateWithProperty({x: {}}), '');
|
||||
|
||||
var templateWithPropertyEscaped = _.template('<%-x.foo%>');
|
||||
assert.strictEqual(templateWithPropertyEscaped({x: {}}), '');
|
||||
assert.strictEqual(templateWithPropertyEscaped({x: {}}), '');
|
||||
});
|
||||
|
||||
QUnit.test('interpolate evaluates code only once.', function(assert) {
|
||||
assert.expect(2);
|
||||
var count = 0;
|
||||
var template = _.template('<%= f() %>');
|
||||
template({f: function(){ assert.ok(!count++); }});
|
||||
|
||||
var countEscaped = 0;
|
||||
var templateEscaped = _.template('<%- f() %>');
|
||||
templateEscaped({f: function(){ assert.ok(!countEscaped++); }});
|
||||
});
|
||||
|
||||
QUnit.test('#746 - _.template settings are not modified.', function(assert) {
|
||||
assert.expect(1);
|
||||
var settings = {};
|
||||
_.template('', null, settings);
|
||||
assert.deepEqual(settings, {});
|
||||
});
|
||||
|
||||
QUnit.test('#779 - delimeters are applied to unescaped text.', function(assert) {
|
||||
assert.expect(1);
|
||||
var template = _.template('<<\nx\n>>', null, {evaluate: /<<(.*?)>>/g});
|
||||
assert.strictEqual(template(), '<<\nx\n>>');
|
||||
});
|
||||
|
||||
}());
|