825Prototypal Inheritance and it’s Problem with Objects

Prototypal inheritance in Javascript is one of these features that sets it apart from other languages. A quick reminder:

var myDog = {};
myDog.legs = 4;
myDog.type = "Dachshund";
myDog.color = "brown";
myDog.says = "wau wau wau";

var yourDog = Object.create(myDog);
yourDog.says = "wan wan wan";

console.log(yourDog.type, yourDog.says);
> "Dachshund", "wau wau wau";

console.log(myDog.type, myDog.says);
> "Dachshund", "wan wan wan";

myDog is the prototype for yourDog, together they for a prototype chain. Any properties that would be added in myDog would also be accessible in yourDog. If yourDog adds a property with the same name (yourDog.says), this new property is returned when called. If a property is not defined, but present in the prototype, it will shine through.

So far so good.

Let's say we have an Array of dogs and we would like to prototypal inherit that whole array.

var myDogs = []
// fill array with dog objects

Following the pattern from above, the way to make a yourDogs array should be like that:

var yourDogs = Object.create(myDogs);

Let's update the first dog of the new yourDogs array to say something else:

yourDogs[0].says = "wow wow wow";

One would expect, that - because of the prototypal inheritance - that the changed value would only hide the original value. Let's check:

console.log(myDogs[0].says);
> "wow wow wow";

Ouch. The value was not as expected added to the prototypal branch only, but also to the original object. The prototype object and its chained offspring have the same object. Why is that? The answer is, that only variable types of Number, String, Boolean, etc are passed by value. Objects - and Arrays are objects - are passed by reference. (Check with typeof() to confirm the type of a variable.). That means the objects in our arrays are one and the same, and therefore any change in would will also occur in the other.

Seems logical, but still expectations are betrayed.

Let's consider the following case, this time without dogs. You have an array with objects and you want to apply a filter to some properties of the objects, which should be collected in another array. But - and this is crucial - you don't want the original array objects to change.

var original = [];
// add many, many objects

Because we saw before, that any changes in a new object would also reflect in the old one, we might be tempted to make a deep copy of the new one and then make our changes.

