Links^2 – July 22th, 2010

Posted in Links

MooTools: Track Class Instances With The TrackInstances Mutator

Posted in JavaScript, MooTools

(Script also on GitHub and MooTools Forge)

It’s great to track all of your classes’ instances for debugging purposes or mass altering.

Huh? Mass Altering?

  • For instances of some Audio/Video player classes: stop/pause all players
  • For instances of positioned elements: recalculate position of all elements upon window resize
  • Call hide method of all instances of a class upon an event

I needed it more than once and I used to track instances from within any class I needed it:

var MyClass=new Class({
	initialize:function () {
		MyClass.instances.push(this);
	},
	recalcPosition:function () {
		// something that recalculates position or any other task that should happen on all instances
	}
});
MyClass.instances=[];
// from another code:
MyClass.instances.each(function (instance) {
	instance.recalcPosition();
});

However, I got too many classes with this behavior. I ended up writing a MooTools Class Mutator to automate the process:

/*
---
script: Class.Mutators.TrackInstances.js
description: Allows a class to track its instances by having instances array as a class property
license: MIT-style license
authors:
- Elad Ossadon ( http://devign.me | http://twitter.com/elado )
requires:
- core:1.2.4
provides: [Class.Mutators.TrackInstances]
...
*/
Class.Mutators.TrackInstances=function (allow) {
	if (!allow) return;
	// save current initialize method
	var oldInit=this.prototype.initialize;
	var klass=this;
	// overwrite initialize method
	klass.prototype.initialize=function () {
		(klass.instances=klass.instances || []).push(this);
		oldInit.apply(this,arguments);
	};
};

Usage:

var MyClass=new Class({
	initialize:function () {
	},
	TrackInstances:true,
	recalcPosition:function () {
		// something that recalculates position or any other task that should happen on all instances
	}
});
var x=new MyClass();
var y=new MyClass();
MyClass.instances; // [x, y]
MyClass.instances.length; // 2
// from another code:
window.addEvent("resize",function () {
	MyClass.instances.each(function (instance) {
		instance.recalcPosition();
	});
});

The only constraint is that the “initialize” declaration in an object should be prior to the TrackInstances:true. That’s because mutators are called in the same loop as all other methods, and if the loop didn’t get to a certain method, then the mutator won’t know it. According to these tickets, the MooTools team won’t fix it anytime soon.

Bug: Chrome’s for..in Loop Messes the Order of the Indexes

Posted in Browsers, JavaScript

Yes. I know I should never rely on for..in loop order, but when it comes to inconsistency of browsers it can be annoying.

I found it out when I wanted to fetch the first key of an object, but got different results on chrome (incorrect result) and other browsers.

Code:

console.log("wordsAsKeys");
var wordsAsKeys={ words:"value",as:"value",keys:"value" };
for (var k in wordsAsKeys) console.log(k);
console.log("numbersAsKeys");
var numbersAsKeys={ "3":"value","2":"value","1":"value" };
for (var k in numbersAsKeys) console.log(k);
console.log("mixedKeys");
var mixedKeys={ "3":"value",words:"value","1":"value" };
for (var k in mixedKeys) console.log(k);

The Result:

Firefox / Safari / IE:

wordsAsKeys
	words
	as
	keys
numbersAsKeys
	3
	2
	1
mixedKeys
	3
	words
	1

Chrome:

wordsAsKeys
	words
	as
	keys
numbersAsKeys
	1
	2
	3
mixedKeys
	1
	3
	words

As you can see, the second and third loops enumerate on an object with numbers as indexes. What Google Chrome seem to do is treat the object as an Array, which outputs the numeric indexes first, in ascending order.

To me, it looks like a bug that may create inconsistency. Google & Chromium team – please fix it :)

Columns With Separator Border in CSS: The Easy Way

Posted in CSS, HTML

CSS comes with quite a few production faults. You can’t properly vertically align, and you can’t comfortably create columns in a website without hacks.

Creating two columns with a dividing border, with the border’s length depending on that of the longest column and without the use of background images or JavaScript, is also a non-standard task, because you can’t affect the height of one element based on the height of another.

In the image on the right there are two floated divs used to create columns. If there’s a border on the left column and shorter than the right column, the border will also be shorter.

The left column’s border reaches the bottom

The left column’s border reaches the bottom

The left column’s border reaches the end of the shorter column

The left column’s border reaches the end of the shorter column

The Required Result

The border continues along the longer column

The border continues along the longer column

The secret

Both columns have a border. The left column is displaced one pixel to the right. This way, the borders overlap, and the longest border reaches the bottom of the page.

Each column has its own border, but the left column is moved one pixel right, overlapping the right column

Each column has its own border, but the left column is moved one pixel right, overlapping the right column

In general, the concept of moving element with negative margins or position is quite interesting and can be an effective solution to many problems. I’m sure I’ll deal with it in future posts.

Code

<style type="text/css">
#menu {
	float:left;
	border-right:1px solid #000;
	width:150px;
	padding:10px;
	background-color:#6E919A;
}
#content {
	float:left;
	border-left:1px solid #000;
	width:250px;
	margin-left:-1px;
	padding:10px;
	background-color:#9BC9D1;
}
</style>
<div id="menu">Menu<br/>Menu<br/>Menu<br/>Menu</div>
<div id="content">Content<br/>Content</div>

Links^2 | July 8th, 2010

Posted in Links
svn commit -m "`curl "http://whatthecommit.com/" | grep '^<p>' | cut -d '>' -f 2`" src/mycode



Page optimized by WP Minify WordPress Plugin