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<myArray.length; i++) {
	console.log(myArray[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<this.length; i++) {
	sum += this[i];
}
console.log(sum);		// 18

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.

<script type="text/javascript" charset="utf-8">
$(document).ready( function() {
	$('.container').html('<a href="http://www.trembl.org">click</a>');
});
$('.container > a').click(function(e) {
	// do things
	e.preventDefault();
});
</script>
 
<div id="container">
</div

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('<canvas id="track' + trackNumber + '"></canvas>');
 
// ...
 
// $('#container canvas').live('mousedown', function (e) {
$(document).on('click', '#container canvas', function(e){	// pre jQuery 1.7
	console.log(this.id);
});

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

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?

654Find Largest Number in Javascript

Nice way and fast way of finding the largest number in an array.

var arr = [1233, 32, 442];
var largest = Math.max.apply(Math, arr);

http://ejohn.org/blog/fast-javascript-maxmin/

http://stackoverflow.com/questions/1379553/how-might-i-find-the-largest-number-contained-in-a-javascript-array

652PHP Arrays to Javascript Objects via JSON

Moving PHP Associative Array (Dictionaries, whatever..) over for use in Javascript. In JS Associative Array are actually objects, so we might as well make it into one.

echo "var data =" . json_encode($somatic, JSON_FORCE_OBJECT) . ";

233Modifying Quicktags in WordPress

Open:

/wp-includes/js/quicktags.js

Change/Add/Delete tags to your likening.

195UIWebView, Changing filenames with Javascript

Calling JS from webViewDidFinishLoading, modifying paths to local. Before that all the images had to be stored into the local path.

http://iphoneincubator.com/blog/windows-views/uiwebview-dynamically-modify-html-documents

Interesting direction, but still looking for an elegant way to mix external sites (HTML) with local content (images, scripts…)