As the average monitor resolution and width increases, the real estate of the browser window changes. When browser windows are often wider than they are tall, it makes sense to focus on new ways to display data, such as tabs, and accordions.
The Accordion Solution
As a part of web development, we needed a solution to display multiple views of information on the same page, and wanted a sleek javascript transition effect. We chose a horizontal accordion solution based on MooTools' kwicks. The horizontal accordion is a wide, animated tab controller. It allows us to have multiple views on a single page without all being displayed at once. When a user clicks on a tab, it will animate, and expand to the selected tab. Thus creating a accordion like javascript animated UI.
Adding accordion object events
The concept of our control is to be able to click through each 'tab' to expand to it's respective view. By using MooTools transitions and effects we create what looks like an accordion. For the clicking to work, we must add events to each tab for it to expand.
init: function() {
    if ($$('#kwick')) {
        // create the list of kwicks
        eyemagine.accordion.kwicks = $$('#kwick .kwick');
        // create the transition to animate with
        eyemagine.accordion.fx = new Fx.Elements(eyemagine.accordion.kwicks, {
            wait: false,
            duration: 250,
            transition: Fx.Transitions.easeOut
        });
        // loop through each kwick
        kwicks.each(function(kwick, i){
            kwick.addEvent('click', function(e){
                // call the accordions jump function to expand to that view
                eyemagine.accordion.jumpToFrame(kwick.get('id'),false);
                e.stop();
            });
        });
        // call the init function for our accordion class to expand to the default view
        eyemagine.accordion.initKwick();
    }
},
Creating the accordion control
Now that we have our tabs' actions set we need to add functionality to them. In order to expand/contract the views we need to calculate the size of what the view should be based on how many views we currently have. The content of our view is also an issue. We will need to fade the content in and out using style opacity so we do not see the content when it is not active. Here is a sample of how the accordion control would look:
accordion: {
    fx: null,
    kwicks: null,
    transitionLong: 300,
    transitionShort: 10,
    // initialize the accordion control
    initKwick: function() {
        $$('#kwick .kwick.init').each(function(kwick, j){
            eyemagine.accordion.jumpToFrame(kwick.get('id'),true);
        });
    },
    // jump to a specific view
    jumpToFrame: function(id,force) {
        var kwick = $(id);
        // dont jump if the view is locked
        if (kwick.hasClass('locked') && !force) {
            return;
        } else if ($(id)) {
            // get the kwick id
            var i = eyemagine.accordion.getAccordianItemId(id);
            // our page specific offsets
            var obj = {};
            var offsetWidth = 37;
            var totalWidth = 950 - (eyemagine.accordion.kwicks.length * 5 );
            // set up the width of the kwicks
            eyemagine.accordion.kwicks.each(function(other, j){
                // reset the offset width
                offsetWidth = 37;
                // loop through each clickable tab
                var titles = $$('#' + other.get('id') + ' .kwick_title').each(function(title, j){
                    offsetWidth = title.offsetWidth + 10;
                    if (other != kwick){
                        // set the width
                        totalWidth -= offsetWidth;
                    }
                });
                if (other != kwick){
                    var w = other.getStyle('width').toInt();
                    if (w != offsetWidth) obj[j] = {'width': [w, offsetWidth]};
                }
                // chain the tweens for fade in-out
                $$('#' + other.get('id') + ' .accordionContent').each(function(content, j){
                    if (other != kwick){
                        other.addEvent('click', function(e){
                            // jump to a frame based on their link attribute
                            eyemagine.accordion.jumpToFrame(other.get('link'),false);
                            e.stop();
                        });
                        // create and start the transisition
                        var cfx = new Fx.Tween(content, {
                            property: 'opacity',
                            duration: eyemagine.accordion.transitionLong,
                            transition: Fx.Transitions.Quart.easeOut
                        });
                        cfx.start(0);
                    } else {
                        other.removeClass('accordionLink');
                        other.removeEvents('click');
                        content.set('tween', {duration: eyemagine.accordion.transitionLong});
                        content.tween('opacity', 1);
                    }
                });
                // nav never gets pushed over so no need to chain it
                $$('#' + other.get('id') + ' .accordionNav').each(function(content, j){
                    if (other != kwick){
                        // fade out the view
                        content.set('tween', {duration: 'short'});
                        content.tween('opacity', '0');
                    } else {
                        // fade in the view
                        content.set('tween', {duration: 'short'});
                        content.tween('opacity', '1');
                    }
                });
            });
            // set the total width transition
            obj[i] = {
                'width': [kwick.getStyle('width').toInt(), totalWidth]
            };
            // start the total width transition
            eyemagine.accordion.fx.start(obj);
        }
    },
    // get the id of the kwick from the kwick object
    getAccordianItemId: function (name) {
        var id;
        eyemagine.accordion.kwicks.each(function(other, j){
            if (other.get('id') == name){
                id = j;
            }
        });
        return id;
    }
},
The Wizard Interface
Using the accordion object is great for selecting individual views to access. But what about a wizard like interface? In order to accomplish this we need to lock and unlock certain tabs. The easiest way to do this is by adding and removing classes. This way we can change the way these locked tabs look without any additional effort in our javascript.
unlock: function (id) {
    $(id).removeClass('locked');
},
lock: function (id) {
    $(id).addClass('locked','true');
},
Within our functions we will call the unlock functions after our javascript validation, for example:
validateForm: function(valid) {
    if (valid) {
        // unlock the tab and jump to the next frame
        eyemagine.accordion.unlock('next');
        eyemagine.accordion.jumpToFrame('next', false);
    }
},
Initialing the accordion and controlling the view by URL
One problem we ran into with the accordion control was that if we wanted to link to a specific view, we could only link to the page containing the views. To get around this solution we added a URL hash checker to jump to that hash.
initKwick: function() {
    // get the hash URL from the browser
    if (window.location.hash) {
        var jumpto = window.location.hash.substr(1);
    }
    // check to see if we have a quick with the hash's name
    if ($(jumpto) && $(jumpto).hasClass('kwick')) {
        // jump to our hash url
        eyemagine.accordion.jumpToFrame(jumpto,true);
    } else {
        // jump to any kwick with the init class
        $$('#kwick .kwick.init').each(function(kwick, j){
            eyemagine.accordion.jumpToFrame(kwick.get('id'),true);
        });
    }
},
Practical use
Many new UI developments, such as iPhone scroll view, have been widely accepted and praised. The horizontal accordion shares many similarities to the scroll view, and is both a great way to conserve real estate and help us keep the user in the view we chose. These UIs are great for both mobile devices, and browser based navigation. By eliminating the use of conventional scroll bars we can fully customize and control what and where the data is going to be displayed. This includes a very easily expandable wizard-like interface that can help ease navigation for the end user.





