Tag > javascript

FLEX: first impressions

by airportyh posted at 11-20-2008 06:51PM - Comments (0)   flex javascript programming
At work I am required to write a web UI that has a rich-desktop kind of interface. Without getting into too much details, it's layout will look a bit like an older email application(e.g. outlook, the older versions). It also need to have drag-n-drop capabilities. I whipped up a prototype of the UI using prototype and scriptaculous, since that's what I've been getting fluent with. A couple of things about my prototype made me decide to give Flex a try.
  1. No draggable divider. The draggable divider - although not essential - is something that seasoned computer users have learned to expect when you give them interfaces that have multiple panels jammed onto one screen. Scriptaculous didn't have an draggable divider widget. YUI and ExtJS did, and I am not against learing a new library. But I get the vibe that their implementations might not be rock solid.
  2. Buggy drag-n-drop libary. Scriptaculous comes with a drag-n-drop library. I've used it in multiple occations. It's also been buggy for me on multiple occations. A lot of the bugs are attributed to differences in browsers.
I decided that I was tired of chasing down cross browser bugs, which will only grow exponentially the more complex my UI gets. Therefore, Flex could really be the answer to these problems.

I am probably 60% done with my port of the UI prototype from Javascript/prototype/scriptaculous to Flex. I am happy with it for the most part. Here are my first impressions of Flex. First the pros:
  1. Programming in Flex is suprisingly similar to programming in HTML/javascript/CSS. (Well, not as suprising as it could have been since I've heard Charles Lowe say the same on DrunkAndRetired.com podcast). You write a mxml file, which is like your markup - in place of your HTML; you write ActionScript inplace of Javascript; and there's a css 3 compliant stylesheet you can use to style the UI.
  2. Flex has a rich UI component model that similar to many of the desktop UI toolkits(Swing, GTK, MFC, etc), which is a departure from the HTML/Javascript model. This is a plus because you get a lot of widgets you can use out of the box with very little code. Using third party Javascript widgets is usually more involved.
  3. ActionScript is not much different from Javascript, so people literate in Javascript should pick it up easily. The only significant difference I've noticed so far is the type declaration syntax - ActionScript is statically typed. I believe ActionScript is compatible with a newer version of Ecmascript which has optional type declaration for variables and parameters. Type declaration in ActionScript(as far I can tell) is required on function parameters and global variables(errors out if you leave it), and optional on local variables(warns you if you leave it).
  4. Yes, you have to write XML, but it's not that bad. I have expressed my hatred for making programmers read and write XML by hand in the past. It's inhumane! Flex makes you do that. Yes. But! It's used in a way that's not as bad as some other ways in which XML have been used(build scripts, web configuration, for example). In Flex, XML is used for Markup (wow! a markup language used for markup? what a concept?). The XML declaratively defines the UI(such as in HTML), which, I my opinion, is the way UI's ought to be written, and not in a procedure way(such as in Swing).
  5. Flex components look good by default. For HTML/CSS you always have to design your own theme - even if you just want it to look half way decent. No such BS in Flex. Flex components look good out of the box(no CSS tweaks or includes required), because of this I believe you can prototype Flex UIs faster.
  6. A Flex app runs exactly the same on any browser it supports. This was the main sell for me. Nothing more needs to be said.
Now the cons:
  1. Develop feedback - not as instant. Developer feedback loop is slower because of the compile step. ActionScript is a compiled language, and you need to compile your Flex programing to get a SWF file. Also, in Flex 3, they took away the eval() function(why oh why???). This means you cannot create an interactive shell in Flex like Firebug or the python shell.
  2. Mandatory Static typing. Although I have nothing against static typing in general. I don't like mandatory static typing(such as exists in Java, C#, C++). Haskell is a staticly typed language, it verifies all your types for you, and yet it doesn't require you to specify the types of all you variables and parameters because it can infer them all for you. I like that. This is not a big issue for me, it's just not as kosher as Javascript in this respect.
  3. It's annoying that you have to write mx: to begin all Flex component tags in the mxml spec. No such BS in HTML. I tried a hack to do without it, it didn't work so well.
Overall, the pros are worth more than the cons. Linguistically, I prefer Javascript to ActionScript and HTML to MXML, so it's not going to Change My Life(TM). But the UI component model and cross browser compatibility greatly outweigh those nags.

Radio button change event firing

by airportyh posted at 11-10-2008 10:54AM - Comments (0)   crossbrowser html javascript programming
If you register the change event for a radio button, they fire at different times between IE and FF. FF fires the event immediately when you click on the radio button to change its value. IE does not, it fires changed only when you blur the element.

IE bug: input endtags show up as nodes

by airportyh posted at 11-10-2008 10:50AM - Comments (0)   crossbrowser html ie javascript programming
If you write an input element like this:
<input type="text" id="name" name="name" value="></input>
In IE, if you try to traverse the dom, you will get the end-tag as a separate element /input. Ex. with prototype: $('name').next() should get you /input.

button's value attribute

by airportyh posted at 09-29-2008 04:50PM - Comments (0)   crossbrowser javascript programming
If you use a button element as a submit button in a form, like:
<button id="mybutton">My Button</button>
$('mybutton').value in FF will get you an empty string whereas in IE you would get "My Button"

Making justtodolist work for chrome and safari

Since Chrome is so great, I wanted to use it for all my browser needs. But the apps I've been working on myself have not been targeted for WebKit - the rendering engine used by chrome, and also used my Safari. This is mostly due to laziness on my part - having to handle two browsers at a time is chaos enough. But Safari compatibility is on my todo list for more than one of my projects, and chrome is a good push for this cause. And so I went in today and made just todo list. compatible with Chrome and Safari. The differences I encountered were:
  1. This is really prototype specific - prototype adds an empty underscore parameter for all Ajax request for WebKit browsers. Because apparently, Safari errors out when you try to post with an empty body on XHR calls. And, who knows, this might already be fixed in WebKit. I happened to have code that was not handling this fact on the server side. This was no biggy.
  2. This is an error on my part really, but I had a form with a text input inside. But also registered for the key events on the text input so that when enter is pressed I called form.submit(). The key event code is really unnecessary because an enter on the text input triggers the form submit on both FF and IE. So, although on the other 2 browsers this was no problem, in WebKit this triggers 2 posts. So... just DON'T do this.

Google Chrome

by airportyh posted at 09-02-2008 10:33PM - Comments (0)   browser google javascript programming tech
Google just released this awesome browser. They have a great comic strip walking you through what the big deal is about, which is a must read for web developers. I've been using the browser for half a day and it's been pretty rock solid for all the sites I normally use. Javascript is clearly MUCH faster thanks to the v8 engine, which I think Steve Yegge alluded to a while ago. I like many of it's different features, and think it's a great boost to the browser world as well as javascript, i.e. the NBL(Next Big Language).

Play Date with jQuery

by airportyh posted at 08-31-2008 11:47PM - Comments (0)   javascript jquery programming prototype
I had a new toy project and started out with my trusty sidekick: prototype.js but a bit of the way in i decide to try my hand at jQuery instead, since I've already read a lot about jQuery and really like the monad-like paradigm which allows you to write elegant "flow" code without having to worry about null values anywhere in the chain.

It was quite easy translating my existing prototype.js code to jQuery(probably just around 30 lines).
  • The end result was probably 20% more succient.
  • I love the css 3 capable selectors, it's very refreshing to be able to use attribute and partial string match selectors which normally you don't get to use for your work. 
  • I also like the way attributes are set as chained methods(again, in the monad flavor), you do something like $('#myid').attr('value') to get the value and $('#myid').attr('value', 1) to set the value to 1. This again, allows you to chain stuff together. What's the point of this? ...I guess I just like the monad thing.
  • I think the jQuery syntax for behavioral javascript is prettier than prototype.js + lowpro.js
I really have nothing bad to say about jQuery. Even the UI components seem pretty on par with prototype.js, there's jqueryui, from which I used the autocomplete plugin. It's a little bit unfortunate that I had already invested about 1800 lines of javascript code on writing javascript components based on prototype.js and scriptaculous at work, otherwise had I started over I would very probably use jQuery. I will definitely go jQuery for my other projects.

Are there anything from prototype.js that I miss? Well, yes, I miss the array extensions from prototype, which lets you use ruby/smalltalk/lisp-like internal iterator style list operations. jQuery has a $.each, but it's not quite as pretty... but it gets the job done. And I haven't looked, but I am not sure there's an equivalent to prototype's Event.KEY_RETURN, Event.KEY_BACKSPACE and such in jQuery. Also, I had gotten comfortable to the OO model from prototype, and doing without it will be different, but then again I am adaptable. Plus, there's nothing at all stopping you from using jQuery and prototype.js together.

The z-index IE bug

by airportyh posted at 08-23-2008 02:38PM - Comments (0)   css javascript programming
Yeah, the z-index IE bug, have you heard of it? I was bitten by it a couple of days ago. In my case, I had a list of text fields in a form layed out from top to bottom. The problem is, I have these interactive drop downs on that can activate just under the text fields when you focus on the field and there is a validation error, which I use relative/absolute positioning to get in the right place, and so the position: relative declaration triggers the IE bug which causes the text field beneath the one that has the focus to occlude its drop down. My solution? I now have a javascript snippet that runs as the dom is ready that sets the z-index of all the containers(the one that has position: relative) of the text fields in descending order. So for example, if you have 10 text fields, the first one would have its z-index: 10 and the last one would have z-index: 1.

In a related note, if you use the relative/absolute positioning technique, the child element that has position: absolute is considered the child of the parent element that has position: relative in terms of z-index, which if you then have overflow: hidden on the parent element or its ancestors, the child element would get cut out if it's position is out of bounds, vs if you didn't have position: relative set on the parent element then the child would not get cut out because it's considered to be the child of the root element in terms of z-index.

The Hidden Singleton with Javascript

by airportyh posted at 08-23-2008 01:04PM - Comments (0)   javascript programming
This pattern is well documented else where, I think I first saw it in the Definitive Javascript book. Let's say you want to provide a function that does stuff with a static variable, but don't want that static variable to be global(visible to the outside)? You would do this:

myfunction = function(){
    var mysingleton = new Singleton();
    return function(x, y){
        return mysingleton.doit(x,y);
    };
}();


so now you can do myfunction(1,2) which in reality calls the doit method of the same instance of Singleton everytime. As a more concrete example, you can create a counter function like this:

counter = function(){
    var i = 0;
    return function(){
        return i++;
    };
}();


Each time you call counter() the result increases by 1.

A variation of this pattern is to extend an existing function/method by replacement. This is similar to the ruby practice of aliasing a method to a different name and then sticking a new method in it's place that at some point calls the original version. Anyway, for example, let's say you have an existing function from an existing library... say scriptaculous effects' Effect.Shake. You want to change the default options without having to rename the function(so that all your existing code that depends on it doesn't not need to change), you would do:

    Effect.Shake = function(){
        var original = Effect.Shake;
        return function(element, options){
           
original(element, Object.extend({
                distance: 5,
                duration: 0.5
              }, options || {}));
        };
    }();


