OSX Screensaver emulation with Canvas: That’s Bean
December 6, 2009 by Ed Spencer · 1 Comment
OS X has a pretty little screensaver which takes a bunch of images and ‘drops’ them, spinning, onto the screen. Think of it like scattering photographs onto a table, one at a time.
Naturally, there’s a desperate need for a JavaScript/Canvas port of this functionality, resulting in the following:
I had to limit the video capture framerate a bit so the video makes it look less smooth than it actually is. Check it out running in your own browser here.
For obvious reasons I have called the code behind this Bean, and it’s all available up on Github.
For the curious, here’s a little explanation about how it works. Bean starts off with a blank canvas and a list of image urls, which it preloads before getting started. It then drops one image at a time, rotating it as it goes. Each falling image is called a Plunger, because it plunges.
Each Plunger gets a random position and rotation to end up in, and takes care of drawing itself to the canvas on each frame by calculating its current size and rotation as it falls away from you.
Drawing each Plunger image on every frame quickly starts to kill the CPU, so we take a frame snapshot every time a Plunger has finished its descent. This just entails drawing the completed Plunges first and then using Canvas’ getImageData API to grab the pixel data for the image.
This gives us a snapshot of all of the fallen Plungers, meaning we can just draw a single background image and the currently falling Plunger on each frame. This approach ensures the performance remains constant, as we are only ever drawing a maximum of 2 images per frame. Each time a Plunger finishes its descent a new snapshot is taken.
Bean attempts to draw a new frame roughly 25 times per second and modern browsers seem to handle this pretty well. Safari pulls around 60% of one core on my MacBook Pro, with Firefox somewhat less performant. Needless to say, I didn’t even bother trying to make this work with IE.
Here’s the code to set the Bean in motion. This is using a few bundled APOD images:
var bean = new Bean({
imageUrls: [
'images/DoubleCluster_cs_fleming.jpg',
'images/NGC660Hagar0_c900.jpg',
'images/filaments_iac.jpg',
'images/m78wide_tvdavis900.jpg',
'images/sunearthpanel_sts129.jpg',
'images/NGC253_SSRO_900.jpg',
'images/Ophcloud_spitzer_c800.jpg'
],
canvasId : 'main',
fillBody : true
});
bean.onReady(function(bean) {
bean.start();
});
Ext.ux.Exporter – export any Grid to Excel or CSV
November 24, 2009 by Ed Spencer · 15 Comments
Sometimes we want to print things, like grids or trees. The Ext JS printing plugin is pretty good for that. But what if we want to export them instead? Enter Ext.ux.Exporter.
Ext.ux.Exporter allows any store-based component (such as grids) to be exported, locally, to Excel or any other format. It does not require any server side programming – the export document is generated on the fly, entirely in JavaScript.
The extension serves as a base for exporting any kind of data, but comes bundled with a .xls export formatter suitable for exporting any Grid straight to Excel. Here’s how to do that:
var grid = new Ext.grid.GridPanel({
store: someStore,
tbar : [
{
xtype: 'exportbutton',
store: someStore
}
],
//your normal grid config goes here
});
Clicking the Download button in the top toolbar iterates over the data in the store and creates an Excel file locally, before Base64 encoding it and redirecting the browser via a data url. If you have Excel or a similar program installed your browser should ask you to save the file or open it with Excel.
I put together a quick example of the plugin in action inside the repository, just clone or download the code and drag the examples/index.html file into your browser to run it.
The Exporter will work with any store or store-based component. It also allows export to any format – for example CSV or PDF. Although the Excel Formatter is probably the most useful, implementing a CSV or other Formatter should be trivial – check out the Excel Formatter example in the ExcelFormatter directory.
Jaml: beautiful HTML generation for JavaScript
November 4, 2009 by Ed Spencer · 27 Comments
Generating HTML with JavaScript has always been ugly. Hella ugly. It usually involves writing streams of hard-to-maintain code which just concatenates a bunch of strings together and spits them out in an ugly mess.
Wouldn’t it be awesome if we could do something pretty like this:
div(
h1("Some title"),
p("Some exciting paragraph text"),
br(),
ul(
li("First item"),
li("Second item"),
li("Third item")
)
);
And have it output something beautiful like this:
<div>
<h1>Some title</h1>
<p>Some exciting paragraph text</p>
<br />
<ul>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</ul>
</div>
With Jaml, we can do exactly that. Jaml is a simple library inspired by the excellent Haml library for Ruby. It works by first defining a template using an intuitive set of tag functions, and then rendering it to appear as pretty HTML. Here’s an example of how we’d do that with the template above:
Jaml.register('simple', function() {
div(
h1("Some title"),
p("Some exciting paragraph text"),
br(),
ul(
li("First item"),
li("Second item"),
li("Third item")
)
);
});
Jaml.render('simple');
All we need to do is call Jaml.register with a template name and the template source. Jaml then stores this for later use, allowing us to render it later using Jaml.render(). Rendering with Jaml gives us the nicely formatted, indented HTML displayed above.
So we’ve got a nice way of specifying reusable templates and then rendering them prettily, but we can do more. Usually we want to inject some data into our template before rendering it – like this:
Jaml.register('product', function(product) {
div({cls: 'product'},
h1(product.title),
p(product.description),
img({src: product.thumbUrl}),
a({href: product.imageUrl}, 'View larger image'),
form(
label({'for': 'quantity'}, "Quantity"),
input({type: 'text', name: 'quantity', id: 'quantity', value: 1}),
input({type: 'submit', value: 'Add to Cart'})
)
);
});
In this example our template takes an argument, which we’ve called product. We could have called this anything, but in this case the template is for a product in an ecommerce store so product makes sense. Inside our template we have access to the product variable, and can output data from it.
Let’s render it with a Product from our database:
//this is the product we will be rendering
var bsg = {
title : 'Battlestar Galactica DVDs',
thumbUrl : 'thumbnail.png',
imageUrl : 'image.png',
description: 'Best. Show. Evar.'
};
Jaml.render('product', bsg);
The output from rendering this template with the product looks like this:
<div class="product">
<h1>Battlestar Galactica DVDs</h1>
<p>Best. Show. Evar.</p>
<img src="thumbnail.png" />
<a href="image.png">View larger image</a>
<form>
<label for="quantity">Quantity</label>
<input type="text" name="quantity" id="quantity" value="1"></input>
<input type="submit" value="Add to Cart"></input>
</form>
</div>
Cool – we’ve got an object oriented declaration of an HTML template which is cleanly separated from our data. How about we define another template, this time for a category which will contain our products:
Jaml.register('category', function(category) {
div({cls: 'category'},
h1(category.name),
p(category.products.length + " products in this category:"),
div({cls: 'products'},
Jaml.render('product', category.products)
)
);
});
Our category template references our product template, achieving something rather like a partial in Ruby on Rails. This obviously allows us to keep our templates DRY and to easily render a hypothetical Category page like this:
//here's a second product
var snowWhite = {
title : 'Snow White',
description: 'not so great actually',
thumbUrl : 'thumbnail.png',
imageUrl : 'image.png'
};
//and a category
var category = {
name : 'Doovde',
products: [bsg, snowWhite]
}
Jaml.render('category', category);
All we’ve done is render the ‘category’ template with our ‘Doovde’ category, which contains an array of products. These were passed into the ‘product’ template to produce the following output:
<div class="category">
<h1>Doovde</h1>
<p>2 products in this category:</p>
<div class="products"><div class="product">
<h1>Battlestar Galactica DVDs</h1>
<p>Best. Show. Evar.</p>
<img src="thumbnail.png" />
<a href="image.png">View larger image</a>
<form>
<label for="quantity">Quantity</label>
<input type="text" name="quantity" id="quantity" value="1"></input>
<input type="submit" value="Add to Cart"></input>
</form>
</div>
<div class="product">
<h1>Snow White</h1>
<p>not so great actually</p>
<img src="thumbnail.png" />
<a href="image.png">View larger image</a>
<form>
<label for="quantity">Quantity</label>
<input type="text" name="quantity" id="quantity" value="1"></input>
<input type="submit" value="Add to Cart"></input>
</form>
</div>
</div>
</div>
You can see live examples of all of the above at http://edspencer.github.com/jaml.
Jaml currently sports a few hacks and is not particularly efficient. It is presented as a proof of concept, though all the output above is true output from the library. As always, all of the code is up on Github, and contributions are welcome
Jaml would be suitable for emulating a Rails-style directory structure inside a server side JavaScript framework – each Jaml template could occupy its own file, with the template name coming from the file name. This is roughly how Rails and other MVC frameworks work currently, and it eliminates the need for the Jaml.register lines. Alternatively, the templates could still be stored server side and simply pulled down and evaluated for client side rendering.
Happy rendering!
Making RowEditor use your column renderers
October 29, 2009 by Ed Spencer · 1 Comment
The RowEditor plugin is one of my favourite Ext JS components. It basically allows any row on a grid to be turned into an adhoc form on the fly, saving you the effort of defining additional form components.
Recently I had a grid which had a few fields that don’t have an editor, something like this:
var myGrid = new Ext.grid.GridPanel({
plugins: [new Ext.ux.grid.RowEditor()],
columns: [
{
header : "Username",
dataIndex: 'username',
editor : new Ext.form.TextField()
},
{
header : "Signup date",
dataIndex: 'created_at',
renderer : Ext.util.Format.dateRenderer('m/d/Y')
}
]
});
Simple stuff – we just show a username and a signup date, which is altered by a renderer. When we double-click a row it turns into an editable row, and we get a textfield allowing us to edit the username. Unfortunately, while in edit mode our date renderer is ignored, and the raw value displayed instead.
Thankfully, we can fix this by altering RowEditor’s source code. The method we need to change is startEditing, which sadly suffers from long method syndrome. About halfway into that method there’s a for loop, which we’re going to alter to look like this:
for (var i = 0, len = cm.getColumnCount(); i < len; i++){
val = this.preEditValue(record, cm.getDataIndex(i));
f = fields[i];
//our changes start here
var column = cm.getColumnById(cm.getColumnId(i));
val = column.renderer.call(column, val, {}, record);
//our changes end here
f.setValue(val);
this.values[f.id] = Ext.isEmpty(val) ? '' : val;
}
We didn’t really have to do much, just grab the renderer for the column and pass it the default value and the record which was found earlier in the method.
For the curious, the empty object we pass in as the second argument to the renderer is what would usually be the ‘meta’ object (see the renderer documentation on the Column class). Under the covers, RowEditor actually creates an Ext.form.DisplayField instance for each column that you don’t specify an editor for. This is why we use f.setValue(val); above. DisplayField doesn’t have the same meta stuff as a normal cell would, so if you’re looking to customise CSS via the metadata you’ll have to do something like this instead:
columns: [
{
...
editor: new Ext.form.DisplayField({
cls: 'myCustomCSSClass',
style: 'border: 10px solid red;'
})
}
]
Pretty easy. It’s a shame we have to overwrite the source code as this makes the solution less future proof, but if you look at RowEditor’s source code you’ll see why a 45 line override would be equally unpleasant.
git: what to do if you commit to no branch
October 28, 2009 by Ed Spencer · 1 Comment
Using git, you’ll sometimes find that you’re not on any branch. This usually happens when you’re using a submodule inside another project. Sometimes you’ll make some changes to this submodule, commit them and then try to push them up to a remote repository:
ed$ git commit -m "My excellent commit" [detached HEAD d2bdb98] My excellent commit 3 files changed, 3 insertions(+), 3 deletions(-) ed$ git push origin master Everything up-to-date
Er, what? Everything is not up to date – I just made changes! The clue is in the first part of the commit response – [detached HEAD d2bdb98]. This just means that we’ve made a commit without actually being on any branch.
Luckily, this is easy to solve – all we need to do is checkout the branch we should have been on and merge in that commit SHA:
ed$ git checkout master Previous HEAD position was d2bdb98... My excellent commit Switched to branch 'master' ed$ git merge d2bdb98 Updating 88f218b..d2bdb98 Fast forward ext-mvc-all-min.js | 2 +- ext-mvc-all.js | 2 +- view/FormWindow.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
Once we got onto the master branch, we just called git merge with the SHA reference for the commit we just made (d2bd98), which applied our commit to the master branch. The output tells us that the commit was applied, and now we can push up to our remote repository as normal:
ed$ git push origin master Counting objects: 11, done. Delta compression using up to 2 threads. Compressing objects: 100% (6/6), done. Writing objects: 100% (6/6), 692 bytes, done. Total 6 (delta 4), reused 0 (delta 0) To git@github.com:extmvc/extmvc.git 88f218b..d2bdb98 master -> master
This had me puzzled for a while so hopefully it’ll save someone banging their head against a nearby wall.