RSS

Monthly Archives: May 2012

More Khmer fonts in Google Web Fonts API directory

By Danh Hong

http://www.google.com/webfonts?subset=khmer

Advertisements
 
1 Comment

Posted by on May 21, 2012 in General

 

Unit Testing Backbone.js Apps With QUnit And SinonJS

This article will be appearing in my forthcoming book on Backbone.js and continues the section on unit testing. We previously looked at Jasmine and will now look at QUnit and SinonJS.

QUnit is a powerful JavaScript test suite written by jQuery team member Jörn Zaefferer and used by many large open-source projects (such as jQuery and Backbone.js) to test their code. It’s both capable of testing standard JavaScript code in the browser as well as code on the server-side (where environments supported include Rhino, V8 and SpiderMonkey). This makes it a robust solution for a large number of use-cases.

 

Quite a few Backbone.js contributors feel that QUnit is a better introductory framework for testing if you don’t wish to start off with Jasmine and BDD right away. As we’ll see later on in this article, QUnit can also be combined with third-party solutions such as SinonJS to produce an even more powerful testing solution supporting spies and mocks, which some say is preferable over Jasmine.

My personal recommendation is that it’s worth comparing both frameworks and opting for the solution that you feel the most comfortable with.

QUnit

Getting Setup

Luckily, getting QUnit setup is a fairly straight-forward process that will take less than 5 minutes.

We first setup a testing environment composed of three files:

  • A HTML structure for displaying test results,
  • The qunit.js file composing the testing framework and,
  • The qunit.css file for styling test results.

The latter two of these can be downloaded from the QUnit website.

If you would prefer, you can use a hosted version of the QUnit source files for testing purposes. The hosted URLs can be found here.

Sample HTML with QUnit-compatible markup:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <title>QUnit Test Suite</title>
  5.      <link rel=”stylesheet” href=”qunit.css”>
  6.      <script src=”qunit.js”></script>
  7.      <!– Your application –>
  8.      <script src=”app.js”></script>
  9.      <!– Your tests –>
  10.      <script src=”tests.js”></script>
  11. </head>
  12. <body>
  13.     <h1 id=”qunit-header”>QUnit Test Suite</h1>
  14.     <h2 id=”qunit-banner”></h2>
  15.     <div id=”qunit-testrunner-toolbar”></div>
  16.     <h2 id=”qunit-userAgent”></h2>
  17.     <ol id=”qunit-tests”>test markup, hidden.</ol>
  18. </body>
  19. </html>

Let’s go through the elements above with qunit mentioned in their ID. When QUnit is running:

  • qunit-header shows the name of the test suite
  • qunit-banner shows up as red if a test fails and green if all tests pass
  • qunit-testrunner-toolbar contains additional options for configuring the display of tests
  • qunit-userAgent displays the navigator.userAgent property
  • qunit-tests is a container for our test results

When running correctly, the above test runner looks as follows:

screenshot 1

The numbers of the form (a, b, c) after each test name correspond to a) failed asserts, b) passed asserts and c) total asserts. Clicking on a test name expands it to display all of the assertions for that test case. Assertions in green have successfully passed.

screenshot 2

If however any tests fail, the test gets highlighted (and the qunit-banner at the top switches to red):

screenshot 3

Assertions

QUnit supports a number of basic assertions, which are used in testing to verify that the result being returned by our code is what we expect. If an assertion fails, we know that a bug exists. Similar to Jasmine, QUnit can be used to easily test for regressions. Specifically, when a bug is found one can write an assertion to test the existence of the bug, write a patch and then commit both. If subsequent changes to the code break the test you’ll know what was responsible and be able to address it more easily.

Some of the supported QUnit assertions we’re going to look at first are:

  • ok ( state, message ) – passes if the first argument is truthy
  • equal ( actual, expected, message ) – a simple comparison assertion with type coercion
  • notEqual ( actual, expected, message ) – the opposite of the above
  • expect( amount ) – the number of assertions expected to run within each test
  • strictEqual( actual, expected, message) – offers a much stricter comparison than equal() and is considered the preferred method of checking equality as it avoids stumbling on subtle coercion bugs
  • deepEqual( actual, expected, message ) – similar to strictEqual, comparing the contents (with ===) of the given objects, arrays and primitives.

Creating new test cases with QUnit is relatively straight-forward and can be done using test(), which constructs a test where the first argument is the name of the test to be displayed in our results and the second is a callback function containing all of our assertions. This is called as soon as QUnit is running.

Basic test case using test( name, callback ):

  1. var myString = “Hello Backbone.js”;
  2. test( “Our first QUnit test – asserting results”, function(){
  3.     // ok( boolean, message )
  4.     ok( true, “the test succeeds”);
  5.     ok( false, “the test fails”);
  6.     // equal( actualValue, expectedValue, message )
  7.     equal( myString, “Hello Backbone.js”, “The value expected is Hello Backbone.js!”);
  8. });

What we’re doing in the above is defining a variable with a specific value and then testing to ensure the value was what we expected it to be. This was done using the comparison assertion, equal(), which expects its first argument to be a value being tested and the second argument to be the expected value. We also used ok(), which allows us to easily test against functions or variables that evaluate to booleans.

Note: Optionally in our test case, we could have passed an ‘expected’ value to test()defining the number of assertions we expect to run. This takes the form: test( name, [expected], test ); or by manually settings the expectation at the top of the test function, like so: expect( 1 ). I recommend you to make it a habit and always define how many assertions you expect. More on this later.

As testing a simple static variable is fairly trivial, we can take this further to test actual functions. In the following example we test the output of a function that reverses a string to ensure that the output is correct using equal() and notEqual():

Comparing the actual output of a function against the expected output:

  1. function reverseString( str ){
  2.     return str.split(“”).reverse().join(“”);
  3. }
  4. test( “reverseString()”, function() {
  5.     expect( 5 );
  6.     equal( reverseString(“hello”), “olleh”, “The value expected was olleh” );
  7.     equal( reverseString(“foobar”), “raboof”, “The value expected was raboof” );
  8.     equal( reverseString(“world”), “dlrow”, “The value expected was dlrow” );
  9.     notEqual( reverseString(“world”), “dlroo”, “The value was expected to not be dlroo” );
  10.     equal( reverseString(“bubble”), “double”, “The value expected was elbbub” );
  11. })

Running these tests in the QUnit test runner (which you would see when your HTML test page was loaded) we would find that four of the assertions pass whilst the last one does not. The reason the test against "double" fails is because it was purposefully written incorrectly. In your own projects if a test fails to pass and your assertions are correct, you’ve probably just found a bug!

Adding structure to assertions

Housing all of our assertions in one test case can quickly become difficult to maintain, but luckily QUnit supports structuring blocks of assertions more cleanly. This can be done using module() – a method that allows us to easily group tests together. A typical approach to grouping might be keeping multiple tests testing a specific method as part of the same group (module).

Basic QUnit Modules:

  1. module( “Module One” );
  2. test( “first test”, function() {} );
  3. test( “another test”, function() {} );
  4. module( “Module Two” );
  5. test( “second test”, function() {} );
  6. test( “another test”, function() {} );
  7. module( “Module Three” );
  8. test( “third test”, function() {} );
  9. test( “another test”, function() {} );

We can take this further by introducing setup() and teardown() callbacks to our modules, where setup() is run before each test whilst teardown() is run after each test.

Using setup() and teardown() :

  1. module( “Module One”, {
  2.     setup: function() {
  3.         // run before
  4.     },
  5.     teardown: function() {
  6.         // run after
  7.     }
  8. });
  9. test(“first test”, function() {
  10.     // run the first test
  11. });

These callbacks can be used to define (or clear) any components we wish to instantiate for use in one or more of our tests. As we’ll see shortly, this is ideal for defining new instances of views, collections, models or routers from a project that we can then reference across multiple tests.

