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/

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.

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

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 !

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.

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)

Photoshop Tutorial How to Create a Lightning

Photoshop Tutorial How to Create a Lightning

This Photoshop tutorial go through some really basic and important Photoshop techniques while showing you how to create a fearsome lightning bolt from scratch. You will be using Filters, Adjustment Layers and much more  to create the lightning effect.

Step 1: Create Lightning

a) Create a new document e.g. 600x600px

b) Create a new layer and name it Lightning

image

c)Open the Gradient editor (Type G and click on the gradient in the top left corner) and create a black and white gradient with a narrow gray area as shown below:

Gradient

d) Paint the document with a linear gradient. The more narrow the grey area is the more clean the lightning will be so don’t make it too narrow.

image

e) Next make sure you have selected black as foreground and white as background

image

Then goto Filter > Render > Difference Clouds. Feel free to undo and redo to get the lightning effect you want:

image

f) Notice the main black line through the middle. This will be your lightning bolt. But to isolate it, you first invert (Image > Adjustments > Invert or Ctrl+I) it:

image

f) Add a new Adjustment layer with levels. You could also apply the levels directly but really in this tutorial you may need the flexibility later to fix the levels

image

g) You should adjust the levels to increase the intensity of the lightning.

image

Step 2 Add Color

a) Create a new layer and paint it with a blue gradient

blue gradient

b) Set the blending mode to overlay

image

c) Create another layer and call it Red Light. Then set the layer blending mode to soft light. Select a soft, big round brush and paint some lights with  a red, yellow and/or a violet color

image

d) If you want to intensify the lightning even further I recommend you add an adjustment layer for Curves and Hue/Saturation. Set the Curves first. Individual settings for your setup may be needed.

image

Than only adjust the Lightning a bit down in the Hue/Saturation layer

image

The Result – Lightning Created in Photoshop

image

Embroidery Effect with Illustrator and Photoshop

I have received quite a few emails asking me how to create a embroidery effect in Photoshop. It is a really nice effect and I had no idea how to do that in Photoshop. So one of these days while running I sort of had this idea of using the Scribble effect in Illustrator and then going to Photoshop to make it look real. After giving it a try I got a very nice result and that is what I share with you today.

So for this tutorial I will show you how to create a embroidery effect using Illustrator and Photoshop. The whole process is quite simple and it will take an average of 45 minutes to get it done.

Step 1

Open the logo or shape you want to apply the effect in Illustrator. In my case I am using the Abduzeedo logo, the 2011 version.

Embroidery Effect with Illustrator and Photoshop

Step 2

Select the shapes and go to Effect>Stylize>Scribble. The Scribble Options will open and you will be able to customize the settings. The Abduzeedo logo has a sort of 3D effect, so I used different angles for the Scribble direction.

Embroidery Effect with Illustrator and Photoshop

Step 3

Now it’s time to go to Photoshop. The first thing to do here is to find a really cool texture. The one I am using is courtesy of Shutterstock and you can find it at http://goo.gl/PNAHF

Place the texture in your design. Again, the texture is really important to make your design look real.

Embroidery Effect with Illustrator and Photoshop

Step 4

Copy the logo from Illustrator and paste it in Photoshop. I aligned it in the center of my canvas.

Embroidery Effect with Illustrator and Photoshop

Step 5

Go to Layer>Layer Styles>Inner Shadow. For the Blend Mode use Color Dodge with white for the color at 45% Opacity. For the Angle use 90º, 3 pixels for the Distance, 0% Opacity and 3 pixels for the Size. Also for the Contour use the one I used in the image below.

Embroidery Effect with Illustrator and Photoshop

Step 6

Select Inner Glow. For the Blend Mode use Linear Burn with black for the color at 40% Opacity and 0% Noise. Change the Size to 8 pixels and keep the rest as it is.

Embroidery Effect with Illustrator and Photoshop

Step 7

Duplicate the layer once and move it up a few pixels and to any size a few pixels as well.

Embroidery Effect with Illustrator and Photoshop

Step 8

Duplicate the layer a few more times and move it to the sides and up and down. The idea is make it look less uniform. After that select all layers and merge them (Layer>Merge Layers)

Embroidery Effect with Illustrator and Photoshop

Step 9

