2.4 Discovering or finding feeds
The “Add Feed” feature requires an exact URL of a feed. Discovering feeds or “Find Feed” is more flexible – all the user needs to give it is something to search for. This freedom, on the other hand, makes it harder to program.
Listing 13: Discovering feeds dialog – FindFeed.mxml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <?xml version="1.0" encoding="utf-8"?> <iic:ClosableTitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:iic="net.ivanidris.flex.components.*" creationComplete="init();"> <mx:Script source="Find.as"/> <mx:VBox> <mx:Grid> <mx:GridRow> <mx:GridItem> <mx:Label text="Find feeds based on keywords"/> </mx:GridItem> </mx:GridRow> <mx:GridRow> <mx:GridItem> <mx:TextInput id="keywords"/> </mx:GridItem> <mx:GridItem> <mx:Button id="find" label="Find" click="onFind();"/> </mx:GridItem> </mx:GridRow> <mx:GridRow> <mx:GridItem> <mx:Label text="For instance cnn or news"/> </mx:GridItem> </mx:GridRow> </mx:Grid> <mx:DataGrid dataProvider="{feeds}" width="782"> <mx:columns> <mx:DataGridColumn headerText="Add" dataField="add" width="50" textAlign="center"> <mx:itemRenderer> <mx:Component> <mx:CheckBox click="data.add=!data.add;" selected="{data.add}"/> </mx:Component> </mx:itemRenderer> </mx:DataGridColumn> <mx:DataGridColumn headerText="URL" dataField="url"/> <mx:DataGridColumn headerText="Title" dataField="title"/> </mx:columns> </mx:DataGrid> </mx:VBox> <iic:PushButton x="10" y="256" label="Add Selected Feeds" id="addSelected" enabled="false" click="onAddSelected();"/> </iic:ClosableTitleWindow> |
You probably have noticed that this file does not contain any Actionscript code. That is because it is in Find.as.
Listing 14: Discovering feeds – Find.as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | import com.adobe.serialization.json.JSON; import mx.collections.ArrayCollection; import mx.controls.Alert; import mx.managers.PopUpManager; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.rpc.http.HTTPService; import net.ivanidris.flexreader.FeedInfo; [Bindable] private var feeds: ArrayCollection; private var loader:URLLoader; private function init():void { keywords.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); } private function onFind():void { var url:String = '/findFeed.py?q=' + keywords.text; var request:URLRequest = new URLRequest(url); loader = new URLLoader(request); loader.addEventListener("complete", onServerResponse); } private function onServerResponse(e:Event):void { var feed: FeedInfo; feeds = new ArrayCollection(); var json:Object = JSON.decode(loader.data); for each(var i in json) { feed = new FeedInfo(); feed.url = i.url; feed.title = i.title; feeds.addItem(feed); } if(feeds.length > 0) { addSelected.enabled = true; } } override public function onKeyDown(event:KeyboardEvent) :void { // process enters if(event.charCode == 13 && keywords.text.length > 0) { onFind(); } } public function useHttpService(parameters:Object):void { var service:HTTPService; service = new HTTPService(); service.url = "/addSelectedFeeds.py"; service.method = "POST"; service.addEventListener("result", httpResult); service.addEventListener("fault", httpFault); service.send(parameters); } public function httpResult(event:ResultEvent):void { removeMe(); } public function httpFault(event:FaultEvent):void { var faultstring:String = event.fault.faultString; Alert.show(faultstring); } public function onAddSelected():void { var len:int = feeds.length; var result:Array = new Array(); for (var i:int=0;i<len;i++) { var feed:FeedInfo = FeedInfo(feeds.getItemAt(i)); if (feed.add) { result.push(feed); } } if(result.length > 0) { var parameters:Object = new Object(); parameters.data = JSON.encode(result); useHttpService(parameters); } } |
Find.as either sends a request to findFeed.py or addSelectedFeeds.py. In the discover feeds scenario, you are more likely to find multiple items for query such as “cnn” or ” hamburger” or whatever. The FeedInfo class stores information about the found feeds. FeedInfo is small class with three fields – a url, a title and a boolean telling us whether to add this feed or not.
Listing 15: Discovering feeds – findFeed.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import cgi import urllib from google.appengine.api import urlfetch from django.utils import simplejson import re form = cgi.FieldStorage() query = urllib.quote(form.getfirst("q", "")) url = "http://ajax.googleapis.com/ajax/services/feed/find?v=1.0&q=" + query result = urlfetch.fetch(url) resultList = [] print 'Content-type: text/plain' print '' if result.status_code == 200: json = simplejson.loads(result.content.strip()) if json['responseStatus'] == 200: for entry in json['responseData']['entries']: text = re.sub('<.*?>', '', entry['title']) filteredDict = dict(title = text, url = entry['url']) resultList.append(filteredDict) jsonString = simplejson.dumps( resultList ) print jsonString.strip() |
findFeed.py in Listing 15 finds the feeds and returns feed info in JSON format. The script removes tags in the feed titles. The reason is that Flex doesn’t render the tags properly anyway.
Listing 16: Adding selected feeds – addSelectedFeeds.py
1 2 3 4 5 6 7 8 9 10 11 12 | import cgi from net.ivanidris.flexreader import Feed from django.utils import simplejson form = cgi.FieldStorage() data = form.getfirst("data", "") json = simplejson.loads(data) for i in json: feed = Feed.Feed(key_name = i['url'], link = i['url'], title = i['title']) feed.put() |
In the Find Feed dialog the user can select, the feeds to add. addSelectedFeeds.py of Listing 16 as suggested by its name, adds selected feeds to the datastore.
More From ivanidris
ivanidris Recommends
- Seven Characteristics of Stepper Motors | Solder In The Veins (Solder In The Veins)
- 10 Questions with Facebook Research Engineer – Andrei Alexandrescu (Server-Side Magazine)


