FeedSpider Dev Blog: After Action Report

FeedSpider 1.0.0 was approved and published to the Firefox Marketplace last Sunday, and I’m happy to say that I had a great experience with the process! It was simple and straightforward, and there few really nice features that the webOS App Catalog was missing.

Notably, when you upload your app package to the Firefox Marketplace, it is scanned by the automated system to let you know if there are any conditions that would cause the app to be instantly rejected. In my case, I had one critical failure on the first upload. One of the rules for privileged apps (at least) is no inline script tags. All scripts must be loaded from .js files. The Enyo bootplate uses an inline script tag in its index.html to load the debug page if the minified version of the app is not present, so I had to pull that out.

The other neat feature is that it will tell you what position your app is in the review queue and the estimated time before it is reviewed. That’s something that I would have loved to have in the webOS App Catalog.

I also had the chance to go through the Marketplace’s update process yesterday. I’ve had a few bugs reported to me and found a couple others on my own. Any application (even one as relatively simple as FeedSpider) is a complex beast; there are behaviours that you wouldn’t even think to test for until it gets into the hands of others and they find out that things don’t exactly work as expected. The core logic still seems pretty solid, as it has undergone few changes from the webOS version. But I completely rewrote the UI layer, so I’ve been expecting to find little glitches along the way. There are a couple of notable ones that I fixed in 1.0.1, mostly relating to how individual articles are handled. I also fixed the one where the main list doesn’t refresh properly after you finish reading all of the articles in a feed or category. Instead, it redraws the dynamic part of the list over the static part of the list. That just required setting the list count to 0 before refreshing it.

The big lesson in this version was on how Enyo Scrollers behave. FeedSpider 1.0.0 just resets the content of the article scroller when you switch between articles. That, however, doesn’t reset the scroll position. So, if you open an article, scroll to the bottom, and then open another article, you’ll find the scroller in the same position as the previous article. The solution to this problem seemed obvious – reset the scroller position to the top before displaying the article panel.

Not exactly.

This works when using the forward and back buttons at the bottom of the article page to switch between articles, since the article panel remains visible. However, when moving from the list of articles to an individual article, it doesn’t. I had to do a bit of digging using console.log and the scroller’s getScrollBounds call, and I learned that if the scroller is not visible on screen, getScrollBounds will return 0,0 regardless of the actual scroll position. So, the solution wound up being making sure to make the article panel visible before resetting it’s content and calling scrollToTop.

The other issue that I ran into was with link handling in the individual articles, or rather that there wasn’t any. Clicking on the article title would properly load the article in the browser, but clicking on a link in the article body would cause problems. The root cause of that is that in webOS, clicking on an external link in an application in webOS will open it in the default browser. In Firefox OS, due to the slightly different nature of how applications work, an application can load web content right in it’s window, but it has to provide the browser chrome. I missed that while planning out the app.

For FeedSpider 1.0.0, this means that clicking on a link in the article body will cause the link to load in FeedSpider’s window, with no way to get back short of closing the app entirely and re-loading it. The solution at least, is simple. If you add the target=”_blank” attribute to the link, it will properly open in a new window. The implementation, however, is a little more difficult when all you have to work with is a blob of html content.

If I were using jQuery, the solution would be simple – add a global click handler to ‘a’ tags, as demonstrated here. Then I could stop the link click and redirect it to a web activity or something else. Since Enyo doesn’t implement event handlers like that, it becomes a little more complicated. I thought about using regex to parse the blob and automatically insert the target attribute to any links, but you know what they say about regular expressions. And, apparently attempting to do that specific operation is bad practice and something that I was warned against.

The far simpler (and hopefully better) solution was to do it the Enyo way. I set up a tap event handler on the component that holds the content. If the target of the tap event has an “href” attribute, then I add the “target” attribute and let the click bubble its way up the chain, causing it to open in the default browser. What throws a wrench in the works are elements that are wrapped in <a> tags, such as images. There, the tap registers on the image, rather than the link. So, I have to check the parent element as well, and do the same procedure if the parent has an “href” attribute. My method winds up looking like this:

 catchLinkTap: function(inSender, inEvent)
 {
     if (inEvent.target.href != undefined) {
         inEvent.target.target = "_blank"
     }
 
     //Catch images. These will be wrapped in an <a> tag.
     if (inEvent.target.parentElement.href != undefined)
     {
         inEvent.target.parentElement.target = "_blank"
     }
 },

It feels a little bit clunky, because I’m using a “global” tap handler rather than an element-specific one. But, still, it works pretty well.

So, what happens next? There’s one thing that is still missing from the Enyo port, simply because I was not sure how to do it – localization. Fortunately, @_minego as been working on the same thing for Macaw and has graciously offered me the use of his library. So, that is the next major milestone for FeedSpider. Once I get localization implemented, (and maybe another round of bugfixes as the UI matures), I’ll start looking at the cross-platfom port. I still intend for webOS to be the next target – I did promise after all.

To close, congrats to @_minego for getting Macaw done and into the Marketplace! FeedSpider 1.0.1 is currently 9 of 24 in queue, and should hopefully be published within the next few days. I hope to see it out there soon!