vendor/assets/javascripts/webshims/shims/combos/17.js in webshims-rails-0.4.7 vs vendor/assets/javascripts/webshims/shims/combos/17.js in webshims-rails-1.10.3

- old
+ new

@@ -1,2368 +1,3120 @@ -//DOM-Extension helper -jQuery.webshims.register('dom-extend', function($, webshims, window, document, undefined){ +jQuery.webshims.register('form-number-date-api', 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.onTrigger = function(evt, fn){ - return this.on(evt, fn).each(fn); - }; - - $.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'); - } + if(!webshims.getStep){ + webshims.getStep = function(elem, type){ + var step = $.attr(elem, 'step'); + if(step === 'any'){ + return step; } - }); - }; - - 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, {}); + type = type || getType(elem); + if(!typeModels[type] || !typeModels[type].step){ + return step; } - if(key){ - data[key] = val; + step = typeProtos.number.asNumber(step); + return ((!isNaN(step) && step > 0) ? step : typeModels[type].step) * (typeModels[type].stepScaleFactor || 1); + }; + } + if(!webshims.addMinMaxNumberToCache){ + webshims.addMinMaxNumberToCache = function(attr, elem, cache){ + if (!(attr+'AsNumber' in cache)) { + cache[attr+'AsNumber'] = typeModels[cache.type].asNumber(elem.attr(attr)); + if(isNaN(cache[attr+'AsNumber']) && (attr+'Default' in typeModels[cache.type])){ + cache[attr+'AsNumber'] = typeModels[cache.type][attr+'Default']; + } } - } - - 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; - }); }; - }); + } + var nan = parseInt('NaN', 10), + doc = document, + typeModels = webshims.inputTypes, + isNumber = function(string){ + return (typeof string == 'number' || (string && string == string * 1)); + }, + supportsType = function(type){ + return ($('<input type="'+type+'" />').prop('type') === type); + }, + getType = function(elem){ + return (elem.getAttribute('type') || '').toLowerCase(); + }, + isDateTimePart = function(string){ + return (string && !(isNaN(string * 1))); + }, + addMinMaxNumberToCache = webshims.addMinMaxNumberToCache, + addleadingZero = function(val, len){ + val = ''+val; + len = len - val.length; + for(var i = 0; i < len; i++){ + val = '0'+val; + } + return val; + }, + EPS = 1e-7, + typeBugs = webshims.bugs.bustedValidity + ; - ['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); + webshims.addValidityRule('stepMismatch', function(input, val, cache, validityState){ + if(val === ''){return false;} + if(!('type' in cache)){ + cache.type = getType(input[0]); + } + + var ret = (validityState || {}).stepMismatch || false, base; + if(typeModels[cache.type] && typeModels[cache.type].step){ + if( !('step' in cache) ){ + cache.step = webshims.getStep(input[0], cache.type); } - 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(cache.step == 'any'){return false;} - - if(!desc){ - desc = extendedProps['*']; + if(!('valueAsNumber' in cache)){ + cache.valueAsNumber = typeModels[cache.type].asNumber( val ); } - if(desc){ - desc = desc[name]; - } + if(isNaN(cache.valueAsNumber)){return false;} - if(desc){ - propMethod = desc[curType]; + addMinMaxNumberToCache('min', input, cache); + base = cache.minAsNumber; + if(isNaN(base)){ + base = typeModels[cache.type].stepBase || 0; } - if(propMethod){ - if(name == 'value'){ - oldValMethod = propMethod.isVal; - propMethod.isVal = isVal; + ret = Math.abs((cache.valueAsNumber - base) % cache.step); + + ret = !( ret <= EPS || Math.abs(ret - cache.step) <= EPS ); + } + return ret; + }); + + + + [{name: 'rangeOverflow', attr: 'max', factor: 1}, {name: 'rangeUnderflow', attr: 'min', factor: -1}].forEach(function(data, i){ + webshims.addValidityRule(data.name, function(input, val, cache, validityState) { + var ret = (validityState || {})[data.name] || false; + if(val === ''){return ret;} + if (!('type' in cache)) { + cache.type = getType(input[0]); + } + if (typeModels[cache.type] && typeModels[cache.type].asNumber) { + if(!('valueAsNumber' in cache)){ + cache.valueAsNumber = typeModels[cache.type].asNumber( val ); } - 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(isNaN(cache.valueAsNumber)){ + return false; } - 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; - } + addMinMaxNumberToCache(data.attr, input, cache); - 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); - } - }); + if(isNaN(cache[data.attr+'AsNumber'])){ + return ret; + } + ret = ( cache[data.attr+'AsNumber'] * data.factor < cache.valueAsNumber * data.factor - EPS ); } 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]; + }); + }); + + webshims.reflectProperties(['input'], ['max', 'min', 'step']); + + + //IDLs and methods, that aren't part of constrain validation, but strongly tight to it + var valueAsNumberDescriptor = webshims.defineNodeNameProperty('input', 'valueAsNumber', { + prop: { + get: function(){ + var elem = this; + var type = getType(elem); + var ret = (typeModels[type] && typeModels[type].asNumber) ? + typeModels[type].asNumber($.prop(elem, 'value')) : + (valueAsNumberDescriptor.prop._supget && valueAsNumberDescriptor.prop._supget.apply(elem, arguments)); + if(ret == null){ + ret = nan; } - if(oDesc && oDesc[propType]){ - return oDesc[propType]; + return ret; + }, + set: function(val){ + var elem = this; + var type = getType(elem); + if(typeModels[type] && typeModels[type].numberToString){ + //is NaN a number? + if(isNaN(val)){ + $.prop(elem, 'value', ''); + return; + } + var set = typeModels[type].numberToString(val); + if(set !== false){ + $.prop(elem, 'value', set); + } else { + webshims.error('INVALID_STATE_ERR: DOM Exception 11'); + } + } else { + valueAsNumberDescriptor.prop._supset && valueAsNumberDescriptor.prop._supset.apply(elem, arguments); } - 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 = Modernizr.ES5; - var extendNativeValue = (function(){ - var UNKNOWN = webshims.getPrototypeOf(document.createElement('foobar')); - var has = Object.prototype.hasOwnProperty; - return function(nodeName, prop, desc){ - var elem; - var elemProto; - if( isExtendNativeSave && (elem = document.createElement(nodeName)) && (elemProto = webshims.getPrototypeOf(elem)) && UNKNOWN !== elemProto && ( !elem[prop] || !has.call(elem, prop) ) ){ - var sup = elem[prop]; - desc._supvalue = function(){ - if(sup && sup.apply){ - return sup.apply(this, arguments); + var valueAsDateDescriptor = webshims.defineNodeNameProperty('input', 'valueAsDate', { + prop: { + get: function(){ + var elem = this; + var type = getType(elem); + return (typeModels[type] && typeModels[type].asDate && !typeModels[type].noAsDate) ? + typeModels[type].asDate($.prop(elem, 'value')) : + valueAsDateDescriptor.prop._supget && valueAsDateDescriptor.prop._supget.call(elem) || null; + }, + set: function(value){ + var elem = this; + var type = getType(elem); + if(typeModels[type] && typeModels[type].dateToString && !typeModels[type].noAsDate){ + + if(value === null){ + $.prop(elem, 'value', ''); + return ''; } - 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); + var set = typeModels[type].dateToString(value); + if(set !== false){ + $.prop(elem, 'value', set); + return set; + } else { + webshims.error('INVALID_STATE_ERR: DOM Exception 11'); } - return data && data[prop]; - }; - initProp.extendValue(nodeName, prop, desc.value); + } else { + return valueAsDateDescriptor.prop._supset && valueAsDateDescriptor.prop._supset.apply(elem, arguments) || null; + } } - 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({stepUp: 1, stepDown: -1}, function(name, stepFactor){ + var stepDescriptor = webshims.defineNodeNameProperty('input', name, { + prop: { + value: function(factor){ + var step, val, dateVal, valModStep, alignValue, cache; + var type = getType(this); + if(typeModels[type] && typeModels[type].asNumber){ + cache = {type: type}; + if(!factor){ + factor = 1; + webshims.info("you should always use a factor for stepUp/stepDown"); + } + factor *= stepFactor; + + val = $.prop(this, 'valueAsNumber'); + + if(isNaN(val)){ + webshims.info("valueAsNumber is NaN can't apply stepUp/stepDown "); + throw('invalid state error'); + } + + step = webshims.getStep(this, type); + + if(step == 'any'){ + webshims.info("step is 'any' can't apply stepUp/stepDown"); + throw('invalid state error'); + } + + webshims.addMinMaxNumberToCache('min', $(this), cache); + webshims.addMinMaxNumberToCache('max', $(this), cache); + + step *= factor; + + val = (val + step).toFixed(5) * 1; + valModStep = (val - (cache.minAsNumber || 0)) % step; + + if ( valModStep && (Math.abs(valModStep) > EPS) ) { + alignValue = val - valModStep; + alignValue += ( valModStep > 0 ) ? step : ( -step ); + val = alignValue.toFixed(5) * 1; + } + + if( (!isNaN(cache.maxAsNumber) && val > cache.maxAsNumber) || (!isNaN(cache.minAsNumber) && val < cache.minAsNumber) ){ + webshims.info("max/min overflow can't apply stepUp/stepDown"); + throw('invalid state error'); + } + if(dateVal){ + $.prop(this, 'valueAsDate', dateVal); + } else { + $.prop(this, 'valueAsNumber', val); + } + } else if(stepDescriptor.prop && stepDescriptor.prop.value){ + return stepDescriptor.prop.value.apply(this, arguments); + } else { + webshims.info("no step method for type: "+ type); + throw('invalid state error'); } } - }; - - - $.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 typeProtos = { - 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; + number: { + mismatch: function(val){ + return !(isNumber(val)); }, - flushTmpCache: function(){ - tempCache = null; + step: 1, + //stepBase: 0, 0 = default + stepScaleFactor: 1, + asNumber: function(str){ + return (isNumber(str)) ? str * 1 : nan; }, - 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; - }); - }); + numberToString: function(num){ + return (isNumber(num)) ? num : false; } - }; - })(); + }, - 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); - } - }; - } - if(!descs.attr){ - descs.attr = {}; - } - }; - - $.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; - } - }); + range: { + minDefault: 0, + maxDefault: 100 }, - //http://www.w3.org/TR/html5/common-dom-interfaces.html#reflect - createPropDefault: createPropDefault, - data: elementData, - moveToFirstEvent: function(elem, eventType, bindType){ - var events = ($._data(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 ); - } + + date: { + mismatch: function(val){ + if(!val || !val.split || !(/\d$/.test(val))){return true;} + var i; + var valA = val.split(/\u002D/); + if(valA.length !== 3){return true;} + var ret = false; - } - elem = null; - }, - addShadowDom: (function(){ - var resizeTimer; - var lastHeight; - var lastWidth; - - var docObserve = { - init: false, - runs: 0, - test: function(){ - var height = docObserve.getHeight(); - var width = docObserve.getWidth(); - - if(height != docObserve.height || width != docObserve.width){ - docObserve.height = height; - docObserve.width = width; - docObserve.handler({type: 'docresize'}); - docObserve.runs++; - if(docObserve.runs < 9){ - setTimeout(docObserve.test, 90); + if(valA[0].length < 4 || valA[1].length != 2 || valA[1] > 12 || valA[2].length != 2 || valA[2] > 33){ + ret = true; + } else { + for(i = 0; i < 3; i++){ + if(!isDateTimePart(valA[i])){ + ret = true; + break; } - } else { - docObserve.runs = 0; } - }, - handler: function(e){ - clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $(window).width(); - var height = $(window).width(); - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - - } - $(document).triggerHandler('updateshadowdom'); - }, (e.type == 'resize') ? 50 : 9); - }, - _create: function(){ - $.each({ Height: "getHeight", Width: "getWidth" }, function(name, type){ - var body = document.body; - var doc = document.documentElement; - docObserve[type] = function(){ - return Math.max( - body[ "scroll" + name ], doc[ "scroll" + name ], - body[ "offset" + name ], doc[ "offset" + name ], - doc[ "client" + name ] - ); - }; - }); - }, - start: function(){ - if(!this.init && document.body){ - this.init = true; - this._create(); - this.height = docObserve.getHeight(); - this.width = docObserve.getWidth(); - setInterval(this.test, 600); - $(this.test); - webshims.ready('WINDOWLOAD', this.test); - $(window).bind('resize', this.handler); - (function(){ - var oldAnimate = $.fn.animate; - var animationTimer; - - $.fn.animate = function(){ - clearTimeout(animationTimer); - animationTimer = setTimeout(function(){ - docObserve.test(); - }, 99); - - return oldAnimate.apply(this, arguments); - }; - })(); - } } - }; - - - webshims.docObserve = function(){ - webshims.ready('DOM', function(){ - docObserve.start(); - }); - }; - return function(nativeElem, shadowElem, opts){ - opts = opts || {}; - if(nativeElem.jquery){ - nativeElem = nativeElem[0]; + + return ret || (val !== this.dateToString( this.asDate(val, true) ) ); + }, + step: 1, + //stepBase: 0, 0 = default + stepScaleFactor: 86400000, + asDate: function(val, _noMismatch){ + if(!_noMismatch && this.mismatch(val)){ + return null; } - if(shadowElem.jquery){ - shadowElem = shadowElem[0]; + return new Date(this.asNumber(val, true)); + }, + asNumber: function(str, _noMismatch){ + var ret = nan; + if(_noMismatch || !this.mismatch(str)){ + str = str.split(/\u002D/); + ret = Date.UTC(str[0], str[1] - 1, str[2]); } - var nativeData = $.data(nativeElem, dataID) || $.data(nativeElem, dataID, {}); - var shadowData = $.data(shadowElem, dataID) || $.data(shadowElem, dataID, {}); - var shadowFocusElementData = {}; - if(!opts.shadowFocusElement){ - opts.shadowFocusElement = shadowElem; - } else if(opts.shadowFocusElement){ - if(opts.shadowFocusElement.jquery){ - opts.shadowFocusElement = opts.shadowFocusElement[0]; + return ret; + }, + numberToString: function(num){ + return (isNumber(num)) ? this.dateToString(new Date( num * 1)) : false; + }, + dateToString: function(date){ + return (date && date.getFullYear) ? addleadingZero(date.getUTCFullYear(), 4) +'-'+ addleadingZero(date.getUTCMonth()+1, 2) +'-'+ addleadingZero(date.getUTCDate(), 2) : false; + } + }, + time: { + mismatch: function(val, _getParsed){ + if(!val || !val.split || !(/\d$/.test(val))){return true;} + val = val.split(/\u003A/); + if(val.length < 2 || val.length > 3){return true;} + var ret = false, + sFraction; + if(val[2]){ + val[2] = val[2].split(/\u002E/); + sFraction = parseInt(val[2][1], 10); + val[2] = val[2][0]; + } + $.each(val, function(i, part){ + if(!isDateTimePart(part) || part.length !== 2){ + ret = true; + return false; } - shadowFocusElementData = $.data(opts.shadowFocusElement, dataID) || $.data(opts.shadowFocusElement, dataID, shadowFocusElementData); + }); + if(ret){return true;} + if(val[0] > 23 || val[0] < 0 || val[1] > 59 || val[1] < 0){ + return true; } - - nativeData.hasShadow = shadowElem; - shadowFocusElementData.nativeElement = shadowData.nativeElement = nativeElem; - shadowFocusElementData.shadowData = shadowData.shadowData = nativeData.shadowData = { - nativeElement: nativeElem, - shadowElement: shadowElem, - shadowFocusElement: opts.shadowFocusElement - }; - if(opts.shadowChilds){ - opts.shadowChilds.each(function(){ - elementData(this, 'shadowData', shadowData.shadowData); - }); + if(val[2] && (val[2] > 59 || val[2] < 0 )){ + return true; } - - if(opts.data){ - shadowFocusElementData.shadowData.data = shadowData.shadowData.data = nativeData.shadowData.data = opts.data; + if(sFraction && isNaN(sFraction)){ + return true; } - opts = null; - webshims.docObserve(); - }; - })(), - 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; + if(sFraction){ + if(sFraction < 100){ + sFraction *= 100; + } else if(sFraction < 10){ + sFraction *= 10; } - }; - + } + return (_getParsed === true) ? [val, sFraction] : false; }, - "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; - } - }; + step: 60, + stepBase: 0, + stepScaleFactor: 1000, + asDate: function(val){ + val = new Date(this.asNumber(val)); + return (isNaN(val)) ? null : val; }, - "src": (function(){ - var anchor = document.createElement('a'); - anchor.style.display = "none"; - return function(descs, name){ - - createPropDefault(descs); - if(descs.prop){return;} - descs.prop = { - set: function(val){ - descs.attr.set.call(this, val); - }, - get: function(){ - var href = this.getAttribute(name); - var ret; - if(href == null){return '';} - - anchor.setAttribute('href', href+'' ); - - if(!$.support.hrefNormalized){ - try { - $(anchor).insertAfter(this); - ret = anchor.getAttribute('href', 4); - } catch(er){ - ret = anchor.getAttribute('href', 4); - } - $(anchor).detach(); - } - return ret || anchor.href; - } - }; - }; - })(), - enumarated: function(descs, name){ - - createPropDefault(descs); - if(descs.prop){return;} - descs.prop = { - set: function(val){ - descs.attr.set.call(this, val); - }, - get: function(){ - var val = (descs.attr.get.call(this) || '').toLowerCase(); - if(!val || descs.limitedTo.indexOf(val) == -1){ - val = descs.defaultValue; - } - return val; - } - }; + asNumber: function(val){ + var ret = nan; + val = this.mismatch(val, true); + if(val !== true){ + ret = Date.UTC('1970', 0, 1, val[0][0], val[0][1], val[0][2] || 0); + if(val[1]){ + ret += val[1]; + } } - -// ,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) || ''; - } + return ret; + }, + dateToString: function(date){ + if(date && date.getUTCHours){ + var str = addleadingZero(date.getUTCHours(), 2) +':'+ addleadingZero(date.getUTCMinutes(), 2), + tmp = date.getSeconds() + ; + if(tmp != "0"){ + str += ':'+ addleadingZero(tmp, 2); } - }); - }); - }, - defineNodeNameProperty: function(nodeName, prop, descs){ - havePolyfill[prop] = true; - - if(descs.reflect){ - webshims.propTypes[descs.propType || 'standard'](descs, prop); - } - - ['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}); + tmp = date.getUTCMilliseconds(); + if(tmp != "0"){ + str += '.'+ addleadingZero(tmp, 3); } - - extendQ[type](nodeName, prop, desc); - if(nodeName != '*' && webshims.cfg.extendNative && type == 'prop' && desc.value && $.isFunction(desc.value)){ - extendNativeValue(nodeName, prop, desc); - } - descs[type] = desc; + return str; + } else { + return false; } - }); - 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); + month: { + mismatch: function(val){ + return typeProtos.date.mismatch(val+'-01'); + }, + step: 1, + stepScaleFactor: false, + //stepBase: 0, 0 = default + asDate: function(val){ + return new Date(typeProtos.date.asNumber(val+'-01')); + }, + asNumber: function(val){ + //1970-01 + var ret = nan; + if(val && !this.mismatch(val)){ + val = val.split(/\u002D/); + val[0] = (val[0] * 1) - 1970; + val[1] = (val[1] * 1) - 1; + ret = (val[0] * 12) + val[1]; } - 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]; - } - }); + return ret; + }, + numberToString: function(num){ + var mod; + var ret = false; + if(isNumber(num)){ + mod = (num % 12); + num = ((num - mod) / 12) + 1970; + mod += 1; + if(mod < 1){ + num -= 1; + mod += 12; } + ret = addleadingZero(num, 4)+'-'+addleadingZero(mod, 2); + } - descs[prop] = webshims.defineNodeNameProperty(name, prop, descs[prop]); + + return ret; + }, + dateToString: function(date){ + if(date && date.getUTCHours){ + var str = typeProtos.date.dateToString(date); + return (str.split && (str = str.split(/\u002D/))) ? str[0]+'-'+str[1] : false; + } else { + return false; + } } - if(!_noTmpCache){ - initProp.flushTmpCache(); + } +// ,'datetime-local': { +// mismatch: function(val, _getParsed){ +// if(!val || !val.split || (val+'special').split(/\u0054/).length !== 2){return true;} +// val = val.split(/\u0054/); +// return ( typeProtos.date.mismatch(val[0]) || typeProtos.time.mismatch(val[1], _getParsed) ); +// }, +// noAsDate: true, +// asDate: function(val){ +// val = new Date(this.asNumber(val)); +// +// return (isNaN(val)) ? null : val; +// }, +// asNumber: function(val){ +// var ret = nan; +// var time = this.mismatch(val, true); +// if(time !== true){ +// val = val.split(/\u0054/)[0].split(/\u002D/); +// +// ret = Date.UTC(val[0], val[1] - 1, val[2], time[0][0], time[0][1], time[0][2] || 0); +// if(time[1]){ +// ret += time[1]; +// } +// } +// return ret; +// }, +// dateToString: function(date, _getParsed){ +// return typeProtos.date.dateToString(date) +'T'+ typeProtos.time.dateToString(date, _getParsed); +// } +// } + }; + + if(typeBugs || !supportsType('range') || !supportsType('time')){ + typeProtos.range = $.extend({}, typeProtos.number, typeProtos.range); + typeProtos.time = $.extend({}, typeProtos.date, typeProtos.time); + typeProtos.month = $.extend({}, typeProtos.date, typeProtos.month); +// typeProtos['datetime-local'] = $.extend({}, typeProtos.date, typeProtos.time, typeProtos['datetime-local']); + } + + //'datetime-local' + ['number', 'month', 'range', 'date', 'time'].forEach(function(type){ + if(typeBugs || !supportsType(type)){ + webshims.addInputType(type, typeProtos[type]); + } + }); + + if($('<input />').prop('labels') == null){ + webshims.defineNodeNamesProperty('button, input, keygen, meter, output, progress, select, textarea', 'labels', { + prop: { + get: function(){ + if(this.type == 'hidden'){return null;} + var id = this.id; + var labels = $(this) + .closest('label') + .filter(function(){ + var hFor = (this.attributes['for'] || {}); + return (!hFor.specified || hFor.value == id); + }) + ; + + if(id) { + labels = labels.add('label[for="'+ id +'"]'); + } + return labels.get(); + }, + writeable: false } - return descs; - }, - - createElement: function(nodeName, create, descs){ - var ret; - if($.isFunction(create)){ - create = { - after: create - }; + }); + } + +}); +(function($){ + + var id = 0; + var isNumber = function(string){ + return (typeof string == 'number' || (string && string == string * 1)); + }; + var retDefault = function(val, def){ + if(!(typeof val == 'number' || (val && val == val * 1))){ + return def; + } + return val * 1; + }; + var createOpts = ['step', 'min', 'max', 'readonly', 'title', 'disabled', 'tabindex']; + var rangeProto = { + _create: function(){ + var i; + + + this.element.addClass('ws-range').attr({role: 'slider'}).append('<span class="ws-range-min" /><span class="ws-range-rail"><span class="ws-range-thumb" /></span>'); + this.trail = $('.ws-range-rail', this.element); + this.range = $('.ws-range-min', this.element); + this.thumb = $('.ws-range-thumb', this.trail); + + this.updateMetrics(); + + this.orig = this.options.orig; + + for(i = 0; i < createOpts.length; i++){ + this[createOpts[i]](this.options[createOpts[i]]); } - 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; + this.value = this._value; + this.value(this.options.value); + this.initDataList(); + this.element.data('rangeUi', this); + this.addBindings(); + this._init = true; }, - onNodeNamesPropertyModify: function(nodeNames, props, desc, only){ - if(typeof nodeNames == 'string'){ - nodeNames = nodeNames.split(listReg); + value: $.noop, + _value: function(val, _noNormalize, animate){ + var left, posDif; + var o = this.options; + var oVal = val; + var thumbStyle = {}; + var rangeStyle = {}; + if(!_noNormalize && parseFloat(val, 10) != val){ + val = o.min + ((o.max - o.min) / 2); } - if($.isFunction(desc)){ - desc = {set: desc}; + + if(!_noNormalize){ + val = this.normalizeVal(val); } + left = 100 * ((val - o.min) / (o.max - o.min)); - nodeNames.forEach(function(name){ - if(!modifyProps[name]){ - modifyProps[name] = {}; + this.options.value = val; + this.thumb.stop(); + this.range.stop(); + + rangeStyle[this.dirs.width] = left+'%'; + if(this.vertical){ + left = Math.abs(left - 100); + } + thumbStyle[this.dirs.left] = left+'%'; + + + if(!animate){ + this.thumb.css(thumbStyle); + this.range.css(rangeStyle); + } else { + if(typeof animate != 'object'){ + animate = {}; + } else { + animate = $.extend({}, animate); } - if(typeof props == 'string'){ - props = props.split(listReg); + if(!animate.duration){ + posDif = Math.abs(left - parseInt(this.thumb[0].style[this.dirs.left] || 50, 10)); + animate.duration = Math.max(Math.min(999, posDif * 5), 99); } - 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; + this.thumb.animate(thumbStyle, animate); + this.range.animate(rangeStyle, animate); + } + if(this.orig && (oVal != val || (!this._init && this.orig.value != val)) ){ + this.options._change(val); + } + this.element.attr({ + 'aria-valuenow': this.options.value, + 'aria-valuetext': this.options.textValue ? this.options.textValue(this.options.value) : this.options.options[this.options.value] || this.options.value + }); + }, + initDataList: function(){ + if(this.orig){ + var listTimer; + var that = this; + var updateList = function(){ + $(that.orig) + .jProp('list') + .off('updateDatalist', updateList) + .on('updateDatalist', updateList) + ; + clearTimeout(listTimer); + listTimer = setTimeout(function(){ + if(that.list){ + that.list(); } - modifyProps[name][prop].push(desc.set); - } + }, 9); - if(desc.initAttr){ - initProp.content(name, prop); - } - }); - initProp.flushTmpCache(); + }; + $(this.orig).on('listdatalistchange', updateList); + this.list(); + } + }, + list: function(opts){ + var o = this.options; + var min = o.min; + var max = o.max; + var trail = this.trail; + var that = this; + + this.element.attr({'aria-valuetext': o.options[o.value] || o.value}); + $('.ws-range-ticks', trail).remove(); + + + $(this.orig).jProp('list').find('option').each(function(){ + o.options[$.prop(this, 'value')] = $.prop(this, 'label'); }); + + $.each(o.options, function(val, label){ + if(!isNumber(val) || val < min || val > max){return;} + var left = 100 * ((val - min) / (max - min)); + var title = o.showLabels ? ' title="'+ label +'"' : ''; + if(that.vertical){ + left = Math.abs(left - 100); + } + trail.append('<span class="ws-range-ticks"'+ title +' style="'+(that.dirs.left)+': '+left+'%;" />'); + }); }, - defineNodeNamesBooleanProperty: function(elementNames, prop, descs){ - if(!descs){ - descs = {}; + readonly: function(val){ + val = !!val; + this.options.readonly = val; + this.element.attr('aria-readonly', ''+val); + }, + disabled: function(val){ + val = !!val; + this.options.disabled = val; + if(val){ + this.element.attr({tabindex: -1, 'aria-disabled': 'true'}); + } else { + this.element.attr({tabindex: this.options.tabindex, 'aria-disabled': 'false'}); } - 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;} - var attr; - if(val === undefined){ - attr = (elem.attributes[name] || {}); - val = attr.specified ? attr.value : null; - return (val == null) ? undefined : val; + tabindex: function(val){ + this.options.tabindex = val; + if(!this.options.disabled){ + this.element.attr({tabindex: val}); } + }, + title: function(val){ + this.element.prop('title', val); + }, + min: function(val){ + this.options.min = retDefault(val, 0); + this.value(this.options.value, true); + }, + max: function(val){ + this.options.max = retDefault(val, 100); + this.value(this.options.value, true); + }, + step: function(val){ + this.options.step = val == 'any' ? 'any' : retDefault(val, 1); + this.value(this.options.value); + }, + + normalizeVal: function(val){ + var valModStep, alignValue, step; + var o = this.options; - if(typeof val == 'boolean'){ - if(!val){ - elem.removeAttribute(name); - } else { - elem.setAttribute(name, name); + if(val <= o.min){ + val = o.min; + } else if(val >= o.max) { + val = o.max; + } else if(o.step != 'any'){ + step = o.step; + valModStep = (val - o.min) % step; + alignValue = val - valModStep; + + if ( Math.abs(valModStep) * 2 >= step ) { + alignValue += ( valModStep > 0 ) ? step : ( -step ); } - } else { - elem.setAttribute(name, val); + val = alignValue.toFixed(5) * 1; } + return 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; + doStep: function(factor, animate){ + var step = retDefault(this.options.step, 1); + if(this.options.step == 'any'){ + step = Math.min(step, (this.options.max - this.options.min) / 10); + } + this.value( this.options.value + (step * factor), false, animate ); + + }, + + getStepedValueFromPos: function(pos){ + var val, valModStep, alignValue, step; + + if(pos <= 0){ + val = this.options[this.dirs.min]; + } else if(pos > 100) { + val = this.options[this.dirs.max]; + } else { + if(this.vertical){ + pos = Math.abs(pos - 100); + } + val = ((this.options.max - this.options.min) * (pos / 100)) + this.options.min; + step = this.options.step; + if(step != 'any'){ + valModStep = (val - this.options.min) % step; + alignValue = val - valModStep; + + if ( Math.abs(valModStep) * 2 >= step ) { + alignValue += ( valModStep > 0 ) ? step : ( -step ); } - 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; - }); + val = ((alignValue).toFixed(5)) * 1; + + } + } + + return val; + }, + addBindings: function(){ + var leftOffset, widgetUnits, hasFocus; + var that = this; + var o = this.options; + + var eventTimer = (function(){ + var events = {}; + return { + init: function(name, curVal, fn){ + if(!events[name]){ + events[name] = {fn: fn}; + if(that.orig){ + $(that.orig).on(name, function(){ + events[name].val = $.prop(that.orig, 'value'); + }); + } + } - }); - return true; + events[name].val = curVal; + }, + call: function(name, val){ + if(events[name].val != val){ + clearTimeout(events[name].timer); + events[name].val = val; + events[name].timer = setTimeout(function(){ + events[name].fn(val, that); + }, 0); + } + } + }; + })(); + + var setValueFromPos = function(e, animate){ + + var val = that.getStepedValueFromPos((e[that.dirs.mouse] - leftOffset) * widgetUnits); + if(val != o.value){ + that.value(val, false, animate); + eventTimer.call('input', val); } - return false; }; - var callRegister = function(module){ - if(registeredCallbacks[module]){ - registeredCallbacks[module].forEach(function(data){ - data.callback(); - }); + + var remove = function(e){ + if(e && e.type == 'mouseup'){ + eventTimer.call('input', o.value); + eventTimer.call('change', o.value); } + that.element.removeClass('ws-active'); + $(document).off('mousemove', setValueFromPos).off('mouseup', remove); }; - 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 add = function(e){ + e.preventDefault(); + $(document).off('mousemove', setValueFromPos).off('mouseup', remove); + if(!o.readonly && !o.disabled){ + leftOffset = that.element.focus().addClass('ws-active').offset(); + widgetUnits = that.element[that.dirs.width](); + if(!widgetUnits || !leftOffset){return;} + leftOffset = leftOffset[that.dirs.pos]; + widgetUnits = 100 / (widgetUnits - ((that.thumb[that.dirs.outerWidth]() || 2) / 2)); + setValueFromPos(e, o.animate); + $(document) + .on({ + mouseup: remove, + mousemove: setValueFromPos + }) + ; + e.stopPropagation(); } }; - - - var activeLang = function(lang){ - - if(typeof lang == 'string' && lang !== currentLang){ - currentLang = lang; - shortLang = currentLang.split('-')[0]; - if(currentLang == shortLang){ - shortLang = false; + var elementEvts = { + mousedown: add, + focus: function(e){ + if(!o.disabled){ + eventTimer.init('input', o.value); + eventTimer.init('change', o.value); + that.element.addClass('ws-focus'); } - $.each(callbacks, function(i, data){ - callLang(data); - }); - } else if(typeof lang == 'object'){ - - if(lang.register){ - if(!registeredCallbacks[lang.register]){ - registeredCallbacks[lang.register] = []; + hasFocus = true; + }, + blur: function(e){ + that.element.removeClass('ws-focus ws-active'); + hasFocus = false; + eventTimer.init('input', o.value); + eventTimer.call('change', o.value); + }, + keyup: function(){ + that.element.removeClass('ws-active'); + eventTimer.call('input', o.value); + eventTimer.call('change', o.value); + }, + + keydown: function(e){ + var step = true; + var code = e.keyCode; + if(!o.readonly && !o.disabled){ + if (code == 39 || code == 38) { + that.doStep(1); + } else if (code == 37 || code == 40) { + that.doStep(-1); + } else if (code == 33) { + that.doStep(10, o.animate); + } else if (code == 34) { + that.doStep(-10, o.animate); + } else if (code == 36) { + that.value(that.options.max, false, o.animate); + } else if (code == 35) { + that.value(that.options.min, false, o.animate); + } else { + step = false; } - registeredCallbacks[lang.register].push(lang); - lang.callback(); - } else { - if(!lang.activeLang){ - lang.activeLang = ''; + if (step) { + that.element.addClass('ws-active'); + eventTimer.call('input', o.value); + e.preventDefault(); } - 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); + eventTimer.init('input', o.value, this.options.input); + eventTimer.init('change', o.value, this.options.change); + + elementEvts[$.fn.mwheelIntent ? 'mwheelIntent' : 'mousewheel'] = function(e, delta){ + if(delta && hasFocus && !o.readonly && !o.disabled){ + that.doStep(delta); + e.preventDefault(); + eventTimer.call('input', o.value); + } + }; + this.element.on(elementEvts); + this.thumb.on({ + mousedown: add }); - return retDesc; - }; - }); - - webshims.isReady('webshimLocalization', true); -}); -//html5a11y -(function($, document){ - //if we support basic styleing or do not support ARIA (assumed) abort - if(!Modernizr.localstorage || ('hidden' in document.createElement('a'))){return;} - - 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); + }, + updateMetrics: function(){ + var width = this.element.innerWidth(); + this.vertical = (width && this.element.innerHeight() - width > 10); + + this.dirs = this.vertical ? + {mouse: 'pageY', pos: 'top', min: 'max', max: 'min', left: 'top', width: 'height', outerWidth: 'outerHeight'} : + {mouse: 'pageX', pos: 'left', min: 'min', max: 'max', left: 'left', width: 'width', outerWidth: 'outerWidth'} + ; + this.element + [this.vertical ? 'addClass' : 'removeClass']('vertical-range') + [this.vertical ? 'addClass' : 'removeClass']('horizontal-range') + ; } }; - $.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); - } + $.fn.rangeUI = function(opts){ + opts = $.extend({readonly: false, disabled: false, tabindex: 0, min: 0, step: 1, max: 100, value: 50, input: $.noop, change: $.noop, _change: $.noop, showLabels: true, options: {}}, opts); + return this.each(function(){ + $.webshims.objectCreate(rangeProto, { + element: { + value: $(this) + } + }, opts); }); - 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); - -//additional tests for partial implementation of forms features -(function($){ - "use strict"; - var isWebkit = /webkit/i.test(navigator.userAgent); - 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 required="" name="a" /></form>'); - var testRequiredFind = function(){ - if(form[0].querySelector){ - try { - bugs.findRequired = !(form[0].querySelector('select:required')); - } catch(er){ - bugs.findRequired = false; - } - } }; - var inputElem = $('input', form).eq(0); - var onDomextend = function(fn){ - webshims.loader.loadList(['dom-extend']); - webshims.ready('dom-extend', fn); - }; + jQuery.webshims.isReady('range-ui', true); +})(jQuery); +jQuery.webshims.register('form-number-date-ui', function($, webshims, window, document, undefined, options){ + "use strict"; + var curCfg; + var formcfg = $.webshims.formcfg; - bugs.findRequired = false; - bugs.validationMessage = 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; - } + var stopPropagation = function(e){ + e.stopImmediatePropagation(e); }; - - if(!Modernizr.formvalidation || bugs.bustedValidity){ - testRequiredFind(); - } else { - //create delegatable events - webshims.capturingEvents(['input']); - webshims.capturingEvents(['invalid'], true); - - if(window.opera || window.testGoodWithFix){ - - form.appendTo('head'); - - testRequiredFind(); - bugs.validationMessage = !(inputElem.prop('validationMessage')); - - webshims.reTest(['form-native-extend', 'form-message']); - - form.remove(); - - $(function(){ - onDomextend(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).on('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; - } - } - }); - }); - - }); + var createFormat = function(name){ + if(!curCfg.patterns[name+'Obj']){ + var obj = {}; + $.each(curCfg.patterns[name].split(curCfg[name+'Format']), function(i, name){ + obj[name] = i; }); + curCfg.patterns[name+'Obj'] = obj; } - - if(isWebkit && !webshims.bugs.bustedValidity){ - (function(){ - var elems = /^(?:textarea|input)$/i; - var form = false; - - document.addEventListener('contextmenu', function(e){ - if(elems.test( e.target.nodeName || '') && (form = e.target.form)){ - setTimeout(function(){ - form = false; - }, 1); + }; + var splitInputs = { + date: { + _create: function(){ + var obj = { + splits: [$('<input type="text" class="yy" size="4" maxlength />')[0], $('<input type="text" class="mm" maxlength="2" size="2" />')[0], $('<input type="text" class="dd ws-spin" maxlength="2" size="2" />')[0]] + }; + obj.elements = [obj.splits[0], $('<span class="ws-input-seperator" />')[0], obj.splits[1], $('<span class="ws-input-seperator" />')[0], obj.splits[2]]; + return obj; + }, + sort: function(element){ + createFormat('d'); + var i = 0; + var seperators = $('.ws-input-seperator', element).html(curCfg.dFormat); + var inputs = $('input', element); + $.each(curCfg.patterns.dObj, function(name, value){ + var input = inputs.filter('.'+ name); + if(input[0]){ + + input.appendTo(element); + if(i < seperators.length){ + seperators.eq(i).insertAfter(input); + } + i++; } - }, false); - - $(window).on('invalid', function(e){ - if(e.originalEvent && form && form == e.target.form){ - e.wrongWebkitInvalid = true; - e.stopImmediatePropagation(); - } }); - - })(); - } - } - - - -jQuery.webshims.register('form-core', function($, webshims, window, document, undefined, options){ - "use strict"; - - - var checkTypes = {checkbox: 1, radio: 1}; - var emptyJ = $([]); - var bugs = webshims.bugs; - var groupTypes = {radio: 1}; - 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"]'); + }, + month: { + _create: function(){ + var obj = { + splits: [$('<input type="text" class="yy" size="4" />')[0], $('<input type="text" class="mm ws-spin" />')[0]] + }; + obj.elements = [obj.splits[0], $('<span class="ws-input-seperator" />')[0], obj.splits[1]]; + return obj; + }, + sort: function(element){ + var seperator = $('.ws-input-seperator', element).html(curCfg.dFormat); + var mm = $('input.mm', element); + var action; + if(curCfg.date.showMonthAfterYear){ + mm.appendTo(element); + action = 'insertBefore'; + } else { + mm.prependTo(element); + action = 'insertAfter'; + } + seperator[action](mm); + } } - return ret; }; - - var getContentValidationMessage = webshims.getContentValidationMessage = function(elem, validity, key){ - var message = $(elem).data('errormessage') || elem.getAttribute('x-moz-errormessage') || ''; - if(key && message[key]){ - message = message[key]; - } - 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; - } + var labelWidth = (function(){ + var getId = function(){ + return webshims.getID(this); + }; + return function(element, labels, noFocus){ + $(element).attr({'aria-labelledby': labels.map(getId).get().join(' ')}); + if(!noFocus){ + labels.on('click', function(e){ + element.getShadowFocusElement().focus(); + e.preventDefault(); + return false; }); } - } - - if(typeof message == 'object'){ - message = message.defaultMessage; - } - return message || ''; + }; + })(); + var addZero = function(val){ + if(!val){return "";} + val = val+''; + return val.length == 1 ? '0'+val : val; }; - /* - * Selectors for all browsers - */ - var rangeTypes = {number: 1, range: 1, date: 1/*, time: 1, 'datetime-local': 1, datetime: 1, month: 1, week: 1*/}; - var hasInvalid = function(elem){ - var ret = false; - $($.prop(elem, 'elements')).each(function(){ - ret = $(this).is(':invalid'); - if(ret){ - return false; + + (function(){ + var monthDigits = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12']; + formcfg.de = { + numberFormat: { + ",": ".", + ".": "," + }, + timeSigns: ":. ", + numberSigns: ',', + dateSigns: '.', + dFormat: ".", + patterns: { + d: "dd.mm.yy" + }, + month: { + currentText: 'Aktueller Monat' + }, + date: { + close: 'schließen', + clear: 'Löschen', + prevText: 'Zurück', + nextText: 'Vor', + currentText: 'Heute', + monthNames: ['Januar','Februar','März','April','Mai','Juni', + 'Juli','August','September','Oktober','November','Dezember'], + monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun', + 'Jul','Aug','Sep','Okt','Nov','Dez'], + dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'], + dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'], + dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'], + weekHeader: 'KW', + firstDay: 1, + isRTL: false, + showMonthAfterYear: false, + yearSuffix: '' } - }); - return ret; - }; - $.extend($.expr[":"], { - "valid-element": function(elem){ - return $.nodeName(elem, 'form') ? !hasInvalid(elem) :!!($.prop(elem, 'willValidate') && isValid(elem)); - }, - "invalid-element": function(elem){ - return $.nodeName(elem, 'form') ? hasInvalid(elem) : !!($.prop(elem, 'willValidate') && !isValid(elem)); - }, - "required-element": function(elem){ - return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required')); - }, - "user-error": function(elem){ - return ($.prop(elem, 'willValidate') && $(elem).hasClass('user-error')); - }, - "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; + }; + + formcfg.en = { + numberFormat: { + ".": ".", + ",": "," + }, + numberSigns: '.', + dateSigns: '/', + timeSigns: ":. ", + dFormat: "/", + patterns: { + d: "mm/dd/yy" + }, + month: { + currentText: 'This month' + }, + date: { + "closeText": "Done", + clear: 'Clear', + "prevText": "Prev", + "nextText": "Next", + "currentText": "Today", + "monthNames": ["January","February","March","April","May","June","July","August","September","October","November","December"], + "monthNamesShort": ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"], + "dayNames": ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"], + "dayNamesShort": ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"], + "dayNamesMin": ["Su","Mo","Tu","We","Th","Fr","Sa"], + "weekHeader": "Wk", + "firstDay": 0, + "isRTL": false, + "showMonthAfterYear": false, + "yearSuffix": "" } - 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; + }; + + formcfg['en-US'] = formcfg['en-US'] || formcfg['en']; + formcfg[''] = formcfg[''] || formcfg['en-US']; + curCfg = formcfg['']; + + var createMonthKeys = function(langCfg){ + if(!langCfg.date.monthkeys){ + var create = function(i, name){ + var strNum; + var num = i + 1; + strNum = (num < 10) ? '0'+num : ''+num; + langCfg.date.monthkeys[num] = strNum; + langCfg.date.monthkeys[name] = strNum; + langCfg.date.monthkeys[name.toLowerCase()] = strNum; + }; + langCfg.date.monthkeys = {}; + langCfg.date.monthDigits = monthDigits; + langCfg.numberSigns += '-'; + $.each(langCfg.date.monthNames, create); + $.each(langCfg.date.monthNamesShort, create); } - var val = $.prop(elem, 'validity'); - return !!(val && (val.rangeOverflow || val.rangeUnderflow)); - } + }; - }); - - ['valid', 'invalid', 'required', 'optional'].forEach(function(name){ - $.expr[":"][name] = $.expr.filters[name+"-element"]; - }); - - - $.expr[":"].focus = function( elem ) { - try { - var doc = elem.ownerDocument; - return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()); - } catch(e){} - return false; - }; - - if(Modernizr.formvalidation && isWebkit && !webshims.bugs.bustedValidity){ - (function(){ - var retriggerRadioValidity = function(){ - var validity; - if((validity = this.validity) && !validity.customError){ - this.setCustomValidity(''); + createMonthKeys(curCfg); + + $.webshims.ready('dom-extend', function(){ + $.webshims.activeLang({ + register: 'form-core', + callback: function(){ + $.each(arguments, function(i, val){ + if(formcfg[val]){ + curCfg = formcfg[val]; + createMonthKeys(curCfg); + $(document).triggerHandler('wslocalechange'); + return false; + } + }); } - }; - - webshims.addReady(function(context, insertedElement){ - if(context !== document){ - $('input[type="radio"]:invalid', context) - .add(insertedElement.filter('input[type="radio"]:invalid')) - .each(retriggerRadioValidity) - ; - } }); - })(); - } + }); + })(); + - 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]; + (function(){ + + + var mousePress = function(e){ + $(this)[e.type == 'mousepressstart' ? 'addClass' : 'removeClass']('mousepress-ui'); + }; + + var retDefault = function(val, def){ + if(!(typeof val == 'number' || (val && val == val * 1))){ + return def; + } + return val * 1; + }; + + var createOpts = ['step', 'min', 'max', 'readonly', 'title', 'disabled', 'tabindex', 'placeholder', 'value']; + + + var formatVal = { + number: function(val){ + return (val+'').replace(/\,/g, '').replace(/\./, curCfg.numberFormat['.']); + }, + time: function(val){ + return val; + }, + //todo empty val for month/split + month: function(val, options){ + var names; + var p = val.split('-'); + if(p[0] && p[1]){ + names = curCfg.date[options.formatMonthNames] || curCfg.date[options.monthNames] || curCfg.date.monthNames; + p[1] = names[(p[1] * 1) - 1]; + if(options && options.splitInput){ + val = [p[0] || '', p[1] || '']; + } else if(p[1]){ + val = curCfg.date.showMonthAfterYear ? p.join(' ') : p[1]+' '+p[0]; } } - 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(invalidClass)){ - if(isValid(elem)){ - $(elem).getShadowElement().removeClass(invalidClasses); - if(name == 'checked' && val) { - getGroupElements(elem).not(elem).removeClass(invalidClasses).removeAttr('aria-invalid'); + return val; + }, + date: function(val, opts){ + var p = (val+'').split('-'); + if(p[2] && p[1] && p[0]){ + if(opts && opts.splitInput){ + val = p; + } else { + val = curCfg.patterns.d.replace('yy', p[0] || ''); + val = val.replace('mm', p[1] || ''); + val = val.replace('dd', p[2] || ''); + } + } else if(opts && opts.splitInput){ + val = [p[0] || '', p[1] || '', p[2] || '']; } + + return val; } - } - 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 isInGroup = function(name){ - var ret; - try { - ret = document.activeElement.name === name; - } catch(e){} - return ret; - }; - /* form-ui-invalid/form-ui-valid are deprecated. use user-error/user-success instead */ - var invalidClass = 'user-error'; - var invalidClasses = 'user-error form-ui-invalid'; - var validClass = 'user-success'; - var validClasses = 'user-success form-ui-valid'; - var switchValidityClass = function(e){ - var elem, timer; - if(!e.target){return;} - elem = $(e.target).getNativeElement()[0]; - if(elem.type == 'submit' || !$.prop(elem, 'willValidate')){return;} - timer = $.data(elem, 'webshimsswitchvalidityclass'); - var switchClass = function(){ - if(e.type == 'focusout' && elem.type == 'radio' && isInGroup(elem.name)){return;} - var validity = $.prop(elem, 'validity'); - var shadowElem = $(elem).getShadowElement(); - var addClass, removeClass, trigger, generaltrigger, validityCause; - - $(elem).trigger('refreshCustomValidityRules'); - if(validity.valid){ - if(!shadowElem.hasClass(validClass)){ - addClass = validClasses; - removeClass = invalidClasses; - generaltrigger = 'changedvaliditystate'; - trigger = 'changedvalid'; - if(checkTypes[elem.type] && elem.checked){ - getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass).removeAttr('aria-invalid'); + }; + + var parseVal = { + number: function(val){ + return (val+'').replace(curCfg.numberFormat[','], '').replace(curCfg.numberFormat['.'], '.'); + }, + time: function(val){ + return val; + }, + month: function(val, opts){ + + var p = (!opts.splitInput) ? val.trim().split(/[\.\s-\/\\]+/) : val; + + if(p.length == 2){ + p[0] = curCfg.date.monthkeys[p[0]] || p[0]; + p[1] = curCfg.date.monthkeys[p[1]] || p[1]; + if(p[1].length == 2){ + val = p[0]+'-'+p[1]; + } else if(p[0].length == 2){ + val = p[1]+'-'+p[0]; + } else { + val = ''; } - $.removeData(elem, 'webshimsinvalidcause'); + } else if(opts.splitInput) { + val = ''; } - } else { - validityCause = returnValidityCause(validity, elem); - if($.data(elem, 'webshimsinvalidcause') != validityCause){ - $.data(elem, 'webshimsinvalidcause', validityCause); - generaltrigger = 'changedvaliditystate'; + return val; + }, + date: function(val, opts){ + createFormat('d'); + var i; + var obj; + if(opts.splitInput){ + obj = {yy: 0, mm: 1, dd: 2}; + } else { + obj = curCfg.patterns.dObj; + val = val.split(curCfg.dFormat); } - if(!shadowElem.hasClass(invalidClass)){ - addClass = invalidClasses; - removeClass = validClasses; - if (checkTypes[elem.type] && !elem.checked) { - getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass); - } - trigger = 'changedinvalid'; - } + + return (val.length == 3 && val[0] && val[1] && val[2]) ? + ([addZero(val[obj.yy]), addZero(val[obj.mm]), addZero(val[obj.dd])]).join('-') : + '' + ; } - if(addClass){ - shadowElem.addClass(addClass).removeClass(removeClass); - //jQuery 1.6.1 IE9 bug (doubble trigger bug) - setTimeout(function(){ - $(elem).trigger(trigger); - }, 0); + }; + + var steps = { + number: { + step: 1 + }, + time: { + step: 60 + }, + month: { + step: 1, + start: new Date() + }, + date: { + step: 1, + start: new Date() } - if(generaltrigger){ - setTimeout(function(){ - $(elem).trigger(generaltrigger); - }, 0); + }; + + + var placeholderFormat = { + date: function(val, opts){ + var hintValue = (val || '').split('-'); + if(hintValue.length == 3){ + hintValue = opts.splitInput ? + hintValue : + curCfg.patterns.d.replace('yy', hintValue[0]).replace('mm', hintValue[1]).replace('dd', hintValue[2]); + } else { + hintValue = opts.splitInput ? + [val, val, val] : + val; + } + return hintValue; + }, + month: function(val, opts){ + var hintValue = (val || '').split('-'); + + if(hintValue.length == 2){ + hintValue = opts.splitInput ? + hintValue : + curCfg.patterns.d.replace('yy', hintValue[0]).replace('mm', hintValue[1]); + } else { + hintValue = opts.splitInput ? + [val, val] : + val; + } + return hintValue; } - $.removeData(e.target, 'webshimsswitchvalidityclass'); }; - if(timer){ - clearTimeout(timer); - } - if(e.type == 'refreshvalidityui'){ - switchClass(); - } else { - $.data(elem, 'webshimsswitchvalidityclass', setTimeout(switchClass, 9)); - } - }; - - $(document).on(options.validityUIEvents || 'focusout change refreshvalidityui', switchValidityClass); - customEvents.changedvaliditystate = true; - customEvents.refreshCustomValidityRules = 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 = (isWebkit || 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 = 'span'; - var errorBubble; - var hideTimer = false; - var focusTimer = false; - var resizeTimer = false; - var boundHide; + var createHelper = (function(){ + var types = {}; + return function(type){ + var input; + if(!types[type]){ + input = $('<input type="'+type+'" />'); + types[type] = { + asNumber: function(val){ + var type = (typeof val == 'object') ? 'valueAsDate' : 'value'; + return input.prop(type, val).prop('valueAsNumber'); + }, + asValue: function(val){ + var type = (typeof val == 'object') ? 'valueAsDate' : 'valueAsNumber'; + return input.prop(type, val).prop('value'); + } + }; + } + return types[type]; + }; + })(); - 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(); + steps.range = steps.number; + + + var spinBtnProto = { + _create: function(){ + var i; + var o = this.options; + var helper = createHelper(o.type); + this.type = o.type; + this.orig = o.orig; + + this.elemHelper = $('<input type="'+ this.type+'" />'); + this.asNumber = helper.asNumber; + this.asValue = helper.asValue; + + this.buttonWrapper = $('<span class="input-buttons '+this.type+'-input-buttons"><span unselectable="on" class="step-controls"><span class="step-up"></span><span class="step-down"></span></span></span>') + .insertAfter(this.element) + ; + + if(o.splitInput){ + this._addSplitInputs(); } else { - - this.getMessage(elem, message); - this.position(visual, offset); - - this.show(); - if(this.hideDelay){ - hideTimer = setTimeout(boundHide, this.hideDelay); - } - $(window) - .on('resize.validityalert reposoverlay.validityalert', function(){ - clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - api.position(visual); - }, 9); - }) - ; + this.inputElements = this.element; } - if(!noFocusElem){ - this.setFocus(visual, offset); + this.options.containerElements.push(this.buttonWrapper[0]); + + if(typeof steps[this.type].start == 'object'){ + steps[this.type].start = this.asNumber(steps[this.type].start); } + + + + for(i = 0; i < createOpts.length; i++){ + this[createOpts[i]](o[createOpts[i]]); + } + + this.element.data('wsspinner', this); + + this.addBindings(); + + if(!o.min && typeof o.relMin == 'number'){ + o.min = this.asValue(this.getRelNumber(o.relMin)); + $.prop(this.orig, 'min', o.min); + } + + if(!o.max && typeof o.relMax == 'number'){ + o.max = this.asValue(this.getRelNumber(o.relMax)); + $.prop(this.orig, 'max', o.max); + } + + this._init = true; }, - getOffsetFromBody: function(elem){ - return webshims.getRelOffset(errorBubble, elem); + _addSplitInputs: function(){ + if(!this.inputElements){ + var create = splitInputs[this.type]._create(); + this.splits = create.splits; + this.inputElements = $(create.elements).prependTo(this.element).filter('input'); + } }, - 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)); + parseValue: function(){ + var value = this.inputElements.map(function(){ + return $.prop(this, 'value'); + }).get(); + if(!this.options.splitInput){ + value = value[0]; } + return parseVal[this.type](value, this.options); + }, + formatValue: function(val, noSplit){ + return formatVal[this.type](val, noSplit === false ? false : this.options); + }, + placeholder: function(val){ + var options = this.options; + options.placeholder = val; + var placeholder = val; + if(placeholderFormat[this.type]){ + placeholder = placeholderFormat[this.type](val, this.options); + } + if(options.splitInput && typeof placeholder == 'object'){ + $.each(this.splits, function(i, elem){ + $.prop(elem, 'placeholder', placeholder[i]); + }); + } else { + this.element.prop('placeholder', placeholder); + } + }, + getRelNumber: function(rel){ + var start = steps[this.type].start || 0; + if(rel){ + start += rel; + } + return start; + }, + addZero: addZero, + _setStartInRange: function(){ + var start = this.getRelNumber(this.options.relDefaultValue); + if(!isNaN(this.minAsNumber) && start < this.minAsNumber){ + start = this.minAsNumber; + } else if(!isNaN(this.maxAsNumber) && start > this.maxAsNumber){ + start = this.maxAsNumber; + } + this.elemHelper.prop('valueAsNumber', start); + this.options.defValue = this.elemHelper.prop('value'); - if(scrollTop > elemTop){ - webshims.scrollRoot.animate( - {scrollTop: elemTop - 5}, - { - queue: false, - duration: Math.max( Math.min( 600, (scrollTop - elemTop) * 1.5 ), 80 ) + }, + reorderInputs: function(){ + if(splitInputs[this.type]){ + var element = this.element; + splitInputs[this.type].sort(element); + setTimeout(function(){ + var data = webshims.data(element); + if(data && data.shadowData){ + data.shadowData.shadowFocusElement = element.find('input')[0] || element[0]; } - ); - smooth = true; + }, 9); } - try { - focusElem[0].focus(); - } catch(e){} - if(smooth){ - webshims.scrollRoot.scrollTop(scrollTop); - setTimeout(function(){ - webshims.scrollRoot.scrollTop(scrollTop); - }, 0); - } - setTimeout(function(){ - $(document).on('focusout.validityalert', boundHide); - }, 10); - $(window).triggerHandler('reposoverlay'); }, - getMessage: function(elem, message){ - if (!message) { - message = getContentValidationMessage(elem[0]) || elem.prop('customValidationMessage') || elem.prop('validationMessage'); + value: function(val){ + this.valueAsNumber = this.asNumber(val); + this.options.value = val; + if(isNaN(this.valueAsNumber) || (!isNaN(this.minAsNumber) && this.valueAsNumber < this.minAsNumber) || (!isNaN(this.maxAsNumber) && this.valueAsNumber > this.maxAsNumber)){ + this._setStartInRange(); + } else { + this.elemHelper.prop('value', val); + this.options.defValue = ""; } - if (message) { - $('span.va-box', errorBubble).text(message); + + val = formatVal[this.type](val, this.options); + if(this.options.splitInput){ + + $.each(this.splits, function(i, elem){ + $.prop(elem, 'value', val[i]); + }); + } else { + this.element.prop('value', val); } - else { - this.hide(); + + this._propertyChange('value'); + }, + initDataList: function(){ + var listTimer; + var that = this; + var updateList = function(){ + $(that.orig) + .jProp('list') + .off('updateDatalist', updateList) + .on('updateDatalist', updateList) + ; + clearTimeout(listTimer); + listTimer = setTimeout(function(){ + if(that.list){ + that.list(); + } + }, 9); + + }; + + $(this.orig).onTrigger('listdatalistchange', updateList); + }, + getOptions: function(){ + var options = {}; + var datalist = $(this.orig).jProp('list'); + datalist.find('option').each(function(){ + options[$.prop(this, 'value')] = $.prop(this, 'label'); + }); + return [options, datalist.data('label')]; + }, + list: function(val){ + if(this.type == 'number' || this.type == 'time'){ + this.element.attr('list', $.attr(this.orig, 'list')); } + this.options.list = val; + this._propertyChange('list'); }, - position: function(elem, offset){ - offset = offset ? $.extend({}, offset) : api.getOffsetFromBody(elem); - offset.top += elem.outerHeight(); - errorBubble.css(offset); + _propertyChange: $.noop, + tabindex: function(val){ + this.options.tabindex = val; + this.inputElements.prop('tabindex', this.options.tabindex); }, - show: function(){ - if(errorBubble.css('display') === 'none'){ - errorBubble.css({opacity: 0}).show(); + title: function(val){ + this.options.title = val; + this.element.prop('title', this.options.title); + }, + + min: function(val){ + this.elemHelper.prop('min', val); + this.minAsNumber = this.asNumber(val); + if(this.valueAsNumber != null && isNaN(this.valueAsNumber)){ + this._setStartInRange(); } - errorBubble.addClass('va-visible').fadeTo(400, 1); + this.options.min = val; + this._propertyChange('min'); }, - hide: function(){ - errorBubble.removeClass('va-visible').fadeOut(); + max: function(val){ + this.elemHelper.prop('max', val); + this.maxAsNumber = this.asNumber(val); + if(this.valueAsNumber != null && isNaN(this.valueAsNumber)){ + this._setStartInRange(); + } + this.options.max = val; + this._propertyChange('max'); }, - clear: function(){ - clearTimeout(focusTimer); - clearTimeout(hideTimer); - $(document).unbind('.validityalert'); - $(window).unbind('.validityalert'); - errorBubble.stop().removeAttr('for'); + step: function(val){ + var defStep = steps[this.type]; + this.options.step = val; + this.elemHelper.prop('step', retDefault(val, defStep.step)); }, - _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){ - errorBubble.bgIframe(); + addBindings: function(){ + var isFocused; + + var that = this; + var o = this.options; + + var eventTimer = (function(){ + var events = {}; + return { + init: function(name, curVal, fn){ + if(!events[name]){ + events[name] = {fn: fn}; + $(that.orig).on(name, function(){ + events[name].val = $.prop(that.orig, 'value'); + }); + } + events[name].val = curVal; + }, + call: function(name, val){ + if(events[name] && events[name].val != val){ + clearTimeout(events[name].timer); + events[name].val = val; + events[name].timer = setTimeout(function(){ + events[name].fn(val, that); + }, 9); + } + } + }; + })(); + var initChangeEvents = function(){ + eventTimer.init('input', $.prop(that.orig, 'value'), that.options.input); + eventTimer.init('change', $.prop(that.orig, 'value'), that.options.change); + }; + + var step = {}; + + var preventBlur = function(e){ + if(preventBlur.prevent){ + e.preventDefault(); + (isFocused || that.element.getShadowFocusElement()).focus(); + e.stopImmediatePropagation(); + return true; } + }; + var callSplitChange = (function(){ + var timer; + + var call = function(e){ + var val; + clearTimeout(timer); + val = that.parseValue(); + $.prop(that.orig, 'value', val); + eventTimer.call('input', val); + if(!e || e.type != 'wsupdatevalue'){ + eventTimer.call('change', val); + } + }; + + var onFocus = function(){ + clearTimeout(timer); + }; + var onBlur = function(e){ + clearTimeout(timer); + timer = setTimeout(call, 0); + + if(e.type == 'change'){ + stopPropagation(e); + if(!o.splitInput){ + call(); + } + } + }; + + that.element.on('wsupdatevalue', call); + + that.inputElements + .add(that.buttonWrapper) + .add(that.element) + .on( + { + 'focus focusin': onFocus, + 'blur focusout change': onBlur + } + ) + ; + setTimeout(function(){ + if(that.popover){ + $('> *', that.popover.element) + .on({ + 'focusin': onFocus, + 'focusout': onBlur + }) + ; + } + }, 0); + })(); + + var spinEvents = {}; + var spinElement = o.splitInput ? this.inputElements.filter('.ws-spin') : this.inputElements.eq(0); + var elementEvts = { + blur: function(e){ + if(!preventBlur(e) && !o.disabled && !o.readonly){ + if(!preventBlur.prevent){ + isFocused = false; + } + } + stopPropagation(e); + }, + focus: function(e){ + if(!isFocused){ + initChangeEvents(); + isFocused = this; + } + }, + keypress: function(e){ + if(e.isDefaultPrevented()){return;} + var chr; + var stepped = true; + var code = e.keyCode; + if(!e.ctrlKey && !e.metaKey && curCfg[that.type+'Signs']){ + chr = String.fromCharCode(e.charCode == null ? code : e.charCode); + stepped = !(chr < " " || (curCfg[that.type+'Signs']+'0123456789').indexOf(chr) > -1); + } else { + stepped = false; + } + if(stepped){ + e.preventDefault(); + } + }, + 'input keydown keypress': (function(){ + var timer; + var isStopped = false; + var releaseTab = function(){ + if(isStopped === true){ + isStopped = 'semi'; + timer = setTimeout(releaseTab, 250); + } else { + isStopped = false; + } + }; + var stopTab = function(){ + isStopped = true; + clearTimeout(timer); + timer = setTimeout(releaseTab, 300); + }; + var select = function(){ + this.focus(); + this.select(); + stopTab(); + }; + + return function(e){ + if(o.splitInput && o.jumpInputs){ + if(e.type == 'input'){ + if($.prop(this, 'value').length === $.prop(this, 'maxLength')){ + try { + $(this) + .next() + .next('input') + .each(select) + ; + } catch(er){} + } + } else if(!e.shiftKey && !e.crtlKey && e.keyCode == 9 && (isStopped === true || (isStopped && !$.prop(this, 'value')))){ + e.preventDefault(); + } + } + } + })() + }; + var mouseDownInit = function(){ + if(!o.disabled && !isFocused){ + that.element.getShadowFocusElement().focus(); + } + preventBlur.set(); + + return false; + }; + + preventBlur.set = (function(){ + var timer; + var reset = function(){ + preventBlur.prevent = false; + }; + return function(){ + clearTimeout(timer); + preventBlur.prevent = true; + setTimeout(reset, 9); + }; + })(); + + ['stepUp', 'stepDown'].forEach(function(name){ + step[name] = function(factor){ + if(!o.disabled && !o.readonly){ + if(!isFocused){ + mouseDownInit(); + } + var ret = false; + if (!factor) { + factor = 1; + } + try { + that.elemHelper[name](factor); + ret = that.elemHelper.prop('value'); + that.value(ret); + eventTimer.call('input', ret); + } catch (er) {} + return ret; + } + }; }); + + + + this.buttonWrapper.on('mousedown', mouseDownInit); + + this.setInput = function(value){ + that.value(value); + eventTimer.call('input', value); + }; + this.setChange = function(value){ + that.setInput(value); + eventTimer.call('change', value); + }; + + + + this.inputElements.on(elementEvts); + + if(!o.noSpinbtn){ + spinEvents[$.fn.mwheelIntent ? 'mwheelIntent' : 'mousewheel'] = function(e, delta){ + if(delta && isFocused && !o.disabled){ + step[delta > 0 ? 'stepUp' : 'stepDown'](); + e.preventDefault(); + } + }; + spinEvents.keydown = function(e){ + if(o.list || e.isDefaultPrevented() || $.attr(this, 'list')){return;} + var stepped = true; + var code = e.keyCode; + if (code == 38) { + step.stepUp(); + } else if (code == 40) { + step.stepDown(); + } else { + stepped = false; + } + if(stepped){ + e.preventDefault(); + } + }; + + spinElement.attr({'autocomplete': 'off', role: 'spinbutton'}).on(spinEvents); + } + + + if(!o.splitInput){ + $(document).on('wslocalechange',function(){ + if(o.value){ + that.value(o.value); + } + + if(placeholderFormat[that.type] && o.placeholder){ + that.placeholder(o.placeholder); + } + }); + } else { + $(document).onTrigger('wslocalechange',function(){ + that.reorderInputs(); + }); + } + + $('.step-up', this.buttonWrapper) + .on({ + 'mousepressstart mousepressend': mousePress, + 'mousedown mousepress': function(e){ + step.stepUp(); + } + }) + ; + $('.step-down', this.buttonWrapper) + .on({ + 'mousepressstart mousepressend': mousePress, + 'mousedown mousepress': function(e){ + step.stepDown(); + } + }) + ; + initChangeEvents(); } }; + ['readonly', 'disabled'].forEach(function(name){ + spinBtnProto[name] = function(val){ + if(this.options[name] != val || !this._init){ + this.options[name] = !!val; + if(name == 'readonly' && this.options.noInput){ + this.element + .prop(name, true) + .attr({'aria-readonly': this.options[name]}) + ; + } else { + this.element.prop(name, this.options[name]); + } + this.buttonWrapper[this.options[name] ? 'addClass' : 'removeClass']('ws-'+name); + } + }; + }); - boundHide = $.proxy(api, 'hide'); - return api; + $.fn.spinbtnUI = function(opts){ + opts = $.extend({ + monthNames: 'monthNames', + size: 1, + startView: 0 + }, opts); + return this.each(function(){ + $.webshims.objectCreate(spinBtnProto, { + element: { + value: $(this) + } + }, opts); + }); + }; })(); - - /* extension, but also used to fix native implementation workaround/bugfixes */ (function(){ - var firstEvent, - invalids = [], - stopSubmitTimer, - form - ; + var picker = {}; + var disable = { + + }; - $(document).on('invalid', function(e){ - if(e.wrongWebkitInvalid){return;} - var jElm = $(e.target); - var shadowElem = jElm.getShadowElement(); - if(!shadowElem.hasClass(invalidClass)){ - shadowElem.addClass(invalidClasses).removeClass(validClasses); - setTimeout(function(){ - $(e.target).trigger('changedinvalid').trigger('changedvaliditystate'); - }, 0); + var getDateArray = function(date){ + var ret = [date.getFullYear(), addZero(date.getMonth() + 1), addZero(date.getDate())]; + ret.month = ret[0]+'-'+ret[1]; + ret.date = ret[0]+'-'+ret[1]+'-'+ret[2]; + return ret; + }; + var today = getDateArray(new Date()); + + var _setFocus = function(element, _noFocus){ + var setFocus, that; + element = $(element || this.activeButton); + this.activeButton.attr({tabindex: '-1', 'aria-selected': 'false'}); + this.activeButton = element.attr({tabindex: '0', 'aria-selected': 'true'}); + this.index = this.buttons.index(this.activeButton[0]); + + clearTimeout(this.timer); + + if(!this.popover.openedByFocus && !_noFocus){ + that = this; + setFocus = function(noTrigger){ + clearTimeout(that.timer); + that.timer = setTimeout(function(){ + if(element[0]){ + element[0].focus(); + if(noTrigger !== true && !element.is(':focus')){ + setFocus(true); + } + } + }, that.popover.isVisible ? 99 : 360); + }; + this.popover.activateElement(element); + setFocus(); } - 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); + }; + + var _initialFocus = function(){ + var sel; + if(this.popover.navedInitFocus){ + sel = this.popover.navedInitFocus.sel || this.popover.navedInitFocus; + if((!this.activeButton || !this.activeButton[0]) && this.buttons[sel]){ + this.activeButton = this.buttons[sel](); + } else if(sel){ + this.activeButton = $(sel, this.element); + } + + if(!this.activeButton[0] && this.popover.navedInitFocus.alt){ + this.activeButton = this.buttons[this.popover.navedInitFocus.alt](); + } } - - //if firstinvalid was prevented all invalids will be also prevented - if( firstEvent && firstEvent.isDefaultPrevented() ){ - e.preventDefault(); + + if(!this.activeButton || !this.activeButton[0]){ + this.activeButton = this.buttons.filter('.checked-value'); } - 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; - }); - })(); - - $.fn.getErrorMessage = function(){ - var message = ''; - var elem = this[0]; - if(elem){ - message = getContentValidationMessage(elem) || $.prop(elem, 'customValidationMessage') || $.prop(elem, 'validationMessage'); - } - return message; - }; - - if(options.replaceValidationUI){ - webshims.ready('DOM forms', function(){ - $(document).on('firstinvalid', function(e){ - if(!e.isInvalidUIPrevented()){ - e.preventDefault(); - $.webshims.validityAlert.showFor( e.target ); - } - }); - }); - } -}); - -})(jQuery); -jQuery.webshims.register('form-message', function($, webshims, window, document, undefined, options){ - "use strict"; - var validityMessages = webshims.validityMessages; - - var implementProperties = (options.overrideMessages || options.customMessages) ? ['customValidationMessage'] : []; - - validityMessages['en'] = $.extend(true, { - typeMismatch: { - email: 'Please enter an email address.', - url: 'Please enter a URL.', - number: 'Please enter a number.', - date: 'Please enter a date.', - time: 'Please enter a time.', - range: 'Invalid input.', - "datetime-local": 'Please enter a datetime.' - }, - rangeUnderflow: { - defaultMessage: 'Value must be greater than or equal to {%min}.' - }, - rangeOverflow: { - defaultMessage: 'Value must be less than or equal to {%max}.' - }, - stepMismatch: 'Invalid input.', - tooLong: 'Please enter at most {%maxlength} character(s). You entered {%valueLen}.', + + if(!this.activeButton[0]){ + this.activeButton = this.buttons.filter('.this-value'); + } + if(!this.activeButton[0]){ + this.activeButton = this.buttons.eq(0); + } + + this.setFocus(this.activeButton, this.opts.noFocus); + }; - patternMismatch: 'Invalid input. {%title}', - valueMissing: { - defaultMessage: 'Please fill out this field.', - checkbox: 'Please check this box if you want to proceed.' - } - }, (validityMessages['en'] || validityMessages['en-US'] || {})); - - - ['select', 'radio'].forEach(function(type){ - if(typeof validityMessages['en'].valueMissing == 'object'){ - validityMessages['en'].valueMissing[type] = 'Please select an option.'; - } - }); - - ['date', 'time', 'datetime-local'].forEach(function(type){ - if(typeof validityMessages['en'].rangeUnderflow == 'object'){ - validityMessages.en.rangeUnderflow[type] = 'Value must be at or after {%min}.'; - } - }); - ['date', 'time', 'datetime-local'].forEach(function(type){ - if(typeof validityMessages['en'].rangeOverflow == 'object'){ - validityMessages.en.rangeOverflow[type] = 'Value must be at or before {%max}.'; - } - }); - - validityMessages['en-US'] = validityMessages['en-US'] || validityMessages['en']; - validityMessages[''] = validityMessages[''] || validityMessages['en-US']; - - validityMessages['de'] = $.extend(true, { - typeMismatch: { - email: '{%value} ist keine zulässige E-Mail-Adresse', - url: '{%value} ist keine zulässige Webadresse', - number: '{%value} ist keine Nummer!', - date: '{%value} ist kein Datum', - time: '{%value} ist keine Uhrzeit', - range: '{%value} ist keine Nummer!', - "datetime-local": '{%value} ist kein Datum-Uhrzeit Format.' - }, - rangeUnderflow: { - defaultMessage: '{%value} ist zu niedrig. {%min} ist der unterste Wert, den Sie benutzen können.' - }, - rangeOverflow: { - defaultMessage: '{%value} ist zu hoch. {%max} ist der oberste Wert, den Sie benutzen können.' - }, - stepMismatch: 'Der Wert {%value} ist in diesem Feld nicht zulässig. Hier sind nur bestimmte Werte zulässig. {%title}', - tooLong: 'Der eingegebene Text ist zu lang! Sie haben {%valueLen} Zeichen eingegeben, dabei sind {%maxlength} das Maximum.', - patternMismatch: '{%value} hat für dieses Eingabefeld ein falsches Format! {%title}', - valueMissing: { - defaultMessage: 'Bitte geben Sie einen Wert ein', - checkbox: 'Bitte aktivieren Sie das Kästchen' - } - }, (validityMessages['de'] || {})); - - ['select', 'radio'].forEach(function(type){ - if(typeof validityMessages['de'].valueMissing == 'object'){ - validityMessages['de'].valueMissing[type] = 'Bitte wählen Sie eine Option aus'; - } - }); - - ['date', 'time', 'datetime-local'].forEach(function(type){ - if(typeof validityMessages['de'].rangeUnderflow == 'object'){ - validityMessages.de.rangeUnderflow[type] = '{%value} ist zu früh. {%min} ist die früheste Zeit, die Sie benutzen können.'; - } - }); - ['date', 'time', 'datetime-local'].forEach(function(type){ - if(typeof validityMessages['de'].rangeOverflow == 'object'){ - validityMessages.de.rangeOverflow[type] = '{%value} ist zu spät. {%max} ist die späteste Zeit, die Sie benutzen können.'; - } - }); - - var currentValidationMessage = validityMessages['']; - - - webshims.createValidationMessage = function(elem, name){ - var message = currentValidationMessage[name]; - if(message && typeof message !== 'string'){ - message = message[ $.prop(elem, 'type') ] || message[ (elem.nodeName || '').toLowerCase() ] || message[ 'defaultMessage' ]; - } - if(message){ - ['value', 'min', 'max', 'title', 'maxlength', 'label'].forEach(function(attr){ - if(message.indexOf('{%'+attr) === -1){return;} - var val = ((attr == 'label') ? $.trim($('label[for="'+ elem.id +'"]', elem.form).text()).replace(/\*$|:$/, '') : $.attr(elem, attr)) || ''; - if(name == 'patternMismatch' && attr == 'title' && !val){ - webshims.error('no title for patternMismatch provided. Always add a title attribute.'); + + webshims.ListBox = function (element, popover, opts){ + this.element = $('ul', element); + this.popover = popover; + this.opts = opts || {}; + this.buttons = $('button:not(:disabled)', this.element); + + + this.ons(this); + this._initialFocus(); + }; + + webshims.ListBox.prototype = { + setFocus: _setFocus, + _initialFocus: _initialFocus, + prev: function(){ + var index = this.index - 1; + if(index < 0){ + if(this.opts.prev){ + this.popover.navedInitFocus = 'last'; + this.popover.actionFn(this.opts.prev); + this.popover.navedInitFocus = false; + } + } else { + this.setFocus(this.buttons.eq(index)); } - message = message.replace('{%'+ attr +'}', val); - if('value' == attr){ - message = message.replace('{%valueLen}', val.length); + }, + next: function(){ + var index = this.index + 1; + if(index >= this.buttons.length){ + if(this.opts.next){ + this.popover.navedInitFocus = 'first'; + this.popover.actionFn(this.opts.next); + this.popover.navedInitFocus = false; + } + } else { + this.setFocus(this.buttons.eq(index)); } - }); - } - return message || ''; - }; - - - if(webshims.bugs.validationMessage || !Modernizr.formvalidation || webshims.bugs.bustedValidity){ - implementProperties.push('validationMessage'); - } - - webshims.activeLang({ - langObj: validityMessages, - module: 'form-core', - callback: function(langObj){ - currentValidationMessage = langObj; - } - }); - - implementProperties.forEach(function(messageProp){ - webshims.defineNodeNamesProperty(['fieldset', 'output', 'button'], messageProp, { - prop: { - value: '', - writeable: false - } - }); - ['input', 'select', 'textarea'].forEach(function(nodeName){ - var desc = webshims.defineNodeNameProperty(nodeName, messageProp, { - prop: { - get: function(){ - var elem = this; - var message = ''; - if(!$.prop(elem, 'willValidate')){ - return message; - } - - var validity = $.prop(elem, 'validity') || {valid: 1}; - - if(validity.valid){return message;} - message = webshims.getContentValidationMessage(elem, validity); - - if(message){return message;} - - if(validity.customError && elem.nodeName){ - message = (Modernizr.formvalidation && !webshims.bugs.bustedValidity && desc.prop._supget) ? desc.prop._supget.call(elem) : webshims.data(elem, 'customvalidationMessage'); - if(message){return message;} - } - $.each(validity, function(name, prop){ - if(name == 'valid' || !prop){return;} - - message = webshims.createValidationMessage(elem, name); - if(message){ + }, + ons: function(that){ + this.element + .on({ + 'keydown': function(e){ + var handled; + var key = e.keyCode; + if(e.ctrlKey){return;} + if(key == 36 || key == 33){ + that.setFocus(that.buttons.eq(0)); + handled = true; + } else if(key == 34 || key == 35){ + that.setFocus(that.buttons.eq(that.buttons.length - 1)); + handled = true; + } else if(key == 38 || key == 37){ + that.prev(); + handled = true; + } else if(key == 40 || key == 39){ + that.next(); + handled = true; + } + if(handled){ return false; } - }); - return message || ''; - }, - writeable: false - } - }); - }); + } + }) + ; + } + }; - }); -}); -(function($, Modernizr, webshims){ - "use strict"; - var hasNative = Modernizr.audio && Modernizr.video; - var supportsLoop = false; - var bugs = webshims.bugs; - - var loadSwf = function(){ - webshims.ready(swfType, function(){ - if(!webshims.mediaelement.createSWF){ - webshims.mediaelement.loadSwf = true; - webshims.reTest([swfType], hasNative); + webshims.Grid = function (element, popover, opts){ + this.element = $('tbody', element); + this.popover = popover; + this.opts = opts || {}; + this.buttons = $('button:not(:disabled,.othermonth)', this.element); + + this.ons(this); + + this._initialFocus(); + if(this.popover.openedByFocus){ + this.popover.activeElement = this.activeButton; } - }); - }; - var options = webshims.cfg.mediaelement; - var swfType = options && options.player == 'jwplayer' ? 'mediaelement-swf' : 'mediaelement-jaris'; - var hasSwf; - if(!options){ - webshims.error("mediaelement wasn't implemented but loaded"); - return; - } - if(hasNative){ - var videoElem = document.createElement('video'); - Modernizr.videoBuffered = ('buffered' in videoElem); - supportsLoop = ('loop' in videoElem); + }; - webshims.capturingEvents(['play', 'playing', 'waiting', 'paused', 'ended', 'durationchange', 'loadedmetadata', 'canplay', 'volumechange']); - if(!Modernizr.videoBuffered){ - webshims.addPolyfill('mediaelement-native-fix', { - f: 'mediaelement', - test: Modernizr.videoBuffered, - d: ['dom-support'] - }); + + webshims.Grid.prototype = { + setFocus: _setFocus, + _initialFocus: _initialFocus, - webshims.reTest('mediaelement-native-fix'); - } - } - - if(hasNative && !options.preferFlash){ - var switchOptions = function(e){ - var parent = e.target.parentNode; - if(!options.preferFlash && ($(e.target).is('audio, video') || (parent && $('source:last', parent)[0] == e.target)) ){ - webshims.ready('DOM mediaelement', function(){ - if(hasSwf){ - loadSwf(); - } - webshims.ready('WINDOWLOAD '+swfType, function(){ - setTimeout(function(){ - if(hasSwf && !options.preferFlash && webshims.mediaelement.createSWF && !$(e.target).closest('audio, video').is('.nonnative-api-active')){ - options.preferFlash = true; - document.removeEventListener('error', switchOptions, true); - $('audio, video').each(function(){ - webshims.mediaelement.selectSource(this); - }); - webshims.info("switching mediaelements option to 'preferFlash', due to an error with native player: "+e.target.src); - } else if(!hasSwf){ - document.removeEventListener('error', switchOptions, true); + first: function(){ + this.setFocus(this.buttons.eq(0)); + }, + last: function(){ + this.setFocus(this.buttons.eq(this.buttons.length - 1)); + }, + upPage: function(){ + $('.ws-picker-header > button:not(:disabled)', this.popover.element).trigger('click'); + }, + downPage: function(){ + this.activeButton.filter(':not([data-action="changeInput"])').trigger('click'); + }, + ons: function(that){ + this.element + .on({ + 'keydown': function(e){ + var handled; + var key = e.keyCode; + + if(e.shiftKey){return;} + + if((e.ctrlKey && key == 40)){ + handled = 'downPage'; + } else if((e.ctrlKey && key == 38)){ + handled = 'upPage'; + } else if(key == 33 || (e.ctrlKey && key == 37)){ + handled = 'prevPage'; + } else if(key == 34 || (e.ctrlKey && key == 39)){ + handled = 'nextPage'; + } else if(e.keyCode == 36 || e.keyCode == 33){ + handled = 'first'; + } else if(e.keyCode == 35){ + handled = 'last'; + } else if(e.keyCode == 38){ + handled = 'up'; + } else if(e.keyCode == 37){ + handled = 'prev'; + } else if(e.keyCode == 40){ + handled = 'down'; + } else if(e.keyCode == 39){ + handled = 'next'; } - }, 20); - }); - }); + if(handled){ + that[handled](); + return false; + } + } + }) + ; } }; - document.addEventListener('error', switchOptions, true); - $('audio, video').each(function(){ - if(this.error){ - switchOptions({target: this}); - } + $.each({ + prevPage: {get: 'last', action: 'prev'}, + nextPage: {get: 'first', action: 'next'} + }, function(name, val){ + webshims.Grid.prototype[name] = function(){ + if(this.opts[val.action]){ + this.popover.navedInitFocus = { + sel: 'button[data-id="'+ this.activeButton.attr('data-id') +'"]:not(:disabled,.othermonth)', + alt: val.get + }; + this.popover.actionFn(this.opts[val.action]); + this.popover.navedInitFocus = false; + } + }; }); - } - - - if(Modernizr.track && !bugs.track){ - (function(){ + + $.each({ + up: {traverse: 'prevAll', get: 'last', action: 'prev', reverse: true}, + down: {traverse: 'nextAll', get: 'first', action: 'next'} + }, function(name, val){ + webshims.Grid.prototype[name] = function(){ + var cellIndex = this.activeButton.closest('td').prop('cellIndex'); + var sel = 'td:nth-child('+(cellIndex + 1)+') button:not(:disabled,.othermonth)'; + var button = this.activeButton.closest('tr')[val.traverse](); + + if(val.reverse){ + button = $(button.get().reverse()); + } + button = button.find(sel)[val.get](); + + if(!button[0]){ + if(this.opts[val.action]){ + this.popover.navedInitFocus = sel+':'+val.get; + this.popover.actionFn(this.opts[val.action]); + this.popover.navedInitFocus = false; + } + } else { + this.setFocus(button.eq(0)); + } + }; + }); + + $.each({ + prev: {traverse: 'prevAll',get: 'last', reverse: true}, + next: {traverse: 'nextAll', get: 'first'} + }, function(name, val){ + webshims.Grid.prototype[name] = function(){ + var sel = 'button:not(:disabled,.othermonth)'; + var button = this.activeButton.closest('td')[val.traverse]('td'); + if(val.reverse){ + button = $(button.get().reverse()); + } + button = button.find(sel)[val.get](); + if(!button[0]){ + button = this.activeButton.closest('tr')[val.traverse]('tr'); + if(val.reverse){ + button = $(button.get().reverse()); + } + button = button.find(sel)[val.get](); + } + + if(!button[0]){ + if(this.opts[name]){ + this.popover.navedInitFocus = val.get; + this.popover.actionFn(this.opts[name]); + this.popover.navedInitFocus = false; + } + } else { + this.setFocus(button.eq(0)); + } + }; + }); + + picker.getWeek = function(date){ + var onejan = new Date(date.getFullYear(),0,1); + return Math.ceil((((date - onejan) / 86400000) + onejan.getDay()+1)/7); + }; + picker.getYearList = function(value, data){ + var j, i, val, disabled, lis, prevDisabled, nextDisabled, classStr, classArray, start; - if(!bugs.track){ - bugs.track = typeof $('<track />')[0].readyState != 'number'; - } - if(!bugs.track){ - try { - new TextTrackCue(2, 3, ''); - } catch(e){ - bugs.track = true; - } + var size = data.options.size; + var max = data.options.max.split('-'); + var min = data.options.min.split('-'); + var currentValue = data.options.value.split('-'); + var xthCorrect = 0; + var enabled = 0; + var str = ''; + var rowNum = 0; + + if(data.options.useDecadeBase == 'max' && max[0]){ + xthCorrect = 11 - (max[0] % 12); + } else if(data.options.useDecadeBase == 'min' && min[0]){ + xthCorrect = 11 - (min[0] % 12); } - var trackOptions = webshims.cfg.track; - var trackListener = function(e){ - $(e.target).filter('track').each(changeApi); - }; - var changeApi = function(){ - if(bugs.track || (!trackOptions.override && $.prop(this, 'readyState') == 3)){ - trackOptions.override = true; - webshims.reTest('track'); - document.removeEventListener('error', trackListener, true); - if(this && $.nodeName(this, 'track')){ - webshims.error("track support was overwritten. Please check your vtt including your vtt mime-type"); + value = value[0] * 1; + start = value - ((value + xthCorrect) % (12 * size)); + + + + for(j = 0; j < size; j++){ + if(j){ + start += 12; + } else { + prevDisabled = picker.isInRange([start-1], max, min) ? {'data-action': 'setYearList','value': start-1} : false; + } + + str += '<div class="year-list picker-list ws-index-'+ j +'"><div class="ws-picker-header"><button disabled="disabled">'+ start +' – '+(start + 11)+'</button></div>'; + lis = []; + for(i = 0; i < 12; i++){ + val = start + i ; + classArray = []; + if( !picker.isInRange([val], max, min) ){ + disabled = ' disabled=""'; } else { - webshims.info("track support was overwritten. due to bad browser support"); + disabled = ''; + enabled++; } + + if(val == today[0]){ + classArray.push('this-value'); + } + + if(currentValue[0] == val){ + classArray.push('checked-value'); + } + + classStr = classArray.length ? ' class="'+ (classArray.join(' ')) +'"' : ''; + + if(i && !(i % 3)){ + rowNum++; + lis.push('</tr><tr class="ws-row-'+ rowNum +'">'); + } + lis.push('<td class="ws-item-'+ i +'" role="presentation"><button data-id="year-'+ i +'" type="button"'+ disabled + classStr +' data-action="setMonthList" value="'+val+'" tabindex="-1" role="gridcell">'+val+'</button></td>'); } + if(j == size - 1){ + nextDisabled = picker.isInRange([val+1], max, min) ? {'data-action': 'setYearList','value': val+1} : false; + } + str += '<div class="picker-grid"><table role="grid" aria-label="'+ start +' – '+(start + 11)+'"><tbody><tr class="ws-row-0">'+ (lis.join(''))+ '</tr></tbody></table></div></div>'; + } + + return { + enabled: enabled, + main: str, + next: nextDisabled, + prev: prevDisabled, + type: 'Grid' }; - var detectTrackError = function(){ - document.addEventListener('error', trackListener, true); - - if(bugs.track){ - changeApi(); + }; + + + picker.getMonthList = function(value, data){ + + var j, i, name, val, disabled, lis, fullyDisabled, prevDisabled, nextDisabled, classStr, classArray; + var o = data.options; + var size = o.size; + var max = o.max.split('-'); + var min = o.min.split('-'); + var currentValue = o.value.split('-'); + var enabled = 0; + var rowNum = 0; + var str = ''; + + value = value[0] - Math.floor((size - 1) / 2); + for(j = 0; j < size; j++){ + if(j){ + value++; } else { - $('track').each(changeApi); + prevDisabled = picker.isInRange([value-1], max, min) ? {'data-action': 'setMonthList','value': value-1} : false; } - }; - if(!trackOptions.override){ - if(webshims.isReady('track')){ - detectTrackError(); + if(j == size - 1){ + nextDisabled = picker.isInRange([value+1], max, min) ? {'data-action': 'setMonthList','value': value+1} : false; + } + lis = []; + + if( !picker.isInRange([value, '01'], max, min) && !picker.isInRange([value, '12'], max, min)){ + disabled = ' disabled=""'; + fullyDisabled = true; } else { - $(detectTrackError); + fullyDisabled = false; + disabled = ''; } - } - })(); - - } + + if(o.minView >= 1){ + disabled = ' disabled=""'; + } + + str += '<div class="month-list picker-list ws-index-'+ j +'"><div class="ws-picker-header">'; + + str += o.selectNav ? + '<select data-action="setMonthList" class="year-select">'+ picker.createYearSelect(value, max, min).join('') +'</select>' : + '<button data-action="setYearList"'+disabled+' value="'+ value +'" tabindex="-1">'+ value +'</button>'; + str += '</div>'; + + for(i = 0; i < 12; i++){ + val = curCfg.date.monthkeys[i+1]; + name = (curCfg.date[o.monthNames] || curCfg.date.monthNames)[i]; + classArray = []; + if(fullyDisabled || !picker.isInRange([value, val], max, min) ){ + disabled = ' disabled=""'; + } else { + disabled = ''; + enabled++; + } + + if(value == today[0] && today[1] == val){ + classArray.push('this-value'); + } + + if(currentValue[0] == value && currentValue[1] == val){ + classArray.push('checked-value'); + } + + classStr = (classArray.length) ? ' class="'+ (classArray.join(' ')) +'"' : ''; + if(i && !(i % 3)){ + rowNum++; + lis.push('</tr><tr class="ws-row-'+ rowNum +'">'); + } -webshims.register('mediaelement-core', function($, webshims, window, document, undefined){ - hasSwf = swfobject.hasFlashPlayerVersion('9.0.115'); - $('html').addClass(hasSwf ? 'swf' : 'no-swf'); - var mediaelement = webshims.mediaelement; - mediaelement.parseRtmp = function(data){ - var src = data.src.split('://'); - var paths = src[1].split('/'); - var i, len, found; - data.server = src[0]+'://'+paths[0]+'/'; - data.streamId = []; - for(i = 1, len = paths.length; i < len; i++){ - if(!found && paths[i].indexOf(':') !== -1){ - paths[i] = paths[i].split(':')[1]; - found = true; + lis.push('<td class="ws-item-'+ i +'" role="presentation"><button data-id="month-'+ i +'" type="button"'+ disabled + classStr +' data-action="'+ (data.type == 'month' ? 'changeInput' : 'setDayList' ) +'" value="'+value+'-'+val+'" tabindex="-1" role="gridcell" aria-label="'+ curCfg.date.monthNames[i] +'">'+name+'</button></td>'); + + } + + str += '<div class="picker-grid"><table role="grid" aria-label="'+value+'"><tbody><tr class="ws-row-0">'+ (lis.join(''))+ '</tr></tbody></table></div></div>'; } - if(!found){ - data.server += paths[i]+'/'; - } else { - data.streamId.push(paths[i]); - } - } - if(!data.streamId.length){ - webshims.error('Could not parse rtmp url'); - } - data.streamId = data.streamId.join('/'); - }; - var getSrcObj = function(elem, nodeName){ - elem = $(elem); - var src = {src: elem.attr('src') || '', elem: elem, srcProp: elem.prop('src')}; - var tmp; + + return { + enabled: enabled, + main: str, + prev: prevDisabled, + next: nextDisabled, + type: 'Grid' + }; + }; - if(!src.src){return src;} - tmp = elem.attr('data-server'); - if(tmp != null){ - src.server = tmp; - } - - tmp = elem.attr('type'); - if(tmp){ - src.type = tmp; - src.container = $.trim(tmp.split(';')[0]); - } else { - if(!nodeName){ - nodeName = elem[0].nodeName.toLowerCase(); - if(nodeName == 'source'){ - nodeName = (elem.closest('video, audio')[0] || {nodeName: 'video'}).nodeName.toLowerCase(); + picker.getDayList = function(value, data){ + + var j, i, k, day, nDay, name, val, disabled, lis, prevDisabled, nextDisabled, addTr, week, rowNum; + + var lastMotnh, curMonth, otherMonth, dateArray, monthName, fullMonthName, buttonStr, date2, classArray; + var o = data.options; + var size = o.size; + var max = o.max.split('-'); + var min = o.min.split('-'); + var currentValue = o.value.split('-'); + var monthNames = curCfg.date[o.monthNamesHead] || curCfg.date[o.monthNames] || curCfg.date.monthNames; + var enabled = 0; + var str = []; + var date = new Date(value[0], value[1] - 1, 1); + + date.setMonth(date.getMonth() - Math.floor((size - 1) / 2)); + + for(j = 0; j < size; j++){ + date.setDate(1); + lastMotnh = date.getMonth(); + rowNum = 0; + if(!j){ + date2 = new Date(date.getTime()); + date2.setDate(-1); + dateArray = getDateArray(date2); + prevDisabled = picker.isInRange(dateArray, max, min) ? {'data-action': 'setDayList','value': dateArray[0]+'-'+dateArray[1]} : false; } - } - if(src.server){ - src.type = nodeName+'/rtmp'; - src.container = nodeName+'/rtmp'; - } else { - tmp = mediaelement.getTypeForSrc( src.src, nodeName, src ); + dateArray = getDateArray(date); - if(tmp){ - src.type = tmp; - src.container = tmp; + str.push('<div class="day-list picker-list ws-index-'+ j +'"><div class="ws-picker-header">'); + if( o.selectNav ){ + monthName = ['<select data-action="setDayList" class="month-select" tabindex="0">'+ picker.createMonthSelect(dateArray, max, min, monthNames).join('') +'</select>', '<select data-action="setDayList" class="year-select" tabindex="0">'+ picker.createYearSelect(dateArray[0], max, min, '-'+dateArray[1]).join('') +'</select>']; + if(curCfg.date.showMonthAfterYear){ + monthName.reverse(); + } + str.push( monthName.join(' ') ); + } + + fullMonthName = [curCfg.date.monthNames[(dateArray[1] * 1) - 1], dateArray[0]]; + monthName = [monthNames[(dateArray[1] * 1) - 1], dateArray[0]]; + if(curCfg.date.showMonthAfterYear){ + monthName.reverse(); + fullMonthName.reverse(); } + + if(!data.options.selectNav) { + str.push( + '<button data-action="setMonthList"'+ (o.minView >= 2 ? ' disabled="" ' : '') +' value="'+ dateArray.date +'" tabindex="-1">'+ monthName.join(' ') +'</button>' + ); + } + + + str.push('</div><div class="picker-grid"><table role="grid" aria-label="'+ fullMonthName.join(' ') +'"><thead><tr>'); + + if(data.options.showWeek){ + str.push('<th class="week-header">'+ curCfg.date.weekHeader +'</th>'); + } + for(k = curCfg.date.firstDay; k < curCfg.date.dayNamesShort.length; k++){ + str.push('<th class="day-'+ k +'"><abbr title="'+ curCfg.date.dayNames[k] +'">'+ curCfg.date.dayNamesShort[k] +'</abbr></th>'); + } + k = curCfg.date.firstDay; + while(k--){ + str.push('<th class="day-'+ k +'"><abbr title="'+ curCfg.date.dayNames[k] +'">'+ curCfg.date.dayNamesShort[k] +'</abbr></th>'); + } + str.push('</tr></thead><tbody><tr class="ws-row-0">'); + + if(data.options.showWeek) { + week = picker.getWeek(date); + str.push('<td class="week-cell">'+ week +'</td>'); + } + + for (i = 0; i < 99; i++) { + addTr = (i && !(i % 7)); + curMonth = date.getMonth(); + otherMonth = lastMotnh != curMonth; + day = date.getDay(); + classArray = []; + + if(addTr && otherMonth ){ + str.push('</tr>'); + break; + } + if(addTr){ + rowNum++; + str.push('</tr><tr class="ws-row-'+ rowNum +'">'); + if(data.options.showWeek) { + week++; + str.push('<td class="week-cell">'+ week +'</td>'); + } + } + + if(!i){ + + if(day != curCfg.date.firstDay){ + nDay = day - curCfg.date.firstDay; + if(nDay < 0){ + nDay += 7; + } + date.setDate(date.getDate() - nDay); + day = date.getDay(); + curMonth = date.getMonth(); + otherMonth = lastMotnh != curMonth; + } + } + + dateArray = getDateArray(date); + buttonStr = '<td role="presentation" class="day-'+ day +'"><button data-id="day-'+ date.getDate() +'" role="gridcell" data-action="changeInput" value="'+ (dateArray.join('-')) +'"'; + + if(otherMonth){ + classArray.push('othermonth'); + } else { + classArray.push('day-'+date.getDate()); + } + + if(dateArray[0] == today[0] && today[1] == dateArray[1] && today[2] == dateArray[2]){ + classArray.push('this-value'); + } + + if(currentValue[0] == dateArray[0] && dateArray[1] == currentValue[1] && dateArray[2] == currentValue[2]){ + classArray.push('checked-value'); + } + + if(classArray.length){ + buttonStr += ' class="'+ classArray.join(' ') +'"'; + } + + if(!picker.isInRange(dateArray, max, min) || (data.options.disableDays && $.inArray(day, data.options.disableDays) != -1)){ + buttonStr += ' disabled=""'; + } + + str.push(buttonStr+' tabindex="-1">'+ date.getDate() +'</button></td>'); + + date.setDate(date.getDate() + 1); + } + str.push('</tbody></table></div></div>'); + if(j == size - 1){ + dateArray = getDateArray(date); + dateArray[2] = 1; + nextDisabled = picker.isInRange(dateArray, max, min) ? {'data-action': 'setDayList','value': dateArray.date} : false; + } } - } - tmp = elem.attr('media'); - if(tmp){ - src.media = tmp; - } - if(src.type == 'audio/rtmp' || src.type == 'video/rtmp'){ - if(src.server){ - src.streamId = src.src; - } else { - mediaelement.parseRtmp(src); - } - } - return src; - }; - - - - var hasYt = !hasSwf && ('postMessage' in window) && hasNative; - - var loadTrackUi = function(){ - if(loadTrackUi.loaded){return;} - loadTrackUi.loaded = true; - $(function(){ - webshims.loader.loadList(['track-ui']); - }); - }; - var loadYt = (function(){ - var loaded; - return function(){ - if(loaded || !hasYt){return;} - loaded = true; - webshims.loader.loadScript("https://www.youtube.com/player_api"); - $(function(){ - webshims.polyfill("mediaelement-yt"); - }); + + + return { + enabled: 9, + main: str.join(''), + prev: prevDisabled, + next: nextDisabled, + type: 'Grid' + }; }; - })(); - var loadThird = function(){ - if(hasSwf){ - loadSwf(); - } else { - loadYt(); - } - }; - - webshims.addPolyfill('mediaelement-yt', { - test: !hasYt, - d: ['dom-support'] - }); - - mediaelement.mimeTypes = { - audio: { - //ogm shouldn´t be used! - 'audio/ogg': ['ogg','oga', 'ogm'], - 'audio/ogg;codecs="opus"': 'opus', - 'audio/mpeg': ['mp2','mp3','mpga','mpega'], - 'audio/mp4': ['mp4','mpg4', 'm4r', 'm4a', 'm4p', 'm4b', 'aac'], - 'audio/wav': ['wav'], - 'audio/3gpp': ['3gp','3gpp'], - 'audio/webm': ['webm'], - 'audio/fla': ['flv', 'f4a', 'fla'], - 'application/x-mpegURL': ['m3u8', 'm3u'] - }, - video: { - //ogm shouldn´t be used! - 'video/ogg': ['ogg','ogv', 'ogm'], - 'video/mpeg': ['mpg','mpeg','mpe'], - 'video/mp4': ['mp4','mpg4', 'm4v'], - 'video/quicktime': ['mov','qt'], - 'video/x-msvideo': ['avi'], - 'video/x-ms-asf': ['asf', 'asx'], - 'video/flv': ['flv', 'f4v'], - 'video/3gpp': ['3gp','3gpp'], - 'video/webm': ['webm'], - 'application/x-mpegURL': ['m3u8', 'm3u'], - 'video/MP2T': ['ts'] + + picker.isInRange = function(values, max, min){ + var i; + var ret = true; + for(i = 0; i < values.length; i++){ + + if(min[i] && min[i] > values[i]){ + ret = false; + break; + } else if( !(min[i] && min[i] == values[i]) ){ + break; + } } - } - ; - - mediaelement.mimeTypes.source = $.extend({}, mediaelement.mimeTypes.audio, mediaelement.mimeTypes.video); - - mediaelement.getTypeForSrc = function(src, nodeName, data){ - if(src.indexOf('youtube.com/watch?') != -1 || src.indexOf('youtube.com/v/') != -1){ - return 'video/youtube'; - } - if(src.indexOf('rtmp') === 0){ - return nodeName+'/rtmp'; - } - src = src.split('?')[0].split('.'); - src = src[src.length - 1]; - var mt; + if(ret){ + for(i = 0; i < values.length; i++){ + + if((max[i] && max[i] < values[i])){ + ret = false; + break; + } else if( !(max[i] && max[i] == values[i]) ){ + break; + } + } + } + return ret; + }; - $.each(mediaelement.mimeTypes[nodeName], function(mimeType, exts){ - if(exts.indexOf(src) !== -1){ - mt = mimeType; - return false; + picker.createMonthSelect = function(value, max, min, monthNames){ + if(!monthNames){ + monthNames = curCfg.date.monthNames; } - }); - return mt; - }; - - - mediaelement.srces = function(mediaElem, srces){ - mediaElem = $(mediaElem); - if(!srces){ - srces = []; - var nodeName = mediaElem[0].nodeName.toLowerCase(); - var src = getSrcObj(mediaElem, nodeName); - if(!src.src){ - - $('source', mediaElem).each(function(){ - src = getSrcObj(this, nodeName); - if(src.src){srces.push(src);} - }); - } else { - srces.push(src); + var selected; + var i = 0; + var options = []; + var tempVal = value[1]-1; + for(; i < monthNames.length; i++){ + selected = tempVal == i ? ' selected=""' : ''; + if(selected || picker.isInRange([value[0], i+1], max, min)){ + options.push('<option value="'+ value[0]+'-'+addZero(i+1) + '"'+selected+'>'+ monthNames[i] +'</option>'); + } } - return srces; - } else { - mediaElem.removeAttr('src').removeAttr('type').find('source').remove(); - if(!$.isArray(srces)){ - srces = [srces]; + return options; + }; + + picker.createYearSelect = function(value, max, min, valueAdd){ + + var temp; + var goUp = true; + var goDown = true; + var options = ['<option selected="">'+ value + '</option>']; + var i = 0; + if(!valueAdd){ + valueAdd = ''; } - srces.forEach(function(src){ - var source = document.createElement('source'); - if(typeof src == 'string'){ - src = {src: src}; - } - source.setAttribute('src', src.src); - if(src.type){ - source.setAttribute('type', src.type); + while(i < 8 && (goUp || goDown)){ + i++; + temp = value-i; + if(goUp && picker.isInRange([temp], max, min)){ + options.unshift('<option value="'+ (temp+valueAdd) +'">'+ temp +'</option>'); + } else { + goUp = false; } - if(src.media){ - source.setAttribute('media', src.media); + temp = value + i; + if(goDown && picker.isInRange([temp], max, min)){ + options.push('<option value="'+ (temp+valueAdd) +'">'+ temp +'</option>'); + } else { + goDown = false; } - mediaElem.append(source); + } + return options; + }; + + var actions = { + changeInput: function(val, popover, data){ + popover.stopOpen = true; + data.element.getShadowFocusElement().focus(); + setTimeout(function(){ + popover.stopOpen = false; + }, 9); + popover.hide(); + data.setChange(val); + } + }; + + (function(){ + var retNames = function(name){ + return 'get'+name+'List'; + }; + var retSetNames = function(name){ + return 'set'+name+'List'; + }; + var stops = { + date: 'Day', + week: 'Day', + month: 'Month' + }; + + $.each({'setYearList' : ['Year', 'Month', 'Day'], 'setMonthList': ['Month', 'Day'], 'setDayList': ['Day']}, function(setName, names){ + var getNames = names.map(retNames); + var setNames = names.map(retSetNames); + actions[setName] = function(val, popover, data, startAt){ + val = ''+val; + var o = data.options; + var values = val.split('-'); + if(!startAt){ + startAt = 0; + } + $.each(getNames, function(i, item){ + if(i >= startAt){ + var content = picker[item](values, data); + + if( values.length < 2 || content.enabled > 1 || stops[data.type] === names[i]){ + popover.element + .attr({'data-currentview': setNames[i]}) + .addClass('ws-size-'+o.size) + .data('pickercontent', { + data: data, + content: content, + values: values + }) + ; + popover.bodyElement.html(content.main); + if(content.prev){ + popover.prevElement + .attr(content.prev) + .prop({disabled: false}) + ; + } else { + popover.prevElement + .removeAttr('data-action') + .prop({disabled: true}) + ; + } + if(content.next){ + popover.nextElement + .attr(content.next) + .prop({disabled: false}) + ; + } else { + popover.nextElement + .removeAttr('data-action') + .prop({disabled: true}) + ; + } + if(webshims[content.type]){ + new webshims[content.type](popover.bodyElement.children(), popover, content); + } + popover.element.trigger('pickerchange'); + return false; + } + } + }); + }; }); + })(); + + picker.commonInit = function(data, popover){ + var actionfn = function(e){ + if(!$(this).is('.othermonth') || $(this).css('cursor') == 'pointer'){ + popover.actionFn({ + 'data-action': $.attr(this, 'data-action'), + value: $(this).val() || $.attr(this, 'value') + }); + } + return false; + }; + var id = new Date().getTime(); + var generateList = function(o, max, min){ + var options = []; + var label = ''; + var labelId = ''; + o.options = data.getOptions() || {}; + $('div.ws-options', popover.contentElement).remove(); + $.each(o.options[0], function(val, label){ + var disabled = picker.isInRange(val.split('-'), o.maxS, o.minS) ? + '' : + ' disabled="" ' + ; + options.push('<li role="presentation"><button value="'+ val +'" '+disabled+' data-action="changeInput" tabindex="-1" role="option">'+ (label || data.formatValue(val, false)) +'</button></li>'); + }); + if(options.length){ + id++; + if(o.options[1]){ + labelId = 'datalist-'+id; + label = '<h5 id="'+labelId+'">'+ o.options[1] +'</h5>'; + labelId = ' aria-labelledbyid="'+ labelId +'" '; + } + new webshims.ListBox($('<div class="ws-options">'+label+'<ul role="listbox" '+ labelId +'>'+ options.join('') +'</div>').insertAfter(popover.bodyElement)[0], popover, {noFocus: true}); + } + }; + var updateContent = function(){ + if(popover.isDirty){ + var o = data.options; + o.maxS = o.max.split('-'); + o.minS = o.min.split('-'); + + $('button', popover.buttonRow).each(function(){ + var text; + if($(this).is('.ws-empty')){ + text = curCfg.date.clear; + if(!text){ + text = formcfg[''].date.clear || 'clear'; + webshims.warn("could not get clear text from form cfg"); + } + } else if($(this).is('.ws-current')){ + text = (curCfg[data.type] || {}).currentText; + if(!text){ + text = (formcfg[''][[data.type]] || {}).currentText || 'current'; + webshims.warn("could not get currentText from form cfg"); + } + $.prop(this, 'disabled', !picker.isInRange(today[data.type].split('-'), o.maxS, o.minS)); + } + if(text){ + $(this).text(text).attr({'aria-label': text}); + if(webshims.assumeARIA){ + $.attr(this, 'aria-label', text); + } + } + + }); + popover.nextElement.attr({'aria-label': curCfg.date.nextText}); + $('> span', popover.nextElement).html(curCfg.date.nextText); + popover.prevElement.attr({'aria-label': curCfg.date.prevText}); + $('> span', popover.prevElement).html(curCfg.date.prevText); + + generateList(o, o.maxS, o.minS); + + } + $('button.ws-empty', popover.buttonRow).prop('disabled', $.prop(data.orig, 'required')); + popover.isDirty = false; + }; - } - }; - - - $.fn.loadMediaSrc = function(srces, poster){ - return this.each(function(){ - if(poster !== undefined){ - $(this).removeAttr('poster'); - if(poster){ - $.attr(this, 'poster', poster); + popover.actionFn = function(obj){ + if(actions[obj['data-action']]){ + actions[obj['data-action']](obj.value, popover, data, 0); + } else { + webshims.warn('no action for '+ obj['data-action']); } - } - mediaelement.srces(this, srces); - $(this).mediaLoad(); - }); - }; - - mediaelement.swfMimeTypes = ['video/3gpp', 'video/x-msvideo', 'video/quicktime', 'video/x-m4v', 'video/mp4', 'video/m4p', 'video/x-flv', 'video/flv', 'audio/mpeg', 'audio/aac', 'audio/mp4', 'audio/x-m4a', 'audio/m4a', 'audio/mp3', 'audio/x-fla', 'audio/fla', 'youtube/flv', 'jwplayer/jwplayer', 'video/youtube', 'video/rtmp', 'audio/rtmp']; - - mediaelement.canThirdPlaySrces = function(mediaElem, srces){ - var ret = ''; - if(hasSwf || hasYt){ - mediaElem = $(mediaElem); - srces = srces || mediaelement.srces(mediaElem); - $.each(srces, function(i, src){ - if(src.container && src.src && ((hasSwf && mediaelement.swfMimeTypes.indexOf(src.container) != -1) || (hasYt && src.container == 'video/youtube'))){ - ret = src; - return false; + }; + + popover.contentElement.html('<button class="ws-prev" tabindex="0"><span></span></button> <button class="ws-next" tabindex="0"><span></span></button><div class="ws-picker-body"></div><div class="ws-button-row"><button type="button" class="ws-current" data-action="changeInput" value="'+today[data.type]+'" tabindex="0"></button> <button type="button" data-action="changeInput" value="" class="ws-empty" tabindex="0"></button></div>'); + popover.nextElement = $('button.ws-next', popover.contentElement); + popover.prevElement = $('button.ws-prev', popover.contentElement); + popover.bodyElement = $('div.ws-picker-body', popover.contentElement); + popover.buttonRow = $('div.ws-button-row', popover.contentElement); + + popover.isDirty = true; + + popover.contentElement + .on('click', 'button[data-action]', actionfn) + .on('change', 'select[data-action]', actionfn) + ; + + popover.contentElement.on({ + keydown: function(e){ + if(e.keyCode == 9){ + var tabbable = $('[tabindex="0"]:not(:disabled)', this).filter(':visible'); + var index = tabbable.index(e.target); + if(e.shiftKey && index <= 0){ + tabbable.last().focus(); + return false; + } + if(!e.shiftKey && index >= tabbable.length - 1){ + tabbable.first().focus(); + return false; + } + } else if(e.keyCode == 27){ + data.element.getShadowFocusElement().focus(); + popover.hide(); + return false; + } } }); - } - - return ret; - }; - - var nativeCanPlayType = {}; - mediaelement.canNativePlaySrces = function(mediaElem, srces){ - var ret = ''; - if(hasNative){ - mediaElem = $(mediaElem); - var nodeName = (mediaElem[0].nodeName || '').toLowerCase(); - if(!nativeCanPlayType[nodeName]){return ret;} - srces = srces || mediaelement.srces(mediaElem); + $(data.options.orig).on('input', function(){ + var currentView; + if(data.options.updateOnInput && popover.isVisible && data.options.value && (currentView = popover.element.attr('data-currentview'))){ + actions[currentView]( data.options.value , popover, data, 0); + } + }); - $.each(srces, function(i, src){ - if(src.type && nativeCanPlayType[nodeName].prop._supvalue.call(mediaElem[0], src.type) ){ - ret = src; - return false; + data._propertyChange = (function(){ + var timer; + var update = function(){ + if(popover.isVisible){ + updateContent(); + } + }; + return function(prop){ + if(prop == 'value'){return;} + popover.isDirty = true; + if(popover.isVisible){ + clearTimeout(timer); + timer = setTimeout(update, 9); + } + }; + })(); + + popover.activeElement = $([]); + + popover.activateElement = function(element){ + element = $(element); + if(element[0] != popover.activeElement[0]){ + popover.activeElement.removeClass('ws-focus'); + element.addClass('ws-focus'); } + popover.activeElement = element; + }; + popover.element.on({ + wspopoverbeforeshow: function(){ + data.element.triggerHandler('wsupdatevalue'); + updateContent(); + } }); - } - return ret; - }; - - mediaelement.setError = function(elem, message){ - if(!message){ - message = "can't play sources"; - } + + $(document).onTrigger('wslocalechange', data._propertyChange); + }; - $(elem).pause().data('mediaerror', message); - webshims.warn('mediaelementError: '+ message); - setTimeout(function(){ - if($(elem).data('mediaerror')){ - $(elem).trigger('mediaerror'); + picker._common = function(data){ + var popover = webshims.objectCreate(webshims.wsPopover, {}, {prepareFor: data.element}); + var opener = $('<button type="button" class="ws-popover-opener"><span /></button>').appendTo(data.buttonWrapper); + var options = data.options; + var init = false; + + var show = function(){ + if(!options.disabled && !options.readonly && !popover.isVisible){ + if(!init){ + picker.commonInit(data, popover); + } + + if(!init || data.options.restartView) { + actions.setYearList( options.defValue || options.value, popover, data, data.options.startView); + } else { + actions[popover.element.attr('data-currentview') || 'setYearList']( options.defValue || options.value, popover, data, 0); + } + + init = true; + popover.show(data.element); + } + }; + + options.containerElements.push(popover.element[0]); + + if(!options.startView){ + options.startView = 0; } - }, 1); - }; - - var handleThird = (function(){ - var requested; - return function( mediaElem, ret, data ){ - if(!requested){ - loadTrackUi(); + if(!options.minView){ + options.minView = 0; } - webshims.ready(hasSwf ? swfType : 'mediaelement-yt', function(){ - if(mediaelement.createSWF){ - mediaelement.createSWF( mediaElem, ret, data ); - } else if(!requested) { - requested = true; - loadThird(); - //readd to ready - handleThird( mediaElem, ret, data ); - } - }); - if(!requested && hasYt && !mediaelement.createSWF){ - loadYt(); + if(options.startView < options.minView){ + options.minView = options.startView; + webshims.warn("wrong config for minView/startView."); } - }; - })(); - - var stepSources = function(elem, data, useSwf, _srces, _noLoop){ - var ret; - if(useSwf || (useSwf !== false && data && data.isActive == 'third')){ - ret = mediaelement.canThirdPlaySrces(elem, _srces); - if(!ret){ - if(_noLoop){ - mediaelement.setError(elem, false); - } else { - stepSources(elem, data, false, _srces, true); - } - } else { - handleThird(elem, ret, data); + if(!options.size){ + options.size = 1; } - } else { - ret = mediaelement.canNativePlaySrces(elem, _srces); - if(!ret){ - if(_noLoop){ - mediaelement.setError(elem, false); - if(data && data.isActive == 'third') { - mediaelement.setActive(elem, 'html5', data); + + popover.element + .addClass(data.type+'-popover input-picker') + .attr({role: 'application'}) + .on({ + wspopoverhide: function(){ + popover.openedByFocus = false; + }, + focusin: function(e){ + if(popover.activateElement){ + popover.openedByFocus = false; + popover.activateElement(e.target); + } + }, + focusout: function(){ + if(popover.activeElement){ + popover.activeElement.removeClass('ws-focus'); + } } - } else { - stepSources(elem, data, true, _srces, true); - } - } else if(data && data.isActive == 'third') { - mediaelement.setActive(elem, 'html5', data); - } - } - }; - var stopParent = /^(?:embed|object|datalist)$/i; - var selectSource = function(elem, data){ - var baseData = webshims.data(elem, 'mediaelementBase') || webshims.data(elem, 'mediaelementBase', {}); - var _srces = mediaelement.srces(elem); - var parent = elem.parentNode; + }) + ; + + labelWidth(popover.element.children('div.ws-po-outerbox').attr({role: 'group'}), options.labels, true); + labelWidth(opener, options.labels, true); + + opener + .attr({ + 'tabindex': options.labels.length ? 0 : '-1' + }) + .on({ + mousedown: function(){ + stopPropagation.apply(this, arguments); + popover.preventBlur(); + }, + click: function(){ + if(popover.isVisible && popover.activeElement){ + popover.openedByFocus = false; + popover.activeElement.focus(); + } + show(); + }, + focus: function(){ + popover.preventBlur(); + } + }) + ; + + (function(){ + var mouseFocus = false; + var resetMouseFocus = function(){ + mouseFocus = false; + }; + data.inputElements.on({ + focus: function(){ + if(!popover.stopOpen && (data.options.openOnFocus || (mouseFocus && options.openOnMouseFocus))){ + popover.openedByFocus = !options.noInput; + show(); + } else { + popover.preventBlur(); + } + }, + mousedown: function(){ + mouseFocus = true; + setTimeout(resetMouseFocus, 9); + if(data.element.is(':focus')){ + popover.openedByFocus = !options.noInput; + show(); + } + popover.preventBlur(); + } + }); + })(); + data.popover = popover; + }; - clearTimeout(baseData.loadTimer); - $.data(elem, 'mediaerror', false); + picker.month = picker._common; + picker.date = picker.month; - if(!_srces.length || !parent || parent.nodeType != 1 || stopParent.test(parent.nodeName || '')){return;} - data = data || webshims.data(elem, 'mediaelement'); - stepSources(elem, data, options.preferFlash || undefined, _srces); - }; - mediaelement.selectSource = selectSource; + webshims.picker = picker; + })(); - $(document).on('ended', function(e){ - var data = webshims.data(e.target, 'mediaelement'); - if( supportsLoop && (!data || data.isActive == 'html5') && !$.prop(e.target, 'loop')){return;} - setTimeout(function(){ - if( $.prop(e.target, 'paused') || !$.prop(e.target, 'loop') ){return;} - $(e.target).prop('currentTime', 0).play(); - }, 1); + (function(){ - }); - if(!supportsLoop){ - webshims.defineNodeNamesBooleanProperty(['audio', 'video'], 'loop'); - } - - ['audio', 'video'].forEach(function(nodeName){ - var supLoad = webshims.defineNodeNameProperty(nodeName, 'load', { - prop: { - value: function(){ - var data = webshims.data(this, 'mediaelement'); - selectSource(this, data); - if(hasNative && (!data || data.isActive == 'html5') && supLoad.prop._supvalue){ - supLoad.prop._supvalue.apply(this, arguments); + var stopCircular, isCheckValidity; + + var modernizrInputTypes = Modernizr.inputtypes; + var inputTypes = { + + }; + var copyProps = [ + 'disabled', + 'readonly', + 'value', + 'min', + 'max', + 'step', + 'title', + 'placeholder' + ]; + + // + var copyAttrs = ['data-placeholder', 'tabindex']; + + $.each(copyProps.concat(copyAttrs), function(i, name){ + var fnName = name.replace(/^data\-/, ''); + webshims.onNodeNamesPropertyModify('input', name, function(val){ + if(!stopCircular){ + var shadowData = webshims.data(this, 'shadowData'); + if(shadowData && shadowData.data && shadowData.nativeElement === this && shadowData.data[fnName]){ + shadowData.data[fnName](val); } } - } + }); }); - nativeCanPlayType[nodeName] = webshims.defineNodeNameProperty(nodeName, 'canPlayType', { - prop: { - value: function(type){ - var ret = ''; - if(hasNative && nativeCanPlayType[nodeName].prop._supvalue){ - ret = nativeCanPlayType[nodeName].prop._supvalue.call(this, type); - if(ret == 'no'){ - ret = ''; + + if(options.replaceUI && 'valueAsNumber' in document.createElement('input')){ + var reflectFn = function(val){ + if(webshims.data(this, 'hasShadow')){ + $.prop(this, 'value', $.prop(this, 'value')); + } + }; + + webshims.onNodeNamesPropertyModify('input', 'valueAsNumber', reflectFn); + webshims.onNodeNamesPropertyModify('input', 'valueAsDate', reflectFn); + } + + var extendType = (function(){ + return function(name, data){ + inputTypes[name] = data; + data.attrs = $.merge([], copyAttrs, data.attrs); + data.props = $.merge([], copyProps, data.props); + }; + })(); + + var isVisible = function(){ + return $.css(this, 'display') != 'none'; + }; + var sizeInput = function(data){ + var init; + var updateStyles = function(){ + $.style( data.orig, 'display', '' ); + var hasButtons, marginR, marginL; + var correctWidth = 0.6; + if(!init || data.orig.offsetWidth){ + hasButtons = data.buttonWrapper && data.buttonWrapper.filter(isVisible).length; + marginR = $.css( data.orig, 'marginRight'); + data.element.css({ + marginLeft: $.css( data.orig, 'marginLeft'), + marginRight: hasButtons ? 0 : marginR + }); + + if(hasButtons){ + marginL = (parseInt(data.buttonWrapper.css('marginLeft'), 10) || 0); + data.element.css({paddingRight: ''}); + + if(marginL < 0){ + marginR = (parseInt(marginR, 10) || 0) + ((data.buttonWrapper.outerWidth() + marginL) * -1); + data.buttonWrapper.css('marginRight', marginR); + data.element + .css({paddingRight: ''}) + .css({ + paddingRight: (parseInt( data.element.css('paddingRight'), 10) || 0) + data.buttonWrapper.outerWidth() + }) + ; + } else { + data.buttonWrapper.css('marginRight', marginR); + correctWidth = data.buttonWrapper.outerWidth(true) + 0.6; } } - if(!ret && hasSwf){ - type = $.trim((type || '').split(';')[0]); - if(mediaelement.swfMimeTypes.indexOf(type) != -1){ - ret = 'maybe'; + + data.element.outerWidth( $(data.orig).outerWidth() - correctWidth ); + } + init = true; + $.style( data.orig, 'display', 'none' ); + }; + $(document).onTrigger('updateshadowdom', updateStyles); + }; + + + var implementType = function(){ + var type = $.prop(this, 'type'); + + var i, opts, data, optsName, labels; + if(inputTypes[type] && webshims.implement(this, 'inputwidgets')){ + data = {}; + optsName = type; + + //todo: do we need deep extend? + + labels = $(this).jProp('labels'); + + opts = $.extend({}, options.widgets, options[type], $($.prop(this, 'form')).data(type) || {}, $(this).data(type) || {}, { + orig: this, + type: type, + labels: labels, + options: {}, + input: function(val){ + opts._change(val, 'input'); + }, + change: function(val){ + opts._change(val, 'change'); + }, + _change: function(val, trigger){ + stopCircular = true; + $.prop(opts.orig, 'value', val); + stopCircular = false; + if(trigger){ + $(opts.orig).trigger(trigger); } + }, + containerElements: [] + }); + + + for(i = 0; i < copyProps.length; i++){ + opts[copyProps[i]] = $.prop(this, copyProps[i]); + } + + for(i = 0; i < copyAttrs.length; i++){ + optsName = copyAttrs[i].replace(/^data\-/, ''); + if(optsName == 'placeholder' || !opts[optsName]){ + opts[optsName] = $.attr(this, copyAttrs[i]) || opts[optsName]; } - return ret; } + + data.shim = inputTypes[type]._create(opts); + + webshims.addShadowDom(this, data.shim.element, { + data: data.shim || {} + }); + + data.shim.options.containerElements.push(data.shim.element[0]); + + labelWidth($(this).getShadowFocusElement(), labels); + $.attr(this, 'required', $.attr(this, 'required')); + $(this).on('change', function(e){ + if(!stopCircular){ + data.shim.value($.prop(this, 'value')); + } + }); + + (function(){ + var has = { + focusin: true, + focus: true + }; + var timer; + var hasFocusTriggered = false; + var hasFocus = false; + + $(data.shim.options.containerElements) + .on({ + 'focusin focus focusout blur': function(e){ + e.stopImmediatePropagation(); + hasFocus = has[e.type]; + clearTimeout(timer); + timer = setTimeout(function(){ + if(hasFocus != hasFocusTriggered){ + hasFocusTriggered = hasFocus; + $(opts.orig).triggerHandler(hasFocus ? 'focus' : 'blur'); + $(opts.orig).trigger(hasFocus ? 'focusin' : 'focusout'); + } + hasFocusTriggered = hasFocus; + }, 0); + } + }) + ; + })(); + + + data.shim.element.on('change input', stopPropagation); + + if(Modernizr.formvalidation){ + $(opts.orig).on('firstinvalid', function(e){ + if(!webshims.fromSubmit && isCheckValidity){return;} + $(opts.orig).off('invalid.replacedwidgetbubble').on('invalid.replacedwidgetbubble', function(evt){ + if(!e.isInvalidUIPrevented() && !evt.isDefaultPrevented()){ + webshims.validityAlert.showFor( e.target ); + e.preventDefault(); + evt.preventDefault(); + } + $(opts.orig).off('invalid.replacedwidgetbubble'); + }); + }); + } + + + if(data.shim.buttonWrapper && data.shim.buttonWrapper.filter(isVisible).length){ + data.shim.element.addClass('has-input-buttons'); + } + + if(opts.calculateWidth){ + sizeInput(data.shim); + } + $(this).css({display: 'none'}); } - }); - }); - webshims.onNodeNamesPropertyModify(['audio', 'video'], ['src', 'poster'], { - set: function(){ - var elem = this; - var baseData = webshims.data(elem, 'mediaelementBase') || webshims.data(elem, 'mediaelementBase', {}); - clearTimeout(baseData.loadTimer); - baseData.loadTimer = setTimeout(function(){ - selectSource(elem); - elem = null; - }, 9); + }; + + if(!modernizrInputTypes.range || options.replaceUI){ + extendType('range', { + _create: function(opts, set){ + return $('<span />').insertAfter(opts.orig).rangeUI(opts).data('rangeUi'); + } + }); } - }); - var initMediaElements = function(){ - - webshims.addReady(function(context, insertedElement){ - var media = $('video, audio', context) - .add(insertedElement.filter('video, audio')) - .each(function(){ - var data = webshims.data(this, 'mediaelement'); - - if(hasNative && $.prop(this, 'paused') && !$.prop(this, 'readyState') && $(this).is('audio[preload="none"][controls]:not([autoplay])') && (!data || data.isActive == 'html5')){ - //IE controls not visible bug - $(this).prop('preload', 'metadata').mediaLoad(); - } else { - selectSource(this, data); + if(Modernizr.formvalidation){ + ['input', 'form'].forEach(function(name){ + var desc = webshims.defineNodeNameProperty(name, 'checkValidity', { + prop: { + value: function(){ + isCheckValidity = true; + var ret = desc.prop._supvalue.apply(this, arguments); + isCheckValidity = false; + return ret; + } } - - if(hasNative){ + }); + }); + } + + + ['number', 'time', 'month', 'date'].forEach(function(name){ + if(!modernizrInputTypes[name] || options.replaceUI){ + extendType(name, { + _create: function(opts, set){ - //FF progress bug - (function(){ - var bufferTimer; - var lastBuffered; - var elem = this; - var getBufferedString = function(){ - var buffered = $.prop(elem, 'buffered'); - if(!buffered){return;} - var bufferString = ""; - for(var i = 0, len = buffered.length; i < len;i++){ - bufferString += buffered.end(i); - } - return bufferString; - }; - var testBuffer = function(){ - var buffered = getBufferedString(); - if(buffered != lastBuffered){ - lastBuffered = buffered; - $(elem).triggerHandler('progress'); - } - }; - - $(this) - .on({ - 'play loadstart progress': function(e){ - if(e.type == 'progress'){ - lastBuffered = getBufferedString(); - } - clearTimeout(bufferTimer); - bufferTimer = setTimeout(testBuffer, 999); - }, - 'emptied stalled mediaerror abort suspend': function(e){ - if(e.type == 'emptied'){ - lastBuffered = false; - } - clearTimeout(bufferTimer); - } - }) - ; - })(); + if(opts.splitInput && !splitInputs[name]){ + webshims.warn('splitInput not supported for '+ name); + opts.splitInput = false; + } + var markup = opts.splitInput ? + '<span class="ws-'+name+' ws-input" role="group"></span>' : + '<input class="ws-'+name+'" type="text" />'; + var data = $(markup) //role="spinbutton"??? + .insertAfter(opts.orig) + .spinbtnUI(opts) + .data('wsspinner') + ; + if(webshims.picker && webshims.picker[name]){ + webshims.picker[name](data); + } + data.buttonWrapper.addClass('input-button-size-'+(data.buttonWrapper.children().filter(isVisible).length)); + return data; } - - }) - ; - if(!loadTrackUi.loaded && $('track', media).length){ - loadTrackUi(); + }); } - media = null; }); - }; - - if(Modernizr.track && !bugs.track){ - webshims.defineProperty(TextTrack.prototype, 'shimActiveCues', { - get: function(){ - return this._shimActiveCues || this.activeCues; - } + + + webshims.addReady(function(context, contextElem){ + $('input', context) + .add(contextElem.filter('input')) + .each(implementType) + ; }); - } - //set native implementation ready, before swf api is retested - if(hasNative){ - webshims.isReady('mediaelement-core', true); - initMediaElements(); - webshims.ready('WINDOWLOAD mediaelement', loadThird); - } else { - webshims.ready(swfType, initMediaElements); - } - webshims.ready('WINDOWLOAD mediaelement', loadTrackUi); + })(); }); -})(jQuery, Modernizr, jQuery.webshims); \ No newline at end of file +