Tuesday, April 26, 2011

IE: Using JS onclick and jquery .click() on the same element

In case you need to call two different javascript methods on the same element, please do not mix jquery and javascript. Well yes, I can bundle the two methods into one and call one, but what if one method is bound to the type of element in the DOM (e.g., the table headers in the tablesorter plugin).

I always use javascript to bind events on elements because it is easier to debug, you do not have to look for the binded methods all over the js files. Also the onclick, onblur, onfocus, and such methods always work fine in all browsers.

Or so I thought.

Till I discovered this corner scenario where your onclick will not work in Internet Explorer:
  • Your element e is already click-binded to a method called second() using jquery that returns false. 
  • You add a js onclick method called first(). 
  • You invoke the click on this element e programatically using the click() method.
Here is the code snippet:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js">
function callOnClick(){
    alert("call another item's onclick method");
     $("#toclick").click();
}
function first(){
    alert("one");
}
function second(){
    alert("two");
}
function third(){
    alert("three");
}
$(document).ready(function(){
    $("#toclick").click(function(e){
        second();
        return false;
    });
    $("#toclick").click(function(e){
        third();
    });
});
</script>

<div id="toclick" onclick="first()" style="cursor:pointer; margin-bottom:10px">
    This should get clicked automatically.
</div>

<div id = "trigger" onclick="callOnClick()"  style="cursor:pointer;">
    Click here.
</div>
The javascript method first() is not called at all. However, if you add another method called third() using jquery after the second() method, it gets called. If you are viewing this on any browser other than IE, you would see alerts two, three, and one when you click on click here.But on IE, you will see only two and three.

Moral of the story: Do not intermingle jquery click() and javascript onclick(), and if you cannot avoid that, do not return false from your jquery click() method.

Here is a working sample:

This should get clicked automatically.
Click here.

View this post on IE and other browsers and you'll know the difference.

Edit: This works fine with jQuery 1.4.2. Seems like a bug in jQuery 1.2.6, the version I previously used.

Sunday, April 24, 2011

Non-breaking space &othrs in Firefox

There are times where Internet Explorer surprises me. I've encountered numerous instances where css/javascript works perfectly fine in Firefox but screws up badly in IE 7 or IE 6. But the real surprise comes when things work in IE but fail in Firefox..

For example, HTML entities used by names, if not suffixed by a semicolon, and not separated by a space with the following word, fail to render in Firefox 3. It works fine in Internet Explorer 6, 7, 8, 9 and all versions of Chrome.

The following html code would appear differently in Firefox than other browsers:
There is a space between the two spaces: space&nbspspace
The following rendered html would retain the HTML entity nbsp in Firefox, would work fine in other browsers (You will have to visit this blog page in both a Firefox and a non-Firefox browser to know the difference):
There is a space between the two spaces: space space 
Using either "&nbsp;space" or "&nbsp space" does the trick in Firefox 3 as well. This is true not only for non-breaking space but for all HTML entities.

Firefox 4 seems to have fixed this problem. Well, yeah, I agree, it is not a problem, only rigid syntax. If you miss a semi-colon at the end of an HTML entity you used by name, and you are tight-bound for whitespace, you are in for a surprise if you are using a Firefox version<4.

But I wonder what took the guys at Mozilla six-and-a-half years to accommodate this developer-friendly convenient feature.

Thursday, April 14, 2011

jQuery tablesorter cache

The jQuery plugin tablesorter is a convenient way of in-place sorting HTML tables. However. I was in for a surprise when I used ajax to change some data in some of the rows, and the sorting wouldn't work perfectly after that.

Tablesorter is intelligent enough to create a cache of the entire table so that it doesn't have to read the DOM every time a sorting arrow is clicked. In fact, it reads and formats every cell as per the parsing function defined for it (you can have your own parsing mechanism for a specific type of data) before caching to save some extra processing.

Coming back to the point, the cache can be rebuilt using the following command:
$("#tableId").trigger("update");
Call this simple trigger to refresh the cache as soon as you update data in your table and the sorting would work smoothly.

Friday, April 8, 2011

Credit Card validation: Luhn algorithm

I was paying my phone bill online when I was taken aback by an alert stating an incorrect credit card number. I was sure, but I double checked, and the number I entered was 16 digits, had no leading/trailing spaces, and had no non-numeric stray characters.

How could then someone validate my card number in the browser, without going to the server? Are all card numbers generated guided by some mathematical rules? I knew all Visa cards begin with a 4 and Master cards with a 5, but are there more rules/algorithms that could be programmed in client-side javascript?

The curious part of me opened the Developer Tools. (And I must note that the Chrome Developer Tools are much better than Firebug, only that I am used to Firebug, but lets put that comparison aside for a later post). Half expecting to find an uncompressed javascript, I started digging into the scripts section. I was about to close off the Developer Tools when I found some embedded script in the HTML. And voila, it turned out to be what I was looking for! Totally uncompressed, and with comments intact!

I spend the next 10 minutes going through the stack of JS functions, and found a confident algorithm to shoo away invalid card numbers, besides the usual number of digits and starting digits etc:

  • Double every second digit, starting from the right. If the result is in two digits, add the two digits.
  • Sum all digits obtained as above to all the remaining (undoubled) digits. 
  • If the sum so obtained is not a multiple of 10, the card number is invalid!!

Googling up gave me tons of results on credit card number validation; a reliable wikipedia page told me the algorithm is called Luhn algorithm, patented by some Hans Peter Luhn in 1954. This is used as the validation algorithm for almost all Card Issuing Networks across the world for like 6 decades!. And I was so surprised at the javascript validation error...

Wednesday, April 6, 2011

Switch String in, break remains

Java 5 saw a flurry of very useful language enhancements in Sep 2004: generics, autoboxing, annotations, the enhanced for-loop, among others. The Java 6 release in Dec 2006 brought no language enhancement to make the developer's life easier. Java 7, however, to be released in mid 2011, comes with a few.

Changes to JSR 334 under Project Coin include a try-with-resources statement, catching multiple exception types in the same catch block, binary literals, underscores as a digit group separator in numbers, and the most useful, strings in switch statements.

This sounds as a relief, though I wonder what took them 15 long years to figure out the use of a switch statement that accepts a String object in the expression. I believe in real-world programming, we use more if-then-else in Strings than in ints, at least I get to do that in many cases in projects I've worked upon.

While they were at it, I'd have expected them to do away with the break at the end of every case in a switch-case block. It is a nuisance in many cases, because you generally have one flow for one case. Of course there might be cases, as in the example in the link given above, where you might need the fallthrough. A cleaner solution would have been to use some other keyword, maybe continue, whenever a fallthrough is desired, and break as the default implementation, the way Perl and Google's Go do it.

Tuesday, April 5, 2011

{google:baseurl} and the Chrome omnibar

The Chrome omnibar is perhaps the most useful browser feature ever invented. It becomes your favourite search engine's search box if you enter text that does not look like a valid URL, it transforms itself into the search box of your oft-visited sites at the press of a tab, it also lets you configure/change settings of the browser itself. I use it day and night, and would not exaggerate if I say that this was the primary reason (apart from Google minimalism) that made me switch over from Firefox to Chrome two and a half years ago.

This morning was the first time I was pissed off at the Omnibar. Whenever I searched google using it, I saw a distracting yellow balloon just under it telling me that I have moved, and that I should switch to google.co.in. It gave me a yes/no option, and heck, it never seemed to take no for an answer. It actually accepted a No and closed the balloon, but never seemed to remember it. I made another search, and there it was, to distract me again, the yellow balloon again telling me I had moved.

Believing this was a bug, since I am on the dev channel of Chrome, and having got enough irritated, I accepted Yes, and the balloon never showed me its face again. (I didn't have the time/patience to take a screenshot, but I am sure I'll find many on the web, or I can recreate it on one of the other three computers I have at home, not all mine though) Nevertheless, all my google searches are now directed to the Indian domain after I accepted the balloon message.

Now when I had some time, I decided to revert back to the .com domain using chrome://settings/searchEngines on my favourite omnibar. I changed google.co.in to google.com and searched, but it still redirects me to google.co.in. Went back to the search engines and realised I had changed only the keyword; the url points to {google:baseURL}search?{google:RLZ}{google:acceptedSuggestion}{google:originalQueryForSuggestion}sourceid=chrome&ie={inputEncoding}&q=%s. 

And to my utter disbelief, the baseURL cannot be changed. Google forces me to use the Indian domain through the omnibar.

That is a thousand Google -1. I know, they only have a Google +1, another -1.


Hello World!

Hello World is the first program one writes when starting in a new language. Now, English is a new language for me, so here I go.
Hello, World!
Spent a couple of hours on naming my blog and choosing a blogger template, and customizing it using the new blogger template designer. Shall move to my own css and images in some time.