Skip to content

Instantly share code, notes, and snippets.

@rgrove
Created May 30, 2012 22:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rgrove/2839394 to your computer and use it in GitHub Desktop.
Save rgrove/2839394 to your computer and use it in GitHub Desktop.
var AttrProto = Y.Attribute.prototype,
GlobalEnv = YUI.namespace('Env.Model'),
Lang = Y.Lang,
YArray = Y.Array,
EVT_ADD = 'add',
EVT_ERROR = 'error',
EVT_RESET = 'reset';
Y.LazyModelList = Y.Base.create('lazyModelList', Y.ModelList, [], {
// -- Public Methods -------------------------------------------------------
get: function (name) {
if (this.attrAdded(name)) {
return AttrProto.get.apply(this, arguments);
}
return YArray.map(this._items, function (item) {
return item[name];
});
},
getAsHTML: function (name) {
if (this.attrAdded(name)) {
return Y.Escape.html(AttrProto.get.apply(this, arguments));
}
return YArray.map(this._items, function (item) {
return Y.Escape.html(item[name]);
});
},
getAsURL: function (name) {
if (this.attrAdded(name)) {
return encodeURIComponent(AttrProto.get.apply(this, arguments));
}
return YArray.map(this._items, function (item) {
return encodeURIComponent(item[name]);
});
},
indexOf: function (model) {
return YArray.indexOf(model._isYUIModel ?
this._models : this._items, model);
},
reset: function (models, options) {
models || (models = []);
options || (options = {});
var facade = Y.merge({src: 'reset'}, options);
if (models._isYUIModelList) {
models = models.toArray(); // assume we'll get an array of plain objects (for now)
}
facade.models = models;
if (options.silent) {
this._defResetFn(facade);
} else {
// Sort the models before firing the reset event.
if (this.comparator) {
models.sort(Y.bind(this._sort, this));
}
this.fire(EVT_RESET, facade);
}
return this;
},
toJSON: function () {
return this.toArray();
},
revive: function (item) {
return Lang.isNumber(item) ?
this._reviveIndex(item) : this._reviveObject(item);
},
// -- Protected Methods ----------------------------------------------------
// Generates ad-hoc clientIds for non-instantiated models.
_generateClientId: function () {
GlobalEnv.lastId || (GlobalEnv.lastId = 0);
return this.model.NAME + '_' + (GlobalEnv.lastId += 1);
},
_reviveIndex: function (index) {
return this._models[index] || this._reviveObject(this._items[index], index);
},
_reviveObject: function (model, index) {
if (!model) {
return null;
}
if (!model._isYUIModel) {
model = new this.model(model);
this._attachList(model);
}
if (index || index === 0) {
this._models[index] = model;
}
return model;
},
_isInList: function (item) {
return ('clientId' in item && this._clientIdMap[item.clientId]) ||
('id' in item && this._idMap[item.id]);
},
_add: function (item, options) {
var facade;
options || (options = {});
// Ensure that the item has a clientId.
'clientId' in item || (item.clientId = this._generateClientId());
if (this._isInList(item)) {
this.fire(EVT_ERROR, {
error: 'Model is already in the list.',
model: item,
src : 'add'
});
return;
}
facade = Y.merge(options, {
index: 'index' in options ? options.index : this._findIndex(item),
model: item
});
options.silent ? this._defAddFn(facade) : this.fire(EVT_ADD, facade);
return item;
},
_clear: function () {
YArray.each(this._models, this._detachList, this);
this._clientIdMap = {};
this._idMap = {};
this._items = [];
this._models = [];
},
_remove: function (item, options) {
// If the given item is a model instance, turn it into an index before
// calling the parent _remove method, since we only want to deal with
// the plain object version.
if (item._isYUIModel) {
item = this.indexOf(item);
}
return Y.ModelList.prototype._remove.call(this, item, options);
},
// -- Default Event Handlers -----------------------------------------------
_defAddFn: function (e) {
var item = e.model;
this._clientIdMap[item.clientId] = item;
if (Lang.isValue(item.id)) {
this._idMap[item.id] = item;
}
this._items.splice(e.index, 0, item);
},
_defRemoveFn: function (e) {
var index = e.index,
item = e.model,
model = this._models[index];
delete this._clientIdMap[item.clientId];
if ('id' in item) {
delete this._idMap[item.id];
}
if (model) {
this._detachList(model);
this._models.splice(index, 1);
}
this._items.splice(index, 1);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment