Archive for the ‘Javascript’ Category
Rails and JavaScript: page.call gotchas
Posted by Giovanni Intini | Filed under Ajax, Javascript, Programming, Prototype.js, Rails, Ruby, Ruby on Rails
Ruby on Rails has wonderful out of the box javascript support, but sometimes implementing dynamic user interfaces is not so easy as it seems.
In an application I’m working on I have a list of people with a checkbox each. In the load event of the page I add a click handler to every checkbox using this javascript code:
$$('.ConfermaInvitati').each(function(element) { Event.observe(element, 'click', clickHandler); }); // ... function clickHandler(event) { var e = Event.element(event); new Ajax.Updater(e.up(), 'my/invited/toggle', { parameters: { id: e.up().up().id }, onLoading: function() { e.src = "/images/admin/spinner.gif"; }, onSuccess: function() { new Ajax.Request('my/refresh', {}) } }); }
This works fine until I add a new person via an Ajax call. That person won’t have a clickHandler because the element wasn’t on the page when I called the click handler. So I thought it was time to test page.call in the render :update block I had in the rails application.
I tried this code:
render :update do |page| # Do stuff that creates the new objects and adds it to the page # The data I need is in @invited page.call("Event.observe($$('##{@invited.permalink} .ConfermaInvitati').first()), 'click', clickHandler)")
Obviously that didn’t work, and it turned out I have to read documentation before doing fancy things
The rails docs told me that I had to use call passing the function name as the first argument and an array of parameters as the second argument, the problem is that call turns all the parameters into strings—this means I could not pass the clickHandler function to Event.observe.
I found the solution in <<. If you do page << "foo", foo will be evaluated as raw javascripts. This meant I was able to do
page << "Event.observe($$('##{@invited.permalink} .ConfermaInvitati').first()), 'click', clickHandler)
and finally have the functionality I was looking for. So remember, don’t page.call if you need to pass javascript variables to your functions.
The battle of the languages part II
Posted by Giovanni Intini | Filed under Java, Javascript, Lua, PHP, Programming, Ruby
My previous post about a programming contest I had with my friends was wildly popular. Much much more than I even thought possible.
I started with a simple comparison of PHP, C, Ruby, Erlang and Javascript and ended up with lots of comments where people posted interesting implementations in more and more languages, even obscure ones (to me) like Haskell and Ocaml.
I owe everyone a fairer benchmark so I will do the test again, this time testing the following languages:
- C
- Common Lisp
- Erlang
- Haskell
- Javascript
- Java
- Ocaml
- Perl
- PHP
- Python
- Ruby
I need submissions for most of these languages, and I actually am quite open to submissions for the languages I speak
The rules are simple, the program has to store the results in an array (not just count them) and has to run without any strange libraries or compilers or compiler switches. To avoid interpreter starting time problems, please submit programs that autotime themselves.
As usual we’ll find the pythagorean triplets up to 5000. The reference implementation is the following, in Ruby:
t = Time.now result = [] 2.upto(5000) do |c| 1.upto(c-1) do |b| a = Math.sqrt(c*c - b*b) result << [a.to_i, b, c] if a.to_i == a end end puts Time.now - t
This code takes 15.70s to run on my macbook pro.
Now it’s your turn!
Update: Lua version by Sindisil
local tt = os.clock() local result = {} local c for c = 2, 5000 do local b for b = 1, c-1 do local a = math.sqrt(c*c - b*b) if a == math.floor(a) then result[#result+1] = { a, b, c } end end end print(os.clock() - tt)
It takes 5.48s to run on my box.
Update: new Ruby version.
include Math a, b, c = 0 result = [] 2.upto(5000) do |c| d = c * c 1.upto(c-1) do |b| a = sqrt(d - b*b) result << [a.floor, b, c] if a.floor == a end end puts Process.times[0]
Following Gabriele Renzi’s suggestions we now have a faster ruby version: 12.30s
Update: faster Lua version from Chris Swetenham, it runs in 3.44s
local tt = os.clock() local result = {} local c local n = 1 local math = math local sqrt = math.sqrt local floor = math.floor for c = 2, 5000 do local b for b = 1, c-1 do local a = sqrt(c*c - b*b) if a == floor(a) then result[n] = { a, b, c } n = n + 1 end end end print(os.clock() - tt)
Update: PHP version by Fullo
<?php $start = microtime(true); $a = $b = $c = 0; $result = array(); for ($c = 2; $c <= 5000; $c++) { for ($b = 1; $b < $c; $b++) { $a = sqrt($c*$c - $b*$b); if (intval($a) == $a) $result[] = array($a,$b,$c); } } echo (microtime(true) - $start); ?>
It runs in 9.73s.
Update: Python version from ludo, it runs in 11.2s
from time import clock start = clock() from math import sqrt results = [] for c in xrange(2, 5001): d = c * c for b in xrange(1, c): a = sqrt(d - b * b) if a % 1 == 0.0: results.append((a, b, c)) print clock() - start
The results for now:
- Lua 3.44
- PHP 9.73
- Python 11.20
- Ruby 12.30
Erlang, Ruby and PHP battle it out!
Posted by Giovanni Intini | Filed under Erlang, Javascript, PHP, Programming, Ruby
Update: here’s the followup!
Yesterday I attended PHP Day, in the beautiful city of Verona, and while going there by train, together with my friend Federico Feroldi, I told him that in a test I made a week ago Erlang was much slower than ruby in finding pythagorean triplets.
That was a partial lie, since the ruby implementation was somewhat optimized, while the erlang implementation wasn’t at all. So we decided to rewrite both programs using the same optimized algorithm and then test their speeds.
This is the ruby implementation of a method that counts the number of pythagorean triplets up to N:
def pythag(n) result = [] (2..n).each do |c| (1...c).each do |b| a = Math.sqrt(c*c - b*b) result << [a.to_i, b, c] if a.to_i == a end end result end
Then we coded it in Erlang. The code I’m going to show you is more complex than the ruby code because we took advantage of the parallelization features of the Erlang language:
-module(pythag). -export([bard/1, pbard/1]). my_is_integer(X) -> round(X) == X. pbard(N) -> pmap(fun(C) -> [ {C, B, trunc(A)} || B <- lists:seq(C, N), A <- [math:sqrt(C*C + B*B)], my_is_integer(A) ] end, lists:seq(2, N)). bard(N) -> lists:map(fun(C) -> [ {C, B, trunc(A)} || B <- lists:seq(C, N), A <- [math:sqrt(C*C + B*B)], my_is_integer(A) ] end, lists:seq(2, N)). pmap(F, L) -> S = self(), %% make_ref() returns a unique reference %% we'll match on this later Ref = erlang:make_ref(), Pids = lists:map(fun(I) -> spawn(fun() -> do_f(S, Ref, F, I) end) end, L), %% gather the results gather(Pids, Ref). do_f(Parent, Ref, F, I) -> Parent ! {self(), Ref, (catch F(I))}. gather([Pid|T], Ref) -> receive {Pid, Ref, Ret} -> [Ret|gather(T, Ref)] end; gather([], _) -> [].
The pythag function has been named bard, as in The Bard
The pbard function fires up a thread for each iteration of the outer loop and then gathers all the result back. This allows for up to 50% performance increase when using dual core CPUs (like my Macbook Pro
).
Once we coded it in two languages we couldn’t stop, so here’s a PHP implementation, a Javascript one and, last, but not least, a C implementation, because you can never forget C when you need speed
PHP:
<?php $i=0; for ($c = 2; $c <= 5000; $c++) { for ($b = 1; $b < $c; $b++) { $a = sqrt($c*$c - $b*$b); if (is_int($a)) { $i++; } } } print("$i"); ?>
JavaScript:
function pythag(n) { var a,b,c,i for (c = 2; c <= n; c++) { for (b = 1; b < c; b++) { a = Math.sqrt(c*c - b*b); if (Math.floor(a) == a) { i++; } } } return i; }
C:
#include <stdio.h> #include <math.h> #define MAX 5000 int main() { double c, b; int i = 0; double a; for (c = 2; c <= MAX; c++) { for (b = 1; b < c; b++) { a = sqrt(c*c - b*b); if (trunc(a) == a) { i++; } } } printf("%d\n", i); }
To test the various relative speeds I ran them from the shell using time (php ruby and c), or used the internal timer (erlang), or ran them in firefox (js only actually).
The results were interesting. At the first run, using 5000 as N in the pythag functions the order was:
- C (obviously): 0.40s
- Erlang (smp): 3.95s
- Erlang (non-smp): 5.66s
- Ruby: 15.31s
- PHP: 19s (or so)
- Javascript: couldn’t even finish running because firefox said it was taking too much time
Fullo passed by and asked what we were doing, I told him I was testing languages and that PHP was dog-slow. He said it couldn’t be and asked me what version of PHP I was using. I checked and it was PHP 4.x.x.
After downloading and compiling PHP5 I ran the tests again and the final result was this:
- C (obviously): 0.40s
- Erlang (smp): 3.95s
- Erlang (non-smp): 5.66s
- PHP5: 8.9s (or so)
- Ruby: 15.31s
- Javascript: couldn’t even finish running because firefox said it was taking too much time
Now the numbers make sense. Doing these comparations was a nice experience, because when you implement the same thing in different languages you always learn something about optimization and code beauty.
A praise for jQuery
Posted by Giovanni Intini | Filed under Ajax, Javascript, Programming, jQuery
I’ve been doing some drupal development lately, and had to make the switch from Prototype to jQuery (by the way it’s the same switch WordPress made in 2.2).
At first I had to learn the different approach jQuery has to manipulating the DOM, but once I got the hang of it I really started appreciating jQuery.
The main difference I’ve found is that I prefer programming Prototype via the Rails helpers, while programming jQuery is so fun I prefer to do it directly in JavaScript.
Actually it turned out so fun that I keep adding content to pages and changes links in JS, while I should do that in the backend.
Here’s an example, from a drupal module I wrote:
$(document).ready(function() { $('#comments h2').after('<p class="slider"><a href="#" class="slide-open">Espandi tutti i commenti</a> - <a href="#" class="slide-close">Contrai tutti i commenti</a></p>'); $('.comment .expand').html("[+]"); $('.comment .content').hide(); $('.comment h3').click(function() { $(this).siblings('.content').slideToggle(); if ($(this).children('.expand').html() == "[-]") { $(this).children('.expand').html("[+]"); } else { $(this).children('.expand').html("[-]"); } return false; }); $('#comments .slider .slide-open').click(function() { $('.content').show(); $('.comment .expand').html("[-]"); return false; }); $('#comments .slider .slide-close').click(function() { $('.content').hide(); $('.comment .expand').html("[+]"); return false; }); })
What does this code do? Add a couple of links after the comments heading, hide all the comments and add a slidedown/up functionality to them.
The best thing of adding this functionality in the frontend is that when the user has js disabled or is using a non-js browser the site falls back to the normal behavior.
Javascript Classes
Posted by Giovanni Intini | Filed under Ajax, Javascript, Yahoo
Before you go “hey, but js doesn’t have classes” let me tell I meant classes as in “school classes”
I don’t usually like repeating myself and writing posts about links I put on my del.icio.us, but this time I have to. I’m having a great time learning from these videos of Doug Crockford’s presentation of JS @ Yahoo!
Wonderful stuff there, after 15 minutes of the first video I already learnt some JS tricks I didn’t know (or didn’t care about).