Archive for the ‘javascript’ Category

Python Calling Javascript? A UI Pattern

Thursday, December 22nd, 2011

We have been very busy (excuse us for the lack of posts!) working on a second version of a client project. It involves redoing the whole UI in a much more responsive manner. In times past the “simple” way I have done this, especially with Django on the backend, has been to have the server respond with HTML, and inject that into the DOM. There are some serious limitations with this approach once you get far enough down the road. And it gets very messy.

We decided on a whole different approach to a responsive application. We are serving up data. The javascript takes care of the rest. Often times a single action requires multiple reactions by the interface. Yet, if you’ve abstracted your code (be pythonic, even in javascript: D.R.Y!) you can’t jump into a specific call/response, or even if you could, it’d be awful to throw a switch statement in there. The Command Pattern to the rescue!

To be fair, what we’ve implemented is a very simple execution of the pattern. Let’s take the python-end first:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class CommandBuilder(object):
 
    def __init__(self, *args, **kwargs):
        super(CommandBuilder, self).__init__(*args, **kwargs)
        self.data = []
 
    def raw_callback(self, callback, args):
        self.data.append({ 'callback': callback, 'args': args })
        return self
 
    @property
    def js(self):
        return self.JavascriptMethods(self)
 
    def dumps(self):
        return { 'commands': self.data }
 
    class JavascriptMethods(object):
 
        def __init__(self, command):
            self.command = command
 
        def a_function(self, a_model):
            return self.command.raw_callback('a_function', [ a_model.id, a_model.name ])

Just for some syntactic-sugar I also used the builder pattern and a python property which masks the Javascript Methods inner class. All that means you can write pretty code like this:

1
2
cmds = CommandBuilder.js.a_function(a_model).a_function(a_model).a_function(a_model)
return HTTPResponse(simplejson.dumps(cmds.dumps()))

In the real world you wouldn’t be calling the same javascript function over and over, you would expose the functions you need to call. And now we need a little bit of javascript to handle this known JSON data structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var Commander = {
    a_function: function(id, name) {
        alert(name+" has an id of: "+id);
    }
};
 
var Engine = {
    run_command: function(data) {
        if(data == undefined || data.command == undefined || data.command.length === 0) {
            alert('This is not a command structure');
        }
        for(var i in data.command) {
            var row = data.command[i];
            if(typeof Commander[row.callback] === 'function') {
                 Commander[row.callback].apply(undefined, row.args); // undefined as this
            } else {
                 alert('Function '+row.callback+' does not exist on Commander');
            }
        }
    }
};

The javascript `apply` method is a lifesaver here. With this simple pattern we can have the server force client-side code to be executed. Now, if you’ve been a diligent developer you’ve already been naming your functions on the client-side, not just throwing around a million anonymous functions. And you’ve separated out the functions that deal with calling URLs or dealing with the DOM from those functions which deal with the data. There is a huge bonus with doing that (besides this pattern being useful for you): you can start testing your javascript!

Reflections:

  • I tend to think of the `.js` in python a namespace. You can specify a specific Javascript object on the front end with a few minor changes on both ends. My `CommandBuilder` object has a few more methods on it, so the `.js` serves as a semantic separator as well.
  • There is only one downside to this pattern that I have observed so far – if you make changes to function signatures in javascript, you’ll need to change the python side as well. You need to stay on your toes with this pattern.

Google IO 2011

Sunday, May 8th, 2011

This week Active Frequency is taking a field trip to San Francisco for Google I/O 2011!

We’re psyched to immerse ourselves in all things Google for a few days; here are a couple of highlights we’re especially looking forward to:

John

  • Learning about ActivityFragments available in Honeycomb. These seem like an incredibly powerful way to use and organize your mobile applications. To use a web concept – this has the potential to be the native “responsive design” to tablet/phone displays.
  • I am eager to see just how far Android can leverage NFC today. This isn’t something I’ve read very much about. The hardware/software rollout plan can be very much a chicken and egg problem, so I look forward to seeing Google’s plan.
  • And last, but not least, they have a specifically UI building focused talk, which excites me. The app I’ve been working on is mostly functional – but obviously ugly. I hope I get some ideas and inspiration here.

Kevin

  • “JavaScript Programming in the Large with Closure Tools” – JavaScript, a language with many critics but one of my personal favorites, has really come into its own of late. As we write bigger and bigger JavaScript apps, though, we run into more and more problems associated with non-trivial systems – and tools like Closure help make JavaScript more of a “real” language than the “scripting” language it started out as.
  • “Writing Web Apps in Go” – I’ll be honest: I’m a bit skeptical about Go’s suitability for web apps. But how can you not be curious about a language designed by such an all-star cast?
  • “Map your business, inside and out” and “Location Based App development using Google APIs” – these two talks represent just some of the cool things going on with geolocation.

We’ll be hanging around at I/O – if you’re there too, find us: @activefrequency, @kgrinberg, @jobelenus

jQuery Plugins: Column View, Part 2

Wednesday, February 2nd, 2011

So in the first part we talked generically about some design decisions surrounding making jQuery plugins. Now, I want to focus specifically on my Column View jQuery plugin and some of the design decisions I needed to make when writing it.

