/**
 * Accessible Tabs - jQuery plugin for accessible, unobtrusive Navigation
 * @requires jQuery v1.0.3
 *
 * made for Anatom5 http://anatom5.de
 * 
 * code: http://github.com/ginader/Accessible-Navigation
 * please report issues at: http://github.com/ginader/Accessible-Navigation/issues
 *
 * Usage: $('ul').accessibleNavigation(); // selector needs to point to the top level UL of the Navigation
 *
 *
 * Copyright (c) 2009 Dirk Ginader (http://ginader.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Version: 1.0
 * 
 * History:
 * * 1.0 initial release
 */


(function($) {
    var debugMode = true;
    $.fn.extend({
        accessibleNavigation: function(config) {
            var o = this;
            
            debug('accessibleNavigation');
            debug(o);
            o.topLevelLIs = []; // contains all TopLevel LIs when found
            o.activeTop = null; //contains the active TopLevel LI if available
            o.activeItem = null; //contains the active
            o.shim = null; // contains the iframe shim that is used to allow the submenus to overlap Form Elements in IE only
            o.options = $.extend({
                activeClass: 'active', // class to be applied to the currently opened Top Level Navigation Item (LI)
                currentClass: 'current', // class to be applied to the currently selected Top Level Navigation Item (LI)
                topLevelClass: 'top', // class to be applied to all top level navigation Items (LIs)
                deactivateTimeout: 1000, // time in miliseconds until the navigation closes after the mouse leaves it
				defaultActiveClass:'defaultactive'
            }, config);
            var keyCodes = {
                37 : 'left',
                38 : 'up',
                39 : 'right',
                40 : 'down',
                13 : 'enter',
                27 : 'escape',
                32 : 'spacebar'
            };
            /*
            backspace   8
            tab         9
            enter       13
            shift       16
            ctrl        17
            alt         18
            pause/break 19
            caps lock   20
            escape      27
            spacebar    32
            page up     33
            page down   34
            end         35
            home        36
            left arrow  37
            up arrow    38
            right arrow 39
            down arrow  40
            insert      45
            delete      46
            */
            o.setup = function(el){
                if(!el.is('ul')){
                    return false;
                }
                o.topLevelLIs = el.children('li');
                o.topLevelLIs.each(function(){
                    o.initEvents($(this));
                });
                el.children('li:has(ul)').addClass(o.options.topLevelClass);
                 // this class changes the display:none by default submenus to position offscreen to make screenreader buffers aware
                // TODO: make all links in the submenus tabindex -1 so nobody tabs to them accidentily
                el.find('ul a').attr('tabindex',-1);
            };
            o.setupIEshim = function(el){
                // build the iframe shim that helps IE6 to overlay form elements
                o.shim = document.createElement('iframe');
                o.shim.scrolling = 'no';
                o.shim.frameBorder = '0';
                el.before(o.shim);
                o.shim = $(o.shim);
                debug(o.shim);
                o.shim.css({
                    'width' : 0,
                    'height' : 0,
                    'left' : 0,
                    'backgroundColor' : 'transparent',
                    'position' : 'absolute'
                });
                o.shimDefault = o.shim.offset();
                o.shim.css('display','none');
            };
            o.initEvents = function(el){
                el.find('a').eq(0).focus(function(){
                    o.activeItem = $(this).parent();
                    debug('o.activeItem set on focus()');
                    debug(o.activeItem);
                });
                el.find('ul a').focus(function(e){
                    o.activate(e);
                });
                el.find('ul a').blur(function(e){
                    o.deactivateTimeout(e);
                });
                el.hover(function(e){
                    o.activate(e);
                },function(e){
                    o.deactivateTimeout(e);
                });
                el.keydown(function(e){
                    if(keyCodes[e.which]){
                        e.stopPropagation();
                        e.preventDefault();
                    }
                });
                el.keyup(function(e){
                    if(keyCodes[e.which]){
                        o[keyCodes[e.which]](e);
                        e.stopPropagation();
                        e.preventDefault();
                    }
                });
            };
            o.enter = function(e){
                o.activate(e);
            };
            o.spacebar = function(e){
                o.activate(e);
            };
            o.escape = function(e){
                o.deactivate(e);
                o.activeTop.find('a:first').focus(); //send back the focus to the top item of the dropdown that was just closed
            };
            o.left = function(e){
                var active = o.getActiveItem(e);
                if($.inArray(active, o.topLevelLIs)){
                    active.prev().find('a:first').focus();
                }
            };
            o.right = function(e){
                o.activeItem = o.getActiveItem(e);
                debug(o.activeItem);
                if($.inArray(o.activeItem, o.topLevelLIs)){
                    debug('activeItem is top level LI');
                    debug('activeItem:');
                    debug(o.activeItem);
                    debug('activeItem.next:');
                    debug(o.activeItem.next());
                    o.activeItem.next().find('a:first').focus();
                }
            };
            o.up = function(e){
                var active = o.getActiveItem(e);
                if(!active.hasClass(o.options.topLevelClass)){
                    active.prev().find('a:first').focus();
                    if(!active.prev().length){
                        o.activeTop.find('a:first').focus();
                    }
                }
            };
            o.down = function(e){
                var active = o.getActiveItem(e);
                if(active.hasClass(o.options.topLevelClass)){
                    active.children().find('a:first').focus();
                }else{
                    active.next().find('a:first').focus();
                    if(!active.next().length){
                        o.activeTop.find('a:first').focus();
                    }
                }
                
            };
            o.getActiveItem = function(e){
                debug('getActiveItem');
                if(o.activeItem){
                    debug('activeItem already exists:');
                    debug(o.activeItem);
                    return o.activeItem;
                }else if(o.activeTop){
                    debug('activeItem does not exist. Use activeTop instead:');
                    debug(o.activeTop);
                    return o.activeTop;
                }else{
                    debug('activeItem and activeTop don\'t exist. get getTopLevelLi:');
                    o.activeTop = o.getTopLevelLi(e);    
                    debug(o.activeItem);
                    return o.activeItem;
                }
            };
            o.activate = function(e,el){
                debug('activate');
				debug(e);
                if(o.timeout){
                    window.clearTimeout(o.timeout);
                    o.timeout = null;
                }
                o.topLevelLIs.removeClass(o.options.activeClass);
				if(el){
					o.activeTop = el;
				}else{
                	o.activeTop = o.getTopLevelLi(e);
				}
                o.activeTop.addClass(o.options.activeClass);
                o.activeTop.find('ul a').attr('tabindex','');
                o.activeItem = o.getActiveItem(e);
                if($.inArray(o.activeItem, o.topLevelLIs)){
                    debug('activeItem IS topLevel');
                    debug(o.activeItem);
                    debug('first a:');
                    debug(o.activeTop.find('ul a:first'));
                    //o.activeTop.find('ul a:first').focus();
                    //o.activeItem = o.activeTop.find('ul li:first');
                }
                var flyout = o.activeTop.children('ul').eq(0);
                if(o.shim && flyout){
                    var flyoutPos = flyout.offset();
                    o.shim.css({
                        'left' : flyoutPos.left - o.shimDefault.left,
                        'top' : flyoutPos.top - o.shimDefault.top,
                        'width' : flyout.width(),
                        'height' : flyout.height(),
                        'display' : 'block'
                    });
                }
            };
            o.deactivateTimeout = function(e){
                debug('deactivateTimeout');
                o.timeout = window.setTimeout(function(){
                    o.deactivate(e);
                },o.options.deactivateTimeout);
            };
            o.deactivate = function(e){
                debug('deactivate');
                o.activeTop = o.getTopLevelLi(e).removeClass(o.options.activeClass);
                o.activeTop.find('ul a').attr('tabindex',-1);
                if(o.shim){
                    o.shim.hide();
                }
				if(o.defaultActive.size()){
					o.initDefaultActive(o.defaultActive.eq(0));
				}
            };
            o.getTopLevelLi = function(e){
                debug('getTopLevelLi');
                var target = $(e.target);
                var ancestor = target.parents('.'+o.options.topLevelClass);
                var topLevelLI = (target.hasClass(o.options.topLevelClass) ? target : ancestor);
                ancestor = target.parent('li').eq(0);
                var activeLI =  (target.is('li') ? target : ancestor);
                o.activeItem = activeLI;
                debug('getTopLevelLi() found activeItem:');
                debug(o.activeItem);
                debug('getTopLevelLi() found topLevelLI:');
                debug(topLevelLI);
                return topLevelLI;
            };
			o.initDefaultActive = function(el){
				debug('initDefaultActive');
				debug(el);
				o.activate(null,el);
			};
            return o.each(function() {
                var el = $(this);
                o.setup(el);
                if($.browser.msie && $.browser.version < 7){
                    o.setupIEshim(el);
                }
				debug('find default active menu item: '+o.options.defaultActiveClass);
				o.defaultActive = $('.'+o.options.defaultActiveClass);
				debug(o.defaultActive.size());
				if(o.defaultActive.size()){
					o.initDefaultActive(o.defaultActive.eq(0));
				}
            });
        },
        addSubNavList: function(html){
            var o = this;
            //debug('addSubNavList');
            //debug(o);
            if(!html){
                debug('define html content');
                return;
            }
            return o.each(function() {
                $(this).append(html);
            });
        }
    });
    // private Methods
    function debug(msg){
        if(debugMode && window.console && window.console.log){
            window.console.log(msg);
        }
    }
})(jQuery);
