Archive for the ‘JavaScript’ Category

Javascript: Function.prototype.toString returns an optimized version of the function

June 17, 2007

I was working an a user script for Gmail (I’ll link to it when it’s done), and could not understand why some code didn’t run on a specific page.

One of my tricks of seeing a Javascript function body when the function is dynamically added is to call the function toString() (e.g. in Firebug console). Regretfully, Firebug doesn’t tab-complete functions’ methods, so I have to manually type “toString()”. (I opened issue 959 for this.)

However, in the code I wrote, I accidentally wrote something like:

var count = getCount();
if(count == 0)
    count == 1;

Note the bug in the last line, where the comparison operator (==) is used instead of the assignment operator (=). Surely, my mistake. However, when I look at the text that was returned from the call to Function.prototype.toString() for that function, I saw it is:

var count = getCount();
if (count == 0) {
}

So the Javascript engine noticed that nothing really useful is going on in the body of that if, and simply removed it, and that is reflected in what Function.prototype.toString returns. I didn’t knew that.

PS

Naturally tools like JSLint warn about this problem:

Expected an assignment or function call and instead saw an expression.

count == 1;

But this is a minor user script, and I never considered passing such scripts through JSLint. I might consider starting doing it for my scripts…

Javascript component library found – Jack Slocum’s Ext

April 30, 2007

In the recent few months I was troubled in thoughts what JavaScript library we should used, now that we are rebuilding our product web UI.

The first limitation is that we will use the corporate common UI library which uses Prototype and Scriptaculous, but some components are missing from these libraries. The common UI library author did try to improve the library by adding more components to it, but they are far from being complete.

My main other options was YUI and Dojo. I followed and liked YUI from its very beginning – it seems like a nicely designed library with a devoted community. Then I attended Alex Russell‘s presentation at the ISOC conference, and I was impressed by the Dojo design concepts he presented, namely events and widgets.

However, I recently read the Ext library by Jack Slocum was released, and that it can work against Prototype, YUI and jQuery. I knew it was started as a grid for YUI which lacked that feature but added it in the recently released 2.2.0 version, but when I took a look at Ext’s component collection, I realized it has exactly all the components we needed for our revised UI:

  • a decent data grid
  • a date selection (calendar) control
  • a good menu component
  • impressive windoids support

There is one problem with Ext – although it is released under an Open Source license (LGPL), they encourage people who use it commercially to be a license. I didn’t see similar requests on YUI and Dojo. I don’t really know how our corporate will handle this license issue, but I think that when coding time approaches, I’ll start the process of using Ext in our product. Meanwhile I’m playing with it so I can show off what it can do to our product.

location.replace and Back button bug in IE

April 12, 2007

In our web application, after the user logs on, we display a “Please wait…” screen and then the user is taken to the main screen, using a “location.replace(URL)” function call.

Yesterday, due to another problem, we noticed that when the user clicks the Back button on Internet Explorer (6 & 7), he is taken to the “Please wait” screen, and then back to the main window, instead of being taken to the login screen, since the “location.replace()” method promises according to all the documentation we found not to put the current page in the browser history object, so pressing the browser Back button should take you to the previous page.

Both my colleague and I put up a clean sample HTML files to test it, but where in my test page the problem didn’t re-occur, it did with my colleague HTML files. A little search for differences showed that I wrote a simple HTML page from scratch:

<html>
  <body>
    <form>
      <input type=button value=click onclick=”location.replace(‘b.htm’)”>
    </form>
  </body>
</html>

But my colleague used a template to create her HTML file, so her files looked like:

<html>
  <head>
    <meta http-equiv=”Content-Type” content=”text/html; charset=iso-8859-1″>
    <title>EXAMPLE</title>
  </head>
  <body>
    <form>
      <input type=button value=click onclick=”location.replace(‘b.htm’)”>
    </form>
  </body>
</html>

Checking it further, we found out that when you use location.replace (and also window.open with the last parameter set to true) and the page you switch to has a Content-Type http-equiv <meta> tag that has a charset setting in its content attribute, Internet Explorer for some reason adds the current page to the history object, so pressing the Back button will take you to that page.

Note that for the bug to happen the new page to which you replace need to have this <meta> tag, and the current page content has no affect. Also, you must set the charset in that page – setting a content type without a charset (e.g. “text/html;”) doesn’t cause the problem. Finally, setting the content type using a real HTTP response header and not using an http-equiv <meta> tag also doesn’t cause the problem.

The fix was simple as the page we were opening was actually a frameset, so the charset setting in it could be safely removed.

This is indeed an interesting bug, to which I found no reference on the web.

"Display Anchors" toolbar button

March 6, 2007

I often use the “Display Anchors” option found in the Information menu of the Web Developer Firefox extension to build a link directly to a part of a page I’m interested in.

I usually doing it by clicking the toolbar button to show the Web Developer toolbar, then open the Information menu and select “Display Anchors”. A shorter way might have been using the right-click menu, since all Web Developer options are also available through a right click menu item. In any case, it requires at least three steps – Web Developer -> Information menu -> Display Anchors for this simple operation.

Today I’ve got sick of it and looked for a way to make it a one click operation. I googled for “display anchors” toolbar Firefox and got to David McRitchie’s bookmarklets page, where as point to the no-longer-available Show Classes and IDs bookmarklet page, but also has his own “id visible’ bookmarklet, which does something similar:

