Skip to content

Open Source

Community Highlights: Adventures in localizing a Cappuccino Application

Cappuccino Blog - Thu, 07/29/2010 - 06:06

Community Highlights: Using Cappuccino to build the MemoryMiner Web Viewer

Back with a second post is John Fox, creator of MemoryMiner, a digital storytelling application for Mac OS X. John writes about the steps he took to localize his Cappuccino application, a web viewer for MemoryMiner.

The post comes complete with sample code, and its worth a read if you’re interested in localizing your own applications.

Categories: Open Source

Firefox 4 Beta 2 now available for download

Mozilla Developer News - Tue, 07/27/2010 - 22:37

The Mozilla community is proud to announce that Firefox 4 Beta 2 is now available for download on Mac, Windows or Linux.

Firefox 4 Beta 2 includes several major features and improvements – by testing them early we’ll be able to respond to your feedback for future versions of Firefox. The included Feedback Add-On that helps you let us know what you think about the new features and technologies in the beta. You can read more about this release on the Mozilla Blog, or at any of the following links:

We want to thank the Mozilla community of nightly testers for the amazing feedback that helped shaped Firefox 4 Beta 2. We appreciate your assistance in testing this preview of the next version of Firefox!

Categories: Open Source

How FuncUnit works

JavaScriptMVC - Tue, 07/27/2010 - 08:25

FuncUnit is a mashup of a bunch of awesome JavaScript projects.  It can be useful knowing how they all work together to make FuncUnit tick. This article details the components and how they fit together.  This is a primer for anyone wanting to contribute to FuncUnit.

FuncUnit is is comprised of the following parts:

  • Selenium - Provides browser automation
  • QUnit - A browser-based testing an assertion API.  
  • jQuery - Used for CSS selector and DOM utilities.  
  • EnvJS - A simulated browser environment.
  • Syn - A synthetic event library.

FuncUnit supports 2 modes: Browser and Selenium mode.

Browser Mode

Browser mode is when you open up your browser to a funcunit html page. This page includes the funcunit script which has inside it QUnit, jQuery, Syn and the FuncUnit API.

When you use FuncUnit (or S), it basically sends those commands to a popup window.  This is pretty straightforward.

Selenium Mode

Selenium mode is used when you use envjs to open the funcunit html page.  Here, EnvJS reads the html page and then loads and runs any script tags it finds (just like a normal browser).  But instead of sending commands to a popup window, funcunit.js starts selenium, serializes those commands, and send them to a custom Selenium server build.  The selenium server has jQuery and Syn and will run the commands the same way browser mode ran the commands.  Selenium server will return the results to FuncUnit which reports them to the console.

The Secret

Now that you know the secret to FuncUnit's awesomeness - how you are able to write a test with just a browser and funcunit.js, but automatically run it - please help us make this project even better. Here are some things we want to work on:

  • An in-browser Selenium like IDE.
  • Cucumber-like API.
  • Plugins for testing Flash / Silverlight integration.
Categories: Open Source

FuncUnit - Fun Web Application Testing

JavaScriptMVC - Tue, 07/27/2010 - 08:25

Last week we released Syn and mentioned how all testing solutions suffer from some fatal flaw. Today, we are releasing a beta of FuncUnit, which has "solved" JavaScript web application testing.

Features
  • Functional Testing - Test complex behavior like drag-drop.
  • High Fidelity - Create identical events that a mouse and keyboard create. Run tests in a real browser.
  • Automated - Test multiple browsers from the command line.
  • Easy to Write - Write, run, and debug tests in the browser, without configuring a server or other tool. Write tests in a familiar jQuery-style API.
  • Free - It's open source! Save yourself $5,000 for similar solutions.
  • Multi-system - Runs in IE 6+, FF 2+, Safari 4+, Opera 9+, Chrome, on PC, Mac, and Linux.
Download

Download FuncUnit Beta 4

What

FuncUnit is a web application testing framework that combines Selenium, jQuery, QUnit, and Envjs. It focuses on making testing as easy and fun as possible.

Writing tests is a chore and won't be done unless it's stupidly easy. Plus, tests won't get run unless they can be run automatically.

The problem with other automated testing solutions is that everyone has to install and configure cumbersome external software to even begin writing tests. After setting up the software, you write the tests with some obtuse API in a language other than JavaScript. But the worst part is debugging these tests across the software-browser bridge. The tests are almost impossible to debug!

We fixed this.

Write, Run, and Debug with the Browser

FuncUnit lets you write tests by just creating an html file that includes funcunit.js.

Simply open the html page in your browser and it runs your tests. If you made a mistake, or your app breaks, use your favorite debugger (Firebug) to catch the problem. It's easy.

Automate Your Tests

When you've setup your testing server with the browsers you want to support, running the same tests is as simple as opening the test page with envjs:

envjs http://test.myco.com/tests/filemanager.html

We typically set this up to run as a nightly build.

API

FuncUnit's API is super sweet. If you know QUnit and jQuery, it will be second nature. The following tests the handy autosuggest from phpguru. See it in action here. (Turn off your popup blocker!)

module("autosuggest",{
  setup : function(){
    S.open('autosuggest.html')
  }
});

test("JavaScript results",function(){
  S('input').click().type("JavaScript")

  // wait until we have some results
  S('.autocomplete_item').visible(function(){
    equal( S('.autocomplete_item').size(), 
           5, 
           "there are 5 results")
  })
});
Demos

Make sure you have your popup blocker off!

Documentation

JavaScriptMVC's FuncUnit docs.

Use

Setting up FuncUnit is almost exactly like setting up QUnit. After downloading FuncUnit into a public folder on your server (or a local file on your hard drive):

  1. Create an empty test script (ex: mytest.js).
  2. Create a qunit like page (ex: mytest.html) that will load your test and display your results. Use this as a template (It's also in the download).
  3. Have that page include funcunit.js, qunit.css, and your test script (mytest.js)

Open mytest.html, you should see something like:

Functemplate

*** you probably want to change the name of these files ***

Writing Tests

All interaction with the tested page is done through the FuncUnit object. This is aliased as S. S is to FuncUnit as $ is to jQuery.

Typically a test is broken down in 5 parts:

  • Opening a page
  • Performing user actions (like clicking and typing).
  • Waiting for the page to complete its response (animations and Ajax)
  • Getting properties of the page (like the text of an element)
  • Asserting the properties are correct (like the text == "Hello World")

Testing a dynamic webpage is largely asynchronous. To avoid LOTS of nested callback functions, most FuncUnit commands are queued. But  these commands take a callback function that runs after the command completes, but before the next command runs.

For example, the following performs 3 drags that each take a second.  But, between the second and third drag, it checks the #start element's text.

S("#start")
   .drag({ to:"#first", duration: 1000 })
   .drag({ to:"#second", duration: 1000 },
         function(){
            equals(S("#start").text(),"2 drops")
         })
   .drag({ to:"#third", duration: 1000 })
Opening a page

To open a page is simple. Write:

S.open("path/to/mypage.html")

The path to the page should be relative to the FuncUnit test page (mytest.html). Typically an open should be done in a module's setup function.

Actions

Actions are used to simulate user behavior such as clicking, typing, moving the mouse. FuncUnit provides the following actions:

  • click - clicks an element (mousedown, mouseup, click).
  • dblclick - two clicks followed by a dblclick.
  • rightClick - a right mousedown, mouseup, and contextmenu.
  • type - Types characters into an element.
  • move - mousemove, mouseover, and mouseouts from one element to another.
  • drag - a drag motion from one element to another.
  • scroll - scrolls an element.

The following might simulate typing and resizing a "resizable" textarea plugin:

S('textarea').click().type( "Hello World" );
  
S('.resizer').drag( "+20 +20" );
Waits

Waits are used to wait for a specific condition to be met before continuing to command. Waits look like most jQuery setter methods. For example, the following waits until the width of an element is 200 pixels and tests its offset.

var sm = S("#sliderMenu");
sm.width( 200, function(){

  var offset = sm.offset();
  equals( offset.left, 200)
  equals( offset.top, 200)
})

You can also provide a test function that when true, continues to the next action or wait command. The following is equivalent to the previous example:

var sm = S("#sliderMenu");

sm.width(
  function( width ) {
    return width == 200;
  }, 
  function(){
    var offset = sm.offset();
    equals( offset.left, 200)
    equals( offset.top, 200)
  }
)
Getters

Getters are used to test the conditions of the page. Most getter commands also correspond to a jQuery method of the same name.

The following checks that a textarea, which can only be resized vertically, is 20 pixels taller after a drag, but the same width:

var txtarea = S('textarea'),
	
    // save references to width and height
    startingWidth = txtarea.width(), 
    startingHeight = txtarea.height();

S('.resizer').drag("+20 +20", function(){
  equals(txtarea.width(), 
         startingWidth, 
         "width stays the same");
         
  equals(txtarea.height(), 
         startingHeight+20, 
         "height got bigger");
});
Assertions

FuncUnit uses qUnit for assertions so you can use:

  • ok - ok(state, message)
  • equals - equals(actual, expected, message)
  • same - same(actual, expected, message)
Running Tests

Running tests in the browser is easy - just open the FuncUnit page. But running tests via the command line is equally as easy. Simply open your test page with envjs:

envjs http://localhost/tests/grid.html

Or if you are using Mac/Linux:

./envjs http://localhost/tests/grid.html
Setting Up Your Test Server

We'll be putting this up in JavaScriptMVC's FuncUnit docs.

Conclusion

We believe FuncUnit finally makes testing JavaScript approachable. We hope you can use to to write better, more robust applications that move web development along faster than ever. If you have questions or comments please post on FuncUnit's Google Group.

Thanks!

FuncUnit is a mashup of some of the best open source tools available:

  • Selenium - Browser automation
  • QUnit - Testing API
  • jQuery - CSS selector and DOM utilities (your app does not need jQuery)
  • EnvJS - Simulated browser environment
  • Syn - A synthetic event library
Important Links
Categories: Open Source

Syn - a Standalone Synthetic Event Library.

JavaScriptMVC - Tue, 07/27/2010 - 08:25

Syn is used to simulate user actions such as typing, clicking, dragging the mouse.  It creates synthetic events and performs default event behavior.

Features
  • Enables complex JavaScript functional testing.
  • Standalone (does not need jQuery).
  • Cross Browser (IE6+, FF1.5+, Opera 9.6+, Safari 4+, Chrome 4+) and multi-platform (Win, Safari, Linux).
  • 99.9% browser sniffing free (only 1 sniff to prevent crashing Safari).
Download

syn.js (59KB. Size doesn't matter. Users don't download this)

Demo

Synthetic Recorder Demo. If you find a bug, it's the recorder and not syn.js's fault. But please let us know! Eventually, we will turn the recorder into something like the Selenium IDE.

Documentation

JavaScriptMVC's Syn documentation.

Why

Testing rich, dynamic web applications sucks. At Jupiter, we've tried almost every testing solution available (qUnit, Quick Test Pro, Selenium, JsUnit, Env.js, TestCase) and all of them suffer from some fatal flaw.  

Problems:

  • Manual - A tester has to run the tests manually on every supported browser.  People are lazy. 
  • Unit Tests Only - We need to test the app as a whole and complex UI behavior like drag-drop.
  • Low fidelity - We need to make sure the tests are reporting accurate results.
  • Difficult to write - We sling JS like a ninja monkey throws poo.  We want to write tests in a nice JS API.
  • Expensive - A QTP license is 5k a person!  I'd rather buy a vacation.
  • Support - We want to test Mac and Linux browsers.

We've solved all of these problems in our upcoming FuncUnit testing framework. It's a mashup of qUnit, Selenium, Rhino, and Env.js. But its core library, Syn, which does the work of simulating user actions with very high fidelity, is what we are releasing today.

Use

Using Syn feels good and should be done with a clean conscience, as it may lead to feelings of guilty pleasure. There's only several things a user does and these correspond nicely to the Syn API:

  • click - a mousedown and mouseup on the same element.
  • dblclick - two clicks in rapid succession.
  • type - typing a sequence of characters.
  • key - typing a single character
  • move - moving the mouse.
  • drag - a mousedown followed by a move and a mouseup.

These user interactions are called actions. The following is an example of clicking an element with id='hello', typing "Hello World", and then dragging your mouse from that element to an element with id='trash'.

Syn.click( {},'hello' )
   .type( 'Hello World' )
   .drag( $('#trash') ); 

* jQuery is used to get the trash element for brevity. It is not required.

You'll notice that Syn is chainable. You want to use chaining because actions don't complete immediately (thank IE's .focus() for this). Provide a callback to know when a command has completed and use a delay to for timeouts between commands. The following asserts that 'hello' has been removed from the page:

Syn.click( {},'hello' )
   .type( 'Hello World' )
   .delay()         //waits 600ms seconds by default
   .drag( $('#trash') , function() {
     ok( $('#hello').length == 0, "removed hello" )
   }); 

Notice that an element id is absent from the type and drag methods. If an element id is not provided, the previous command's element is used.

Lets explore a how to use each action in detail.

Click and Dblclick

A click is the following sequence of events followed by the event's default actions:

  • mousedown
  • focus (Called only if the element was focusable, and mousedown's default actions were not prevented)
  • mouseup
  • click

A dblclick is just two clicks followed by a dblclick event. The options for a click action become properties on the event. The following sets clientX and clientY for the mousedown and mouseup of a click action:

Syn.click({clientX: 533, clientY: 100}, 'foo')

A few important points on click:

  • ClientX and ClientY are relative to the viewport (window).  
  • You can provide pageX and pageY for positions relative to the page (such as jQuery's offset).
  • If jQuery is available, the clientX and clientY will be set to the center of the element.
  • If you want to set the control key values of the click action, you have to type or key that button.
Type and Key

The key action is the following sequence of events followed by the event's default actions:

  • keydown (Except for the print key)
  • keypress (For keys that generate a keypress)
  • focus (for keys that change focus, like \t)
  • keyup

The type action calls the key action for each character. Check the keycodes documentation for a list of key names. The following types "JavaScriptMVC" then presses backspaces to delete the "MVC", leaving "JavaScript".

Syn.type( 'JavaScriptMVC\b\b\b', 'foo' )

Special Characters

Some characters don't have a type-able key such as right, ctrl, and delete. To type these keys you just have to surround them with [ and ]. The following types JavaScriptMVC, moves the cursor to the left 3 times, and then types delete 3 times:

Syn.type(
 'JavaScriptMVC[left][left][left][delete][delete][delete]',
 'foo')

Command Keys

The command keys ctrl, alt, and shift often want to be held while another key is pressed. For these keys, you have to call the key like [command], and release the key with [command-up]. The following types JavaScriptMVC, selects the MVC text, and then deletes it.

Syn.type(
 'JavaScriptMVC[shift][left][left][left][shift-up]\b',
 'foo')
Drag and Move

A move action is the following events

  • mousemove
  • mouseout (the cursor leaves an element)
  • mouseover (the cursor enters an element)

A move creates a linear sequence of mouse move, outs and overs between two points. A drag action is a mousedown followed by a move and a final mouseup. To make a drag motion from one point to another over 2 seconds:

Syn.drag(
     {
       from: {clientX: 100, clientY: 100},
       to:   {clientX: 200, clientY: 200},
       duration: 2000
     },
     'foo') 

Or if you want to provide pageX and pageY:

Syn.drag(
     {
        from: {pageX: 100, pageY: 100}, 
        to:   {pageX: 200, pageY: 200} 
     }, 
     'foo')

You can shorten this to:

Syn.drag(
     {from: '100x100', to: '200x200' },
     'foo')

But most commonly, you want to drag one element to another element. To drag the foo to the bar element:

Syn.drag(
     document.getElementById('bar'),
     'foo')

This drags from the center of one element to the other.

Conclusion

You should care about syn if you:

  • Work on the Selenium or some other functional testing library.
  • Want to test complex UI behavior.

Our naive hope is that Syn might be the Sizzle of functional testing - a standalone, extendable, drop in, synthetic event library.

Categories: Open Source

Organize jQuery Widgets with jQuery.Controller

JavaScriptMVC - Tue, 07/27/2010 - 08:25

Do you like organized code and hate nested functions that are impossible to reuse? Want to be able to extend plugins and widgets? Do you want these widgets to clean themselves up after they are removed? Great! JavaScriptMVC-extracted jQuery.Controller is the easiest and most robust way to build jQuery widgets.

Features
  • Extendable widgets.
  • Deterministic and debug-able code.
  • Auto cleanup.
  • Namespaced widgets.
Download

jquery.controller.js (minimized 7.8kb) [includes jquery.class.js, jquery.event.destroyed.js]

Demos
  1. Tabs widget.  
  2. Extending Tabs to use history.
Documentation

JavaScriptMVC's controller docs.

Use

Using controller is easy. Extend $.Controller with the name and methods of your widget. Methods that look like "event" or "selector event" are bound (or delegated) when a new controller is created. The init method is called after the events are bound.

The following creates a tab widget.

// create a new Tabs class
$.Controller.extend("Tabs",{

  // initialize code
  init : function(el){

    // activate the first tab
    this.activate( $(el).children("li:first") )

    // hide other tabs
    var tab = this.tab;
    this.element.children("li:gt(0)").each(function(){
      tab($(this)).hide()
    })
  },

  // helper function finds the tab for a given li
  tab : function(li){
    return $(li.find("a").attr("href"))
  },

  // on an li click, activates new tab  
  "li click" : function(el, ev){
    ev.preventDefault();
    this.activate(el)
  },

  //hides old activate tab, shows new one
  activate : function(el){
    this.tab(this.find('.active').removeClass('active')).hide()
    this.tab(el.addClass('active')).show();
  }
})
  
// creates a Tabs on the #tabs element
$("#tabs").tabs();

There are a few important things to notice:

  • Creating a Controller class creates a jQuery plugin with the underscored class name. In this case, it created the tabs plugin: $("#tabs").tabs();
  • The tabs() plugin creates a new Tabs instance on each element matched by the selector. The tabs instance is created with the element and any parameters passed to tabs(). In this case it is called like new Tabs(el).
  • When an instance of Controller is created, events are bound, this.element is set to the Controller's element, and init is called to setup the widget.
Extending Widgets

Many jQuery widgets suffer from an "everything-but-the-kitchen-sink" mentality. They pack every conceivable type of related functionality. This causes software bloat and slower load times for users. The root problem is the lack of a standard way to organize and extend widgets.

Controller fixes this problem by using Class. The following extends the Tabs widget above to make history enabled tabs.*

//inherit from tabs
Tabs.extend("HistoryTabs",{
  // ignore clicks
  "li click" : function(){},
  
  // listen for hashchanges
  "hashchange" : function(){
    var hash = window.location.hash;
    this.activate(hash === '' || hash === '#' ?
      this.element.find("li:first") : 
      this.element.find("a[href="+hash+"]").parent()
    )
  }
})

// create a history tabs
$("#historytab").history_tabs()

*This assumes you are using something like Ben Alman's jQuery Hashchange Event Plugin.

By using Controller, we are able to keep functionality bloat to a minimum while providing a base class for future complex functionality.

Deterministic Code

Have you ever tried understanding someone else's jQuery code? You'll probably see a nested mess of anonymous callback functions wrapped in a self calling anonymous function. Despite there being as many jQuery widgets as there are atoms in the universe, there isn't a great way to organize jQuery functionality.

If you're working on a big project, or with other developers, unorganized code can create a big problem real fast.  You need code that is deterministic - if you see functionality expressed in the page, you know where that functionality is expressed in code.

Controller provides this by organizing all entry points to a widget (methods and events) and adding the controller's name to the element's className. We'll break these down in the next two sub-sections; but the result is if something happens on the page, say an "li" in a ".tabs" element is clicked, you know to look for "li click" in a Tabs controller.

Organized Methods and Events

Controllers' prototype properties organize public methods and event handlers. This makes finding 'where stuff gets happens' in a widget really easy. For example, if you wanted to activate the last tab in a Tabs, you could call:

$('#tabs').tabs("activate", $("#tabs li:last"))

But the REALLY clever thing about controller is how it organizes event handlers. By naming a function like "event" or "selector event", Controller knows to listen for those events. Event handlers are self labeling! We typically refer to these methods as actions.

Controller even lets you parameterize actions, making it possible to configure the event or selector when the controller is created. And, with the jquery.controller.subscribe.js plugin, you can listen to OpenAjax messages. The following are example actions:

// listens for all clicks in this controller
click : function(el, ev){...}

//  changes in .foo .bar element in this controller
".foo .bar change" : function(el, ev) {...}

// listen to this.options.activateEvent events in an li
"li {activateEvent}" : function(){...}

//listen for OpenAjax hub "recipe.created" messages
"recipe.created subscribe" : function(called, recipe){...}

//listens for drag events with jquery.event.drag.js
".drag dragover" : function(el, ev, drag, drop){ ... }

Controller Element Label

Controllers label their element's className with their name. For example, after a HistoryTabs controller is added to the #historytab element, it would look like:

<div id='historytab' class='history_tabs'></div>

You can also see all controllers on an element with $("#foo").data('controllers').

In summary, Controller organizes functionality so it is easy to find. It provides a flexible but orderly way to organize widgets.

Auto-magic Cleanup

If you're building a JavaScript application, removing a widget from the page is almost as important as adding one. Unfortunately, the vast majority of jQuery plugins are designed to enhance a static page and this important feature is ignored. Typically, the only way to remove a widget is to remove its element. Even when the element is removed, the widget is often still bound to other objects such as the document which causes errors.

Controller makes cleaning up widgets easy, and in most cases automatic. It also lets you remove a controller without removing the element.

In the previous section, we showed how controller auto-binds actions. Controller also auto-unbinds those actions when the controller is destroyed. A controller can be destroyed in two ways:

  1. The controller's element is removed from the page with jQuery manipulators like .remove(), .html().
  2. The controller's destroy method is called like:
    $('.hider:first').controller().destroy()
    

Controller also provides bind and delegate methods that allow you to listen to events on elements outside the controller's element. These event handlers will automatically be removed when the controller is destroyed.

The following controller displays "Click to Hide" and hides itself when the document is clicked.

$.Controller.extend("CloseOnClick",{
  init : function(){
    // call close on document clicks
    this.bind(document, 'click', 'close');

    // remove and save old content
    this.oldChildren = this.element.children().remove();
    
    // show text to hide
    this.element.html("<p>Click to hide</p>")
  },
  close : function(){
    this.element.hide()
  },
  destroy : function(){
    .... //we will fill this in later
  }
});

$('.hider').close_on_click()

When a 'hider' element is removed, or destroy is called on a CloseOnClick controller, the controller's event handlers are unbound, removing the document click handler.

If your widget has made any modifications to the element, overwrite the destroy function to set things back to their original state.

The following sets back the original contents of the element:

  destroy : function(){
    this.element.children.remove();
    this.element.append(this.oldChildren)
    this.oldChildren = null;
    
    // always call super to call base destroy
    this._super()
  }
Namespaces

It's important to keep plugins from stomping on each other. If you create a Controller with a namespace, it includes the namespace in the jQuery plugin. For example:

$.Controller.extend("Jupiter.Tabs");

// creates -->

$("#tabs").jupiter_tabs()

This isn't exactly namespacing and not 100% protection against collision. But in practice, we've not had any problems.

Conclusions

Controller is JavaScriptMVC's, and by extension, Jupiter's secret-sauce. It helps us build functionality in a robust and repeatable way. It's hard to express the amazing feeling walking onto a project with 50 controllers I have never seen and instantly start contributing and fixing bugs.

Controller also helps us develop faster because we don't have to invent a new pattern for every widget. 

Controller is not for all jQuery plugins. If you are building something very small, unlikely to be extended, or DOM related, controller is probably not the best fit. But if you find yourself needing to organize your team's jQuery code around a proven pattern, take Controller for a spin.

Categories: Open Source

A Simple, Powerful, Lightweight Class for jQuery

JavaScriptMVC - Tue, 07/27/2010 - 08:25

jQuery's functional programming style is downright elegant for manipulating the DOM. But it lacks the structure and code reuse patterns that professional scripters need. John Resig's Simple Class inspired, jQuery.Class is a lightweight, but powerful class-like system that bridges the gap between jQuery's functional programming style and Object Oriented Programming.

Features
  • Static and prototypal inheritance
  • Introspection
  • Namespaces
  • Setup and initialization methods
  • Easy callback creation
Download

jquery.class.js (minimized 2kb)

Demo

Extend a tabs widget to a history tabs widget demo.

Documentation

JavaScriptMVC's Class docs.

Use

To create a monster class with static and prototype properties:

$.Class.extend("Monster",
// static properties
{
  count: 0  
},
// prototype properties
{
  // constructor function
  init : function(name){
    //save the name
    this.name = name;

    this.energy = 10;

    //increment the static count
    this.Class.count++;
  }
})

//create a monster
var dragon = new Monster('dragon');

Inheritance

To extend (or inherit) from a class just call .extend on the class and provide the new name of your class and the static and prototype properties:

Monster.extend("SeaMonster",{},{
  swim : function(distance){
    this.energy -= distance
  }
})

If you want to call an base class's static or prototype method from the extended class:

SeaMonster.extend("LochNessMonster",{},{
  swim : function(distance){
    this._super(distance/2);
  }
})

Notice how _super calls the base class's method.

Introspection

You can access the full and short name of the class for groovy introspection techniques.  The following uses the class's name to change where the ajax request is sent:

$.Class.extend("Model",{
  findAll : function(success){
    // use the class's name to find items
    $.get('/'+this.shortName.toLowerCase()+'s',
           success,
           'json')
  }
},{});

// create a task model
Model.extend('Task')

//use it to make a request to /tasks
Task.findAll(function(tasks){
   alert(tasks.length);
})

Namespaces

Namespaces are a GREAT idea. It's nice when code doesn't clobber each other.

$.Class.extend("MyCo.Project.MyClass");

MyCo.Project.MyClass.shortName //-> MyClass

MyCo.Project.MyClass.fullName //-> MyCo.Project.MyClass
Setup and Initialization Methods

When a class or instance of a class is created, setup and init methods are called on the class or instance. Setup is called before init and can be used to normalize arguments to init. Init is the class or instance's constructor function. But unlike normal constructor functions, you don't have to worry initialization code that will prevent further inheritance*.

The following makes sure all classes extending Controller will have their init function called with a jQuery element instead of an element:

$.Class.extend("Controller",{
  setup : function(el){
    arguments[0] = jQuery(el);
    return arguments;
  }
})

// A dummy tabs class
Controller.extend('Tabs',{
  init : function(el){
    this.element = el;
  }
})

var tab1 = new Tabs($("#foo")),
    tab2 = new Tabs($("#bar")[0]);

//call jQuery methods on element
tab1.element.show();
tab2.element.hide();

*You probably won't need setup methods, but it's cool if you need a lot of pre-processing for extending classes.  The problem with normal constructor functions is that they typically need to be callable without arguments to be able to setup a correct prototype chain.

Easy Callback Creation

Similar to jQuery's proxy, Class provides a static and prototype callback function that returns a callback that has 'this' or the context set to the Class or instance.

The following uses callback to return a function that will call the new task's show method with 'this' set to the new task.

$.Class.extend("Task",{
  init : function(name){
    this.name = name
  },
  get : function(){
    $.get('task',
         {name:this.name},
         this.callback('show'),
         'text')
  },
  show : function(instructions){
    alert(this.name+instructions)
  }
})

new Task("dishes").get()

The callback function lets you curry arguments and even gets a little Aspect Oriented Program-ish and lets you chain multiple callbacks*:

$.Class.extend("Task",{
  init : function(name){
    this.name = name
  },
  get : function(date, callback){
    $.get('task',
         {name:this.name},

         // call show, then callback, curry date
         this.callback(['show', callback], date),
         'text')
  },
  show : function(date, instructions){
    // return arguments for next function
    return [this.name, date, instructions]
  }
})

new Task("dishes").get(
  new Date(), 
  function(name, date, instructions){
    console.log(name, date, instructions);
  }
)

*Chaining callbacks is helpful when there are multiple processing steps before some final callback is called. It makes it so you don't have to curry the final callback over and over again. ;

Conclusions

Use classes where appropriate.  There has been some fun poked at classy-ing up jQuery.  But there is an important difference between an API for modifying the DOM and a sortable-paginated-groupable grid.

jQuery lacks a clear and repeatable pattern for organizing code. It also lacks tools to extend and add functionality to existing widgets. This is to jQuery's strength. It makes jQuery useful to everyone.

But, as code gets more complex and teams get bigger, the need for patterns and tools to bridge the jQuery to Object Oriented Architecture gap becomes unavoidable. We hope jQuery.Class can help.

Categories: Open Source

Set inner/outer width/height with jQuery Dimensions.Etc Plugin

JavaScriptMVC - Tue, 07/27/2010 - 08:25

You often want to animate or set an object to be a specific width or height on the page. But if that element has padding, border, or margin, it will probably take up more space than you expect. The jquery.dimensions.etc.js plugin lets you set and animate the outerWidth, outerHeight, innerWidth and innerHeight of DOM elements.

Download

jquery.dimensions.etc.js (minified 2kb)

Features
  • Set and animate innerWidth, innerHeight, outerWidth, and outerHeight.
  • Fast.  Uses the curStyles plugin.
Demo

Change the dimensions of an element in the dimensions demo.

Documentation

Read JavaScriptMVC's dimensions docs.

Use

Setting and animating the dimensions with the innerWidth, innerHeight, outerWidth, and outerHeight helpers is pretty straightforward:

// include padding
$('#foo').innerHeight(20)
$('#foo').animate({innerWidth: 80})

// include padding + border
$('#bar').outerHeight(40)
$('#bar').animate({outerWidth: 40})

// padding + border + margin
$('#zed').outerHeight(50, true)
$('#zed').animate({outerWidthMargin: 600})

The numeric value is the length of the dimension in pixels.  

These helpers adjust the height and width of the element but include the padding, border, and margin in their calculation. For example, setting outerHeight(40) on an element with "padding:5; border: solid 1px black" will have it's height set to 40 - 2*5 - 2*1 = 28.

Conclusions

We use outerWidth and outerHeight quite often to make an element the size we want it to appear on the page. It enables us to use and adjust border and padding on most widgets we create. Before outerWidth and outerHeight, we had to manually adjust for border and padding. Hopefully you can avoid our problem by making use of this plugin. Good luck.

Categories: Open Source

Get Multiple Computed Styles FAST with the curStyles jQuery Plugin

JavaScriptMVC - Tue, 07/27/2010 - 08:25

Do you use jQuery's css or curCSS functions to get multiple styles on the same element? Don't you know this is slow? The JavaScriptMVC extracted curStyles plugin boosts performance when reading multiple computed styles on a single element.

Download

jquery.curstyles.js (minified 0.9kb) [works with any version of jQuery]

Features
  • Gets multiple computed style values on a single element.
  • Takes hyphenated (padding-left) or camelCase (paddingLeft) names.
  • Performs faster than curCSS.
Demo

See how to make a 2-3X faster jQuery.fn.height plugin in the curStyles demo.

Documentation

JavaScriptMVC's curStyles docs.

Use

Call curStyles on your jQuery element to get a JavaScript object of style-value pairs. For example:

$('#foo').curStyles('paddingTop','marginTop')

might return something like:

{
  paddingTop: '2px',
  marginTop: '12px'
}

The values returned are the element's computed style values.

Computed Style Values

An element's computed style value is the measurable value (typically in px) of all the styles applied on the element. In IE, these values are calculated from properties on the currentStyle property of an element. In all other (standard) browsers, these values are found using getComputedStyle.

A Faster jQuery.fn.height

The following makes a jQuery.fn.height plugin and is shown in the demo.

$.fn.fastHeight = function(){
  
  //start with the offsetHeight
  var sum = this[0] && this[0].offsetHeight;
  // subtract out the current values
  $.each(
    this.curStyles(
      "borderTopWidth",
      "borderBottomWidth",
      "paddingTop",
      "paddingBottom"), 
    function(name, val){
      sum -= parseInt(val) || 0;
    });

   return sum;
}
Conclusions

This plugin is very useful for optimizing performance critical paths.  If you need to get only a handful of computed properties from an element over and over again, you can typically double its speed by using curStyles.

Categories: Open Source

Convert Form Elements to JavaScript Object Literals with jQuery formParams Plugin

JavaScriptMVC - Tue, 07/27/2010 - 08:25

Want to quickly extract form data to a more usable format? Of course you do! We use JavaScriptMVC's formParams plugin constantly to turn form data into much easier to manipulate JavaScript Objects.  We're releasing formParams standalone so everyone can save a little time on this extremely common task.

Download

jquery.formparams.js (minified 1kb) [works with all versions of jQuery]

Features
  • Converts form data into object literals like: {foo: 'bar'}
  • Creates nested objects with input names like: 'foo[bar]'
  • Can convert values that look like numbers and booleans to Numbers and Booleans.
  • Works without a form element.
Demo

Form Params Demo

Documentation

JavaScriptMVC's formParams documentation.

Use

Just call formParams on any jQuery wrapped element (form or not):

$('#myform').formParams()  //-> Object

#myform html might look like:

<form id='myform'>
  <input type='text' name='donate' />
  
  <input type='text' name='credit[name][first]' />
  <input type='text' name='credit[name][last]' />

  <input type='text' name='credit[number]' />
  <input type='text' name='credit[expire]' />
  <input type='text' name='credit[security]' />
</form>

The result of formParams might look like:

//$('#myform').formParams()  -> 
{
  donate: 50.55,
  credit : {
    name : {
      first: "Justin",
      last: "Meyer"
    },
    number: "0000-2342-4654-5555"
    expire: "5/4/2011",
    security: 555
  }
}

Sweet huh? You can turn off the Number/Boolean conversion (leaving all values as strings) by calling form params with false:

$('#myform').formParams(false)  //-> Object

Oh, and one other cool thing ... if you have a bunch of checkboxes with the same name like:

<input type='checkbox' checked='checked' 
       name='items' value='model' />
<input type='checkbox' checked='checked'
       name='items' value='view' />
<input type='checkbox' 
       name='items' value='controller'/>

formParams will put the values of the checked checkboxes in an array like:

{items: ['model','view']}

How handy is that!

Conclusions

formParams is quite handy. Because it already depends on an existing form, it's very useful for adding unobtrusive AJAX behavior to forms. We'll often use it to validate a JavaScript object literal before converting the literal to JSON with jquery-json before sending it to a JSON-REST service. That typically looks like:

$('form#recipe').submit( function( ev ) {
  ev.preventDefault();
  var recipe = $(this).formParams().recipe;
  if( !recipe.title && recipe.instructions ) {
    alert( 'provide a title and instructions' );
  }else{
    $.post("/recipes.json",
           $.toJSON(recipe),
           function(){ .... },
           'json'
  }
})

Enjoy!

Categories: Open Source

compareDocumentPosition plugin for jQuery

JavaScriptMVC - Tue, 07/27/2010 - 08:25

Being able to quickly compare two elements' positions in the browser is extremely useful for a variety of tasks. The DOM Level 3 specification describes the compareDocumentPosition method. It returns a bitmask with a whole bunch of useful information.  But not all browsers support it :(

For a really solid walkthrough of compareDocumentPosition, check out John Resig's Comparing Document Position article. In this article, he gets close to providing a fast compareDocumentPosition for all browsers. JavaScriptMVC's standalone jquery.compare plugin steals his ideas and DOES provide a fast compareDocumentPosition in all the browsers jQuery supports.

Download

jquery.compare.js (minified 0.8kb) [works with all versions of jQuery]

Demo

Compare Element Positions

Documentation

JavaScriptMVC's jquery/dom/compare docs.

Use

To use the compare plugin, just call compare on your jQuery wrapped elements with another element or jQuery element:

$('#foo').compare( $("#bar") ) //-> Number

The number is actually a bitmask that represents multiple several pieces of relational information about the two elements. Here's what each bit means:

Bits Number Meaning 000000 0 Elements are identical. 000001 1 The nodes are in different documents (or one is outside of a document). 000010 2 Node B precedes Node A. 000100 4 Node A precedes Node B. 001000 8 Node B contains Node A. 010000 16 Node A contains Node B.

This means if a compare results in a 10, node B is before and contains node A. Typically, you just want to know one bit's information. To do this, use the bitwise AND operator (&) like:

if( $('#foo').compare( $("#bar") )  & 2  ){
  //do something  because #bar is before #foo
}
How it works

The plugin uses all the techniques in John's article, but fixes the 'Safari' problem.  Older versions of Safari lack compareDocumentPosition and sourceIndex.  This makes comparing node order (the 2 and 4 values of the bitmask) challenging. A naïve approach might be to walk up the parent nodes until an intersection happens. But, as I've learned from event delegation, calling parentNode is surprisingly slow.  But using document Ranges and comparing them is fast. The following code adds the 2 and 4 values in Safari:

var range = document.createRange(), 
    sourceRange = document.createRange(),
    compare;
range.selectNode(this[0]);
sourceRange.selectNode(b);
compare = range.compareBoundaryPoints(Range.START_TO_START, 
                                      sourceRange);
number += (compare === -1 && 4)
number += (compare === 1 && 2)

This code uses Safari's implemented compareBoundryPoints method in the DOM Level 2 Traversal-Range recommendation. CompareBoundaryPoints compares 2 ranges. You have to provide which parts of the ranges to compare and it returns -1,0, or 1 to indicate the the boundary positions. 

Categories: Open Source

Ajax Fixtures Plugin for jQuery

JavaScriptMVC - Tue, 07/27/2010 - 08:25

Are you developing jQuery hotness so fast that the slow-poke server team can't supply you AJAX services fast enough?  If so, you might be interested in the JavaScriptMVC-extracted jQuery.Fixture plugin.  Fixtures simulate AJAX responses so you can keep developing JavaScript functionality even if the server's services aren't working.  The fixture plugin is easy to setup and remove once the services are online.

Download

jquery.fixture.js  - works with jQuery 1.2 and greater

Features
  • Easy to toggle fixtures on and off (just remove the plugin)
  • Dynamic fixtures
  • Pre-made REST fixtures
  • Fixture helpers
Demo

Fixture Messages Demo

Documentation

JavaScriptMVC's jQuery.fixture documentation

Use

It's easy to use fixtures.  Just ...

  1. Add the script to your page.
  2. Set the fixture parameter to your simulated response file.

For example ....

$.ajax({url: "/task.json",
  dataType: "json",
  type: "get",
  success: myCallback,

  fixture: "fixtures/task.json"
});

... uses "fixtures/task.json" as the response instead of "task.json". The "fixtures/task.json" file might look like:

{
  "name" : "take out trash",
  "description" : "to the curb",
  "id" : 5
}

When the tasks service comes online, just remove the fixtures script tag and jQuery will make requests as normal.

Methods

The fixture plugin overwrites $.ajax, $.get and $.post to accept a fixture parameter or argument.

//... a property with $.ajax
$.ajax({fixture: FIXTURE_VALUE})

//... a parameter in $.get and $.post
$.get (  url, data, callback, type, FIXTURE_VALUE )
$.post(  url, data, callback, type, FIXTURE_VALUE )

Dynamic Fixtures

Services almost always return different results depending on the data sent to the service.  Sometimes a single static file is unable to approximate the result of these services.  In these cases, by providing a function as the fixture object, fixtures can dynamically generate the result of the request from the data passed into the service (just like your server would do).

$.ajax({
  type:     "get", 
  url:      "tasks",
  data:     {limit: 1000},
  dataType: "json",
  
  fixture: function( settings ){
    var tasks = [];
    for( var i=0; i < settings.data.limit; i++ ) {
      tasks.push({id: i, name: "task "+i})
    }
    return [tasks]
  }
})

Dynamic Fixtures are really helpful for performance testing your app. Wan't 10k tasks? Make the fixture return 10k tasks. Want requests to take 5 seconds to return, set jQuery.fixture.delay to 5000.

Rest Helpers

The fixture plugin includes several pre-made fixtures (-restUpdate, -restCreate, -restDestroy) that simulate a REST interface.  The following example uses -restCreate to simulate creating tasks.:

$.post(
  '/messages.php',
  messageData, 
  function(){ ... },
  'json',
  '-restCreate')
Fixture Helpers

$.fixture.make is used to create fixtures that retrieve JSON data from the server.  The fixtures it generates supports limit, offset, filtering, and sorting.  The following creates a fixture for 1000 threaded messages and then gets 100-150th child messages of message 5.

//makes a threaded list of messages
$.fixture.make(
  ["messages","message"],
  1000, 
  function(i, messages){
    return {
      subject: "This is message "+i,
      body: "Here is some text for this message",
      date: Math.floor( new Date().getTime() ),
      parentId: i < 100 ? null : Math.floor(Math.random()*i)
    }
})
//uses the messages fixture to return messages 
// limited by offset, limit, order, etc.
$.ajax({
  url: "messages",
  data:{ 
     offset: 100, 
     limit: 50, 
     order: "date ASC",
     parentId: 5},
  },
  success: function(messages){  ... },
  fixture: "-messages"
});
Conclusions

Fixtures are a big part of Jupiter and JavaScriptMVC's "secret sauce".  In our years doing JavaScript consulting, rarely is the back-end complete. Instead of waiting around, we use fixtures to keep moving forward. The back-end teams can use these fixtures as documentation of the service they need to build.  

Even after services are built, fixtures are useful for error, performance, and usability testing.  And when new features are added, you can easily start developing from the fixtures again.

Fixtures kick ass.

Categories: Open Source

Paris SproutCore Meetup

SproutCore - Mon, 07/26/2010 - 15:10

We’re having a SproutCore meetup in Paris on Thursday, August 5th at 8:00 pm. Charles, the creator of SproutCore, will be here, as well as members of the core team. Whether you’re already familiar with the framework of just curious to know more about it, join us for a beer at the Café Léa.

Hope to see you there!

Categories: Open Source

EuroPython2010

qooxdoo News - Mon, 07/26/2010 - 11:38

The well on Paradise Place

I've just returned from Birmingham where EuroPython, the European Python conference, has been held for the second time in successive years. The organizers have done a tremendous job to make it a friendly and productive conference. I attended the preceding tutorial days, taking a full-day tutorial on py.test by Holger Krekel, a half-day introduction to Google App Engine by the venerable Wesley Chun, author of Core Python, and a half-day tutorial about TextTest held by Geoffrey Bache. All of them were excellent.

During the main conference which lasted from Monday through Thursday I focused on presentations relating to code quality and performance. Highlights for me were Raymond Hettinger's Idiomatic Python who was given another free time slot to cover more material, and the talks about virtual machines (PyPy, HotPy). Guido van Rossum, Python's "Benevolent Dictator for Lifetime", gave a very insightful questions-and-answers keynote session, where he addressed many issues both interesting and relevant for Python's future. Concerning one of them, which is also very close to my own heart, he mentioned that he is interested in high-level concurrency constructs and is attending all CSP-related talks in the conference (e.g. [1], [2]). There was also a CSP-related sprint in the days following the conference. I think this is a very important field, and has to be covered in good manner in Python. One other thing that struck me was the way people twist and bent Python, using its meta programming facilities, as e.g. Kay Schlühr demonstrated with Langscape, a framework to define language extensions which get translated to standard Python. There were also two lightning talks sessions which were a very good way of presenting interesting topics to a large audience in a few minutes.

The same well, seen from the Conservatoir's entrance.

During the conference there was also the first meeting of the PSF ever to be held outside the US. The PSF, the Python Software Foundation, is the non-profit legal entity behind Python that holds the intellectual property rights and tries to promote and protect the language. Twenty non-members where invited to attend and I managed to slip in. It was an interesting insight into the inner workings of an international open-source organisation. All in all it was a very interesting and enjoyable conference, with lots of contacts and chats during breaks and in the after-conference evenings. Way to go, EuroPython! (Ah, I wish they would rename it into PyCon Europe).

Categories: Open Source

2010-07-24 - NEW EXAMPLE: 3D Rotation Viewer

UIZE JavaScript Framework - Sun, 07/25/2010 - 04:06
The new 3D Rotation Viewer example demonstrates how to easily create a slick 3D rotation viewer in UIZE that lets users rotate the view of an object a full 360 degrees using a mouse, or finger on the Apple iPad. The example is inspired by a showcase example by Apple of HTML5 technologies. The UIZE implementation works in pretty much all browsers, with no need for HTML5 or CSS3 features. This was an exercise in seeing how easy it would be to create an equivalent experience in UIZE. It was easy, taking less than a day. The code is all original, with absolutely no referencing of Apple's code (but thanks to Apple for their delicious iPod Touch products, and for their fabulous photos of said products). In the example, an instance of the Uize.Widget.Drag class is being used to create a simple 3D rotation viewer. Using a mouse, you can click and drag to rotate the 3D image. On an Apple iPad, you can use your finger. The viewer implements a deceleration behavior - the speed at the time of release determines how long it will take to spin down to a stop. When the page loads initially, the image is animated 360 degrees clockwise. Buttons beneath the viewer let you trigger other kinds of spins.
Categories: Open Source

2010-06-28 - UIZE Web Site Revamp

UIZE JavaScript Framework - Sun, 07/25/2010 - 04:06
The uize.com Web site has been updated with a bright new look and usability improvements for the Apple iPad. While there are those among us who are attracted to the dark side... where color themes are concerned, there is no denying that the overwhelming preference is for light themed Web sites. Dark text over a light background is the age old convention when it comes to the printed word. People are used to it, comfortable with it, and a light background improves readability in high ambient light conditions where a dark background would have a hard time competing with the ambient light. Add to that the fact that fingerprints on touch devices like the Apple iPad really show up something awful against a dark background, and that one can see one's own reflection too easily against a glossy display when its background is dark, and you have a whole bunch of compelling reasons to have a light background. Hence, the new look for the uize.com Web site. In addition to the color theme changes, many features have been tweaked slightly to improve usability on touch devices like the Apple iPad. Some user interface controls have been made larger, font size for some links has been increased, and some iPad specific issues have been addressed. Hope you like the new look. Bright and fresh.
Categories: Open Source

2010-07-15 - NEW EXAMPLE: UIZE Unit Tests

UIZE JavaScript Framework - Sun, 07/25/2010 - 04:06
The new UIZE Unit Tests example lets you select and run any of the test modules of the UIZE JavaScript Framework. In the example, a test module selector lets you choose your test module. On selecting a test module, the test module is loaded dynamically. After it has loaded, you can use the "START TESTS" button to start running the tests contained inside the selected test module. While the tests are being performed, a progress bar is updated to show how far you are through the tests. Also, a log is written to with details of the tests being performed. You can stop the tests at any time using the "STOP TESTS" button. If one of the tests fails (none should, of course), test execution is aborted and a synopsis of the failure is displayed in a dialog. To run the entire test suite for the UIZE JavaScript Framework, you can select the Uize.Test.UnitTests test module.
Categories: Open Source

2010-07-11 - NEW EXAMPLE: Digital Clock

UIZE JavaScript Framework - Sun, 07/25/2010 - 04:06
The new Digital Clock example shows how the Uize.Widget.SegmentDisplay.Seven widget class can be used to easily create a digital clock that shows hours, minutes, and seconds. In the example, six seven segment display widgets are used - two for the hours display, two for the minutes display, and two for the seconds display. After the page loads and is initialized, a timer/interval is started that updates the clock's display every second. For every update, the current time is queried using JavaScript's Date object and formatted to an HHMMSS string using the Uize.Date.Formatter.format method of the Uize.Date.Formatter module, specifying the string value '{hh}{mm}{ss}' for the date format. From the formatted string, the first character is used to set the value of the hours display's tens widget, and the second character is used to set the value of the hours display's ones widget. In a similar manner, the third and fourth characters of the formatted date string are used for the minutes display's two seven segment display widgets, and the last two characters of the formatted date string are used for the seconds display's two widgets.
Categories: Open Source

2010-07-07 - NEW EXAMPLE: Button

UIZE JavaScript Framework - Sun, 07/25/2010 - 04:06
The new Button example provides a demonstration of the features of the Uize.Widget.Button widget class. In the example, an instance of the Uize.Widget.Button widget class is instantiated and wired up. A log widget is used to log the instance events that occur for the button widget. Interacting with the widget will cause events to be fired, and those events will appear in the log. The log displays both the custom instance events that are fired using the button widget's fire method, as well as all Changed.* property change events that result from values of the button's various set-get properties being changed (so, the log can be used to watch for changes in the state of the button widget). Below the instance event log for the button is a set of links for testing aspects of the programmatic interface of the button widget. A "TOGGLE ENABLED" link toggles the value of the button's enabled set-get property. A "TOGGLE BUSY" link toggles the value of its busy set-get property. A "TOGGLE SELECTED" link toggles the value of its selected set-get property. Finally, a "CHANGE BUTTON TEXT" link changes the value of its text set-get property.
Categories: Open Source

2010-07-07 - NEW MODULE: Uize.Widget.Log.InstanceEvents

UIZE JavaScript Framework - Sun, 07/25/2010 - 04:06
The new Uize.Widget.Log.InstanceEvents module implements a log interface for logging the instance events of an instance of a Uize subclass. The Uize.Widget.Log.InstanceEvents module provides a convenient way to easily present a log of all the instance events that occur for an instance of a Uize subclass, including custom instance events that are fired using the instance's fire method, as well as all Changed.* property change events that result from values of the instance's various set-get properties being changed. This means that you can use a Uize.Widget.Log.InstanceEvents instance to watch for changes in the state of some other instance. The instance for which instance events are logged can be an instance of any Uize subclass - not just widget classes.
Categories: Open Source