So I've changed the default distance to 5 and duration to 0.5 throughout my app for any calls to shake() by adding this in one place only.

Relativize that thing: todays CSS war story

by airportyh posted at 08-22-2008 12:43AM - Comments (0)   css html javascript programming
Today, I had a seemingly simple problem: position a floating label element inside of a text input field, inside a elastic layout. To achieve an effect like:

Moreover, I wanted to implement this as a generic javascript widget that I can reuse throughout the application. This was hard, real hard.

At first, I just used position: absolute and set the position of the label relative the the root document, getting the coordinates required from the position and dimension of the companion text field. Well, this didn't work so well when the window is resized. Too bad we got an elastic layout, if we had a fixed width one I would have been done. My quick and dirty solution was to register the window.onresize callback and reset the positions of the labels whenever the window is resized. This actually worked well in IE, but not so in FF. The problem with FF is that the callback is invoked too sparsely, it's just not responsive enough when you are just dragging the corner of the window around, but you see these labels in all the wrong places while you are dragging around the corner of the browser until you leave your mouse still for a second, at which point the labels receive the event and jump to where they should be. This just plain looks bad, and although your users probably won't resize the window too much, I think it will definitely give the impression of a cheesy app.

So, my first attempt at a work around is a brute force one. I wrote my onresize callback functionality for FF that is more responsive. Here was the code.
 /* this is a funny hack in FF to get window resize events more often */
var ffonresize = function(){
    var listeners = [];
    var dim = document.viewport.getDimensions();
    var pe = null;
    pe = new PeriodicalExecuter(function(pe) {
        var nd = document.viewport.getDimensions();
        if (!(nd.width == dim.width && nd.height == dim.height)){
            dim = nd;
            listeners.each(function(l){l(nd)});
        }
    }, 0.2);
    return function(listener){
        listeners.push(listener);
    }
}();

/*
...
*/
if (Prototype.Browser.Gecko)
    ffonresize(this.__onResize);
else
    Event.observe(window, 'resize', this.__onResize);


This improved the situation, but... not good enough. Then I thought, there must be a way with position: relative to do it. After all, isn't that what it's for?

I tried making the label element position: relative, but this didn't work: you could shift the position of the element relative to where it would have been, but the space for where it would have been is still taken up, and now it's an empty space...
I did some research. One of the best resources is quirksmode again, this is also a helpful article. It turns out the common practice to use is to have a container that is relative and then a child under it that is absolute, which will cause the child to use the parent's position as the reference point. But trying the things out didn't work at first. After some trial and error, I figured out that, not only does the parent have to be position: relative, it also had to be display: block. My parent container happened to be table cells, so I either had to set their display to block or add a div under them. Setting their display to block didn't work for me because it completely messed up the layout of the table, so I had to go with the second method.

Adding the div was annoying because not only did I have to go to a few different places in the app to add the markup, it also made my widget depend on more. Of course, I guess I could inject the div dynamically, but I haven't tried that yet. So, this worked, I no longer had to use the onresize callback and reset the position of the labels, I just set:

position: absolute;
top: 2px;
right: 5%;


Top of 2px to give the top some space, right of 5% to give enough space for the label. Both are relative to the divs I newly added. Well, this kinda worked... except for my short textfields. See, I had long text fields that take up almost 100% of the width of the parent, but also shorter ones that take up about 60%, so while it worked well for the long textfield, sitting right inside it on the right edge, it was well outside of the short textfields. I wanted to use javascript to figure out what's the % of the width of the text field, which I could use to calculate where the label should be, but that number is in my css, and using javascript you can only get dimensions in terms of pixels, i.e., all the percentage info is lost.

What to do? Well, I calculated the percentage by doing a division between the text field and its parent's width in pixels, this is my code(using prototype.js):
right: (1 + 100 * (1 - this.field.getWidth() / this.field.up().getWidth())) + "%"

Yeah, it's pretty crazy, but it worked, beautifully. It works in IE7, FF3, and Safari, didn't work in Opera, but that could have been because other javascript bugs I had wrt Opera.

function dot toString()

by airportyh posted at 07-15-2008 01:53PM - Comments (0)   crossbrowser javascript programming
function.toString() has different behavior between IE and FF. FF collapses the parameter list onto one line, while IE leaves it untouched. Ex:
function f(
  param1,
  param2,
  param3){
  ...
}

f.toString();

In FF you would get something like:
function(param1, param2, param3){
...
}

in IE:
function f(
  param1,
  param2,
  param3){
...
}


In IE, this breaks function.argumentNames() in prototype.js, so don't break the parameter list into multiple lines if you are using prototype.js, or until they fix it. Also, notice that FF removes the name of the function in the toString() output.

prototype descendantsOf works different in FF than IE

by airportyh posted at 06-30-2008 12:23PM - Comments (0)   crossbrowser javascript programming
I haven't dug down to the bottom of this but basically Element.descendantOf(elm, ans) gives different results from IE vs FF.