All Topics:
apps
css
dashboard
games
javascript
php
tehcl
textmate
tools
video

Topic: javascript

Demo: "3D" JavaScript Tile Flipping Photo Gallery

published:
2009.12.02
topics:
css
javascript
video

FlipBox is another LightBox clone (a JavaScript photo gallery tool) where the new twist is a fun "3D" tile flipping animation effect. It is much easier to demonstrate than to explain, so I decided to do my first screencast with audio (be gentle!) so I could show you what FlipBox is all about. Incidentally, Mac OSX 10.6 Snow Leopard has a great free screen capture tool built into QuickTime. Sorry in advance if the volume is a little low. Real action starts at 0:45:

More About FlipBox

FlipBox is jQuery-based and makes use of my rotate3Di plugin to create a 3D-like isometric tile flipping effect using the CSS3 transform property currently only supported by Safari, Chrome, and Firefox 3.5+. (That's another reason why I wanted to record a video demo.) If you happen to have an awesome web browser, you can check out a live demo of FlipBox.

In it's current state, with only a little preparation by the user, FlipBox is already a simple to use LightBox-like tool. There's a few other demos with this concept I hope to put together, and I would also like to write proper documentation and do a release.


jQuery Patch: Animate CSS Rotation and Scale

published:
2009.08.07
topics:
css
javascript

I have created a monkey patch for jQuery 1.3.1+ which enables you to independently set and/or animate both the scale and rotation of any HTML content with jQuery. This code uses the scale() and rotate() CSS transformations that are only supported by Webkit, Safari, Chrome, and Firefox 3.5 at this time.

As an example I have some spinning HTML content below. You can click the content to increase its scale while it continues to spin. Try it out:

Click me to scale up!

After applying my patch, the following jQuery code is used to create this example:

setInterval(
    function () {
        $('#at_ex1').animate({rotate: '+=10deg'}, 0);
    },
    200
);

$('#at_ex1').click(
    function () {
        $(this).animate({scale: '+=0.33'}, {queue: false, duration: 1000});
    }
);

Features of this Patch:

  1. Get and set rotate and scale CSS transforms independently with the added custom jQuery methods rotate() and scale(). These work like setting any other CSS property, i.e. you are rotating to an angle not rotating by an angle. Example syntax:
    $('#example').rotate('30deg'); // rotates to 30deg
    $('#example').scale(1.5); // scales to 150%
    $('#example').rotate('45deg'); // rotates to 45deg
    $('#example').rotate(); // will return '45deg'
    $('#example').scale(); // will return '1.5'
            
  2. Animate rotate and scale CSS transforms independently using jQuery's animate() method. This works like any other jQuery CSS animation, i.e. you can rotate to a specific angle, or you can increase or decrease the angle of rotation by any number of degrees. Here are examples of both syntaxes:
    // Rotate to 30deg and scale to 125%
    $('#example').animate({rotate: '30deg', scale: '1.25'}, 1000);
    // Rotate by 30deg from current position and scale down by 10%
    $('#example').animate({rotate: '+=30deg', scale: '-=0.1'}, 1000);
            

Download and Usage

Download a zip file of the patch now or visit the project on GitHub.

This patch requires another one of my jQuery patches that adds CSS transform support to jQuery. The file jquery-css-transform.js should be included in your download.

To use this patch, load jquery-animate-css-rotate-scale.js after loading jQuery and jquery-css-transform.js. For example:

<script src="jquery.js" type="text/javascript"></script>
<script src="jquery-css-transform.js" type="text/javascript"></script>
<script src="jquery-animate-css-rotate-scale.js" type="text/javascript"></script>

CSS text-shadow Fun: Realtime Lighting Demo

published:
2009.06.22
topics:
css
javascript
Official Demo, Hacks.Mozilla.org.

After my last post about the CSS text-shadow property it occurred to me that it could be used to create some fun pseudo-realtime lighting effects.

In the example below I am using a PNG to create a spotlight, and I am using JavaScript to update the text-shadow style on the text in order to simulate realtime shadows from a single light source. Move your mouse over the box to cast a shadow with the spotlight.

Should work in Firefox 3.5, Safari, Opera, and Chrome. Apparently still no support in IE8? Big shocker there.</sarcasm>

View the example in a new window.


Fix jQuery UI Tabs to Update Browser Location

published:
2009.06.08
topics:
javascript

When I spoke at MinneWebCon 2009 about Standardizing Web User Interfaces I covered one of my major pet peeves on the web: when content that can and should have a direct link, does not.

(The most common example would be the all-Flash portfolios and galleries of designers. You get three pages into their sites looking at a particular piece of their work, and then you look up in your browser location bar and you are still at http://www.stupid-designer.com/ ... I can't share their design work with somebody even if I wanted to, because there is no link! Terrible SEO and self-promotion.</rant>)

In terms of web user interface widgets, the very common tab view is often done incorrectly. For instance, both YUI's tab view and jQuery UI's tab view fail to change the browser's location when you switch tabs.

You can already directly link to a tab if you know the URL or right-click the tab to find the URL. However, if I use my browser's default bookmarking behavior, or if I use the location bar to copy and paste a link to somebody, or any number of other scenarios — because neither the YUI nor jQuery's tab views update the browsers location when you switch tabs, you are likely to send somebody a link to the first tab you landed on rather than the tab you are viewing.

The strangest part of all this is that enabling the direct linking on the back end is actually the hard part. Getting the location to update as you switch tabs is laughably easy. Here is the code for the default jQuery tab view behavior:

$('#tabs').tabs();
To fix the jQuery tab view so that it updates the browsers location as you switch tabs, the code looks like this:

$('#tabs').tabs();
$('#tabs ul li a').click(function () {location.hash = $(this).attr('href');});

Couldn't be simpler. I've set it up so you can see it in action. In this fixed jQuery tabs example as you click the tabs you will see your browser's location update.

I have submitted a ticket.


jQuery Syntax for Easy Portability?

published:
2009.06.03
topics:
javascript

I have to say, I find the syntax of the jQuery JavaScript library to be very logical, efficient, and readable. I realized today that jQuery code also has the very interesting property of being relatively easy to port to any other JavaScript library. And jQuery, or a jQuery-like syntax, seems to be a reasonable starting point for creating JavaScript-library-agnostic code — that is, JavaScript code that depends on a JavaScript library to function, but can be easily made to work with any library.

As an example, lets consider the following jQuery call:

$('#foo,#bar').addClass('test').css('color', 'blue');
Now lets look at code that does the same thing written for YUI and Dojo:

// YUI
YAHOO.util.Dom.addClass(['foo', 'bar'], 'test');
YAHOO.util.Dom.setStyle(['foo', 'bar'], 'color', 'blue');

// Dojo
dojo.query('#foo,#bar').addClass('test').style('color', 'blue');

Lets say we wanted to keep the jQuery syntax shown in the very first example above, but instead of including jquery.js and all of the jQuery code, we wanted to use the YUI JavaScript library. How could we make the jQuery style call use YUI? Here's some code that maps those calls to the YUI library:

function UseYUI(selector) {
    this.nodes = YAHOO.util.Selector.query(selector);

    this.addClass = function (className) {
        YAHOO.util.Dom.addClass(this.nodes, className);

        return this;
    }

    this.css = function (property, value) {
        if (typeof value == 'undefined') {
            return YAHOO.util.Dom.getStyle(this.nodes, property);

        } else {
            YAHOO.util.Dom.setStyle(this.nodes, property, value);

            return this;
        }
    }
}

function $(selector) {
    return new UseYUI(selector);
}

After adding the above code to your page you could keep the jQuery syntax — i.e. $('#foo,#bar').addClass(… — but include the YUI library code and files instead of the code and files for jQuery.

And actually, if we had many methods like addClass where they are the same in jQuery and YUI except for the first argument, we could create a helper function to generate the mapped functions for us:

function UseYUI(selector) {
    this.nodes = YAHOO.util.Selector.query(selector);
    
    this.mapMethodToYUIDom = function(method) {
        this[method] = function () {
            var args = new Array();
            args.push(this.nodes);
            for (var i = 0; i < arguments.length; i++) {
                args.push(arguments[i]);
            }
        
            YAHOO.util.Dom[method].apply(null, args)
        
            return this;
        }
    }

    this.mapMethodToYUIDom('addClass');
    this.mapMethodToYUIDom('removeClass');
}

Mapping the jQuery style calls to Dojo in this case is even easier than YUI. Much easier:

function $(selector) {
    var nodes = dojo.query(selector);

    nodes.css = nodes.style;

    return nodes;
}

It would be a fair amount of work, and a decent bulk of code, to completely map all jQuery style calls to either YUI or Dojo, or any other JavaScript library for that matter. Obviously, when porting from one JavaScript library to another, going through line by line and replacing each call would result in slightly faster and more file-size efficient code. But that's no walk in the park either.

With the method I've described in this post, you could actually put in the one-time effort towards creating the code to dynamically map from jQuery syntax to any other framework thereby making any and all projects you build and distribute library-agnostic. What do you think? It seems like such mappings would come in useful.