/**
 * @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.srfocusable = function(elem){
		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 = ['p', 'li', 'dt', 'dd', 'blockquote', 'address', 'th', 'td', 'dfn'];
	exp.semanticAtom = function(elem){
		var name = elem.nodeName.toLowerCase();
		return ( exp.srfocusable(elem) || $.inArray(name, semanticAtom) !== -1);
	};
	
	$.fn.firstExpOf = function(sel){
		var elems 	= $('*', this),
			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;
	};
	
	$.fn.lastExpOf = function(sel){
		var elems 	= $('*', this),
			len 	= elems.length,
			ret
		;
		while(len--){
			if(exp[sel](elems[i], i)){
				ret = [elems[len]];
				break;
			}
		}
		return this.pushStack(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);
				}
            }
		};
		
	});
	
	
})(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
	};
});
	 
	$.each({
		focus: 'focusin',
		blur: 'focusout'	
	}, function( original, fix ){
		$.event.special[fix] = {
			setup:function() {
				if ( $.browser.msie ) return false;
				this.addEventListener( original, $.event.special[fix].handler, true );
			},
			teardown:function() {
				if ( $.browser.msie ) return false;
				this.removeEventListener( original,
				$.event.special[fix].handler, true );
			},
			handler: function(e) {
				arguments[0] = $.event.fix(e);
				arguments[0].type = fix;
				return $.event.handle.apply(this, arguments);
			}
		};
	});
	
	$.ui = $.ui ||
		{};
	/*
	 * 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;
			}
			
		}
		$.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 emElem = $('<div style="width: 1em; position: absolute; padding: 0; border: none; margin: 0; visibility: hidden;top: 0;'+ offsetDir +'" />'),
			timer,
			emPx = 0,
			oldVal = 0,
			html = $(document.documentElement)
		;
				
		function test(){
			var width = emElem.width(), e;
			
			if(emPx !== width){
				emPx = width;
				e = {
					type: 'emchange',
					emPx: emPx,
					oldEmPx: oldVal
				};
				$.event.trigger(e);
			}
			oldVal = width;
			emPx = width;
			
			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(){
				emElem.appendTo('body');
				addEmClass(test());
				html.bind('emchange', addEmClass);
				
				timer = setInterval(test, 999);
				
			}, 0);
		});
		return test;
	})();
		
	(function($){
		var allowFocus 	= true,
			focusTime 	= 0,
			currentFocus = document,
			focusTimer
		;
		
		function stopKeyFocus(e){
			allowFocus = false;
			setTimeout(function(){
				allowFocus = true;
			}, 1);
		}
		
		
		function addFocus(e){
			var jElm = $(e.target).addClass('a11y-focus');
			currentFocus = e.target;
			focusTime = new Date().getTime();
			
			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){
			if(!jElm.is('a[href], area, input, button, select, textarea')){
				jElm.css({outline: 'none'}).attr({tabindex: '-1'});
			}
			return jElm;
		}
		
		$.fn.setFocus = function(time, doTabI){
			if(!this[0]){return this;}
			
			var elem 		= this[0],
				jElm 		= $(elem),
				opts 		= {},
				extraDelay 	= 1,
				focusFn		= function(){
								var refocus = currentFocus;
								setTimeout(function(){
									stopKeyFocus();
									try{
										elem.focus();
										jElm.addClass('a11y-focus-widget');
										opts.complete.apply(elem, arguments);
									} catch(e){}
								}, extraDelay);
								
								try{
									if(extraDelay > 9 && refocus.blur && refocus.focus){
										refocus.blur();
										stopKeyFocus();
										if(focusBefore && document.focus){
											document.focus();
										}
										refocus.focus();
									}
								} catch(e){}
							},
				queueFn 	= function(){
								opts.parent.queue(function(){
									focusFn();
									opts.parent.dequeue();
								});
							},
				focusBefore
			;
			
			if(isFinite(time)){
				opts.time = time;
				if(doTabI !== undefined){
					opts.addTabindex = doTabI;
				}
			} else {
				opts = time;
			}
			opts = $.extend({}, $.fn.setFocus.defaults, opts);
			focusBefore = (opts.compMode && $.unique(jElm.add(currentFocus))[0] === currentFocus);
			if(opts.addTabindex){
				addTabindex(jElm);
			}
			
			if(opts.compMode && (focusBefore || new Date().getTime() - focusTime > 180)){
				extraDelay = 120;
				opts.time = Math.max(opts.time - extraDelay, 120);
			}
			$.ui.SR.update();
			clearTimeout(focusTimer);
			focusTimer = setTimeout(opts.parent ? queueFn : focusFn, opts.time);
			return this;
		};
		
		$.fn.setFocus.defaults = {
			time: 200,
			addTabindex: false,
			parent: false,
			compMode: true,
			complete: function(){}
		};
			
	})(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;
		};
	}
	
	$.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',
			selector 	= this.selector,
			context 	= this.context
		;
		
		if(opts.useEventTypes === 'mouse'){
			eventTypes = 'mouseenter mouseleave';
		} else if(opts.useEventTypes === 'focus'){
			eventTypes = 'focusin focusout';
		}
		
		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];
			}
			
			var inOutData = $.data(this, 'inOutData');
			
			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
			.each(function(){
				$(this).data('inOutData', {inEvents: 0});
			})
			[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).css({display: 'block'}),
				parent		= jElm.parent().css({height: ''}),
				outerHeight = parent.height()
			;
			parent.css({overflow: 'hidden', height: '0px'});
			parent.animate(
				{
					height: outerHeight
				}, 
				$.extend({}, opts, {complete: function(){
					parent.css({height: '', overflow: ''});
					fn.apply(this, arguments);
				}})
			);
		});
	};
	$.fn.slideParentDown.defaults = {
		duration: 400,
		complete: function(){}
	};
		
	$.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(){
						jElm.css({display: 'none'});
						parent.css({height: '', overflow: '', display: ''});
						fn.apply(this, arguments);
					}
				}));
		});
	};
	$.fn.slideParentUp.defaults = {
		duration: 400,
		complete: function(){},
		flickrFix: false
	};
})(jQuery);
