OK - I've made a fix in the iterator. The fix assumes if the property
points to an object instead of an array - that it should assume it's
an array with the object as the only member. You should be able to
replace your app_iterator.js file under modules/app_iterator with this
file -- assuming you're using the current 2.0.2 release. Also, this
patch has been made to head and will be in next weeks 2.1 release. I
have to paste it inline -- can't figure out how to attach it using
google groups.
Appcelerator.Module.Iterator = {
getName: function() {
return "appcelerator iterator"
},
getDescription: function() {
return "iterator widget"
},
getVersion: function() {
return 1
},
getSpecVersion: function() {
return 1
},
getAuthor: function() {
return "Jeff Haynie"
},
getModuleURL: function() {
return "
http://www.appcelerator.org"
},
isWidget: function() {
return true
},
getWidgetName: function() {
return "app:iterator"
},
getActions: function() {
return ["execute"]
},
execute: function(id, parameterMap, data, scope) {
var compiled = parameterMap["compiled"];
var propertyName = parameterMap["property"];
var items = parameterMap["items"];
var table = parameterMap["table"];
var width = parameterMap["width"];
var headers = parameterMap["headers"];
var selectable = parameterMap["selectable"];
var array = null;
if (!compiled) {
compiled = eval(parameterMap["template"] + "; init_" +
id);
parameterMap["compiled"] = compiled
}
if (items) {
data = items.evalJSON() || []
}
if (propertyName) {
array = Object.getNestedProperty(data, propertyName) || []
} else {
array = data
}
var html = "";
if (!array) {
html = compiled(data)
} else {
if (table) {
html += '<table width="' + width + '" cellspacing="' +
parameterMap["cellspacing"] + '"><tr>';
headers.each(function(h) {
html += "<th>" + h + "</th>"
});
html += "</tr>"
}
// this is in the case we pass in an object instead of
// an array, make it an array of length one so we can iterate
if (!Object.isArray(array))
{
array = [array];
}
for (var c = 0, len = array.length; c < len; c++) {
var o = array[c];
if (typeof o != "object") {
o = {
"iterator_value": o
}
}
o["iterator_index"] = c;
o["iterator_length"] = len;
o["iterator_odd_even"] = (c % 2 == 0) ? "even": "odd";
if (table) {
if (o["iterator_odd_even"] == "odd") {
html += '<tr class="' +
parameterMap["rowOddClassName"] + '">'
} else {
html += '<tr class="' +
parameterMap["rowEvenClassName"] + '">'
}
}
for (idx in o) {
if (typeof o[idx] == "string") {
o[idx] = o[idx].replace(/'/, "\u2019")
}
}
html += compiled(o);
if (table) {
html += "</tr>"
}
}
if (table) {
html += "</table>"
}
}
var element = $(id);
if (selectable) {
element.setAttribute("selectable", selectable)
}
element.innerHTML = html;
Appcelerator.Compiler.dynamicCompile(element)
},
getAttributes: function() {
return [{
name: "on",
optional: true,
description: "Used to execute the iterator"
},
{
name: "items",
optional: true,
description: "Literal (or template-replaced) JSON array to
iterate over"
},
{
name: "property",
optional: true
},
{
name: "rowEvenClassName",
optional: true
},
{
name: "rowOddClassName",
optional: true
},
{
name: "table",
optional: true,
defaultValue: "false"
},
{
name: "width",
optional: true,
defaultValue: "100%"
},
{
name: "headers",
optional: true,
defaultValue: ","
},
{
name: "cellspacing",
optional: true,
defaultValue: "0"
},
{
name: "selectable",
optional: true
}]
},
compileWidget: function(A) {
this.execute(A["id"], A, null, "")
},
buildWidget: function(A, B) {
B["template"] =
Appcelerator.Compiler.compileTemplate(Appcelerator.Compiler.getHtml(A),
true, "init_" + A.id);
B["table"] = B["table"] == "true";
if (B["table"]) {
B["headers"] = B["headers"].split(",")
}
var C = !!(!B["on"] && B["items"]);
return {
"presentation": "",
"position": Appcelerator.Compiler.POSITION_REPLACE,
"parameters": B,
"wire": true,
"compile": C
}
}
};
Appcelerator.Core.registerModule("app:iterator",
Appcelerator.Module.Iterator)
On Feb 28, 6:25 pm, "Jeff Haynie" <
jhay...@gmail.com> wrote:
> Another idea is to fix this in the iterator and make it a little more smart
> such that if you have an object -- you assume it's an array with 1 element.
> Maybe that would work.... Thoughts anyone?
>
>
>
> On Thu, Feb 28, 2008 at 6:21 PM, Jeff Haynie <
jhay...@gmail.com> wrote:
> > You're correct in the way this works and it's stupid (I wrote it to do
> > this).
> > When I transform from JSON to XML I don't know if an element will have
> > more than 1 node. So, I essentially wanted to be able to do simple stuff
> > like:
>
> > contactlist.contact.firstname
>
> > to give you the firstname
>
> > However, it breaks down in the case of multiples -- in which case if I see
> > one than one of the same element I know it's an array.
>
> > What I'm not sure on is the correct implementation of how this should
> > work. I either have to assume that each element is an array or do something
> > else (which I'm not sure what it is).
>
> > Anyone know of a generic purpose library for converting XML to JSON --
> > that already addresses this?
>
> > Jeff
>
> > On Thu, Feb 28, 2008 at 6:11 PM, <
pricha...@xaware.com> wrote:
>
> > > I've just started integrating Appcelerator with our product XAware,
> > > which can return HTML results over http. I created a simple result
> > > that returns a contact list such as:
>
> > > <contactlist>
> > > <contact>
> > > <firstname>John</firstname>
> > > <lastname>Smith</lastname>
> > > <phone>
719-555-1111</phone>
> > > </contact>
> > > <contact>
> > > <firstname>Jane</firstname>
> > > <lastname>Doe</lastname>
> > > <phone>
719-555-2222</phone>
> > > </contact>
> > > </contactlist>
>
> > > I tried using the following app:http and app:iterator widgets, similar
> > > to your techcrunch rss feed example:
>
> > > <app:http on="l:get.contacts then get">
> > > <uri method="get" uri="
http://localhost:8090/xaware/bizview/
> > > XAFiles/TestDemo1.xbd<
http://localhost:8090/xaware/bizview/XAFiles/TestDemo1.xbd>"