// ==========================================================================
// Project: The M-Project - Mobile HTML5 Application Framework
// Copyright: (c) 2011 panacoda GmbH. All rights reserved.
// Creator: dominik
// Date: 10.04.12
// License: Dual licensed under the MIT or GPL Version 2 licenses.
// ==========================================================================
/**
* @class
*
* A carousel is a view that allows you to slide/scroll vertically or horizontally
* through a set of items. If required, a paginator indicates the user which item
* is currently visible and how many of them are there at all.
*
* @extends M.View
*/
M.DynamicCarousel = M.CarouselView.extend(
/** @scope M.CarouselView.prototype */ {
/**
* The type of this object.
*
* @type String
*/
type: 'M.DynamicCarousel',
carouselTemplateView: null,
/**
* This method is called automatically once the bound content changes. It then re-renders the
* carousel's content.
*
* @private
*/
renderUpdate: function () {
if (this.contentBinding && this.value) {
this.removeAllItems();
var that = this;
/* Get the list view's template view for each list item */
var templateView = this.carouselTemplateView;
/* if there is no template, log error and stop */
if (!templateView) {
M.Logger.log('The template view could not be loaded! Maybe you forgot to use m_require to set up the correct load order?', M.ERR);
return;
}
/* check if there is an events propety specified for the template or if we should use the list's events */
templateView.events = templateView.events ? templateView.events : this.events;
/* Get the list view's content as an object from the assigned content binding */
if (this.contentBinding && typeof(this.contentBinding.target) === 'object' && typeof(this.contentBinding.property) === 'string' && this.value) {
var content = this.value;
} else {
M.Logger.log('The specified content binding for the carousel view (' +
this.id + ') is invalid!', M.WARN);
return;
}
var itemIndex = 0;
var itemIds= [];
_.each(content, function (items, count) {
var item = that.renderItem(items, templateView);
that.itemsHtml += item.render();
itemIds[itemIndex] = item;
itemIndex++;
});
/* set the num of items */
this.numItems = this.value.length;
/* add the items to the DOM */
this.addItems(this.itemsHtml);
_.each(itemIds, function(item) {
item.registerEvents();
})
/* no re-theme the carousel (async) */
var that = this;
window.setTimeout(function () {
that.isInitialized = NO;
that.initThemeUpdate(YES);
}, 1);
}
},
renderItem: function (content, templateView) {
var that = this;
var obj = templateView.design({});
/* Determine the "modelId" value of the list item */
if (that.useIndexAsId && typeof(index) === 'number') {
obj.modelId = index;
} else if (content.type === 'M.Model') {
if (that.idName) {
obj.modelId = content.get(that.idName);
} else {
obj.modelId = content.m_id;
}
} else if (that.idName) {
obj.modelId = content[that.idName] || undefined;
} else if (typeof(index) === 'number') {
obj.modelId = index;
}
obj = that.cloneObject(obj, content);
//set the current list item value to the view value. This enables for example to get the value/contentBinding of a list item in a template view.
obj.value = content;
return obj;
},
/**
* This method clones an object of the template including its sub views (recursively).
*
* @param {Object} obj The object to be cloned.
* @param {Object} item The current item (record/data).
* @private
*/
cloneObject: function (obj, item) {
/* Get the child views as an array of strings */
var childViewsArray = obj.childViews ? obj.getChildViewsAsArray() : [];
/* If the item is a model, read the values from the 'record' property instead */
var record = item.type === 'M.Model' ? item.record : item;
/* Iterate through all views defined in the template view */
for (var i in childViewsArray) {
/* Create a new object for the current view */
obj[childViewsArray[i]] = obj[childViewsArray[i]].design({});
/* create childViews of the current object */
obj[childViewsArray[i]] = this.cloneObject(obj[childViewsArray[i]], item);
/* This regex looks for a variable inside the template view (<%= ... %>) ... */
var pattern = obj[childViewsArray[i]].computedValue ? obj[childViewsArray[i]].computedValue.valuePattern : obj[childViewsArray[i]].valuePattern;
var regexResult = /<%=\s+([.|_|-|$|§|@|a-zA-Z0-9\s]+)\s+%>/.exec(pattern);
/* ... if a match was found, the variable is replaced by the corresponding value inside the record */
if (regexResult) {
switch (obj[childViewsArray[i]].type) {
case 'M.LabelView':
case 'M.ButtonView':
case 'M.ImageView':
case 'M.TextFieldView':
while (regexResult !== null) {
if (typeof(record[regexResult[1]]) === 'object') {
pattern = record[regexResult[1]];
pattern = pattern[obj[childViewsArray[i]].valueId];
if (obj[childViewsArray[i]].valuePath) {
if (pattern) {
eval('pattern = pattern.' + obj[childViewsArray[i]].valuePath);
}
}
regexResult = null;
} else {
pattern = pattern.replace(regexResult[0], record[regexResult[1]]);
regexResult = /<%=\s+([.|_|-|$|§|@|a-zA-Z0-9\s]+)\s+%>/.exec(pattern);
}
}
obj[childViewsArray[i]].value = pattern;
break;
}
}
}
obj.item = item;
_.each(Object.keys(item), function (key) {
if (!obj.hasOwnProperty(key)) {
obj[key] = item[key];
}
});
return obj;
}
}
)
//VIEW
content: M.ScrollView.design({
childViews: 'carousel',
carousel: M.DynamicCarousel.design({
contentBinding: {
target: IOL_Info.iolController,
property: 'iolSponsorItems'
},
carouselTemplateView : IOL_Info.ListItemIolTemplateStart,
sizeCalculator: M.CAROUSEL_SIZE_SURROUNDING_ELEMENT
})
}),
//TEMPLATE
IOL_Info.ListItemIolTemplateStart = M.CarouselItemView.design({
childViews: 'group',
events: {
tap: {
target:IOL_Info.iolDetailController,
action:'showDetailItem'
}
},
group : M.IolGroupLabelView.design({
cssClass : 'iol-label-group-image',
childViews: 'image name',
image: M.ImageView.design({
valuePattern: '<%= image %>',
valueId : '0',
valuePath : '_urls._60_60',
cssClass:'carouselImg'
}),
name: M.LabelView.design({
valuePattern: '<%= name %>',
cssClass : 'value-list-view'
}),
})
});