Miedlar.com

miedz

Prototype Carousel w/ Scriptaculous (version 2)

by Brian R. Miedlar
Updated: 1/21/2007

Version 2 now runs on the Prototype 1.6 library and utilizes the built-in behaviour handling. (See Version 1)

A carousel provides a quick browse through items which combats the precision of keyword searches and the lack of precision in typical browsing/paging environments. Many ajax frameworks are beginning to implement carousel components.

Sample Screenshot

I wanted a quick way to implement a prototype based carousel that allows for n-item paging. Building on top of prototype it seems appropriate to utilize the scriptaculous effects library for carousel paging/movement. Additionally, I wanted the items within the carousel to be extracted from the HTML itself so that they can be indexed in search engines. It also should allow for vertical paging, horizontal paging, as well as grouped paging. And this method would still allow for dynamically generated content through javascript if needed.

I made this work with prototype.js and my javascript dependency loading layer.

Utilizing the Prototype 1.6 Css Selectors for Behaviour Loading

Because prototype 1.6 has improved css selector support there is no longer a need for the Behaviour.js library.

The behaviours can be registered to a queue and applied once the dom has been loaded

    var OS = Class.create(...);
    ...
    OS.PageLoadComplete = function() {
        _os.pageLoading = false;
        $A(OS.BehaviourQueue).each(function(selectors) {
            OS.ApplyBehaviour(selectors);
        });
        OS.BehaviourQueue = [];
    };
    Event.observe(document, 'dom:loaded', function() {
        OS.PageLoadComplete();
    });
    OS.BehaviourQueue = [];
    OS.RegisterBehaviour = function(selectors) {
        if(!_os.pageLoading) { OS.ApplyBehaviour(selectors); return; }
        OS.BehaviourQueue.push(selectors);    
    }
    OS.ApplyBehaviour = function(selectors) {
        $H(selectors).each(function(item) {
            $$(item.key).each(function(element) {
                item.value(element);
            });
        });
    };
        

Using this methodology we can load the behaviours in the same way as done in Sebastian's behaviour.js script

            SomeClass.SomeBehaviour = {
                '#SomeElementId .someClass': function(element) {
                    //code to inject behaviour to the element
                },
                '#AnotherElementId .someClass.withClass': function(element) {
                    //code to inject behaviour to the element
                }
            }
            OS.RegisterBehaviour(SomeClass.SomeBehaviour);
        

Carousel with Prototype 1.6

Following defines the microformat of a carousel. All carousels should be formatted as such and then injected upon with behaviour for vertical/horizontal movement and sizing

The code has been improved to find the components necessary within the root ID of the carousel rather than putting the carousel within a container

    <div id="SomeCarouselElementId" class="carousel">
        <div class="button navButton previous" style="display:none;">Up</div>
        <div class="button navButton next" style="display:none;">Down</div>
        <div class="container">
            <div class="items">
                <div class="item">
                    <div class="key">SomeKey1</div>
                    <!-- Additional data members should exist as class containers -->
                    <div class="someDataClass1">somedata</div>
                    <div class="someDataClass2">somedata</div>
                </div>            
                <div class="item">
                    <div class="key">SomeKey1</div>
                    <!-- Additional data members should exist as class containers -->
                    <div class="someDataClass1">somedata</div>
                    <div class="someDataClass2">somehtml</div>
                </div>            
            </div>
        </div>
    </div>
        

Following is code showing how to create a carousel.

Using behaviors we can apply the carousel to properly behaviour-css tagged elements

Alternatively we can load this directly with a javascript class.

The Carousel constructor is called with six arguments:

    key, carouselElement, itemWidth, itemHeight, observer, options
  • key: gives the carousel an identifier string to be referenced on observer callbacks
  • carouseElement: This is the root microformat ID of the carousel.
  • width: the width to scroll per item (this is the group width if you are using a group set)
  • height: the height to scroll per item (this is the group height if you are using a group set)
  • observer: If supplied then callbacks will be fired on the observer (fireActiveCarouselLoaded, fireActiveCarouselItem, fireDeactiveCarouselItem)
  • options: This allows for overriding the default options
    • setSize: specifies how many items are scrolled at a time
    • groupSize: (default==1) allows multiple items to be treated as one item
    • duration: time in seconds to complete scroll
    • direction: 'horizontal' or 'vertical'
    • itemParser: this function is called for each item in the itemContainerElement. This function should return an object that will be represented in the item.value. You can use this object at a later time on activation callbacks.
    • setItemEvents: this function is called for each item in the itemContainerElement. This allows you to bind events to each item. Typically you should bind carousel.activate(carouselItem) to some kind of event so that the event will trigger activation callbacks to the observer.

    ModelBehavior.fireActiveCarouselLoaded = function(carousel) {
        //Allows for load callbacks
    }
    ModelBehavior.fireActiveCarouselItem 
        = function(carousel, element, item) {
        //Allows for item activation callbacks
    }
    ModelBehavior.fireDeactiveCarouselItem 
        = function(carousel, element, item) {
        //Allows for item deactivation callbacks 
    }        
    
    ModelBehavior.SomeInitializationFunction = {
        ModelBehavior.SimpleCarousel = 
            new Carousel('SimpleCarousel1', 'SimpleCarouselItems', 
            200, 30, 
            'BtnCarousel_Forward', 'BtnCarousel_Back', 
            ModelBehavior, 
            {
            'setSize': 5,
            'groupSize': 1,
            'duration': .5,
            'direction': 'vertical',
            'itemParser': function(item) {
                //Given html element you can build a data object 
                //for the item if needed for later activation
                return {}; //some object representing the value
            },
            'setItemEvents': function(carousel, element, 
                carouselItem, observer) {
                
                //This allows you to set events to the item 
                //like rollovers/mouse events
                Event.observe(element, 'click', function(){                    
                    carousel.activate(carouselItem);
                });
            }
        });
        ModelBehavior.SimpleCarousel.load();
    }
            

Loading the Carousel library

My scripts requires the following standard javascript imports to be made before using the OS platform.

  • prototype.js
  • scriptaculous.js w/ effects.js
  • os.js (defines dependency loading and behaviour registration)

I then use behaviours and my javascript loading architecture to load the necessary code dependencies.

  • behaviors/model.js (this code loads the dependencies and creates the carousels)
  • carousel.js (this is the carousel model)

Example and Code

View a sample vertical and horizontal carousel here

Download the sample code here

Note: the path to the javascript libraries is defined in os.js

Comments

Nickname:
Message: