Monday, October 25, 2010

RightJS 2.2 Notes

I'm cooking a new evil plan for RightJS 2.2 release and would like to share some thoughts and notes, so you knew what's going on and where are we heading.


Native Fx

We are living in an interesting moment. Native CSS transitions are finally becoming reality. Safari does it, Chrome does it, Opera does it, FF4 does it (they promised they will include the feature into the 3.7 release). IE9b does not. Rumors has it, the feature will be in the final release, but I have my doubts it will happen.

Anyways, now, when the majority of sane browsers support the feature, I think it's the right time to start using native CSS transitions as a default option for our dom-morph effects. It is faster, simpler and more reliable.


Better UJS

The current implementation of UJS in RightJS works with an event target property only. The trouble with this solution is that when you have something like

<div id="one">first
<div id="two">second
<div id="three">third</div>
</div>
</div>

and you attach an event listener to say the top one

"div#one".onClick(function() {
...
});

it will reacts only if the user clicks on the div#one itself and will successfully ignoring clicks on the inner element. Sometimes that's what you need, but in majority of the cases it creates more confusion than helping.

I'm still thinking about this one, but there is a good chance that the logic will be changed and our UJS will mimic the normal event listeners behavior and react on inner elements as well.

Hey! You will be able to make UJS stuff within UJS stuff! :)


Cookie plugin

At the beginning it seemed like a good idea to have a basic Cookie wrapper out of the box, but later I realized that on majority of my projects I don't use it. Well I assume you have pretty much the same experience.

So I think the cookie module will be kicked out of the core into an officially supported plugin. it's not much, just half a KB of gzipped code, but I guess we can fill this half a K with something more useful in everyday life.


IE8 And Pals

IE8, or as it known in some circles "IE7 on steroids" is kinda of troubling browser. The problem is that on a good half of the pages this darn things automatically falls into IE7 mode and therefore downloads the "olds" module, on the other half, it still has some troubles with native css selectors because some of CSS3 constructions are not supported, which consequentially makes some wonder-people to wonder how "right" right.js exactly is?

Furthermore the change/submit events still don't bubble and we carry quite large chunk of code in the core, to work this thing around.

So I was having that wild thought in my head, that we could ditch IE8 and pals support into the olds module so we could fix those things in there and not bother the core.

Currently, I'm considering the idea of making the line between the old and new browsers right where the CSS transitions support starts, which will effectively drop the whole IE support into the olds module.

That probably will make some jquery folks to moan that we are unfair towards them, but I'm looking into my glass ball and it says that after all the cutting and stitching, RightJS core size could drop below 12k.

Well, at least that the target. Besides there is still a tiny chance that IE9 folks will hear the voice of sanity and add css-transitions into it, then this distinction will be perfectly justified.


---

Anyhow, those are the notes and thoughts. Let me know if you have something on your mind about that

Thursday, October 14, 2010

Cloned SELECT elements in IE

What I love about IE browsers is that genuine feeling of moral superiority that you unavoidable accumulate inside yourself when you're dealing with its features. Found one more "treasure" that killed half of my day.

The story goes like that. Say I have a SELECT element and then you clone it a bunch of times and populate with new content, kinda like that

var original = document.createElement('select');
clone = original.cloneNode(false);
document.body.appendChild(clone);

$(clone).html('<option>boo hoo!</option>');

And that all works fine, but now say you update the content in another function, say an ajax callback or something

var original = document.createElement('select');
clone = original.cloneNode(false);
document.body.appendChild(clone);

setTimeout(function() {
$(clone).html('<option>boo hoo!</option>');
}, 0);

You would expect that this is no different from the first example and here is where they will get ya. Not only it does not update the options list (it will be empty), but it also somehow manages to show you that the innerHTML property was actually updated and contains all the new data.


// .....

setTimeout(function() {
$(clone).html('<option>boo hoo!</option>');
alert(clone.innerHTML); // -> '<option>boo hoo!</option>'
}, 0);