javascript:(function(){ var z=[],N,id,tc,j; function r(N) { if (N.id) z.push(N); var C=N.childNodes,i;for(i=0;i<C.length;++i)r(C[i]); } r(document.body); for (j in z) { N=z[j]; id=document.createTextNode(” %C2%ABid=”+N.id+”%C2%BB”); tc=document.createElement(”span”); tc.style.color=”red”; tc.style.background=”#FFEE99″; tc.appendChild(id); N.parentNode.insertBefore(tc,N.nextSibling); N.parentNode.insertBefore(document.createTextNode(” “),tc); }})();

I worked on it a little, and came up with a bookmarklet that creates link in a fashion similar to Web Developer’s “Show Anchors” way:

javascript:(function(){ var z=[],N,tc,j; function r(N) { if(N.id) z.push(N); var C=N.childNodes,i;for(i=0;i<C.length;++i)r(C[i]);}r(document.body);for(j in z) { N=z[j];tc=document.createElement(”div”);tc.innerHTML=”<a style=\”background-color:#FFFF99 !important;border:solid 1px #FFCC66 !important;color:#000000 !important;opacity:0.9 !important;text-decoration:none !important;font-size:10px !important;\” href=\”#”+N.id +”\”>#”+N.id+”<a>”;N.parentNode.insertBefore(tc,N);}})();

It currently only add links to elements with ID and not to a href-less named <a> elements. I’ll add these when I see the need.

Note: The bookmarklets are currently not links as I can’t find a way to convince WordPress editor to make them proper links.

BISON Critique

February 14, 2007

Via Ajaxian I got to BISON by Kai Jäger. I’ll ignore the fact that it’s actually quite useless, and also contradicts with an existing GNU utility, and refer to some of the implementation details.

First of all, the writer complains that he was not able to send data with null characters, and also that the data was always converted to UTF-8, which is problematic for binary data. To solve the problem of the null character he uses yEnc, and as for the UTF-8 problem, he simply says it will probably make the BISON data longer (sometimes even longer then the JSON equivalent), which renders the entire effort only useful as a JavaScript exercise.

However, AJAX is certainly capable of sending binary data to the server. For example, Gmail does it when you add an attachment. The attachment is a binary data that can contain null characters. Of course, Gmail might also be using some encoding, but on the other hand, Gmail, being a web app, have no access to the file data until it is passed to the server. I guess Gmail (and everyone else that wants to upload binary data using AJAX) is simply setting the correct header:

xmlHttp.setRequestHeader(‘Content-Type’, ‘application/x-www-form-urlencoded’);

This should solve both problem, as the send data will be encoded in the correct encoding.

BTW, during the encoding discussion he mentions that he chose yEnc since base64 encoding “can sometimes be twice the size of the original unencoded message”. Anyone who knows how base64 encoding works knows that this is almost never true, and as Wikipedia says, “the actual length of MIME-compliant base64-encoded binary data is usually about 137% of the original data length, though for very short messages the overhead can be a lot higher.

I had a look in the JavaScript code itself, and the first thing that came to me was his extensions to the String.prototype object which are done in quite a clumsy way, and can be done a lot nicer (and I think more efficiently) using array trickery.

For example:

String.prototype.repeat = function(times) {
    var repeatedStr = “”
    for (var i = 0; i < times; i++) {
        repeatedStr += this;
    }
    return repeatedStr;
}

can be written as

String.prototype.repeat = function(times) {
    return new Array(times+1).join(this);
}

and this

String.prototype.reverse = function() {
    var reversedString = “”
    for (var i = this.length – 1; i >= 0; i–) {
        reversedString += this.charAt(i);
    }
    return reversedString;
}

can be written as

String.prototype.reverse = function() {
    return this.split(“”).reverse().join(“”)
}

 

That’s all for now. I still need to look at the rest of the code to see what it does. I also want to have a look at yEnc – it looks interesting.

Problems with defaultValue

June 14, 2006

Today I found a problem in one of our screens (the filter screen) which only occurs on Firefox, but not on IE. After checking it further, I realized that the problem is with the defaultValue attribute of the <input type=text> element.

We use this attribute to store the default value of filter fields, and when the user wants to reset the filter, we set the value to the default value manually, without calling reset(). The default filter value can be set by the server administrator.

It appears that on Firefox, setting the defaultValue attribute causes the control to change its value if the user didn't change it yet. The logic is probably that if the user didn't change it, the control shows the default value, so changing the defaultValue attribute changes what the control displays, and the control's value attribute.

On IE, on the other hand, the MSDN clearly says that "The value of the property can be changed programmatically, but doing so has no effect on the appearance of the object or the submitted value."

I wanted to see what the HTML standard has to say about it, but apparently, the defaultValue attribute is a non-standard extension, supported by both IE and FF.

The solution to our problem is very simple. Use another custom attribute (e.g. defValue) to store the default value. This will have no affect, has the browsers have no special treatment for this custom attribute.

JavaScript is single-threaded

April 26, 2006

Damien Katz is mocking on an ONJava.com article that tries to implement Mutual Exclution for JavaScript.

I must say that I didn't really know it for sure that JavaScript is ALWAYS single-threaded, and there are never two threaded running in parallel. It is good to know that.

PS

After a long time of not blogging it, I noticed when I came back that WordPress.com has put back the Import options, so I imported my old Blogger blog into here.

Or-Assignment in JavaScript and Python

April 5, 2006

I just realized the other day that the || and && operators in JavaScript work like they work in Python, so you can write something like

var w = opener || window;

(Yes, I started learning Python for fun)


Follow

Get every new post delivered to your Inbox.