749Javascript, Array and For-Loops

Ok, looping over an array is something that we do all the time, for most of us it has become a second nature.

var myArray = ["a", "b", "c", "z"];

for (int i=0; i

But I recently came across a Javascript loop that puzzled me slightly.

var myArray = ["a", "b", "c", "z"];

for (var i=0,f ; f=myArray[ i++]; ) {
    console.log(f);
}

Let's have a closer look what's happening here. As a reminder, For-statements have the following structure: for (initiation; condition; increment) { block }

In the initiation, variables are initiated; Condition tests this var, and if it returns true, continues another loop; and here's something funny; the increment is left blank. Don't panic, because we are already incrementing i at the condition test.

This is equivalent:

var myArray = ["a", "b", "c", "z"];

for (var i=0,f ; f=myArray[ i]; i++) {
    console.log(f);
}

This, however, is not the same:

var myArray = ["a", "b", "c", "z"];

for (var i=0,f ; f=myArray[ ++i]; ) {
    console.log(f);
}

i gets incremented before it is used to traverse myArray, therefor resulting in this output:

b
c
z

In nice and simple arrays like in this example, it should not make any difference to test the array length at every time coming around, but a larger ones it might be beneficial.

As usual, take care that the array does not contain any falsy objects. And don't loop an object that way.

Thanks to the Re-introduction to Javascript https://developer.mozilla.org/en/a_re-introduction_to_javascript for clarifying that issue for me.

Update

Turns out things are not so clear after all. Let's consider the following case: I have an array of numbers, I'd like to get the sum of all numbers in the array. One way to do it:

var myArray = [1,2,3,5,7];
for (var i=0, sum=0; i

So, shouldn't this work too...?

var myArray = [1,2,3,5,7];
for (var i=0, sum=0; sum = myArray[i]; i++) {};
console.log(sum);       // undefined

Apparently not... I am trying to find out why not.

This, on the other hand works:

for (var i=0, sum=0; this[i]; sum+=this[i++]){};

737Processing Math convenience methods in pure Javascript

Like everybody else, I am huge fan of Processing, and like everybody else I find myself working more and more with Javascript.

There is a implementation port of Processing (aptly called ProcessingJS) by John Resig of jQuery fame. It's still lacking the 3D features, but not because they would be hard to implement in JS, but rather the OpenGL bindings in the browsers don't exists wide-spreadly (yet). Let's hope WebGL is going to change that soon.

After working a lot with Processing, one becomes quite spoilt with it's methods. The two best kept secrets of Processing are on the one hand the matrix state operations - pushMatrix(), and popMatrix() - and on the other hand the very handy map() method, basically mapping a number from one range to another.

In Javascript's canvas you have the pushMatrix() popMatrix() equivalents as save() and restore(). The map() methods does not exists as such, but it is easy implemented. I took a look at the Processing source and rewrote the Java methods in Javascript.

var p5 = {};

p5.sq = function(a) {
    return a*a;
}

p5.constrain = function(amt, low, high) {
  return (amt < low) ? low : ((amt > high) ? high : amt);
}

p5.degrees = function(radians) {
  return radians * (180/Math.PI);
}

p5.mag = function(a, b) {
  return Math.sqrt(a*a + b*b);
}

p5.dist = function(x1, y1, x2, y2) {
  return Math.sqrt(p5.sq(x2-x1) + p5.sq(y2-y1));
}

p5.lerp = function(start, stop, amt) {
  return start + (stop-start) * amt;
}

p5.norm = function(value, start, stop) {
  return (value - start) / (stop - start);
}

p5.map = function (value, istart, istop, ostart, ostop) {
    return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
}

The code including comments and a minified version is also up on GitHub, show you love and fork it. https://github.com/trembl/p5.Math.js/

Update - Extending Math

Rather than creating a dedicated object, and as all the function are kind of related to Math, I thought it would be a good idea to extend the Math object itself. (Well, it's a good idea for my project - your mileage, especially if you are flying with a lot of libraries might vary).

And how to you extend a Javascript build-in object? With prototype, right?

Math.prototpe.sq = function(a) {
    return a*a;
}

Wrong. Because Math does not have a constructor, it therefore hasn't been constructed and therefore does not have the prototype method. It has been instantiated and you add methods (or functions?) like this:

Math.sq = function(a) {
    return a*a;
}

You get the idea. The new code also lives at GitHub, check it out. https://github.com/trembl/p5.Math.js/

721jQuery’s Live Clicks

Update Since jQuery 1.7 live() is marked for deprecation and should not be used any more. Use on() instead.

When content is dynamically created by jQuery it is not automatically inserted into the DOM. Therefore, if you dynamically add - for example - a link, and you want to capture a click on this link, it is necessary to use the live() function.it is necessary to use the on() function.



NG. The link is added to the container, but the click function is not called.

// $('.container > a').live('click', function(e) {  // pre jQuery 1.7
$(document).on('click', '.container > a', function(e){
    // do things
    e.preventDefault();
});

OK. The link is added to the DOM, and the click function is called.

Yeah.

Of course the same also goes for appended elements:

$("#container").append('');

// ...

// $('#container canvas').live('mousedown', function (e) {
$(document).on('click', '#container canvas', function(e){   // pre jQuery 1.7
    console.log(this.id);
});

707Digging a tunnel to a remote SFTP Server

The problem seems to be familiar. The host (let's call it target machine) you want to connect to is in a corporate network, you are not able to directly connect to it. However you have SSH access to another computer (the intermediary machine) on the same network, which means your are able to SSH your way into the intermediary machine and from there to the target machine.

So far so good.

Whereas the command line has its merits, for some jobs it's more convenient to use an FTP client (like Cyberduck). Cyberduck does not support SSH tunneling by itself, but there are way to make it work.

First, we will create an SSH tunnel to the intermediary machine and second we will set this tunnel up as a proxy through which Cyberduck will be able to connect to the target machine.

1. The SSH Tunnel

ssh -qTnN -D 4040 -C username@intermediary

Key in the password for your intermediary server, and its connection should be available for your localhost:4040.

2. The SOCKS Proxy

And localhost:4040 is were we are pointing our SOCKS proxy to:

2. Back to Cyberduck

Now, with the tunnel active and the proxy configured, just enter the login credentials of the target machine in your FTP application - and voila - it should work. At least it worked for me.

703Blocking hosts in /etc/hosts

How to block access to websites on your personal computer. The /etc/hosts file maintains a records of redirects, it you want to block access to a particular site, redirect to your local machine, or whichever site you find appropriate. Not that most website forward host-to-block.net to www.host-to-block.net, so make sure to block the www site as well.

Open the file in your favourite text editor, make sure you have the permissions to open it.

sudo nano /etc/hosts

Add the following line to the file.

127.0.0.1       host-to-block.net
127.0.0.1       www.host-to-block.net

Flush the cache to make the changes immediate.

sudo dscacheutil -flushcache

Again. The crucial bit is to also block the www-site. That seems to be missing from a lot of descriptions/tutorials out there in the wild.

693Changing the Cursor with Events when dragging an HTML5 canvas

With jQuery document ready:

$(function(){
    var canvas = $('#testCanvas')[0];
    canvas.addEventListener('mousedown', function(e){
        e.preventDefault();
        e.stopPropagation();
        e.target.style.cursor = 'move';
    }, false);
    canvas.addEventListener('mouseup', function(e){
        e.target.style.cursor = 'default';
    }, false);
});

And without...

$('#testCanvas')[0].addEventListener('mousedown', function(e){
    e.preventDefault();
    e.stopPropagation();
    e.target.style.cursor = 'move';
}, false);

$('#testCanvas')[0].addEventListener('mouseup', function(e) {
    e.target.style.cursor = 'default';
}, false);

Based on this: http://stackoverflow.com/questions/2659999/html5-canvas-hand-cursor-problems

688Ruby Version Manager for OSX

Nice, simple and clean way to install the latest version of Ruby and Gems on OSX.

The Tutorial: http://pragmaticstudio.com/blog/2010/9/23/install-rails-ruby-mac

And here's also the direct link: http://rvm.beginrescueend.com/

682Remove empty array fields in PHP

array_filter($my_array)

array_filter WITHOUT a callback function removes 'false', 'null' and '' fields from an array.

680javascript:void(0) – the better a href=”#”

Using a href="javascript:void(0)" instead of a href="#" does not jump to the top. Sould have been clear, but still good to know.

677Forcing a Boolean value in Javascript aka ‘The double negative trick’

return !!someValueThatisNotBooleanButShouldBe;

I first encountered it at Mark Pilgrim'sDive Into HTML5. Anyone else remembers his classic Kant Pro Generator from the olden days?