Web App Stores Via Twittter/Facebook

It seems likely to me that Facebook and Twitter will eventually be competing with Apple in terms of App stores. Facebook sort of already is with their extensive apps platform, however that’s just competing for developer attention. Twitter doesn’t really have an equivalent today (developers mainly build clients and interact with data), but don’t underestimate their clout.

The reason I say this is that Facebook and Twitter have become identity gatekeepers on the net. Already you can login to many sites via accounts with one of the two sites. Creating the API’s to handle purchase/subscriptions and transparently handling the billing to effectively turning a HTML5 site into an “app” is the next logical step. They could undercut Apple and still walk away with a handsome profit for not doing terribly much more than leveraging their size and reach. These apps would work on any device with a web browser. Desktop or mobile.

Given both sites need to diversify revenue streams (something Google never figured out), it seems only logical to make this step. $0.99 for Angry Birds seems more than plausible.

And yes, there are offline abilities in a browser.

Make Login Pages Autofocus

I see this way too often and it gets on my nerves. If you have a page that’s main purpose is a form, such as a login page, please make the page autofocus to the first field in the form. Having to tab or click on the first field is a nuisance. Even big sites make this mistake.

If you don’t care about IE you can do it as simply as:

<form method="post" action="/">
<p>
    <label for="username">Username:</label>
    <input type="text" name="username" id="username" autofocus="autofocus"/>
</p>
<p>
    <label for="password">Password:</label>
    <input type="password" name="password" id="password" />
</p>
<p><input type="submit" name="login" value="Login"/></p>
</form>

Since autofocus is boolean you technically don’t even need to specify an attribute value.

To do it with IE in mind you could use the following JavaScript below the form (no library needed):

function focusForm(){
    setTimeout(function(){
        try {
            // id of element to focus on
            var elem = document.getElementById(‘username’);
            elem.focus();
            elem.select();
        } catch(e){}
    }, 50); // setTimeout to fix IE bug
}
focusForm();

Note the use of select() so if the form reloads due to an incorrect password the field is not just in focus but the contents highlighted. There is also a setTimeout() since IE, at least some older versions have trouble with this if it happens too quickly. 50 should be fast enough that it won’t be noticed by humans.

See how simple that is? No excuses for not fixing this 😉 .

localStorage With Cookie Fallback

I mentioned the other day that localStorage can be used as an alternative for cookies. The benefit is that localStorage doesn’t sent it’s data back on every request to the server like a cookie. Headers are uncompressed in http making that very costly. However not every web browser out there supports localStorage. Most however do.

Here’s an example based on jQuery and jQuery.cookie. It’s designed to turn objects into JSON and store the JSON representation. On retrieval it restores the object. This doesn’t handle things like expiring cookies (it simply defaults to 365 days). I just had this around from an old project with these very specific requirements and figured I’d post it as-is in case it can help anyone and to demonstrate. This isn’t ideal for reuse, but for someone playing with the idea, maybe it will motivate 😉 .

function storeData(type, obj){
    var data = jQuery.toJSON(obj);
 
    // If using a modern browser, lets use localStorage and avoid the overhead
    // of a cookie
    if(typeof localStorage != ‘undefined’ && localStorage !== null){
        localStorage[type] = data;
    }
 
    // Otherwise we need to store data in a cookie, not quite so eloquent.
    else {
        jQuery.cookie(type, data, { expires: 365, path: ‘/’ });
    }
}
 
function loadStoredData(type){
     var data;
 
    // If using localStorage, retrieve from there
    if(typeof localStorage != ‘undefined’ && localStorage !== null){
        data = localStorage[type];
    }
 
    // Otherwise we have to use cookie based storage
    else {
        data = jQuery.cookie(type);
    }
 
    // If we have data, lets turn it into an object, otherwise return false
    if(data){
        return jQuery.secureEvalJSON(data);
    }
    return false;
}

Pretty simple right? It’s still a key/value API.

