82 Comments

New Mobile Safari stuff in iOS5: position:fixed, overflow:scroll, new input type support, web workers, ECMAScript 5

June 7th, 2011

(note: this is based on the first iOS5 beta [9A5220p] and is subject to change on final release)

It looks like there’s finally some major improvements in mobile Safari, some of which I’ve found below on my “first glance” after downloading the SDK. Chime in if you find anything yourself!

Bad news first

Much to my disappointment, browser-based file uploads are still not supported (input type=”file”), even though they have been supported on Android since version 2.2 (which they have continued to improve and refine). The best use case for this is uploading pictures and videos straight from the browser, but Apple seems more interested in making those functions possible directly from the operating system itself, supporting only big names like Twitter and YouTube. So much for the little guys.

There’s other stuff on my wishlist that hasn’t yet been implemented, such as WebGL and indexedDB, along with some HTML5 input types, but regardless it’s good to see some real progress in iOS 5. (update: it appears that some WebGL features are starting to be supported, although the demos I tried didn’t seem to work).

Now let’s move on to the awesome new stuff that IS implemented!

position:fixed

A point of contention since the original iPhone was released in 2007, position:fixed now works on iOS5! What this means to developers: it’s now very easy to create top and bottom toolbars for your web apps. (there’s a long history of hacks and workarounds which will still need to be implemented as a fallback for the time being, but I’ll save that for another post. I should also mention that position:fixed has worked on Android since version 2.2, and webOS seems to support a somewhat hacky implementation).

Here’s a video demo of position:fixed on iOS5:

(check out the demo for yourself)

overflow:scroll

This is a similar problem to position:fixed, but now it works on iOS5! For content that doesn’t fit in its container element, previously the content was completely cut off (similarly with iframes). On the desktop we have the option to show scrollbars instead, allowing the user to scroll to see the content, but iOS made this difficult by requiring two fingers to scroll. Now overflow:scroll works and the user can scroll through the container’s content with a single finger. Developers can use new CSS to enable native scrolling (with scrollbars and momentum): -webkit-overflow-scrolling: touch; (via Johan Brook).

It’s assumed that it’s up to the developer to implement some sort of visual indicator to let the user know they can interact with the element.

One criticism so far: there’s no inertia scroll on this element, so it doesn’t quite feel the same as scrolling the page.

Here’s a quick video demo of overflow:scroll on iOS 5.

(check out the demo for yourself)

New Input Types

HTML5 defined many new helpful input types, and mobile operating systems have been slowly implementing them and creating optimized keyboards for the inputs. iOS5 now supports these input types: date, datetime, month, time, range. Click on the images to see their respective demo pages:

iOS Date InputiOS Datetime InputiOS Month InputiOS Time InputiOS Range Input

And a fun one – my iPhone slider hack based on input type range, which now actually works on the iPhone itself (because input type=”range” is now supported)!

iOS Slider implemented with Range Input

Web Workers (JavaScript)

JavaScript is single-threaded, and it happens to run on the same thread as the UI, which means computationally expensive operations can lead to an unresponsive UI, and no one likes that. Web Workers help by offloading tasks to another thread and only returning output when it needs to. In other words, it’s a good thing for us web developers.

According to my own tests, Web Workers seemed to be briefly enabled on early versions of iOS3, but were soon disabled thereafter. Now with iOS5, they’re back again!

New ECMAScript 5 stuff (JavaScript)

(based on kangax’s ECMAScript 5 compatibility table)

Feature iOS 4.3.2 iOS 5 beta 1
Object.create Yes Yes
Object.defineProperty Yes Yes
Object.defineProperties Yes Yes
Object.getPrototypeOf Yes Yes
Object.keys Yes Yes
Object.seal No Yes
Object.freeze No Yes
Object.preventExtensions No Yes
Object.isSealed No Yes
Object.isFrozen No Yes
Object.isExtensible No Yes
Object.getOwnPropertyDescriptor Yes Yes
Object.getOwnPropertyNames Yes Yes
Date.prototype.toISOString Yes Yes
Date.prototype.toISOString Yes Yes
Date.prototype.toISOString Yes Yes
Date.now Yes Yes
JSON Yes Yes
Function.prototype.bind No No
String.prototype.trim Yes Yes
Array.prototype.indexOf Yes Yes
Array.prototype.lastIndexOf Yes Yes
Array.prototype.every Yes Yes
Array.prototype.some Yes Yes
Array.prototype.forEach Yes Yes
Array.prototype.map Yes Yes
Array.prototype.filter Yes Yes
Array.prototype.reduce Yes Yes
Array.prototype.reduceRight Yes Yes
Getter in property initializer Yes Yes
Setter in property initializer Yes Yes
Property access on strings Yes Yes
Reserved words as property names No Yes
Strict mode No Yes

HTML5Test score

iOS 4.3.2 scores 206 (7 bonus points) on the HTML5 Test, whereas iOS 5 beta scores 267 (9 bonus points). Much of these gains seem to be made in the “Forms” and “Parsing rules” sections, as well as the “Web Workers” section.

