5 QUnit.module('Backbone.View', {
7 beforeEach: function(assert) {
8 $('#qunit-fixture').append(
9 '<div id="testElement"><h1>Test</h1></div>'
12 view = new Backbone.View({
14 className: 'test-view',
15 other: 'non-special-option'
21 QUnit.test('constructor', function(assert) {
23 assert.equal(view.el.id, 'test-view');
24 assert.equal(view.el.className, 'test-view');
25 assert.equal(view.el.other, void 0);
28 QUnit.test('$', function(assert) {
30 var myView = new Backbone.View;
31 myView.setElement('<p><a><b>test</b></a></p>');
32 var result = myView.$('a b');
34 assert.strictEqual(result[0].innerHTML, 'test');
35 assert.ok(result.length === +result.length);
38 QUnit.test('$el', function(assert) {
40 var myView = new Backbone.View;
41 myView.setElement('<p><a><b>test</b></a></p>');
42 assert.strictEqual(myView.el.nodeType, 1);
44 assert.ok(myView.$el instanceof Backbone.$);
45 assert.strictEqual(myView.$el[0], myView.el);
48 QUnit.test('initialize', function(assert) {
50 var View = Backbone.View.extend({
51 initialize: function() {
56 assert.strictEqual(new View().one, 1);
59 QUnit.test('render', function(assert) {
61 var myView = new Backbone.View;
62 assert.equal(myView.render(), myView, '#render returns the view instance');
65 QUnit.test('delegateEvents', function(assert) {
67 var counter1 = 0, counter2 = 0;
69 var myView = new Backbone.View({el: '#testElement'});
70 myView.increment = function(){ counter1++; };
71 myView.$el.on('click', function(){ counter2++; });
73 var events = {'click h1': 'increment'};
75 myView.delegateEvents(events);
76 myView.$('h1').trigger('click');
77 assert.equal(counter1, 1);
78 assert.equal(counter2, 1);
80 myView.$('h1').trigger('click');
81 assert.equal(counter1, 2);
82 assert.equal(counter2, 2);
84 myView.delegateEvents(events);
85 myView.$('h1').trigger('click');
86 assert.equal(counter1, 3);
87 assert.equal(counter2, 3);
90 QUnit.test('delegate', function(assert) {
92 var myView = new Backbone.View({el: '#testElement'});
93 myView.delegate('click', 'h1', function() {
96 myView.delegate('click', function() {
99 myView.$('h1').trigger('click');
101 assert.equal(myView.delegate(), myView, '#delegate returns the view instance');
104 QUnit.test('delegateEvents allows functions for callbacks', function(assert) {
106 var myView = new Backbone.View({el: '<p></p>'});
115 myView.delegateEvents(events);
116 myView.$el.trigger('click');
117 assert.equal(myView.counter, 1);
119 myView.$el.trigger('click');
120 assert.equal(myView.counter, 2);
122 myView.delegateEvents(events);
123 myView.$el.trigger('click');
124 assert.equal(myView.counter, 3);
128 QUnit.test('delegateEvents ignore undefined methods', function(assert) {
130 var myView = new Backbone.View({el: '<p></p>'});
131 myView.delegateEvents({'click': 'undefinedMethod'});
132 myView.$el.trigger('click');
135 QUnit.test('undelegateEvents', function(assert) {
137 var counter1 = 0, counter2 = 0;
139 var myView = new Backbone.View({el: '#testElement'});
140 myView.increment = function(){ counter1++; };
141 myView.$el.on('click', function(){ counter2++; });
143 var events = {'click h1': 'increment'};
145 myView.delegateEvents(events);
146 myView.$('h1').trigger('click');
147 assert.equal(counter1, 1);
148 assert.equal(counter2, 1);
150 myView.undelegateEvents();
151 myView.$('h1').trigger('click');
152 assert.equal(counter1, 1);
153 assert.equal(counter2, 2);
155 myView.delegateEvents(events);
156 myView.$('h1').trigger('click');
157 assert.equal(counter1, 2);
158 assert.equal(counter2, 3);
160 assert.equal(myView.undelegateEvents(), myView, '#undelegateEvents returns the view instance');
163 QUnit.test('undelegate', function(assert) {
165 var myView = new Backbone.View({el: '#testElement'});
166 myView.delegate('click', function() { assert.ok(false); });
167 myView.delegate('click', 'h1', function() { assert.ok(false); });
169 myView.undelegate('click');
171 myView.$('h1').trigger('click');
172 myView.$el.trigger('click');
174 assert.equal(myView.undelegate(), myView, '#undelegate returns the view instance');
177 QUnit.test('undelegate with passed handler', function(assert) {
179 var myView = new Backbone.View({el: '#testElement'});
180 var listener = function() { assert.ok(false); };
181 myView.delegate('click', listener);
182 myView.delegate('click', function() { assert.ok(true); });
183 myView.undelegate('click', listener);
184 myView.$el.trigger('click');
187 QUnit.test('undelegate with selector', function(assert) {
189 var myView = new Backbone.View({el: '#testElement'});
190 myView.delegate('click', function() { assert.ok(true); });
191 myView.delegate('click', 'h1', function() { assert.ok(false); });
192 myView.undelegate('click', 'h1');
193 myView.$('h1').trigger('click');
194 myView.$el.trigger('click');
197 QUnit.test('undelegate with handler and selector', function(assert) {
199 var myView = new Backbone.View({el: '#testElement'});
200 myView.delegate('click', function() { assert.ok(true); });
201 var handler = function(){ assert.ok(false); };
202 myView.delegate('click', 'h1', handler);
203 myView.undelegate('click', 'h1', handler);
204 myView.$('h1').trigger('click');
205 myView.$el.trigger('click');
208 QUnit.test('tagName can be provided as a string', function(assert) {
210 var View = Backbone.View.extend({
214 assert.equal(new View().el.tagName, 'SPAN');
217 QUnit.test('tagName can be provided as a function', function(assert) {
219 var View = Backbone.View.extend({
220 tagName: function() {
225 assert.ok(new View().$el.is('p'));
228 QUnit.test('_ensureElement with DOM node el', function(assert) {
230 var View = Backbone.View.extend({
234 assert.equal(new View().el, document.body);
237 QUnit.test('_ensureElement with string el', function(assert) {
239 var View = Backbone.View.extend({
242 assert.strictEqual(new View().el, document.body);
244 View = Backbone.View.extend({
245 el: '#testElement > h1'
247 assert.strictEqual(new View().el, $('#testElement > h1').get(0));
249 View = Backbone.View.extend({
252 assert.ok(!new View().el);
255 QUnit.test('with className and id functions', function(assert) {
257 var View = Backbone.View.extend({
258 className: function() {
266 assert.strictEqual(new View().el.className, 'className');
267 assert.strictEqual(new View().el.id, 'id');
270 QUnit.test('with attributes', function(assert) {
272 var View = Backbone.View.extend({
279 assert.strictEqual(new View().el.className, 'class');
280 assert.strictEqual(new View().el.id, 'id');
283 QUnit.test('with attributes as a function', function(assert) {
285 var View = Backbone.View.extend({
286 attributes: function() {
287 return {'class': 'dynamic'};
291 assert.strictEqual(new View().el.className, 'dynamic');
294 QUnit.test('should default to className/id properties', function(assert) {
296 var View = Backbone.View.extend({
297 className: 'backboneClass',
300 'class': 'attributeClass',
305 var myView = new View;
306 assert.strictEqual(myView.el.className, 'backboneClass');
307 assert.strictEqual(myView.el.id, 'backboneId');
308 assert.strictEqual(myView.$el.attr('class'), 'backboneClass');
309 assert.strictEqual(myView.$el.attr('id'), 'backboneId');
312 QUnit.test('multiple views per element', function(assert) {
315 var $el = $('<p></p>');
317 var View = Backbone.View.extend({
326 var view1 = new View;
327 $el.trigger('click');
328 assert.equal(1, count);
330 var view2 = new View;
331 $el.trigger('click');
332 assert.equal(3, count);
334 view1.delegateEvents();
335 $el.trigger('click');
336 assert.equal(5, count);
339 QUnit.test('custom events', function(assert) {
341 var View = Backbone.View.extend({
344 fake$event: function() { assert.ok(true); }
348 var myView = new View;
349 $('body').trigger('fake$event').trigger('fake$event');
351 $('body').off('fake$event');
352 $('body').trigger('fake$event');
355 QUnit.test('#1048 - setElement uses provided object.', function(assert) {
359 var myView = new Backbone.View({el: $el});
360 assert.ok(myView.$el === $el);
362 myView.setElement($el = $($el));
363 assert.ok(myView.$el === $el);
366 QUnit.test('#986 - Undelegate before changing element.', function(assert) {
368 var button1 = $('<button></button>');
369 var button2 = $('<button></button>');
371 var View = Backbone.View.extend({
374 assert.ok(myView.el === e.target);
379 var myView = new View({el: button1});
380 myView.setElement(button2);
382 button1.trigger('click');
383 button2.trigger('click');
386 QUnit.test('#1172 - Clone attributes object', function(assert) {
388 var View = Backbone.View.extend({
389 attributes: {foo: 'bar'}
392 var view1 = new View({id: 'foo'});
393 assert.strictEqual(view1.el.id, 'foo');
395 var view2 = new View();
396 assert.ok(!view2.el.id);
399 QUnit.test('views stopListening', function(assert) {
401 var View = Backbone.View.extend({
402 initialize: function() {
403 this.listenTo(this.model, 'all x', function(){ assert.ok(false); });
404 this.listenTo(this.collection, 'all x', function(){ assert.ok(false); });
408 var myView = new View({
409 model: new Backbone.Model,
410 collection: new Backbone.Collection
413 myView.stopListening();
414 myView.model.trigger('x');
415 myView.collection.trigger('x');
418 QUnit.test('Provide function for el.', function(assert) {
420 var View = Backbone.View.extend({
422 return '<p><a></a></p>';
426 var myView = new View;
427 assert.ok(myView.$el.is('p'));
428 assert.ok(myView.$el.has('a'));
431 QUnit.test('events passed in options', function(assert) {
435 var View = Backbone.View.extend({
437 increment: function() {
442 var myView = new View({
444 'click h1': 'increment'
448 myView.$('h1').trigger('click').trigger('click');
449 assert.equal(counter, 2);
452 QUnit.test('remove', function(assert) {
454 var myView = new Backbone.View;
455 document.body.appendChild(view.el);
457 myView.delegate('click', function() { assert.ok(false); });
458 myView.listenTo(myView, 'all x', function() { assert.ok(false); });
460 assert.equal(myView.remove(), myView, '#remove returns the view instance');
461 myView.$el.trigger('click');
464 // In IE8 and below, parentNode still exists but is not document.body.
465 assert.notEqual(myView.el.parentNode, document.body);
468 QUnit.test('setElement', function(assert) {
470 var myView = new Backbone.View({
472 click: function() { assert.ok(false); }
476 click: function() { assert.ok(true); }
478 var oldEl = myView.el;
479 var $oldEl = myView.$el;
481 myView.setElement(document.createElement('div'));
486 assert.notEqual(oldEl, myView.el);
487 assert.notEqual($oldEl, myView.$el);