var copy = [];
$.extend(true, copy, original);     // Yes, that's jQuery
copy.map(function(element) {
    // make our changes to element
    //return element;
}

It's works, but it's rather kludgy. It takes quite a long time to make the deep copy and the prototypal chain breaks by doing that. Note also that the return of the map() function is not assigned to a new variable, and that the function does not need to return anything actually - because we are operating on the object directly.

A better solution would be this:

var better = copy.map(function(element) {
    var protoype = Object.create(element);  // create prototypal inheritance
    // make our changes to element
    return protoype;
}

better is now an array of objects which are prototypal linked to the original array. Any newly added properties will only be added to the new array - covering any properties which are already present in the original one.

console.log(original[0].dog.says);
> "wau wau wau"
console.log(better[0].dog.says);
> "wau wau wau"

better[0].dog.says = "wuff wuff wuff";

console.log(original[0].dog.says);
> "wau wau wau"
console.log(better[0].dog.says);
> "wuff wuff wuff"

That would I would have expected in the beginning. The nice things about Javascript is, that even when in works in unexpected ways, it's usually fairly trivial to align it again with your imagination. And sorry for bringing the dogs back.

819Single, Multiple Files and Javascript’s FileReader API

Getting a single file (with convenience jQuery event handler)

     
$('#open #chooseFile').change(function(e){
    var fileList = e.target.files;
    // get the one and only file
    var file = fileList[0];
    // further process file content...
    var reader = new FileReader();
    reader.readAsText(file, "text/plain");      
    reader.onload = localLoaded;
    reader.onerror = localError;
    // ...
});

Getting multiple files:

           

$('#open #chooseFile').change(function(e){
    var fileList = e.target.files;
    // loop over the files

    for (var i=0, file; file=fileList[i]; i++) {
        var reader = new FileReader();
        reader.readAsText(file, "text/plain");      
        reader.onload = localLoaded;
        reader.onerror = localError;
        // ...
    }
});

818Swapping div elements with jQuery

I found myself in need for swapping div elements. On the one hand, elements, which are situated next to each other (in the code), on the other hand I also wanted to swap only sub-elements of these divs.

How can this be done with jQuery?

Let's start with the first case, swapping adjunct divs.

...
...
...
...
...
// get a handle on the elements
var elements = $(".elements");

// let's assume, we want to swap #e2 and #e3
var leftElement = $(elements[2]);
var rightElement = $(elements[3]);

leftElement.insertAfter(rightElement); // inserts leftElement after rightElement

insertAfter takes the object, with with the method is associated (leftElement) and inserts the object's div after the div specified as a method argument. Here's more on SO about it.

In a previous version of the code, i mistakenly though, that it's necessary to replace the leftElement with the right one prior to inserting...

// NG
leftElement.replaceWith(rightElement);
leftElement.insertAfter(rightElement);

This also seemed to work ok. Only later I found out, that any jQuery data() objects connected to the rightElement will get wiped when replaceWith is being called.

Finally you'll also want to do an update to the elements array, to get them in their new order:

var elements = $(".elements");

814Swapping Array Items in Javascript

var myArray = ["a", "c", "b"];
myArray.swap(1, 2);
console.log(myArray);
// ["a", "b", "c"];

Array.prototype.swap=function(a, b) {
    this[a]= this.splice(b, 1, this[a])[0];
    return this;
}

It could also be done with a temp var, but this solution seems to be the most elegant. The key to this is in the additional arguments the splice() function can accept.

splice(start, itemCount, additionalItems ...)

splice() removes elements denominated by the start and itemCount argument, and - if specified - inserts additional items at the same position.

Also important to note is that splice() returns an array. And to turn that array into an item again we need to select it directly with [0].

812jQuery: Getting the element index from a list of identical class elements

Let's say you have a number of identical class elements:

One Title
Another Title
Brrrr
Zzzzzz

And you want to get a particular element from this list.

var myArray = $(".myClass");
var thirdElement = myArray[2];
console.log(thirdElement);
// 
Brrrr

But note, that myArray[2] is the HTML element, not an jQuery object. If you want to access it via jQuery, you'll have to "arm" it...

var myArray = $(".myClass");
var thirdElement = $(myArray[2]);
console.log(thirdElement);
// [
Brrrr
]

Interrating over a jQuery selected list can be done with the each() function:

myArray.each(function(i, element){
    var myElement = myArray[i];
    // this
    // element
}

myElement, element and this would all hold the same value at each iteration. i is obviously the index counter.

It's also described quite clearly at the jQuery Docs, but I think it's important enough to reiterate.

813Copying Arrays in Javascript with slice(0)

Using Arrays in Javascript retain their values by references.

var oneArray = ["a", "b", "c"];
var anotherArray = oneArray;
anotherArray[0] = "z";

console.log(oneArray, anotherArray);
// ["z", "b", "c"], ["z", "b", "c"]

Ok, but let's say you'll need to make a copy of the array. How do you do that?

var oneArray = ["a", "b", "c"];
var anotherArray = oneArray.slice(0);
anotherArray[0] = "z";

console.log(oneArray, anotherArray);
// ["a", "b", "c"], ["z", "b", "c"]

If you'd really, really want you could also wrap it into a prototype function. Although the code-characters savings are minimal.

Array.prototype.copy = function() {
    return this.slice(0);
}

var anotherArray = oneArray.slice(0);
//vs
var anotherArray = oneArray.copy();

Minimal, but maybe contextually for self-explaining.

811Fuji Xerox ApeosPort (DocuCentre) IV C3370 & OSX Lion

Setting up the ApeosPort C3370 in OSX Lion should not be difficult at all. Download the latest drivers, install, select and there you go. Right? Not quite.

Selecting "FX ApeosPort-IV C3370 v3017.104 PS" or similar driver did not produce a workable connection to the printer. Rather it produced some annoying 'beep' sounds at the printer every time I was trying to print. But it did not produce any print-outs.

Thanks to this I found that the solution is to select the following driver: "FX Print Drive for Mac OX v1.2.2" (or whatever the latest version might be). It's working!

810Installing Circos on OS 10.6

Circos, the Perl-package for visualizing data and information in a circular layout is an immensely popular application in the bio-informatics/bio-visualization community. And rightly so, as it able to produce visually stunning and appealing graphics.

Because its the native environment is bio-informaticians, the software is written in Perl. For those without Perl experience, it can be slightly frustrating to set it up on OSX (as it was for me). Here are the steps I needed to do to get it running, hope that this might reduce the trouble and let others get to work on their visualization more quickly.

The whole installation process is also detailed on the Installation page.

1 Getting Circos Download the software, tutorials, tools and courses

2 Testing the modules Go the the circosX-XX/bin folder and run: ./test.modules This gives you a list of the installed Perl modules, and - more importantly - the ones still missing.

3 Install the missing modules Switch to the super user with 'su'. For each missing modules say: cpan -i Modulename::Subname

cpan -i Config::General
cpan -i Graphics::ColorObject
cpan -i Math::VecStat
etc, etc

All worked swimmingly, except GD was making a bit of trouble.

4 Installing GD The graphics library GD has to be present on your system. If it's not, install it. (I am with homebrew, therefore installing GD is done like that: brew install gd)

Still after installing GD, installing the Perl module would not work. But after applying a little force, it went fine:

cpan -i -f GD

5 Adding circos to your path Adding the circos 'bin' directory to your path lets you call the circos program directly without specifying the whole path. That's a good thing.

PATH="/path/to/circos-0.55/bin:${PATH}"
export PATH

After that, everything should work and your Circos adventure can begin...

809Measuring Text in Canvas

HTML Canvas allows for the drawing of text with

ctx.fillStyle = "666";      // text color
ctx.textAlign = "center";       // alignment
ctx.font = "normal 12px Helvetica Neue";        // font
ctx.fillText("my Text, x , y);      // draw

Sometimes, you might want to draw a border around the text. Getting the textHeight should not present a problem, after all we can set the font size directly. But textWidth is not fixed in that way, because it depends (nnnn) on the actual text that is being displayed.

ctx.measureText takes the text as an argument and returns an object with a width property, describing the width of the text.

var texttWidth = ctx.measureText(columnName).width;

width is for now the only inhabitant of that object, but it would be a fair guess, that it might be more densely populate in the future.

806Replacing HTML elements with jQuery’s replaceWith

Let's say you are having some HTML elements that should only be enabled, if the browser sports certain features. By default, the element is disabled, like in the following example:

Open File...

Next, we check in Javascript is this certain feature is supported. If it is, we replace the disabled element with an active version.

if (isSupported()) {
    $('#item').replaceWith('Open File...');
}

Which results in this:

Open File...

Simple, but effective.