Archive for the ‘Javascript’ Category

Rails and JavaScript: page.call gotchas

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

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:

  1. Lua 3.44
  2. PHP 9.73
  3. Python 11.20
  4. Ruby 12.30

Erlang, Ruby and PHP battle it out!

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:

  1. C (obviously): 0.40s
  2. Erlang (smp): 3.95s
  3. Erlang (non-smp): 5.66s
  4. Ruby: 15.31s
  5. PHP: 19s (or so)
  6. 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:

  1. C (obviously): 0.40s
  2. Erlang (smp): 3.95s
  3. Erlang (non-smp): 5.66s
  4. PHP5: 8.9s (or so)
  5. Ruby: 15.31s
  6. 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

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

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).