alpaca
Version:
Alpaca provides the easiest and fastest way to generate interactive forms for the web and mobile devices. It runs simply as HTML5 or more elaborately using Bootstrap, jQuery Mobile or jQuery UI. Alpaca uses Handlebars to process JSON schema and provide
164 lines (134 loc) • 5.32 kB
JavaScript
(function($) {
var Alpaca = $.alpaca;
Alpaca.NormalizedView = Base.extend(
/**
* @lends Alpaca.NormalizedView.prototype
*/
{
/**
* Once all of the Alpaca views are registered with the framework, each is normalized so that parent-chain
* references and overrides are normalized into a single, fast lookup object.
*
* @constructs
*
* @class Normalized view.
*
* @param {String} the view id
*/
constructor: function(viewId) {
this.id = viewId;
},
/**
* Normalization occurs once per view upon startup of Alpaca.
*/
normalize: function(views)
{
// load the view object
var viewObject = views[this.id];
if (!viewObject)
{
Alpaca.logError("View compilation failed - view not found: " + this.id);
return false;
}
// collect the inheritance chain
var chain = [];
var current = viewObject;
while (current) {
chain.push(current);
var parentId = current.parent;
if (parentId) {
var parent = views[current.parent];
if (!parent) {
Alpaca.logError("View compilation failed - cannot find parent view: " + parentId + " for view: " + current.id);
return false;
}
current = parent;
}
else
{
current = null;
}
}
// reverse the chain
chain = chain.reverse();
var setScalar = function(target, source, propertyId)
{
var value = source[propertyId];
var currentValue = target[propertyId];
if (!Alpaca.isUndefined(currentValue) && !Alpaca.isUndefined(value))
{
Alpaca.logDebug("View property: " + propertyId + " already has value: " + currentValue + " and overwriting to: " + value);
}
if (!Alpaca.isUndefined(value)) {
target[propertyId] = value;
}
};
var setFunction = function(target, source, propertyId)
{
var value = source[propertyId];
var currentValue = target[propertyId];
if (!Alpaca.isUndefined(currentValue) && !Alpaca.isUndefined(value))
{
Alpaca.logDebug("View property: " + propertyId + " already has function, overwriting");
}
if (!Alpaca.isUndefined(value)) {
target[propertyId] = value;
}
};
var mergeMap = function(target, source, propertyId)
{
var sourceMap = source[propertyId];
if (sourceMap)
{
if (!target[propertyId])
{
target[propertyId] = {};
}
Alpaca.mergeObject2(sourceMap, target[propertyId]);
}
};
// walk forward and apply
for (var i = 0; i < chain.length; i++)
{
var element = chain[i];
// core properties
setScalar(this, element, "type"); // view, edit, create
setScalar(this, element, "ui"); // bootstrap, jqueryui, jquerymobile, web
// whether the view is readonly
setScalar(this, element, "displayReadonly");
// locale
setScalar(this, element, "locale");
// functions
setFunction(this, element, "render");
setFunction(this, element, "postRender");
// view templates
mergeMap(this, element, "templates");
// field templates
mergeMap(this, element, "fields");
// layout
mergeMap(this, element, "layout");
// styles
mergeMap(this, element, "styles");
// callbacks
mergeMap(this, element, "callbacks");
// messages
mergeMap(this, element, "messages");
// horizontal
setScalar(this, element, "horizontal");
// TODO: remove some of these?
setScalar(this, element, "collapsible");
setScalar(this, element, "legendStyle");
setScalar(this, element, "toolbarStyle");
setScalar(this, element, "buttonStyle");
setScalar(this, element, "toolbarSticky");
setScalar(this, element, "globalTemplate");
// TODO: remove wizard?
mergeMap(this, element, "wizard");
}
Alpaca.logDebug("View compilation complete for view: " + this.id);
Alpaca.logDebug("Final view: ");
Alpaca.logDebug(JSON.stringify(this, null, " "));
return true;
}
});
})(jQuery);