/**
 * @author trixta 
 */
(function($){
	if(!window.console){
		window.console = {};
	}
	if(!console.log){
		console.log = function(){};
	}
	
	var head 	= /h\d/,
		form 	= /input|select|button|textarea/,
		exp 	= $.expr.filters
	;
	
	exp.srVisible = function(elem, i){
		return (elem.offsetWidth > 0 && elem.offsetHeight > 0 && jQuery.curCSS(elem, 'visibility') !== 'hidden');
	};
	
	exp.srfocusable = function(elem, i, _skipVisible){
		var name = elem.nodeName.toLowerCase();
		return ( (head.test( name )) || (name === 'area') || (name === 'a' && elem.href) || (form.test(name) && !elem.disabled && elem.type !== 'hidden') );
	};
	
	var semanticAtom = ['a', 'p', 'li', 'dt', 'dd', 'blockquote', 'address', 'th', 'td', 'dfn'];
	exp.semanticAtom = function(elem, i){
		var name = elem.nodeName.toLowerCase();
		return (( exp.srfocusable(elem, i) || $.inArray(name, semanticAtom) !== -1 ) );
	};
	
	exp.semanticAtomSrFocusable = exp.semanticAtom;
	
	$.fn.firstExpOf = function(sel){
		if(!this[0]){
			return this.pushStack([]);
		}
		var elems 	= $('*', this[0]),
			len 	= elems.length,
			ret		= []
		;
		for(var i = 0; i < len; i++){
			if(exp[sel](elems[i], i)){
				ret = [elems[i]];
				break;
			}
		}
		return this.pushStack(ret);
	};
	
	var currentLoc = location.href.split('#')[0];
	$.fn.getHrefHash = function(sel){
		var ret = '';
		if(this[0]){
			ret = this[0].href.replace(currentLoc, '');
		}
		return ret;
	};
	
	$.setA11yMode = function(hard){
		if(hard){
			$.expr.filters.semanticAtomSrFocusable = $.expr.filters.srfocusable;
		} else {
			$.expr.filters.semanticAtomSrFocusable = $.expr.filters.semanticAtom;
		}
	};
	
	
	var body, bodyStyle;
	
	$.SCROLLBARWIDTH = 15;
	
	function setConstants(){
		body = $(document.body);
		bodyStyle = body[0].style;
		
		var testElem 		= $('<div style="position: absolute; visibility: hidden; width: 80px; overflow: scroll;height: 80px;"><div style="width: 99px; height: 99px;" /></div>')
								.appendTo('body');
		$.SCROLLBARWIDTH = testElem.innerWidth() - $('div', testElem).css('width', 'auto').innerWidth();
		testElem.remove();
		testElem = null;
	}
	
	if(!document.body || !document.body.style){
		$(setConstants);
	} else {
		setConstants();
	}
	
	$.each(['outerHeight', 'outerWidth', 'height', 'width', 'innerHeight', 'innerWidth'], function(i, name){
		$.fn[name +'s'] = function(arg){
			if( (name === 'height' || name === 'width') && arg !== undefined ){
				return $.fn[name].apply(this, arguments);
			}
			var ret = 0;
			this.each(function(){
				ret += $(this)[name](arg);
			});
			return ret;
		};
	});
	
})(jQuery);