I really knew I only had one requirement beyond reproducing the metaphor from OS X’s Finder. I knew it had to be dynamic. I couldn’t just ask whoever wants to use this to display all of their column data onto the page and link them all together. It would create a nightmare to maintain or even develop in certain situations. So, that meant I needed to create DOM elements.

But, I knew the user needed to be in control of the DOM. They need to style, place, and size the entire column view widget. Some plugins (e.g. Fancybox, which is fantastic) take the other route by doing all the DOM work for you. All you do is provide the content. For that kind of plugin the design decision is perfect – it is a lightbox, it needs to a do a lot of DOM work and styling to accomplish the task.

So I decided to only manipulate the DOM once during the setup of the plugin; I take the contents of the node and place that in the first column:

1
div.html(columnview.contents().detach()).appendTo(columnview); //replace contents into new column

This way any developer can style the node they designate as the column view widget and I leave that entirely alone. They can be sure that their work remains intact and functional.

To keep the metaphor going and keep the widget dynamic, I also needed to add a way to reload a specific column. When you make a new file or folder in the OS X Finder you can see it right away in the column. To accomplish this, I needed to store the loaded url of each column. As I described last time, the best way to store data is with jQuery’s `data` method, so whenever a column’s contents are updated I place the called url onto it’s DOM node with a `data` call.

I am sure there are lots of different ways to accomplish this task. By defining my one operating principle (being dynamic) all my execution questions could easily be answered. Overall I got a very minimalist approach that would not get in a developer’s way. Some might label this as “unpolished”. But I disagree. Write as little code as you need to the job done, right? I’d like to hear if you agree or disagree? Or perhaps, what else you think this widget needs to do, or could do?

JQuery Plugins: Column View, Part 1

Wednesday, January 19th, 2011

I recently had the task of replicating the OS X Finder’s Column View for a web application we are writing. The app itself is not quite done – but the columnview plugin is already out for public use.

I am one of those few developers who really like working with JavaScript. Because of my affinity I have gotten a lot of JavaScript projects over the years. As far as I am concerned, jQuery is the bee’s knees for working in JavaScript – it captures the natural feel of the language while exploiting its features (e.g. lexical scoping). So for a long time I just worked on these projects writing the necessary code to “get ‘er done”… creating a sloppy mess. These days I am concerned about the architectural issues – and I am not the only one. Questions around jQuery plugins are some of the more common I see on developer community sites like StackOverflow. With these questions circling I wanted to explore the topic in two parts.

First, I want to talk about creating jQuery plugins in general. Second, in the next post I want to talk specifically about this plugin and some of the design choices I made along the way.

What I am writing about here comes from some experiences and, more importantly, the jQuery Authoring Plugins Page. I am going to assume you understand and agree that cluttering the global namespace is considered “Bad Form” and will get you snide looks at parties. You also understand singletons and closures. There are wonderful resources only a-google-away if you don’t, but I won’t be providing them here. With that out of the way, this is the generic jQuery-approved boilerplate for creating a new plugin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(function ( $ ) {
    var methods = {
    ...
    };
 
    $.fn.columnview = function(method) {
        methods.columnview = this;
 
        if ( methods[method] ) {
            return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.columnview' );
        } 
 
        return this;
    };
})( jQuery );

The jQuery folks ask that a single plugin does not create more than one entry into the jQuery namespace (if you peek at their authoring page you’ll see the “Not Like This” example). So you stick all of your plugin’s methods into the methods singleton. You place both the singleton and the actual assignment to the jQuery object within an anonymous function and call it immediately. This prevents any of your code from leaking out into the global namespace. You’ll notice the code inserted as your plugin into jQuery is only 11 lines long. All your operations should occur in your methods.

So what do these 11 lines do? Three things. First, whichever jQuery object you called the plugin from is set in the singleton, making it available to all your methods. The method’s `this` context will not be the jQuery object you called from the outside so you absolutely need this reference. Second, when you start up your plugin, like so:

1
2
3
$('#columnview').columnview();
// or like this
$('#columnview').columnview({my:'options', go:'here'});

…it runs the init function (you’re going to have to define one) with the singleton you (optionally) pass in (line 12 in the code snippet). Third, you can call a specific function on the plugin, like so:

1
$('#columnview').columnview("refresh_column", 1);

That would call `methods.refresh_column` with the argument of `1` (line 10 in the code snippet). If you have ever used the jQuery Dialog plugin you have done this with the `close()` method.

There is one more question (really more like a wall) that people run into. It happens with more advanced JavaScript use, the nature of the language itself, and the event driven model we use on the web. Data?! Where do we put it?! Normally we’ve got classes with variables or a database to hold all our stuff. Now we’ve got a singleton and we could put stuff in there. But the singleton belongs to everyone and it can get messy sticking things into arrays (which end up resembling a struct from C). Developers coming from more “normal” programming ecosystems don’t consider the DOM as a place to store things. The DOM in JavaScript can, and should, be thought of as your data-store. jQuery has a handy function to do this storage for you: `data()`.

Data takes a key and a value and sticks it onto a DOM node. It does not put it on the jQuery object (which easily gets GC’d, lost, found, buried in soft peat moss, and subjected to public inquiry [bonus points if you get the reference]) but on the DOM node itself. So you can always be sure to have the up-to-date value and get it from anywhere without any concern. Using `data()` saves lives and makes your brain hurt less.

Next time: we’ll delve into the columnview plugin specifically.

EDIT: Part 2 is up!