While doing an experiment with Getters and Setters I whipped together a small lib for a versioning array, the histarray. So far tested only in Firefox 3, it utilizes __defineGetter__(someNumber, function(){}) to return an element from an internal array (the history). Its push method will either overwrite the current revision if it is not the last, or push a new revision into the history. A Setter is also defined, so no matter where in the time line you currently are, that element will be updated.
function histarray()
{
for(var i = 0; i < arguments.length; i++)
this._add(arguments[i], i);
this.__defineSetter__('revision', function(v)
{
return (v > this.length) ?
this.revision :
this._revision = v;
});
this.__defineGetter__('revision', function()
{
return this._revision;
});
this.__defineGetter__('prev', function()
{
return (this.revision != 0) ?
(function(self)
{
var a = Array();
for(var i in self._elements)
a.push(self._elements[i][self.revision - 1]);
return a;
})(this) :
null;
});
this.__defineGetter__('nxt', function()
{
return (this.revision < this.revisions) ?
(function(self)
{
var a = Array();
for(var i in self._elements)
a.push(self._elements[i][self.revision + 1]);
return a;
})(this) :
null;
});
};
histarray.prototype =
{
length: 0,
revisions: 0,
_elements: Array(),
_revision: 0,
_add: function(e, i)
{
this._elements[i] = (function(e,self)
{
var a = Array();
for(var i = 0; i < self.revisions; i++)
a.push(null);
a.push(e);
return a;
})(e,this);
this.__defineGetter__(i, function()
{
return this._elements[i][this.revision];
});
this.__defineSetter__(i, function(v)
{
return this._elements[i][this.revision] = v;
});
this.length = i + 1;
},
// push csv or a single array
push: function()
{
if(typeof arguments[0] == 'object')
this.push.apply(this, arguments[0]);
else
{
if(this.revision == this.revisions)
{
this.revision++;
this.revisions++;
}
for(var i = 0; i < arguments.length; i++)
{
if(arguments[i] == null) continue;
if(this._elements[i])
this._elements[i][this.revision] = arguments[i];
else
this._add(arguments[i], i);
}
}
return this.length;
}
};
// creates a new histarray.
var ha = new histarray('e1', 'e2', 'e3');
// this is now just like a normal array, ha[0] == 'e1'
// now using push does not add a new element, but instead adds a new revision
ha.push('e1v2', 'e2v2', 'e3v2')
// now ha[0] == 'e1v2' and ha.revision == 1 and ha.prev[0] == 'e1'
// if we change the revision back to 0
ha.revision = 0;
// ha[0] == 'e1', ha.nxt[0] == 'e1v2'
// with the revision still at 0, we can update an old element
ha[0] = 'e1a';
// this just changes the first revision of the first element.
Not certain is will be useful for anything in particular. But I still have a couple ideas to add, and am interested in hear what people have to say about this.