Monday, 17 March 2014

Session tokens, cookies, and local storage

Link-post today, the Meteor blog has a very interesting post about why Meteor has so-far avoided session cookies in favor of localStorage, including a high-level but nevertheless useful overview of issues with session cookies. Useful read for the security-minded, including an interesting suggestion near the end of a "both and" approach.

Tuesday, 18 February 2014

Centering Made Easy

Almost a note-to-self today. :-) Now that IE6 and IE7 are dead unless you need to support users from the far East, centering content within elements using CSS is dead easy. Three simple rules:

display:        table-cell;
text-align:     center;
vertical-align: middle;

So for instance:

<style>
  .content {
    width: 300px;
    height: 300px;
    border: 1px solid #aaa;
    padding: 2px;
    display: table-cell;
    text-align: center;
    vertical-align: middle;
  }
</style>
<div class="content">
    Here is <strong>my content</strong> with
    <em>markup</em>; my content wraps in the container,
    but that's not a problem for this technique.
</div>

That comes out with the content nicely displayed centered both horizontally and vertically. Unlike the line-height trick, it works well with content that wraps. Here's a live example.

I'm not saying we should have to say things are table-cells when they're not, but at least it's only in the presentation layer, not the markup.

Wednesday, 22 January 2014

Plain JavaScript

"I want to do this with pure JavaScript, not jQuery."
"How do I do this with raw JavaScript?"
"I don't like to use libraries, I like to use vanilla JavaScript."

Enough! Using a library like jQuery (or Closure or MooTools or...) is using plain/vanilla/raw/pure JavaScript. (I mean, unless you're using CoffeeScript, TypeScript, Dart, or other such languages.) Using a library doesn't change the language you're using.

jQuery is a library, not a language. You don't write things "in" jQuery. You write things with jQuery, in JavaScript. Or with MooTools, in CoffeeScript. Or with Closure, in Dart. You get the idea.

If you want to do things in the browser without a browser library, what you're doing is using the DOM API directly. Which is to say, writing with the DOM API, in (choose your language, probably JavaScript).

This isn't just a rant about prepositions. (It is a rant, but not just a rant.) It's about understanding what you're using, and how.

Saturday, 11 January 2014

Windows Pop-Up Shutdown Script

Sometimes, you want to configure a Windows system so that it shows a message when shutting down. In my case, it's to remind me (because I'm too bone-headed to remember!) to unmount any shares on the relevant box, since otherwise it tends to make the machine where I have them mounted...unhappy.

It's easy to do: First, create the script you want to run, perhaps:

WScript.Echo("Remember to unmount the shares!");

...in a file somewhere (shutdownmsg.js, in my case).

Now, we tell Windows to run that on shutdown:

  1. Run gpedit.msc
  2. Navigate to Local Computer Policy > Computer Configuration > Administrative Templates > System > Scripts
  3. Change the setting for Run shutdown scripts visible to Enabled (if you don't do this, your machine will basically hang on shutdown, waiting for you to reply to a dialog box you can't see)
  4. Navigate to Local Computer Policy > Computer Configuration > Windows Settings > Scripts (Startup / Shutdown)
  5. Double-click Shutdown
  6. Click Add and add your script (in my case, c:\bin\shutdownmsg.js)
  7. Close gpedit

That's it! Now when you shut down, the dialog box will appear and stop the entire process until you dismiss it. Conveniently for me, this happens before the network stuff is shut down, so I can unmount my drives cleanly.

Tuesday, 24 September 2013

Submitting forms programmatically

Very short one today, folks, because something surprised me: If you use jQuery to submit a form programmatically, it will trigger submit handlers on the form. This surprised me because if you use the DOM to do it, it doesn't. Consider this HTML:

<form id="theForm" action="http://blog.niftysnippets.org" target="_blank" method="GET">
    <p>This one will trigger the submit handler:</p>
    <input type="submit" value="Click to send form normally">
</form>
<p>So will this one (which surprised me):</p>
<input type="button" id="jQuerySubmit" value="Click to use jQuery to send the form">
<p>This one won't (standard DOM behavior):</p>
<input type="button" id="domSubmit" value="Click to use HTMLFormElement#submit to send the form">

And this code (below the above in the HTML file):

$('#theForm').submit(function() {
  alert("jQuery submit handler called");
})[0].onsubmit = function() {
  alert("DOM submit handler called");
};

$("#jQuerySubmit").click(function() {
  $("#theForm").submit();
});

$("#domSubmit").click(function() {
  $("#theForm")[0].submit();
});

Clicking the jQuerySubmit button triggers the handlers, clicking the domSubmit button does not. Live copy

So if, like me, you're used to that handler not getting called when you submit programmatically, well, jQuery changes that! If you want the old behavior, use the DOM directly (it's only three more characters :-) ).

Happy coding!

Wednesday, 15 May 2013

Private properties in ES6 -- and ES3, and ES5

JavaScript famously lacks private properties on objects. The next version will have them (more on that below), but we can have most of the benefits of the upcoming improvement right now (without resorting to the usual hidden variables in the constructor), even on older engines. In this post, I look at what's coming, and what we can do now.

"But wait," I hear you say, "Don't we already know how to do private data, à la Crockford's Private Members in JavaScript?" Yes, but it has some downsides, not least that those members aren't actually properties, and methods shared via the prototype can't use them. A few months back, looking at the way private properties are being added to JavaScript, I was struck by how easily we can have very nearly private properties right now, today. Real properties. And of course those properties can be data properties, or methods (since methods are just data properties referring to functions). So now I'm finally getting around to writing it up.

First, a couple of terms:

  • ES3 - The version of ECMAScript (standard JavaScript) defined by the third edition specification in 1999. All major browsers support ES3.
  • ES5 - The version of ECMAScript defined by the [fifth edition specification][1] in 2011. Most modern browsers support at least parts of ES5, and many support nearly all of it.
  • ES6 - The upcoming version of ECMAScript being defined for the next specification. Early access drafts and such are available here.

The Typical Pattern For Private Information

Okay, let's start with the typical pattern for private data in classes of objects, as popularized by Crockford and others. Let's assume we have a Foo constructor and we want the objects it creates to have a hidden nifty piece of data:

function Foo() {
    var nifty = 42;

    this.method1 = function() {
        // Has access to `nifty` because this function
        // closes over it
        console.log("Truly private nifty info: " + nifty);
    };
}
Foo.prototype.method2 = function() {
    // Does not have access to `nifty`, because this
    // function does not close over it. So the following
    // line would be an error, there is no `nifty` in scope:
    // console.log("Truly private nifty info: " + nifty);
};

var f = new Foo();
f.method1(); // Can use `nifty`
f.method2(); // Cannot :-(

nifty is truly private. Nothing has access to it but the method1 function of the object created by that specific call to new Foo. So that's great...

...but there are a few issues with this pattern:

  1. Each and every Foo object gets its own method1 function. We don't get the reuse we get with method2, where there's only one of them shared by all Foo objects via the prototype. In terms of memory impact and so on, this isn't really a big deal with modern engines unless you're creating thousands and thousands of these, since modern engines are able to reuse the code of method1 even though a new method1 object is created for each Foo object. But it's unsatisfying, and there are some development patterns that involve dynamically changing the prototype, which are obviously unable to act on method1 above, as it's not on the prototype.
  2. Different Foo objects can only see their own private data, not the private data in other Foo objects. This is markedly different from languages with true private members, and makes certain operations quite difficult.
  3. There's no way to have protected properties: If we have a Bar that inherits from Foo, there's no way for Foo objects to define things that Bar objects can see but other code cannot. (Some would argue this is a good thing, because protected data members create serious coupling between the base objects and the derived objects. But they're still quite popular in Java, C#, etc.)

...and further, just subjectively, it's clunky from a style perspective.

Truly Private Properties in ES6

With ES6, we can get truly private properties, because ES6 will have private name objects. Private name objects let you use a special kind of object as a property name, rather than a string. If you don't have access to that specific name object, you can't retrieve the property from the object.

Here's what that looks like:

// ES6 private properties (not yet available in the wild
import Name from "@name"; // (Remember that this syntax is still in flux)
var Foo = (function() {
    // Create a private name object as our private property key
    var nifty = new Name();

    // Our constructor    
    function Foo() {
        // We can just assign here as normal
        this[nifty] = 42;
    }

    // Methods shared by all Foo instances
    Foo.prototype.method1 = function() {
        // This method has access to `nifty`, because it
        // closes over the private key
        console.log("Truly private nifty info: " + this[nifty]);
    };
    Foo.prototype.method2 = function() {
        // Also has access, for the same reason
        console.log("Truly private nifty info: " + this[nifty]);
    };

    return Foo;
})();

var f = new Foo();
f.method1(); // Can use `nifty`
f.method2(); // Can too! :-)
// Both `method1` and `method2` are *reused* by all `Foo` objects

It's just that simple. Properties created using private name objects are automatically non-enumerable, so they don't show up in for-in loops or calls to Object.keys, and code that doesn't have the specific Name object we created (nifty) cannot access that property. It is a property on the instance, but it's truly private.

So, how does this look against those issues with the typical pattern?

  1. Prototype methods on Foo objects can access the private data. Foo objects don't each have to have their own method1 as in the typical pattern shown at the top.
  2. Since all Foo code has access to the key, different Foo objects can see the private data in other Foo objects, as in Java, C#, etc.
  3. We could define Bar, deriving from Foo, in the same scoping function, which would mean it had access to the nifty name object and therefore to the nifty information in Foo objects.

Voilá! Truly private properties.

Which is great, but we don't have ES6 yet. Is there a way we can get there, or get close? Yes! We can get really close right now in ES5, and it's nearly as good in ES3.

Near-Private Properties in ES5 (and even ES3)

As of ES5, we can create non-enumerable properties (ones that are not included in for-in and don't show up in Object.keys). So those are fairly well hidden, but if whoever you're trying to keep this private from glances at the object once in the debugger, they can learn the name and use the property (and you end up with the consequent issues when you change something you considered private but which got used by the guy down the corridor anyway).

So what's the answer? Make the name different every time. Suppose we define our own Name constructor until we have ES6, and make it generate a random string of a reasonable length (and never the same string twice):

var Name = function() {
    var used = {};

    function Name() {
        var length, str;

        do {
            length = 5 + Math.floor(Math.random() * 10);
            str = "_";
            while (length--) {
                str += String.fromCharCode(32 + Math.floor(95 * Math.random()));
            }
        }
        while (used[str]);
        used[str] = true;
        return new String(str); // Since this is called via `new`, we have to return an object to override the default
    }

    return Name;
}();

Now we can use the ES6 code above (minus the import statement, of course) and get really obscure properties (even in ES3), in that they have names that change every time the code runs. The guy down the corridor can look at the name in the debugger, but he can't write code relying on it, because it's always changing. Instead, he has to come down the corridor and ask you to make an API change so he can do what he needs to do, which is what he should have done in the first place.

In ES5, we can take it a step further and make the property non-enumerable so that in addition to having a random name, it doesn't show up in for-in or Object.keys. We can even do that in the same codebase by only using the ES5 feature if it's present.

Here's a complete ES3 and ES5 example, using our Name constructor from above, changes called out with *** markers:

// Nearly-private properties
// ***No `import` here (once the final form is determined, we'll probably be able to feature test for it)
var Foo = (function() {
    // Create a random string as our private property key
    var nifty = new Name();

    // Our constructor    
    function Foo() {
        // We can just assign here as normal
        this[nifty] = 42;
    }

    // ***On ES5, make the property non-enumerable
    // (that's the default for properties created with
    // Object.defineProperty)
    if (Object.defineProperty) { // Only needed for ES3-compatibility
        Object.defineProperty(Foo.prototype, nifty, {
            writable: true
        });
    }
    // ***End change

    // Methods shared by all Foo instances
    Foo.prototype.method1 = function() {
        // This method has access to `nifty`, because it
        // closes over the private key
        console.log("Truly private nifty info: " + this[nifty]);
    };
    Foo.prototype.method2 = function() {
        // Also has access, for the same reason
        console.log("Truly private nifty info: " + this[nifty]);
    };

    return Foo;
})();

var f = new Foo();
f.method1(); // Can use nifty!
f.method2(); // Can too! :-)
// Both `method1` and `method2` are *reused* by all `Foo` objects

That's it! Virtually identical to the ES6 code, and it provides nearly as good encapsulation, certainly on ES5. The property we create is not truly private, but it's really obscure (on ES5) and pretty obscure even on ES3. In ES5 it doesn't show up in for-in loops (because the property we created is non-enumerable), and even on ES3 its name changes every time the code runs. So any code attempting to use the private data must first figure out the property name, which is a non-trivial exercise (probably impossible purely in code in ES5, as that code can't get a list of the non-enumerable property names of the object). Naturally, one glance at the object in a debugger shows you the property and its value, but nothing is private from debuggers, and the name will change next time. The guy down the corridor will be forced to get up and ask you to make the information available in the API, rather than using your private data!

Hey, What About Methods?

The great thing is that there's absolutely nothing special about methods using this pattern. You want a private method? Just define it, just like you define a private data property. Because of course, JavaScript doesn't really have methods, just properties that refer to functions and a bit of syntactic sugar.

Here's an example for ES3 and ES5 that uses both a private data property, and a private method. And of course, making it ES6 instead just requires adding the import and then (optionally) removing the Object.defineProperties call:

var Greeter = (function() {
    var normalize = new Name();     // Private worker method key
    var personName = new Name();    // Private data key

    // Our constructor    
    function Greeter(n) {
        this[personName] = n;
    }

    // Private properties
    if (Object.definePropertes) { // Only needed for ES3-compatibility
        Object.definePropertes(Greeter.prototype, {
            normalize:  {writable: true},
            personName: {writable: true}
        });
    }

    // Methods shared by all Greeter instances
    Greeter.prototype[normalize] = function(arg) {
        // Okay, so this is a really boring thing for the private worker method to do
        var s = this[personName];
        return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
    };
    Greeter.prototype.sayHey = function() {
        console.log("Hey " + this[normalize]());
    };
    Greeter.prototype.sayBye = function() {
        console.log("Bye " + this[normalize]());
    };

    return Greeter;
})();

var g = new Greeter("JACK"); // Note the all caps
g.sayHey(); // "Hey Jack"
g.sayBye(); // "Bye Jack"

Happy Coding!

Wednesday, 13 February 2013

Opera switching to WebKit+V8

Opera has decided to switch to using WebKit and V8 for for all new products. First they'll start with a product for smartphones (since as they say, many mobile-facing sites are only/best tested on WebKit anyway), and then Opera Desktop and other products will follow.

By my count, that leaves us with three major rendering engines (WebKit, Gecko, and Trident), and three major JavaScript engines (V8, SpiderMonkey, and JScript). Well, you could perhaps argue that there are two JScripts (the really broken one in IE8 and earlier, and the much better and completely rewritten one in IE9 and later), but let's not quibble.