Mobile Experience On A Budget

This blog is largely read by people on traditional desktops and laptops. It’s mobile usage is a bit on the low side, though that’s changing. I decided I wanted to start making the mobile experience suck less, but I didn’t want to go as far as serving a whole new experience for mobile. Responsive web design is interesting, but I didn’t want to invest so much time in it just yet.

This is still an ongoing project, and partially an experiment but here is my game plan:

Make The Standard Design Light/Flexible

The site right now is actually pretty simple in design and structure. It’s a grid layout, everything is modular and ID/classed up. I’m a slight performance junkie and graphically impaired, so image use is pretty minimal and I’ve sprited what I could to make the design as light weight as possible. The core site itself is actually just a few requests. Everything that can benefit from being so is minimized/gziped to lessen the payload down the wire. JS is only included on pages where it’s needed. Light payloads and minimal requests are the name of the game.

This benefits all platforms. Even with 45 thumbnails from Project 365 images on one page, I still can load it all about 2.5 seconds on my laptop. That’s not terrible. Some say “think mobile first”. I say “think performance everywhere”. There’s no reason why performance should be limited to mobile.

Rejigger For Mobile

Step two is to adjust the site for mobile. In my case that means hiding some less useful things, and some size and layout related changes to fit on a smaller screen. Like I said, I’m not serving up a separate mobile site. My pages are already rather light and saving 1 KB doesn’t seem worth it to me just yet. I just want my existing site to not feel like a desktop site. This is more about usability. Performance wise I optimized with mobile in the back of my head while working on the desktop experience.

I didn’t want to include a separate mobile stylesheet since my changes are intended to be subtle and minimal. Besides, that’s a separate request for mobile users. Instead I appended to my existing stylesheet with something like this:

@media only screen and (max-device-width: 480px) {
    body  {
        min-width: 0;
        width: auto;
    }
    #page {
        min-width: 0;
        width: 100%;
    }
    /* and so on… */
}
@media screen and (max-device-width: 480px) and (orientation:landscape) {
    /* landscape specific css */
}

Like I said, I intended for my changes to be pretty subtle. This works pretty well. The one thing it can’t really handle is images. I tend to be pretty light on image use, so it’s not a deal killer for me. However I may eventually look at better solutions in the responsive image world. For now I’ll just make the editorial decision to keep image use tame.

In general my philosophy has been:

  • Does this have value in a mobile context? (no: hide it, yes: continue)
  • Can I adjust the layout/design to make this not suck on mobile? (no: hide it, yes: continue)
  • Is this more work than it’s worth? (no: do it, yes: hide it)

Final Thoughts

I’ve still got some more polish to do, I know <pre/> blocks don’t look/feel right and the comments area is still not quite there. The image gallery experience is not even started. But overall it’s still better than the desktop experience I was serving just hours ago.

Perhaps one day the paradigm will shift on this blog, but I don’t see that happening just yet. Most of what benefits mobile also benefits the desktop experience. This approach gives me an improved mobile experience with minimal hassle. I also benefit from not needing two do work twice as I would if I had a separate mobile experience. That means more time to be productive.

IE6 Is Dead

Via the Exploring IE (listen to this in the background to set the mood):

Time to pop open the champagne because, based on the latest data from Net Applications, IE6 usage in the US has now officially dropped below 1%!

I’ve officially updated my last IE6 install to IE7. This is great news for the Internet. Everyone on the web benefits by this old browser going away. Developers can iterate faster and do more.

IE7… I’m looking at you now.

jQuery And Checkbox Values

I rarely use checkboxes and radio buttons. Perhaps because of that I forgot this little rookie error.

For the intents and purposes below assume the following HTML:

<p>
<label for="checkbox1">Checkbox 1</label>
<input type="checkbox" id="checkbox1" checked="checked"/>
</p>
 
<p>
<label for="checkbox2">Checkbox 2</label>
<input type="checkbox" id="checkbox2"/>
</p>

You wouldn’t really expect it, but both of these return “on” when you get the val():

$(‘#checkbox1’).val(); // returns "on"
$(‘#checkbox2’).val(); // returns "on"

Now say you flipped them by unchecking checkbox1 and checking checkbox2. Same thing:

$(‘#checkbox1’).val(); // returns "on"
$(‘#checkbox2’).val(); // returns "on"

Now reload the page, so one is checked and two is not checked. Try again this time using .attr('checked');. That also doesn’t work, but that makes sense. jQuery 1.6’s release notes even explain it:

Before jQuery 1.6, .attr(“checked”) returned the Boolean property value (true) but as of jQuery 1.6 it returns the actual value of the attribute (an empty string), which doesn’t change when the user clicks the checkbox to change its state

The best way I’ve found to get a checkbox value is to use the is() method:

$(‘#checkbox1’).is(‘:checked’) // returns true

As to why val() doesn’t check the type of node and do this for me automatically? I’m not entirely sure. I’m assuming backwards compatibility. I suspect I’m not the only one who keeps forgetting this little caveat.

On The Future Of Flash

Adobe is killing Flash, as a plugin for mobile. This shouldn’t come as a surprise to anyone who works on the web. Anyone who knows me knows I’ve bet on HTML5 since the beginning and haven’t been ashamed to say it. I don’t do Flash. To quote Adobe:

Our future work with Flash on mobile devices will be focused on enabling Flash developers to package native apps with Adobe AIR for all the major app stores. We will no longer continue to develop Flash Player in the browser to work with new mobile device configurations (chipset, browser, OS version, etc.) following the upcoming release of Flash Player 11.1 for Android and BlackBerry PlayBook.

I strongly suspect that even this use case is limited and will experience the same fate as the Flash plugin within the next 24-36 months. HTML5 is supported by browsers, a browser is shipped with the OS and is highly optimized for what it’s running on. It’s also the ultimate in cross-platform. Why write Flash when you can do something for every platform and not rely on a vendor to abstract you?

Platforms like PhoneGap bridge the world of Apps and HTML5 quite nicely. Adobe bought Nitobi which develops PhoneGap, but PhoneGap is also going to Apache Software Foundation which means Adobe’s ability to derail the project would be somewhat limited if they wanted to go that route.

Quite a few Apps use HTML/JS extensively already. HTML5’s success is despite Apple essentially crippling the use of HTML5 in native apps by preventing UIWebView from taking advantage of the Nitro engine. If/when Apple gets to fixing this another barrier will be gone. I suspect Apple will eventually make scrolling that doesn’t suck on iOS easier. Right now Joe Hewitt’s Scrollability is likely your best bet.

Adobe goes on to say:

However, HTML5 is now universally supported on major mobile devices, in some cases exclusively. This makes HTML5 the best solution for creating and deploying content in the browser across mobile platforms. We are excited about this, and will continue our work with key players in the HTML community, including Google, Apple, Microsoft and RIM, to drive HTML5 innovation they can use to advance their mobile browsers.

Interestingly they left out that little browser vendor Mozilla. Perhaps because they are most likely targeting WebKit on mobile and that’s the common tie between those companies sans-Microsoft which they need IE support. If Adobe wants a future here they should learn quick that you can’t ignore platforms. My advice to Adobe is to make sure their solution allows developers to bring their product to any modern browser on any device.

Flash is the last plugin with real usage even on the desktop. This is the first step towards the concept of plugins in the browser going away. It’s unlikely many will see a need to go HTML5 on mobile and develop a separate Flash code base to do the same thing on a desktop. The name of the game these days is write once, run anywhere (credit to Sun for the slogan). Today marks the start of the decline of Flash.

As Brendan Eich best put it: “Always bet on JavasScript“. I have and I continue to do so. The Open Web is winning. Slowly but surely.

PHP’s include_once() Is Insanely Expensive

I’ve always heard the include_once() and require_once() functions were computationally expensive in PHP, but I never knew how much. I tested the following out on my i7 2010 MacBook Pro using PHP 5.3.4 as shipped by Apple.

This first test uses include_once() to keep track of how often a file is included:

$includes = Array();
$file = ‘benchmarkinclude’;
 
for($i=0; $i < 1000000; $i++){
    include_once($file.‘.php’);
}

Took: 10.020140171051 sec

This second example uses include() and uses in_array() to keep track of if I loaded the include:

$includes = Array();
$file = ‘benchmarkinclude’;
 
for($i=0; $i < 1000000; $i++){
    if(!in_array($file, $includes)){
        include($file . ‘.php’);
        $includes[] = $file;
    }
}

Took: 0.27652382850647 sec

For both, the include had the following computation:

$x = 1 + 1;

Lesson learned: Avoid using _once if you can avoid it.

Update: That means something like this will theoretically be faster:

$rja_includes = Array();
function rja_include_once($file){
    global $rja_includes;
    if(!in_array($file, $rja_includes)){
        include($file);
        $rja_includes[] = $file;
    }
}

F.B.I. Violating Section 508?

Section 508 is familiar to many in IT. For those who don’t know it, Wikipedia explains it best:

In 1998 the US Congress amended the Rehabilitation Act to require Federal agencies to make their electronic and information technology accessible to people with disabilities. Section 508 was enacted to eliminate barriers in information technology, to make available new opportunities for people with disabilities, and to encourage development of technologies that will help achieve these goals. The law applies to all Federal agencies when they develop, procure, maintain, or use electronic and information technology. Under Section 508 (29 U.S.C. § 794d), agencies must give disabled employees and members of the public access to information that is comparable to the access available to others.

The F.B.I however decided it’s above this law and decided to replace the shutdown pages for a bunch of gambling sites they shut down with the following HTML (example link):

<html>
  <title>WARNING</title>
<img src="banner7.jpg"/>
</html>

I’ve noticed this several times over the years, so this seems to be a chronic problem nobody is calling them out on.

The image (linked locally for posterity) contains the following text below the FBI and DOJ seal’s:

This domain name has been seized by the F.B.I pursuant to an Arrest Warrant in Rem obtained by the United States Attorney’s Office for the Southern District of New York and issued by the United States District Court for the Southern District of New York.

Conducting, financing, managing, supervising, directing, or owning all or part of an illegal gambling business is a federal crime (18 U.S.C § 1955)

For persons engaged in the business of betting or wagering, it is also a federal crime to knowingly accept, in connection with the participation of another person in unlawful Internet gambling, credit, electronic fund transfers, or checks. (31 U.S.C §§ 5363 & 5366)

Violation of these laws carry criminal penalties of up to five years’ imprisonment and a fine up to $250,000.

Properties, including domain names, used in violation of the provisions of 18 U.S.C 1955 or involved in money laundering transactions are subject to forfeiture to the United States.
(18 U.S.C. §§ 981 & 1955(d))

To my knowledge, this is a direct violation of Section 508. There are provisions for when Section 508 compliance creates an undue burden, however this could be remedied in under 5 minutes by using text rather than an image. It’s a clear violation. Any federal IT employee would know about this. Civilian IT professionals know about Section 508. The seals could have been one image with an alt tag containing the text “FBI/DOJ Seals” and the above text in HTML. This is trivial. I did half the work just transcribing it up above. I have no doubt the individual who put it together was familiar with Section 508.

In a world where we web developers make efforts to bring information to the disabled and make the internet easily accessible to those with disabilities, this is pretty sad and a real step backwards. The rest of the Internet has been moving forward to making things accessible via initiatives like WAI-ARIA. Target had to settle a lawsuit for $6 million for failing to make a much more complex site ADA compliant. Since financial settlement with the FBI would be very unlikely this gets ignored by NFB and others, but I don’t think it should be.