If you’re trying to automate tests of your SproutCore application with Selenium, for example, you’ll realise that the HTML element ids are automatically generated. They change every now and then and break all your tests.
To get rid of this problem, you can override the layerId method of certain view classes to generate a stable, and human readable, id.
The following code takes the view hierarchy, and generates an id based on the parents’ names. For example, the mainPage.mainView.someOtherView.theTargetView view will be given the mmsome.theTargetView id.
CT._ct_layerId = function() {
var k1, k2, k3, k4, guid;
if (!this._ct_layerId_cache) {
guid = SC.guidFor(this);
// Compute the new value
k1 = this.get('keyForParentView');
// If k1 is null, defer the computation to later...
if (!k1) return SC.guidFor(this);
// Finish the computation
k2 = this.getPath('parentView.keyForParentView') || '';
k3 = this.getPath('parentView.parentView.keyForParentView') || '';
k4 = this.getPath('parentView.parentView.parentView.keyForParentView') || '';
// Cache the result
this._ct_layerId_cache = k4.substr(0,1) + k3.substr(0,1) + k2.substr(0,4) + '.' + k1;
// If the id is already taken, fallback to guid
if (SC.View.views[this._ct_layerId_cache]) {
this._ct_layerId_cache = guid;
// else, update the SC.View.views hash with the new value
} else {
delete SC.View.views[guid];
SC.View.views[this._ct_layerId_cache] = this;
}
}
return this._ct_layerId_cache;
}.property();
SC.View.prototype.mixin({
keyForParentView: function() {
var parentView = this.get('parentView'),
key;
for (key in parentView) {
if (this === parentView[key]) return key;
}
return null;
}.property()
});
SC.TextFieldView.prototype.mixin({
layerId: CT._ct_layerId
});
SC.LabelView.prototype.mixin({
layerId: CT._ct_layerId
});
SC.ImageView.prototype.mixin({
layerId: CT._ct_layerId
});
Leave a comment