Using setup() and teardown() for instantiation and clean-up:

  1. // Define a simple model and collection modeling a store and
  2. // list of stores
  3. var Store = Backbone.Model.extend({});
  4. var StoreList = Backbone.Collection.extend({
  5.     model: store,
  6.     comparator: function( store ) { return store.get(“name”) }
  7. });
  8. // Define a group for our tests
  9. module( “StoreList sanity check”, {
  10.     setup: function() {
  11.         this.list = new StoreList;
  12.         this.list.add(new Store({ name: “Costcutter” }));
  13.         this.list.add(new Store({ name: “Target” }));
  14.         this.list.add(new Store({ name: “Walmart” }));
  15.         this.list.add(new Store({ name: “Barnes & Noble” });
  16.     },
  17.     teardown: function() {
  18.         window.errors = null;
  19.     }
  20. });
  21. // Test the order of items added
  22. test( “test ordering”, function() {
  23.     expect( 1 );
  24.     var expected = [“Barnes & Noble”, “Costcutter”, “Target”, “Walmart”];
  25.     var actual = this.list.pluck(“name”);
  26.     deepEqual( actual, expected, “is maintained by comparator” );
  27. });

Here, a list of stores is created and stored on setup(). A teardown() callback is used to simply clear our a list of errors we might be storing within the window scope, but is otherwise not needed.

Assertion examples

Before we continue any further, let’s review some more examples of how QUnits various assertions can be correctly used when writing tests:

equal – a comparison assertion. It passes if actual == expected

  1. test( “equal”, 2, function() {
  2.   var actual = 6 – 5;
  3.   equal( actual, true,  “passes as 1 == true” );
  4.   equal( actual, 1,     “passes as 1 == 1” );
  5. });

notEqual – a comparison assertion. It passes if actual != expected

  1. test( “notEqual”, 2, function() {
  2.   var actual = 6 – 5;
  3.   notEqual( actual, false, “passes as 1 != false” );
  4.   notEqual( actual, 0,     “passes as 1 != 0” );
  5. });

strictEqual – a comparison assertion. It passes if actual === expected.

  1. test( “strictEqual”, 2, function() {
  2.   var actual = 6 – 5;
  3.   strictEqual( actual, true,  “fails as 1 !== true” );
  4.   strictEqual( actual, 1,     “passes as 1 === 1” );
  5. });

notStrictEqual – a comparison assertion. It passes if actual !== expected.

  1. test( “notStrictEqual”, 2, function() {
  2.   var actual = 6 – 5;
  3.   notStrictEqual( actual, true,  “passes as 1 !== true” );
  4.   notStrictEqual( actual, 1,     “fails as 1 === 1” );
  5. });

deepEqual – a recursive comparison assertion. Unlike strictEqual(), it works on objects, arrays and primitives.

  1. test( “deepEqual”, 4, function() {
  2.   var actual = {q: “foo”, t: “bar”};
  3.   var el =  $(“div”);
  4.   var children = $(“div”).children();
  5.   equal( actual, {q: “foo”, t: “bar”},   “fails – objects are not equal using equal()” );
  6.   deepEqual( actual, {q: “foo”, t: “bar”},   “passes – objects are equal” );
  7.   equal( el, children, “fails – jQuery objects are not the same” );
  8.   deepEqual(el, children, “fails – objects not equivalent” );
  9. });

notDeepEqual – a comparison assertion. This returns the opposite of deepEqual

  1. test( “notDeepEqual”, 2, function() {
  2.   var actual = {q: “foo”, t: “bar”};
  3.   notEqual( actual, {q: “foo”, t: “bar”},   “passes – objects are not equal” );
  4.   notDeepEqual( actual, {q: “foo”, t: “bar”},   “fails – objects are equivalent” );
  5. });

raises – an assertion which tests if a callback throws any exceptions

  1. test( “raises”, 1, function() {
  2.   raises(function() {
  3.     throw new Error( “Oh no! It’s an error!” );
  4.   }, “passes – an error was thrown inside our callback”);
  5. });

Fixtures

From time to time we may need to write tests that modify the DOM. Managing the clean-up of such operations between tests can be a genuine pain, but thankfully QUnit has a solution to this problem in the form of the #qunit-fixture element, seen below.

Fixture markup:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <title>QUnit Test</title>
  5.     <link rel=”stylesheet” href=”qunit.css”>
  6.     <script src=”qunit.js”></script>
  7.     <script src=”app.js”></script>
  8.     <script src=”tests.js”></script>
  9. </head>
  10. <body>
  11.     <h1 id=”qunit-header”>QUnit Test</h1>
  12.     <h2 id=”qunit-banner”></h2>
  13.     <div id=”qunit-testrunner-toolbar”></div>
  14.     <h2 id=”qunit-userAgent”></h2>
  15.     <ol id=”qunit-tests”></ol>
  16.     <div id=”qunit-fixture”></div>
  17. </body>
  18. </html>

We can either opt to place static markup in the fixture or just insert/append any DOM elements we may need to it. QUnit will automatically reset the innerHTML of the fixture after each test to its original value. In case you’re using jQuery, it’s useful to know that QUnit checks for its availability and will opt to use $(el).html() instead, which will cleanup any jQuery event handlers too.

Fixtures example:

Let us now go through a more complete example of using fixtures. One thing that most of us are used to doing in jQuery is working with lists – they’re often used to define the markup for menus, grids and a number of other components. You may have used jQuery plugins before that manipulated a given list in a particular way and it can be useful to test that the final (manipulated) output of the plugin is what was expected.

For the purposes of our next example, we’re going to use Ben Alman’s $.enumerate()plugin, which can prepend each item in a list by its index, optionally allowing us to set what the first number in the list is. The code snippet for the plugin can be found below, followed by an example of the output is generates:

  1. $.fn.enumerate = function( start ) {
  2.       if ( typeof start !== “undefined” ) {
  3.         // Since `start` value was provided, enumerate and return
  4.         // the initial jQuery object to allow chaining.
  5.         return this.each(function(i){
  6.           $(this).prepend( “<b>” + ( i + start ) + “</b> ” );
  7.         });
  8.       } else {
  9.         // Since no `start` value was provided, function as a
  10.         // getter, returing the appropriate value from the first
  11.         // selected element.
  12.         var val = this.eq( 0 ).children( “b” ).eq( 0 ).text();
  13.         return Number( val );
  14.       }
  15.     };
  16. /*
  17.     <ul>
  18.       <li>1. hello</li>
  19.       <li>2. world</li>
  20.       <li>3. i</li>
  21.       <li>4. am</li>
  22.       <li>5. foo</li>
  23.     </ul>
  24. */

Let’s now write some specs for the plugin. First, we define the markup for a list containing some sample items inside our qunit-fixture element:

<div id="qunit-fixture">
    <ul>
      <li>hello</li>
      <li>world</li>
      <li>i</li>
      <li>am</li>
      <li>foo</li>
    </ul>
  </div>

Next, we need to think about what should be tested. $.enumerate() supports a few different use cases, including:

  • No arguments passed – i.e $(el).enumerate()
  • 0 passed as an argument – i.e $(el).enumerate(0)
  • 1 passed as an argument – i.e $(el).enumerate(1)

As the text value for each list item is of the form “n. item-text” and we only require this to test against the expected output, we can simply access the content using$(el).eq(index).text() (for more information on .eq() see here).

and finally, here are our test cases:

  1. module( “jQuery#enumerate” );
  2. test( “No arguments passed”, 5, function() {
  3.   var items = $(“#qunit-fixture li”).enumerate();
  4.   equal( items.eq(0).text(), “1. hello”, “first item should have index 1” );
  5.   equal( items.eq(1).text(), “2. world”, “second item should have index 2” );
  6.   equal( items.eq(2).text(), “3. i”, “third item should have index 3” );
  7.   equal( items.eq(3).text(), “4. am”, “fourth item should have index 4” );
  8.   equal( items.eq(4).text(), “5. foo”, “fifth item should have index 5” );
  9. });
  10. test( “0 passed as an argument”, 5, function() {
  11.   var items = $(“#qunit-fixture li”).enumerate( 0 );
  12.   equal( items.eq(0).text(), “0. hello”, “first item should have index 0” );
  13.   equal( items.eq(1).text(), “1. world”, “second item should have index 1” );
  14.   equal( items.eq(2).text(), “2. i”, “third item should have index 2” );
  15.   equal( items.eq(3).text(), “3. am”, “fourth item should have index 3” );
  16.   equal( items.eq(4).text(), “4. foo”, “fifth item should have index 4” );
  17. });
  18. test( “1 passed as an argument”, 3, function() {
  19.   var items = $(“#qunit-fixture li”).enumerate( 1 );
  20.   equal( items.eq(0).text(), “1. hello”, “first item should have index 1” );
  21.   equal( items.eq(1).text(), “2. world”, “second item should have index 2” );
  22.   equal( items.eq(2).text(), “3. i”, “third item should have index 3” );
  23.   equal( items.eq(3).text(), “4. am”, “fourth item should have index 4” );
  24.   equal( items.eq(4).text(), “5. foo”, “fifth item should have index 5” );
  25. });

Asynchronous code

As with Jasmine, the effort required to run synchronous tests with QUnit is fairly straight-forward. That said, what about tests that require asynchronous callbacks (such as expensive processes, Ajax requests and so on)? When we’re dealing with asynchronous code, rather than letting QUnit control when the next test runs, we can inform that we need it to stop running and wait until it’s okay to continue once again.

Remember: running asynchronous code without any special considerations can cause incorrect assertions to appear in other tests, so we want to make sure we get it right.

Writing QUnit tests for asynchronous code is made possible using the start() and`stop() methods, which programmatically set the start and stop points during such tests. Here’s a simple example:

  1. test(“An async test”, function(){
  2.    stop();
  3.    expect( 1 );
  4.    $.ajax({
  5.         url: “/test”,
  6.         dataType: “json”,
  7.         success: function( data ){
  8.             deepEqual(data, {
  9.                topic: “hello”,
  10.                message: “hi there!”
  11.             });
  12.             start();
  13.         }
  14.     });
  15. });

A jQuery $.ajax() request is used to connect to a test resource and assert that the data returned is correct. deepEqual() is used here as it allows us to compare different data types (e.g objects, arrays) and ensures that what is returned is exactly what we’re expecting. We know that our Ajax request is asynchronous and so we first callstop(), run the code making the request and finally at the very end of our callback, inform QUnit that it is okay to continue running other tests.

Note: rather than including stop(), we can simply exclude it and substitute test()with asyncTest() if we prefer. This improves readability when dealing with a mixture of asynchronous and synchronous tests in your suite. Whilst this setup should work fine for many use-cases, there is no guarantee that the callback in our $.ajax()request will actually get called. To factor this into our tests, we can use expect()once again to define how many assertions we expect to see within our test. This is a healthy safety blanket as it ensures that if a test completes with an insufficient number of assertions, we know something went wrong and fix it.

SinonJS

Similar to the section on testing Backbone.js apps using the Jasmine BDD framework, we’re nearly ready to take what we’ve learned and write a number of QUnit tests for our Todo application.

Before we start though, you may have noticed that QUnit doesn’t support test spies. Test spies are functions which record arguments, exceptions and return values for any of their calls. They’re typically used to test callbacks and how functions may be used in the application being tested. In testing frameworks, spies can usually be either anonymous functions or wrap functions which already exist.

What is SinonJS?

In order for us to substitute support for spies in QUnit, we will be taking advantage of a mocking framework called SinonJS by Christian Johansen. We will also be using theSinonJS-QUnit adapter which provides seamless integration with QUnit (meaning setup is minimal). Sinon.JS is completely test-framework agnostic and should be easy to use with any testing framework, so it’s ideal for our needs.

The framework supports three features we’ll be taking advantage of for unit testing our application:

  • Anonymous spies
  • Spying on existing methods
  • A rich inspection interface

Using this.spy() without any arguments creates an anonymous spy. This is comparable to jasmine.createSpy() and we can observe basic usage of a SinonJS spy in the following example:

Basic Spies:

  1. test(“should call all subscribers for a message exactly once”, function () {
  2.     var message = getUniqueString();
  3.     var spy = this.spy();
  4.     PubSub.subscribe( message, spy );
  5.     PubSub.publishSync( message, “Hello World” );
  6.     ok( spy1.calledOnce, “the subscriber was called once” );
  7. });

We can also use this.spy() to spy on existing functions (like jQuery’s $.ajax) in the example below. When spying on a function which already exists, the function behaves normally but we get access to data about its calls which can be very useful for testing purposes.

Spying On Existing Functions:

  1. test( “should inspect jQuery.getJSON’s usage of jQuery.ajax”, function () {
  2.     this.spy( jQuery, “ajax” );
  3.     jQuery.getJSON( “/todos/completed” );
  4.     ok( jQuery.ajax.calledOnce );
  5.     equals( jQuery.ajax.getCall(0).args[0].url, “/todos/completed” );
  6.     equals( jQuery.ajax.getCall(0).args[0].dataType, “json” );
  7. });

SinonJS comes with a rich spy interface which callows us to test whether a spy was called with a specific argument, if it was called a specific number of times and test against the values of arguments. A complete list of features supported in the interface can be found here (http://sinonjs.org/docs/), but let’s take a look at some examples demonstrating some of the most commonly used ones:

Matching arguments: test a spy was called with a specific set of arguments:

  1. test( “Should call a subscriber with standard matching”: function () {
  2.     var spy = sinon.spy();
  3.     PubSub.subscribe( “message”, spy );
  4.     PubSub.publishSync( “message”, { id: 45 } );
  5.     assertTrue( spy.calledWith( { id: 45 } ) );
  6. });

Stricter argument matching: test a spy was called at least once with specific arguments and no others:

  1. test( “Should call a subscriber with strict matching”: function () {
  2.     var spy = sinon.spy();
  3.     PubSub.subscribe( “message”, spy );
  4.     PubSub.publishSync( “message”, “many”, “arguments” );
  5.     PubSub.publishSync( “message”, 12, 34 );
  6.     // This passes
  7.     assertTrue( spy.calledWith(“many”) );
  8.     // This however, fails
  9.     assertTrue( spy.calledWithExactly( “many” ) );
  10. });

Testing call order: testing if a spy was called before or after another spy:

  1. test( “Should call a subscriber and maintain call order”: function () {
  2.     var a = sinon.spy();
  3.     var b = sinon.spy();
  4.     // This would fail as b was called after a
  5.     PubSub.subscribe( “message”, a );
  6.     PubSub.subscribe( “event”, b );
  7.     PubSub.publishSync( “message”, { id: 45 } );
  8.     PubSub.publishSync( “event”, [1, 2, 3] );
  9.     assertTrue( a.calledBefore(b) );
  10.     assertTrue( b.calledAfter(a) );
  11. });

Match execution counts: test a spy was called a specific number of times:

  1. test( “Should call a subscriber and check call counts”, function () {
  2.     var message = getUniqueString();
  3.     var spy = this.spy();
  4.     PubSub.subscribe( message, spy );
  5.     PubSub.publishSync( message, “some payload” );
  6.     // Passes if spy was called once and only once.
  7.     ok( spy.calledOnce ); // calledTwice and calledThrice are also supported
  8.     // The number of recorded calls.
  9.     equal( spy.callCount, 1 );
  10.     // Directly checking the arguments of the call
  11.     equals( spy.getCall(0).args[0], message );
  12. });

Stubs and mocks

SinonJS also supports two other powerful features which are useful to be aware of: stubs and mocks. Both stubs and mocks implement all of the features of the spy API, but have some added functionality.

Stubs

A stub allows us to replace any existing behaviour for a specific method with something else. They can be very useful for simulating exceptions and are most often used to write test cases when certain dependencies of your code-base may not yet be written.

Let us briefly re-explore our Backbone Todo application, which contained a Todo model and a TodoList collection. For the purpose of this walkthrough, we want to isolate our TodoList collection and fake the Todo model to test how adding new models might behave.

We can pretend that the models have yet to be written just to demonstrate how stubbing might be carried out. A shell collection just containing a reference to the model to be used might look like this:

  1. var TodoList = Backbone.Collection.extend({
  2.     model: Todo
  3. });
  4. // Let’s assume our instance of this collection is
  5. this.todoList;

Assuming our collection is instantiating new models itself, it’s necessary for us to stub the models constructor function for the the test. This can be done by creating a simple stub as follows:

  1. this.todoStub = sinon.stub( window, “Todo” );

The above creates a stub of the Todo method on the window object. When stubbing a persistent object, it’s necessary to restore it to its original state. This can be done in ateardown() as follows:

  1. this.todoStub.restore();

After this, we need to alter what the constructor returns, which can be efficiently done using a plain Backbone.Model constructor. Whilst this isn’t a Todo model, it does still provide us an actual Backbone model.

  1. teardown: function() {
  2.     this.todoStub = sinon.stub( window, “Todo” );
  3.     this.model = new Backbone.Model({
  4.       id: 2,
  5.       title: “Hello world”
  6.     });
  7.     this.todoStub.returns( this.model );
  8. });

The expectation here might be that this snippet would ensure our TodoList collection always instantiates a stubbed Todo model, but because a reference to the model in the collection is already present, we need to reset the model property of our collection as follows:

  1. this.todoList.model = Todo;

The result of this is that when our TodoList collection instantiates new Todo models, it will return our plain Backbone model instance as desired. This allows us to write a spec for testing the addition of new model literals as follows:

  1. module( “Should function when instantiated with model literals”, {
  2.   setup:function() {
  3.     this.todoStub = sinon.stub(window, “Todo”);
  4.     this.model = new Backbone.Model({
  5.       id: 2,
  6.       title: “Hello world”
  7.     });
  8.     this.todoStub.returns(this.model);
  9.     this.todos = new TodoList();
  10.     // Let’s reset the relationship to use a stub
  11.     this.todos.model = Todo;
  12.     this.todos.add({
  13.       id: 2,
  14.       title: “Hello world”
  15.     });
  16.   },
  17.   teardown: function() {
  18.     this.todoStub.restore();
  19.   }
  20. });
  21. test(“should add a model”, function() {
  22.     equal( this.todos.length, 1 );
  23. });
  24. test(“should find a model by id”, function() {
  25.     equal( this.todos.get(5).get(“id”), 5 );
  26.   });
  27. });

Mocks

Mocks are effectively the same as stubs, however they mock a complete API out and have some built-in expectations for how they should be used. The difference between a mock and a spy is that as the expectations for their use are pre-defined, it will fail if any of these are not met.

Here’s a snippet with sample usage of a mock based on PubSubJS. Here, we have aclearTodo() method as a callback and use mocks to verify its behavior.

  1. test(“should call all subscribers when exceptions”, function () {
  2.     var myAPI = { clearTodo: function () {} };
  3.     var spy = this.spy();
  4.     var mock = this.mock( myAPI );
  5.     mock.expects( “clearTodo” ).once().throws();
  6.     PubSub.subscribe( “message”, myAPI.clearTodo );
  7.     PubSub.subscribe( “message”, spy );
  8.     PubSub.publishSync( “message”, undefined );
  9.     mock.verify();
  10.     ok( spy.calledOnce );
  11. });

Practical

We can now begin writing test specs for our Todo application, which are listed and separated by component (e.g Models, Collections, Views, Routers). It’s useful to pay attention to the name of the test, the logic being tested and most importantly the assertions being made as this will give you some insight into how what we’ve learned can be applied to a complete application.

To get the most out of this section, I recommend grabbinghttps://github.com/addyosmani/backbone-koans-qunit – this is a port of the Backbone.js Jasmine Koans over to QUnit that I converted for this post.

In case you haven’t had a chance to try out one of the Koans kits as yet, they are a set of unit tests using a specific testing framework that both demonstrate how a set of specs for an application may be written, but also leave some tests unfilled so that you can complete them as an exercise.

Models

For our models we want to at minimum test that:

  • New instances can be created with the expected default values
  • Attributes can be set and retrieved correctly
  • Changes to state correctly fire off custom events where needed
  • Validation rules are correctly enforced
  1. module( “About Backbone.Model”);
  2. test(“Can be created with default values for its attributes.”, function() {
  3.     expect( 1 );
  4.     var todo = new Todo();
  5.     equal( todo.get(“text”), “” );
  6. });
  7. test(“Will set attributes on the model instance when created.”, function() {
  8.     expect( 3 );
  9.     var todo = new Todo( { text: “Get oil change for car.” } );
  10.     equal( todo.get(“text”), “Get oil change for car.” );
  11.     equal( todo.get(“done”), false );
  12.     equal( todo.get(“order”), 0 );
  13. });
  14. test(“Will call a custom initialize function on the model instance when created.”, function() {
  15.     expect( 1 );
  16.     var toot = new Todo({ text: “Stop monkeys from throwing their own crap!” });
  17.     equal( toot.get(“text”), “Stop monkeys from throwing their own rainbows!” );
  18. });
  19. test(“Fires a custom event when the state changes.”, function() {
  20.     expect( 1 );
  21.     var spy = this.spy();
  22.     var todo = new Todo();
  23.     todo.bind( “change”, spy );
  24.     // How would you update a property on the todo here?
  25.     // Hint: http://documentcloud.github.com/backbone/#Model-set
  26.     todo.set( { text: “new text” } );
  27.     ok( spy.calledOnce, “A change event callback was correctly triggered” );
  28. });
  29. test(“Can contain custom validation rules, and will trigger an error event on failed validation.”, function() {
  30.     expect( 3 );
  31.     var errorCallback = this.spy();
  32.     var todo = new Todo();
  33.     todo.bind(“error”, errorCallback);
  34.     // What would you need to set on the todo properties to cause validation to fail?
  35.     todo.set( { done: “not a boolean” } );
  36.     ok( errorCallback.called, “A failed validation correctly triggered an error” );
  37.     notEqual( errorCallback.getCall(0), undefined );
  38.     equal( errorCallback.getCall(0).args[1], “Todo.done must be a boolean value.” );
  39. });

Collections

For our collection we’ll want to test that:

  • New model instances can be added as both objects and arrays
  • Changes to models result in any necessary custom events being fired
  • url property for defining the URL structure for models is correctly defined
  1. module( “About Backbone.Collection”);
  2. test( “Can add Model instances as objects and arrays.”, function() {
  3.     expect( 3 );
  4.     var todos = new TodoList();
  5.     equal( todos.length, 0 );
  6.     todos.add( { text: “Clean the kitchen” } );
  7.     equal( todos.length, 1 );
  8.     todos.add([
  9.         { text: “Do the laundry”, done: true },
  10.         { text: “Go to the gym” }
  11.     ]);
  12.     equal( todos.length, 3 );
  13. });
  14. test( “Can have a url property to define the basic url structure for all contained models.”, function() {
  15.     expect( 1 );
  16.     var todos = new TodoList();
  17.     equal( todos.url, “/todos/” );
  18. });
  19. test(“Fires custom named events when the models change.”, function() {
  20.     expect(2);
  21.     var todos = new TodoList();
  22.     var addModelCallback = this.spy();
  23.     var removeModelCallback = this.spy();
  24.     todos.bind( “add”, addModelCallback );
  25.     todos.bind( “remove”, removeModelCallback );
  26.     // How would you get the “add” event to trigger?
  27.     todos.add( {text:”New todo”} );
  28.     ok( addModelCallback.called );
  29.     // How would you get the “remove” callback to trigger?
  30.     todos.remove( todos.last() );
  31.     ok( removeModelCallback.called );
  32. });

Views

For our views we want to ensure:

  • They are being correctly tied to a DOM element when created
  • They can render, after which the DOM representation of the view should be visible
  • They support wiring up view methods to DOM elements

One could also take this further and test that user interactions with the view correctly result in any models that need to be changed being updated correctly.

  1. module( “About Backbone.View”, {
  2.     setup: function() {
  3.         $(“body”).append(“<ul id=”todoList”></ul>”);
  4.         this.todoView = new TodoView({ model: new Todo() });
  5.     },
  6.     teardown: function() {
  7.         this.todoView.remove();
  8.         $(“#todoList”).remove();
  9.     }
  10. });
  11. test(“Should be tied to a DOM element when created, based off the property provided.”, function() {
  12.     expect( 1 );
  13.     equal( this.todoView.el.tagName.toLowerCase(), “li” );
  14. });
  15. test(“Is backed by a model instance, which provides the data.”, function() {
  16.     expect( 2 );
  17.     notEqual( this.todoView.model, undefined );
  18.     equal( this.todoView.model.get(“done”), false );
  19. });
  20. test(“Can render, after which the DOM representation of the view will be visible.”, function() {
  21.    this.todoView.render();
  22.     // Hint: render() just builds the DOM representation of the view, but doesn’t insert it into the DOM.
  23.     //       How would you append it to the ul#todoList?
  24.     //       How do you access the view’s DOM representation?
  25.     //
  26.     // Hint: http://documentcloud.github.com/backbone/#View-el
  27.     $(“ul#todoList”).append(this.todoView.el);
  28.     equal($(“#todoList”).find(“li”).length, 1);
  29. });
  30. asyncTest( “Can wire up view methods to DOM elements.” , function() {
  31.     expect( 2 );
  32.     var viewElt;
  33.     $(“#todoList”).append( this.todoView.render().el );
  34.     setTimeout(function() {
  35.         viewElt = $(“#todoList li input.check”).filter(“:first”);
  36.         equal( viewElt.length > 0, true);
  37.         // Make sure that QUnit knows we can continue
  38.         start();
  39.     }, 1000, “Expected DOM Elt to exist”);
  40.     // Hint: How would you trigger the view, via a DOM Event, to toggle the “done” status.
  41.     //       (See todos.js line 70, where the events hash is defined.)
  42.     //
  43.     // Hint: http://api.jquery.com/click
  44.     $(“#todoList li input.check”).click();
  45.     expect( this.todoView.model.get(“done”), true );
  46. });

Events

For events, we may want to test a few different use cases:

  • Extending plain objects to support custom events
  • Binding and triggering custom events on objects
  • Passing along arguments to callbacks when events are triggered
  • Binding a passed context to an event callback
  • Removing custom events

and a few others that will be detailed in our module below:

  1. module( “About Backbone.Events”, {
  2.     setup: function() {
  3.         this.obj = {};
  4.         _.extend( this.obj, Backbone.Events );
  5.         this.obj.unbind(); // remove all custom events before each spec is run.
  6.     }
  7. });
  8. test( “Can extend JavaScript objects to support custom events.”, function() {
  9.     expect( 3 );
  10.     var basicObject = {};
  11.     // How would you give basicObject these functions?
  12.     // Hint: http://documentcloud.github.com/backbone/#Events
  13.     _.extend( basicObject, Backbone.Events );
  14.     equal( typeof basicObject.bind, “function” );
  15.     equal( typeof basicObject.unbind, “function” );
  16.     equal( typeof basicObject.trigger, “function” );
  17. });
  18. test( “Allows us to bind and trigger custom named events on an object.”, function() {
  19.     expect( 1 );
  20.     var callback = this.spy();
  21.     this.obj.bind( “basic event”, callback );
  22.     this.obj.trigger( “basic event” );
  23.     // How would you cause the callback for this custom event to be called?
  24.     ok( callback.called );
  25. });
  26. test( “Also passes along any arguments to the callback when an event is triggered.”, function() {
  27.     expect( 1 );
  28.     var passedArgs = [];
  29.     this.obj.bind(“some event”, function() {
  30.             [].push.apply( passedArgs, arguments );
  31.     });
  32.     this.obj.trigger( “some event”, “arg1”, “arg2” );
  33.     deepEqual( passedArgs, [“arg1”, “arg2”] );
  34. });
  35. test( “Can also bind the passed context to the event callback.”, function() {
  36.     expect( 1 );
  37.     var foo = { color: “blue” };
  38.     var changeColor = function() {
  39.         this.color = “red”;
  40.     };
  41.     // How would you get “this.color” to refer to “foo” in the changeColor function?
  42.     this.obj.bind( “an event”, changeColor, foo );
  43.     this.obj.trigger( “an event” );
  44.     equal( foo.color, “red” );
  45. });
  46. test( “Uses “all” as a special event name to capture all events bound to the object.” , function() {
  47.     expect( 2 );
  48.     var callback = this.spy();
  49.     this.obj.bind( “all”, callback );
  50.     this.obj.trigger( “custom event 1” );
  51.     this.obj.trigger( “custom event 2” );
  52.     equal( callback.callCount, 2 );
  53.     equal( callback.getCall(0).args[0], “custom event 1” );
  54. });
  55. test( “Also can remove custom events from objects.”, function() {
  56.     expect( 5 );
  57.     var spy1 = this.spy();
  58.     var spy2 = this.spy();
  59.     var spy3 = this.spy();
  60.     this.obj.bind( “foo”, spy1 );
  61.     this.obj.bind( “bar”, spy1 );
  62.     this.obj.bind( “foo”, spy2 );
  63.     this.obj.bind( “foo”, spy3 );
  64.     // How do you unbind just a single callback for the event?
  65.     this.obj.unbind( “foo”, spy1 );
  66.     this.obj.trigger( “foo” );
  67.     ok( spy2.called );
  68.     // How do you unbind all callbacks tied to the event with a single method
  69.     this.obj.unbind( “foo” );
  70.     this.obj.trigger( “foo” );
  71.     ok( spy2.callCount, 1 );
  72.     ok( spy2.calledOnce, “Spy 2 called once” );
  73.     ok( spy3.calledOnce, “Spy 3 called once” );
  74.     // How do you unbind all callbacks and events tied to the object with a single method?
  75.     this.obj.unbind( “bar” );
  76.     this.obj.trigger( “bar” );
  77.     equal( spy1.callCount, 0 );
  78. });

App

It can also be useful to write specs for any application bootstrap you may have in place. For the following module, our setup initiates and appends a TodoApp view and we can test anything from local instances of views being correctly defined to application interactions correctly resulting in changes to instances of local collections.

  1. module( “About Backbone Applications” , {
  2.     setup: function() {
  3.         Backbone.localStorageDB = new Store(“testTodos”);
  4.         $(“#qunit-fixture”).append(“<div id=”app”></div>”);
  5.         this.App = new TodoApp({ appendTo: $(“#app”) });
  6.     },
  7.     teardown: function() {
  8.         $(“#app”).remove();
  9.     }
  10. });
  11. test( “Should bootstrap the application by initializing the Collection.”, function() {
  12.     expect( 2 );
  13.     notEqual( this.App.todos, undefined );
  14.     equal( this.App.todos.length, 0 );
  15. });
  16. test( “Should bind Collection events to View creation.” , function() {
  17.       $(“#new-todo”).val( “Foo” );
  18.       $(“#new-todo”).trigger(new $.Event( “keypress”, { keyCode: 13 } ));
  19.       equal( this.App.todos.length, 1 );
  20.  });

Further Reading & Resources

That’s it for this section on testing applications with QUnit and SinonJS. I encourage you to try out the QUnit Backbone.js Koans and see if you can extend some of the examples. For further reading consider looking at some of the additional resources below:

I hope this post was useful. I would like to thank the very clever Andrée Hansson and Sindre Sorhus for their technical reviews. Any corrections or feedback on the post is always welcome as I would like to ensure it’s as accurate as possible. Thanks!

 

Referenced by: http://addyosmani.com/blog/unit-testing-backbone-js-apps-with-qunit-and-sinonjs/

 
Leave a comment

Posted by on May 18, 2012 in Javascript, JQuery

 

How to Customize your Facebook Fan Box

With the addition of a facebook fan box to your website you’re not only benefiting your end users but also yourself. The fb fan box allows users to directly view how many friends you have on your facebook page and also allows them to become a fan with just one click. The only potential downsides to adding a fan box to your page is that it is not easy to customize or the original styling just doesn’t match up with the unique style of your site. Well not anymore, in this tutorial we are going to teach you how to customize your very own facebook fan box.

This tutorial will teach you step by step how to customize your facebook fan box to look like ours. After completing this tutorial you should be able to play around with the code and make modifications that you see fit to change the styling to your own needs.

4/29/10 – This tutorial has been updated to allow full customization of the Facebook Fan Box and positioning of the new “Like” button.

Setting Up Your Widget

Step 1 – Get Your Facebook Fan Box Code

First things first you need to get the code for your facebook fan box from facebook, your code should look something similar to the code below.

2 <script type="text/javascript">FB.init("1690883eb733618b294e98cb1dfba95a");</script>
3 <fb:fan profile_id="34572893685" stream="0" connections="10" logobar="0" width="300"></fb:fan>
4 <div style="font-size:8px; padding-left:10px"><a href="http://www.facebook.com/pages/North-Miami-FL/Daddy-Design/34572893685">Daddy Design</a> on Facebook</div>

facebook fan box default styling

Step 2 – Linking Your CSS

The second step is to set up the linking to your css code and adjusting your facebook fan box code to allow for the customization you’re about to start. The div associated at the end of the original fan box code is only a link back to your facebook page, we decided to remove it, however you may choose to leave it. Items that we have changed in our code are the width from 300 to 240 and connections from 10 to 8, your width and number of connections may change depending on the space available for your fan box. Items we have added are height at 200 (also subject to change) and the line of code to link to our css stylesheet. Please view the updated coded below.

2 <script type="text/javascript">FB.init("1690883eb733618b294e98cb1dfba95a");</script>
3 <fb:fan profile_id="34572893685" stream="0" connections="8" logobar="0" width="240" height="200" css="http://www.yoursite.com/stylesheet.css?1"></fb:fan>

One important item to take notice of is ‘?1’ which appears at the end of the css link, this item is the cache level for the facebook fan box, every time you make changes to the css inside your stylesheet and upload to your server you must change the number after the question mark to correspond with the number of edits you have made.

Here’s another handy tip, if you are using wordpress you can insert your code to look like the code below, this will link straight to your wordpress stylesheet. (Make sure you edit the ‘?1′ accordingly.)

css="<?php bloginfo('stylesheet_url'); ?>?1"

Styling Your Widget with CSS

Step 1 – Styling the Main Widget

The first step in customizing the css is to fix link hover issues and to remove any unneeded styling from the main widget. Check the first set of css modifications below.

1 .fan_box a:hover{
2   text-decorationnone;
3 }
4 .fan_box .full_widget{
5   height200px;
6   border0 !important;
7   backgroundnone !important;
8   positionrelative;
9 }

In lines 1 through 3 of the code we have removed the underline hover effect for all links inside the fan box to avoid any type of conflicts. In lines 4 through 9 of the code we have removed the border from around the full fan box widget, set the height to match our widget height, removed the background, and positioned it to allow for the moving of the “Like” button. One thing to keep notice of is the usage of ‘!important’, this is a css trick that will override the already used css code inside of the widget, anything that we change that currently has any values associated with it must use this code or else the original code will still take priority.

facebook fan box - step 1

Step 2 – Styling the Widget Header

The second step in customizing the css is to adjust the fan box header. Check the second set of css modifications below.

01 .fan_box .connect_top{
02   backgroundnone !important;
03   padding0 !important;
04 }
05 .fan_box .profileimage, .fan_box .name_block{
06   displaynone;
07 }
08 .fan_box .connect_action{
09   padding0 !important;
10 }

We are basically going to be getting rid of everything in the widget header except for the “Like” button, which we will position to the bottom of our widget later. In lines 1 through 4 we have gotten rid of the light blue background color for the header and removed all of the headers padding. In lines 5 through 7 we have completely removed both the main profile name and image. In lines 8 through 10 we have removed padding associated with the “Like” button that was not needed.

facebook fan box - step 2

Step 3 – Styling Fan Connections

The third step in customizing the css is to adjust the actual fb fan connections. Check the third set of css modifications below.

01 .fan_box .connections{
02   padding0 !important;
03   border0 !important;
04   font-familyArialHelveticasans-serif;
05   font-size11px;
06   font-weightbold;
07   color#666;
08 }
09 span.total{
10   color#FF6600;
11   font-weightbold;
12 }
13 .fan_box .connections .connections_grid {
14   padding-top10px !important;
15 }
16 .fan_box .connections_grid .grid_item{
17   padding0 10px 10px 0 !important;
18 }
19 .fan_box .connections_grid .grid_item .name{
20   font-family"lucida grande",tahoma,verdana,arial,sans-serif;
21   font-weightnormal;
22   color#666 !important;
23   padding-top1px !important;
24 }

In lines 1 through 8 of the code we adjusted the padding surrounding the fan box connections, removed the border at the top, and adjusted the font for the line of text that displays “X people like Profile Name”. In lines 9 through 12 of the code we have adjusted the color and font weight of the number of fans displayed. In lines 13 through 15 of the code we have adjusted the padding between the line of text and the actual fan connections. In lines 16 through 18 of the code we have adjusted the padding between the actual fan connections. In lines 19 through 24 of the code we have adjusted the actual fan name, make sure that you DO NOT change the font family, if changed it may cause alignment issues with the connections.

facebook fan box - step 3

Step 4 – Positioning the “Like” Button

The fourth and final step in customizing the css is to position the “Like” button. Check the fourth and final set of css modifications below.

01 .fan_box .connect_widget{
02 positionabsolute;
03 bottom0;
04 right10px;
05 margin0 !important;
06 }
07 .fan_box .connect_widget .connect_widget_interactive_area {
08 margin0 !important;
09 }
10 .fan_box .connect_widget td.connect_widget_vertical_center {
11 padding0 !important;
12 }

With the addition of this block of code the “Like” button will now appear at the bottom right of our fan box widget. How does this work? It works because earlier we used relative positioning on the main widget div in Step 3, whenever relative positioning is used on an element you can then use absolute positioning to position another element anywhere inside of the main element. The way to position the element is by using the attributes top, bottom, left, and right depending on where you want to move the element. In our situation we wanted it to be at the bottom right of our widget so we used the attribute bottom with a position of 0 and right with a position of 10px. The reason we used 10px for right instead of 0 is because we had added 10 pixels of right padding to each of our fan connections, this way the button and fan image will line up correctly. Lines 1 through 6 of the code are used to position the actual div to the bottom right of the widget. In lines 7 through 12 of the code we have removed padding and margin associated with the “Like” button and its surrounding table data so that it will align properly.

facebook fan box - step 4

Complete CSS Code

Below is all of the css code from the previous 4 steps combined together.

01 .fan_box a:hover{
02   text-decorationnone;
03 }
04 .fan_box .full_widget{
05   height200px;
06   border0 !important;
07   backgroundnone !important;
08   positionrelative;
09 }
10 .fan_box .connect_top{
11   backgroundnone !important;
12   padding0 !important;
13 }
14 .fan_box .profileimage, .fan_box .name_block{
15   displaynone;
16 }
17 .fan_box .connect_action{
18   padding0 !important;
19 }
20 .fan_box .connections{
21   padding0 !important;
22   border0 !important;
23   font-familyArialHelveticasans-serif;
24   font-size11px;
25   font-weightbold;
26   color#666;
27 }
28 span.total{
29   color#FF6600;
30   font-weightbold;
31 }
32 .fan_box .connections .connections_grid {
33   padding-top10px !important;
34 }
35 .fan_box .connections_grid .grid_item{
36   padding0 10px 10px 0 !important;
37 }
38 .fan_box .connections_grid .grid_item .name{
39   font-family"lucida grande",tahoma,verdana,arial,sans-serif;
40   font-weightnormal;
41   color#666 !important;
42   padding-top1px !important;
43 }
44 .fan_box .connect_widget{
45 positionabsolute;
46 bottom0;
47 right10px;
48 margin0 !important;
49 }
50 .fan_box .connect_widget .connect_widget_interactive_area {
51 margin0 !important;
52 }
53 .fan_box .connect_widget td.connect_widget_vertical_center {
54 padding0 !important;
55 }

Troubleshooting

If you are trying to edit the css and no changes are showing up, make sure you are adjusting the cache level at the end of the css link in the widget code.

If you are having problems getting this tutorial to work please reread the tutorial and try again, if you still can not get it to work please leave us a comment below and we will respond as soon as possible.

Note

4/20/10 – Facebook has currently just changed the “Become a Fan” button to the new “Like” button. We are awaiting any further changes to the Fan Box and once things appear to calm down we will update this tutorial. Keep checking back…

4/29/10 – This tutorial has been updated to allow full customization of the Facebook Fan Box and positioning of the new “Like” button.

 
Leave a comment

Posted by on May 16, 2012 in Facebook

 

How To Create a Cool Animated Menu with jQuery

In this tutorial we’ll be building a cool navigation list complete with a sliding hover effect. Learn how to build the concept in Photoshop, lay out the basic HTML elements, style everything up in CSS then tie it all together with a few lines of jQuery to create a semantic, accessible and degradable menu design.

 

View the animated menu demo

The design we’ll be building features a cool label image that slides into place under each navigation item on hover. We’ll build the design to work without jQuery first of all to ensure it’s widely accessible to users without Javascript enabled, then enhance the effect with jQuery for the majority of users.

View the animated menu demo

Build the Photoshop concept

Create a new document and fill the background with a light beige. Add a subtle 1.5% noise texture by going to Filter > Noise > Add Noise.

Use a subtle grunge Photoshop brush to add a little extra texture to the top centre of the canvas. Adjust the opacity to tone down the distressed effect.

Draw and fill a rectangle to create the base of the label graphic. Press CMD+T to transform the shape, then drag a guide to highlight the centre point.

Use the Polygonal Lasso tool to draw a small triangle. Use this triangle to clip out the bottom edges. Flip the selection horizontally and align with the guide to ensure the clipping is symmetrical.

Begin adding a range of Layer Style effects to bring the label to life. Start with a Gradient Overlay to add a range of dark to light red tones.

Add a thin stroke using a dark red colour selection with settings of 2px width and aligned to the inside.

Set up an Inner Glow using a slightly lighter red with 100% opacity, Normal blending mode, 50% Choke and 3px in size.

Add a soft Drop Shadow aligned to 90 degrees to give the impression of depth. Reduce the opacity to around 20% to tone down the effect.

Finish off the label with a distressed texture using the subtle grunge brushes. Load the selection of the label shape, inverse and delete out the excess. Change the blending mode to Lighter Color at 35%.

All the menu needs now is a series of text links. Set the fonts up with Helvetica Bold and choose a fill colour from the label. Simulate the hover effect by switching the fill to beige on the active link.

Make a selection of the label graphic and export the image as a PNG24 file with Alpha transparency.

The demo file uses just three images: A textured background image, the red label graphic and a repeating noise texture.

Create the basic HTML structure

View the HTML code

The basic menu system first needs to be laid out as a HTML skeleton. Begin the page with a Doctype, followed by page title and a link to the CSS stylesheet. Write out the menu itself as a good old Unordered List element, with each <li> item containing an anchor.

Style up the design with CSS

View the CSS code

Next, the CSS brings the design to life. Begin the CSS file with a quick reset to remove any default browser styling, then set up the surrounding page design by adding the repeating noise background texture to the page body. Centre up the <ul> with margin: auto; and text-align: center; and clear the element using overflow: hidden;.
Float each <li> item to the left to place each nav item side by side. The rest of the styling can then go directly onto the anchors. Each anchor needs to have the exact dimensions of the label graphic, taking into consideration any padding used to position the text into place. Replicate the font styling from Photoshop using the same bold Helvetica styling, and use the CSS3 text-shadow property to recreate the Photoshop Drop Shadow. Finally, add the label graphic as a background image and set the position to -149px so it is hidden off screen until the mouse hovers the nav item.
Set up the styling for the :hover effects by moving the background back into position and alter the colour of the font and shadow to ensure they can still be seen when the background colour changes.

A preview of the HTML file so far will show a fully working menu design, albeit with basic CSS styling where the label immediately appears and disappears without any cool sliding effects. It’s important to first develop this basic fall back so users without Javascript enabled will still see a hover effect.

Spice up the effect with jQuery

View the Javascript code

In order to add some fancy Javascript effects we first need to head back to the HTML file and link up some JS files. We’ll require three files: The jQuery library, a handy plugin allowing background position animation, and finally our own blank scripts.js file where we’ll write our own code.

View the jQuery code

The first thing to add to our jQuery code is a simple line to turn off the basic CSS effect. Adding a special ‘.js’ class to the anchor with Javascript allows us to add an extra line of CSS to overwrite the original styling. With this out of the way we can then style the actual sliding hover effect. Add a hover function to the anchors within the menu list. On hover, use .animate() to set thebackgroundPosition to 0 0, then back off screen on hover-out. A speed of 200 keeps things nice and swift. One extra snippet to add is a.stop(true,true) to prevent the effect looping if the mouse passes over the menu quickly.

View the extra jQuery code

A preview of the effect in the browser will show the label sliding in and out on hover. We can add one extra line to really spruce up the effect. Adding an extra animation to move the label by just 5px creates a cool little bounce effect. Similar effects can also be achieved using easing plugins, but to save linking up extra files this little trick works nicely.

The complete HTML, CSS & jQuery code

HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Animated Label Navigation Menu</title>

<link href="style.css" rel="stylesheet" type="text/css" media="screen" />

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js" type="text/javascript"></script>
<script src="js/animate-bg.js" type="text/javascript"></script>
<script src="js/scripts.js" type="text/javascript"></script>
</head>

<body>

<div id="container">
	<ul id="nav">
		<li><a href="#">Home</a></li>
		<li><a href="#">About</a></li>
		<li><a href="#">Work</a></li>
		<li><a href="#">Contact</a></li>
	</ul>
</div>

</body>
</html>

CSS

body, div, h1, h2, h3, h4, h5, h6, p, ul, ol, li, dl, dt, dd, img, form, fieldset, input, textarea, blockquote {
	margin: 0; padding: 0; border: 0;
}

body {
	background: #f5f0e0 url(images/noise.png);
}

#container {
	height: 800px;
	background: url(images/bg.jpg) center top no-repeat;
}

ul#nav {
	width: 700px; margin: 0 auto; text-align: center; overflow: hidden;
}
	ul#nav li {
		float: left; list-style: none;
	}
		ul#nav li a {
			display: block; width: 97px; height: 77px;
			padding: 72px 0 0 0; margin: 0 32px 0 32px;
			font: bold 16px Helvetica, Arial, Sans-Serif; text-transform: uppercase;
			color: #9c5959; text-shadow: 0 1px 3px #c4bda6; text-decoration: none;

			background: url(images/label.png) 0 -149px no-repeat;
		}
			ul#nav li a:hover {
				background: url(images/label.png) 0 0 no-repeat;
				color: #eee9d9; text-shadow: 0 2px 3px #4c2222;
			}

			ul#nav li a.js:hover {
				background: url(images/label.png) 0 -149px no-repeat;
			}

jQuery

$(document).ready(function() {
	$("ul#nav li a").addClass("js");
	$("ul#nav li a").hover(
      function () {
        $(this).stop(true,true).animate({backgroundPosition:"(0 0)"}, 200);
        $(this).animate({backgroundPosition:"(0 -5px)"}, 150);
      },
      function () {
        $(this).animate({backgroundPosition:"(0 -149px)"}, 200);

      }
    );

});

The final animated menu design

View the animated menu demo

View the animated menu demo

 
Leave a comment

Posted by on May 16, 2012 in Facebook

 

postcard from Paris – css3 keyframes animations in use

I decided to explore the area of css3 keyframes animations. The idea was simple – to create a sort of virtual postcard. I live in Paris so obviously I send you my greetings from Paris :). Click here or on the image to view the animation demo.
Postcard from Paris css3 reframes animation preview

Download the source files

(.psd file included)
Postcard from Paris
.zip 1.9MB

The css3 animations are supported by : Chrome 2+, Safari 4+, Firefox 5+, iOS Safari 3.2+ and
Android 2.1+ (source Smashing Magazine).
We are going to animate 3 elements : the clouds (there are three layers of clouds), the rotating phare light and the Eiffel Tower sparkling.

The html structure is very simple :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Greetings from Paris</title>
</head>
<body>
   <div id="wrap">
      <h1>Bonne Nuit <em>PARIS !</em></h1>
      <div id="phare"></div>
      <div id="eiffel"></div>
      <div id="eiffel_wrap">
         <div id="sparkling1"></div>
         <div id="sparkling2"></div>
      </div>
      <div id="roofs"></div>
      <footer>by PeHaa, Paris 2011</footer>
   </div>
</body>
</html>

We will use the following images (I will discuss the sparkling effect a little bit later)
used images
Let’s start to complete the css stylesheet :
ccs part 1

Animating clouds

To animate the three layers of clouds independently we use the following keyframes. (Notice that each time I use the -webkit- and -moz- prefixes).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* will be applied to #wrap that has 3 backgrounds layers */
    @-webkit-keyframes wind  {
             0% {background-position: 0px 200px,0px 350px, left top;}
            50% {background-position500px 40px,600px 450px, left top;}
            100% {background-position: 1000px 200px,1200px 350px, left top}
    }
    @-moz-keyframes wind  {
             0% {background-position: 0px 200px,0px 350px, left top;}
            50% {background-position500px 40px,600px 450px, left top;}
            100% {background-position: 1000px 200px,1200px 350px, left top}
    }
/* will be applied to #roofs that has 2 backgrounds layers */
    @-webkit-keyframes wind1 {
             0% {background-position: 100px 250px, left bottom;}
            50% {background-position650px 150px, left bottom;}
            100% {background-position: 1300px 250px, left bottom}
    }
    @-moz-keyframes wind1 {
             0% {background-position: 100px 250px, left bottom;}
            50% {background-position650px 150px, left bottom;}
            100% {background-position: 1300px 250px, left bottom}
    }

This way we have defined the property of background-position for the beginning, middle and end of our animation. Next we add :

1
2
3
4
#wrap {-webkit-animation: wind 80s linear infinite;
       -moz-animation: wind 80s linear infinite;}
#roofs {-webkit-animation: wind 80s linear infinite;
       -moz-animation: wind 80s linear infinite; }

to associate the animations with the proper elements and to define the duration, timing-function and iteration count, respectively (I use the shorthand notation).

Animating phare light

This time we are going to simultaneously animate the opacity and rotate the phare light with the rotation origin in its top center point (as in the image above).

1
2
3
4
5
6
7
@-webkit-keyframes phare {
         0% { -webkit-transform:rotate(0deg); opacity:0}
    50% { -webkit-transform:rotate(180deg); opacity:1}
        100% { -webkit-transform:rotate(360deg); opacity:0;}
}
    #phare {-webkit-transform-origin: center top;
        -webkit-animation: phare 15s linear infinite;}

(here and further, repeat the same with -moz- prefixes).

Adding sparkles

We will use two different images with sparkling effect
Sparkling
Below is the styling :

1
2
3
4
5
6
#eiffel_wrap { position:absolute; width:240px;
              height:462px; right:10px; top: 180px; opacity:0;}
#sparkling1 { position:absolute; background: url('images/sparkling1.png') no-repeat;
              width:240px; height:462px; opacity:0;}
#sparkling2 { position:absolute; background: url('images/sparkling2.png') no-repeat;
              width:240px; height:462px;  opacity:0;}

We will animate the #eiffel_wrap#sparkling1 and #sparkling2.

1
2
3
4
5
@-webkit-keyframes sparkling {
        0% {opacity:0;}
        50%{opacity:1;}
        100% {opacity:0;}
    }

The idea is to use the sparkling animation to turn out and in the #sparkling1 and #sparkling2 elements within the 0.4s cycle, with the first in/out when the second is out/in. To achieve that we will delay the sparkling animation of 0.2s on #sparkling1.

1
2
3
>
#sparkling1 {-webkit-animation: sparkling .4s .2s  infinite;}
#sparkling2 {-webkit-animation: sparkling .4s  infinite;}

In Paris this beautiful evening spectacle may be seen for several minutes every full hour. We will use the#eiffel_wrap element and eiffel_wrap animation to recreate this effect (not literarily though – I will not make you wait an hour long).

1
2
3
4
5
6
#eiffel_wrap { -webkit-animation: eiffel_wrap 30s 1s  infinite;}
@-webkit-keyframes eiffel_wrap {
            0% {opacity:1;-webkit-animation-timing-function: steps(1);}
            40%{opacity:0;}
            100% {opacity:0;}
            }

With -webkit-animation-timing-function: steps(1); the transition is instantaneous with no fading out effect.

And here we are.
I hope you found this tutorial useful and got inspired. Please share and bookmark if you like it.
As always I’m looking forward to your comments and… see you in Paris !

 
Leave a comment

Posted by on May 16, 2012 in CS Style

 

How to Create a Custom Facebook Share Button for your iFrame Tab

A common feature of Facebook is the use of being able to ‘Share’ objects whether these objects are videos or links. If you’re anything like us then you like to have full control over what and how you share it, this proved rather difficult until now. In this tutorial we are going to show you, in two easy steps, how to create a custom Facebook ‘Share’ button to use on your Facebook iFrame tab that will allow viewers to share and post your custom content to their Wall. The difference between this ‘Share’ button and the standard ‘Share’ button is that every element (custom message, custom title and custom thumb image) within the share window is completely customizable, giving you total control over what you want to share.

The Code

Step 1: PHP

<source lan=’java’>
<?php
$title=urlencode('Title of Your iFrame Tab');
$url=urlencode('http://www.facebook.com/wordpressdesign');
$summary=urlencode('Custom message that summarizes what your tab is about, or just a simple message to tell people to check out your tab.');
$image=urlencode('http://www.yourdomain.com/images/share-thumbnail.jpg');
?>
</source>

Each line within the PHP allows you customize every element within the share window. Every bit of coding within the “(‘…‘)” that you see effects those elements. To understand which PHP element affects what, take a look at the screenshot below:
fb share gragh
Keep note that the $url section must contain a URL. This directs people to your tab once the share has been published on the poster’s wall. Also, the $image must contain a full URL. If your link to the image is “images/share-thumbnail.jpg”, it will not be read correctly because the share window is coming from Facebook’s server, not yours. As for the size of your thumbnail image ($image), it will automatically be proportionately resized to fit either 100px wide or 100px tall (depending which measurement is larger of the original image). So ideally, you should make your thumbnail 100px X 100px to prevent unwanted resizing.

Step 2: XHTML

<source lan=’java’>
<a onClick="window.open('http://www.facebook.com/sharer.php?s=100&amp;p[title]=<?php echo $title;?>&amp;p[summary]=<?php echo $summary;?>&amp;p[url]=<?php echo $url; ?>&amp;&amp;p[images][0]=<?php echo $image;?>','sharer','toolbar=0,status=0,width=548,height=325');" href="javascript: void(0)">Insert text or an image here.</a>
</source>

As you can see, the onClick=”window.open(‘…’);” will create a popup window that contains the ‘Share’ information (see picture above). Do not change this information. The only bits of coding you need to change are the width and the height of the code (if you are not satisfied with the measurements). These measurements define the width and height of the popup window containing the “Share” information.

The other bit of coding you can change is where it says; “Insert text or an image here”. This is where you can insert whatever element you choose to become the link. This can simply be text or a fancy button that you created yourself. The choice is up to you!

Completed Code

<source lan=’java’>
<?php
$title=urlencode('Title of Your iFrame Tab');
$url=urlencode('http://www.facebook.com/wordpressdesign');
$summary=urlencode('Custom message that summarizes what your tab is about, or just a simple message to tell people to check out your tab.');
$image=urlencode('http://www.yourdomain.com/images/share-thumbnail.jpg');
?>

<a onClick="window.open('http://www.facebook.com/sharer.php?s=100&amp;p[title]=<?php echo $title;?>&amp;p[summary]=<?php echo $summary;?>&amp;p[url]=<?php echo $url; ?>&amp;&amp;p[images][0]=<?php echo $image;?>','sharer','toolbar=0,status=0,width=548,height=325');" href="javascript: void(0)">Insert text or an image here.</a>
</source>

Demo

You can view the live demo here.
Download the code here.

Please Note

Your iFrame tab must be a PHP file in order for this to work.

Troubleshooting

If you are having problems getting this tutorial to work please reread the tutorial and try again, if you still cannot get it to work please leave us a comment below and we will respond as soon as possible.

 
Leave a comment

Posted by on May 16, 2012 in PHP

 

How to create slick effects with CSS3 box-shadow

Drop shadows and inner shadows are some of the effects I learned to apply using Photoshop’s Blending options. But now, since CSS3 “hit the charts”, you don’t need Adobe’s design tool to add a drop shadow or an inner shadow to a box.

Nowadays, the cool thing is that you create beautiful CSS3 shadows without actually needing Photoshop anymore.

View demo

box-shadow property

The box-shadow property allows you to add multiple shadows (outer or inner) on box elements. To do that you must specify values as: color, size, blur and offset.

<shadow> = inset? && [ <length>{2,4} && <color>? ]

Rocket science?

Not at all, here’s an quick example:

box-shadow: 3px 3px 10px 5px #000;

This CSS declaration will generate the following shadow:

  • A positive value for the horizontal offset draws a shadow that is offset to the right of the box, a negative
    length to the left.
  • The second length is the vertical offset. A positive value for the vertical offset basically offsets the
    shadow down, a negative one up.
  • You’re not allowed to use negative values for blur radius. The larger
    the value, the more the shadow’s edge is blurred, as it can be seen above.
  • Spread distance positive values cause the
    shadow shape to expand in all directions by the specified radius.
    Negative ones cause the shadow shape to contract.
  • The color is the color of the shadow.
  • The inset keyword (missing above), if present,
    changes the drop shadow from an outer shadow to an inner
    shadow

The above theory it’s just a small amount, if you want to read more, than be my guest and check the W3C specs.

Enough theory, let’s see some stuff!

Now let’s see how can you take advantage of this wonderful CSS3 feature. Below I’ll show you how to enhance your designs with the coolest box-shadow techniques!

Add depth to your body

Reference URL

body:before
{
   content: "";
   position: fixed;
   top: -10px;
   left: 0;
   width: 100%;
   height: 10px;
   z-index: 100;
   -webkit-box-shadow: 0px 0px 10px rgba(0,0,0,.8);
   -moz-box-shadow: 0px 0px 10px rgba(0,0,0,.8);
   box-shadow: 0px 0px 10px rgba(0,0,0,.8);
   }

Drop shadows

Here are the articles that inspired me, and not only:

#box
{
  position: relative;
  width: 60%;
  background: #ddd;
  -moz-border-radius: 4px;
  border-radius: 4px;
  padding: 2em 1.5em;
  color: rgba(0,0,0, .8);
  text-shadow: 0 1px 0 #fff;
  line-height: 1.5;
  margin: 60px auto;
}

#box:before, #box:after
{
  z-index: -1;
  position: absolute;
  content: "";
  bottom: 15px;
  left: 10px;
  width: 50%;
  top: 80%;
  max-width:300px;
  background: rgba(0, 0, 0, 0.7);
  -webkit-box-shadow: 0 15px 10px rgba(0,0,0, 0.7);
  -moz-box-shadow: 0 15px 10px rgba(0, 0, 0, 0.7);
  box-shadow: 0 15px 10px rgba(0, 0, 0, 0.7);
  -webkit-transform: rotate(-3deg);
  -moz-transform: rotate(-3deg);
  -o-transform: rotate(-3deg);
  -ms-transform: rotate(-3deg);
  transform: rotate(-3deg);
}

#box:after
{
  -webkit-transform: rotate(3deg);
  -moz-transform: rotate(3deg);
  -o-transform: rotate(3deg);
  -ms-transform: rotate(3deg);
  transform: rotate(3deg);
  right: 10px;
  left: auto;
}

Quick tips

Try spicing up shadows with RGBa color. The box-shadow property can be used using CSS3 RGBa colors to create shadows with differing levels of opacity. If your browsers supports thebox-shadow property, then it will definitively support the RGBa color mode.

Use multiple shadows in one CSS declaration:

  box-shadow: 3px 3px 10px 5px #000, 0 0 4px rgba(0, 0, 0, .5) inset;

Browser Support

  • Internet Explorer 9/10
  • Firefox (from 3.5)
  • Safari/Chrome
  • Opera (from 10.5)
 
Leave a comment

Posted by on May 16, 2012 in CS Style