Time to share another fun tip about Prototype.js — how to stop the default behavior of a link. Of course, I wasted hours of my life looking in all the wrong places to fix this problem, and now the time wasting will come to an end. But to appreciate my suffering, allow me to walk you through from the beginning.
In the simple days, we would add an event to a link, and stop the link from executing with this beauty:
link.onclick = function() {
//do something
return false;
}
And then we found out that an event listener is needed to attach more than one event to an object, so method 2 for attaching events became:
Event.observe(link, 'click', dosomething, false);function dosomething() {
//do something
return false;
}
The problem with this method is that return false;
no longer works. The dosomething()
function will not stop the link from going to the URL. So, a potential solution is seen in method 3:
Event.observe(link, 'click', dosomething, false);
link.onclick = function() {return false;};
Both functions will execute onclick, and a return false;
is guaranteed. But this solution is not elegant. Luckily, Prototype.js offers method 4, which is Event.stop()
.
Event.observe(link, 'click', dosomething, false);function dosomething(e) {
//do something
Event.stop(e);
}
The above code will have the same functionality as return false;
, and all the Event.stop()
function needs as a parameter is the event. I was happy when Beau presented this solution to me, but my happiness was short-lived. This solution works in IE, Firefox, and the Safari Webkit, but it does not work in Safari 2.0.3. For now, I will have to keep using method 3 (unless someone knows a better way), but a good method is waiting to be used as soon as the next version of Safari comes out.
I’ve always been frustrated by this, but I never really hear anybody talk about it, so I figured I was just dumb.
I recently discovered Event.stop() and I fell in love, except I can’t get it to work properly with forms (when I’m observing the submit event).
I just assumed it would work with forms. I guess it is never that easy. I’ll play around with the form part and see if I can come up with anything.
Off the top of my head, I think it me have to do with the event object
e
. If you try:Check and see what element it has a handle on. Sometimes with nested HTML it focuses on the first child (not sure why).
I’m not sure where the correct place to put this. But what is your or ParticleTree’s take on JQuery. Is is better than prototype? Should it be used with Prototype. I’m just curious what your take is.
Event.Stop looks nice.
Jordan - JQuery looks like it has some nice functionality, and the fact that it comes in around 10kb makes it appealing. The only thng I don’t like about it is the chainable function calls (I think they hurt readability), but you only have to use those if you want to. Right now, since I am so comfortable with Prototype and the features it has, I am not looking to switch. It is nice to keep an eye out for emerging libraries though, and JQuery may have some potential. The documentation is not finished, so I didn’t have time to go through the entire source looking at its capabilities.
I’m a jackass Ryan, I forgot to pass in the event object, hence nothing would happen. Works like a champ.
JQuery is amazingly small…but with more features in the DOM/Effects/Events world.
Ryan, starting to think you had something to do with the original prototype project. Did they hire you? ;)
j/k man. Anyway, I like how you can do that with prototype. You’re slowly chipping away everything the library has to offer. This really is great.
Maybe in secret I wrote Prototype.
Or maybe Ryan = Sam Stephenson!
Or not :(
But yeah, I’m tryin to chip.
I found that anchorObj.removeAttribute (‘href’) works well in all browsers.
This tip is really fun. Many thanks.
I’m not sure this solves your problem with safari, but I had some problems with firefox and found out that moving Event.stop(e) as the first command in the function resolved them!
So, instead of having:
function dosomething(e) { //do something Event.stop(e); }
I now have:
function dosomething(e) { Event.stop(e); //do something }
Thanks for your article!
I thought this information should have been basic material covered in the documentation. Thanks for taking care of that for us!
I’m adding degradable ajax calls to some of my sites using the prototype library and found the following works well.
Event.observe('delete-','click',function(e){Event.stop(e);cancelWorkOrder('');},false);
Whoops, it looks like like my php was filtered out. Let me try again. :)
Event.observe('delete-<?php echo $i; ?>','click',function(e){Event.stop(e);deleteWorkOrder('<?php echo $i; ?>');},false);
Wow, this tip was really a life saver :) I used it as a workaround, because I can’t seem to get Event.observe working. Here’s a part of a code taken from a Class: registerCallbacks: function() { Event.observe(this.addLine,’onclick’, this.addline_onclick, true); }, addline_onclick: function() { alert(‘test’); },
This doesn’t work, but this does: this.addline.onclick = this.addline_onclick.bindAsEventListener(this);
And I really don’t get it :( With Event.stop I got rid of bubbling, which was causing the headaches.
I’ve been searching for this for ages!
Here’s hoping someone’s still paying attention to this thread:
Following up on Justin’s original question (that he appears to have found an answer for), I’m having the same problem and it’s starting to really frustrate me. I’d appreciate any help you might be able to throw my way.
I have a form whose ‘submit’ event I’m listening for using prototype.js. On submit, I need to hash the password value before submitting. Unfortunately, the password is being hashed multiple times (I can’t say for certain how many). My code:
Event.observe ( $( ‘profileLoginForm’ ), ‘submit’, function ( e ) { Event.element ( e ).profileLoginPassword.value = MD5 ( Event.element ( e ).profileLoginPassword.value ); // Event.stop ( e ); }, false );
It’s clearly something I’m doing wrong. I get the same value every time, it’s just the same incorrect value. A little help and another set of eyes would be appreciated tremendously.
Thank you.
Oops. Sorry for the lousy formatting. Let’s try this:
Event.observe ( $( ‘profileLoginForm’ ), ‘submit’, function ( e ) { Event.element ( e ).profileLoginPassword.value = MD5 ( Event.element ( e ).profileLoginPassword.value ); // Event.stop ( e ); }, false );
I’m sorry about this guys, but Event.stop(e) is NOT commented out in my code. I’ve been trying every single thing I can think of and I happened to paste my last wildly flailing attempt. This is the “correct” code that I’ve tried and that has failed:
Event.observe ( $( ‘profileLoginForm’ ), ‘submit’, function ( e ) { Event.element ( e ).profileLoginPassword.value = MD5 ( Event.element ( e ).profileLoginPassword.value ); Event.stop ( e ); }, false );
Sorry for all of the confusion. My frustration is redlining right about now.
It may be bad form, but I’m going to answer my own post so that:
The key, I think, is in a portion of code I left out. Here’s the complete snippet that was NOT working:
Event.observe ( window, ‘load’, init, false );
function init() { Event.observe ( $( ‘profileLoginForm’ ), ‘submit’, function ( e ) { Event.element ( e ).profileLoginPassword.value = MD5 ( Event.element ( e ).profileLoginPassword.value ); }, false ); }
And here’s what worked:
Event.observe ( window, ‘load’, function ( e ) { Event.observe ( $( ‘profileLoginForm’ ), ‘submit’, function ( e ) { Event.element ( ev ).profileLoginPassword.value = MD5 ( Event.element ( e ).profileLoginPassword.value ); }, false ); Event.stop ( e );
}, false );
Can’t explain why. Certainly wish I could. The key seems to have been the window’s onload handler.
You know, just in case anyone’s interested…
Rob, my guess is that the reason that worked with the window ‘load’ is that your script is in an external file or otherwise runs before the form itself is instantiated. Waiting for the page to load means you’ll actually be reliably binding the event listener to the form, whereas running it before the form tags means you might be binding it to nothing.
To fix this issue also in Safari you can use method 5: preventDefault ;)
if (e && e.preventDefault) e.preventDefault(); //DOM return false; //IE
Just wanted to point out that the comment above by Webby does not work.
If you look int the Prototype code, the Event.stop actually calsl the event.preventDefault() method:
Event.stop function
if (event.preventDefault) { event.preventDefault(); event.stopPropagation(); } else { event.returnValue = false; event.cancelBubble = true; }
Bah I used code instead of pre.
just a quick not about prototype.js… (this seems to work in most browsers EXCEPT Safari):
You can gzip the prototype.js file, getting the filesize down to 12,479kb sweet! So I now include it with:
src=’prototype.js.gz’
Thanks so much for that tipp
if(Ryan_needs_a_hug==1) Hug(Ryan); else return false; I guess if we simply return false on any action nothing will happen. Actually I learned it way back :P am just trying to show off. ;-) Good stuff. I msut work now. Rest of the stuff I will read later.
Everyone needs a hug.w
hi i am having trouble using this lightbox i have used the old one and it was fine but know i want to have a html file in my lightbox but once using this lightbox to do that i ge an error of: Method Not Allowed The requested method POST is not allowed for the URL /crowsnest/map.html. i not sure what this means but if anyone can help me it would be appreciated thank you Andrew the error is on the contact us page if you click the “click here for map” you will see what i am talking abt……..
Thank you Ryan for that advice. It also works fine with anonymous function like this:
Thank you soo much. This really should have been pointed put and put in a h1 tag on the prototype site.