Go to Layer>Layer Styles>Drop Shadow. Use black for the color with Color Burn for the Blend Mode and 50% Opacity. For the Angle use 120º, for the Distance keep 0, for the Spread use 0% and for the Size use 15px.

Embroidery Effect with Illustrator and Photoshop

Step 10

Select Inner Glow and then for the Blend Mode use Color Dodge at 50%, white for the color, Center for the Source, 0 for the Choke and 40 pixels for the Size.

Embroidery Effect with Illustrator and Photoshop

Step 11

This is the result after the layer styles. The whole idea is to create the highlight and the depth that we always see on the embroidery effects.

Embroidery Effect with Illustrator and Photoshop

Step 12

Here I added the Abduzeedo word with the custom font with the same effect. Just repeated the previous steps.

Embroidery Effect with Illustrator and Photoshop

Step 13

Select all layers and duplicate them. After that go to Layer>Merge Layers. You can use the keyboard shortcut for that Command (mac)/Control (pc) + Shit + Alt + E. Then go to Filter>Blur>Gaussian Blur. Change the Blend Mode to Screen.

Embroidery Effect with Illustrator and Photoshop

Conclusion

Go to Layer>Layer Mask>Hide all then with the Brush Tool (B) and a very soft brush with white start painting in the center to make that area visible.

As you can see the technique is pretty simple, it’s all about some layer styles and the Scribble effect in Illustrator. There’s also another ways to do that, like with custom brushes, but I think the scribble filter does a really good job for a quick result with nice realism.

Embroidery Effect with Illustrator and Photoshop

Download the Photoshop File

Click here to download the Photoshop file used for this tutorial

About the author

Abduzeedo is a blog about design. There are all sorts of articles for those who want to look for inspiration. Also you will find very useful tutorials for the most used applications out there, with a special selection of Photoshop Tutorials and Illustrator Tutorials. You can get in follow us via Twitter at@abduzeedo

Create a Settings Page For Your WordPress Theme

Creating your own theme for WordPress is a great way to give your blog or other WordPress powered web site an original touch. But even the nicest looking theme is not that nice if you have to get under the hood and edit the theme’s HTML or PHP code whenever it’s time change some aspects of it. Especially, when it’s not you but a paying customer using your theme. Luckily, creating a settings page for your theme in WordPress is not very hard, and after reading this tutorial, you will be able to create one in no time!

 


Step 1 Deciding What Settings Are Needed

It all starts from the need: to create a clear and useful settings page, you have to figure out the things that will need to be changed and leave out everything else. Every new setting you add to the admin menus adds complexity to the user interface and risks making the theme harder to use. That’s why it’s better to be careful and handpick the options that are going to be changed often and leave out one time customizations that can easily be done changing one file inside the theme.

Another question to keep in mind is “Who is going to be changing these settings?” If the user is familiar with PHP and WordPress, it might be reasonable to expect that she is OK with embedding her Google Analytics code in the code herself, but you shouldn’t require that from a graphic designer, not to mention a writer who doesn’t even need to know anything about HTML and CSS.

Common ideas for things to define in theme settings include:

  • The site’s Google Analytics tracking code
  • The number of sidebars and their positioning (left, right, maybe even up and down)
  • Page width
  • The contents of your footer
  • Options for features that are specific to the theme, such as custom teaser formats.

Once you have collected the list of theme features that you’d like to control through a settings page, you are almost ready to start the implementation. Before you move on and create your settings page, you can save time by making sure that there isn’t a WordPress feature already available for the customization you have in mind. Widgets, custom menus, custom backgrounds and header images are all useful tools for making your theme customizable with a lot less work than required for creating your own settings. They are, however, topics for a different tutorial.

Settings Created in This Tutorial

For this tutorial, I dreamed up a theme front page that consists of a grid with a varying number of featured posts that can be picked, edited and reordered by the admin using a custom settings page.

In the editor, the front page elements will be presented as a list of elements to which new ones can be added using JavaScript and jQuery.

I like to be able to preview the admin page in the WordPress admin as I design the HTML, so I usually start by linking a settings page to WordPress, and only then move to designing the contents of the page. That’s why, our next step is creating a placeholder settings page and hooking it to WordPress.


Step 2 Hooking the Settings Page to WordPress