Miscellaneous new stuff

  • Inline SVG in text/html
  • float32array, int8array, int16array, int32array in JavaScript
  • window.matchmedia() (JavaScript)
  • onsearch Event (JavaScript) – it looks like this was just broken in later iOS 4.3 builds, but it’s back now in iOS 5
  • MathML elements recognized (based on html5test)
  • Improved speed of Canvas rendering (source)
  • UIWebView and home screen web apps now running on Nitro? (expected but not tested)
  • Newly supported CSS gradient syntax (-webkit-linear-gradient versus the older -webkit-gradient syntax)
  • classList (JavaScript)
  • A major WebKit HTML5 History (popstate) bug is now fixed
  • contentEditable now works properly
19 Comments

The incredibly painful way of getting an RSS feed of a Twitter list

June 5th, 2011

(why does Twitter make it so hard? What did RSS ever do to it?)

The skinny

The Twitter API appears to support two methods for getting RSS feeds of lists. Both of these methods are pretty buried and their API docs don’t help too much, but nonetheless both of these feeds work:

http://api.twitter.com/1/nathansmith/lists/javascript/statuses.atom

If you have the list ID (requires using some dev tools – see below), you can also use this format:

http://api.twitter.com/1/lists/statuses.atom?list_id=41981352

The explanation

