Autologin script gets extraction tool

Written . Tagged Firefox, Greasemonkey, JavaScript, OS X.

Before I switched to Firefox, I was using SlimBrowser.

Though comparably sucky (no Greasemonkey!), it has something Firefox doesn’t: an autologin feature. Basically you fill out a log-in form on some page, select a menu command, and an autologin will be created. Running that autologin, e.g. through something similar to Firefox bookmark keywords, will direct you to that page, fill out the form and submit it.

Firefox can auto-fill form values, but doesn’t submit the form afterwards. Though that’s easily greasemonkeyed, it only works if you’ve a single account.

About a year ago, I first released the Autologin userscript, that worked somewhat like the SlimBrowser autologin.

Today, I updated the script, making it a lot easier to use.

With the new script, you can add an autologin by simply filling out the log-in form, making sure the focus (typically the caret) is in the form, and selecting Tools > User Script Commands > Create autologin from form. Previously, you had to poke through the page source and compose the autologin URL yourself.

Behind the code

Detecting the focused form with JavaScript was pretty interesting.

There is, to my knowledge, no obvious way to check for focus on a form (or otherwise) element.

One way of achieving this would be to add focus event handlers to every form element, so that every time a form element gains focus, it stores itself into some variable.

I went with another, rather clever solution. The idea is to use the CSS :focus pseudo-class to set some attribute value on the focused element, and then sniff for that attribute.

This idea was suggested by ecmananut. In the original suggestion, the dummy attribute to set was azimuth (being unlikely to clash with actual attributes set); for whatever reason, using that particular attribute didn’t work, so I went with background-attachment:fixed instead. Though less uncommon than azimuth, it’s probably very rare that the background-attachment of a (non-textarea) form field is set to fixed.

The pertinent code follows. with_each() wraps a for loop applying a callback function to each element matched by some XPath expression.

function get_focused_form() {
  GM_addStyle("input:focus, select:focus {background-attachment:fixed;}");
  var result;
  with_each("//input | //select", function(element) {
      var bAt = window.getComputedStyle(element, null).backgroundAttachment;
      if (bAt == "fixed")
          return (result = element);  // Return into get_focused_form
  if (result)
      return result.form;