Creating a settings page starts by creating a function that sets up the menu and hooking it to the WordPress action admin_menu. This tells WordPress to call your function when its time to create the menus so that everything is done at its proper time. Add this code to your theme’s functions.php file:

  1. function setup_theme_admin_menus() {
  2.     // We will write the function contents very soon.
  3. }
  4. // This tells WordPress to call the function named “setup_theme_admin_menus”
  5. // when it’s time to create the menu pages.
  6. add_action(“admin_menu”, “setup_theme_admin_menus”);

We’ll now put the code for creating the settings pages inside the function we just created.

When creating your settings page, you have the choice of either adding the page as a submenu to one of the existing settings groups or of creating your own top level menu.

Adding a submenu is done with the function add_submenu_page:

  1. <?php add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function) ?>
  • $parent_slug is a unique identifier for the top menu page to which this submenu is added as a child.
  • $page_title is the title of the page to be added
  • $menu_title is the title shown in the menu (often a shorter version of $page_title
  • $capability is the minimum capability required from a user in order to have access to this menu.
  • $menu_slug is a unique identifier for the menu being created
  • $function is the name of a function that is called to handle (and render) this menu page

If you choose to add the menu page as a submenu to one of the WordPress groups, you can use the following values as the $parent_slug parameter:

  • Dashboard: index.php
  • Posts: edit.php
  • Media: upload.php
  • Links: link-manager.php
  • Pages: edit.php?post_type=page
  • Comments: edit-comments.php
  • Appearance: themes.php
  • Plugins: plugins.php
  • Users: users.php
  • Tools: tools.php
  • Settings: options-general.php

The Appearance group looks like a good candidate for placing our settings page. Let’s try that, and create our first settings page. Here’s an updated version of our menu setup function:

  1. function setup_theme_admin_menus() {
  2.     add_submenu_page(‘themes.php’,
  3.         ‘Front Page Elements’, ‘Front Page’, ‘manage_options’,
  4.         ‘front-page-elements’, ‘theme_front_page_settings’);
  5. }

We still need to create the function theme_front_page_settings for this to work. Here it is in its simplest form:

  1. function theme_front_page_settings() {
  2.     echo “Hello, world!”;
  3. }

And this is how it looks in action:

We also need to check that the user has the rights required for editing the settings page. To do that, add the following code at the beginning of the settings page function:

  1. // Check that the user is allowed to update options
  2. if (!current_user_can(‘manage_options’)) {
  3.     wp_die(‘You do not have sufficient permissions to access this page.’);
  4. }

Now, if a user who isn’t allowed to manage options comes to the settings page, she will see nothing but the message, “You do not have sufficient permissions to access this page.”

If your theme needs multiple settings pages, it can be confusing for the user to look for them scattered all around the menu structure. In that case, creating your own settings group makes it easier for the theme user to find all the menu pages for the theme.

To add your own settings group, you need to create a top level menu page and link the submenu pages to it. Here is a new version of our menu setup function. The add_menu_page function used to create the top level menu is similar to add_submenu_page except that it doesn’t take the $parent_slug parameter.

  1. function setup_theme_admin_menus() {
  2.     add_menu_page(‘Theme settings’, ‘Example theme’, ‘manage_options’,
  3.         ‘tut_theme_settings’, ‘theme_settings_page’);
  4.     add_submenu_page(‘tut_theme_settings’,
  5.         ‘Front Page Elements’, ‘Front Page’, ‘manage_options’,
  6.         ‘front-page-elements’, ‘theme_front_page_settings’);
  7. }
  8. // We also need to add the handler function for the top level menu
  9. function theme_settings_page() {
  10.     echo “Settings page”;
  11. }

If you test the code and refresh the WordPress admin, you’ll see your new menu group appear at the bottom of the menu list:

But something doesn’t look quite right yet. Clicking the top menu element doesn’t lead you to the “Front Page” menu but a menu page called “Example theme.” This is not consistent with how the other WordPress menus function, so let’s do one more thing: by changing the $menu_slug attribute in theadd_submenu_page call to the same value as in the top level menu, we can link the two menus so that selecting the top menu selects the front page menu:

  1. function setup_theme_admin_menus() {
  2.     add_menu_page(‘Theme settings’, ‘Example theme’, ‘manage_options’,
  3.         ‘tut_theme_settings’, ‘theme_settings_page’);
  4.     add_submenu_page(‘tut_theme_settings’,
  5.         ‘Front Page Elements’, ‘Front Page’, ‘manage_options’,
  6.         ‘tut_theme_settings’, ‘theme_front_page_settings’);
  7. }
  8. function theme_settings_page() {
  9. }

Looks better. If you want to still improve the looks of your menu group, there are two optional fields in theadd_menu_page function that you will find useful. Just add the values after the function name in the method call:

  • $icon_url specifies the URL of an icon for the top level menu.
  • $position specifies the position of your menu group in the menu list. The higher the value, the lower the position in the menu.

Step 3 Creating the HTML Form For the Settings Pages

Now that we have created the settings page, and it shows up nicely in the side menu, it’s time to start adding some content. So, let’s go back to the list of settings we had in mind, and draft a page for editing them.

In this tutorial, we need a field for defining how many elements should be listed on one row, and a list for defining the actual elements. To start from the easier, let’s create a text field for the number of elements on one row. Edit your settings page function:

  1. function theme_front_page_settings() {
  2. ?>
  3.     <label for=”num_elements”>
  4.         Number of elements on a row:
  5.     </label>
  6.     <input type=”text” name=”num_elements” />
  7. <?php
  8. }

When you reload your settings page, you’ll see the first settings field appear:

To make the settings page fit seamlessly in the WordPress experience and to give your plugin a professional touch, it’s a best practice to use the CSS classes and styles that WordPress uses in its own settings pages. A good way to learn the tricks is to just go ahead and analyze the WordPress source code.

The most important thing is to wrap your setting page with a div with the class "wrap". Within that divelement, you can use many predefined styles such as headings, buttons, and form fields. Let’s start by styling the title of our settings page:

  • We will create a h2 heading for the page (You can use the heading tags from h2 to h6 to create headings with different sizes.)
  • We will show the theme settings page icon before the heading. (You can use the predefined WordPress icons with the screen_icon function. The function can take one of the following parameters: indexedituploadlink-managerpagescommentsthemespluginsusers,tools or options-general.)
  • We will put the input element inside a form and a table with the class form-table.
  1. function theme_front_page_settings() {
  2. ?>
  3.     <div class=”wrap”>
  4.         <?php screen_icon(‘themes’); ?> <h2>Front page elements</h2>
  5.         <form method=”POST” action=””>
  6.             <table class=”form-table”>
  7.                 <tr valign=”top”>
  8.                     <th scope=”row”>
  9.                         <label for=”num_elements”>
  10.                             Number of elements on a row:
  11.                         </label>
  12.                     </th>
  13.                     <td>
  14.                         <input type=”text” name=”num_elements” size=”25″ />
  15.                     </td>
  16.                 </tr>
  17.             </table>
  18.         </form>
  19.     </div>
  20. <?php
  21. }

Next, it’s time to start adding the elements.

To do this, we’ll use jQuery as it makes things much easier than writing JavaScript by from scratch, and comes bundled with WordPress. If you have used jQuery before, there is just one thing to keep in mind: the$ notation that you would normally use with jQuery doesn’t work in WordPress — you have to type the whole word, jQuery instead.

First, we’ll create the element for editing the settings for one main page block to serve as a template for the elements that are added by the user. Add this code right between the closing table tag and the closing form tag right after it.

  1. <?php $posts = get_posts(); ?>
  2. <li class=”front-page-element” id=”front-page-element-placeholder”>
  3.     <label for=”element-page-id”>Featured post:</label>
  4.     <select name=”element-page-id”>
  5.         <?php foreach ($posts as $post) : ?>
  6.             <option value=”<?php echo $post-<ID; ?>”>
  7.                 <?php echo $post-<post_title; ?>
  8.             </option>
  9.         <?php endforeach; ?>
  10.     </select>
  11.     <a href=”#”>Remove</a>
  12. </li>

Now, it looks like this:

Now that we have our template, it’s time to hide it and create the JavaScript for using it to create new featured post rows to the settings page. Set the style for the li element above to display:none;

  1. <li class=”front-page-element” id=”front-page-element-placeholder” style=”display:none”>

Then, we’ll create a list for holding the front page elements as they are added, and a link that the user will click to add the new elements. I’m repeating the entire HTML so that you can clearly see where the changes go:

  1. <div class=”wrap”>
  2.     <?php screen_icon(‘themes’); ?> <h2>Front page elements</h2>
  3.     <form method=”POST” action=””>
  4.         <table class=”form-table”>
  5.             <tr valign=”top”>
  6.                 <th scope=”row”>
  7.                     <label for=”num_elements”>
  8.                         Number of elements on a row:
  9.                     </label>
  10.                 </th>
  11.                 <td>
  12.                     <input type=”text” name=”num_elements” size=”25″ />
  13.                 </td>
  14.             </tr>
  15.         </table>
  16.         <h3>Featured posts</h3>
  17.         <ul id=”featured-posts-list”>
  18.         </ul>
  19.         <input type=”hidden” name=”element-max-id” />
  20.         <a href=”#” id=”add-featured-post”>Add featured post</a>
  21.     </form>
  22.     <li class=”front-page-element” id=”front-page-element-placeholder”
  23.         style=”display:none;”>
  24.         <label for=”element-page-id”>Featured post:</label>
  25.         <select name=”element-page-id”>
  26.             <?php foreach ($posts as $post) : ?>
  27.                 <option value=”<?php echo $post->ID; ?>”>
  28.                     <?php echo $post->post_title; ?>
  29.                 </option>
  30.             <?php endforeach; ?>
  31.         </select>
  32.         <a href=”#”>Remove</a>
  33.     </li>
  34. </div>

In a real-life theme it’s a good practice to put your JavaScript code in a separate file, but to make this tutorial a bit easier to follow, I am now adding the JavaScript in the same function with the HTML above, right before the wrap div:

  1. <script type=”text/javascript”>
  2.     var elementCounter = 0;
  3.     jQuery(document).ready(function() {
  4.         jQuery(“#add-featured-post”).click(function() {
  5.             var elementRow = jQuery(“#front-page-element-placeholder”).clone();
  6.             var newId = “front-page-element-” + elementCounter;
  7.             elementRow.attr(“id”, newId);
  8.             elementRow.show();
  9.             var inputField = jQuery(“select”, elementRow);
  10.             inputField.attr(“name”, “element-page-id-” + elementCounter);
  11.             var labelField = jQuery(“label”, elementRow);
  12.             labelField.attr(“for”, “element-page-id-” + elementCounter);
  13.             elementCounter++;
  14.             jQuery(“input[name=element-max-id]”).val(elementCounter);
  15.             jQuery(“#featured-posts-list”).append(elementRow);
  16.             return false;
  17.         });
  18.     });
  19. </script>

The JavaScript code above creates a function that is called when the user clicks the link with id add-featured-post. This function clones the template list item we created earlier and updates its fields to have unique ids and names. This way they will all be properly sent with the form when the user clicks submit. The variable elementCounter contains the next id to add. It is also saved in a hidden field so that when the form is submitted, we know how many front page elements to expect.

If you click the “Add featured post” link a couple of times, you’ll see hownew elements are added to the list:

But when you click on the remove link, you’ll notice that nothing happens. Let’s add a function for removing elements from the list:

  1. function removeElement(element) {
  2.     jQuery(element).remove();
  3. }

We also need to call to the function. Add the following code right before incrementing elementCounter.

  1. var removeLink = jQuery(“a”, elementRow).click(function() {
  2.     removeElement(elementRow);
  3.     return false;
  4. });

Before moving on to saving the form, there is one more thing to do. We’ll use the ui.sortable jQuery plugin to make the front page elements sortable by dragging them on the page. To enable the sorting functionality, we’ll need to include the proper JavaScript file (which also comes bundled with WordPress). This can be done by adding the following line of code at the end of functions.php:

  1. if (is_admin()) {
  2.     wp_enqueue_script(‘jquery-ui-sortable’);
  3. }

Then, we’ll add the following JavaScript right before (or after) the jQuery("#add-featured-post").click function defined above.

  1. jQuery(“#featured-posts-list”).sortable( {
  2.     stop: function(event, ui) {
  3.         var i = 0;
  4.         jQuery(“li”, this).each(function() {
  5.             setElementId(this, i);
  6.             i++;
  7.         });
  8.         elementCounter = i;
  9.         jQuery(“input[name=element-max-id]”).val(elementCounter);
  10.     }
  11. });

This snippet makes the list sortable and adds an event that is called whenever the user finishes sorting. The event handler updates all the ids in the elements so that the new order is preserved also when saving the form (this will become clearer once we implement the saving). When writing this stop handler, I noticed that the code for setting the id for the contents of the template was duplicated in two places so I refactored it into its own function, which I placed right before theline with jQuery(document).ready():

  1. function setElementId(element, id) {
  2.     var newId = “front-page-element-” + id;
  3.     jQuery(element).attr(“id”, newId);
  4.     var inputField = jQuery(“select”, element);
  5.     inputField.attr(“name”, “element-page-id-” + id);
  6.     var labelField = jQuery(“label”, element);
  7.     labelField.attr(“for”, “element-page-id-” + id);
  8. }

With adding new elements, sorting them, and removing them working, it’s time to move on to saving the data. But before that, add a submit button right before the form’s closing tag.

  1. <p>
  2.     <input type=”submit” value=”Save settings” class=”button-primary”/>
  3. </p>

Step 4 Saving the Form

The settings page looks good, but there is something missing: it doesn’t do anything yet. It’s time to save some data. WordPress provides an easy system for saving theme and plugin settings as key value pairs to the database using two functions: get_option and update_option. The data stored using the functions can be as simple as a number value or as complex as an array nested multiple times.

The handling of the form is done in the same function that renders the form. To know whether a form was submitted or not, we add a hidden field, update_settings to the form and then check whether that field was sent or not in the handling function.

  1. if (isset($_POST[“update_settings”])) {
  2.     // Do the saving
  3. }

The hidden field that goes inside the form looks like this:

  1. <input type=”hidden” name=”update_settings” value=”Y” />

Let’s start by saving the easier setting, num_elements. We’ll escape the attribute to make sure the user isn’t sending malicious content in the from of HTML tags and then save it to the WordPress settings storage. When using update_option, we don’t need to worry about whether the setting has already been saved or not.

  1. $num_elements = esc_attr($_POST[“num_elements”]);
  2. update_option(“theme_name_num_elements”, $num_elements);

Before we move to saving the list, let’s add the current value of num_elements to the settings form so that the user always sees what value she has entered in before deciding the next value. This will also help us test that the value was actually saved.

  1. <input type=”text” name=”num_elements” value=”<?php echo $num_elements;?>” size=”25″ />

And for cases where we haven’t saved anything yet, we’ll need to load the current value from options, so let’s add this piece of code to be executed when there is no form submitted.

  1. $num_elements = get_option(“theme_name_num_elements”);

When a form is saved, it’s important to notify the user so that she isn’t left wondering whether something happened or not. So, let’s render a simple notice saying “Settings saved.” right after the update_option:

  1. ?>
  2.     <div id=”message” class=”updated”>Settings saved</div>
  3. <?php

Then, let’s save the front page elements. The highest id value in the front page elements is passed in aselement-max-id, so we can take that value and loop through elements up to that id, saving their data into an array in the correct order:

  1. $front_page_elements = array();
  2. $max_id = esc_attr($_POST[“element-max-id”]);
  3. for ($i = 0; $i < $max_id; $i ++) {
  4.     $field_name = “element-page-id-” . $i;
  5.     if (isset($_POST[$field_name])) {
  6.         $front_page_elements[] = esc_attr($_POST[$field_name]);
  7.     }
  8. }
  9. update_option(“theme_name_front_page_elements”, $front_page_elements);

This saves the data, but we still need to present the values on the settings page. So, let’s do the same as with the num_elements field and load the default options in the beginning of the function:

  1. $front_page_elements = get_option(“theme_name_front_page_elements”);

And then, render the existing elements when doing the form:

  1. <?php $element_counter = 0; foreach ($front_page_elements as $element) : ?>
  2.     <li class=”front-page-element” id=”front-page-element-<?php echo $element_counter; ?>”>
  3.         <label for=”element-page-id-<?php $element_counter; ?>”>Featured post:</label>
  4.         <select name=”element-page-id-<?php $element_counter; ?>”>
  5.         <?php foreach ($posts as $post) : ?>
  6.             <?php $selected = ($post->ID == $element) ? “selected” : “”; ?>
  7.             <option value=”<?php echo $post->ID; ?>” <?php echo $selected; ?>>
  8.                 <?php echo $post->post_title; ?>
  9.             </option>
  10.         <?php endforeach; ?>
  11.         </select>
  12.         <a href=”#” onclick=”removeElement(jQuery(this).closest(‘.front-page-element’));”>Remove</a>
  13.     </li>
  14. <?php $element_counter++; endforeach; ?>

We also need to set the initial value for the elementCounter variable used in JavaScript by setting the hidden field’s initial value in PHP and reading it in when initializing the JavaScript variable:

  1. <input type=”hidden” name=”element-max-id” value=”<?php echo $element_counter; ?>” />

And the JavaScript part:

  1. var elementCounter = jQuery(“input[name=element-max-id]”).val();

Step 5 Using the Settings Inside the Theme

Saving and showing settings values within the admin area is great, but what really counts is how you use them to customize your theme, so now, we have come to the point where it’s time to take our settings and do something cool with them.

From here on, changes go to index.php instead of functions.php. First, we’ll read the options to variables:

  1. <?php
  2.     $num_elements = get_option(“theme_name_num_elements”);
  3.     $elements = get_option(“theme_name_front_page_elements”);
  4. ?>

Let’s loop through the $elements list, grouping them into rows with $num_elements blocks on each.

  1. <div id=”front-page-element-container”>
  2.     <div class=”front-page-element-row”>
  3.         <?php foreach($elements as $post_id) : ?>
  4.             <?php if ($num == $num_elements) : ?>
  5.                 </div>
  6.                 <div class=”front-page-element-row”>
  7.             <?php endif; ?>
  8.             <!– Render element here –>
  9.         <?php endforeach; ?>
  10.     </div>
  11. </div>

And then, using the data saved for each element, we’ll fill in the element rendering part above:

  1. <?php $element_post = get_post($post_id); ?>
  2. <div class=”front-page-element”>
  3.     <div class=”thumbnail-image”>
  4.         <?php if (has_post_thumbnail($post_id)) : ?>
  5.             <?php echo get_the_post_thumbnail($post_id, ‘tutorial-thumb-size’); ?>
  6.         <?php endif; ?>
  7.         <a class=”title” href=”<?php echo get_permalink($post_id); ?>”><?php echo $element_post->post_title;?></a>
  8.     </div>
  9. </div>

With a couple elements, it looks like this:

Still quite boring. The posts don’t have thumbnail images and there is no styling for them. To make them look better, let’s first add support for post thumbnail images. This is done by hooking a new function that sets up theme features to be called right after the theme has been loaded

  1. function setup_theme_features() {
  2.     if (function_exists(‘add_theme_support’)) {
  3.         add_theme_support(‘post-thumbnails’);
  4.     }
  5.     if (function_exists(“add_image_size”)) {
  6.         add_image_size(‘tutorial-thumb-size’, 200, 200, true);
  7.     }
  8. }
  9. add_action(‘after_setup_theme’, ‘setup_theme_features’);

The function, setup_theme_features turns on the post thumbnails using WordPress functionadd_theme_support so that WordPress adds this functionality to the post saving page. On the post’s page, we can now add one image as thumbnail by clicking on “Use as featured image” on the image upload page after uploading the photo.

The function also defines a new image size type, tutorial-thumb-size which is used when getting the post thumbnail in the rendering code.

After selecting the featured image, save the changes and reload the front page. Looks more interesting already:

Finally, we’ll add a few styles to style.css, and there we go, the theme has a configurable featured posts display:

  1. .front-page-element-row {
  2.     overflow: auto;
  3. }
  4. .front-page-element {
  5.     float: left;
  6.     margin: 10px 10px 10px 10px;
  7.     padding: 0px;
  8.     width: 200px;
  9.     height: 200px;
  10. }
  11. .thumbnail-image {
  12.     width: 200px;
  13.     height: 200px;
  14.     background: #eee;
  15.     position: relative;
  16. }
  17. .thumbnail-image .title {
  18.     position: absolute;
  19.     bottombottom: 20px;
  20.     display: block;
  21.     background: #000;
  22.     color: #fff;
  23.     padding: 10px;
  24.     font-family: Arial;
  25.     font-size: 12pt;
  26.     text-decoration: none;
  27. }

Conclusion

Now, we have created a settings page for a custom theme. The theme is far from complete, but I hope this introduction got you started with adding settings and customizable elements to your next WordPress theme.