As it turns out, getting an RSS feed of a Twitter list is no easy task, at least from what I’ve found. Twitter has largely replaced RSS for me, in terms of getting the latest and greatest information, and maybe Twitter wants to keep it that way by having me rely on their service instead of an RSS feed. That’s how it seems to me anyway (this is also evidenced by their killing off of making RSS feeds easily discoverable but still making the feed available as long as you can figure out your Twitter user id (which is a task in itself), for instance here’s my RSS feed: https://twitter.com/statuses/user_timeline/16521889.rss). I’d say this is simply a conspiracy against RSS feeds and developers in general, which is the direction Twitter is headed these days.

In any case, I digress! I want to get an RSS feed of a Twitter list. Great! All I should have to do is go to the page of the list and subscribe to the RSS feed. But.. there’s no RSS feed. Hmm.

Google is your friend… most of the time

A search for “twitter list rss” comes up with links to implementing an RSS feed via Yahoo Pipes as well as pages referring to an appspot service that now 404s (twiterlist2rss). In any case, they are both not what I’m looking for. Which means I have to get creative. Which means… my options at this point are screen scraping (made harder by the fact that Twitter content is now served with JavaScript) or.. gasp.. using their API!

Twitter REST API to the rescue

After digging through the API docs, I found just the page I was looking for, detailing the REST service for Twitter lists.

As it turns out, the basic structure for requesting list data is as follows:

http://api.twitter.com/version/lists/statuses.format

As a newbie Twitter developer, there were a couple of things wrong here. First, what’s the version of the API I’m supposed to use? From other examples on the web (outside of the documentation…) I just assumed I’d be using version 1, and that seemed to work. Ok, whatever, we’ll go with 1:

http://api.twitter.com/1/lists/statuses.format

Second step: this API is actually quite nice, and will return data in three different formats: xml, json, or atom (RSS!). Ok, now we’re making progress!

http://api.twitter.com/1/lists/statuses.atom

Where’s this list_id you speak of?

Now to pass in the info – I need to pass in the list ID in a key called “list_id”. The only problem is… where do I find the list ID? For the purposes of this example I’ll use Nathan Smith’s excellent JavaScript developers list. To normal human beings, this list might be called “nathansmith/javascript”, but a Twitter ID is numerical, so that’s not what we’re looking for.

So.. I assume at this point I can use some of the Twitter developer tools and fiddle around with them until I find an API call that will translate the human-readable list name into a numerical ID. But no.. I don’t want to download anything, I don’t want to investigate more of the API or go down any more rabbit holes.

It’s time to cut this rabbit hole short and do a bit of investigating. So I pulled up the list, opened up Web Inspector in Chrome, and took a look at the Network tab in the hopes of seeing an API call with an ID I was looking for…

…And I found it! Somewhere down the line, Twitter was calling statuses.json with this request:

https://api.twitter.com/1/lists/statuses.json?list_id=41981352&include_entities=1&include_available_features=1&contributor_details=true

There’s our list_id (and incidentally, the same API call [with json instead of atom].. which shows that Web Inspector is more useful than API docs sometimes)! After a short copy-paste, all the pieces of my Frankenstein API call have been put together:

http://api.twitter.com/1/lists/statuses.atom?list_id=41981352

And it works, without having to mess around with OAuth or authentication, registering an app, or whatever. Of course now we can refer back to the API docs and mess around with some parameters to get just the data I’m looking for. Maybe most useful to developers is the handy ability to get easily paginated results:

http://api.twitter.com/1/lists/statuses.atom?list_id=41981352&page=2

There’s also what would be a handy “count” variable, but it’s altogether useless as it appears to be ignored. The API always returned 20 results for me.

In any case, there you have it! The incredibly roundabout way to get an RSS feed of your favorite Twitter list.

UPDATE

Thanks to this site, it looks like there’s a more straightforward way of getting the RSS feed. Using the same list we were trying to get above, it looks like this also works:

http://api.twitter.com/1/nathansmith/lists/javascript/statuses.atom

12 Comments

Android 3.0 Honeycomb is first to implement the Device API

February 24th, 2011

I fired up the newly released Android 3.0 SDK to run some tests and found they’ve implemented part of the long-awaited Device API (aka the Media Capture API). From your browser you can now upload pictures and videos from the camera as well as sounds from the microphone. The returned data should be available to manipulate via the File API (although I haven’t yet tested this).

I made a short video demo with some explanation:

Here’s the code so you can play around with it for yourself!

<form enctype="multipart/form-data" method="post">
  <h2>Regular file upload</h2>
  <input type="file"></input>

  <h2>capture=camera</h2>
  <input type="file" accept="image/*;capture=camera"></input>

  <h2>capture=camcorder</h2>
  <input type="file" accept="video/*;capture=camcorder"></input>

  <h2>capture=microphone</h2>
  <input type="file" accept="audio/*;capture=microphone"></input>
</form>
1 Comment

My O’Reilly Books Wishlist

February 22nd, 2011

Introduction

Ok, so this post is only here in the hopes I’ll actually win something. :P

O’Reilly Books has a promotion where a random winner will receive up to $500 of books on their wishlist, provided they post the list somewhere online. You can probably see why this is here then!

The List

Programming the Mobile Web ($50)
Palm webOS ($45)
MongoDB: The Definitive Guide ($40)
JavaScript: The Definitive Guide: Rough Cuts Version, Sixth Edition ($50)
HTML5: Up and Running ($30)
Building Android Apps with HTML, CSS, and JavaScript ($30)
Building iPhone Apps with HTML, CSS, and JavaScript ($30)
HTML & CSS: The Good Parts ($35)
HTML5 Canvas ($40)
jQuery Cookbook ($35)
Learning Android ($35)
CSS Cookbook, Third Edition ($50)

3 Comments

Improving yourself as a programmer versus as a human being

February 20th, 2011

(OR “The Post In Which I Conflate Programming and Philosophy” OR “The Programmer’s Existentialist Crisis”)

I woke up this morning to read Dmitry A. Soshnikov’s tweet:
Have one-two langs in which you are a master and know professionally, and in addition, consider alternative langs. Your experience will grow.

While this seems like good advice for aspiring programmers, I can’t help but think what this means for those who will buy into this. Us programmers have a keen ability to sit and focus on problems for extended periods of time, usually to the detriment of everything else around us. From the perspective of “real life”, we might as well be sitting in a basement somewhere playing World of Warcraft. Sure, programming is more productive, profitable, and surely not brainless, but at the end of the day we could still only be sitting in a basement somewhere. What I mean to say here is that we’re not actually living our actual lives doing these things.

I realize Dmitry was only talking about learning another programming language for professional life, but for me and so many others, professional life is not easily separated from personal life. We don’t just work during the week during work hours. We can’t just turn off our minds and stop thinking about it when we go home. I end up thinking about programming or web design puzzles in my leisure time and on weekends, largely because I enjoy doing so. But when I see something questioning whether I should be devoting even more of this time to learning another programming language, I think about what I could be doing instead. Put another way, I think about what is missing and neglected in my life, and how those things will remain missing and neglected.

Socrates famously said “The unexamined life is not worth living”. He, along with those who followed in his immediate footsteps (famously, Plato and Aristotle) were concerned with how us mere mortals should live our lives, and more particularly how we should lead good lives. The sad fact about (western) philosophy is that it’s turned into a shadow of its former self, now plagued by millennia of self-doubt and failed grandiose systems. But it seems the original Socratic intention of finding how to lead a good life is still an admirable goal, even if we disagree on how exactly to achieve it.

Socrates also had a bit to say about those seeking to be experts in their field, and he couldn’t resist getting in a jab at his wife in the process:

It is the example of the rider who wishes to become an expert horseman: “None of your soft-mouthed, docile animals for me,” he says; “the horse for me to own must show some spirit” in the belief, no doubt, if he can manage such an animal, it will be easy enough to deal with every other horse besides. And that is just my case. I wish to deal with human beings, to associate with man in general; hence my choice of wife. I know full well, if I can tolerate her spirit, I can with ease attach myself to every human being else.

Yes, Socrates essentially just compared his wife with a horse. A wild horse, to be exact.

I’m unsure if this translates well into learning programming languages. Does this mean we should learn the worst languages first, so that the rest of the languages we learn will be comparably easy? I hope not, that seems like quite a lot of wasted time. But I certainly agree that the first languages we learn shouldn’t be the easiest. This might only make us frustrated in the long run. So perhaps we can learn something from Socrates’s quote after all, if taken with a grain of salt.

So should we still strive to become experts in our field? I believe that’s an admirable and acceptable goal, but it shouldn’t be our main goal. We should first be concerned with leading good lives. I myself have a LONG way to go on this point, believe me.

I’ll surely learn another programming language, but not for its own sake, unless my life is in reasonably good order.