Posts tagged with Javascript

Immutable Javascript

November 20th, 2011

Something I quickly whipped up the other day, which you can find on GitHub as a Gist.

Wish you had some immutability in Javascript? Now you can!

var t = {a: 1, b: 2}.immutable();
console.log(t.a, t.b);
try {
  t.a = 3; // ->  Uncaught Error: a is immutable and cannot be modified.
} catch (e) {
  console.log(e);
}
var t2 = t.copy({a: 3});
console.log(t2.a, t2.b);
t2.mutable();
t2.a = 1;
console.log(t2.a, t2.b);

As you can see, the methods immutable, copy, and mutable are added to Object.prototype. This is done using custom getters and setters to mask the original properties, so it only works with objects that expose them and not things like strings. Of course, if you figure out how to get this to work for other Javascript datatypes, please let me know!

Backbone

June 22nd, 2011

One of the hot new Javascript libraries is Backbone.js, a sort of client-side MVC framework, so I decided to take it for a spin for Where’s My Bike. First, it also introduced me to Zepto, which I love. Second, its system of Models, Collections, and Views are quite powerful but it’s a real hassle to have to declare. If you have a model, say a Bike, wouldn’t you always also want a collection of them and a view to create or edit them? Read more »

Towards a Scala DSL for Javascript

June 16th, 2011

Reposting from the Lift mailing list.

For some time know I’ve been thinking about how cool it’d be to be able to essentially write Javascript but with all the Scala goodiness behind the scenes. Lift already has abstractions for more common Javascript language elements, so I have suspected that it could be used as the basic for something that looked more like plain Javascript.

This evening I was looking at PhantomJS and realized that to use it for the type of work I need I would have to control it with lots of Javascript files generated on the fly. So, I finally sat down and hacked around. This is what I’ve come up with:

As you can see, for Javascript language features I’ve basically just put j_ before what are also reserved words in Scala. So, JsFalse becomes j_false. The same is true for break, continue, and return.

As you can see with j_if and j_for, those case classes are declared such that you get a more natural syntax, one approaching Javascript’s. For instance, you can directly call a JsVar with 0 to n parameters, without writing Call("var_name", params0, ...). I guess that the experimental Dynamic trait could be added to the pimped JsVar (RichJsVar, of course) but that’s probably going a bit far! ;-)

I’ve also added a bunch of implicits, both for my pimped classes but also to convert JsCmd to JsExp. Lift already has a conversion the other way around but there isn’t one in this direction. I’m not sure if there is no implicit for a good reason. Perhaps this will break things?

Where is this wonderful code, you ask? Why, it’s a simple Gist: https://gist.github.com/1028437!

I look forward to your comments!

The Facebook Login Button and logging into your webapp

March 19th, 2011

Recently I’m been working on a single sign-on system (SSO, in the biz) and this week I added support for logging into the SSO via the Facebook Login Button. It’s cool that you can have a user log into you website using Facebook but as it stands there are a few… unfortunate… aspects to the system, all based around one fact: logging into a site using a Facebook account is logging into Facebook.

On first glance that sounds great: if a user isn’t logged into Facebook when they click the Login Button, Facebook asks them to login and then asks the user if they wish to give your app access to their data, the default being the most limited personal data (good). Sounds nice. The Facebook Javascript SDK creates a cookie on your domain with the current user’s Facebook user id and an OAuth access token. You can then make API calls. Great.

However, by using the Login Button you’re tying your app’s basic user state to Facebook. If you’re like me, you want to do some stuff, both client-side and server-side, when a user is logged into your app. Likewise, you want to preform some actions when the user logs out of your app. And we do want to let the user to be able to easily log out: maybe they’re using a computer at an internet cafe, maybe they want to let their sister log into the same site under her own account, maybe they just don’t like leaving themselves logged in. This is where I believe Login with Facebook has some problems.

Let’s assume that we have stand-alone login and logout pages. My experience is with this case, though I believe that my observations stand for other cases. Let’s take the flow in reverse, as I think it will make more sense in the end. The user clicks a link to your logout page. What do you do? Perhaps we’d like to do it all server-side so we can then redirect them to the home page without any prompting. Seems fair enough. So, let’s destroy any sessions (including cookies that sessions might be recreated from) that our website set.

But wait, Facebook created a cookie on our domain with the current user’s access token. Let’s delete that too to make sure our user is logged out of our app via Facebook. But no, that won’t work (more explanation in a bit). I know, you say: let’s use the FB.logout() function. Except that logs you out of Facebook entirely. Remember what I said about the Login Button logging you into Facebook? Well, it logically follows that the logout call logs you out.

Except, why would anyone ever want to do that to their users? It seems like such a bewildering and user-hostile option, to log the user out of Facebook when they think they’re just logging out of your site. And if you make it clear to the user that logging out of your site will also involve logging out of Facebook, who would ever want to do that?

But Facebook is using OAuth 2.0, right? So that means there’s an access token and you can revoke it, right? There definitely is an access token: Facebook nicely gives it to you at the end of a successful login process. However, you can’t programmatically revoke your own access token other than by calling FB.logout(). There’s no function to do that and for the life of me I can’t figure out as a user how to revoke access that I’ve given out. Twitter, in contrast, has a pretty easy to manage Connections page. Update: it’s the Apps You Use page.

All this hints at what I believe to be an underlying assumption: a user will never (should never) want to log out of your site once logged in by Facebook. I think this is fundamentally wrong, but let me skip that issue and explain why being unable to simply logout of the Facebook login of your app (yes, it’s a mouthful) is so annoying.

There are two main ways to detect that a user has logged into Facebook via the Login button. First, you can add an onlogin callback to the button’s XBFML declaration (aside: XFBML is so stupid). Incidentally, this callback is not documented anywhere in Facebook’s documentation. But, it exists and it works. Except, it will never fire if the user is already logged in. The user will be left clicking the Login Button madly and almost definitely not noticing the output in the Javascript error console explaining that the user cannot log in because they are already logged in. No new login, no callback called.

So that doesn’t work, on to the second option. How can we handle the case if the user clicks the login button but they’re already logged in? Luckily you can subscribe to the user.login event, which will eventually fire whenever the user is logged in. That is, it will always eventually fire. This includes when you load your login page with the Login Button: the Facebook API will be initialized, it will detect the user is logged in, and then it will fire the user.login event.

Unfortunately, since this happens all in Javascript and once the DOM has (entirely?) loaded, a user will see page flicker: they will see the login page and then it will disappear after a second if, like in my case, you redirect to another page upon successful login. It is confusing as a user to see the login page, suggesting that I am not logged in, and then to automatically be redirected and the website considers me logged in, all without me ever touching the Login Button.

I think Facebook assumes you’ll avoid this login page flicker by first checking the Facebook cookie left on your domain on the server-side. I am doing that but I run the risk of logging a user into my app based upon expired credentials which are still stored in the cookie, since I refuse to call FB.logout(). So, my website’s logout functionality currently destroys the Facebook cookie but does not call FB.logout(). But, as I mentioned, the user will be logged in automatically via the Javascript API the next time they visit the login page, despite no cookie being present.

In theory we can improve the client-side experience a little bit by first checking if the user is already logged into the website via Facebook. If they are, handle the Facebook login as normal but if, and only if, they are not do we then add the Login Button XFBML to the DOM and parse it. Then, at least, the user is only shown the login button if they need to login, but the fact remains they are still seeing the login page in the first place. In the worse case the page might be mostly empty while all the Javascript is executing to handle an already logged in user.

For this and other reasons we naturally start wondering whether some of this page flicker can be avoided by processing on the server-side. The only solution to potentially using an expired Facebook access token seems to be to use the server-side API’s authentication functionality with the cookie Facebook set, but then you start to fall down the rabbit hole of duplicating all client-side functionality in your server-side code. And if you’re like me, the original reason you chose client-side login and the Login Button was because it was so easy to implement and seemed to have a superior user experience to server-side  authentication (notice Facebook never says ‘login’ when talking about the server-side API).

One thing I’ve noticed is that Facebook’s cookies have quite short life times (like, several hours). I believe that Facebook has made the basic assumption, probably fair in most cases, that a user logging into a website using Facebook generally just wants to use it for a little bit and won’t be too put out if upon returning a day later they have to login again. And so, logout happens essentially magically as access tokens expire.

However, that still seems rather user- and developer-hostile: users will be logged out of the site without knowing it, or the site will keep them logged in based upon a stale access token, or the site must be constantly refreshing its access token behind the scenes. I don’t even know if a site can refresh it behind the scenes and in fact I think it would be somewhat bizarre if they could. The server-side authentication flow I mentioned earlier seems to be the closest thing to this.

To wrap up, I think the basic workings of the Login Button and the ability for a user to login to your website via the Facebook API is a good one, but the system makes some assumptions that are ultimately user-hostile. In some (all?) cases I think Facebook was actually trying to make the user-experience better but their solutions went against established practices for logging users into and out of websites, including facebook.com itself. I don’t have any specific recommendations beyond doing what’s expected and allowing sites to log users out of their sites (expire or destroy the access tokens).

jrunscript

November 11th, 2010

I just learned about jrunscript, which is a Javascript console and interpreter distributed with Java 6, so chances are you already have it. In fact, it is a general purpose interpreter and you can select another language with the -l flag if it is in the classpath. The -q flag lists the currently installed languages. This is what I got on OS X 10.6.4:

$ jrunscript -q
Language ECMAScript 1.6 implemention "Mozilla Rhino" 1.6 release 2
Language AppleScript 2.1.2 implemention "AppleScriptEngine" 1.0

Pretty cool and it means you don’t even need to download Rhino like I mentioned in my previous blog post of Javascript consoles.

PHP Closures

October 16th, 2010

PHP 5.3 has added support for true anonymous functions and closures. Unfortunately, there are a few gotchas.

The main one is that no variables are automatically enclosed: you must specify the variables you want to enclose. So, this will cause an exception:

$a = 2;
$f = function($i) {
  return $i + $a;
}
$f(1); // -> PHP Parse error:  syntax error, unexpected T_VARIABLE

While this is the proper format:

$a = 2;
$f = function($i) use ($a) {
  return $i + $a;
}
$f(1); // -> 3

However, you can also cheat with global:

$a = 2;
$f = function($i) {
  global $a;
  return $i + $a;
}
$f(1); // -> 3

Also, classes that are in scope seem to get imported into the closure’s scope. I believe this is because the class isn’t actually copied into the closure but is instead looked up:

class C {
  static $a = 1;
}
$f = function($i) {
  return $i + C::$a;
}

While normally you would never want to abuse the scope, I guess there may be times when you do.

You can even pass enclosed values by reference:

$a = 2;
$f = function($i) use (&$a) {
  $a = $i;
}
$f(1);
$a == 1 // -> true

Interestingly, I also learned that you can’t mutate a function’s input value:

$f = function($i) {
  return $i++;
}
$f(1); // -> 1

This is also the case in Javascript. To be honest, I’m not sure why this is, since the parameter is not an enclosed variable. But there you go. I’m sure someone who knows more about closures than me can explain why this is.

PS I find the original closures RFC somewhat more useful than the main documentation.

regexInArray

September 8th, 2010

Javascript arrays have an inArray() method that tests for the existence of a search object and returns its key. However, sometimes you don’t want to test for an exact match. I wrote a little function that will test a regex instead. Like inArray() it returns -1 if none of the elements satisfy the condition.

function regexInArray(search, arr) {
  for (var k = 0; k < arr.length; k++) {
    if (search.test(arr[k])) {
      return k;
    }
  }
  return -1;
}

MathPlus

September 8th, 2010

I’ve been slowly assembling a set of common mathematical functions in a Javascript library called MathPlus. Tonight I added support for vectors. Check it out and let me know what you think.

Imajs

July 23rd, 2010

I made this a month or two ago but I forgot to mention it here: Jacob Biljnai of Tumblr was complaining on Twitter that there wasn’t a Javascript-based image resizing API so I made him one using App English, Imajs. Enjoy.

HTML5 Video Transformation

June 4th, 2010

This week I’ve been messing around with the HTML5 video element and have discovered you can do some pretty cool stuff. For instance, Mozilla shows how to do greenscreen image replacement while a video is played. This is very cool but there’s an annoying intermediate step required: since you cannot directly fetch raw frame image data from a video element, you must write each frame to an intermediate canvas element and then use its getImageData method to get raw image data you then transform and write to the final canvas element.

I brought this up in an email to the HTML5 Doctors last night. Remy suggested that I write up a blog post with some benchmarks, so here are some quick findings. You can find my code on GitHub. In the example I take a video and invert all its colors, frame-by-frame.

Here’s my html:

And my Javascript:

Using Chrome 5.0.375.55 on OS X and its developer tools, I took a heap snapshot after loading benchmark.html. There were 2171 code (what, I don’t know) and 12463 objects, taking up 464.70 kb and 866.97 kb respectively. I then started the profiler and executed the following Javascript: var video = document.getElementById("video); video.play();. Once the video appeared to have stopped (confirmed by video.ended) I stopped the profiler and took another heap snapshot. This time there were 2202 code and 13037 objects taking up 471.58 kb and 922.11 kb. Not surprisingly the profile shows that processFrame() takes up the vast majority of execution time (77.63% self, 83.65% total).

This all leads me to believe that, at least for smaller videos like the 480 x 280 px video I used from Apple’s documentation, there are not significant performance issues when transforming videos frame-by-frame in Javascript.

That being said, I still find the process ineffiecent and would like to be able to get a sort of FrameData object directly from video elements, just like you can get an ImageData object from canvas elements. This would mean I would only need to use one canvas element (canvas2 in my example), instead of two.