text: //innerShiv for IE8-
  (function($){
  	if(Modernizr.genericDOM){return;}
  	var webshims = $.webshims;
  	var doc = document;
  	var b;
  	var d;
  	var rtagName = /<([\w:]+)/;
  	var wrapMap = {
  		option: 1,
  		optgroup: 1,
  		legend: 1,
  		thead: 1,
  		tr: 1,
  		td: 1,
  		col: 1,
  		area: 1
  	};
  	
  	
  	var htmlExp = /^(?:[^<]*(<[\w\W]+>)[^>]*$)/;
  	
  	webshims.fixHTML5 = function(h) {
  			if(typeof h != 'string' || wrapMap[ (rtagName.exec(h) || ["", ""])[1].toLowerCase() ]){return h;}
  			if (!d) {
  				b = doc.body;
  				if(!b){return h;}
  				d = doc.createElement('div');
  				d.style.display = 'none';
  			}
  			var e = d.cloneNode(false);
  			b.appendChild(e);
  			e.innerHTML = h;
  			b.removeChild(e);
  			return e.childNodes;
  		}
  	;
  
  })(jQuery);
  
  //DOM-Extension helper
  jQuery.webshims.register('dom-extend', function($, webshims, window, document, undefined){
  	"use strict";
  	//shortcus
  	var modules = webshims.modules;
  	var listReg = /\s*,\s*/;
  		
  	//proxying attribute
  	var olds = {};
  	var havePolyfill = {};
  	var extendedProps = {};
  	var extendQ = {};
  	var modifyProps = {};
  	
  	var oldVal = $.fn.val;
  	var singleVal = function(elem, name, val, pass, _argless){
  		return (_argless) ? oldVal.call($(elem)) : oldVal.call($(elem), val);
  	};
  	$.fn.val = function(val){
  		var elem = this[0];
  		if(arguments.length && val == null){
  			val = '';
  		}
  		if(!arguments.length){
  			if(!elem || elem.nodeType !== 1){return oldVal.call(this);}
  			return $.prop(elem, 'value', val, 'val', true);
  		}
  		if($.isArray(val)){
  			return oldVal.apply(this, arguments);
  		}
  		var isFunction = $.isFunction(val);
  		return this.each(function(i){
  			elem = this;
  			if(elem.nodeType === 1){
  				if(isFunction){
  					var genVal = val.call( elem, i, $.prop(elem, 'value', undefined, 'val', true));
  					if(genVal == null){
  						genVal = '';
  					}
  					$.prop(elem, 'value', genVal, 'val') ;
  				} else {
  					$.prop(elem, 'value', val, 'val');
  				}
  			}
  		});
  	};
  	
  	var dataID = '_webshimsLib'+ (Math.round(Math.random() * 1000));
  	var elementData = function(elem, key, val){
  		elem = elem.jquery ? elem[0] : elem;
  		if(!elem){return val || {};}
  		var data = $.data(elem, dataID);
  		if(val !== undefined){
  			if(!data){
  				data = $.data(elem, dataID, {});
  			}
  			if(key){
  				data[key] = val;
  			}
  		}
  		
  		return key ? data && data[key] : data;
  	};
  
  
  	[{name: 'getNativeElement', prop: 'nativeElement'}, {name: 'getShadowElement', prop: 'shadowElement'}, {name: 'getShadowFocusElement', prop: 'shadowFocusElement'}].forEach(function(data){
  		$.fn[data.name] = function(){
  			return this.map(function(){
  				var shadowData = elementData(this, 'shadowData');
  				return shadowData && shadowData[data.prop] || this;
  			});
  		};
  	});
  	
  	
  	
  	
  	['removeAttr', 'prop', 'attr'].forEach(function(type){
  		olds[type] = $[type];
  		$[type] = function(elem, name, value, pass, _argless){
  			var isVal = (pass == 'val');
  			var oldMethod = !isVal ? olds[type] : singleVal;
  			if( !elem || !havePolyfill[name] || elem.nodeType !== 1 || (!isVal && pass && type == 'attr' && $.attrFn[name]) ){
  				return oldMethod(elem, name, value, pass, _argless);
  			}
  			
  			var nodeName = (elem.nodeName || '').toLowerCase();
  			var desc = extendedProps[nodeName];
  			var curType = (type == 'attr' && (value === false || value === null)) ? 'removeAttr' : type;
  			var propMethod;
  			var oldValMethod;
  			var ret;
  			
  			
  			if(!desc){
  				desc = extendedProps['*'];
  			}
  			if(desc){
  				desc = desc[name];
  			}
  			
  			if(desc){
  				propMethod = desc[curType];
  			}
  			
  			if(propMethod){
  				if(name == 'value'){
  					oldValMethod = propMethod.isVal;
  					propMethod.isVal = isVal;
  				}
  				if(curType === 'removeAttr'){
  					return propMethod.value.call(elem);	
  				} else if(value === undefined){
  					return (propMethod.get) ? 
  						propMethod.get.call(elem) : 
  						propMethod.value
  					;
  				} else if(propMethod.set) {
  					if(type == 'attr' && value === true){
  						value = name;
  					}
  					
  					ret = propMethod.set.call(elem, value);
  				}
  				if(name == 'value'){
  					propMethod.isVal = oldValMethod;
  				}
  			} else {
  				ret = oldMethod(elem, name, value, pass, _argless);
  			}
  			if((value !== undefined || curType === 'removeAttr') && modifyProps[nodeName] && modifyProps[nodeName][name]){
  				
  				var boolValue;
  				if(curType == 'removeAttr'){
  					boolValue = false;
  				} else if(curType == 'prop'){
  					boolValue = !!(value);
  				} else {
  					boolValue = true;
  				}
  				
  				modifyProps[nodeName][name].forEach(function(fn){
  					if(!fn.only || (fn.only = 'prop' && type == 'prop') || (fn.only == 'attr' && type != 'prop')){
  						fn.call(elem, value, boolValue, (isVal) ? 'val' : curType, type);
  					}
  				});
  			}
  			return ret;
  		};
  		
  		extendQ[type] = function(nodeName, prop, desc){
  			
  			if(!extendedProps[nodeName]){
  				extendedProps[nodeName] = {};
  			}
  			if(!extendedProps[nodeName][prop]){
  				extendedProps[nodeName][prop] = {};
  			}
  			var oldDesc = extendedProps[nodeName][prop][type];
  			var getSup = function(propType, descriptor, oDesc){
  				if(descriptor && descriptor[propType]){
  					return descriptor[propType];
  				}
  				if(oDesc && oDesc[propType]){
  					return oDesc[propType];
  				}
  				if(type == 'prop' && prop == 'value'){
  					return function(value){
  						var elem = this;
  						return (desc.isVal) ? 
  							singleVal(elem, prop, value, false, (arguments.length === 0)) : 
  							olds[type](elem, prop, value)
  						;
  					};
  				}
  				if(type == 'prop' && propType == 'value' && desc.value.apply){
  					return  function(value){
  						var sup = olds[type](this, prop);
  						if(sup && sup.apply){
  							sup = sup.apply(this, arguments);
  						} 
  						return sup;
  					};
  				}
  				return function(value){
  					return olds[type](this, prop, value);
  				};
  			};
  			extendedProps[nodeName][prop][type] = desc;
  			if(desc.value === undefined){
  				if(!desc.set){
  					desc.set = desc.writeable ? 
  						getSup('set', desc, oldDesc) : 
  						(webshims.cfg.useStrict && prop == 'prop') ? 
  							function(){throw(prop +' is readonly on '+ nodeName);} : 
  							$.noop
  					;
  				}
  				if(!desc.get){
  					desc.get = getSup('get', desc, oldDesc);
  				}
  				
  			}
  			
  			['value', 'get', 'set'].forEach(function(descProp){
  				if(desc[descProp]){
  					desc['_sup'+descProp] = getSup(descProp, oldDesc);
  				}
  			});
  		};
  		
  	});
  	
  	//see also: https://github.com/lojjic/PIE/issues/40 | https://prototype.lighthouseapp.com/projects/8886/tickets/1107-ie8-fatal-crash-when-prototypejs-is-loaded-with-rounded-cornershtc
  	var isExtendNativeSave = (!$.browser.msie || parseInt($.browser.version, 10) > 8);
  	var extendNativeValue = (function(){
  		var UNKNOWN = webshims.getPrototypeOf(document.createElement('foobar'));
  		var has = Object.prototype.hasOwnProperty;
  		return function(nodeName, prop, desc){
  			var elem = document.createElement(nodeName);
  			var elemProto = webshims.getPrototypeOf(elem);
  			if( isExtendNativeSave && elemProto && UNKNOWN !== elemProto && ( !elem[prop] || !has.call(elem, prop) ) ){
  				var sup = elem[prop];
  				desc._supvalue = function(){
  					if(sup && sup.apply){
  						return sup.apply(this, arguments);
  					}
  					return sup;
  				};
  				elemProto[prop] = desc.value;
  			} else {
  				desc._supvalue = function(){
  					var data = elementData(this, 'propValue');
  					if(data && data[prop] && data[prop].apply){
  						return data[prop].apply(this, arguments);
  					}
  					return data && data[prop];
  				};
  				initProp.extendValue(nodeName, prop, desc.value);
  			}
  			desc.value._supvalue = desc._supvalue;
  		};
  	})();
  		
  	var initProp = (function(){
  		
  		var initProps = {};
  		
  		webshims.addReady(function(context, contextElem){
  			var nodeNameCache = {};
  			var getElementsByName = function(name){
  				if(!nodeNameCache[name]){
  					nodeNameCache[name] = $(context.getElementsByTagName(name));
  					if(contextElem[0] && $.nodeName(contextElem[0], name)){
  						nodeNameCache[name] = nodeNameCache[name].add(contextElem);
  					}
  				}
  			};
  			
  			
  			$.each(initProps, function(name, fns){
  				getElementsByName(name);
  				if(!fns || !fns.forEach){
  					webshims.warn('Error: with '+ name +'-property. methods: '+ fns);
  					return;
  				}
  				fns.forEach(function(fn){
  					nodeNameCache[name].each(fn);
  				});
  			});
  			nodeNameCache = null;
  		});
  		
  		var tempCache;
  		var emptyQ = $([]);
  		var createNodeNameInit = function(nodeName, fn){
  			if(!initProps[nodeName]){
  				initProps[nodeName] = [fn];
  			} else {
  				initProps[nodeName].push(fn);
  			}
  			if($.isDOMReady){
  				(tempCache || $( document.getElementsByTagName(nodeName) )).each(fn);
  			}
  		};
  		
  		var elementExtends = {};
  		return {
  			createTmpCache: function(nodeName){
  				if($.isDOMReady){
  					tempCache = tempCache || $( document.getElementsByTagName(nodeName) );
  				}
  				return tempCache || emptyQ;
  			},
  			flushTmpCache: function(){
  				tempCache = null;
  			},
  			content: function(nodeName, prop){
  				createNodeNameInit(nodeName, function(){
  					var val =  $.attr(this, prop);
  					if(val != null){
  						$.attr(this, prop, val);
  					}
  				});
  			},
  			createElement: function(nodeName, fn){
  				createNodeNameInit(nodeName, fn);
  			},
  			extendValue: function(nodeName, prop, value){
  				createNodeNameInit(nodeName, function(){
  					$(this).each(function(){
  						var data = elementData(this, 'propValue', {});
  						data[prop] = this[prop];
  						this[prop] = value;
  					});
  				});
  			}
  		};
  	})();
  		
  	var createPropDefault = function(descs, removeType){
  		if(descs.defaultValue === undefined){
  			descs.defaultValue = '';
  		}
  		if(!descs.removeAttr){
  			descs.removeAttr = {
  				value: function(){
  					descs[removeType || 'prop'].set.call(this, descs.defaultValue);
  					descs.removeAttr._supvalue.call(this);
  				}
  			};
  		}
  	};
  	
  	$.extend(webshims, {
  
  		getID: (function(){
  			var ID = new Date().getTime();
  			return function(elem){
  				elem = $(elem);
  				var id = elem.attr('id');
  				if(!id){
  					ID++;
  					id = 'ID-'+ ID;
  					elem.attr('id', id);
  				}
  				return id;
  			};
  		})(),
  		extendUNDEFProp: function(obj, props){
  			$.each(props, function(name, prop){
  				if( !(name in obj) ){
  					obj[name] = prop;
  				}
  			});
  		},
  		//http://www.w3.org/TR/html5/common-dom-interfaces.html#reflect
  		createPropDefault: createPropDefault,
  		data: elementData,
  		moveToFirstEvent: (function(){
  			var getData = $._data ? '_data' : 'data';
  			return function(elem, eventType, bindType){
  				var events = ($[getData](elem, 'events') || {})[eventType];
  				var fn;
  				
  				if(events && events.length > 1){
  					fn = events.pop();
  					if(!bindType){
  						bindType = 'bind';
  					}
  					if(bindType == 'bind' && events.delegateCount){
  						events.splice( events.delegateCount, 0, fn);
  					} else {
  						events.unshift( fn );
  					}
  					
  					
  				}
  				elem = null;
  			};
  		})(),
  		addShadowDom: function(nativeElem, shadowElem, opts){
  			opts = opts || {};
  			if(nativeElem.jquery){
  				nativeElem = nativeElem[0];
  			}
  			if(shadowElem.jquery){
  				shadowElem = shadowElem[0];
  			}
  			if(!opts.shadowFocusElement){
  				opts.shadowFocusElement = shadowElem;
  			}
  			var nativeData = $.data(nativeElem, dataID) || $.data(nativeElem, dataID, {});
  			var shadowData = $.data(shadowElem, dataID) || $.data(shadowElem, dataID, {});
  			nativeData.hasShadow = shadowElem;
  			shadowData.nativeElement = nativeElem;
  			shadowData.shadowData = nativeData.shadowData = {
  				nativeElement: nativeElem,
  				shadowElement: shadowElem,
  				shadowFocusElement: opts.shadowFocusElement
  			};
  			if(opts.shadowChilds){
  				opts.shadowChilds.each(function(){
  					elementData(this, 'shadowData', shadowData.shadowData);
  				});
  			}
  			
  			if(opts.data){
  				nativeData.shadowData.data = opts.data;
  				shadowData.shadowData.data = opts.data;
  			}
  			opts = null;
  		},
  		propTypes: {
  			standard: function(descs, name){
  				createPropDefault(descs);
  				if(descs.prop){return;}
  				descs.prop = {
  					set: function(val){
  						descs.attr.set.call(this, ''+val);
  					},
  					get: function(){
  						return descs.attr.get.call(this) || descs.defaultValue;
  					}
  				};
  				
  			},
  			"boolean": function(descs, name){
  				
  				createPropDefault(descs);
  				if(descs.prop){return;}
  				descs.prop = {
  					set: function(val){
  						if(val){
  							descs.attr.set.call(this, "");
  						} else {
  							descs.removeAttr.value.call(this);
  						}
  					},
  					get: function(){
  						return descs.attr.get.call(this) != null;
  					}
  				};
  			}
  			
  //			,enumarated: $.noop
  //			,unsignedLong: $.noop
  //			,"doubble": $.noop
  //			,"long": $.noop
  //			,tokenlist: $.noop
  //			,settableTokenlist: $.noop
  		},
  		reflectProperties: function(nodeNames, props){
  			if(typeof props == 'string'){
  				props = props.split(listReg);
  			}
  			props.forEach(function(prop){
  				webshims.defineNodeNamesProperty(nodeNames, prop, {
  					prop: {
  						set: function(val){
  							$.attr(this, prop, val);
  						},
  						get: function(){
  							return $.attr(this, prop) || '';
  						}
  					}
  				});
  			});
  		},
  		defineNodeNameProperty: function(nodeName, prop, descs){
  			havePolyfill[prop] = true;
  						
  			if(descs.reflect){
  				webshims.propTypes[descs.propType || 'standard'](descs);
  			}
  			
  			['prop', 'attr', 'removeAttr'].forEach(function(type){
  				var desc = descs[type];
  				if(desc){
  					if(type === 'prop'){
  						desc = $.extend({writeable: true}, desc);
  					} else {
  						desc = $.extend({}, desc, {writeable: true});
  					}
  						
  					extendQ[type](nodeName, prop, desc);
  					if(nodeName != '*' && webshims.cfg.extendNative && type == 'prop' && desc.value && $.isFunction(desc.value)){
  						extendNativeValue(nodeName, prop, desc);
  					}
  					descs[type] = desc;
  				}
  			});
  			if(descs.initAttr){
  				initProp.content(nodeName, prop);
  			}
  			return descs;
  		},
  		
  		defineNodeNameProperties: function(name, descs, propType, _noTmpCache){
  			var olddesc;
  			for(var prop in descs){
  				if(!_noTmpCache && descs[prop].initAttr){
  					initProp.createTmpCache(name);
  				}
  				if(propType){
  					if(descs[prop][propType]){
  						webshims.log('override: '+ name +'['+prop +'] for '+ propType);
  					} else {
  						descs[prop][propType] = {};
  						['value', 'set', 'get'].forEach(function(copyProp){
  							if(copyProp in descs[prop]){
  								descs[prop][propType][copyProp] = descs[prop][copyProp];
  								delete descs[prop][copyProp];
  							}
  						});
  					}
  				}
  				descs[prop] = webshims.defineNodeNameProperty(name, prop, descs[prop]);
  			}
  			if(!_noTmpCache){
  				initProp.flushTmpCache();
  			}
  			return descs;
  		},
  		
  		createElement: function(nodeName, create, descs){
  			var ret;
  			if($.isFunction(create)){
  				create = {
  					after: create
  				};
  			}
  			initProp.createTmpCache(nodeName);
  			if(create.before){
  				initProp.createElement(nodeName, create.before);
  			}
  			if(descs){
  				ret = webshims.defineNodeNameProperties(nodeName, descs, false, true);
  			}
  			if(create.after){
  				initProp.createElement(nodeName, create.after);
  			}
  			initProp.flushTmpCache();
  			return ret;
  		},
  		onNodeNamesPropertyModify: function(nodeNames, props, desc, only){
  			if(typeof nodeNames == 'string'){
  				nodeNames = nodeNames.split(listReg);
  			}
  			if($.isFunction(desc)){
  				desc = {set: desc};
  			}
  			
  			nodeNames.forEach(function(name){
  				if(!modifyProps[name]){
  					modifyProps[name] = {};
  				}
  				if(typeof props == 'string'){
  					props = props.split(listReg);
  				}
  				if(desc.initAttr){
  					initProp.createTmpCache(name);
  				}
  				props.forEach(function(prop){
  					if(!modifyProps[name][prop]){
  						modifyProps[name][prop] = [];
  						havePolyfill[prop] = true;
  					}
  					if(desc.set){
  						if(only){
  							desc.set.only =  only;
  						}
  						modifyProps[name][prop].push(desc.set);
  					}
  					
  					if(desc.initAttr){
  						initProp.content(name, prop);
  					}
  				});
  				initProp.flushTmpCache();
  				
  			});
  		},
  		defineNodeNamesBooleanProperty: function(elementNames, prop, descs){
  			if(!descs){
  				descs = {};
  			}
  			if($.isFunction(descs)){
  				descs.set = descs;
  			}
  			webshims.defineNodeNamesProperty(elementNames, prop, {
  				attr: {
  					set: function(val){
  						this.setAttribute(prop, val);
  						if(descs.set){
  							descs.set.call(this, true);
  						}
  					},
  					get: function(){
  						var ret = this.getAttribute(prop);
  						return (ret == null) ? undefined : prop;
  					}
  				},
  				removeAttr: {
  					value: function(){
  						this.removeAttribute(prop);
  						if(descs.set){
  							descs.set.call(this, false);
  						}
  					}
  				},
  				reflect: true,
  				propType: 'boolean',
  				initAttr: descs.initAttr || false
  			});
  		},
  		contentAttr: function(elem, name, val){
  			if(!elem.nodeName){return;}
  			if(val === undefined){
  				val = (elem.attributes[name] || {}).value;
  				return (val == null) ? undefined : val;
  			}
  			
  			if(typeof val == 'boolean'){
  				if(!val){
  					elem.removeAttribute(name);
  				} else {
  					elem.setAttribute(name, name);
  				}
  			} else {
  				elem.setAttribute(name, val);
  			}
  		},
  		
  //		set current Lang:
  //			- webshims.activeLang(lang:string);
  //		get current lang
  //			- webshims.activeLang();
  //		get current lang
  //			webshims.activeLang({
  //				register: moduleName:string,
  //				callback: callback:function
  //			});
  //		get/set including removeLang
  //			- webshims.activeLang({
  //				module: moduleName:string,
  //				callback: callback:function,
  //				langObj: languageObj:array/object
  //			});
  		activeLang: (function(){
  			var callbacks = [];
  			var registeredCallbacks = {};
  			var currentLang;
  			var shortLang;
  			var notLocal = /:\/\/|^\.*\//;
  			var loadRemoteLang = function(data, lang, options){
  				var langSrc;
  				if(lang && options && $.inArray(lang, options.availabeLangs || []) !== -1){
  					data.loading = true;
  					langSrc = options.langSrc;
  					if(!notLocal.test(langSrc)){
  						langSrc = webshims.cfg.basePath+langSrc;
  					}
  					webshims.loader.loadScript(langSrc+lang+'.js', function(){
  						if(data.langObj[lang]){
  							data.loading = false;
  							callLang(data, true);
  						} else {
  							$(function(){
  								if(data.langObj[lang]){
  									callLang(data, true);
  								}
  								data.loading = false;
  							});
  						}
  					});
  					return true;
  				}
  				return false;
  			};
  			var callRegister = function(module){
  				if(registeredCallbacks[module]){
  					registeredCallbacks[module].forEach(function(data){
  						data.callback();
  					});
  				}
  			};
  			var callLang = function(data, _noLoop){
  				if(data.activeLang != currentLang && data.activeLang !== shortLang){
  					var options = modules[data.module].options;
  					if( data.langObj[currentLang] || (shortLang && data.langObj[shortLang]) ){
  						data.activeLang = currentLang;
  						data.callback(data.langObj[currentLang] || data.langObj[shortLang], currentLang);
  						callRegister(data.module);
  					} else if( !_noLoop &&
  						!loadRemoteLang(data, currentLang, options) && 
  						!loadRemoteLang(data, shortLang, options) && 
  						data.langObj[''] && data.activeLang !== '' ) {
  						data.activeLang = '';
  						data.callback(data.langObj[''], currentLang);
  						callRegister(data.module);
  					}
  				}
  			};
  			
  			
  			var activeLang = function(lang){
  				
  				if(typeof lang == 'string' && lang !== currentLang){
  					currentLang = lang;
  					shortLang = currentLang.split('-')[0];
  					if(currentLang == shortLang){
  						shortLang = false;
  					}
  					$.each(callbacks, function(i, data){
  						callLang(data);
  					});
  				} else if(typeof lang == 'object'){
  					
  					if(lang.register){
  						if(!registeredCallbacks[lang.register]){
  							registeredCallbacks[lang.register] = [];
  						}
  						registeredCallbacks[lang.register].push(lang);
  						lang.callback();
  					} else {
  						if(!lang.activeLang){
  							lang.activeLang = '';
  						}
  						callbacks.push(lang);
  						callLang(lang);
  					}
  				}
  				return currentLang;
  			};
  			
  			return activeLang;
  		})()
  	});
  	
  	$.each({
  		defineNodeNamesProperty: 'defineNodeNameProperty',
  		defineNodeNamesProperties: 'defineNodeNameProperties',
  		createElements: 'createElement'
  	}, function(name, baseMethod){
  		webshims[name] = function(names, a, b, c){
  			if(typeof names == 'string'){
  				names = names.split(listReg);
  			}
  			var retDesc = {};
  			names.forEach(function(nodeName){
  				retDesc[nodeName] = webshims[baseMethod](nodeName, a, b, c);
  			});
  			return retDesc;
  		};
  	});
  	
  	webshims.isReady('webshimLocalization', true);
  });
  //html5a11y
  (function($, document){
  	var browserVersion = $.webshims.browserVersion;
  	if($.browser.mozilla && browserVersion > 5){return;}
  	if (!$.browser.msie || (browserVersion < 12 && browserVersion > 7)) {
  		var elemMappings = {
  			article: "article",
  			aside: "complementary",
  			section: "region",
  			nav: "navigation",
  			address: "contentinfo"
  		};
  		var addRole = function(elem, role){
  			var hasRole = elem.getAttribute('role');
  			if (!hasRole) {
  				elem.setAttribute('role', role);
  			}
  		};
  		
  		$.webshims.addReady(function(context, contextElem){
  			$.each(elemMappings, function(name, role){
  				var elems = $(name, context).add(contextElem.filter(name));
  				for (var i = 0, len = elems.length; i < len; i++) {
  					addRole(elems[i], role);
  				}
  			});
  			if (context === document) {
  				var header = document.getElementsByTagName('header')[0];
  				var footers = document.getElementsByTagName('footer');
  				var footerLen = footers.length;
  				if (header && !$(header).closest('section, article')[0]) {
  					addRole(header, 'banner');
  				}
  				if (!footerLen) {
  					return;
  				}
  				var footer = footers[footerLen - 1];
  				if (!$(footer).closest('section, article')[0]) {
  					addRole(footer, 'contentinfo');
  				}
  			}
  		});
  	}
  })(jQuery, document);
  jQuery.webshims.register('form-datalist', function($, webshims, window, document, undefined){
  	var doc = document;	
  
  	/*
  	 * implement propType "element" currently only used for list-attribute (will be moved to dom-extend, if needed)
  	 */
  	webshims.propTypes.element = function(descs){
  		webshims.createPropDefault(descs, 'attr');
  		if(descs.prop){return;}
  		descs.prop = {
  			get: function(){
  				var elem = descs.attr.get.call(this);
  				if(elem){
  					elem = $('#'+elem)[0];
  					if(elem && descs.propNodeName && !$.nodeName(elem, descs.propNodeName)){
  						elem = null;
  					}
  				}
  				return elem || null;
  			},
  			writeable: false
  		};
  	};
  	
  	
  	/*
  	 * Implements datalist element and list attribute
  	 */
  	
  	(function(){
  		var formsCFG = $.webshims.cfg.forms;
  		var listSupport = Modernizr.input.list;
  		if(listSupport && !formsCFG.customDatalist){return;}
  		
  			var initializeDatalist =  function(){
  				
  				
  			if(!listSupport){
  				webshims.defineNodeNameProperty('datalist', 'options', {
  					prop: {
  						writeable: false,
  						get: function(){
  							var elem = this;
  							var select = $('select', elem);
  							var options;
  							if(select[0]){
  								options = select[0].options;
  							} else {
  								options = $('option', elem).get();
  								if(options.length){
  									webshims.warn('you should wrap you option-elements for a datalist in a select element to support IE and other old browsers.');
  								}
  							}
  							return options;
  						}
  					}
  				});
  			}
  				
  			var inputListProto = {
  				//override autocomplete
  				autocomplete: {
  					attr: {
  						get: function(){
  							var elem = this;
  							var data = $.data(elem, 'datalistWidget');
  							if(data){
  								return data._autocomplete;
  							}
  							return ('autocomplete' in elem) ? elem.autocomplete : elem.getAttribute('autocomplete');
  						},
  						set: function(value){
  							var elem = this;
  							var data = $.data(elem, 'datalistWidget');
  							if(data){
  								data._autocomplete = value;
  								if(value == 'off'){
  									data.hideList();
  								}
  							} else {
  								if('autocomplete' in elem){
  									elem.autocomplete = value;
  								} else {
  									elem.setAttribute('autocomplete', value);
  								}
  							}
  						}
  					}
  				}
  			};
  			
  			if(!listSupport || !('selectedOption') in $('<input />')[0]){
  				//currently not supported x-browser (FF4 has not implemented and is not polyfilled )
  				inputListProto.selectedOption = {
  					prop: {
  						writeable: false,
  						get: function(){
  							var elem = this;
  							var list = $.prop(elem, 'list');
  							var ret = null;
  							var value, options;
  							if(!list){return ret;}
  							value = $.attr(elem, 'value');
  							if(!value){return ret;}
  							options = $.prop(list, 'options');
  							if(!options.length){return ret;}
  							$.each(options, function(i, option){
  								if(value == $.prop(option, 'value')){
  									ret = option;
  									return false;
  								}
  							});
  							return ret;
  						}
  					}
  				};
  			}
  			
  			if(!listSupport){
  				inputListProto['list'] = {
  					attr: {
  						get: function(){
  							var val = webshims.contentAttr(this, 'list');
  							return (val == null) ? undefined : val;
  						},
  						set: function(value){
  							var elem = this;
  							webshims.contentAttr(elem, 'list', value);
  							webshims.objectCreate(shadowListProto, undefined, {input: elem, id: value, datalist: $.prop(elem, 'list')});
  						}
  					},
  					initAttr: true,
  					reflect: true,
  					propType: 'element',
  					propNodeName: 'datalist'
  				};
  			} else {
  				inputListProto['list'] = {
  					attr: {
  						get: function(){
  							var val = webshims.contentAttr(this, 'list');
  							if(val != null){
  								this.removeAttribute('list');
  							} else {
  								val = $.data(this, 'datalistListAttr');
  							}
  							return (val == null) ? undefined : val;
  						},
  						set: function(value){
  							var elem = this;
  							$.data(elem, 'datalistListAttr', value);
  							webshims.objectCreate(shadowListProto, undefined, {input: elem, id: value, datalist: $.prop(elem, 'list')});
  						}
  					},
  					initAttr: true,
  					reflect: true,
  					propType: 'element',
  					propNodeName: 'datalist'
  				};
  			}
  				
  				
  			webshims.defineNodeNameProperties('input', inputListProto);
  			
  			if($.event.customEvent){
  				$.event.customEvent.updateDatalist = true;
  				$.event.customEvent.updateInput = true;
  				$.event.customEvent.datalistselect = true;
  			} 
  			webshims.addReady(function(context, contextElem){
  				contextElem
  					.filter('datalist > select, datalist, datalist > option, datalist > select > option')
  					.closest('datalist')
  					.triggerHandler('updateDatalist')
  				;
  				
  			});
  			
  			
  		};
  		
  		
  		/*
  		 * ShadowList
  		 */
  		var listidIndex = 0;
  		
  		var noDatalistSupport = {
  			submit: 1,
  			button: 1,
  			reset: 1, 
  			hidden: 1,
  			
  			//ToDo
  			range: 1,
  			date: 1
  		};
  		var lteie6 = ($.browser.msie && parseInt($.browser.version, 10) < 7);
  		var globStoredOptions = {};
  		var getStoredOptions = function(name){
  			if(!name){return [];}
  			if(globStoredOptions[name]){
  				return globStoredOptions[name];
  			}
  			var data;
  			try {
  				data = JSON.parse(localStorage.getItem('storedDatalistOptions'+name));
  			} catch(e){}
  			globStoredOptions[name] = data || [];
  			return data || [];
  		};
  		var storeOptions = function(name, val){
  			if(!name){return;}
  			val = val || [];
  			try {
  				localStorage.setItem( 'storedDatalistOptions'+name, JSON.stringify(val) );
  			} catch(e){}
  		};
  		
  		var getText = function(elem){
  			return (elem.textContent || elem.innerText || $.text([ elem ]) || '');
  		};
  		
  		var shadowListProto = {
  			_create: function(opts){
  				
  				if(noDatalistSupport[$.prop(opts.input, 'type')]){return;}
  				var datalist = opts.datalist;
  				var data = $.data(opts.input, 'datalistWidget');
  				if(datalist && data && data.datalist !== datalist){
  					data.datalist = datalist;
  					data.id = opts.id;
  					$(data.datalist)
  						.unbind('updateDatalist.datalistWidget')
  						.bind('updateDatalist.datalistWidget', $.proxy(data, '_resetListCached'))
  					;
  					data._resetListCached();
  					return;
  				} else if(!datalist){
  					if(data){
  						data.destroy();
  					}
  					return;
  				} else if(data && data.datalist === datalist){
  					return;
  				}
  				listidIndex++;
  				var that = this;
  				this.hideList = $.proxy(that, 'hideList');
  				this.timedHide = function(){
  					clearTimeout(that.hideTimer);
  					that.hideTimer = setTimeout(that.hideList, 9);
  				};
  				this.datalist = datalist;
  				this.id = opts.id;
  				this.hasViewableData = true;
  				this._autocomplete = $.attr(opts.input, 'autocomplete');
  				$.data(opts.input, 'datalistWidget', this);
  				this.shadowList = $('<div class="datalist-polyfill" />');
  				
  				if(formsCFG.positionDatalist){
  					this.shadowList.insertAfter(opts.input);
  				} else {
  					this.shadowList.appendTo('body');
  				}
  				
  				this.index = -1;
  				this.input = opts.input;
  				this.arrayOptions = [];
  				
  				this.shadowList
  					.delegate('li', 'mouseenter.datalistWidget mousedown.datalistWidget click.datalistWidget', function(e){
  						var items = $('li:not(.hidden-item)', that.shadowList);
  						var select = (e.type == 'mousedown' || e.type == 'click');
  						that.markItem(items.index(e.currentTarget), select, items);
  						if(e.type == 'click'){
  							that.hideList();
  							$(opts.input).trigger('datalistselect');
  						}
  						return (e.type != 'mousedown');
  					})
  					.bind('focusout', this.timedHide)
  				;
  				
  				opts.input.setAttribute('autocomplete', 'off');
  				
  				$(opts.input)
  					.attr({
  						//role: 'combobox',
  						'aria-haspopup': 'true'
  					})
  					.bind('input.datalistWidget', function(){
  						if(!that.triggeredByDatalist){
  							that.changedValue = false;
  							that.showHideOptions();
  						}
  					})
  					
  					.bind('keydown.datalistWidget', function(e){
  						var keyCode = e.keyCode;
  						var activeItem;
  						var items;
  						if(keyCode == 40 && !that.showList()){
  							that.markItem(that.index + 1, true);
  							return false;
  						}
  						
  						if(!that.isListVisible){return;}
  						
  						 
  						if(keyCode == 38){
  							that.markItem(that.index - 1, true);
  							return false;
  						} 
  						if(!e.shiftKey && (keyCode == 33 || keyCode == 36)){
  							that.markItem(0, true);
  							return false;
  						} 
  						if(!e.shiftKey && (keyCode == 34 || keyCode == 35)){
  							items = $('li:not(.hidden-item)', that.shadowList);
  							that.markItem(items.length - 1, true, items);
  							return false;
  						} 
  						if(keyCode == 13 || keyCode == 27){
  							if (keyCode == 13){
  								activeItem = $('li.active-item:not(.hidden-item)', that.shadowList);
  								that.changeValue( $('li.active-item:not(.hidden-item)', that.shadowList) );
  							}
  							that.hideList();
  							if(activeItem && activeItem[0]){
  								$(opts.input).trigger('datalistselect');
  							}
  							return false;
  						}
  					})
  					.bind('focus.datalistWidget', function(){
  						if($(this).hasClass('list-focus')){
  							that.showList();
  						}
  					})
  					.bind('mousedown.datalistWidget', function(){
  						if(this == document.activeElement || $(this).is(':focus')){
  							that.showList();
  						}
  					})
  					.bind('blur.datalistWidget', this.timedHide)
  				;
  				
  				
  				$(this.datalist)
  					.unbind('updateDatalist.datalistWidget')
  					.bind('updateDatalist.datalistWidget', $.proxy(this, '_resetListCached'))
  				;
  				
  				this._resetListCached();
  				
  				if(opts.input.form && opts.input.id){
  					$(opts.input.form).bind('submit.datalistWidget'+opts.input.id, function(){
  						var val = $.prop(opts.input, 'value');
  						var name = (opts.input.name || opts.input.id) + $.prop(opts.input, 'type');
  						if(!that.storedOptions){
  							that.storedOptions = getStoredOptions( name );
  						}
  						if(val && that.storedOptions.indexOf(val) == -1){
  							that.storedOptions.push(val);
  							storeOptions(name, that.storedOptions );
  						}
  					});
  				}
  				$(window).bind('unload', function(){
  					that.destroy();
  				});
  			},
  			destroy: function(){
  				var autocomplete = $.attr(this.input, 'autocomplete');
  				$(this.input)
  					.unbind('.datalistWidget')
  					.removeData('datalistWidget')
  				;
  				this.shadowList.remove();
  				$(document).unbind('.datalist'+this.id);
  				if(this.input.form && this.input.id){
  					$(this.input.form).unbind('submit.datalistWidget'+this.input.id);
  				}
  				this.input.removeAttribute('aria-haspopup');
  				if(autocomplete === undefined){
  					this.input.removeAttribute('autocomplete');
  				} else {
  					$(this.input).attr('autocomplete', autocomplete);
  				}
  			},
  			_resetListCached: function(e){
  				var that = this;
  				var forceShow;
  				this.needsUpdate = true;
  				this.lastUpdatedValue = false;
  				this.lastUnfoundValue = '';
  
  				if(!this.updateTimer){
  					if(window.QUnit || (forceShow = (e && document.activeElement == that.input))){
  						that.updateListOptions(forceShow);
  					} else {
  						webshims.ready('WINDOWLOAD', function(){
  							that.updateTimer = setTimeout(function(){
  								that.updateListOptions();
  								that = null;
  								listidIndex = 1;
  							}, 200 + (100 * listidIndex));
  						});
  					}
  				}
  			},
  			updateListOptions: function(_forceShow){
  				this.needsUpdate = false;
  				clearTimeout(this.updateTimer);
  				this.updateTimer = false;
  				this.shadowList
  					.css({
  						fontSize: $.curCSS(this.input, 'fontSize'),
  						fontFamily: $.curCSS(this.input, 'fontFamily')
  					})
  				;
  				this.searchStart = $(this.input).hasClass('search-start');
  				
  				var list = [];
  				
  				var values = [];
  				var allOptions = [];
  				var rElem, rItem, rOptions, rI, rLen, item;
  				for(rOptions = $.prop(this.datalist, 'options'), rI = 0, rLen = rOptions.length; rI < rLen; rI++){
  					rElem = rOptions[rI];
  					if(rElem.disabled){return;}
  					rItem = {
  						value: $(rElem).val() || '',
  						text: $.trim($.attr(rElem, 'label') || getText(rElem)),
  						className: rElem.className || '',
  						style: $.attr(rElem, 'style') || ''
  					};
  					if(!rItem.text){
  						rItem.text = rItem.value;
  					} else if(rItem.text != rItem.value){
  						rItem.className += ' different-label-value';
  					}
  					values[rI] = rItem.value;
  					allOptions[rI] = rItem;
  				}
  				
  				if(!this.storedOptions){
  					this.storedOptions = getStoredOptions((this.input.name || this.input.id) + $.prop(this.input, 'type'));
  				}
  				
  				this.storedOptions.forEach(function(val, i){
  					if(values.indexOf(val) == -1){
  						allOptions.push({value: val, text: val, className: 'stored-suggest', style: ''});
  					}
  				});
  				
  				for(rI = 0, rLen = allOptions.length; rI < rLen; rI++){
  					item = allOptions[rI];
  					list[rI] = '<li class="'+ item.className +'" style="'+ item.style +'" tabindex="-1" role="listitem"><span class="option-label">'+ item.text +'</span> <span class="option-value">'+item.value+'</span></li>';
  				}
  				
  				this.arrayOptions = allOptions;
  				this.shadowList.html('<div><ul role="list" class="'+ (this.datalist.className || '') + ' '+ this.datalist.id +'-shadowdom' +'">'+ list.join("\n") +'</ul></div>');
  				
  				if($.fn.bgIframe && lteie6){
  					this.shadowList.bgIframe();
  				}
  				
  				if(_forceShow || this.isListVisible){
  					this.showHideOptions();
  				}
  			},
  			showHideOptions: function(_fromShowList){
  				var value = $.prop(this.input, 'value').toLowerCase();
  				//first check prevent infinite loop, second creates simple lazy optimization
  				if(value === this.lastUpdatedValue || (this.lastUnfoundValue && value.indexOf(this.lastUnfoundValue) === 0)){
  					return;
  				}
  				
  				this.lastUpdatedValue = value;
  				var found = false;
  				var startSearch = this.searchStart;
  				var lis = $('li', this.shadowList);
  				if(value){
  					this.arrayOptions.forEach(function(item, i){
  						var search;
  						if(!('lowerText' in item)){
  							if(item.text != item.value){
  								item.lowerText = item.text.toLowerCase() +  item.value.toLowerCase();
  							} else {
  								item.lowerText = item.text.toLowerCase();
  							}
  						}
  						search = item.lowerText.indexOf(value);
  						search = startSearch ? !search : search !== -1;
  						if(search){
  							$(lis[i]).removeClass('hidden-item');
  							found = true;
  						} else {
  							$(lis[i]).addClass('hidden-item');
  						}
  					});
  				} else if(lis.length) {
  					lis.removeClass('hidden-item');
  					found = true;
  				}
  				
  				this.hasViewableData = found;
  				if(!_fromShowList && found){
  					this.showList();
  				}
  				if(!found){
  					this.lastUnfoundValue = value;
  					this.hideList();
  				}
  			},
  			setPos: function(){
  				var css = (formsCFG.positionDatalist) ? $(this.input).position() : webshims.getRelOffset(this.shadowList, this.input);
  				css.top += $(this.input).outerHeight();
  				css.width = $(this.input).outerWidth() - (parseInt(this.shadowList.css('borderLeftWidth'), 10)  || 0) - (parseInt(this.shadowList.css('borderRightWidth'), 10)  || 0);
  				this.shadowList.css(css);
  				return css;
  			},
  			showList: function(){
  				if(this.isListVisible){return false;}
  				if(this.needsUpdate){
  					this.updateListOptions();
  				}
  				this.showHideOptions(true);
  				if(!this.hasViewableData){return false;}
  				this.isListVisible = true;
  				var that = this;
  				var resizeTimer;
  				
  				that.setPos();
  				that.shadowList.addClass('datalist-visible');
  				
  				$(document).unbind('.datalist'+that.id).bind('mousedown.datalist'+that.id +' focusin.datalist'+that.id, function(e){
  					if(e.target === that.input ||  that.shadowList[0] === e.target || $.contains( that.shadowList[0], e.target )){
  						clearTimeout(that.hideTimer);
  						setTimeout(function(){
  							clearTimeout(that.hideTimer);
  						}, 9);
  					} else {
  						that.timedHide();
  					}
  				});
  				$(window)
  					.unbind('.datalist'+that.id)
  					.bind('resize.datalist'+that.id +'orientationchange.datalist '+that.id +' emchange.datalist'+that.id, function(){
  						clearTimeout(resizeTimer);
  						resizeTimer = setTimeout(function(){
  							that.setPos();
  						}, 9);
  					})
  				;
  				clearTimeout(resizeTimer);
  				return true;
  			},
  			hideList: function(){
  				if(!this.isListVisible){return false;}
  				var that = this;
  				var triggerChange = function(e){
  					if(that.changedValue){
  						$(that.input).trigger('change');
  					}
  					that.changedValue = false;
  				};
  				that.shadowList
  					.removeClass('datalist-visible list-item-active')
  					.scrollTop(0)
  					.find('li.active-item').removeClass('active-item')
  				;
  				that.index = -1;
  				that.isListVisible = false;
  				if(that.changedValue){
  					that.triggeredByDatalist = true;
  					webshims.triggerInlineForm && webshims.triggerInlineForm(that.input, 'input');
  					if(that.input == document.activeElement || $(that.input).is(':focus')){
  						$(that.input).one('blur', triggerChange);
  					} else {
  						triggerChange();
  					}
  					that.triggeredByDatalist = false;
  				}
  				$(document).unbind('.datalist'+that.id);
  				$(window).unbind('.datalist'+that.id);
  				return true;
  			},
  			scrollIntoView: function(elem){
  				var ul = $('ul', this.shadowList);
  				var div = $('div', this.shadowList);
  				var elemPos = elem.position();
  				var containerHeight;
  				elemPos.top -=  (parseInt(ul.css('paddingTop'), 10) || 0) + (parseInt(ul.css('marginTop'), 10) || 0) + (parseInt(ul.css('borderTopWidth'), 10) || 0);
  				if(elemPos.top < 0){
  					div.scrollTop( div.scrollTop() + elemPos.top - 2);
  					return;
  				}
  				elemPos.top += elem.outerHeight();
  				containerHeight = div.height();
  				if(elemPos.top > containerHeight){
  					div.scrollTop( div.scrollTop() + (elemPos.top - containerHeight) + 2);
  				}
  			},
  			changeValue: function(activeItem){
  				if(!activeItem[0]){return;}
  				var newValue = $('span.option-value', activeItem).text();
  				var oldValue = $.prop(this.input, 'value');
  				if(newValue != oldValue){
  					$(this.input)
  						.prop('value', newValue)
  						.triggerHandler('updateInput')
  					;
  					this.changedValue = true;
  				}
  			},
  			markItem: function(index, doValue, items){
  				var activeItem;
  				var goesUp;
  				
  				items = items || $('li:not(.hidden-item)', this.shadowList);
  				if(!items.length){return;}
  				if(index < 0){
  					index = items.length - 1;
  				} else if(index >= items.length){
  					index = 0;
  				}
  				items.removeClass('active-item');
  				this.shadowList.addClass('list-item-active');
  				activeItem = items.filter(':eq('+ index +')').addClass('active-item');
  				
  				if(doValue){
  					this.changeValue(activeItem);
  					this.scrollIntoView(activeItem);
  				}
  				this.index = index;
  			}
  		};
  		
  		//init datalist update
  		initializeDatalist();
  	})();
  	
  });//additional tests for partial implementation of forms features
  (function($){
  	var Modernizr = window.Modernizr;
  	var webshims = $.webshims;
  	var bugs = webshims.bugs;
  	var form = $('<form action="#" style="width: 1px; height: 1px; overflow: hidden;"><select name="b" required /><input type="date" required name="a" /><input type="submit" /></form>');
  	var testRequiredFind = function(){
  		if(form[0].querySelector){
  			try {
  				bugs.findRequired = !(form[0].querySelector('select:required'));
  			} catch(er){
  				bugs.findRequired = false;
  			}
  		}
  	};
  	bugs.findRequired = false;
  	bugs.validationMessage = false;
  	bugs.valueAsNumberSet = false;
  	
  	webshims.capturingEventPrevented = function(e){
  		if(!e._isPolyfilled){
  			var isDefaultPrevented = e.isDefaultPrevented;
  			var preventDefault = e.preventDefault;
  			e.preventDefault = function(){
  				clearTimeout($.data(e.target, e.type + 'DefaultPrevented'));
  				$.data(e.target, e.type + 'DefaultPrevented', setTimeout(function(){
  					$.removeData(e.target, e.type + 'DefaultPrevented');
  				}, 30));
  				return preventDefault.apply(this, arguments);
  			};
  			e.isDefaultPrevented = function(){
  				return !!(isDefaultPrevented.apply(this, arguments) || $.data(e.target, e.type + 'DefaultPrevented') || false);
  			};
  			e._isPolyfilled = true;
  		}
  	};
  	
  	if(!Modernizr.formvalidation || bugs.bustedValidity){
  		testRequiredFind();
  		return;
  	}
  	
  	Modernizr.bugfreeformvalidation = true;
  	if(window.opera || $.browser.webkit || window.testGoodWithFix){
  		var dateElem = $('input', form).eq(0);
  		var timer;
  		var loadFormFixes = function(e){
  			var reTest = ['form-extend', 'form-message', 'form-native-fix'];
  			if(e){
  				e.preventDefault();
  				e.stopImmediatePropagation();
  			}
  			clearTimeout(timer);
  			setTimeout(function(){
  				if(!form){return;}
  				form.remove();
  				form = dateElem = null;
  			}, 9);
  			if(!Modernizr.bugfreeformvalidation){
  				webshims.addPolyfill('form-native-fix', {
  					f: 'forms',
  					d: ['form-extend']
  				});
  				//remove form-extend readyness
  				webshims.modules['form-extend'].test = $.noop;
  			} 
  			
  			if(webshims.isReady('form-number-date-api')){
  				reTest.push('form-number-date-api');
  			}
  			
  			webshims.reTest(reTest);
  			
  			
  			if ($.browser.opera || window.testGoodWithFix) {
  				webshims.loader.loadList(['dom-extend']);
  				webshims.ready('dom-extend', function(){
  					
  					//Opera shows native validation bubbles in case of input.checkValidity()
  					// Opera 11.6/12 hasn't fixed this issue right, it's buggy
  					var preventDefault = function(e){
  						e.preventDefault();
  					};
  					
  					['form', 'input', 'textarea', 'select'].forEach(function(name){
  						var desc = webshims.defineNodeNameProperty(name, 'checkValidity', {
  							prop: {
  								value: function(){
  									if (!webshims.fromSubmit) {
  										$(this).bind('invalid.checkvalidity', preventDefault);
  									}
  									
  									webshims.fromCheckValidity = true;
  									var ret = desc.prop._supvalue.apply(this, arguments);
  									if (!webshims.fromSubmit) {
  										$(this).unbind('invalid.checkvalidity', preventDefault);
  									}
  									webshims.fromCheckValidity = false;
  									return ret;
  								}
  							}
  						});
  					});
  					
  					//options only return options, if option-elements are rooted: but this makes this part of HTML5 less backwards compatible
  					if(Modernizr.input.list && !($('<datalist><select><option></option></select></datalist>').prop('options') || []).length ){
  						webshims.defineNodeNameProperty('datalist', 'options', {
  							prop: {
  								writeable: false,
  								get: function(){
  									var options = this.options || [];
  									if(!options.length){
  										var elem = this;
  										var select = $('select', elem);
  										if(select[0] && select[0].options && select[0].options.length){
  											options = select[0].options;
  										}
  									}
  									return options;
  								}
  							}
  						});
  					}
  					
  				});
  			}
  		};
  		
  		form.appendTo('head');
  		if(window.opera || window.testGoodWithFix) {
  			testRequiredFind();
  			bugs.validationMessage = !(dateElem.prop('validationMessage'));
  			if((Modernizr.inputtypes || {}).date){
  				try {
  					dateElem.prop('valueAsNumber', 0);
  				} catch(er){}
  				bugs.valueAsNumberSet = (dateElem.prop('value') != '1970-01-01');
  			}
  			dateElem.prop('value', '');
  		}
  		
  		form.bind('submit', function(e){
  			Modernizr.bugfreeformvalidation = false;
  			loadFormFixes(e);
  		});
  		
  		timer = setTimeout(function(){
  			form && form.triggerHandler('submit');
  		}, 9);
  		//create delegatable events
  		webshims.capturingEvents(['input']);
  		webshims.capturingEvents(['invalid'], true);
  		$('input, select', form).bind('invalid', loadFormFixes)
  			.filter('[type="submit"]')
  			.bind('click', function(e){
  				e.stopImmediatePropagation();
  			})
  			.trigger('click')
  		;
  		
  	}
  	
  	//create delegatable events
  	webshims.capturingEvents(['input']);
  	webshims.capturingEvents(['invalid'], true);
  	
  	
  })(jQuery);
  
  jQuery.webshims.register('form-core', function($, webshims, window, document, undefined, options){
  	"use strict";
  	
  	var groupTypes = {radio: 1};
  	var checkTypes = {checkbox: 1, radio: 1};
  	var emptyJ = $([]);
  	var bugs = webshims.bugs;
  	var getGroupElements = function(elem){
  		elem = $(elem);
  		var name;
  		var form;
  		var ret = emptyJ;
  		if(groupTypes[elem[0].type]){
  			form = elem.prop('form');
  			name = elem[0].name;
  			if(!name){
  				ret = elem;
  			} else if(form){
  				ret = $(form[name]);
  			} else {
  				ret = $(document.getElementsByName(name)).filter(function(){
  					return !$.prop(this, 'form');
  				});
  			}
  			ret = ret.filter('[type="radio"]');
  		}
  		return ret;
  	};
  	
  	var getContentValidationMessage = webshims.getContentValidationMessage = function(elem, validity){
  		var message = elem.getAttribute('x-moz-errormessage') || elem.getAttribute('data-errormessage') || '';
  		if(message && message.indexOf('{') != -1){
  			try {
  				message = jQuery.parseJSON(message);
  			} catch(er){
  				return message;
  			}
  			if(typeof message == 'object'){
  				validity = validity || $.prop(elem, 'validity') || {valid: 1};
  				if(!validity.valid){
  					$.each(validity, function(name, prop){
  						if(prop && name != 'valid' && message[name]){
  							message = message[name];
  							return false;
  						}
  					});
  				}
  			}
  			webshims.data(elem, 'contentErrorMessage', message);
  			if(typeof message == 'object'){
  				message = message.defaultMessage;
  			}
  		}
  		return message || '';
  	};
  	
  	/*
  	 * Selectors for all browsers
  	 */
  	var rangeTypes = {number: 1, range: 1, date: 1/*, time: 1, 'datetime-local': 1, datetime: 1, month: 1, week: 1*/};
  	$.extend($.expr.filters, {
  		"valid-element": function(elem){
  			return !!($.prop(elem, 'willValidate') && ($.prop(elem, 'validity') || {valid: 1}).valid);
  		},
  		"invalid-element": function(elem){
  			return !!($.prop(elem, 'willValidate') && !isValid(elem));
  		},
  		"required-element": function(elem){
  			return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required'));
  		},
  		"optional-element": function(elem){
  			return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required') === false);
  		},
  		"in-range": function(elem){
  			if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
  				return false;
  			}
  			var val = $.prop(elem, 'validity');
  			return !!(val && !val.rangeOverflow && !val.rangeUnderflow);
  		},
  		"out-of-range": function(elem){
  			if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
  				return false;
  			}
  			var val = $.prop(elem, 'validity');
  			return !!(val && (val.rangeOverflow || val.rangeUnderflow));
  		}
  		
  	});
  	//better you use the selectors above
  	['valid', 'invalid', 'required', 'optional'].forEach(function(name){
  		$.expr.filters[name] = $.expr.filters[name+"-element"];
  	});
  	
  	var customEvents = $.event.customEvent || {};
  	var isValid = function(elem){
  		return ($.prop(elem, 'validity') || {valid: 1}).valid;
  	};
  	
  	if (bugs.bustedValidity || bugs.findRequired) {
  		(function(){
  			var find = $.find;
  			var matchesSelector = $.find.matchesSelector;
  			
  			var regExp = /(\:valid|\:invalid|\:optional|\:required|\:in-range|\:out-of-range)(?=[\s\[\~\.\+\>\:\#*]|$)/ig;
  			var regFn = function(sel){
  				return sel + '-element';
  			};
  			
  			$.find = (function(){
  				var slice = Array.prototype.slice;
  				var fn = function(sel){
  					var ar = arguments;
  					ar = slice.call(ar, 1, ar.length);
  					ar.unshift(sel.replace(regExp, regFn));
  					return find.apply(this, ar);
  				};
  				for (var i in find) {
  					if(find.hasOwnProperty(i)){
  						fn[i] = find[i];
  					}
  				}
  				return fn;
  			})();
  			if(!Modernizr.prefixed || Modernizr.prefixed("matchesSelector", document.documentElement)){
  				$.find.matchesSelector = function(node, expr){
  					expr = expr.replace(regExp, regFn);
  					return matchesSelector.call(this, node, expr);
  				};
  			}
  			
  		})();
  	}
  	
  	//ToDo needs testing
  	var oldAttr = $.prop;
  	var changeVals = {selectedIndex: 1, value: 1, checked: 1, disabled: 1, readonly: 1};
  	$.prop = function(elem, name, val){
  		var ret = oldAttr.apply(this, arguments);
  		if(elem && 'form' in elem && changeVals[name] && val !== undefined && $(elem).hasClass('form-ui-invalid')){
  			if(isValid(elem)){
  				$(elem).getShadowElement().removeClass('form-ui-invalid');
  				if(name == 'checked' && val) {
  					getGroupElements(elem).not(elem).removeClass('form-ui-invalid').removeAttr('aria-invalid');
  				}
  			}
  		}
  		return ret;
  	};
  	
  	var returnValidityCause = function(validity, elem){
  		var ret;
  		$.each(validity, function(name, value){
  			if(value){
  				ret = (name == 'customError') ? $.prop(elem, 'validationMessage') : name;
  				return false;
  			}
  		});
  		return ret;
  	};
  	
  	var switchValidityClass = function(e){
  		if(!e.target || e.target.type == 'submit' || !$.prop(e.target, 'willValidate')){return;}
  		var timer = $.data(e.target, 'webshimsswitchvalidityclass');
  		if(timer){
  			clearTimeout(timer);
  		}
  		$.data(e.target, 'webshimsswitchvalidityclass', setTimeout(function(){
  			
  			var elem = $(e.target).getNativeElement()[0];
  			var validity = $.prop(elem, 'validity');
  			var shadowElem = $(elem).getShadowElement();
  			var addClass, removeClass, trigger, generaltrigger, validityCause;
  			
  			if(validity.valid){
  				if(!shadowElem.hasClass('form-ui-valid')){
  					addClass = 'form-ui-valid';
  					removeClass = 'form-ui-invalid';
  					generaltrigger = 'changedvaliditystate';
  					trigger = 'changedvalid';
  					if(checkTypes[elem.type] && elem.checked){
  						getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass).removeAttr('aria-invalid');
  					}
  					$.removeData(elem, 'webshimsinvalidcause');
  				}
  			} else {
  				validityCause = returnValidityCause(validity, elem);
  				if($.data(elem, 'webshimsinvalidcause') != validityCause){
  					$.data(elem, 'webshimsinvalidcause', validityCause);
  					generaltrigger = 'changedvaliditystate';
  				}
  				if(!shadowElem.hasClass('form-ui-invalid')){
  					addClass = 'form-ui-invalid';
  					removeClass = 'form-ui-valid';
  					if (checkTypes[elem.type] && !elem.checked) {
  						getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass);
  					}
  					trigger = 'changedinvalid';
  				}
  			}
  			if(addClass){
  				shadowElem.addClass(addClass).removeClass(removeClass);
  				//jQuery 1.6.1 IE9 bug (doubble trigger bug)
  				setTimeout(function(){
  					$(elem).trigger(trigger);
  				}, 0);
  			}
  			if(generaltrigger){
  				setTimeout(function(){
  					$(elem).trigger(generaltrigger);
  				}, 0);
  			}
  			$.removeData(e.target, 'webshimsswitchvalidityclass');//oh
  			
  		}, 9));
  	};
  	
  	
  	$(document).bind('focusout change refreshvalidityui', switchValidityClass);
  	customEvents.changedvaliditystate = true;
  	customEvents.changedvalid = true;
  	customEvents.changedinvalid = true;
  	customEvents.refreshvalidityui = true;
  	
  	
  	webshims.triggerInlineForm = function(elem, event){
  		$(elem).trigger(event);
  	};
  	
  	webshims.modules["form-core"].getGroupElements = getGroupElements;
  	
  	
  	var setRoot = function(){
  		webshims.scrollRoot = ($.browser.webkit || document.compatMode == 'BackCompat') ?
  			$(document.body) : 
  			$(document.documentElement)
  		;
  	};
  	setRoot();
  	webshims.ready('DOM', setRoot);
  	
  	webshims.getRelOffset = function(posElem, relElem){
  		posElem = $(posElem);
  		var offset = $(relElem).offset();
  		var bodyOffset;
  		$.swap($(posElem)[0], {visibility: 'hidden', display: 'inline-block', left: 0, top: 0}, function(){
  			bodyOffset = posElem.offset();
  		});
  		offset.top -= bodyOffset.top;
  		offset.left -= bodyOffset.left;
  		return offset;
  	};
  	
  	/* some extra validation UI */
  	webshims.validityAlert = (function(){
  		var alertElem = (!$.browser.msie || parseInt($.browser.version, 10) > 7) ? 'span' : 'label';
  		var errorBubble;
  		var hideTimer = false;
  		var focusTimer = false;
  		var resizeTimer = false;
  		var boundHide;
  		
  		var api = {
  			hideDelay: 5000,
  			
  			showFor: function(elem, message, noFocusElem, noBubble){
  				api._create();
  				elem = $(elem);
  				var visual = $(elem).getShadowElement();
  				var offset = api.getOffsetFromBody(visual);
  				api.clear();
  				if(noBubble){
  					this.hide();
  				} else {
  					this.getMessage(elem, message);
  					this.position(visual, offset);
  					errorBubble.css({
  						fontSize: elem.css('fontSize'),
  						fontFamily: elem.css('fontFamily')
  					});
  					this.show();
  					if(this.hideDelay){
  						hideTimer = setTimeout(boundHide, this.hideDelay);
  					}
  					$(window)
  						.bind('resize.validityalert orientationchange.validityalert emchange.validityalert', function(){
  							clearTimeout(resizeTimer);
  							resizeTimer = setTimeout(function(){
  								api.position(visual);
  							}, 9);
  						})
  					;
  				}
  				
  				if(!noFocusElem){
  					this.setFocus(visual, offset);
  				}
  			},
  			getOffsetFromBody: function(elem){
  				return webshims.getRelOffset(errorBubble, elem);
  			},
  			setFocus: function(visual, offset){
  				var focusElem = $(visual).getShadowFocusElement();
  				var scrollTop = webshims.scrollRoot.scrollTop();
  				var elemTop = ((offset || focusElem.offset()).top) - 30;
  				var smooth;
  				
  				if(webshims.getID && alertElem == 'label'){
  					errorBubble.attr('for', webshims.getID(focusElem));
  				}
  				
  				if(scrollTop > elemTop){
  					webshims.scrollRoot.animate(
  						{scrollTop: elemTop - 5}, 
  						{
  							queue: false, 
  							duration: Math.max( Math.min( 600, (scrollTop - elemTop) * 1.5 ), 80 )
  						}
  					);
  					smooth = true;
  				}
  				try {
  					focusElem[0].focus();
  				} catch(e){}
  				if(smooth){
  					webshims.scrollRoot.scrollTop(scrollTop);
  					setTimeout(function(){
  						webshims.scrollRoot.scrollTop(scrollTop);
  					}, 0);
  				}
  				setTimeout(function(){
  					$(document).bind('focusout.validityalert', boundHide);
  				}, 10);
  			},
  			getMessage: function(elem, message){
  				$('span.va-box', errorBubble).text(message || getContentValidationMessage(elem[0]) || elem.prop('validationMessage'));
  			},
  			position: function(elem, offset){
  				offset = offset ? $.extend({}, offset) : api.getOffsetFromBody(elem);
  				offset.top += elem.outerHeight();
  				errorBubble.css(offset);
  			},
  			show: function(){
  				if(errorBubble.css('display') === 'none'){
  					errorBubble.css({opacity: 0}).show();
  				}
  				errorBubble.addClass('va-visible').fadeTo(400, 1);
  			},
  			hide: function(){
  				errorBubble.removeClass('va-visible').fadeOut();
  			},
  			clear: function(){
  				clearTimeout(focusTimer);
  				clearTimeout(hideTimer);
  				$(document).unbind('.validityalert');
  				$(window).unbind('.validityalert');
  				errorBubble.stop().removeAttr('for');
  			},
  			_create: function(){
  				if(errorBubble){return;}
  				errorBubble = api.errorBubble = $('<'+alertElem+' class="validity-alert-wrapper" role="alert"><span  class="validity-alert"><span class="va-arrow"><span class="va-arrow-box"></span></span><span class="va-box"></span></span></'+alertElem+'>').css({position: 'absolute', display: 'none'});
  				webshims.ready('DOM', function(){
  					errorBubble.appendTo('body');
  					if($.fn.bgIframe && $.browser.msie && parseInt($.browser.version, 10) < 7){
  						errorBubble.bgIframe();
  					}
  				});
  			}
  		};
  		
  		
  		boundHide = $.proxy(api, 'hide');
  		
  		return api;
  	})();
  	
  	
  	/* extension, but also used to fix native implementation workaround/bugfixes */
  	(function(){
  		var firstEvent,
  			invalids = [],
  			stopSubmitTimer,
  			form
  		;
  		
  		$(document).bind('invalid', function(e){
  			if(e.wrongWebkitInvalid){return;}
  			var jElm = $(e.target);
  			var shadowElem = jElm.getShadowElement();
  			if(!shadowElem.hasClass('form-ui-invalid')){
  				shadowElem.addClass('form-ui-invalid').removeClass('form-ui-valid');
  				setTimeout(function(){
  					$(e.target).trigger('changedinvalid').trigger('changedvaliditystate');
  				}, 0);
  			}
  			
  			if(!firstEvent){
  				//trigger firstinvalid
  				firstEvent = $.Event('firstinvalid');
  				firstEvent.isInvalidUIPrevented = e.isDefaultPrevented;
  				var firstSystemInvalid = $.Event('firstinvalidsystem');
  				$(document).triggerHandler(firstSystemInvalid, {element: e.target, form: e.target.form, isInvalidUIPrevented: e.isDefaultPrevented});
  				jElm.trigger(firstEvent);
  			}
  
  			//if firstinvalid was prevented all invalids will be also prevented
  			if( firstEvent && firstEvent.isDefaultPrevented() ){
  				e.preventDefault();
  			}
  			invalids.push(e.target);
  			e.extraData = 'fix'; 
  			clearTimeout(stopSubmitTimer);
  			stopSubmitTimer = setTimeout(function(){
  				var lastEvent = {type: 'lastinvalid', cancelable: false, invalidlist: $(invalids)};
  				//reset firstinvalid
  				firstEvent = false;
  				invalids = [];
  				$(e.target).trigger(lastEvent, lastEvent);
  			}, 9);
  			jElm = null;
  			shadowElem = null;
  		});
  	})();
  	
  	if(options.replaceValidationUI){
  		webshims.ready('DOM', function(){
  			$(document).bind('firstinvalid', function(e){
  				if(!e.isInvalidUIPrevented()){
  					e.preventDefault();
  					$.webshims.validityAlert.showFor( e.target, $(e.target).prop('customValidationMessage') ); 
  				}
  			});
  		});
  	}
  	
  });