(function($){
	var allowFocus 	= true;
	
	function stopFocus(){
		allowFocus = false;
		setTimeout(function(){
			allowFocus = true;
		}, 1);
	}
	
	function testDomTarget(e){
		var oE 	= e.originalEvent;
		if(e.target === document || e.target === window || $.nodeName(e.target, 'body') || $.nodeName(e.target, 'html')){
			stopFocus();
			return false;
		}
		if(oE){
			if(
					allowFocus && e.target && e.target.nodeType === 1 &&
					(oE.explicitOriginalTarget && oE.explicitOriginalTarget && oE.explicitOriginalTarget !== window &&  oE.explicitOriginalTarget !== document && !$(oE.explicitOriginalTarget).is('html, body') ||
					oE.toElement || oE.fromElement)
				) {
					return true;
				} else {
					return false;
				}
		}
		return true;
	}
	
	$.each(['focusin', 'focusout'], function(i, eType){
		
		$.event.special['dom'+ eType] = {
			setup: function(){
				$(this)
					.bind(eType, $.event.special['dom'+ eType].handler);
                return true;
            },
			teardown: function(){
                $(this).unbind(eType, $.event.special['dom'+ eType].handler);
                return true;
            },
            handler: function(e){
				if(testDomTarget(e)){
	                e = $.extend({}, e, {type: 'dom'+ eType});
	                return $.event.handle.call(this, e);
				}
				return undefined;
            }
		};
		
	});
	
	/*
	 * timer
	 */

	var clearInterval 	= window.clearInterval,
		setInterval 	= window.setInterval,
		setTimeout 		= window.setTimeout
	;
	$.createTimer = function(obj){
		
		function clear(name){
			if(obj[name] !== undefined){
				clearInterval(obj[name]);
			}
		}
		
		return {
			setInterval: function(name, fn, delay){
				clear(name); 
				obj[name] = setInterval(function(){fn.call(obj);}, delay);
			},
			setDelay: function(name, fn, delay){
				clear(name);
				obj[name] = setTimeout(function(){fn.call(obj);}, delay);
			},
			clear: clear
		};
	};
})(jQuery);
(function($){
	
	var offsetBaseCSS 	= 'position: absolute; width: 1px; height: 1px; overflow: hidden;margin: 0; padding: 0;top: 0;',
		offsetDir 		= ($('html').attr('dir') === 'rtl') ? 'right: -9999em;' : 'left: -99999em;',
		offsetCSS 		= offsetBaseCSS+offsetDir,
		version 		= parseInt($.browser.version, 10)
	;
	$.support.waiAria = (!$.browser.msie || version > 7);
	$.notIE6 = (!$.browser.msie || version > 6);
	$.browser.lteIE6 = ($.browser.msie && version < 7);
	$.browser.lteIE7 = ($.browser.msie && version < 8);
	$.browser.lteIE8 = ($.browser.msie && version < 9);
	
$(function(){
	
	var style = document.createElement('style'),
		styleS
	;
	
	style.setAttribute('type', 'text/css');
	style = $(style).prependTo('head');
	
	styleS = document.styleSheets[0];
	
	function add(sel, prop){
		if (styleS.cssRules || styleS.rules) {
			if (styleS.insertRule) {
				styleS.insertRule(sel +' {'+ prop +';}', styleS.cssRules.length);
			} else if (styleS.addRule) {
				styleS.addRule(sel, prop);
			}
		}
	}
	
	add('.a11y-js-overflow', 'overflow:visible !important');
	add('.a11y-hidden', 'position:absolute');
	add('.a11y-hidden', offsetDir.replace(';', ''));
	
	
	
	$.cssRule = {
		add: add
	};
});

	$.ui = $.ui ||
		{};
		
	if(!$.ui.keyCode){
		$.ui.keyCode = {
			DOWN: 40,
			END: 35,
			ENTER: 13,
			ESCAPE: 27,
			HOME: 36,
			LEFT: 37,
			PAGE_DOWN: 34,
			PAGE_UP: 33,
			RIGHT: 39,
			SHIFT: 16,
			SPACE: 32,
			TAB: 9,
			UP: 38
		};
	}
		
	
	/*
	 * HCM-Detection
	 */
	$.ui.userMode = (function(){
		var userBg, 
			timer, 
			testDiv;
		
		function testBg(){
			testDiv = testDiv || $('<div style="'+ offsetCSS +'"></div>').appendTo('body');
			var black = $.curCSS( testDiv.css({backgroundColor: '#000000'})[0], 'backgroundColor', true),
				white = $.curCSS( testDiv.css({backgroundColor: '#ffffff'})[0], 'backgroundColor', true),
				newBgStatus = (black === white || white === 'transparent')
			;
			
			if(newBgStatus != userBg){
				userBg = newBgStatus;
				
				$.event.trigger({type: 'usermode', disabled: !userBg, enabled: userBg});
			}
			return userBg;
		}
		
		function init(){
			testBg();
			clearInterval(timer);
			timer = setInterval(testBg, 3000);
		}
				
		$.event.special.usermode = {
			add: function(handler){
				//always trigger
				testBg();
				var elem =  this;
				setTimeout(function(){
					$(elem).trigger({type: 'usermode', disabled: !userBg, enabled: userBg});
				}, 0);
				return handler;
			},
			setup: function(){
				
			},
			teardown: function(){},
            handler: function(){}
		};
		
		return {
			get: testBg,
			init: init
		};
		
	})();
	
	$.fn.userMode = function(fn){
		return this[(fn) ? 'bind' : 'trigger']('usermode', fn);
	};
	
	$(function(){
		$('html').userMode(function(e){
			$(this)[e.enabled ? 'addClass' : 'removeClass']('hcm');
		});
		$.ui.userMode.init();
	});
	
	(function($){
		var preventclick = false;
		
		function handleAriaClick(e){
			
			if(!preventclick && (!e.keyCode || e.keyCode === $.ui.keyCode.ENTER)){
				//ToDo:  || e.keyCode === $.ui.keyCode.SPACE
				preventclick = true;
				setTimeout(function(){
					preventclick = false;
				}, 1);
				return $.event.special.ariaclick.handler.apply(this, arguments);
			} else if(preventclick && e.type == 'click'){
				e.preventDefault();
				return false;
			}
			return undefined;
		}
		$.event.special.ariaclick = {
			setup: function(){
				$(this).bind('click keydown', handleAriaClick);
	            return true;
	        },
			teardown: function(){
	            $(this).unbind('click keydown', handleAriaClick);
	            return true;
	        },
	        handler: function(e){
	            e.type = 'ariaclick';
	            return $.event.handle.apply(this, arguments);
	        }
		};
	})(jQuery);
	
	
	/* EM-Change */
	$.bodyDefaultFontsize = 10;
	$.testEm = (function(){
		var body,
			timer,
			emPx = 0,
			oldVal = 0,
			html = $(document.documentElement)
		;
				
		function test(){
			var fSize = parseInt($.curCSS(body, 'fontSize', true), 10), e;
			
			if(emPx !== fSize){
				emPx = fSize;
				e = {
					type: 'emchange',
					emPx: emPx,
					oldEmPx: oldVal
				};
				$.event.trigger(e);
			}
			oldVal = fSize;
			emPx = fSize;
			return e;
		}
		
		function addEmClass(e){
			var dif 	= e.emPx - $.bodyDefaultFontsize,
				prefix	= (dif > 0) ? 'em-increased-' : 'em-decreased-',
				newCl 	= []
			;
			dif = Math.abs(dif) + 1;
			while (dif-- > 1) {
				newCl.push(prefix + dif);
			}
			html[0].className = $.grep(html[0].className.split(' '), function(n){
				return (n.indexOf('em-increased-') !== 0 && n.indexOf('em-decreased-') !== 0);
			}).concat(newCl).join(' ');
		}
			
		
		$(function(){
			setTimeout(function(){
				body = document.body;
				addEmClass(test());
				html.bind('emchange', addEmClass);
				
				timer = setInterval(test, 999);
				
			}, 0);
		});
		return test;
	})();
		
	(function($){
		var allowFocus 		= true,
			currentFocus 	= document,
			supActiveElem 	= ('activeElement' in document),
			// Jaws 8/9 needs at least 54ms
			minFocusTimer 	= 120,
			focusTimer
		;
		
		function stopKeyFocus(e){
			allowFocus = false;
			setTimeout(function(){
				allowFocus = true;
			}, 1);
		}
		
		
		function addFocus(e){
			var jElm = $(e.target).addClass('a11y-focus');
			currentFocus = e.target;
			if(!supActiveElem){
				document.activeElement = e.target;
			}
			if(allowFocus){
				jElm.addClass('a11y-focus-key').trigger('keyfocus');
			}
		}
		
		$(document)
			.bind('mousedown click', stopKeyFocus)
			.bind('domfocusin', addFocus)
			.bind('focusout', function(e){
				$(e.target)
					.removeClass('a11y-focus-key a11y-focus-widget a11y-focus')
				;
			})
		;
		
		
		function addTabindex(jElm){
			var tabindex = jElm.attr('tabindex');
			if(!(tabindex || tabindex === 0)){
				jElm.css({outline: 'none'}).attr({tabindex: '-1'});
				if( !$.support.waiAria && jElm[0] ){
					jElm[0].hideFocus = true;
				}
			}
			return jElm;
		}
		
		$.fn.setFocus = function(opts){
			if(!this[0]){return this;}
			opts = $.extend({}, $.fn.setFocus.defaults, opts);
			var elem 			= this[0],
				jElm 			= $(elem),
				now				= new Date().getTime(),
				focusFn 		= function(){
								try{
									stopKeyFocus();
									elem.focus();
									jElm.addClass('a11y-focus-widget');
								} catch(e){}
							},
				fxParent
			;
			
			
			if(opts.addTabindex){
				addTabindex(jElm);
			}
			
			$.ui.SR.update();
			
			if( !opts.fast ){
				clearTimeout(focusTimer);
				
				//falsy focus bounce in ie / no scrollIntoView in ff workaround
				fxParent = jElm.closest(':animated', opts.context);
				if( fxParent[0] ){
					fxParent.queue(function(){
						var time = new Date().getTime() - now - minFocusTimer;
						time = (time > 9) ? time : 9;
						focusTimer = setTimeout( focusFn, time );
						setTimeout(function(){
							fxParent.dequeue();
						}, time + 2);
					});
				} else {
					focusTimer = setTimeout( focusFn, minFocusTimer );//min 54
				}
			} else {
				focusFn();
			}
			return this;
		};
		
		$.fn.setFocus.defaults = {
			addTabindex: true,
			fast: false,
			context: false
		};
			
	})(jQuery);
	
	/* hide/show */
	
	$.fn.ariaHide = function(){
		$.fn.hide.apply(this, arguments);
		return this.attr({'aria-hidden': 'true'});
	};
	
	$.fn.ariaShow = function(){
		$.fn.show.apply(this, arguments);
		return this.attr({'aria-hidden': 'false'});
	};
	
	
	/*
	 * SR-Update
	 */
	$.ui.SR = (function(){
		var input, val = 0, alertBox, boxTimer, statusBox, statusTimer;
		
		function init(){
			alertBox = $('<div class="a11y-hidden" role="alert" style="'+ offsetCSS +'" />').ariaHide().appendTo('body');
			statusBox = $('<div class="a11y-hidden" style="'+ offsetCSS +'"><div aria-live="polite" relevant="additions text" /> </div>').appendTo('body').find('div');
			input = $('<form role="presentation" action="#" class="aural" style="'+ offsetCSS +'"><input name="sr-update" id="sr-update" type="hidden" value="'+val+'" /></form>')
				.appendTo('body')
				.find('input')
				.ajaxComplete(update);
		}
		
		function update(){
			var posStyle, wrapperHeight;
			if(input){
				input[0].setAttribute('value', '' +(++val));
				setTimeout(function(){
					input[0].setAttribute('value', '' +(++val));
				}, 1);
			}
		}
		
		
		function alert(notice){
			clearTimeout(boxTimer);
			alertBox.ariaHide()
				.html(notice)
					.find('*')
					.attr({role: 'presentation'})
				.end()
				.ariaShow();
			
			boxTimer = setTimeout(function(){
				alertBox.ariaHide().empty();
			}, 999);
		}
		
		function giveStatus(text){
			
			text = $('<div>'+ text +'</div>')
					.find('*')
					.attr({role: 'presentation'})
				.end();
			statusBox.html(text);
			clearTimeout(statusTimer);
			statusTimer = setTimeout(function(){
				statusBox.empty();
			}, 999);
		}
		
		
		return {
			update: update,
			alert: alert,
			giveStatus: giveStatus,
			init: init
		};
	})();
	$($.ui.SR.init);
	
	/*
	 * getID-Exts
	 */
	
	if(!$.fn.getID){
		var uId = new Date().getTime();
		$.fn.getID = function(setAll){
			
			function setID(){
				var id 		= this.getAttribute('id');
				if(!id){
					id = 'ID-' + (uId++);
					this.setAttribute('id', id);
				}
				return id;
			}
			if(this[0]){
				if(setAll){
					this.each(setID);
				}
				return setID.call(this[0]);
			}
			return undefined;
		};
	}
	
	$.each({
		labelWith: 'aria-labelledby',
		describeWith: 'aria-describedby',
		ownsThis: 'aria-owns',
		controlsThis: 'aria-controls',
		activateThis: 'aria-activedescendant'
	}, function(name, prop){
		$.fn[name] = function(elem){
			return this.attr(prop, $(elem).getID());
		};
	});
	
	/*
	*  inout
	*  hover = focusblur
	*/
		
	$.fn.inOut = function(enter, out, opts){
		opts = $.extend({}, $.fn.inOut.defaults, opts);
		
		var eventTypes 	= 'mouseenter mouseleave focusin focusout';
		
		if(opts.useEventTypes === 'mouse'){
			eventTypes = 'mouseenter mouseleave';
		} else if(opts.useEventTypes === 'focus'){
			eventTypes = 'focusin focusout';
		}
		
		

		this
			.each(function(){
				var inOutData = {inEvents: 0};
				function handler(e){
					var fn,
						params,
						elem = this,
						evt
					;
					if(/focusin|mouseenter/.test(e.type)){
						fn = enter;
						params =  [1, 'in', true]; 
					} else {
						fn = out;
						params = [-1, 'out', false];
					}
										
					clearTimeout(inOutData.inOutTimer);
					inOutData.inEvents = Math.max(inOutData.inEvents + params[0], 0);
					inOutData.inOutTimer = setTimeout(function(){
						if(params[2] != inOutData.inOutState && 
								(params[2] || !opts.bothOut || !inOutData.inEvents)){
							inOutData.inOutState = params[2];
							evt = $.Event(params[1]);
							evt.originalEvent = e;
							fn.call(elem, evt);
						}
					}, /focus/.test(e.type) ? opts.keyDelay : opts.mouseDelay);
				}
				$(this)[opts.bindStyle](eventTypes, handler);
			});
		return this;
	};
	
	$.fn.inOut.defaults = {
		mouseDelay: 0,
		bindStyle: 'bind', // bind | live | bubbleLive
		keyDelay: 1,
		bothOut: false,
		useEventTypes: 'both' // both || mouse || focus
	};
	
	
	$.fn.slideParentDown = function(opts){
		opts = $.extend({}, $.fn.slideParentDown.defaults, opts);
		var fn = opts.complete;
		
		return this.each(function(){
			
			var jElm 		= $(this),
				parent		= jElm.parent().css({height: ''}),
				outerHeight
			;
			jElm
				.css((opts.hideStyle === 'visibility') ? {visibility: ''} : {display: 'block'})
			;
			outerHeight = parent.height();
						
			parent
				.css({overflow: 'hidden', height: '0px'})
				.animate(
					{
						height: outerHeight
					}, 
					$.extend({}, opts, {complete: function(){
						parent.css({height: ''});
						fn.apply(this, arguments);
					}})
				)
			;
			
			
		});
	};
	$.fn.slideParentDown.defaults = {
		duration: 400,
		complete: $.noop,
		hideStyle: 'display'
	};
		
	$.fn.slideParentUp = function(opts){
		opts = $.extend({}, $.fn.slideParentUp.defaults, opts);
		var fn = opts.complete;
		return this.each(function(){
			var jElm 		= $(this),
				parent		= jElm.parent().css({overflow: 'hidden'}),
				cssProp 	= {height: '0px'}
			;
			if($.browser.mozilla && opts.flickrFix){
				cssProp.flickrFix = Math.random() * 2;
			}
			parent
				.animate(cssProp, $.extend({}, opts, {
					complete: function(){
						if(opts.hideStyle === 'visibility'){
							jElm.css({visibility: 'hidden'});
						} else {
							jElm.css({display: 'none'});
							parent.css({height: '', overflow: '', display: ''});
						}
						fn.apply(this, arguments);
					}
				}));
		});
	};
	$.fn.slideParentUp.defaults = {
		duration: 400,
		hideStyle: 'display',
		complete: $.noop,
		flickrFix: false
	};
})(jQuery);
