addEventListener and removeEventListener now works on the window for IE and Safari, and remove jQuery dependency in Router

This commit is contained in:
Jimmy Yuen Ho Wong
2014-01-17 13:22:54 +08:00
parent bf5a04d3f5
commit 0844b00cda
2 changed files with 37 additions and 28 deletions

View File

@@ -1015,21 +1015,21 @@
this.delegateEvents(); this.delegateEvents();
}; };
// Cross-platform `addEventListener`.
var addEventListener = function(obj, eventName, listener, useCapture) {
if (obj.addEventListener) return obj.addEventListener(eventName, listener, useCapture);
else return obj.attachEvent('on' + eventName, listener);
};
// Cross-platform `removeEventListener`.
var removeEventListener = function(obj, eventName, listener, useCapture) {
if (obj.removeEventListener) return obj.removeEventListener(eventName, listener, useCapture);
else return obj.detachEvent('on' + eventName, listener);
};
// Caches a local reference to `Element.prototype` for faster access. // Caches a local reference to `Element.prototype` for faster access.
var ElementProto = typeof Element != 'undefined' && Element.prototype; var ElementProto = typeof Element != 'undefined' && Element.prototype;
// IE8 `addEventListener` polyfill.
var addEventListener = ElementProto && ElementProto.addEventListener ||
function(eventName, listener) {
this.attachEvent('on' + eventName, listener);
};
// IE8 `removeEventListener` polyfill.
var removeEventListener = ElementProto && ElementProto.removeEventListener ||
function(eventName, listener) {
this.detachEvent('on' + eventName, listener);
};
// Find the right `Element#matches` for IE>=9 and modern browsers. // Find the right `Element#matches` for IE>=9 and modern browsers.
var matchesSelector = ElementProto && ElementProto.matches || var matchesSelector = ElementProto && ElementProto.matches ||
ElementProto[_.find(['webkit', 'moz', 'ms', 'o'], function(prefix) { ElementProto[_.find(['webkit', 'moz', 'ms', 'o'], function(prefix) {
@@ -1175,7 +1175,7 @@
} }
}; };
addEventListener.call(root, eventName, handler, false); addEventListener(root, eventName, handler, false);
domEvents.push({eventName: eventName, handler: handler}); domEvents.push({eventName: eventName, handler: handler});
}, },
@@ -1194,7 +1194,7 @@
if (el) { if (el) {
for (i = 0, l = domEvents.length; i < l; i++) { for (i = 0, l = domEvents.length; i < l; i++) {
item = domEvents[i]; item = domEvents[i];
removeEventListener.call(el, item.eventName, item.handler, false); removeEventListener(el, item.eventName, item.handler, false);
} }
this._domEvents = []; this._domEvents = [];
} }
@@ -1507,23 +1507,27 @@
this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState);
var fragment = this.getFragment(); var fragment = this.getFragment();
var docMode = document.documentMode; var docMode = document.documentMode;
var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7)); this._oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));
// Normalize root to always include a leading and trailing slash. // Normalize root to always include a leading and trailing slash.
this.root = ('/' + this.root + '/').replace(rootStripper, '/'); this.root = ('/' + this.root + '/').replace(rootStripper, '/');
if (oldIE && this._wantsHashChange) { if (this._oldIE && this._wantsHashChange) {
var frame = Backbone.$('<iframe src="javascript:0" tabindex="-1">'); var frame = document.createElement('iframe');
this.iframe = frame.hide().appendTo('body')[0].contentWindow; frame.src = 'javascript:0';
frame.tabIndex = -1;
frame.style.display = 'none';
document.body.appendChild(frame);
this.iframe = frame.contentWindow;
this.navigate(fragment); this.navigate(fragment);
} }
// Depending on whether we're using pushState or hashes, and whether // Depending on whether we're using pushState or hashes, and whether
// 'onhashchange' is supported, determine how we check the URL state. // 'onhashchange' is supported, determine how we check the URL state.
if (this._hasPushState) { if (this._hasPushState) {
Backbone.$(window).on('popstate', this.checkUrl); addEventListener(window, 'popstate', this.checkUrl);
} else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) { } else if (this._wantsHashChange && window.onhashchange && !this._oldIE) {
Backbone.$(window).on('hashchange', this.checkUrl); addEventListener(window, 'hashchange', this.checkUrl);
} else if (this._wantsHashChange) { } else if (this._wantsHashChange) {
this._checkUrlInterval = setInterval(this.checkUrl, this.interval); this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
} }
@@ -1560,7 +1564,11 @@
// Disable Backbone.history, perhaps temporarily. Not useful in a real app, // Disable Backbone.history, perhaps temporarily. Not useful in a real app,
// but possibly useful for unit testing Routers. // but possibly useful for unit testing Routers.
stop: function() { stop: function() {
Backbone.$(window).off('popstate', this.checkUrl).off('hashchange', this.checkUrl); if (this._hasPushState) {
removeEventListener(window, 'popstate', this.checkUrl);
} else if (this._wantsHashChange && window.onhashchange && !this._oldIE) {
removeEventListener(window, 'hashchange', this.checkUrl);
}
clearInterval(this._checkUrlInterval); clearInterval(this._checkUrlInterval);
History.started = false; History.started = false;
}, },

View File

@@ -1,10 +1,11 @@
(function() { (function() {
var view; var view;
var addEventListener = Element.prototype.addEventListener ||
function(eventName, listener) { var addEventListener = function(obj, eventName, listener, useCapture) {
this.attachEvent('on' + eventName, listener); if (obj.addEventListener) return obj.addEventListener(eventName, listener, useCapture);
}; else return obj.attachEvent('on' + eventName, listener);
};
function click(element) { function click(element) {
var event = SyntheticEvent('click', { var event = SyntheticEvent('click', {
@@ -56,7 +57,7 @@
var view = new Backbone.BaseView({el: '#testElement'}); var view = new Backbone.BaseView({el: '#testElement'});
view.increment = function(){ counter1++; }; view.increment = function(){ counter1++; };
addEventListener.call(view.el, 'click', function(){ counter2++; }); addEventListener(view.el, 'click', function(){ counter2++; });
var events = {'click h1': 'increment'}; var events = {'click h1': 'increment'};
@@ -109,7 +110,7 @@
var view = new Backbone.BaseView({el: '#testElement'}); var view = new Backbone.BaseView({el: '#testElement'});
view.increment = function(){ counter1++; }; view.increment = function(){ counter1++; };
addEventListener.call(view.el, 'click', function(){ counter2++; }); addEventListener(view.el, 'click', function(){ counter2++; });
var events = {'click h1': 'increment'}; var events = {'click h1': 'increment'};