mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-09 15:24:43 +00:00
feat(mouseenter/mouseleave): emulating ie events
This commit is contained in:
parent
cae9ad4ba9
commit
c8ee631c19
2 changed files with 115 additions and 39 deletions
110
src/jqLite.js
110
src/jqLite.js
|
|
@ -467,6 +467,50 @@ forEach({
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function createEventHandler(element) {
|
||||||
|
var eventHandler = function (event) {
|
||||||
|
if (!event.preventDefault) {
|
||||||
|
event.preventDefault = function() {
|
||||||
|
event.returnValue = false; //ie
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!event.stopPropagation) {
|
||||||
|
event.stopPropagation = function() {
|
||||||
|
event.cancelBubble = true; //ie
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!event.target) {
|
||||||
|
event.target = event.srcElement || document;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUndefined(event.defaultPrevented)) {
|
||||||
|
var prevent = event.preventDefault;
|
||||||
|
event.preventDefault = function() {
|
||||||
|
event.defaultPrevented = true;
|
||||||
|
prevent.call(event);
|
||||||
|
};
|
||||||
|
event.defaultPrevented = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.isDefaultPrevented = function() {
|
||||||
|
return event.defaultPrevented;
|
||||||
|
};
|
||||||
|
|
||||||
|
forEach(eventHandler.fns, function(fn){
|
||||||
|
fn.call(element, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove monkey-patched methods (IE),
|
||||||
|
// as they would cause memory leaks in IE8.
|
||||||
|
// It shouldn't affect normal browsers, as their native methods are defined on prototype.
|
||||||
|
delete event.preventDefault;
|
||||||
|
delete event.stopPropagation;
|
||||||
|
delete event.isDefaultPrevented;
|
||||||
|
};
|
||||||
|
eventHandler.fns = [];
|
||||||
|
return eventHandler;
|
||||||
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
// Functions iterating traversal.
|
// Functions iterating traversal.
|
||||||
// These functions chain results into a single
|
// These functions chain results into a single
|
||||||
|
|
@ -477,53 +521,41 @@ forEach({
|
||||||
|
|
||||||
dealoc: JQLiteDealoc,
|
dealoc: JQLiteDealoc,
|
||||||
|
|
||||||
bind: function(element, type, fn){
|
bind: function bindFn(element, type, fn){
|
||||||
var bind = JQLiteData(element, 'bind');
|
var bind = JQLiteData(element, 'bind');
|
||||||
|
|
||||||
|
|
||||||
if (!bind) JQLiteData(element, 'bind', bind = {});
|
if (!bind) JQLiteData(element, 'bind', bind = {});
|
||||||
forEach(type.split(' '), function(type){
|
forEach(type.split(' '), function(type){
|
||||||
var eventHandler = bind[type];
|
var eventHandler = bind[type];
|
||||||
|
|
||||||
|
|
||||||
if (!eventHandler) {
|
if (!eventHandler) {
|
||||||
bind[type] = eventHandler = function(event) {
|
if (type == 'mouseenter' || type == 'mouseleave') {
|
||||||
if (!event.preventDefault) {
|
var mouseenter = bind.mouseenter = createEventHandler(element);
|
||||||
event.preventDefault = function() {
|
var mouseleave = bind.mouseleave = createEventHandler(element);
|
||||||
event.returnValue = false; //ie
|
var counter = 0;
|
||||||
};
|
|
||||||
}
|
|
||||||
if (!event.stopPropagation) {
|
|
||||||
event.stopPropagation = function() {
|
|
||||||
event.cancelBubble = true; //ie
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (!event.target) {
|
|
||||||
event.target = event.srcElement || document;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isUndefined(event.defaultPrevented)) {
|
|
||||||
var prevent = event.preventDefault;
|
|
||||||
event.preventDefault = function() {
|
|
||||||
event.defaultPrevented = true;
|
|
||||||
prevent.call(event);
|
|
||||||
};
|
|
||||||
event.defaultPrevented = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.isDefaultPrevented = function() {
|
bindFn(element, 'mouseover', function(event) {
|
||||||
return event.defaultPrevented;
|
counter++;
|
||||||
};
|
if (counter == 1) {
|
||||||
|
event.type = 'mouseenter';
|
||||||
forEach(eventHandler.fns, function(fn){
|
mouseenter(event);
|
||||||
fn.call(element, event);
|
}
|
||||||
});
|
});
|
||||||
|
bindFn(element, 'mouseout', function(event) {
|
||||||
// Remove monkey-patched methods (IE),
|
counter --;
|
||||||
// as they would cause memory leaks in IE8.
|
if (counter == 0) {
|
||||||
// It shouldn't affect normal browsers, as their native methods are defined on prototype.
|
event.type = 'mouseleave';
|
||||||
delete event.preventDefault
|
mouseleave(event);
|
||||||
delete event.stopPropagation
|
}
|
||||||
delete event.isDefaultPrevented
|
});
|
||||||
};
|
eventHandler = bind[type];
|
||||||
eventHandler.fns = [];
|
} else {
|
||||||
addEventListenerFn(element, type, eventHandler);
|
eventHandler = bind[type] = createEventHandler(element);
|
||||||
|
addEventListenerFn(element, type, eventHandler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
eventHandler.fns.push(fn);
|
eventHandler.fns.push(fn);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -603,6 +603,50 @@ describe('jqLite', function() {
|
||||||
|
|
||||||
browserTrigger(a, 'click');
|
browserTrigger(a, 'click');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('mouseenter-mouseleave', function() {
|
||||||
|
var root, parent, sibling, child, log;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
log = '';
|
||||||
|
root = jqLite('<div>root<p>parent<span>child</span></p><ul></ul></div>');
|
||||||
|
parent = root.find('p');
|
||||||
|
sibling = root.find('ul');
|
||||||
|
child = parent.find('span');
|
||||||
|
|
||||||
|
parent.bind('mouseenter', function() { log += 'parentEnter;'; });
|
||||||
|
parent.bind('mouseleave', function() { log += 'parentLeave;'; });
|
||||||
|
parent.mouseover = function(event) { parent.data('bind').mouseover(event || {}); };
|
||||||
|
parent.mouseout = function(event) { parent.data('bind').mouseout(event || {}); };
|
||||||
|
|
||||||
|
child.bind('mouseenter', function() { log += 'childEnter;'; });
|
||||||
|
child.bind('mouseleave', function() { log += 'childLeave;'; });
|
||||||
|
child.mouseover = function(event) { child.data('bind').mouseover(event || {}); };
|
||||||
|
child.mouseout = function(event) { child.data('bind').mouseout(event || {}); };
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
dealoc(root);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fire mouseenter when coming from outside the browser window', function() {
|
||||||
|
if (window.jQuery) return;
|
||||||
|
parent.mouseover();
|
||||||
|
expect(log).toEqual('parentEnter;');
|
||||||
|
|
||||||
|
child.mouseover();
|
||||||
|
expect(log).toEqual('parentEnter;childEnter;');
|
||||||
|
child.mouseover();
|
||||||
|
expect(log).toEqual('parentEnter;childEnter;');
|
||||||
|
|
||||||
|
child.mouseout();
|
||||||
|
expect(log).toEqual('parentEnter;childEnter;');
|
||||||
|
child.mouseout();
|
||||||
|
expect(log).toEqual('parentEnter;childEnter;childLeave;');
|
||||||
|
parent.mouseout();
|
||||||
|
expect(log).toEqual('parentEnter;childEnter;childLeave;parentLeave;');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue