Things in Jars

Simon Madine (thingsinjars)

@thingsinjarsFollow me on Twitter

Hi, I’m Simon Madine and I make digital toys and write guides on web development.

I'm a senior web dev on Nokia Maps in Berlin.

  • Twitter
  • Flickr
  • GitHub
  • Forrst
  • Shelvist
  • Last.FM
  • RSS
  • Umpteen ways to test for a function

    Written 9 Jan 2012

    Javascript,Geek

    After wrestling with another 140bytes challenge, I found myself wondering how many different ways you can test an object in JS to see if it’s a function. I wrote out a few of them then threw it out to my colleagues who came up with a few more. I’d love to hear from anyone who can suggest more to add to the list. Ideally, you want to find a test that will return true for all functions and only for functions. It’d be great if it’s a universal test that can be slightly modified to test for other types but that’s not essential.

    Bear in mind, most of these shouldn’t be used in the real world, this is just for fun.

    There are a couple of main categories and several variations within.

    Duck Typing

    When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.

    The Duck Test

    In other words, if an object has the methods of a function and the properties of a function, it’s probably a duck. No, that doesn’t sound right.

    This simply detects whether the object we’re testing contains the methods or properties we’d normally associate with a function. The most common test is checking whether a.call exists. In most cases, this will only be defined on a function and it will be defined on all functions. It is, therefore, a good test to use.

    The downside is that it can be fooled by setting a property of call on the object to be truthy. This will pass the test but still not be a function. Also, if the object is null or undefined, this will throw a TypeError (as pointed out by subzey on git).

    a.call                   // Hey, this has a call property. Quack?
    a.call && a.call.call    // The call also has a call so is probably also a function. Quack.
    a.apply                  // As before but with apply this time
    a.apply && a.apply.apply // ditto and ditto
    

    String comparisons on typeof

    This area of inspection is probably the richest for coming up with silly ideas to test. The typeof operator simply returns a string containing the type of the object. That’s it. Anything you can think of to compare a string against another string, be it RegEx, charAt, equals or threequals (===) can be manipulated to become a check for type.

    typeof a>'f'&&typeof a<'g'   // Long-winded and quite silly. Performs a numerical comparison on the strings
    (typeof a).charAt(0)=='f'    // Sturdy but not very useful.
    typeof a==typeof eval        // May as well use eval for something, it’s a global function
    typeof a==typeof dir         // Shorter but might not exist everywhere
    typeof a=='function'         // The usual way to test. Everything above here is purely academic
    /^f/.test(typeof a)          // Matching the string against a unique RegEx. See the table below
    typeof a==typeof b           // Requires access to another variable which is a known function
    (typeof a)[0]=='f'           // Small and robust but doesn’t work in IE6 or 7
    

    Table of RegEx Patterns to match object types:

    As little aside here, we’ve got a table of simple RegEx tests that do the same as the one mentioned above. They return true if the type is what you expect, false for all other types. They work by assuming things like ‘object’ being the only type to contain a ‘j’ or ‘boolean’ being the only one with an ‘a’.

    Type         RegEx                 Note
    boolean      /a/.test(typeof a)    // Shorter than typeof a==‘boolean’
    function     /^f/.test(typeof a)   // Shorter than typeof a==‘function’
    undefined    /d/.test(typeof a)    // Shorter than typeof a==‘undefined’
    number       /m/.test(typeof a)    // Same length as typeof a==‘number’
    object       /j/.test(typeof a)    // Same length as typeof a==‘object’
    string       /s/.test(typeof a)    // Same length as typeof a==‘string’
    null         /ll/.test(typeof a)   // Longer than typeof a==‘null’
    

    Pick & Mix

    This not only makes the assumption that an object is probably a function if it contains a ‘call’ but also that if that call has the same type as the object, they’re both probably functions.

    typeof a==typeof a.call      // A mixture of typeof string comparison and duck typing

    instanceof

    In some circumstances, instanceof is going to be better than typeof as it compares types rather than strings.

    a instanceof Function      // This will throw a ReferenceError if a is undefined.

    The [[Class]] of the object

    This comes from the JavaScript Garden where you’ll find they have a strong opinion on typeof and instanceof. This uses call to execute the toString method on the prototype of the basic Object constructor. Phew. At that point, you'd have a string ‘[Object Function]’. You can then chop off the beginning and the end using slice (treating the string as if it were an array) to get just the type. All together, it looks like this:

    Object.prototype.toString.call(a).slice(8, -1);

    Testing the string representation of the object

    This is fairly nasty but still quite effective. Convert the object itself to a string (not its type but the actual object) and see if that begins with ‘function’. This is nowhere nearly as robust as some of the other tests as this will also pass true for any strings that begin "function..." but it’s quite cunning. Credit goes to Max for this one.

    /^function/.test(a.toString())   //Test if the output of .toString() begins with ‘function’
    /^function/.test(a+"")           //As above but using a shortcut to coerce the function to a string.
    

    Running it

    This isn’t so much checking whether it looks and sounds like a duck, this is more like serving it à l’orange and seeing if it tastes like a duck. The idea here is to actually try and execute it. If it throws an error, it’s not executable, if it doesn’t, it is. Or something like that. Here, we’re testing that the error is an instanceof TypeError as an undefined object would also end up in the catch.

    The obvious downfall to this technique is that you don’t necessarily want the function executed when you’re testing it. In fact, you almost never want to do that. I might go as far as to say you never want that.

    try {
      a();
      true;
    } catch (e) {
      !(e instanceof TypeError);
    }
    

    The other big weakness in the above technique is that, even if the object is a function, the call itself might throw a TypeError. In Chrome, there's a bit more transparency as the error thrown has a type property. In that case you want to check that the type is 'called_non_callable' but that might still be a consequence of the function. In Safari, there's a similar property on the error (e.message) but the error object itself is no longer a TypeError, it is just an Error.

    More…

    I’m certain there are more. Many, many more. There are also several dozen that are trivial variations on those mentioned above – you could do the same string comparison tests on the [[Class]] property, for instance – but I missed these out. There’s probably a huge section missed out here (I'd forgotten instanceof existed until after the first draft of this post, for instance). If you can think of any more, let me know here or on The Twitter.

    I'll also reiterate my point from earlier: most of these are deliberately useless or inefficient. The point here isn't to find better ways to do things, it's to practice doing what you do every day. The more you play while being a web developer, the less you need to work.

    Comments

  • CSS Verification Testing

    Written 28 Dec 2011

    Opinion,Geek,CSS

    It's difficult to test CSS. In Nokia Maps, we use lots of different kinds of automated tests to ensure the build is doing what it's supposed to do – Jasmine for JS unit tests, jBehave for Java acceptance tests, a whole load of integration tests and systems to make sure all along the process that we know as soon a something goes wrong.

    CSS has typically been left out of this process – not just in our team but generally throughout the industry – because it's a difficult thing to test. CSS is a declarative language meaning that the CSS of a page doesn't describe how the page is to accomplish the task of turning text red, for example, it simply says 'the text should be red' and the implementation details are left up to the browser. This doesn't fit well into typical testing strategies as there is no sensible way to pass information in to check the outputs are as expected. With a declarative language, there is very little logic around which you can wrap a test. In essence, the bit you would normally test is the bit handled by the browser. About the closest CSS gets to having continuous-deployment style tests is to run your files against the in-house style guide using CSSLint.

    That's not to say people haven't tried testing CSS. There are lots of opinions on how or why it should be done but with no concrete answers. There has also been a lot of thinking and quite a lot of work done in the past to try and solve this requirement. This article from 2008 and this article from 2006 both propose a potential route to investigate for testing strategies.

    In summary, the two main approaches used are:

    • Generate images from the rendered HTML and compare differences (c.f. css-test by Gareth Rushgrove)
    • Specify expected values and compare actual values (cssUnit, CSSUnit)

    There must be something about the desire to test CSS and the name Simon as both Simon Perdrisat and Simon Kenyon Shepard created (separate) unit-testing frameworks called 'CSSUnit'. And there's me, obviously.

    As a related aside, there may also be something to do with working at Nokia and wanting to test CSS as Simon Shepard is the Tech Lead on Nokia Maps although I stumbled across his project completely randomly outside work. Weird.

    Another important related note: there's no point in developing a CSS testing framework for Test-Driven Development. Again, this is an aspect of being a declarative language but, by the time you've written your test, you've written your code. There's no Red-Green pattern here. It either does what you intended it to or it doesn't.

    In essence, the only way to test CSS is by verification testing – the kind of thing you do before and after refactoring your styles. This, essentially, involves working within your normal process until the job is done then creating 'snapshots' of the DOM and capturing the current cascaded styles. You can then refactor, rework and reorganise your CSS as much as you like and, as long as the combination of snapshot DOM plus CSS produces the same results as before, you can be confident that your entire system still appears the same way.

    Get to the point...

    Why the long ramble about CSS testing strategies? Well, unsurprisingly, I've had a go at it myself. My approach falls into the second category mentioned above – measure styles once finished and create secure test-beds of DOM structure which can have CSS applied to them. The test system is currently being run through its paces in Nokia Maps City Pages (my bit of maps) and, if it passes muster, I'll put it out into the big, wide world.

    Comments

  • Latest 140byt.es offerings

    Written 17 Dec 2011

    Javascript,Geek

    Long-term readers (a.k.a. my Mum) might remember my JS1K efforts last year and the subsequent discussion of Extreme JS Minification. The same kind of mindset that inspired qfox to create that competition also inspired Jed to create 140 Bytes. As with JS1K, the clue is in the name, you have the length of a tweet – 140 characters – to create something cool or clever in JS.

    I won't go into any more detail here, if you're interested, you've either already heard about it or would do better clicking around the 140bytes site or reading the comments on the master gist.

    My entries

    Following last week's draggable file script, I started messing about with making it small enough to qualify and, predictably, got hooked. Here are four I made last weekend.

    The scripts below are directly embedded from GitHub and are the minified, highly compressed versions. I recommend clicking through to the original gist for each of them where you'l find a file called annotated.js which talks through the code.

    Create a draggable file on-the-fly

    The code from last week shrunk down.

    Detect Doctype

    There's no simple way to access the current document's doctype as a string. There is already a document.doctype object so you might expect (or, at least I'd expect) you could do a .toString() or .asDoctypeString or something like that. Nope. Nothing. You have to manually recreate it as a concatenation of properties. A quick discussion with kirbysayshi and mmarcon came up with a few alternative methods (Max's is quite devious, actually) before eventually culminating in this.

    Chainify and Propertize

    This began as a very minimal implementation of Lea Verou's Chainvas. The idea is to enhance various constructors (Element, Node, etc.) so that each method returns the original object. This means that you can then chain (jQuery-style) any built-in function. Each constructor is also enhanced with a .prop function which allows property setting in a similarly chainable manner. For a better description, read through the Chainvas site.

    Comments

  • jQuery Detach Scrollbars Plugin

    Written 9 Dec 2011

    Geek,Javascript

    tl;dr: I made a plugin: jQueryDetach Scrollbars Plugin download [Zip – 1.4KB]

    A design I recently worked on called for a scrollbar which only took up half the height of the area it was scrolling. Now, I'm not going to get into a discussion about scroll behaviour, accepted standards or user expectations - fascinating though that would be - instead, Here's a jquery plugin.

    The existing jQuery plugins I found that dealt with scrollbars created their own custom, themable bars. jScrollpane, for instance, gives you complete control over pretty much every aspect of the look and feel of the scrollbar. I figured this was too much for my needs, all I wanted was to be able to anchor the scrollbar to a given corner and change its height. The resulting plugin does just that. It even handles OS X Lion's disappearing scrollbars natively, too.

    Usage

    Note: This currently only works on vertical scrolling and doesn't have a good jQuery setup and teardown. If I needed it more than once on a page, I'd have written it a bit more robustly so it could be used more than once. Maybe I'll leave that task as an exercise for the enthusiastic reader.

    If you call the plugin on an element with a scrollbar (i.e. the element has height and contains content that overflows), it will duplicate the scrollbar using the standard browser scrollbar and get rid of the original one. In fact, in its default configuration, there's pretty much no difference between using the plugin and not using it.

    $(element).detachScrollbar();

    It becomes more useful, however, when you pass in a couple of options. This example will move the scrollbar to the left of the content area:

    $(element).detachScrollbar({anchor : 'topleft'});

    You could leave the scrollbar on the right but shrink it downwards:

    $(element).detachScrollbar({anchor : 'bottomright', height : '50%'});

    The only behaviour of a standard scrollable area that isn't replicated by default is being able to use the mouse wheel to scroll while over the content area. If you want this behaviour (and you probably do), all you need to do is include the jQuery Mousewheel plugin in your page. This script will recognise if it's available and enable the functionality.

    How it works

    The script creates a container div around the original scrollable content and sets that to overflow:hidden while setting the original area to height:auto. This means that the original scrollbar disappears. It then creates another invisible div the same height as the original content and wraps that in a div with overflow-y:scroll, this creates a scrollbar that looks exactly like the original one. Add in some clever event trickery to tie the scroll position of one to the scroll position of the other and we're done. We've replicated the original functionality but can now control the styles applied to the scrollbar completely separately from the original content. This means we can position it to the left or above, maybe add a 90° CSS transform and have it look like a horizontal scrollbar, anything you like.

    The plugin also incorporates “Cowboy” Ben Alman's scrollbar width plugin to make sure we're matching dimensions on whatever platform this is used on.

    The options that can be passed in are:

    internal: true / false (default: true)
    autoposition: true / false (default: true)
    anchor: 'topleft' / 'topright' / 'bottomleft' / 'bottomright' (default: 'topright')
    height: Any CSS length (default '100%')

    Advanced usage

    The autoposition option allows you to decide whether to let the plugin handle the layout (which you probably do for most cases) or whether you want to specify everything yourself using the provided classes as styling hooks.

    The other option, internal, determines the DOM structure. Specifically, it says whether everything is contained within the one element or whether the scrollbar is separate. Specifying internal: false would allow you to put the scrollbar anywhere on your page. You could have all scrollbars set as position: fixed along the top of the page if you wanted. Not sure why you would but you could.

    Example and Download

    jQueryDetach Scrollbars Plugin

    jquery.detach-scrollbars.js

    Comments

  • older posts

Browse articles by category:

Toys, Guides, Opinion, Geek, Non-geek, Development, Design, CSS, JS, Open-source Ideas, Cartoons, Photos

Recent side-projects

  • Insta-Art
  • 8-Bit Alpha
  • Shelvi.st
  • The Elementals
  • Harmonious

Toys

Find my digital toys at thelab.thingsinjars.com.

Contact

Send me a message via Twitter.

Adopt-a-Museum

@thingsinjars:

    © 2012 Simon Madine