/************************************************************************* * * Copyright 2008 FlashMobileBlog * All Rights Reserved. * **************************************************************************/ import mobile.core.ArrayDataProvider; import mobile.events.DataProviderEvent; import mobile.events.Event; /** * This is the RSS data provider class for retrieving RSS articles and parsing them for display with a FLIP * list component. *

* The RSSDataProvider class is to be used with components, both UI components and other * ActionScript classes. * It responds to data requests and dispatches events to notify of data changes. * This base class allows for only reading of array data. You can extend this class to provide * different functionality to interact with other data services. *

* * @category Class * @langversion 2.0 * @playerversion Lite 2.1 */ class mobile.data.RSSDataProvider extends ArrayDataProvider { /** * @private * * The RSS XML Data */ private var xData:XML; /** * @private * * A fake object to allow DataProvider functions to run in the context * of a request to improve memory and CPU efficiency */ private var owner:Object; /** * Class Constructor. * * @category Constructor * @productversion FLIP 1.0 * @langversion 2.0 * @playerversion Lite 2.1 * */ function RSSDataProvider() { super(); } /** * * * Open the RSSDataProvider list using the parameters provided. *

* If the RSSDataProvider was previously initialized, then all outstanding * requests will be cancelled and deleted. * When the list has completed its first stage of opening and initialization, this event is dispatched. * The list's Id is available once the open event has been received. *

* @param filter An array of RSS Feed urls, other data may be required for the service depending on the provider. * @param sortOrder The sortOrder of the returned list, implemented for example purposes only. * @param returnFields A bit field of items to maintain for the user interface, for example purposes only. * * @see DataRequest * * @category Method * @langversion 2.0 * @playerversion Lite 2.1 */ public function open(feed:String, sortOrder:Number, returnFields:Number):Void { //Set defaults xData = null; sortOrder = 0; // Default behaviour returnFields = -1; // -1 sets all bits to 1 xData = new XML(); xData.ignoreWhite = true; xData["owner"] = this; xData.onLoad = onXMLHandler; xData.load(feed); } /** * Receives calls to fetch the items in the range specified. This function is a redefinition * of the base class method to encompass asynchronous list creation.. If the list is open then * processing is immediate. *

* When the items have been fetched, the DataProviderEvent.GET_ITEMS event * is dispatched and contains the data. Each call overwrites the previous call for items in cases where * the list is not open yet. *

* * @param startIndex The first index in the range to fetch * @param endIndex The last index in the range to fetch * * * * @category Method * @langversion 2.0 * @playerversion Lite 2.1 */ public function getItems(startIndex:Number, endIndex:Number):Void { if(this.dataArr.length) { doGetItems(startIndex, endIndex); } else { //Record the latest request for items until ready owner.startIndex = startIndex; owner.endIndex = endIndex; } } /** * Fetches the items in the range specified. This function is a redefinition * of the base class method to work asynchronously. *

* When the items have been fetched, the DataProviderEvent.GET_ITEMS event * is dispatched and contains the data. *

* * @param startIndex The first index in the range to fetch * @param endIndex The last index in the range to fetch * * * * @category Method * @langversion 2.0 * @playerversion Lite 2.1 */ private function doGetItems(startIndex:Number, endIndex:Number):Void { var dataArrLen:Number = dataArr.length; startIndex = Math.max(0, Math.min(dataArrLen - 1 , startIndex)); endIndex = Math.max(startIndex, Math.min(dataArrLen - 1, endIndex)); var event:DataProviderEvent = new DataProviderEvent( DataProviderEvent.GET_ITEMS, false, false, startIndex, endIndex, dataArrLen, dataArr.slice(startIndex, endIndex+1) ); event.status = (dataArr.length != 0) ? DataProviderEvent.SUCCESS : DataProviderEvent.INDEX_OUT_OF_RANGE; dispatchEvent(event); } /** * Handles the list events sent through onLoad. *

* This method is run in the context of the XML object, not the DeviceDataProvider class. *

* * @category Method * @langversion 2.0 * @playerversion Lite 2.1 */ public function onXMLHandler():Void { owner.handleXML(this); } /** * @private * * Scope has been regained from the asychronous load, now process the XML. *

* Once parsing of the XML is complete the DataProviderEvent.GET_ITEMS event * is dispatched. *

* * @category Method * @langversion 2.0 * @playerversion Lite 2.1 */ private function handleXML(xml:XML):Void { if(xml != undefined) { parseEntries(); xData = null; dispatchEvent(new Event("open")); if(owner.startIndex != undefined && owner.endIndex != undefined) { doGetItems(owner.startIndex, owner.endIndex); } } } /** * @private * * Parse the RSSDataProvider list entries stored in xData. *

* Each item will be stored in the entries array from the parent ArrayDataProvider object. *

* * * @category Method * @langversion 2.0 * @playerversion Lite 2.1 */ private function parseEntries():Void { var nodes:Array = xData.firstChild.firstChild.childNodes; var len:Number = nodes.length; var node:XMLNode; var entries:Array = []; while(--len) { node = nodes[len]; var nodeName:String = nodes[len].nodeName; if(nodeName == "item") { entries.push(parseEntry(node)); } } addItems(entries); } /** * @private * * Retrieves the data from each of the entries passed to it by parseEntries. *

* Each item will be stored in the entries array from the parent ArrayDataProvider object. *

* * @param node A node contains an individual ATOM item * * @return An object containing each item detail * * @category Method * @langversion 2.0 * @playerversion Lite 2.1 */ private function parseEntry(node:XMLNode):Object { if(node == undefined) { return null; } var entryElements:Array = node.childNodes; var elementLen:Number = entryElements.length; var entry:Object = new Object(); var entryElement:XMLNode; while(elementLen--) { entryElement = entryElements[elementLen]; switch(entryElement.nodeName) { case "title": { entry.label = entryElement.firstChild.nodeValue; break; } case "description": { entry.desc = entryElement.firstChild.nodeValue; break; } case "media:thumbnail": { entry.img = []; entry.icon = entryElement.attributes.url; entry.img.ht = entryElement.attributes.height; entry.img.wt = entryElement.attributes.width; break; } case "link": { entry.link = entryElement.firstChild.nodeValue; break; } case "pubDate": { entry.pubDate = entryElement.firstChild.nodeValue; break; } default: { //pass this to a parse default function break; } } } return entry; } }