Skip to content

Commit

Permalink
Fix bubbling for Event Delegation, so one could do change:relay(form)…
Browse files Browse the repository at this point in the history
… for example
  • Loading branch information
arian committed Apr 13, 2011
1 parent efe3071 commit bd92b67
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 38 deletions.
29 changes: 13 additions & 16 deletions Source/Element/Element.Delegation.js
Expand Up @@ -37,6 +37,12 @@ var check = function(split, target, event){
return Slick.match(target, split.value) && (!condition || condition.call(target, event)); return Slick.match(target, split.value) && (!condition || condition.call(target, event));
}; };


var bubbleUp = function(split, event, fn){
for (var target = event.target; target && target != this; target = document.id(target.parentNode)){
if (target && check(split, target, event)) return fn.call(target, event, target);
}
};

var formObserver = function(eventName){ var formObserver = function(eventName){


var $delegationKey = '$delegation:'; var $delegationKey = '$delegation:';
Expand All @@ -60,14 +66,15 @@ var formObserver = function(eventName){
target = event.target, target = event.target,
form = (target.get('tag') == 'form') ? target : event.target.getParent('form'), form = (target.get('tag') == 'form') ? target : event.target.getParent('form'),
formEvents = form.retrieve($delegationKey + 'originalFn', []), formEvents = form.retrieve($delegationKey + 'originalFn', []),
formListeners = form.retrieve($delegationKey + 'listeners', []); formListeners = form.retrieve($delegationKey + 'listeners', []),
self = this;


forms.include(form); forms.include(form);
this.store($delegationKey + 'forms', forms); this.store($delegationKey + 'forms', forms);


if (!formEvents.contains(fn)){ if (!formEvents.contains(fn)){
var formListener = function(event){ var formListener = function(event){
if (check(split, this, event)) fn.call(this, event); bubbleUp.call(self, split, event, fn);
}; };
form.addEvent(eventName, formListener); form.addEvent(eventName, formListener);


Expand All @@ -87,9 +94,9 @@ var inputObserver = function(eventName){
listener: function(split, fn, args){ listener: function(split, fn, args){
var events = {blur: function(){ var events = {blur: function(){
this.removeEvents(events); this.removeEvents(events);
}}; }}, self = this;
events[eventName] = function(event){ events[eventName] = function(event){
if (check(split, this, event)) fn.call(this, event); bubbleUp.call(self, split, event, fn);
}; };
args[0].target.addEvents(events); args[0].target.addEvents(events);
} }
Expand Down Expand Up @@ -120,21 +127,11 @@ if (!eventListenerSupport) Object.append(eventOptions, {
select: inputObserver('select') select: inputObserver('select')
}); });



Event.definePseudo('relay', { Event.definePseudo('relay', {
listener: function(split, fn, args, monitor, options){ listener: function(split, fn, args){
var event = args[0]; bubbleUp.call(this, split, args[0], fn);

for (var target = event.target; target && target != this; target = target.parentNode){
var finalTarget = document.id(target);
if (check(split, finalTarget, event)){
if (finalTarget) fn.call(finalTarget, event, finalTarget);
return;
}
}
}, },
options: eventOptions options: eventOptions
}); });


})(); })();

66 changes: 44 additions & 22 deletions Tests/Element/Element.Delegation_(non_bubbling).html
Expand Up @@ -12,25 +12,30 @@


<p>Clicking one of the buttons should fire the submit or reset events. For the <strong>submit</strong> event: Try tabbing to the buttons and press enter, or tabbing to the element and press enter.</p> <p>Clicking one of the buttons should fire the submit or reset events. For the <strong>submit</strong> event: Try tabbing to the buttons and press enter, or tabbing to the element and press enter.</p>


<form action="#foo" id="myForm"> <div id="formWrapper">


<input type="text" value="some text" /> <form action="#foo" id="myForm">
<input type="submit" value="Submit" />
<input type="reset" value="reset" />


</form> <input type="text" value="some text" />
<input type="submit" value="Submit" />
<input type="reset" value="reset" />


<p>This form has another ID, so only the reset button should delegate</p> </form>


<form action="#foo" id="myForm2"> <p>This form has another ID, so only the reset button should delegate</p>


<input type="text" value="some text" /> <form action="#foo" id="myForm2">
<input type="submit" value="Submit" />
<input type="reset" value="reset" /> <input type="text" value="some text" />
<input type="submit" value="Submit" />
<input type="reset" value="reset" />

</form>

</div>


</form>


<p>Change the text. When you blur the input field, the change event should fire</p> <p>Change the text. When you blur the input field, the change event should fire for both the form and the input fields</p>


<form action="#foo" id="myForm3"> <form action="#foo" id="myForm3">
<input type="text" value="some text" class="someClass" /><br /> <input type="text" value="some text" class="someClass" /><br />
Expand Down Expand Up @@ -65,27 +70,48 @@


var output = $('result'); var output = $('result');


var log = function(msg){
output.innerHTML += msg + '<br />';
};

var events = { var events = {

'focus:relay(input#myInput,textarea)': function(){ 'focus:relay(input#myInput,textarea)': function(){
output.appendText('\nFocus'); log('Focus on input#myInput,textarea');
}, },

'blur:relay(input#myInput,textarea)': function(){ 'blur:relay(input#myInput,textarea)': function(){
output.appendText('\nBlurred'); log('Blurred on input#myInput,textarea');
}, },

'submit:relay(form#myForm)': function(event){ 'submit:relay(form#myForm)': function(event){
event.stop(); event.stop();
output.appendText('\nSuccesfully delegated and stopped the ' + event.type + ' event'); log('Succesfully delegated and stopped the ' + event.type + ' event on form#myForm');
}, },
'submit:relay(#formWrapper)': function(event){
event.stop();
log('Succesfully delegated and stopped the ' + event.type + ' event on #formWrapper');
},

'reset:relay(form)': function(event){ 'reset:relay(form)': function(event){
event.stop(); event.stop();
output.appendText('\nSuccesfully delegated and stopped the ' + event.type + ' event'); log('Succesfully delegated and stopped the ' + event.type + ' event on form');
}, },

'change:relay(input.someClass,select,input[type=checkbox],input[type=radio])': function(event){ 'change:relay(input.someClass,select,input[type=checkbox],input[type=radio])': function(event){
output.appendText('\nSuccesfully delegated the ' + event.type + ' event'); log('Succesfully delegated the ' + event.type + ' event on the input');
},
'change:relay(form)': function(event){
log('Succesfully delegated the ' + event.type + ' event on the form');
}, },

'select:relay(#myForm4 input)': function(){ 'select:relay(#myForm4 input)': function(){
output.appendText('\nSuccesfully delegated the ' + event.type + ' event'); log('Succesfully delegated the ' + event.type + ' event on #myForm input');
},
'select:relay(#myForm4)': function(){
log('Succesfully delegated the ' + event.type + ' event on #myForm4');
} }

}; };


var container = $('myContainer').addEvents(events); var container = $('myContainer').addEvents(events);
Expand All @@ -97,8 +123,4 @@
container.addEvents(events); container.addEvents(events);
}); });


$$('select').addEvent('select', function(event){
console.log(event);
})

</script> </script>

0 comments on commit bd92b67

Please sign in to comment.