Note: This may be a bit of an example of “doing it wrong”, but I don’t care :P
Yesterday I was having a look at a bug for a client in which we have a search control on a page which does an AJAX search, reloading the whole page.
Obviously that was a bit of a problem, the dynamic search results were being trashed by the full postback.
It was a very basic form, with a text input box for keywords and a button which you could click if you wanted to do the search. When clicking the button everything was fine, but when hitting Enter in the textbox the whole page refreshed.
After doing a few tests I noticed something interesting, the AJAX was working, the search results were loaded client side but then immediately the page posted.
So I went on the hunt for the keyboard event which was on the textbox and I found this:
$(function() {
$('.searchKeywords).keypress(function(e) {
if(e.which == 13) {
e.preventDefault();
if ($(".searchKeywords").val() != "") {
$(".KeywordSearchFilter").click();
}
}
});
});
Nothing odd there, that’s perfectly fine for handling the keypress event and then doing the search, so my next assumption is that the button is having a problem.
I started digging around to see if I could find where the buttons click event handler was being registered.
But no joy, nothing, nada, zip.
No jQuery click handler is being registered.
Ooooook… So I had a look at the source for the button itself and found this:
<input type="submit" name="..." value="Go" onclick="SearchHelper.searchByKeyword(null);;return false;WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("...", "", true, "SearchKeyword", "", false, false))" id="..." class="submit KeywordSearchFilter">
I’ve trimmed out the control names so it’s a bit easier to read
Crap, see the problem? The click events are registered in the onclick attribute of the button!
Well first off I was surprised that jQuery actually fired the onclick attributes events, but it is a problem that it wasn’t acknowledging the return false statement.
So I had 2 options in front of me:
1) Refactor the code so that it was registering the event using jQuery
2) Find some funky way to do this
Option 1 was not really viable, this search control is a super class of a common search control and I didn’t want to break any other parts of the site, sure our tests would cover it *cough cough :P* but it’s quite a large site and with only a few weeks left here I don’t want to cock anything up.
So it’s option 2, time to work out some funky way around it!
Since onclick is just an attribute, I thought “can I just access it and grab the methods out”? I don’t see why not, jQuery must be doing something like that itself.
And since it’s just a set of functions, could I invoke it?
Well it turns out that I could! And this is what I now have in the codebase:
$(function() {
$('.searchKeywords).keypress(function(e) {
if(e.which == 13) {
e.preventDefault();
if ($(".searchKeywords").val() != "") {
$(".KeywordSearchFilter").attr('onclick')();
}
}
});
});
I tested this in IE8, Firefox and Chrome and it worked in all three browsers!
Hey, it may not be the best solution, but hey, it worked! :P