Side navigation
Ticket #3379: bubble.patch
File bubble.patch, 3.0 KB (added by danwrong, September 19, 2008 09:45AM UTC)
Version of patch where tests clean up after themselves
Index: test/unit/event.js
===================================================================
--- test/unit/event.js (revision 5845)
+++ test/unit/event.js (working copy)
@@ -346,3 +346,44 @@
start();
}).click();
});
+
+test("custom event bubbling", function() {
+ expect(6);
+
+ jQuery(document).bind('acustomevent', function(e) {
+ ok(false, 'customevent should not bubble to document as a previous handler returned false');
+ });
+
+ jQuery('#main').bind('acustomevent', function(e, data) {
+ ok(true, 'acustomevent has bubbled to the parent element');
+ equals(e.target, jQuery('#firstp')[0], 'target is the original element that triggered the event');
+ equals(e.type, 'acustomevent', 'event type is preserved in bubble');
+ equals(data, 5, 'data is bubbled up with event');
+ return false;
+ });
+
+ jQuery('#firstp').trigger('acustomevent', 5);
+
+ jQuery(document).bind('anothercustomevent', function(e) {
+ ok(false, 'anothercustomevent should not bubble to document');
+ });
+
+ jQuery('#main').bind('anothercustomevent', function(e) {
+ ok(true, 'anothercustomevent has bubbled to the parent element as a previous handler called stopPropagation');
+ e.stopPropagation();
+ });
+
+ jQuery('#firstp').trigger('anothercustomevent');
+
+ jQuery(document).bind('onemorecustomevent', function() {
+ ok(true, 'onemorecustomevent still bubbles to document even if no handler bound to original target');
+ });
+
+ jQuery('#firstp').trigger('onemorecustomevent');
+
+ jQuery(document).unbind('acustomevent');
+ jQuery(document).unbind('anothercustomevent');
+ jQuery(document).unbind('onemorecustomevent');
+ jQuery('#main').unbind('acustomevent');
+ jQuery('#main').unbind('anothercustomevent');
+});
Index: src/event.js
===================================================================
--- src/event.js (revision 5845)
+++ src/event.js (working copy)
@@ -188,8 +188,8 @@
data.unshift({
type: type,
target: elem,
- preventDefault: function(){},
- stopPropagation: function(){},
+ preventDefault: function(){ this._preventDefault = true },
+ stopPropagation: function(){ this._stopPropagation = true },
timeStamp: now()
});
data[0][expando] = true; // no need to fix fake event
@@ -202,8 +202,15 @@
// Trigger the event, it is assumed that "handle" is a function
var handle = jQuery.data(elem, "handle");
- if ( handle )
- val = handle.apply( elem, data );
+
+ if ( handle )
+ val = handle.apply( elem, data );
+
+ // handle the bubble if need be
+ if (data[0]._stopPropagation !== true && val !== false && elem.parentNode)
+ jQuery.event.trigger( type, data, elem.parentNode );
+
+ if (data[0]._preventDefault === true) donative == false;
// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
Download in other formats:
Original Format
File bubble.patch, 3.0 KB (added by danwrong, September 19, 2008 09:45AM UTC)
Version of patch where tests clean up after themselves
Index: test/unit/event.js
===================================================================
--- test/unit/event.js (revision 5845)
+++ test/unit/event.js (working copy)
@@ -346,3 +346,44 @@
start();
}).click();
});
+
+test("custom event bubbling", function() {
+ expect(6);
+
+ jQuery(document).bind('acustomevent', function(e) {
+ ok(false, 'customevent should not bubble to document as a previous handler returned false');
+ });
+
+ jQuery('#main').bind('acustomevent', function(e, data) {
+ ok(true, 'acustomevent has bubbled to the parent element');
+ equals(e.target, jQuery('#firstp')[0], 'target is the original element that triggered the event');
+ equals(e.type, 'acustomevent', 'event type is preserved in bubble');
+ equals(data, 5, 'data is bubbled up with event');
+ return false;
+ });
+
+ jQuery('#firstp').trigger('acustomevent', 5);
+
+ jQuery(document).bind('anothercustomevent', function(e) {
+ ok(false, 'anothercustomevent should not bubble to document');
+ });
+
+ jQuery('#main').bind('anothercustomevent', function(e) {
+ ok(true, 'anothercustomevent has bubbled to the parent element as a previous handler called stopPropagation');
+ e.stopPropagation();
+ });
+
+ jQuery('#firstp').trigger('anothercustomevent');
+
+ jQuery(document).bind('onemorecustomevent', function() {
+ ok(true, 'onemorecustomevent still bubbles to document even if no handler bound to original target');
+ });
+
+ jQuery('#firstp').trigger('onemorecustomevent');
+
+ jQuery(document).unbind('acustomevent');
+ jQuery(document).unbind('anothercustomevent');
+ jQuery(document).unbind('onemorecustomevent');
+ jQuery('#main').unbind('acustomevent');
+ jQuery('#main').unbind('anothercustomevent');
+});
Index: src/event.js
===================================================================
--- src/event.js (revision 5845)
+++ src/event.js (working copy)
@@ -188,8 +188,8 @@
data.unshift({
type: type,
target: elem,
- preventDefault: function(){},
- stopPropagation: function(){},
+ preventDefault: function(){ this._preventDefault = true },
+ stopPropagation: function(){ this._stopPropagation = true },
timeStamp: now()
});
data[0][expando] = true; // no need to fix fake event
@@ -202,8 +202,15 @@
// Trigger the event, it is assumed that "handle" is a function
var handle = jQuery.data(elem, "handle");
- if ( handle )
- val = handle.apply( elem, data );
+
+ if ( handle )
+ val = handle.apply( elem, data );
+
+ // handle the bubble if need be
+ if (data[0]._stopPropagation !== true && val !== false && elem.parentNode)
+ jQuery.event.trigger( type, data, elem.parentNode );
+
+ if (data[0]._preventDefault === true) donative == false;
// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )