fix bubbling and more comments

This commit is contained in:
David Greenspan
2012-05-09 19:13:22 -07:00
parent 1df3de2d5d
commit 316fcbb7a1
3 changed files with 39 additions and 4 deletions

View File

@@ -130,6 +130,8 @@ Meteor.ui._event._loadW3CImpl = function() {
var eventsCaptured = {};
Meteor.ui._event.registerEventType = function(eventType, subtreeRoot) {
// We capture on the entire document, so don't actually care
// about subtreeRoot!
installCapturer(eventType);
};

View File

@@ -582,6 +582,9 @@ Meteor.ui = Meteor.ui || {};
// without taking enclosing ranges into account, so additional event
// handlers need to be attached.
var attach_secondary_events = function(range) {
// Implementations of LiveEvents that use whole-document event capture
// (all except old IE) don't actually need any of this; this function
// could be a no-op.
for(var r = range; r; r = r.findParent()) {
if (r === range)
continue;
@@ -598,6 +601,12 @@ Meteor.ui = Meteor.ui || {};
}
};
// Handle a currently-propagating event on a particular node.
// We walk all enclosing liveranges of the node, from the inside out,
// looking for matching handlers. If the app calls stopPropagation(),
// we don't stop immediately (within an event map), but we DO stop
// between ranges (i.e. templates), in keeping with the idea that
// ranges are like invisible container nodes.
Meteor.ui._handleEvent = function(event) {
var curNode = event.currentTarget;
if (! curNode)
@@ -609,7 +618,7 @@ Meteor.ui = Meteor.ui || {};
var type = event.type;
for(var range = innerRange; range; range = range.findParent(true)) {
for(var range = innerRange; range; range = range.findParent()) {
if (! range.event_handlers)
continue;
@@ -626,6 +635,8 @@ Meteor.ui = Meteor.ui || {};
}
var returnValue = h.callback.call(range.event_data, event);
// allow app to `return false` from event handler, just like
// you can in a jquery event handler
if (returnValue === false) {
event.stopPropagation();
event.preventDefault();

View File

@@ -1314,7 +1314,8 @@ Tinytest.add("liveui - basic events", function(test) {
// "deep reach" from high node down to replaced low node.
// Tests that attach_secondary_events actually does the
// right thing in IE. Also tests change event bubbling.
// right thing in IE. Also tests change event bubbling
// and proper interpretation of event maps.
event_buf.length = 0;
R = ReactiveVar('foo');
div = OnscreenDiv(Meteor.ui.render(function() {
@@ -1323,13 +1324,34 @@ Tinytest.add("liveui - basic events", function(test) {
return '<input type="checkbox">'+R.get();
}, {events: eventmap('click input'), event_data:event_buf}) +
'</b></span></p></div>';
}, { events: eventmap('change b'), event_data:event_buf }));
}, { events: eventmap('change b', 'change input'), event_data:event_buf }));
R.set('bar');
Meteor.flush();
// click on input
clickElement(div.node().getElementsByTagName('input')[0]);
event_buf.sort(); // don't care about order
test.equal(event_buf, ['change b', 'click input']);
test.equal(event_buf, ['change b', 'change input', 'click input']);
event_buf.length = 0;
div.kill();
Meteor.flush();
// test that 'click *' fires on bubble
event_buf.length = 0;
R = ReactiveVar('foo');
div = OnscreenDiv(Meteor.ui.render(function() {
return '<div><p><span><b>'+
Meteor.ui.chunk(function() {
return '<input type="checkbox">'+R.get();
}, {events: eventmap('click input'), event_data:event_buf}) +
'</b></span></p></div>';
}, { events: eventmap('click *'), event_data:event_buf }));
R.set('bar');
Meteor.flush();
// click on input
clickElement(div.node().getElementsByTagName('input')[0]);
test.equal(
event_buf,
['click input', 'click *', 'click *', 'click *', 'click *', 'click *']);
event_buf.length = 0;
div.kill();
Meteor.flush();