1.2 Requesting feed information
The FeedRequest object sends a POST request to Google App Engine or FeedRequestHandler in main.py, to be exact. The classes involved on the client are URLLoader, URLRequest, URLRequestMethod and URLVariables. The request is sent to /feed with variable feedLinks see 2.1 and Listing 9 to follow the handling of the request on the back-end. navigateToURL is a package-level function that opens a window at the specified URL. I use again the as3corelib to process the JSON response. As mentioned above the setContent Javascript function displays the content of the feed items. setContent gets a string parameter via the Flash ExternalInterface.
Listing 3: FeedRequest.as requests feed information.
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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | package net.ivanidris.flexreader { import com.adobe.serialization.json.JSON; import flash.events.Event; import flash.events.IOErrorEvent; import flash.events.KeyboardEvent; import flash.external.ExternalInterface; import flash.net.URLLoader; import flash.net.URLRequest; import flash.net.URLRequestMethod; import flash.net.URLVariables; import flash.net.navigateToURL; import mx.containers.GridItem; import mx.containers.GridRow; import mx.controls.Label; import mx.managers.PopUpManager; import net.ivanidris.flex.Counter; import net.ivanidris.flexreader.windows.AddComment; import net.ivanidris.flex.Bookmarks; public class FeedRequest { private var loader:URLLoader; private var app; private var counter:Counter; private var entries:FeedEntryCollection; private var feedLinks:Array; public function FeedRequest(app, entries:FeedEntryCollection, counter:Counter, feedLinks:Array):void { this.app = app; this.entries = entries; this.counter = counter; this.feedLinks = feedLinks; } public function initGrid():void { this.app.readerGrid.setFocus(); this.app.readerGrid.addEventListener(Event.ACTIVATE, getFocusBack); this.app.readerGrid.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); for(var i:uint = 0; i < 9; i++) { var row:GridRow = new GridRow(); var item:GridItem = new GridItem(); var label:Label = new Label(); item.addChild(label); row.addChild(item); this.app.readerGrid.addChild(row); } } public function getFeed():void { try { var url:String = '/feed'; var request:URLRequest = new URLRequest(url); var variables:URLVariables = new URLVariables(); variables.feedLinks = escape(JSON.encode(this.feedLinks)); request.data = variables; request.method = URLRequestMethod.POST; loader = new URLLoader(request); loader.addEventListener(IOErrorEvent.IO_ERROR, onIOError); loader.addEventListener(Event.COMPLETE, onServerResponse); } catch(e:Error) { trace(e.message + e.getStackTrace()); } } public function onServerResponse(e:Event):void { loadResults(); } private function onIOError(event:IOErrorEvent):void { trace("ioErrorHandler: " + event); } public function getFocusBack(e:Event):void { setStyle(counter.get()); } public function updateDisplay():void { var s:String = '#' + ( counter.get() + 1 ) ; this.app.currentDisplay.text = s + ' Feed ' + this.entries.getFeedLink(counter.get()); } public function onKeyDown(e:KeyboardEvent) :void{ if(e.target.name.indexOf('Grid') < 0) { return; } if(String.fromCharCode(e.charCode) == 'j' ) { var isNotLast:Boolean = counter.increment(); setStyle(counter.get()); updateDisplay(); this.app.display.text = this.entries.getMarkedNumber() + '/' + (counter.getMax() + 1) + ' read'; if((counter.get() - 1) >= 0) { this.entries.setMarked(counter.get() - 1); } // move on if(!isNotLast) { getFeed(); } } if(String.fromCharCode(e.charCode) == 'k' ) { counter.decrement(); updateDisplay(); setStyle(counter.get()); } if(String.fromCharCode(e.charCode) == 'o' ) { navigateToURL(new URLRequest( this.entries.getUrl(counter.get()))); } if(String.fromCharCode(e.charCode) == 'b' ) { var bookmarksWindow:Bookmarks = Bookmarks(PopUpManager.createPopUp(this.app, Bookmarks, false)); PopUpManager.centerPopUp(bookmarksWindow); bookmarksWindow.title = "Add Bookmark"; bookmarksWindow.url.text = this.entries.getUrl(counter.get()); bookmarksWindow.t.text = this.entries.getTitle(counter.get()); } if(String.fromCharCode(e.charCode) == 'c' ) { var commentsWindow:AddComment = AddComment(PopUpManager.createPopUp(this.app, AddComment, false)); commentsWindow.url.text = this.entries.getUrl(counter.get()); commentsWindow.t.text = this.entries.getTitle(counter.get()); } } public function loadResults():void { try { var json:Object = JSON.decode(unescape(loader.data)); if(json == null || json.length == "") { trace('Nothing to do ' + loader.data); return; } var currentFeed:String = json[0].feedLink; if(this.feedLinks.indexOf(currentFeed) < 0) { this.feedLinks.push(currentFeed); } // must not do anything if nothing is added var newAdded:Boolean = false; for each(var i in json[1].entries) { var feedEntry:FeedEntry = new FeedEntry(); feedEntry.title = i.title; feedEntry.url = i.url; feedEntry.content = i.content; feedEntry.feedLink = currentFeed; if(this.entries.contains(feedEntry)) { continue; } newAdded = true; this.entries.add(feedEntry); } if(newAdded) { counter.setMax(this.entries.len()); setStyle(0); } } catch(ignored:Error) { trace(ignored.message + ignored.getStackTrace()); trace('Error decoding JSON datan' + loader.data); } } public function setStyle(index:Number):void { ExternalInterface.call("setContent", this.entries.getContent(index)); var numEntries:uint = this.entries.len(); for(var i:uint = 0; i < this.app.readerGrid.numChildren; i++) { var row = this.app.readerGrid.getChildAt(i); if(row != null) { if(i == 0) { row.setFocus(); row.drawFocus(true); } if((index + i) < numEntries) { row.getChildAt(0).getChildAt(0).text = this.entries.getTitle(index + i); if(this.entries.getMarked(index + i)) { row.getChildAt(0).getChildAt(0).setStyle('color', '#FF0000'); } } else { row.getChildAt(0).getChildAt(0).text = ""; } } } } } } |
Here the issue with losing focus occurs once more, see my previous article for more information. I never experienced this issue with AJAX, it must be a Flex related glitch. The JSON response results are parsed and placed in FeedEntry objects. These are then put in a FeedEntryCollection object. Read articles are marked in red by the setStyle function. The setStyle function draws a box around the current item as well. Part of the code deals with keeping track of read items. updateDisplay shows in a small display how many items are in the reading tray and how many of those have already been read. When you hit the bottom of your reading tray, or with other words you have read all items, FlexReader polls for new items from the feeds in the datastore. New items are automatically shown and the display refreshed.
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)