All versions affected 6,7 and 8 (didn't test in 9 though)

In case you really really need to update a cloned SELECT element in an async callback, here is a hack how you can do that


// ....
setTimeout(function() {
$(clone).html('<option>boo hoo!</option>');

var dummy = document.createElement('option');
dummy.text = 'dummy'; // DON'T use innerHTML in here!
clone.add(dummy);
clone.removeChild(dummy);
}, 0);

It will fix the problem, but you'll need to add some checks in there to ensure it's actually IE you're dealing with.

That's the whole gotcha. Hope will save someone's day

Saturday, October 2, 2010

Making Pretty CLI Applications In Ruby

Sometimes we need to process large amount of data in Ruby, convert things from one format to another, process a large database, etc. And when you start implementing those things as rake tasks or something like that you need some feedback, say to see the progress and so one. Normally people would use puts

index = 0
count = things.size
things.each do |thing|
do_something_about thing

puts "#{index +=1} of #{count}"
end

But when you have several thousands or millions things to process this approach doesn't work, because it will just blow into the console, which is ugly and well... there are ways to do it much better, prettier and more professionally looking.

There are gems and libs that will help you to do it properly, but in this article I'd like to show how it actually works internally.


Strings Rewriting

One of the first things you might want to learn in order to make seriously looking CLI app is how to rewrite strings all over. It is a bit tricky in Ruby so here how it looks like. First of all you need to learn the "\r" symbol, which is called "caret return" and well it returns the caret. A simple example will demonstrate. Say you have a line of code like that

puts "one\ranother"

when you run it, you will see in the console a string like "another" and what's happening is that ruby will print "one" then return the caret and print "another" over it, so that you see the last one only. But the trouble is that if you'll write something like that

puts "one"
puts "\ranother"

It won't work and you'll see two strings in the console "one" and "another", and because of that if you'll put into your loop something like that

puts "\r#{index += 1} of #{count}"

it won't work either and you will see the same ugly roll of strings. To make it working you have to use the a combination of the print and STDOUT.flush calls, kida like that

8.times do |i|
print "\r#{i}"
STDOUT.flush
sleep 0.1
end

In this case it will print a string and stay on it. STDOUT.flush dumps the current stdout into the console, and on the next iteration, it will normally go to the beginning of the string and write it over as you needed.

But it is still not everything. If you run a piece of code like this one

%w{looooong short}.each do |str|
print "\r#{str}"
STDOUT.flush
sleep 0.5
end

You will see that on the second iteration, the previous line won't be entirely overwritten and instead of "short" you will see "shortong", to make it work properly you need to write a long enough string that contains spaces at the end, for example

%w{looooong short}.each do |str|
print "\r#{str.ljust(80)}"
STDOUT.flush
sleep 0.5
end

String#ljust makes a string of the given length by filling the remaining places with spaces. This way you will always overwrite 80 symbols of the line in the console.

To wrap it up nicely you might create a simple function and your loop will look like that

def print_r(text, size=80)
print "\r#{text.ljust(size)}"
STDOUT.flush
end

index = 0
count = things.size
things.each do |thing|
do_something_about thing

print_r "#{index +=1} of #{count}"
end
puts "\n" # <- a final new line



Displaying the progress

With the trick above you will be able to show a constantly updating status line, but there are still some meat on this bone. Showing the user things like "345 of 87654" is not particularly user friendly, because it might be a bit annoying to calculate the actual progress in your head all the time. Would be nice to show the progress in percents as well. Happily it is very simple to do using placeholders

print_r(
"%d of %d (%d%%)" %
[index+=1, count, (index.to_f/count * 100)]
)

The other usual problem with status reports is that you might have particularly large set of things, say several millions of them and your script might process several thousands of them per second. In this case hitting your console several thousands times per second will seriously slow the process down, so you might need a way to skip some steps and print reports in some periods of time. You can do that the following way

index = 0
count = things.size
step = count / 1000 # 1/10th of a percent

things.each do |thing|
if (index += 1) % step == 0
print_r "....."
end
end

As you can see we defined the step variable and then skip all the non-round iterations. In this particular case it will make the script to update the report every 1/10th of a percent of the job done. Which is in most cases is not a big drawback and still provides the user with progress updates.

You also might think of ETA calculations, but you probably can figure it out on your own now, it's very simple.


Add Some Colors

And the last thing I'd like to show is how to make colors in the console, which might make your application look even cooler. Some developers already know how to do that, but some don't. So here it is.

Basically it is very simple and in some ways similar to HTML tags. You use things called escape sequences which are just some markers like tags, you have an opening one, and you have a closing one, like that

puts "\e[32mGREEN TEXT\e[0m"
puts "\e[31mRED TEXT\e[0m"
puts "\e[36mBLUE TEXT\e[0m"

As you can see, the closing sequence is always the same and the opening one differs only by a number, and this number is basically describes the properties of the following text. It might be a color, or a blinking effect, you can nest them just like normal HTML tags and so one. You can find full list of options on wikipedia

The only trouble with those things is that the format of escape sequences differs from a platform to platform. The example above is for OSX terminal. How to make those things working in DOS and Linux you can find that on the same wikipedia page.


This is about it. Now go and make the world prettier!