This document summarizes Jonathan Fine's presentation on JavaScript Miller Columns. The presentation covers what Miller Columns are, a demonstration of them, how to specify the user interface and author content, using delegation in frameworks, running tests, sample test data, defining classes in JavaScript, and ways to make JavaScript more Pythonic. The goal is to develop a production version of Miller Columns that relies on library modules and is supported by documentation.
1. JavaScript Miller Columns
Jonathan Fine, Open University, UK
EuroPython, 22 July 2010
Source for slides available at
http://bitbucket.org/jfine/javascript-miller-columns
/src/tip/docs/tex/js-miller-columns.tex
2. Overview of talk
What are Miller Columns
Demonstration
Specification
Delegation and frameworks
Testing
Sample code
Python and JavaScript compared
Documenting JavaScript
JavaScript modules (JSMOD)
JavaScript standard library
Pythonic JavaScript
4. What are Miller Columns
Named after Mark Miller of Google. Used in the iPhone and Apple
Finder interface. Click item in one column and next column shows
its children.
We rotate so that columns become rows.
Represents a tree as a sequence of choices:
Start at the root R.
List the children of the root.
Choose one of these children. Call it A.
List the children of A.
Choose one of the children of A. Call it B.
Stop when you get to a node without children.
6. User interface specification
In part it resembles a spreadsheet.
The display consists of a number of rows.
Each row has in it a preferred item.
There is a preferred row.
Up/down arrow keys moves the row preference up/down.
Horizontal movement is different
Left/right arrow keys moves item preference left/right.
Each non-leaf item has a child row.
Beneath each row is the preferred item’s child row.
(and so) Changing item preference changes display beneath
item’s row.
For each node in the tree we remember its preferred child.
7. Authoring and deployment specification
1. Author creates contents (cards) on repository site.
2. Author creates query that returns interesting set of cards.
3. Query returns data as JSON or JSONP.
4. Repository site creates HTML snippet that will display query
on page.
5. Author (or third-party) places HTML snippet on pages they
control.
6. A visitor to the pages now sees the repository content.
8. Delegation and frameworks
On all modern browsers, events bubble up. This allows events to
be handled by a parent or ancestor DOM element. Doing this is
called delegation.
In our setting, delegation is good. It makes code simpler, smaller,
more reliable and faster.
Becoming mainstream. Several JavaScript frameworks/libraries
now support delegation.
Delegation is a good candidate for being part of a JavaScript
standard library.
To simplify deployment, the HTML snippet should have few and
easily satisfied dependencies.
9. Running tests
I’ve written the app so that majority of the code can be tested
using a command line JavaScript interpreter. I can run all these
tests in less than one second. Probably could be reduced to 0.1
seconds.
My test runner is some inelegant bash scripts, such as:
function doit
{
js -f lib/boot.js -f lib/math.js -f lib/__builtin__.js
-f lib/methods.js -f lib/extras.js -f lib/js.js $*
}
doit -f hw/work.js
doit -f hw/_test/test_jsmod.js
doit -f hw/_test/test_js.js
doit -f hw/_test/test_class.js
# etc
10. Some test data
Much of the test involves ‘change of states and output’ testing.
Such tests can be specified with data and are Jasonic.
testit(
[’A’, [’B’, ’C’]],
[
[’down’, ’0’],
[’right’, ’1’],
[’down’, ’1,0’],
[’up’, ’1’],
[’down’, ’1,0’]
]
);
I’d like to create and manage these tests in Python. This would be
an example of Pythonic (and Jasonic) JavaScript.
11. Class definition: constructor and initialisation
We’re using modules (jsmod). In this extract m is the module
object to which we are attaching attributes, and mc is the parent
object for all instances of the MillerColumns class.
var mc = Class(m, ’MillerColumns’);
mc.__init__ = function(object){
this.object = object;
this.currs = [object];
this.path = [];
this.path_keys_map = {};
};
This code is similar to Python, and is good practice in JavaScript.
Class can assign mc.__name__ = ’MillerColumns’.
12. Class definition: down() method
This is what I wrote then. I’d do it a bit different now.
mc.$down = function(){
var curr = this.currs[this.path.length];
var keys = this.get_keys();
if (keys === null)
return null;
var index = keys.index;
if (index === null)
return null;
this.path.push(index);
this.currs.push(curr[keys[index]]);
return this.path;
};
13. About Python
Started by Guido van Rossum in 1990. Stable and mature.
Managed by Python Software Foundation.
Used by choice (of programmer). Scales to large systems.
Used in many areas — such as web servers, scientific
calculation, system administration, GUI programs, testing.
Open source, and all C-implementations use same codebase.
Very high-level, gives programmer productivity.
Friendly, wise and intelligent developer community.
Clean and simple (although unusual) syntax.
Moving to Python 3, to allow major language clean-up.
14. About JavaScript
Started by Brendan Eich in 1995. Key design from Scheme and
Self (giving inheritance). Name due to marketing tie-up with Sun.
Used because it’s all there is on the browser. Doesn’t scale.
Major use is web-browsers (and closely related areas, such as
Flash).
A major implementions (Microsoft) is proprietary.
Lightweight, inflexible programmer’s interface.
Microsoft’s hostility to Netscape (browser wars) still has
consequences.
Complex syntax, with serious gotchas.
Progress to fourth edition of standard abandoned in August
2008 and compromise made.
But don’t blame JavaScript for the problems with the DOM. Any
browser scripting language would have problems here.
15. Python — modules, library and documentation
These are important strengths of Python.
Python has a module structure. For example, file wibble.py
can be imported to provide the module wibble.
Modules can be organised into packages.
Modules can be byte-compiled.
Python has a large and growing standard library.
Python applications and frameworks rely on the standard
library.
There are other library modules available.
Python has high-quality documentation, in both HTML and
PDF form.
16. JavaScript — modules, library and documentation
There are major weaknesses in JavaScript.
JavaScript does not have an inbuilt concept of a module
(although package is a language reserved word).
JavaScript does not have a standard library of JavaScript code
(although there are widely used ‘modules’, e.g. for JSON).
In JavaScript ‘library’ often means ‘large package with some
optional parts’.
These libraries don’t share much code, and sometimes don’t
play well with each other. Sizzlejs is example of progress.
Documentation is sporadic and not to a shared standard.
Note: The serverjs project is working on providing modules for
JavaScript, and the author has a prototype Jsmod system.
17. JavaScript resources
Here’s an incomplete and perhaps biased list.
Wikipedia, for general introductions and overview.
Cockcroft’s JavaScript, the good parts and Zakas’ JavaScript
for web developers.
https://developer.mozilla.org/en/JavaScript.
Libraries such as jQuery and Dojo.
Many presentations on slideshare and videos.
http://dean.edwards.name/ (pushes the boundary).
http://ajaxian.com/ for developer news on Ajax.
JavaScript FAQ
For DOM, http://www.quirksmode.org/
The EuroPython 2010 JavaScript tutorial.
Js4py, a small group of Python users who also do JavaScript.
18. JavaScript remedies
We’ve seen that JavaScript has problems as a programming
environment. Here we look at some work done to improve matters.
Libraries such as Dojo and jQuery (but they still don’t have
modules).
Code to run on server, and treat browser as fairly dumb device
(Ruby-on-Rails, I think).
Google Web Toolkit — a whole browser-client development
environment (in Java) that compiles to browser Java and
client JavaScript.
Pyjamas, which is similar to GWT but for Python.
Running JavaScript on both browser and server (serverjs), to
avoid coding algorithm twice, in two different languages.
JSON (and XML), which work the same on all platforms.
Jsmod, which provided modules for JavaScript (currently
prototype only).
19. The empty module in Python and JavaScript
In Python the empty module is a zero-length file. In next version
of Jsmod it will be:
JSMOD(
{
’name’: ’empty’,
’imports’: []
},
function(m, __)
{
eval(__);
});
This approach allows completely independent import and use of
different versions of the same package. This feature can be a very
useful.
20. The empty JavaScript module
JSMOD( // Takes two arguments.
// 1. Module metadata.
{
’name’: ’empty’, // Name of module.
’imports’: [] // List of imports.
},
// 2. Module initialiser.
// Parameter m is module to be initialised.
// Parameter __ imports into closure namespace.
function(m, __)
{
eval(__);
// Use imports and initialise module here.
});
21. Exporting
As in Python, we export from a module by adding an attribute to
the module object we are initialising. In Python this is done
implicitly, by making a top-level assignment. In JavaScript we have
to be explicit.
JSMOD(
{
’name’: ’urls’, // Name of module.
’imports’: [] // List of imports.
},
function(m, __)
{
eval(__);
m.python = ’http://www.python.org’
});
22. Importing
Importing is done via eval(__), which injects the imports into the
private part of module namespace. (Good practice in JavaScript.)
Unlike Python, provide module attributes rather than module
object. This is also good practice in JavaScript. As in Python,
provide builtins (but not as attributes of JS global object).
JSMOD(
{
’name’: ’whatever’,
’imports’: [’urls’]
},
function(m, __)
{
eval(__);
alert(’Please visit ’ + urls_python);
});
23. Defining classes
JavaScript does not have inbuilt concept of class (even though
class is a reserved word). Also, it uses an object tree (aka
prototypes) for inheritance.
Here’s how to create Jsmod classes. We omit the module wrapper.
// *point* is the parent of all Point instances.
var point = m.Class(’Point’);
point.__init__ = function(x, y){
this.x = x;
this.y = y;
};
point.move = function(dx, dy){
this.x += dx;
this.y += dy;
};
24. Using classes
Much as you’d expect. Here’s a complete example.
JSMOD(
{
’name’: ’whatever’,
’imports’: [’geometry’]
}, function(m, __)
{
eval(__);
var Point = geometry_Point; // A useful shorthand.
var point = Point(1, 3);
point.move(1, 2);
// etc.
});
25. Pythonic JavaScript
Community is core to Python. Pythonic JavaScript not possible
without many Pythonistas contributing.
Sphinx format open source JavaScript documentation.
A good tutorial.
A module system for JavaScript.
A good start on a standard library for JavaScript.
High-quality JavaScript apps based on standard library.
26. How to give and get
Talk with me: jfine (at) pytex (dot) org
Stop by at or join Pythonic JavaScript sprint
Subscribe to js4py on Google groups
Use and improve this year’s JavaScript tutorial
Contribute sample JavaScript code
Help me develop Miller Columns
Start using Miller Columns
In summary, production version of Miller Columns, done right,
relying on library modules and supported by good JavaScript
tutorial and reference documentation.