diff --git a/test/view.js b/test/view.js index 392a50f79..5a9644c4f 100644 --- a/test/view.js +++ b/test/view.js @@ -1,20 +1,12 @@ (function() { - - var view; - - module("Backbone.View", { - - setup: function() { - view = new Backbone.View({ - id : 'test-view', - className : 'test-view', - other : 'non-special-option' - }); - } - - }); + module("Backbone.View"); test("constructor", 3, function() { + var view = new Backbone.View({ + id : 'test-view', + className : 'test-view', + other : 'non-special-option' + }); equal(view.el.id, 'test-view'); equal(view.el.className, 'test-view'); equal(view.el.other, void 0); @@ -29,13 +21,15 @@ ok(result.length === +result.length); }); - test("$el", 3, function() { + test("$el", function() { var view = new Backbone.View; view.setElement('
'); strictEqual(view.el.nodeType, 1); - ok(view.$el instanceof Backbone.$); - strictEqual(view.$el[0], view.el); + if (Backbone.$) { + ok(view.$el instanceof Backbone.$); + strictEqual(view.$el[0], view.el); + } }); test("initialize", 1, function() { @@ -53,21 +47,21 @@ var view = new Backbone.View({el: '#testElement'}); view.increment = function(){ counter1++; }; - view.$el.on('click', function(){ counter2++; }); + addEventListener.call(view.el, 'click', function(){ counter2++; }); var events = {'click h1': 'increment'}; view.delegateEvents(events); - view.$('h1').trigger('click'); + click(view.$('h1')[0]); equal(counter1, 1); equal(counter2, 1); - view.$('h1').trigger('click'); + click(view.$('h1')[0]); equal(counter1, 2); equal(counter2, 2); view.delegateEvents(events); - view.$('h1').trigger('click'); + click(view.$('h1')[0]); equal(counter1, 3); equal(counter2, 3); }); @@ -80,7 +74,7 @@ view.delegate('click', function() { ok(true); }); - view.$('h1').trigger('click'); + click(view.$('h1')[0]); }); test("delegateEvents allows functions for callbacks", 3, function() { @@ -93,23 +87,31 @@ } }; + document.body.appendChild(view.el); + view.delegateEvents(events); - view.$el.trigger('click'); + click(view.el); equal(view.counter, 1); - view.$el.trigger('click'); + click(view.el); equal(view.counter, 2); view.delegateEvents(events); - view.$el.trigger('click'); + click(view.el); equal(view.counter, 3); - }); + document.body.removeChild(view.el); + }); test("delegateEvents ignore undefined methods", 0, function() { var view = new Backbone.View({el: ''}); + + document.body.appendChild(view.el); + view.delegateEvents({'click': 'undefinedMethod'}); - view.$el.trigger('click'); + click(view.el); + + document.body.removeChild(view.el); }); test("undelegateEvents", 6, function() { @@ -117,63 +119,63 @@ var view = new Backbone.View({el: '#testElement'}); view.increment = function(){ counter1++; }; - view.$el.on('click', function(){ counter2++; }); + addEventListener.call(view.el, 'click', function(){ counter2++; }); var events = {'click h1': 'increment'}; view.delegateEvents(events); - view.$('h1').trigger('click'); + click(view.$('h1')[0]); equal(counter1, 1); equal(counter2, 1); view.undelegateEvents(); - view.$('h1').trigger('click'); + click(view.$('h1')[0]); equal(counter1, 1); equal(counter2, 2); view.delegateEvents(events); - view.$('h1').trigger('click'); + click(view.$('h1')[0]); equal(counter1, 2); equal(counter2, 3); }); test("undelegate", 0, function() { - view = new Backbone.View({el: '#testElement'}); + var view = new Backbone.View({el: '#testElement'}); view.delegate('click', function() { ok(false); }); view.delegate('click', 'h1', function() { ok(false); }); view.undelegate('click'); - view.$('h1').trigger('click'); - view.$el.trigger('click'); + click(view.$('h1')[0]); + click(view.el); }); test("undelegate with passed handler", 1, function() { - view = new Backbone.View({el: '#testElement'}); + var view = new Backbone.View({el: '#testElement'}); var listener = function() { ok(false); }; view.delegate('click', listener); view.delegate('click', function() { ok(true); }); view.undelegate('click', listener); - view.$el.trigger('click'); + click(view.el); }); test("undelegate with selector", 2, function() { - view = new Backbone.View({el: '#testElement'}); + var view = new Backbone.View({el: '#testElement'}); view.delegate('click', function() { ok(true); }); view.delegate('click', 'h1', function() { ok(false); }); view.undelegate('click', 'h1'); - view.$('h1').trigger('click'); - view.$el.trigger('click'); + click(view.$('h1')[0]); + click(view.el); }); test("undelegate with handler and selector", 2, function() { - view = new Backbone.View({el: '#testElement'}); + var view = new Backbone.View({el: '#testElement'}); view.delegate('click', function() { ok(true); }); var handler = function(){ ok(false); }; view.delegate('click', 'h1', handler); view.undelegate('click', 'h1', handler); - view.$('h1').trigger('click'); - view.$el.trigger('click'); + click(view.$('h1')[0]); + click(view.el); }); test("tagName can be provided as a string", 1, function() { @@ -191,7 +193,7 @@ } }); - ok(new View().$el.is('p')); + equal(new View().el.tagName, 'P'); }); test("_ensureElement with DOM node el", 1, function() { @@ -211,7 +213,9 @@ View = Backbone.View.extend({ el: "#testElement > h1" }); - strictEqual(new View().el, $("#testElement > h1").get(0)); + var children = document.getElementById('testElement').childNodes; + var h1 = _.findWhere(children, {nodeType: 1}); + strictEqual(new View().el, h1); View = Backbone.View.extend({ el: "#nonexistent" @@ -257,10 +261,10 @@ test("multiple views per element", 3, function() { var count = 0; - var $el = $(''); + var el = document.createElement('p'); var View = Backbone.View.extend({ - el: $el, + el: el, events: { click: function() { count++; @@ -268,52 +272,64 @@ } }); + document.body.appendChild(el); + var view1 = new View; - $el.trigger("click"); + click(el); equal(1, count); var view2 = new View; - $el.trigger("click"); + click(el); equal(3, count); view1.delegateEvents(); - $el.trigger("click"); + click(el); equal(5, count); + + document.body.removeChild(el); }); - test("custom events", 2, function() { - var View = Backbone.View.extend({ - el: $('body'), - events: { - "fake$event": function() { ok(true); } - } - }); + if (Backbone.$) { + test("custom events", 1, function() { + var View = Backbone.View.extend({ + el: 'body', + events: function() { + return {"fake$event": "run"}; + }, + run: function() { + ok(true); + } + }); - var view = new View; - $('body').trigger('fake$event').trigger('fake$event'); + var view = new View; + Backbone.$('body').trigger('fake$event'); - $('body').off('fake$event'); - $('body').trigger('fake$event'); - }); + view.undelegate("fake$event"); + Backbone.$('body').trigger('fake$event'); + }); + } test("#1048 - setElement uses provided object.", 2, function() { - var $el = $('body'); + var el = document.body; - var view = new Backbone.View({el: $el}); - ok(view.$el === $el); + var view = new Backbone.View({el: el}); + ok(view.el === el); - view.setElement($el = $($el)); - ok(view.$el === $el); + view.setElement(el = document.body); + ok(view.el === el); }); test("#986 - Undelegate before changing element.", 1, function() { - var button1 = $(''); - var button2 = $(''); + var button1 = document.createElement('button'); + var button2 = document.createElement('button'); + + document.body.appendChild(button1); + document.body.appendChild(button2); var View = Backbone.View.extend({ events: { click: function(e) { - ok(view.el === e.target); + ok(view.el === e.target || e.srcElement); } } }); @@ -321,8 +337,11 @@ var view = new View({el: button1}); view.setElement(button2); - button1.trigger('click'); - button2.trigger('click'); + click(button1); + click(button2); + + document.body.removeChild(button1); + document.body.removeChild(button2); }); test("#1172 - Clone attributes object", 2, function() { @@ -363,8 +382,23 @@ }); var view = new View; - ok(view.$el.is('p')); - ok(view.$el.has('a')); + ok(view.el.tagName == 'P'); + ok(view.$('a').length != 0); + }); + + test("remove", 1, function() { + var view = new Backbone.View; + document.body.appendChild(view.el); + + view.delegate('click', function() { ok(false); }); + view.listenTo(view, 'all x', function() { ok(false); }); + + view.remove(); + click(view.el); + view.trigger('x'); + + // In IE8 and below, parentNode still exists but is not document.body. + notEqual(view.el.parentNode, document.body); }); test("events passed in options", 1, function() { @@ -383,23 +417,41 @@ } }); - view.$('h1').trigger('click').trigger('click'); + click(view.$('h1')[0]); + click(view.$('h1')[0]); equal(counter, 2); }); - test("remove", 1, function() { - var view = new Backbone.View; - document.body.appendChild(view.el); - - view.delegate('click', function() { ok(false); }); - view.listenTo(view, 'all x', function() { ok(false); }); - - view.remove(); - view.$el.trigger('click'); - view.trigger('x'); - - // In IE8 and below, parentNode still exists but is not document.body. - notEqual(view.el.parentNode, document.body); - }); + // Cross-browser helpers + var ElementProto = (typeof Element != 'undefined' && Element.prototype) || {}; + + var addEventListener = ElementProto.addEventListener || function(eventName, listener) { + return this.attachEvent('on' + eventName, listener); + }; + + function click(element) { + var event; + if (document.createEvent) { + event = document.createEvent('MouseEvent'); + var args = [ + 'click', true, true, + // IE 10+ and Firefox require these + event.view, event.detail, event.screenX, event.screenY, event.clientX, + event.clientY, event.ctrlKey, event.altKey, event.shiftKey, + event.metaKey, event.button, event.relatedTarget + ]; + (event.initMouseEvent || event.initEvent).apply(event, args); + } else { + event = document.createEventObject(); + event.type = 'click'; + event.bubbles = true; + event.cancelable = true; + } + if (element.dispatchEvent) { + element.dispatchEvent(event); + } else { + element.fireEvent(eventName, event); + } + } })();