webshims-rails 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. data/lib/webshims-rails/version.rb +2 -2
  2. data/vendor/assets/javascripts/webshims/extras/custom-validity.js +261 -261
  3. data/vendor/assets/javascripts/webshims/extras/modernizr-custom.js +534 -534
  4. data/vendor/assets/javascripts/webshims/extras/mousepress.js +60 -60
  5. data/vendor/assets/javascripts/webshims/minified/extras/custom-validity.js +1 -1
  6. data/vendor/assets/javascripts/webshims/minified/polyfiller.js +24 -24
  7. data/vendor/assets/javascripts/webshims/minified/shims/FlashCanvasPro/README +82 -82
  8. data/vendor/assets/javascripts/webshims/minified/shims/combos/1.js +35 -34
  9. data/vendor/assets/javascripts/webshims/minified/shims/combos/10.js +79 -82
  10. data/vendor/assets/javascripts/webshims/minified/shims/combos/11.js +45 -44
  11. data/vendor/assets/javascripts/webshims/minified/shims/combos/12.js +43 -42
  12. data/vendor/assets/javascripts/webshims/minified/shims/combos/13.js +28 -27
  13. data/vendor/assets/javascripts/webshims/minified/shims/combos/15.js +4 -4
  14. data/vendor/assets/javascripts/webshims/minified/shims/combos/16.js +57 -59
  15. data/vendor/assets/javascripts/webshims/minified/shims/combos/17.js +64 -66
  16. data/vendor/assets/javascripts/webshims/minified/shims/combos/18.js +53 -54
  17. data/vendor/assets/javascripts/webshims/minified/shims/combos/19.js +64 -66
  18. data/vendor/assets/javascripts/webshims/minified/shims/combos/2.js +72 -73
  19. data/vendor/assets/javascripts/webshims/minified/shims/combos/20.js +42 -46
  20. data/vendor/assets/javascripts/webshims/minified/shims/combos/21.js +52 -50
  21. data/vendor/assets/javascripts/webshims/minified/shims/combos/22.js +55 -59
  22. data/vendor/assets/javascripts/webshims/minified/shims/combos/23.js +66 -64
  23. data/vendor/assets/javascripts/webshims/minified/shims/combos/24.js +80 -82
  24. data/vendor/assets/javascripts/webshims/minified/shims/combos/25.js +60 -59
  25. data/vendor/assets/javascripts/webshims/minified/shims/combos/26.js +79 -81
  26. data/vendor/assets/javascripts/webshims/minified/shims/combos/27.js +101 -104
  27. data/vendor/assets/javascripts/webshims/minified/shims/combos/3.js +94 -95
  28. data/vendor/assets/javascripts/webshims/minified/shims/combos/4.js +26 -29
  29. data/vendor/assets/javascripts/webshims/minified/shims/combos/5.js +33 -36
  30. data/vendor/assets/javascripts/webshims/minified/shims/combos/59.js +51 -54
  31. data/vendor/assets/javascripts/webshims/minified/shims/combos/6.js +27 -28
  32. data/vendor/assets/javascripts/webshims/minified/shims/combos/7.js +27 -28
  33. data/vendor/assets/javascripts/webshims/minified/shims/combos/8.js +39 -38
  34. data/vendor/assets/javascripts/webshims/minified/shims/combos/9.js +65 -68
  35. data/vendor/assets/javascripts/webshims/minified/shims/details.js +4 -4
  36. data/vendor/assets/javascripts/webshims/minified/shims/dom-extend.js +23 -22
  37. data/vendor/assets/javascripts/webshims/minified/shims/form-core.js +19 -22
  38. data/vendor/assets/javascripts/webshims/minified/shims/form-datalist.js +14 -14
  39. data/vendor/assets/javascripts/webshims/minified/shims/form-number-date-api.js +9 -9
  40. data/vendor/assets/javascripts/webshims/minified/shims/form-number-date-ui.js +18 -19
  41. data/vendor/assets/javascripts/webshims/minified/shims/form-shim-extend.js +45 -43
  42. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-de.txt +33 -33
  43. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-en.txt +34 -34
  44. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-core.js +12 -12
  45. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-jaris.js +23 -0
  46. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-native-fix.js +1 -1
  47. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-swf.js +26 -30
  48. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-yt.js +3 -3
  49. data/vendor/assets/javascripts/webshims/minified/shims/styles/shim.css +689 -686
  50. data/vendor/assets/javascripts/webshims/minified/shims/swf/JarisFLVPlayer.swf +0 -0
  51. data/vendor/assets/javascripts/webshims/minified/shims/track-ui.js +9 -9
  52. data/vendor/assets/javascripts/webshims/minified/shims/track.js +21 -21
  53. data/vendor/assets/javascripts/webshims/polyfiller.js +1191 -1175
  54. data/vendor/assets/javascripts/webshims/shims/combos/1.js +1754 -1714
  55. data/vendor/assets/javascripts/webshims/shims/combos/10.js +3247 -3320
  56. data/vendor/assets/javascripts/webshims/shims/combos/11.js +1633 -1588
  57. data/vendor/assets/javascripts/webshims/shims/combos/12.js +1636 -1591
  58. data/vendor/assets/javascripts/webshims/shims/combos/13.js +1100 -1058
  59. data/vendor/assets/javascripts/webshims/shims/combos/14.js +476 -476
  60. data/vendor/assets/javascripts/webshims/shims/combos/15.js +316 -314
  61. data/vendor/assets/javascripts/webshims/shims/combos/16.js +2094 -2104
  62. data/vendor/assets/javascripts/webshims/shims/combos/17.js +2258 -2267
  63. data/vendor/assets/javascripts/webshims/shims/combos/18.js +1380 -1364
  64. data/vendor/assets/javascripts/webshims/shims/combos/19.js +2239 -2247
  65. data/vendor/assets/javascripts/webshims/shims/combos/2.js +2339 -2294
  66. data/vendor/assets/javascripts/webshims/shims/combos/20.js +1493 -1606
  67. data/vendor/assets/javascripts/webshims/shims/combos/21.js +1733 -1635
  68. data/vendor/assets/javascripts/webshims/shims/combos/22.js +2295 -2408
  69. data/vendor/assets/javascripts/webshims/shims/combos/23.js +2269 -2168
  70. data/vendor/assets/javascripts/webshims/shims/combos/24.js +2775 -2780
  71. data/vendor/assets/javascripts/webshims/shims/combos/25.js +1505 -1456
  72. data/vendor/assets/javascripts/webshims/shims/combos/26.js +2111 -2115
  73. data/vendor/assets/javascripts/webshims/shims/combos/27.js +3264 -3331
  74. data/vendor/assets/javascripts/webshims/shims/combos/3.js +3020 -2970
  75. data/vendor/assets/javascripts/webshims/shims/combos/4.js +770 -822
  76. data/vendor/assets/javascripts/webshims/shims/combos/5.js +1025 -1077
  77. data/vendor/assets/javascripts/webshims/shims/combos/59.js +1706 -1753
  78. data/vendor/assets/javascripts/webshims/shims/combos/6.js +444 -433
  79. data/vendor/assets/javascripts/webshims/shims/combos/7.js +699 -688
  80. data/vendor/assets/javascripts/webshims/shims/combos/8.js +1488 -1445
  81. data/vendor/assets/javascripts/webshims/shims/combos/9.js +2445 -2518
  82. data/vendor/assets/javascripts/webshims/shims/details.js +148 -146
  83. data/vendor/assets/javascripts/webshims/shims/dom-extend.js +952 -912
  84. data/vendor/assets/javascripts/webshims/shims/es5.js +802 -802
  85. data/vendor/assets/javascripts/webshims/shims/excanvas.js +924 -924
  86. data/vendor/assets/javascripts/webshims/shims/form-core.js +606 -659
  87. data/vendor/assets/javascripts/webshims/shims/form-datalist.js +681 -676
  88. data/vendor/assets/javascripts/webshims/shims/form-message.js +164 -163
  89. data/vendor/assets/javascripts/webshims/shims/form-native-extend.js +255 -255
  90. data/vendor/assets/javascripts/webshims/shims/form-number-date-api.js +383 -383
  91. data/vendor/assets/javascripts/webshims/shims/form-number-date-ui.js +61 -50
  92. data/vendor/assets/javascripts/webshims/shims/form-shim-extend.js +1569 -1472
  93. data/vendor/assets/javascripts/webshims/shims/geolocation.js +168 -168
  94. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-ar.js +32 -32
  95. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-ch-ZN.js +32 -32
  96. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-de.txt +33 -33
  97. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-el.js +32 -32
  98. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-en.txt +34 -34
  99. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-es.js +31 -31
  100. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-fr.js +32 -32
  101. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-he.js +32 -32
  102. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-hi.js +32 -32
  103. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-hu.js +32 -32
  104. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-it.js +32 -32
  105. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-ja.js +32 -32
  106. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-nl.js +32 -32
  107. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-pt-PT.js +32 -32
  108. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-ru.js +31 -31
  109. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-sv.js +32 -32
  110. data/vendor/assets/javascripts/webshims/shims/json-storage.js +308 -308
  111. data/vendor/assets/javascripts/webshims/shims/mediaelement-core.js +536 -533
  112. data/vendor/assets/javascripts/webshims/shims/mediaelement-jaris.js +861 -0
  113. data/vendor/assets/javascripts/webshims/shims/mediaelement-native-fix.js +98 -98
  114. data/vendor/assets/javascripts/webshims/shims/mediaelement-swf.js +957 -1073
  115. data/vendor/assets/javascripts/webshims/shims/mediaelement-yt.js +543 -543
  116. data/vendor/assets/javascripts/webshims/shims/styles/shim.css +689 -686
  117. data/vendor/assets/javascripts/webshims/shims/swf/JarisFLVPlayer.swf +0 -0
  118. data/vendor/assets/javascripts/webshims/shims/track-ui.js +9 -8
  119. data/vendor/assets/javascripts/webshims/shims/track.js +17 -11
  120. metadata +6 -6
  121. data/vendor/assets/javascripts/webshims/minified/shims/form-native-fix.js +0 -7
  122. data/vendor/assets/javascripts/webshims/shims/FlashCanvas/README +0 -62
  123. data/vendor/assets/javascripts/webshims/shims/FlashCanvasPro/README +0 -82
  124. data/vendor/assets/javascripts/webshims/shims/form-native-fix.js +0 -261
@@ -1,1754 +1,1707 @@
1
- jQuery.webshims.register('form-extend', function($, webshims, window, doc, undefined, options){
2
- "use strict";
3
- var Modernizr = window.Modernizr;
4
- var modernizrInputTypes = Modernizr.inputtypes;
5
- if(!Modernizr.formvalidation || webshims.bugs.bustedValidity){return;}
6
- var typeModels = webshims.inputTypes;
7
- var validityRules = {};
8
-
9
- webshims.addInputType = function(type, obj){
10
- typeModels[type] = obj;
11
- };
12
-
13
- webshims.addValidityRule = function(type, fn){
14
- validityRules[type] = fn;
15
- };
16
-
17
- webshims.addValidityRule('typeMismatch',function (input, val, cache, validityState){
18
- if(val === ''){return false;}
19
- var ret = validityState.typeMismatch;
20
- if(!('type' in cache)){
21
- cache.type = (input[0].getAttribute('type') || '').toLowerCase();
22
- }
23
-
24
- if(typeModels[cache.type] && typeModels[cache.type].mismatch){
25
- ret = typeModels[cache.type].mismatch(val, input);
26
- }
27
- return ret;
28
- });
29
-
30
- var overrideNativeMessages = options.overrideMessages;
31
-
32
- var overrideValidity = (!modernizrInputTypes.number || !modernizrInputTypes.time || !modernizrInputTypes.range || overrideNativeMessages);
33
- var validityProps = ['customError','typeMismatch','rangeUnderflow','rangeOverflow','stepMismatch','tooLong','patternMismatch','valueMissing','valid'];
34
-
35
- var validityChanger = (overrideNativeMessages)? ['value', 'checked'] : ['value'];
36
- var validityElements = [];
37
- var testValidity = function(elem, init){
38
- if(!elem){return;}
39
- var type = (elem.getAttribute && elem.getAttribute('type') || elem.type || '').toLowerCase();
40
-
41
- if(!overrideNativeMessages && !typeModels[type]){
42
- return;
43
- }
44
-
45
- if(overrideNativeMessages && !init && type == 'radio' && elem.name){
46
- $(doc.getElementsByName( elem.name )).each(function(){
47
- $.prop(this, 'validity');
48
- });
49
- } else {
50
- $.prop(elem, 'validity');
51
- }
52
- };
53
-
54
- var oldSetCustomValidity = {};
55
- ['input', 'textarea', 'select'].forEach(function(name){
56
- var desc = webshims.defineNodeNameProperty(name, 'setCustomValidity', {
57
- prop: {
58
- value: function(error){
59
- error = error+'';
60
- var elem = (name == 'input') ? $(this).getNativeElement()[0] : this;
61
- desc.prop._supvalue.call(elem, error);
62
-
63
- if(webshims.bugs.validationMessage){
64
- webshims.data(elem, 'customvalidationMessage', error);
65
- }
66
- if(overrideValidity){
67
- webshims.data(elem, 'hasCustomError', !!(error));
68
- testValidity(elem);
69
- }
70
- }
71
- }
72
- });
73
- oldSetCustomValidity[name] = desc.prop._supvalue;
74
- });
75
-
76
-
77
- if(overrideValidity || overrideNativeMessages){
78
- validityChanger.push('min');
79
- validityChanger.push('max');
80
- validityChanger.push('step');
81
- validityElements.push('input');
82
- }
83
- if(overrideNativeMessages){
84
- validityChanger.push('required');
85
- validityChanger.push('pattern');
86
- validityElements.push('select');
87
- validityElements.push('textarea');
88
- }
89
-
90
- if(overrideValidity){
91
- var stopValidity;
92
- validityElements.forEach(function(nodeName){
93
-
94
- var oldDesc = webshims.defineNodeNameProperty(nodeName, 'validity', {
95
- prop: {
96
- get: function(){
97
- if(stopValidity){return;}
98
- var elem = (nodeName == 'input') ? $(this).getNativeElement()[0] : this;
99
-
100
- var validity = oldDesc.prop._supget.call(elem);
101
-
102
- if(!validity){
103
- return validity;
104
- }
105
- var validityState = {};
106
- validityProps.forEach(function(prop){
107
- validityState[prop] = validity[prop];
108
- });
109
-
110
- if( !$.prop(elem, 'willValidate') ){
111
- return validityState;
112
- }
113
- stopValidity = true;
114
- var jElm = $(elem),
115
- cache = {type: (elem.getAttribute && elem.getAttribute('type') || '').toLowerCase(), nodeName: (elem.nodeName || '').toLowerCase()},
116
- val = jElm.val(),
117
- customError = !!(webshims.data(elem, 'hasCustomError')),
118
- setCustomMessage
119
- ;
120
- stopValidity = false;
121
- validityState.customError = customError;
122
-
123
- if( validityState.valid && validityState.customError ){
124
- validityState.valid = false;
125
- } else if(!validityState.valid) {
126
- var allFalse = true;
127
- $.each(validityState, function(name, prop){
128
- if(prop){
129
- allFalse = false;
130
- return false;
131
- }
132
- });
133
-
134
- if(allFalse){
135
- validityState.valid = true;
136
- }
137
-
138
- }
139
-
140
- $.each(validityRules, function(rule, fn){
141
- validityState[rule] = fn(jElm, val, cache, validityState);
142
- if( validityState[rule] && (validityState.valid || !setCustomMessage) && (overrideNativeMessages || (typeModels[cache.type] && typeModels[cache.type].mismatch)) ) {
143
- oldSetCustomValidity[nodeName].call(elem, webshims.createValidationMessage(elem, rule));
144
- validityState.valid = false;
145
- setCustomMessage = true;
146
- }
147
- });
148
- if(validityState.valid){
149
- oldSetCustomValidity[nodeName].call(elem, '');
150
- webshims.data(elem, 'hasCustomError', false);
151
- } else if(overrideNativeMessages && !setCustomMessage && !customError){
152
- $.each(validityState, function(name, prop){
153
- if(name !== 'valid' && prop){
154
- oldSetCustomValidity[nodeName].call(elem, webshims.createValidationMessage(elem, name));
155
- return false;
156
- }
157
- });
158
- }
159
- return validityState;
160
- },
161
- writeable: false
162
-
163
- }
164
- });
165
- });
166
-
167
- validityChanger.forEach(function(prop){
168
- webshims.onNodeNamesPropertyModify(validityElements, prop, function(s){
169
- testValidity(this);
170
- });
171
- });
172
-
173
- if(doc.addEventListener){
174
- var inputThrottle;
175
- var testPassValidity = function(e){
176
- if(!('form' in e.target)){return;}
177
- var form = e.target.form;
178
- clearTimeout(inputThrottle);
179
- testValidity(e.target);
180
- if(form && overrideNativeMessages){
181
- $('input', form).each(function(){
182
- if(this.type == 'password'){
183
- testValidity(this);
184
- }
185
- });
186
- }
187
- };
188
-
189
- doc.addEventListener('change', testPassValidity, true);
190
-
191
- if(overrideNativeMessages){
192
- doc.addEventListener('blur', testPassValidity, true);
193
- doc.addEventListener('keydown', function(e){
194
- if(e.keyCode != 13){return;}
195
- testPassValidity(e);
196
- }, true);
197
- }
198
-
199
- doc.addEventListener('input', function(e){
200
- clearTimeout(inputThrottle);
201
- inputThrottle = setTimeout(function(){
202
- testValidity(e.target);
203
- }, 290);
204
- }, true);
205
- }
206
-
207
- var validityElementsSel = validityElements.join(',');
208
-
209
- webshims.addReady(function(context, elem){
210
- $(validityElementsSel, context).add(elem.filter(validityElementsSel)).each(function(){
211
- $.prop(this, 'validity');
212
- });
213
- });
214
-
215
-
216
- if(overrideNativeMessages){
217
- webshims.ready('DOM form-message', function(){
218
- webshims.activeLang({
219
- register: 'form-core',
220
- callback: function(){
221
- $('input, select, textarea')
222
- .getNativeElement()
223
- .each(function(){
224
- if(webshims.data(this, 'hasCustomError')){return;}
225
- var elem = this;
226
- var validity = $.prop(elem, 'validity') || {valid: true};
227
- var nodeName;
228
- if(validity.valid){return;}
229
- nodeName = (elem.nodeName || '').toLowerCase();
230
- $.each(validity, function(name, prop){
231
- if(name !== 'valid' && prop){
232
- oldSetCustomValidity[nodeName].call(elem, webshims.createValidationMessage(elem, name));
233
- return false;
234
- }
235
- });
236
- })
237
- ;
238
- }
239
- });
240
- });
241
- }
242
-
243
- } //end: overrideValidity
244
-
245
- webshims.defineNodeNameProperty('input', 'type', {
246
- prop: {
247
- get: function(){
248
- var elem = this;
249
- var type = (elem.getAttribute('type') || '').toLowerCase();
250
- return (webshims.inputTypes[type]) ? type : elem.type;
251
- }
252
- }
253
- });
254
-
255
-
256
- });//additional tests for partial implementation of forms features
257
- (function($){
258
- var Modernizr = window.Modernizr;
259
- var webshims = $.webshims;
260
- var bugs = webshims.bugs;
261
- var form = $('<form action="#" style="width: 1px; height: 1px; overflow: hidden;"><select name="b" required="" /><input type="date" required="" name="a" /><input type="submit" /></form>');
262
- var testRequiredFind = function(){
263
- if(form[0].querySelector){
264
- try {
265
- bugs.findRequired = !(form[0].querySelector('select:required'));
266
- } catch(er){
267
- bugs.findRequired = false;
268
- }
269
- }
270
- };
271
- bugs.findRequired = false;
272
- bugs.validationMessage = false;
273
- bugs.valueAsNumberSet = false;
274
-
275
- webshims.capturingEventPrevented = function(e){
276
- if(!e._isPolyfilled){
277
- var isDefaultPrevented = e.isDefaultPrevented;
278
- var preventDefault = e.preventDefault;
279
- e.preventDefault = function(){
280
- clearTimeout($.data(e.target, e.type + 'DefaultPrevented'));
281
- $.data(e.target, e.type + 'DefaultPrevented', setTimeout(function(){
282
- $.removeData(e.target, e.type + 'DefaultPrevented');
283
- }, 30));
284
- return preventDefault.apply(this, arguments);
285
- };
286
- e.isDefaultPrevented = function(){
287
- return !!(isDefaultPrevented.apply(this, arguments) || $.data(e.target, e.type + 'DefaultPrevented') || false);
288
- };
289
- e._isPolyfilled = true;
290
- }
291
- };
292
-
293
- if(!Modernizr.formvalidation || bugs.bustedValidity){
294
- testRequiredFind();
295
- return;
296
- }
297
-
298
- //create delegatable events
299
- webshims.capturingEvents(['input']);
300
- webshims.capturingEvents(['invalid'], true);
301
-
302
- Modernizr.bugfreeformvalidation = true;
303
- if(window.opera || $.browser.webkit || window.testGoodWithFix){
304
- var dateElem = $('input', form).eq(0);
305
- var timer;
306
- var onDomextend = function(fn){
307
- webshims.loader.loadList(['dom-extend']);
308
- webshims.ready('dom-extend', fn);
309
- };
310
- var loadFormFixes = function(e){
311
- var reTest = ['form-extend', 'form-message', 'form-native-fix'];
312
- if(e){
313
- e.preventDefault();
314
- e.stopImmediatePropagation();
315
- }
316
- clearTimeout(timer);
317
- setTimeout(function(){
318
- if(!form){return;}
319
- form.remove();
320
- form = dateElem = null;
321
- }, 9);
322
- if(!Modernizr.bugfreeformvalidation){
323
- webshims.addPolyfill('form-native-fix', {
324
- f: 'forms',
325
- d: ['form-extend']
326
- });
327
- //remove form-extend readyness
328
- webshims.modules['form-extend'].test = $.noop;
329
- }
330
-
331
- if(webshims.isReady('form-number-date-api')){
332
- reTest.push('form-number-date-api');
333
- }
334
-
335
- webshims.reTest(reTest);
336
-
337
- if(dateElem){
338
- try {
339
- if(dateElem.prop({disabled: true, value: ''}).prop('disabled', false).is(':valid')){
340
- onDomextend(function(){
341
- webshims.onNodeNamesPropertyModify(['input', 'textarea'], ['disabled', 'readonly'], {
342
- set: function(val){
343
- var elem = this;
344
- if(!val && elem){
345
- $.prop(elem, 'value', $.prop(elem, 'value'));
346
- }
347
- }
348
- });
349
- webshims.onNodeNamesPropertyModify(['select'], ['disabled', 'readonly'], {
350
- set: function(val){
351
- var elem = this;
352
- if(!val && elem){
353
- val = $(elem).val();
354
- ($('option:last-child', elem)[0] || {}).selected = true;
355
- $(elem).val( val );
356
- }
357
- }
358
- });
359
- });
360
- }
361
- } catch(er){}
362
- }
363
-
364
- if ($.browser.opera || window.testGoodWithFix) {
365
- onDomextend(function(){
366
-
367
- //Opera shows native validation bubbles in case of input.checkValidity()
368
- // Opera 11.6/12 hasn't fixed this issue right, it's buggy
369
- var preventDefault = function(e){
370
- e.preventDefault();
371
- };
372
-
373
- ['form', 'input', 'textarea', 'select'].forEach(function(name){
374
- var desc = webshims.defineNodeNameProperty(name, 'checkValidity', {
375
- prop: {
376
- value: function(){
377
- if (!webshims.fromSubmit) {
378
- $(this).bind('invalid.checkvalidity', preventDefault);
379
- }
380
-
381
- webshims.fromCheckValidity = true;
382
- var ret = desc.prop._supvalue.apply(this, arguments);
383
- if (!webshims.fromSubmit) {
384
- $(this).unbind('invalid.checkvalidity', preventDefault);
385
- }
386
- webshims.fromCheckValidity = false;
387
- return ret;
388
- }
389
- }
390
- });
391
- });
392
-
393
- });
394
- }
395
- };
396
-
397
- form.appendTo('head');
398
- if(window.opera || window.testGoodWithFix) {
399
- testRequiredFind();
400
- bugs.validationMessage = !(dateElem.prop('validationMessage'));
401
- if((Modernizr.inputtypes || {}).date){
402
- try {
403
- dateElem.prop('valueAsNumber', 0);
404
- } catch(er){}
405
- bugs.valueAsNumberSet = (dateElem.prop('value') != '1970-01-01');
406
- }
407
- dateElem.prop('value', '');
408
- }
409
-
410
- form.bind('submit', function(e){
411
- Modernizr.bugfreeformvalidation = false;
412
- loadFormFixes(e);
413
- });
414
-
415
- timer = setTimeout(function(){
416
- if (form) {
417
- form.triggerHandler('submit');
418
- }
419
- }, 9);
420
-
421
- $('input, select', form).bind('invalid', loadFormFixes)
422
- .filter('[type="submit"]')
423
- .bind('click', function(e){
424
- e.stopImmediatePropagation();
425
- })
426
- .trigger('click')
427
- ;
428
-
429
- if($.browser.webkit && Modernizr.bugfreeformvalidation && !webshims.bugs.bustedValidity){
430
- (function(){
431
- var elems = /^(?:textarea|input)$/i;
432
- var form = false;
433
-
434
- document.addEventListener('contextmenu', function(e){
435
- if(elems.test( e.target.nodeName || '') && (form = e.target.form)){
436
- setTimeout(function(){
437
- form = false;
438
- }, 1);
439
- }
440
- }, false);
441
-
442
- $(window).bind('invalid', function(e){
443
- if(e.originalEvent && form && form == e.target.form){
444
- e.wrongWebkitInvalid = true;
445
- e.stopImmediatePropagation();
446
- }
447
- });
448
- })();
449
- }
450
- }
451
-
452
- })(jQuery);
453
-
454
- jQuery.webshims.register('form-core', function($, webshims, window, document, undefined, options){
455
- "use strict";
456
-
457
- var groupTypes = {radio: 1};
458
- var checkTypes = {checkbox: 1, radio: 1};
459
- var emptyJ = $([]);
460
- var bugs = webshims.bugs;
461
- var getGroupElements = function(elem){
462
- elem = $(elem);
463
- var name;
464
- var form;
465
- var ret = emptyJ;
466
- if(groupTypes[elem[0].type]){
467
- form = elem.prop('form');
468
- name = elem[0].name;
469
- if(!name){
470
- ret = elem;
471
- } else if(form){
472
- ret = $(form[name]);
473
- } else {
474
- ret = $(document.getElementsByName(name)).filter(function(){
475
- return !$.prop(this, 'form');
476
- });
477
- }
478
- ret = ret.filter('[type="radio"]');
479
- }
480
- return ret;
481
- };
482
-
483
- var getContentValidationMessage = webshims.getContentValidationMessage = function(elem, validity, key){
484
- var message = $(elem).data('errormessage') || elem.getAttribute('x-moz-errormessage') || '';
485
- if(key && message[key]){
486
- message = message[key];
487
- }
488
- if(typeof message == 'object'){
489
- validity = validity || $.prop(elem, 'validity') || {valid: 1};
490
- if(!validity.valid){
491
- $.each(validity, function(name, prop){
492
- if(prop && name != 'valid' && message[name]){
493
- message = message[name];
494
- return false;
495
- }
496
- });
497
- }
498
- }
499
-
500
- if(typeof message == 'object'){
501
- message = message.defaultMessage;
502
- }
503
- return message || '';
504
- };
505
-
506
- /*
507
- * Selectors for all browsers
508
- */
509
- var rangeTypes = {number: 1, range: 1, date: 1/*, time: 1, 'datetime-local': 1, datetime: 1, month: 1, week: 1*/};
510
- $.extend($.expr[":"], {
511
- "valid-element": function(elem){
512
- return !!($.prop(elem, 'willValidate') && ($.prop(elem, 'validity') || {valid: 1}).valid);
513
- },
514
- "invalid-element": function(elem){
515
- return !!($.prop(elem, 'willValidate') && !isValid(elem));
516
- },
517
- "required-element": function(elem){
518
- return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required'));
519
- },
520
- "optional-element": function(elem){
521
- return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required') === false);
522
- },
523
- "in-range": function(elem){
524
- if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
525
- return false;
526
- }
527
- var val = $.prop(elem, 'validity');
528
- return !!(val && !val.rangeOverflow && !val.rangeUnderflow);
529
- },
530
- "out-of-range": function(elem){
531
- if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
532
- return false;
533
- }
534
- var val = $.prop(elem, 'validity');
535
- return !!(val && (val.rangeOverflow || val.rangeUnderflow));
536
- }
537
-
538
- });
539
-
540
- ['valid', 'invalid', 'required', 'optional'].forEach(function(name){
541
- $.expr[":"][name] = $.expr.filters[name+"-element"];
542
- });
543
-
544
-
545
- $.expr[":"].focus = function( elem ) {
546
- try {
547
- var doc = elem.ownerDocument;
548
- return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus());
549
- } catch(e){}
550
- return false;
551
- };
552
-
553
- var customEvents = $.event.customEvent || {};
554
- var isValid = function(elem){
555
- return ($.prop(elem, 'validity') || {valid: 1}).valid;
556
- };
557
-
558
- if (bugs.bustedValidity || bugs.findRequired || !Modernizr.bugfreeformvalidation) {
559
- (function(){
560
- var find = $.find;
561
- var matchesSelector = $.find.matchesSelector;
562
-
563
- var regExp = /(\:valid|\:invalid|\:optional|\:required|\:in-range|\:out-of-range)(?=[\s\[\~\.\+\>\:\#*]|$)/ig;
564
- var regFn = function(sel){
565
- return sel + '-element';
566
- };
567
-
568
- $.find = (function(){
569
- var slice = Array.prototype.slice;
570
- var fn = function(sel){
571
- var ar = arguments;
572
- ar = slice.call(ar, 1, ar.length);
573
- ar.unshift(sel.replace(regExp, regFn));
574
- return find.apply(this, ar);
575
- };
576
- for (var i in find) {
577
- if(find.hasOwnProperty(i)){
578
- fn[i] = find[i];
579
- }
580
- }
581
- return fn;
582
- })();
583
- if(!Modernizr.prefixed || Modernizr.prefixed("matchesSelector", document.documentElement)){
584
- $.find.matchesSelector = function(node, expr){
585
- expr = expr.replace(regExp, regFn);
586
- return matchesSelector.call(this, node, expr);
587
- };
588
- }
589
-
590
- })();
591
- }
592
-
593
- //ToDo needs testing
594
- var oldAttr = $.prop;
595
- var changeVals = {selectedIndex: 1, value: 1, checked: 1, disabled: 1, readonly: 1};
596
- $.prop = function(elem, name, val){
597
- var ret = oldAttr.apply(this, arguments);
598
- if(elem && 'form' in elem && changeVals[name] && val !== undefined && $(elem).hasClass('form-ui-invalid')){
599
- if(isValid(elem)){
600
- $(elem).getShadowElement().removeClass('form-ui-invalid');
601
- if(name == 'checked' && val) {
602
- getGroupElements(elem).not(elem).removeClass('form-ui-invalid').removeAttr('aria-invalid');
603
- }
604
- }
605
- }
606
- return ret;
607
- };
608
-
609
- var returnValidityCause = function(validity, elem){
610
- var ret;
611
- $.each(validity, function(name, value){
612
- if(value){
613
- ret = (name == 'customError') ? $.prop(elem, 'validationMessage') : name;
614
- return false;
615
- }
616
- });
617
- return ret;
618
- };
619
-
620
- var switchValidityClass = function(e){
621
- var elem, timer;
622
- if(!e.target){return;}
623
- elem = $(e.target).getNativeElement()[0];
624
- if(elem.type == 'submit' || !$.prop(elem, 'willValidate') || (e.type == 'focusout' && e.type == 'radio')){return;}
625
- timer = $.data(elem, 'webshimsswitchvalidityclass');
626
- var switchClass = function(){
627
- var validity = $.prop(elem, 'validity');
628
- var shadowElem = $(elem).getShadowElement();
629
- var addClass, removeClass, trigger, generaltrigger, validityCause;
630
-
631
- $(elem).trigger('refreshCustomValidityRules');
632
- if(validity.valid){
633
- if(!shadowElem.hasClass('form-ui-valid')){
634
- addClass = 'form-ui-valid';
635
- removeClass = 'form-ui-invalid';
636
- generaltrigger = 'changedvaliditystate';
637
- trigger = 'changedvalid';
638
- if(checkTypes[elem.type] && elem.checked){
639
- getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass).removeAttr('aria-invalid');
640
- }
641
- $.removeData(elem, 'webshimsinvalidcause');
642
- }
643
- } else {
644
- validityCause = returnValidityCause(validity, elem);
645
- if($.data(elem, 'webshimsinvalidcause') != validityCause){
646
- $.data(elem, 'webshimsinvalidcause', validityCause);
647
- generaltrigger = 'changedvaliditystate';
648
- }
649
- if(!shadowElem.hasClass('form-ui-invalid')){
650
- addClass = 'form-ui-invalid';
651
- removeClass = 'form-ui-valid';
652
- if (checkTypes[elem.type] && !elem.checked) {
653
- getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass);
654
- }
655
- trigger = 'changedinvalid';
656
- }
657
- }
658
- if(addClass){
659
- shadowElem.addClass(addClass).removeClass(removeClass);
660
- //jQuery 1.6.1 IE9 bug (doubble trigger bug)
661
- setTimeout(function(){
662
- $(elem).trigger(trigger);
663
- }, 0);
664
- }
665
- if(generaltrigger){
666
- setTimeout(function(){
667
- $(elem).trigger(generaltrigger);
668
- }, 0);
669
- }
670
- $.removeData(e.target, 'webshimsswitchvalidityclass');
671
-
672
- };
673
- if(timer){
674
- clearTimeout(timer);
675
- }
676
- if(e.type == 'refreshvalidityui'){
677
- switchClass();
678
- } else {
679
- $.data(e.target, 'webshimsswitchvalidityclass', setTimeout(switchClass, 9));
680
- }
681
- };
682
-
683
- $(document).bind(options.validityUIEvents || 'focusout change refreshvalidityui', switchValidityClass);
684
- customEvents.changedvaliditystate = true;
685
- customEvents.refreshCustomValidityRules = true;
686
- customEvents.changedvalid = true;
687
- customEvents.changedinvalid = true;
688
- customEvents.refreshvalidityui = true;
689
-
690
-
691
- webshims.triggerInlineForm = function(elem, event){
692
- $(elem).trigger(event);
693
- };
694
-
695
- webshims.modules["form-core"].getGroupElements = getGroupElements;
696
-
697
-
698
- var setRoot = function(){
699
- webshims.scrollRoot = ($.browser.webkit || document.compatMode == 'BackCompat') ?
700
- $(document.body) :
701
- $(document.documentElement)
702
- ;
703
- };
704
- setRoot();
705
- webshims.ready('DOM', setRoot);
706
-
707
- webshims.getRelOffset = function(posElem, relElem){
708
- posElem = $(posElem);
709
- var offset = $(relElem).offset();
710
- var bodyOffset;
711
- $.swap($(posElem)[0], {visibility: 'hidden', display: 'inline-block', left: 0, top: 0}, function(){
712
- bodyOffset = posElem.offset();
713
- });
714
- offset.top -= bodyOffset.top;
715
- offset.left -= bodyOffset.left;
716
- return offset;
717
- };
718
-
719
- /* some extra validation UI */
720
- webshims.validityAlert = (function(){
721
- var alertElem = (!$.browser.msie || parseInt($.browser.version, 10) > 7) ? 'span' : 'label';
722
- var errorBubble;
723
- var hideTimer = false;
724
- var focusTimer = false;
725
- var resizeTimer = false;
726
- var boundHide;
727
-
728
- var api = {
729
- hideDelay: 5000,
730
-
731
- showFor: function(elem, message, noFocusElem, noBubble){
732
- api._create();
733
- elem = $(elem);
734
- var visual = $(elem).getShadowElement();
735
- var offset = api.getOffsetFromBody(visual);
736
- api.clear();
737
- if(noBubble){
738
- this.hide();
739
- } else {
740
- this.getMessage(elem, message);
741
- this.position(visual, offset);
742
-
743
- this.show();
744
- if(this.hideDelay){
745
- hideTimer = setTimeout(boundHide, this.hideDelay);
746
- }
747
- $(window)
748
- .bind('resize.validityalert', function(){
749
- clearTimeout(resizeTimer);
750
- resizeTimer = setTimeout(function(){
751
- api.position(visual);
752
- }, 9);
753
- })
754
- ;
755
- }
756
-
757
- if(!noFocusElem){
758
- this.setFocus(visual, offset);
759
- }
760
- },
761
- getOffsetFromBody: function(elem){
762
- return webshims.getRelOffset(errorBubble, elem);
763
- },
764
- setFocus: function(visual, offset){
765
- var focusElem = $(visual).getShadowFocusElement();
766
- var scrollTop = webshims.scrollRoot.scrollTop();
767
- var elemTop = ((offset || focusElem.offset()).top) - 30;
768
- var smooth;
769
-
770
- if(webshims.getID && alertElem == 'label'){
771
- errorBubble.attr('for', webshims.getID(focusElem));
772
- }
773
-
774
- if(scrollTop > elemTop){
775
- webshims.scrollRoot.animate(
776
- {scrollTop: elemTop - 5},
777
- {
778
- queue: false,
779
- duration: Math.max( Math.min( 600, (scrollTop - elemTop) * 1.5 ), 80 )
780
- }
781
- );
782
- smooth = true;
783
- }
784
- try {
785
- focusElem[0].focus();
786
- } catch(e){}
787
- if(smooth){
788
- webshims.scrollRoot.scrollTop(scrollTop);
789
- setTimeout(function(){
790
- webshims.scrollRoot.scrollTop(scrollTop);
791
- }, 0);
792
- }
793
- setTimeout(function(){
794
- $(document).bind('focusout.validityalert', boundHide);
795
- }, 10);
796
- },
797
- getMessage: function(elem, message){
798
- if (!message) {
799
- message = getContentValidationMessage(elem[0]) || elem.prop('validationMessage');
800
- }
801
- if (message) {
802
- $('span.va-box', errorBubble).text(message);
803
- }
804
- else {
805
- this.hide();
806
- }
807
- },
808
- position: function(elem, offset){
809
- offset = offset ? $.extend({}, offset) : api.getOffsetFromBody(elem);
810
- offset.top += elem.outerHeight();
811
- errorBubble.css(offset);
812
- },
813
- show: function(){
814
- if(errorBubble.css('display') === 'none'){
815
- errorBubble.css({opacity: 0}).show();
816
- }
817
- errorBubble.addClass('va-visible').fadeTo(400, 1);
818
- },
819
- hide: function(){
820
- errorBubble.removeClass('va-visible').fadeOut();
821
- },
822
- clear: function(){
823
- clearTimeout(focusTimer);
824
- clearTimeout(hideTimer);
825
- $(document).unbind('.validityalert');
826
- $(window).unbind('.validityalert');
827
- errorBubble.stop().removeAttr('for');
828
- },
829
- _create: function(){
830
- if(errorBubble){return;}
831
- 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'});
832
- webshims.ready('DOM', function(){
833
- errorBubble.appendTo('body');
834
- if($.fn.bgIframe && $.browser.msie && parseInt($.browser.version, 10) < 7){
835
- errorBubble.bgIframe();
836
- }
837
- });
838
- }
839
- };
840
-
841
-
842
- boundHide = $.proxy(api, 'hide');
843
-
844
- return api;
845
- })();
846
-
847
-
848
- /* extension, but also used to fix native implementation workaround/bugfixes */
849
- (function(){
850
- var firstEvent,
851
- invalids = [],
852
- stopSubmitTimer,
853
- form
854
- ;
855
-
856
- $(document).bind('invalid', function(e){
857
- if(e.wrongWebkitInvalid){return;}
858
- var jElm = $(e.target);
859
- var shadowElem = jElm.getShadowElement();
860
- if(!shadowElem.hasClass('form-ui-invalid')){
861
- shadowElem.addClass('form-ui-invalid').removeClass('form-ui-valid');
862
- setTimeout(function(){
863
- $(e.target).trigger('changedinvalid').trigger('changedvaliditystate');
864
- }, 0);
865
- }
866
-
867
- if(!firstEvent){
868
- //trigger firstinvalid
869
- firstEvent = $.Event('firstinvalid');
870
- firstEvent.isInvalidUIPrevented = e.isDefaultPrevented;
871
- var firstSystemInvalid = $.Event('firstinvalidsystem');
872
- $(document).triggerHandler(firstSystemInvalid, {element: e.target, form: e.target.form, isInvalidUIPrevented: e.isDefaultPrevented});
873
- jElm.trigger(firstEvent);
874
- }
875
-
876
- //if firstinvalid was prevented all invalids will be also prevented
877
- if( firstEvent && firstEvent.isDefaultPrevented() ){
878
- e.preventDefault();
879
- }
880
- invalids.push(e.target);
881
- e.extraData = 'fix';
882
- clearTimeout(stopSubmitTimer);
883
- stopSubmitTimer = setTimeout(function(){
884
- var lastEvent = {type: 'lastinvalid', cancelable: false, invalidlist: $(invalids)};
885
- //reset firstinvalid
886
- firstEvent = false;
887
- invalids = [];
888
- $(e.target).trigger(lastEvent, lastEvent);
889
- }, 9);
890
- jElm = null;
891
- shadowElem = null;
892
- });
893
- })();
894
-
895
- $.fn.getErrorMessage = function(){
896
- var message = '';
897
- var elem = this[0];
898
- if(elem){
899
- message = getContentValidationMessage(elem) || $.prop(elem, 'customValidationMessage') || $.prop(elem, 'validationMessage');
900
- }
901
- return message;
902
- };
903
-
904
- if(options.replaceValidationUI){
905
- webshims.ready('DOM forms', function(){
906
- $(document).bind('firstinvalid', function(e){
907
- if(!e.isInvalidUIPrevented()){
908
- e.preventDefault();
909
- $.webshims.validityAlert.showFor( e.target, $(e.target).prop('customValidationMessage') );
910
- }
911
- });
912
- });
913
- }
914
-
915
- });jQuery.webshims.register('form-message', function($, webshims, window, document, undefined, options){
916
- var validityMessages = webshims.validityMessages;
917
-
918
- var implementProperties = (options.overrideMessages || options.customMessages) ? ['customValidationMessage'] : [];
919
-
920
- validityMessages['en'] = $.extend(true, {
921
- typeMismatch: {
922
- email: 'Please enter an email address.',
923
- url: 'Please enter a URL.',
924
- number: 'Please enter a number.',
925
- date: 'Please enter a date.',
926
- time: 'Please enter a time.',
927
- range: 'Invalid input.',
928
- "datetime-local": 'Please enter a datetime.'
929
- },
930
- rangeUnderflow: {
931
- defaultMessage: 'Value must be greater than or equal to {%min}.'
932
- },
933
- rangeOverflow: {
934
- defaultMessage: 'Value must be less than or equal to {%max}.'
935
- },
936
- stepMismatch: 'Invalid input.',
937
- tooLong: 'Please enter at most {%maxlength} character(s). You entered {%valueLen}.',
938
-
939
- patternMismatch: 'Invalid input. {%title}',
940
- valueMissing: {
941
- defaultMessage: 'Please fill out this field.',
942
- checkbox: 'Please check this box if you want to proceed.'
943
- }
944
- }, (validityMessages['en'] || validityMessages['en-US'] || {}));
945
-
946
-
947
- ['select', 'radio'].forEach(function(type){
948
- validityMessages['en'].valueMissing[type] = 'Please select an option.';
949
- });
950
-
951
- ['date', 'time', 'datetime-local'].forEach(function(type){
952
- validityMessages.en.rangeUnderflow[type] = 'Value must be at or after {%min}.';
953
- });
954
- ['date', 'time', 'datetime-local'].forEach(function(type){
955
- validityMessages.en.rangeOverflow[type] = 'Value must be at or before {%max}.';
956
- });
957
-
958
- validityMessages['en-US'] = validityMessages['en-US'] || validityMessages['en'];
959
- validityMessages[''] = validityMessages[''] || validityMessages['en-US'];
960
-
961
- validityMessages['de'] = $.extend(true, {
962
- typeMismatch: {
963
- email: '{%value} ist keine zulässige E-Mail-Adresse',
964
- url: '{%value} ist keine zulässige Webadresse',
965
- number: '{%value} ist keine Nummer!',
966
- date: '{%value} ist kein Datum',
967
- time: '{%value} ist keine Uhrzeit',
968
- range: '{%value} ist keine Nummer!',
969
- "datetime-local": '{%value} ist kein Datum-Uhrzeit Format.'
970
- },
971
- rangeUnderflow: {
972
- defaultMessage: '{%value} ist zu niedrig. {%min} ist der unterste Wert, den Sie benutzen können.'
973
- },
974
- rangeOverflow: {
975
- defaultMessage: '{%value} ist zu hoch. {%max} ist der oberste Wert, den Sie benutzen können.'
976
- },
977
- stepMismatch: 'Der Wert {%value} ist in diesem Feld nicht zulässig. Hier sind nur bestimmte Werte zulässig. {%title}',
978
- tooLong: 'Der eingegebene Text ist zu lang! Sie haben {%valueLen} Zeichen eingegeben, dabei sind {%maxlength} das Maximum.',
979
- patternMismatch: '{%value} hat für dieses Eingabefeld ein falsches Format! {%title}',
980
- valueMissing: {
981
- defaultMessage: 'Bitte geben Sie einen Wert ein',
982
- checkbox: 'Bitte aktivieren Sie das Kästchen'
983
- }
984
- }, (validityMessages['de'] || {}));
985
-
986
- ['select', 'radio'].forEach(function(type){
987
- validityMessages['de'].valueMissing[type] = 'Bitte wählen Sie eine Option aus';
988
- });
989
-
990
- ['date', 'time', 'datetime-local'].forEach(function(type){
991
- validityMessages.de.rangeUnderflow[type] = '{%value} ist zu früh. {%min} ist die früheste Zeit, die Sie benutzen können.';
992
- });
993
- ['date', 'time', 'datetime-local'].forEach(function(type){
994
- validityMessages.de.rangeOverflow[type] = '{%value} ist zu spät. {%max} ist die späteste Zeit, die Sie benutzen können.';
995
- });
996
-
997
- var currentValidationMessage = validityMessages[''];
998
-
999
-
1000
- webshims.createValidationMessage = function(elem, name){
1001
- var message = currentValidationMessage[name];
1002
- if(message && typeof message !== 'string'){
1003
- message = message[ $.prop(elem, 'type') ] || message[ (elem.nodeName || '').toLowerCase() ] || message[ 'defaultMessage' ];
1004
- }
1005
- if(message){
1006
- ['value', 'min', 'max', 'title', 'maxlength', 'label'].forEach(function(attr){
1007
- if(message.indexOf('{%'+attr) === -1){return;}
1008
- var val = ((attr == 'label') ? $.trim($('label[for="'+ elem.id +'"]', elem.form).text()).replace(/\*$|:$/, '') : $.attr(elem, attr)) || '';
1009
- if(name == 'patternMismatch' && attr == 'title' && !val){
1010
- webshims.error('no title for patternMismatch provided. Always add a title attribute.');
1011
- }
1012
- message = message.replace('{%'+ attr +'}', val);
1013
- if('value' == attr){
1014
- message = message.replace('{%valueLen}', val.length);
1015
- }
1016
- });
1017
- }
1018
- return message || '';
1019
- };
1020
-
1021
-
1022
- if(webshims.bugs.validationMessage || !Modernizr.formvalidation || webshims.bugs.bustedValidity){
1023
- implementProperties.push('validationMessage');
1024
- }
1025
-
1026
- webshims.activeLang({
1027
- langObj: validityMessages,
1028
- module: 'form-core',
1029
- callback: function(langObj){
1030
- currentValidationMessage = langObj;
1031
- }
1032
- });
1033
-
1034
- implementProperties.forEach(function(messageProp){
1035
- webshims.defineNodeNamesProperty(['fieldset', 'output', 'button'], messageProp, {
1036
- prop: {
1037
- value: '',
1038
- writeable: false
1039
- }
1040
- });
1041
- ['input', 'select', 'textarea'].forEach(function(nodeName){
1042
- var desc = webshims.defineNodeNameProperty(nodeName, messageProp, {
1043
- prop: {
1044
- get: function(){
1045
- var elem = this;
1046
- var message = '';
1047
- if(!$.prop(elem, 'willValidate')){
1048
- return message;
1049
- }
1050
-
1051
- var validity = $.prop(elem, 'validity') || {valid: 1};
1052
-
1053
- if(validity.valid){return message;}
1054
- message = webshims.getContentValidationMessage(elem, validity);
1055
-
1056
- if(message){return message;}
1057
-
1058
- if(validity.customError && elem.nodeName){
1059
- message = (Modernizr.formvalidation && !webshims.bugs.bustedValidity && desc.prop._supget) ? desc.prop._supget.call(elem) : webshims.data(elem, 'customvalidationMessage');
1060
- if(message){return message;}
1061
- }
1062
- $.each(validity, function(name, prop){
1063
- if(name == 'valid' || !prop){return;}
1064
-
1065
- message = webshims.createValidationMessage(elem, name);
1066
- if(message){
1067
- return false;
1068
- }
1069
- });
1070
- return message || '';
1071
- },
1072
- writeable: false
1073
- }
1074
- });
1075
- });
1076
-
1077
- });
1078
- });jQuery.webshims.register('form-datalist', function($, webshims, window, document, undefined){
1079
- var doc = document;
1080
-
1081
- /*
1082
- * implement propType "element" currently only used for list-attribute (will be moved to dom-extend, if needed)
1083
- */
1084
- webshims.propTypes.element = function(descs){
1085
- webshims.createPropDefault(descs, 'attr');
1086
- if(descs.prop){return;}
1087
- descs.prop = {
1088
- get: function(){
1089
- var elem = descs.attr.get.call(this);
1090
- if(elem){
1091
- elem = document.getElementById(elem);
1092
- if(elem && descs.propNodeName && !$.nodeName(elem, descs.propNodeName)){
1093
- elem = null;
1094
- }
1095
- }
1096
- return elem || null;
1097
- },
1098
- writeable: false
1099
- };
1100
- };
1101
-
1102
-
1103
- /*
1104
- * Implements datalist element and list attribute
1105
- */
1106
-
1107
- (function(){
1108
- var formsCFG = $.webshims.cfg.forms;
1109
- var listSupport = Modernizr.input.list;
1110
- if(listSupport && !formsCFG.customDatalist){return;}
1111
-
1112
- var initializeDatalist = function(){
1113
-
1114
-
1115
- if(!listSupport){
1116
- webshims.defineNodeNameProperty('datalist', 'options', {
1117
- prop: {
1118
- writeable: false,
1119
- get: function(){
1120
- var elem = this;
1121
- var select = $('select', elem);
1122
- var options;
1123
- if(select[0]){
1124
- options = select[0].options;
1125
- } else {
1126
- options = $('option', elem).get();
1127
- if(options.length){
1128
- webshims.warn('you should wrap your option-elements for a datalist in a select element to support IE and other old browsers.');
1129
- }
1130
- }
1131
- return options;
1132
- }
1133
- }
1134
- });
1135
- }
1136
-
1137
- var inputListProto = {
1138
- //override autocomplete
1139
- autocomplete: {
1140
- attr: {
1141
- get: function(){
1142
- var elem = this;
1143
- var data = $.data(elem, 'datalistWidget');
1144
- if(data){
1145
- return data._autocomplete;
1146
- }
1147
- return ('autocomplete' in elem) ? elem.autocomplete : elem.getAttribute('autocomplete');
1148
- },
1149
- set: function(value){
1150
- var elem = this;
1151
- var data = $.data(elem, 'datalistWidget');
1152
- if(data){
1153
- data._autocomplete = value;
1154
- if(value == 'off'){
1155
- data.hideList();
1156
- }
1157
- } else {
1158
- if('autocomplete' in elem){
1159
- elem.autocomplete = value;
1160
- } else {
1161
- elem.setAttribute('autocomplete', value);
1162
- }
1163
- }
1164
- }
1165
- }
1166
- }
1167
- };
1168
-
1169
- // if(formsCFG.customDatalist && (!listSupport || !('selectedOption') in $('<input />')[0])){
1170
- // //currently not supported x-browser (FF4 has not implemented and is not polyfilled )
1171
- // inputListProto.selectedOption = {
1172
- // prop: {
1173
- // writeable: false,
1174
- // get: function(){
1175
- // var elem = this;
1176
- // var list = $.prop(elem, 'list');
1177
- // var ret = null;
1178
- // var value, options;
1179
- // if(!list){return ret;}
1180
- // value = $.prop(elem, 'value');
1181
- // if(!value){return ret;}
1182
- // options = $.prop(list, 'options');
1183
- // if(!options.length){return ret;}
1184
- // $.each(options, function(i, option){
1185
- // if(value == $.prop(option, 'value')){
1186
- // ret = option;
1187
- // return false;
1188
- // }
1189
- // });
1190
- // return ret;
1191
- // }
1192
- // }
1193
- // };
1194
- // }
1195
-
1196
- if(!listSupport){
1197
- inputListProto['list'] = {
1198
- attr: {
1199
- get: function(){
1200
- var val = webshims.contentAttr(this, 'list');
1201
- return (val == null) ? undefined : val;
1202
- },
1203
- set: function(value){
1204
- var elem = this;
1205
- webshims.contentAttr(elem, 'list', value);
1206
- webshims.objectCreate(shadowListProto, undefined, {input: elem, id: value, datalist: $.prop(elem, 'list')});
1207
- }
1208
- },
1209
- initAttr: true,
1210
- reflect: true,
1211
- propType: 'element',
1212
- propNodeName: 'datalist'
1213
- };
1214
- } else {
1215
- //options only return options, if option-elements are rooted: but this makes this part of HTML5 less backwards compatible
1216
- if(!($('<datalist><select><option></option></select></datalist>').prop('options') || []).length ){
1217
- webshims.defineNodeNameProperty('datalist', 'options', {
1218
- prop: {
1219
- writeable: false,
1220
- get: function(){
1221
- var options = this.options || [];
1222
- if(!options.length){
1223
- var elem = this;
1224
- var select = $('select', elem);
1225
- if(select[0] && select[0].options && select[0].options.length){
1226
- options = select[0].options;
1227
- }
1228
- }
1229
- return options;
1230
- }
1231
- }
1232
- });
1233
- }
1234
- inputListProto['list'] = {
1235
- attr: {
1236
- get: function(){
1237
- var val = webshims.contentAttr(this, 'list');
1238
- if(val != null){
1239
- this.removeAttribute('list');
1240
- } else {
1241
- val = $.data(this, 'datalistListAttr');
1242
- }
1243
-
1244
- return (val == null) ? undefined : val;
1245
- },
1246
- set: function(value){
1247
- var elem = this;
1248
- $.data(elem, 'datalistListAttr', value);
1249
- webshims.objectCreate(shadowListProto, undefined, {input: elem, id: value, datalist: $.prop(elem, 'list')});
1250
- }
1251
- },
1252
- initAttr: true,
1253
- reflect: true,
1254
- propType: 'element',
1255
- propNodeName: 'datalist'
1256
- };
1257
- }
1258
-
1259
-
1260
- webshims.defineNodeNameProperties('input', inputListProto);
1261
-
1262
- if($.event.customEvent){
1263
- $.event.customEvent.updateDatalist = true;
1264
- $.event.customEvent.updateInput = true;
1265
- $.event.customEvent.datalistselect = true;
1266
- }
1267
- webshims.addReady(function(context, contextElem){
1268
- contextElem
1269
- .filter('datalist > select, datalist, datalist > option, datalist > select > option')
1270
- .closest('datalist')
1271
- .triggerHandler('updateDatalist')
1272
- ;
1273
-
1274
- });
1275
-
1276
-
1277
- };
1278
-
1279
-
1280
- /*
1281
- * ShadowList
1282
- */
1283
- var listidIndex = 0;
1284
-
1285
- var noDatalistSupport = {
1286
- submit: 1,
1287
- button: 1,
1288
- reset: 1,
1289
- hidden: 1,
1290
-
1291
- //ToDo
1292
- range: 1,
1293
- date: 1
1294
- };
1295
- var lteie6 = ($.browser.msie && parseInt($.browser.version, 10) < 7);
1296
- var globStoredOptions = {};
1297
- var getStoredOptions = function(name){
1298
- if(!name){return [];}
1299
- if(globStoredOptions[name]){
1300
- return globStoredOptions[name];
1301
- }
1302
- var data;
1303
- try {
1304
- data = JSON.parse(localStorage.getItem('storedDatalistOptions'+name));
1305
- } catch(e){}
1306
- globStoredOptions[name] = data || [];
1307
- return data || [];
1308
- };
1309
- var storeOptions = function(name, val){
1310
- if(!name){return;}
1311
- val = val || [];
1312
- try {
1313
- localStorage.setItem( 'storedDatalistOptions'+name, JSON.stringify(val) );
1314
- } catch(e){}
1315
- };
1316
-
1317
- var getText = function(elem){
1318
- return (elem.textContent || elem.innerText || $.text([ elem ]) || '');
1319
- };
1320
-
1321
- var shadowListProto = {
1322
- _create: function(opts){
1323
-
1324
- if(noDatalistSupport[$.prop(opts.input, 'type')]){return;}
1325
- var datalist = opts.datalist;
1326
- var data = $.data(opts.input, 'datalistWidget');
1327
- if(datalist && data && data.datalist !== datalist){
1328
- data.datalist = datalist;
1329
- data.id = opts.id;
1330
-
1331
- data.shadowList.prop('className', 'datalist-polyfill '+ (data.datalist.className || '') + ' '+ data.datalist.id +'-shadowdom');
1332
- if(formsCFG.positionDatalist){
1333
- data.shadowList.insertAfter(opts.input);
1334
- } else {
1335
- data.shadowList.appendTo('body');
1336
- }
1337
- $(data.datalist)
1338
- .unbind('updateDatalist.datalistWidget')
1339
- .bind('updateDatalist.datalistWidget', $.proxy(data, '_resetListCached'))
1340
- ;
1341
- data._resetListCached();
1342
- return;
1343
- } else if(!datalist){
1344
- if(data){
1345
- data.destroy();
1346
- }
1347
- return;
1348
- } else if(data && data.datalist === datalist){
1349
- return;
1350
- }
1351
- listidIndex++;
1352
- var that = this;
1353
- this.hideList = $.proxy(that, 'hideList');
1354
- this.timedHide = function(){
1355
- clearTimeout(that.hideTimer);
1356
- that.hideTimer = setTimeout(that.hideList, 9);
1357
- };
1358
- this.datalist = datalist;
1359
- this.id = opts.id;
1360
- this.hasViewableData = true;
1361
- this._autocomplete = $.attr(opts.input, 'autocomplete');
1362
- $.data(opts.input, 'datalistWidget', this);
1363
- this.shadowList = $('<div class="datalist-polyfill '+ (this.datalist.className || '') + ' '+ this.datalist.id +'-shadowdom' +'" />');
1364
-
1365
- if(formsCFG.positionDatalist || $(opts.input).hasClass('position-datalist')){
1366
- this.shadowList.insertAfter(opts.input);
1367
- } else {
1368
- this.shadowList.appendTo('body');
1369
- }
1370
-
1371
- this.index = -1;
1372
- this.input = opts.input;
1373
- this.arrayOptions = [];
1374
-
1375
- this.shadowList
1376
- .delegate('li', 'mouseenter.datalistWidget mousedown.datalistWidget click.datalistWidget', function(e){
1377
- var items = $('li:not(.hidden-item)', that.shadowList);
1378
- var select = (e.type == 'mousedown' || e.type == 'click');
1379
- that.markItem(items.index(e.currentTarget), select, items);
1380
- if(e.type == 'click'){
1381
- that.hideList();
1382
- if(formsCFG.customDatalist){
1383
- $(opts.input).trigger('datalistselect');
1384
- }
1385
- }
1386
- return (e.type != 'mousedown');
1387
- })
1388
- .bind('focusout', this.timedHide)
1389
- ;
1390
-
1391
- opts.input.setAttribute('autocomplete', 'off');
1392
-
1393
- $(opts.input)
1394
- .attr({
1395
- //role: 'combobox',
1396
- 'aria-haspopup': 'true'
1397
- })
1398
- .bind('input.datalistWidget', function(){
1399
- if(!that.triggeredByDatalist){
1400
- that.changedValue = false;
1401
- that.showHideOptions();
1402
- }
1403
- })
1404
-
1405
- .bind('keydown.datalistWidget', function(e){
1406
- var keyCode = e.keyCode;
1407
- var activeItem;
1408
- var items;
1409
- if(keyCode == 40 && !that.showList()){
1410
- that.markItem(that.index + 1, true);
1411
- return false;
1412
- }
1413
-
1414
- if(!that.isListVisible){return;}
1415
-
1416
-
1417
- if(keyCode == 38){
1418
- that.markItem(that.index - 1, true);
1419
- return false;
1420
- }
1421
- if(!e.shiftKey && (keyCode == 33 || keyCode == 36)){
1422
- that.markItem(0, true);
1423
- return false;
1424
- }
1425
- if(!e.shiftKey && (keyCode == 34 || keyCode == 35)){
1426
- items = $('li:not(.hidden-item)', that.shadowList);
1427
- that.markItem(items.length - 1, true, items);
1428
- return false;
1429
- }
1430
- if(keyCode == 13 || keyCode == 27){
1431
- if (keyCode == 13){
1432
- activeItem = $('li.active-item:not(.hidden-item)', that.shadowList);
1433
- that.changeValue( $('li.active-item:not(.hidden-item)', that.shadowList) );
1434
- }
1435
- that.hideList();
1436
- if(formsCFG.customDatalist && activeItem && activeItem[0]){
1437
- $(opts.input).trigger('datalistselect');
1438
- }
1439
- return false;
1440
- }
1441
- })
1442
- .bind('focus.datalistWidget', function(){
1443
- if($(this).hasClass('list-focus')){
1444
- that.showList();
1445
- }
1446
- })
1447
- .bind('mousedown.datalistWidget', function(){
1448
- if($(this).is(':focus')){
1449
- that.showList();
1450
- }
1451
- })
1452
- .bind('blur.datalistWidget', this.timedHide)
1453
- ;
1454
-
1455
-
1456
- $(this.datalist)
1457
- .unbind('updateDatalist.datalistWidget')
1458
- .bind('updateDatalist.datalistWidget', $.proxy(this, '_resetListCached'))
1459
- ;
1460
-
1461
- this._resetListCached();
1462
-
1463
- if(opts.input.form && (opts.input.name || opts.input.id)){
1464
- $(opts.input.form).bind('submit.datalistWidget'+opts.input.id, function(){
1465
- if(!$(opts.input).hasClass('no-datalist-cache') && that._autocomplete != 'off'){
1466
- var val = $.prop(opts.input, 'value');
1467
- var name = (opts.input.name || opts.input.id) + $.prop(opts.input, 'type');
1468
- if(!that.storedOptions){
1469
- that.storedOptions = getStoredOptions( name );
1470
- }
1471
- if(val && that.storedOptions.indexOf(val) == -1){
1472
- that.storedOptions.push(val);
1473
- storeOptions(name, that.storedOptions );
1474
- }
1475
- }
1476
- });
1477
- }
1478
- $(window).bind('unload.datalist'+this.id+' beforeunload.datalist'+this.id, function(){
1479
- that.destroy();
1480
- });
1481
- },
1482
- destroy: function(){
1483
- var autocomplete = $.attr(this.input, 'autocomplete');
1484
- $(this.input)
1485
- .unbind('.datalistWidget')
1486
- .removeData('datalistWidget')
1487
- ;
1488
- this.shadowList.remove();
1489
- $(document).unbind('.datalist'+this.id);
1490
- $(window).unbind('.datalist'+this.id);
1491
- if(this.input.form && this.input.id){
1492
- $(this.input.form).unbind('submit.datalistWidget'+this.input.id);
1493
- }
1494
- this.input.removeAttribute('aria-haspopup');
1495
- if(autocomplete === undefined){
1496
- this.input.removeAttribute('autocomplete');
1497
- } else {
1498
- $(this.input).attr('autocomplete', autocomplete);
1499
- }
1500
- },
1501
- _resetListCached: function(e){
1502
- var that = this;
1503
- var forceShow;
1504
- this.needsUpdate = true;
1505
- this.lastUpdatedValue = false;
1506
- this.lastUnfoundValue = '';
1507
-
1508
- if(!this.updateTimer){
1509
- if(window.QUnit || (forceShow = (e && document.activeElement == that.input))){
1510
- that.updateListOptions(forceShow);
1511
- } else {
1512
- webshims.ready('WINDOWLOAD', function(){
1513
- that.updateTimer = setTimeout(function(){
1514
- that.updateListOptions();
1515
- that = null;
1516
- listidIndex = 1;
1517
- }, 200 + (100 * listidIndex));
1518
- });
1519
- }
1520
- }
1521
- },
1522
- updateListOptions: function(_forceShow){
1523
- this.needsUpdate = false;
1524
- clearTimeout(this.updateTimer);
1525
- this.updateTimer = false;
1526
- this.shadowList
1527
- .css({
1528
- fontSize: $.css(this.input, 'fontSize'),
1529
- fontFamily: $.css(this.input, 'fontFamily')
1530
- })
1531
- ;
1532
- this.searchStart = formsCFG.customDatalist && $(this.input).hasClass('search-start');
1533
-
1534
- var list = [];
1535
-
1536
- var values = [];
1537
- var allOptions = [];
1538
- var rElem, rItem, rOptions, rI, rLen, item;
1539
- for(rOptions = $.prop(this.datalist, 'options'), rI = 0, rLen = rOptions.length; rI < rLen; rI++){
1540
- rElem = rOptions[rI];
1541
- if(rElem.disabled){return;}
1542
- rItem = {
1543
- value: $(rElem).val() || '',
1544
- text: $.trim($.attr(rElem, 'label') || getText(rElem)),
1545
- className: rElem.className || '',
1546
- style: $.attr(rElem, 'style') || ''
1547
- };
1548
- if(!rItem.text){
1549
- rItem.text = rItem.value;
1550
- } else if(rItem.text != rItem.value){
1551
- rItem.className += ' different-label-value';
1552
- }
1553
- values[rI] = rItem.value;
1554
- allOptions[rI] = rItem;
1555
- }
1556
-
1557
- if(!this.storedOptions){
1558
- this.storedOptions = ($(this.input).hasClass('no-datalist-cache') || this._autocomplete == 'off') ? [] : getStoredOptions((this.input.name || this.input.id) + $.prop(this.input, 'type'));
1559
- }
1560
-
1561
- this.storedOptions.forEach(function(val, i){
1562
- if(values.indexOf(val) == -1){
1563
- allOptions.push({value: val, text: val, className: 'stored-suggest', style: ''});
1564
- }
1565
- });
1566
-
1567
- for(rI = 0, rLen = allOptions.length; rI < rLen; rI++){
1568
- item = allOptions[rI];
1569
- list[rI] = '<li class="'+ item.className +'" style="'+ item.style +'" tabindex="-1" role="listitem"><span class="option-label">'+ item.text +'</span> <span class="option-value">'+item.value+'</span></li>';
1570
- }
1571
-
1572
- this.arrayOptions = allOptions;
1573
- this.shadowList.html('<div class="datalist-outer-box"><div class="datalist-box"><ul role="list">'+ list.join("\n") +'</ul></div></div>');
1574
-
1575
- if($.fn.bgIframe && lteie6){
1576
- this.shadowList.bgIframe();
1577
- }
1578
-
1579
- if(_forceShow || this.isListVisible){
1580
- this.showHideOptions();
1581
- }
1582
- },
1583
- showHideOptions: function(_fromShowList){
1584
- var value = $.prop(this.input, 'value').toLowerCase();
1585
- //first check prevent infinite loop, second creates simple lazy optimization
1586
- if(value === this.lastUpdatedValue || (this.lastUnfoundValue && value.indexOf(this.lastUnfoundValue) === 0)){
1587
- return;
1588
- }
1589
-
1590
- this.lastUpdatedValue = value;
1591
- var found = false;
1592
- var startSearch = this.searchStart;
1593
- var lis = $('li', this.shadowList);
1594
- if(value){
1595
- this.arrayOptions.forEach(function(item, i){
1596
- var search;
1597
- if(!('lowerText' in item)){
1598
- if(item.text != item.value){
1599
- item.lowerText = item.value.toLowerCase() + item.text.toLowerCase();
1600
- } else {
1601
- item.lowerText = item.text.toLowerCase();
1602
- }
1603
- }
1604
- search = item.lowerText.indexOf(value);
1605
- search = startSearch ? !search : search !== -1;
1606
- if(search){
1607
- $(lis[i]).removeClass('hidden-item');
1608
- found = true;
1609
- } else {
1610
- $(lis[i]).addClass('hidden-item');
1611
- }
1612
- });
1613
- } else if(lis.length) {
1614
- lis.removeClass('hidden-item');
1615
- found = true;
1616
- }
1617
-
1618
- this.hasViewableData = found;
1619
- if(!_fromShowList && found){
1620
- this.showList();
1621
- }
1622
- if(!found){
1623
- this.lastUnfoundValue = value;
1624
- this.hideList();
1625
- }
1626
- },
1627
- setPos: function(){
1628
- this.shadowList.css({marginTop: 0, marginLeft: 0, marginRight: 0, marginBottom: 0});
1629
- var css = (formsCFG.positionDatalist) ? $(this.input).position() : webshims.getRelOffset(this.shadowList, this.input);
1630
- css.top += $(this.input).outerHeight();
1631
- css.width = $(this.input).outerWidth() - (parseInt(this.shadowList.css('borderLeftWidth'), 10) || 0) - (parseInt(this.shadowList.css('borderRightWidth'), 10) || 0);
1632
- this.shadowList.css({marginTop: '', marginLeft: '', marginRight: '', marginBottom: ''}).css(css);
1633
- return css;
1634
- },
1635
- showList: function(){
1636
- if(this.isListVisible){return false;}
1637
- if(this.needsUpdate){
1638
- this.updateListOptions();
1639
- }
1640
- this.showHideOptions(true);
1641
- if(!this.hasViewableData){return false;}
1642
- this.isListVisible = true;
1643
- var that = this;
1644
-
1645
- that.setPos();
1646
- that.shadowList.addClass('datalist-visible').find('li.active-item').removeClass('active-item');
1647
-
1648
- $(window).unbind('.datalist'+that.id);
1649
- $(document)
1650
- .unbind('.datalist'+that.id)
1651
- .bind('mousedown.datalist'+that.id +' focusin.datalist'+that.id, function(e){
1652
- if(e.target === that.input || that.shadowList[0] === e.target || $.contains( that.shadowList[0], e.target )){
1653
- clearTimeout(that.hideTimer);
1654
- setTimeout(function(){
1655
- clearTimeout(that.hideTimer);
1656
- }, 9);
1657
- } else {
1658
- that.timedHide();
1659
- }
1660
- })
1661
- .bind('updateshadowdom.datalist'+that.id, function(){
1662
- that.setPos();
1663
- })
1664
- ;
1665
- return true;
1666
- },
1667
- hideList: function(){
1668
- if(!this.isListVisible){return false;}
1669
- var that = this;
1670
- var triggerChange = function(e){
1671
- if(that.changedValue){
1672
- $(that.input).trigger('change');
1673
- }
1674
- that.changedValue = false;
1675
- };
1676
-
1677
- that.shadowList.removeClass('datalist-visible list-item-active');
1678
- that.index = -1;
1679
- that.isListVisible = false;
1680
- if(that.changedValue){
1681
- that.triggeredByDatalist = true;
1682
- webshims.triggerInlineForm && webshims.triggerInlineForm(that.input, 'input');
1683
- if($(that.input).is(':focus')){
1684
- $(that.input).one('blur', triggerChange);
1685
- } else {
1686
- triggerChange();
1687
- }
1688
- that.triggeredByDatalist = false;
1689
- }
1690
- $(document).unbind('.datalist'+that.id);
1691
- $(window)
1692
- .unbind('.datalist'+that.id)
1693
- .one('resize.datalist'+that.id, function(){
1694
- that.shadowList.css({top: 0, left: 0});
1695
- })
1696
- ;
1697
- return true;
1698
- },
1699
- scrollIntoView: function(elem){
1700
- var ul = $('ul', this.shadowList);
1701
- var div = $('div.datalist-box', this.shadowList);
1702
- var elemPos = elem.position();
1703
- var containerHeight;
1704
- elemPos.top -= (parseInt(ul.css('paddingTop'), 10) || 0) + (parseInt(ul.css('marginTop'), 10) || 0) + (parseInt(ul.css('borderTopWidth'), 10) || 0);
1705
- if(elemPos.top < 0){
1706
- div.scrollTop( div.scrollTop() + elemPos.top - 2);
1707
- return;
1708
- }
1709
- elemPos.top += elem.outerHeight();
1710
- containerHeight = div.height();
1711
- if(elemPos.top > containerHeight){
1712
- div.scrollTop( div.scrollTop() + (elemPos.top - containerHeight) + 2);
1713
- }
1714
- },
1715
- changeValue: function(activeItem){
1716
- if(!activeItem[0]){return;}
1717
- var newValue = $('span.option-value', activeItem).text();
1718
- var oldValue = $.prop(this.input, 'value');
1719
- if(newValue != oldValue){
1720
- $(this.input)
1721
- .prop('value', newValue)
1722
- .triggerHandler('updateInput')
1723
- ;
1724
- this.changedValue = true;
1725
- }
1726
- },
1727
- markItem: function(index, doValue, items){
1728
- var activeItem;
1729
- var goesUp;
1730
-
1731
- items = items || $('li:not(.hidden-item)', this.shadowList);
1732
- if(!items.length){return;}
1733
- if(index < 0){
1734
- index = items.length - 1;
1735
- } else if(index >= items.length){
1736
- index = 0;
1737
- }
1738
- items.removeClass('active-item');
1739
- this.shadowList.addClass('list-item-active');
1740
- activeItem = items.filter(':eq('+ index +')').addClass('active-item');
1741
-
1742
- if(doValue){
1743
- this.changeValue(activeItem);
1744
- this.scrollIntoView(activeItem);
1745
- }
1746
- this.index = index;
1747
- }
1748
- };
1749
-
1750
- //init datalist update
1751
- initializeDatalist();
1752
- })();
1753
-
1
+ jQuery.webshims.register('form-extend', function($, webshims, window, doc, undefined, options){
2
+ "use strict";
3
+ var Modernizr = window.Modernizr;
4
+ var modernizrInputTypes = Modernizr.inputtypes;
5
+ if(!Modernizr.formvalidation || webshims.bugs.bustedValidity){return;}
6
+ var typeModels = webshims.inputTypes;
7
+ var validityRules = {};
8
+
9
+ webshims.addInputType = function(type, obj){
10
+ typeModels[type] = obj;
11
+ };
12
+
13
+ webshims.addValidityRule = function(type, fn){
14
+ validityRules[type] = fn;
15
+ };
16
+
17
+ webshims.addValidityRule('typeMismatch',function (input, val, cache, validityState){
18
+ if(val === ''){return false;}
19
+ var ret = validityState.typeMismatch;
20
+ if(!('type' in cache)){
21
+ cache.type = (input[0].getAttribute('type') || '').toLowerCase();
22
+ }
23
+
24
+ if(typeModels[cache.type] && typeModels[cache.type].mismatch){
25
+ ret = typeModels[cache.type].mismatch(val, input);
26
+ }
27
+ return ret;
28
+ });
29
+
30
+ var overrideNativeMessages = options.overrideMessages;
31
+
32
+ var overrideValidity = (!modernizrInputTypes.number || !modernizrInputTypes.time || !modernizrInputTypes.range || overrideNativeMessages);
33
+ var validityProps = ['customError','typeMismatch','rangeUnderflow','rangeOverflow','stepMismatch','tooLong','patternMismatch','valueMissing','valid'];
34
+
35
+ var validityChanger = (overrideNativeMessages)? ['value', 'checked'] : ['value'];
36
+ var validityElements = [];
37
+ var testValidity = function(elem, init){
38
+ if(!elem){return;}
39
+ var type = (elem.getAttribute && elem.getAttribute('type') || elem.type || '').toLowerCase();
40
+
41
+ if(!overrideNativeMessages && !typeModels[type]){
42
+ return;
43
+ }
44
+
45
+ if(overrideNativeMessages && !init && type == 'radio' && elem.name){
46
+ $(doc.getElementsByName( elem.name )).each(function(){
47
+ $.prop(this, 'validity');
48
+ });
49
+ } else {
50
+ $.prop(elem, 'validity');
51
+ }
52
+ };
53
+
54
+ var oldSetCustomValidity = {};
55
+ ['input', 'textarea', 'select'].forEach(function(name){
56
+ var desc = webshims.defineNodeNameProperty(name, 'setCustomValidity', {
57
+ prop: {
58
+ value: function(error){
59
+ error = error+'';
60
+ var elem = (name == 'input') ? $(this).getNativeElement()[0] : this;
61
+ desc.prop._supvalue.call(elem, error);
62
+
63
+ if(webshims.bugs.validationMessage){
64
+ webshims.data(elem, 'customvalidationMessage', error);
65
+ }
66
+ if(overrideValidity){
67
+ webshims.data(elem, 'hasCustomError', !!(error));
68
+ testValidity(elem);
69
+ }
70
+ }
71
+ }
72
+ });
73
+ oldSetCustomValidity[name] = desc.prop._supvalue;
74
+ });
75
+
76
+
77
+ if(overrideValidity || overrideNativeMessages){
78
+ validityChanger.push('min');
79
+ validityChanger.push('max');
80
+ validityChanger.push('step');
81
+ validityElements.push('input');
82
+ }
83
+ if(overrideNativeMessages){
84
+ validityChanger.push('required');
85
+ validityChanger.push('pattern');
86
+ validityElements.push('select');
87
+ validityElements.push('textarea');
88
+ }
89
+
90
+ if(overrideValidity){
91
+ var stopValidity;
92
+ validityElements.forEach(function(nodeName){
93
+
94
+ var oldDesc = webshims.defineNodeNameProperty(nodeName, 'validity', {
95
+ prop: {
96
+ get: function(){
97
+ if(stopValidity){return;}
98
+ var elem = (nodeName == 'input') ? $(this).getNativeElement()[0] : this;
99
+
100
+ var validity = oldDesc.prop._supget.call(elem);
101
+
102
+ if(!validity){
103
+ return validity;
104
+ }
105
+ var validityState = {};
106
+ validityProps.forEach(function(prop){
107
+ validityState[prop] = validity[prop];
108
+ });
109
+
110
+ if( !$.prop(elem, 'willValidate') ){
111
+ return validityState;
112
+ }
113
+ stopValidity = true;
114
+ var jElm = $(elem),
115
+ cache = {type: (elem.getAttribute && elem.getAttribute('type') || '').toLowerCase(), nodeName: (elem.nodeName || '').toLowerCase()},
116
+ val = jElm.val(),
117
+ customError = !!(webshims.data(elem, 'hasCustomError')),
118
+ setCustomMessage
119
+ ;
120
+ stopValidity = false;
121
+ validityState.customError = customError;
122
+
123
+ if( validityState.valid && validityState.customError ){
124
+ validityState.valid = false;
125
+ } else if(!validityState.valid) {
126
+ var allFalse = true;
127
+ $.each(validityState, function(name, prop){
128
+ if(prop){
129
+ allFalse = false;
130
+ return false;
131
+ }
132
+ });
133
+
134
+ if(allFalse){
135
+ validityState.valid = true;
136
+ }
137
+
138
+ }
139
+
140
+ $.each(validityRules, function(rule, fn){
141
+ validityState[rule] = fn(jElm, val, cache, validityState);
142
+ if( validityState[rule] && (validityState.valid || !setCustomMessage) && (overrideNativeMessages || (typeModels[cache.type] && typeModels[cache.type].mismatch)) ) {
143
+ oldSetCustomValidity[nodeName].call(elem, webshims.createValidationMessage(elem, rule));
144
+ validityState.valid = false;
145
+ setCustomMessage = true;
146
+ }
147
+ });
148
+ if(validityState.valid){
149
+ oldSetCustomValidity[nodeName].call(elem, '');
150
+ webshims.data(elem, 'hasCustomError', false);
151
+ } else if(overrideNativeMessages && !setCustomMessage && !customError){
152
+ $.each(validityState, function(name, prop){
153
+ if(name !== 'valid' && prop){
154
+ oldSetCustomValidity[nodeName].call(elem, webshims.createValidationMessage(elem, name));
155
+ return false;
156
+ }
157
+ });
158
+ }
159
+ return validityState;
160
+ },
161
+ writeable: false
162
+
163
+ }
164
+ });
165
+ });
166
+
167
+ validityChanger.forEach(function(prop){
168
+ webshims.onNodeNamesPropertyModify(validityElements, prop, function(s){
169
+ testValidity(this);
170
+ });
171
+ });
172
+
173
+ if(doc.addEventListener){
174
+ var inputThrottle;
175
+ var testPassValidity = function(e){
176
+ if(!('form' in e.target)){return;}
177
+ var form = e.target.form;
178
+ clearTimeout(inputThrottle);
179
+ testValidity(e.target);
180
+ if(form && overrideNativeMessages){
181
+ $('input', form).each(function(){
182
+ if(this.type == 'password'){
183
+ testValidity(this);
184
+ }
185
+ });
186
+ }
187
+ };
188
+
189
+ doc.addEventListener('change', testPassValidity, true);
190
+
191
+ if(overrideNativeMessages){
192
+ doc.addEventListener('blur', testPassValidity, true);
193
+ doc.addEventListener('keydown', function(e){
194
+ if(e.keyCode != 13){return;}
195
+ testPassValidity(e);
196
+ }, true);
197
+ }
198
+
199
+ doc.addEventListener('input', function(e){
200
+ clearTimeout(inputThrottle);
201
+ inputThrottle = setTimeout(function(){
202
+ testValidity(e.target);
203
+ }, 290);
204
+ }, true);
205
+ }
206
+
207
+ var validityElementsSel = validityElements.join(',');
208
+
209
+ webshims.addReady(function(context, elem){
210
+ $(validityElementsSel, context).add(elem.filter(validityElementsSel)).each(function(){
211
+ $.prop(this, 'validity');
212
+ });
213
+ });
214
+
215
+
216
+ if(overrideNativeMessages){
217
+ webshims.ready('DOM form-message', function(){
218
+ webshims.activeLang({
219
+ register: 'form-core',
220
+ callback: function(){
221
+ $('input, select, textarea')
222
+ .getNativeElement()
223
+ .each(function(){
224
+ if(webshims.data(this, 'hasCustomError')){return;}
225
+ var elem = this;
226
+ var validity = $.prop(elem, 'validity') || {valid: true};
227
+ var nodeName;
228
+ if(validity.valid){return;}
229
+ nodeName = (elem.nodeName || '').toLowerCase();
230
+ $.each(validity, function(name, prop){
231
+ if(name !== 'valid' && prop){
232
+ oldSetCustomValidity[nodeName].call(elem, webshims.createValidationMessage(elem, name));
233
+ return false;
234
+ }
235
+ });
236
+ })
237
+ ;
238
+ }
239
+ });
240
+ });
241
+ }
242
+
243
+ } //end: overrideValidity
244
+
245
+ webshims.defineNodeNameProperty('input', 'type', {
246
+ prop: {
247
+ get: function(){
248
+ var elem = this;
249
+ var type = (elem.getAttribute('type') || '').toLowerCase();
250
+ return (webshims.inputTypes[type]) ? type : elem.type;
251
+ }
252
+ }
253
+ });
254
+
255
+
256
+ });//additional tests for partial implementation of forms features
257
+ (function($){
258
+ "use strict";
259
+ var Modernizr = window.Modernizr;
260
+ var webshims = $.webshims;
261
+ var bugs = webshims.bugs;
262
+ var form = $('<form action="#" style="width: 1px; height: 1px; overflow: hidden;"><select name="b" required="" /><input required="" name="a" /></form>');
263
+ var testRequiredFind = function(){
264
+ if(form[0].querySelector){
265
+ try {
266
+ bugs.findRequired = !(form[0].querySelector('select:required'));
267
+ } catch(er){
268
+ bugs.findRequired = false;
269
+ }
270
+ }
271
+ };
272
+ var inputElem = $('input', form).eq(0);
273
+ var onDomextend = function(fn){
274
+ webshims.loader.loadList(['dom-extend']);
275
+ webshims.ready('dom-extend', fn);
276
+ };
277
+
278
+ bugs.findRequired = false;
279
+ bugs.validationMessage = false;
280
+
281
+ webshims.capturingEventPrevented = function(e){
282
+ if(!e._isPolyfilled){
283
+ var isDefaultPrevented = e.isDefaultPrevented;
284
+ var preventDefault = e.preventDefault;
285
+ e.preventDefault = function(){
286
+ clearTimeout($.data(e.target, e.type + 'DefaultPrevented'));
287
+ $.data(e.target, e.type + 'DefaultPrevented', setTimeout(function(){
288
+ $.removeData(e.target, e.type + 'DefaultPrevented');
289
+ }, 30));
290
+ return preventDefault.apply(this, arguments);
291
+ };
292
+ e.isDefaultPrevented = function(){
293
+ return !!(isDefaultPrevented.apply(this, arguments) || $.data(e.target, e.type + 'DefaultPrevented') || false);
294
+ };
295
+ e._isPolyfilled = true;
296
+ }
297
+ };
298
+
299
+ if(!Modernizr.formvalidation || bugs.bustedValidity){
300
+ testRequiredFind();
301
+ return;
302
+ }
303
+
304
+ //create delegatable events
305
+ webshims.capturingEvents(['input']);
306
+ webshims.capturingEvents(['invalid'], true);
307
+
308
+ if(window.opera || window.testGoodWithFix){
309
+
310
+ form.appendTo('head');
311
+
312
+ testRequiredFind();
313
+ bugs.validationMessage = !(inputElem.prop('validationMessage'));
314
+
315
+ webshims.reTest(['form-extend', 'form-message']);
316
+
317
+ form.remove();
318
+
319
+ $(function(){
320
+ onDomextend(function(){
321
+
322
+ //Opera shows native validation bubbles in case of input.checkValidity()
323
+ // Opera 11.6/12 hasn't fixed this issue right, it's buggy
324
+ var preventDefault = function(e){
325
+ e.preventDefault();
326
+ };
327
+
328
+ ['form', 'input', 'textarea', 'select'].forEach(function(name){
329
+ var desc = webshims.defineNodeNameProperty(name, 'checkValidity', {
330
+ prop: {
331
+ value: function(){
332
+ if (!webshims.fromSubmit) {
333
+ $(this).on('invalid.checkvalidity', preventDefault);
334
+ }
335
+
336
+ webshims.fromCheckValidity = true;
337
+ var ret = desc.prop._supvalue.apply(this, arguments);
338
+ if (!webshims.fromSubmit) {
339
+ $(this).unbind('invalid.checkvalidity', preventDefault);
340
+ }
341
+ webshims.fromCheckValidity = false;
342
+ return ret;
343
+ }
344
+ }
345
+ });
346
+ });
347
+
348
+ });
349
+ });
350
+ }
351
+
352
+ if($.browser.webkit && !webshims.bugs.bustedValidity){
353
+ (function(){
354
+ var elems = /^(?:textarea|input)$/i;
355
+ var form = false;
356
+
357
+ document.addEventListener('contextmenu', function(e){
358
+ if(elems.test( e.target.nodeName || '') && (form = e.target.form)){
359
+ setTimeout(function(){
360
+ form = false;
361
+ }, 1);
362
+ }
363
+ }, false);
364
+
365
+ $(window).on('invalid', function(e){
366
+ if(e.originalEvent && form && form == e.target.form){
367
+ e.wrongWebkitInvalid = true;
368
+ e.stopImmediatePropagation();
369
+ }
370
+ });
371
+ })();
372
+ }
373
+ })(jQuery);
374
+
375
+ jQuery.webshims.register('form-core', function($, webshims, window, document, undefined, options){
376
+ "use strict";
377
+
378
+ var groupTypes = {radio: 1};
379
+ var checkTypes = {checkbox: 1, radio: 1};
380
+ var emptyJ = $([]);
381
+ var bugs = webshims.bugs;
382
+ var getGroupElements = function(elem){
383
+ elem = $(elem);
384
+ var name;
385
+ var form;
386
+ var ret = emptyJ;
387
+ if(groupTypes[elem[0].type]){
388
+ form = elem.prop('form');
389
+ name = elem[0].name;
390
+ if(!name){
391
+ ret = elem;
392
+ } else if(form){
393
+ ret = $(form[name]);
394
+ } else {
395
+ ret = $(document.getElementsByName(name)).filter(function(){
396
+ return !$.prop(this, 'form');
397
+ });
398
+ }
399
+ ret = ret.filter('[type="radio"]');
400
+ }
401
+ return ret;
402
+ };
403
+
404
+ var getContentValidationMessage = webshims.getContentValidationMessage = function(elem, validity, key){
405
+ var message = $(elem).data('errormessage') || elem.getAttribute('x-moz-errormessage') || '';
406
+ if(key && message[key]){
407
+ message = message[key];
408
+ }
409
+ if(typeof message == 'object'){
410
+ validity = validity || $.prop(elem, 'validity') || {valid: 1};
411
+ if(!validity.valid){
412
+ $.each(validity, function(name, prop){
413
+ if(prop && name != 'valid' && message[name]){
414
+ message = message[name];
415
+ return false;
416
+ }
417
+ });
418
+ }
419
+ }
420
+
421
+ if(typeof message == 'object'){
422
+ message = message.defaultMessage;
423
+ }
424
+ return message || '';
425
+ };
426
+
427
+ /*
428
+ * Selectors for all browsers
429
+ */
430
+ var rangeTypes = {number: 1, range: 1, date: 1/*, time: 1, 'datetime-local': 1, datetime: 1, month: 1, week: 1*/};
431
+ var hasInvalid = function(elem){
432
+ var ret = false;
433
+ $($.prop(elem, 'elements')).each(function(){
434
+ ret = $(this).is(':invalid');
435
+ if(ret){
436
+ return false;
437
+ }
438
+ });
439
+ return ret;
440
+ };
441
+ $.extend($.expr[":"], {
442
+ "valid-element": function(elem){
443
+ return $.nodeName(elem, 'form') ? !hasInvalid(elem) :!!($.prop(elem, 'willValidate') && isValid(elem));
444
+ },
445
+ "invalid-element": function(elem){
446
+ return $.nodeName(elem, 'form') ? hasInvalid(elem) : !!($.prop(elem, 'willValidate') && !isValid(elem));
447
+ },
448
+ "required-element": function(elem){
449
+ return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required'));
450
+ },
451
+ "user-error": function(elem){
452
+ return ($.prop(elem, 'willValidate') && $(elem).hasClass('user-error'));
453
+ },
454
+ "optional-element": function(elem){
455
+ return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required') === false);
456
+ },
457
+ "in-range": function(elem){
458
+ if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
459
+ return false;
460
+ }
461
+ var val = $.prop(elem, 'validity');
462
+ return !!(val && !val.rangeOverflow && !val.rangeUnderflow);
463
+ },
464
+ "out-of-range": function(elem){
465
+ if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
466
+ return false;
467
+ }
468
+ var val = $.prop(elem, 'validity');
469
+ return !!(val && (val.rangeOverflow || val.rangeUnderflow));
470
+ }
471
+
472
+ });
473
+
474
+ ['valid', 'invalid', 'required', 'optional'].forEach(function(name){
475
+ $.expr[":"][name] = $.expr.filters[name+"-element"];
476
+ });
477
+
478
+
479
+ $.expr[":"].focus = function( elem ) {
480
+ try {
481
+ var doc = elem.ownerDocument;
482
+ return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus());
483
+ } catch(e){}
484
+ return false;
485
+ };
486
+
487
+ var customEvents = $.event.customEvent || {};
488
+ var isValid = function(elem){
489
+ return ($.prop(elem, 'validity') || {valid: 1}).valid;
490
+ };
491
+
492
+ if (bugs.bustedValidity || bugs.findRequired) {
493
+ (function(){
494
+ var find = $.find;
495
+ var matchesSelector = $.find.matchesSelector;
496
+
497
+ var regExp = /(\:valid|\:invalid|\:optional|\:required|\:in-range|\:out-of-range)(?=[\s\[\~\.\+\>\:\#*]|$)/ig;
498
+ var regFn = function(sel){
499
+ return sel + '-element';
500
+ };
501
+
502
+ $.find = (function(){
503
+ var slice = Array.prototype.slice;
504
+ var fn = function(sel){
505
+ var ar = arguments;
506
+ ar = slice.call(ar, 1, ar.length);
507
+ ar.unshift(sel.replace(regExp, regFn));
508
+ return find.apply(this, ar);
509
+ };
510
+ for (var i in find) {
511
+ if(find.hasOwnProperty(i)){
512
+ fn[i] = find[i];
513
+ }
514
+ }
515
+ return fn;
516
+ })();
517
+ if(!Modernizr.prefixed || Modernizr.prefixed("matchesSelector", document.documentElement)){
518
+ $.find.matchesSelector = function(node, expr){
519
+ expr = expr.replace(regExp, regFn);
520
+ return matchesSelector.call(this, node, expr);
521
+ };
522
+ }
523
+
524
+ })();
525
+ }
526
+
527
+ //ToDo needs testing
528
+ var oldAttr = $.prop;
529
+ var changeVals = {selectedIndex: 1, value: 1, checked: 1, disabled: 1, readonly: 1};
530
+ $.prop = function(elem, name, val){
531
+ var ret = oldAttr.apply(this, arguments);
532
+ if(elem && 'form' in elem && changeVals[name] && val !== undefined && $(elem).hasClass(invalidClass)){
533
+ if(isValid(elem)){
534
+ $(elem).getShadowElement().removeClass(invalidClasses);
535
+ if(name == 'checked' && val) {
536
+ getGroupElements(elem).not(elem).removeClass(invalidClasses).removeAttr('aria-invalid');
537
+ }
538
+ }
539
+ }
540
+ return ret;
541
+ };
542
+
543
+ var returnValidityCause = function(validity, elem){
544
+ var ret;
545
+ $.each(validity, function(name, value){
546
+ if(value){
547
+ ret = (name == 'customError') ? $.prop(elem, 'validationMessage') : name;
548
+ return false;
549
+ }
550
+ });
551
+ return ret;
552
+ };
553
+
554
+ var isInGroup = function(name){
555
+ var ret;
556
+ try {
557
+ ret = document.activeElement.name === name;
558
+ } catch(e){}
559
+ return ret;
560
+ };
561
+ /* form-ui-invalid/form-ui-valid are deprecated. use user-error/user-succes instead */
562
+ var invalidClass = 'user-error';
563
+ var invalidClasses = 'user-error form-ui-invalid';
564
+ var validClass = 'user-success';
565
+ var validClasses = 'user-success form-ui-valid';
566
+ var switchValidityClass = function(e){
567
+ var elem, timer;
568
+ if(!e.target){return;}
569
+ elem = $(e.target).getNativeElement()[0];
570
+ if(elem.type == 'submit' || !$.prop(elem, 'willValidate')){return;}
571
+ timer = $.data(elem, 'webshimsswitchvalidityclass');
572
+ var switchClass = function(){
573
+ if(e.type == 'focusout' && elem.type == 'radio' && isInGroup(elem.name)){return;}
574
+ var validity = $.prop(elem, 'validity');
575
+ var shadowElem = $(elem).getShadowElement();
576
+ var addClass, removeClass, trigger, generaltrigger, validityCause;
577
+
578
+ $(elem).trigger('refreshCustomValidityRules');
579
+ if(validity.valid){
580
+ if(!shadowElem.hasClass(validClass)){
581
+ addClass = validClasses;
582
+ removeClass = invalidClasses;
583
+ generaltrigger = 'changedvaliditystate';
584
+ trigger = 'changedvalid';
585
+ if(checkTypes[elem.type] && elem.checked){
586
+ getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass).removeAttr('aria-invalid');
587
+ }
588
+ $.removeData(elem, 'webshimsinvalidcause');
589
+ }
590
+ } else {
591
+ validityCause = returnValidityCause(validity, elem);
592
+ if($.data(elem, 'webshimsinvalidcause') != validityCause){
593
+ $.data(elem, 'webshimsinvalidcause', validityCause);
594
+ generaltrigger = 'changedvaliditystate';
595
+ }
596
+ if(!shadowElem.hasClass(invalidClass)){
597
+ addClass = invalidClasses;
598
+ removeClass = validClasses;
599
+ if (checkTypes[elem.type] && !elem.checked) {
600
+ getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass);
601
+ }
602
+ trigger = 'changedinvalid';
603
+ }
604
+ }
605
+ if(addClass){
606
+ shadowElem.addClass(addClass).removeClass(removeClass);
607
+ //jQuery 1.6.1 IE9 bug (doubble trigger bug)
608
+ setTimeout(function(){
609
+ $(elem).trigger(trigger);
610
+ }, 0);
611
+ }
612
+ if(generaltrigger){
613
+ setTimeout(function(){
614
+ $(elem).trigger(generaltrigger);
615
+ }, 0);
616
+ }
617
+ $.removeData(e.target, 'webshimsswitchvalidityclass');
618
+ };
619
+
620
+ if(timer){
621
+ clearTimeout(timer);
622
+ }
623
+ if(e.type == 'refreshvalidityui'){
624
+ switchClass();
625
+ } else {
626
+ $.data(elem, 'webshimsswitchvalidityclass', setTimeout(switchClass, 9));
627
+ }
628
+ };
629
+
630
+ $(document).on(options.validityUIEvents || 'focusout change refreshvalidityui', switchValidityClass);
631
+ customEvents.changedvaliditystate = true;
632
+ customEvents.refreshCustomValidityRules = true;
633
+ customEvents.changedvalid = true;
634
+ customEvents.changedinvalid = true;
635
+ customEvents.refreshvalidityui = true;
636
+
637
+
638
+ webshims.triggerInlineForm = function(elem, event){
639
+ $(elem).trigger(event);
640
+ };
641
+
642
+ webshims.modules["form-core"].getGroupElements = getGroupElements;
643
+
644
+
645
+ var setRoot = function(){
646
+ webshims.scrollRoot = ($.browser.webkit || document.compatMode == 'BackCompat') ?
647
+ $(document.body) :
648
+ $(document.documentElement)
649
+ ;
650
+ };
651
+ setRoot();
652
+ webshims.ready('DOM', setRoot);
653
+
654
+ webshims.getRelOffset = function(posElem, relElem){
655
+ posElem = $(posElem);
656
+ var offset = $(relElem).offset();
657
+ var bodyOffset;
658
+ $.swap($(posElem)[0], {visibility: 'hidden', display: 'inline-block', left: 0, top: 0}, function(){
659
+ bodyOffset = posElem.offset();
660
+ });
661
+ offset.top -= bodyOffset.top;
662
+ offset.left -= bodyOffset.left;
663
+ return offset;
664
+ };
665
+
666
+ /* some extra validation UI */
667
+ webshims.validityAlert = (function(){
668
+ var alertElem = (!$.browser.msie || parseInt($.browser.version, 10) > 7) ? 'span' : 'label';
669
+ var errorBubble;
670
+ var hideTimer = false;
671
+ var focusTimer = false;
672
+ var resizeTimer = false;
673
+ var boundHide;
674
+
675
+ var api = {
676
+ hideDelay: 5000,
677
+
678
+ showFor: function(elem, message, noFocusElem, noBubble){
679
+ api._create();
680
+ elem = $(elem);
681
+ var visual = $(elem).getShadowElement();
682
+ var offset = api.getOffsetFromBody(visual);
683
+ api.clear();
684
+ if(noBubble){
685
+ this.hide();
686
+ } else {
687
+ this.getMessage(elem, message);
688
+ this.position(visual, offset);
689
+
690
+ this.show();
691
+ if(this.hideDelay){
692
+ hideTimer = setTimeout(boundHide, this.hideDelay);
693
+ }
694
+ $(window)
695
+ .on('resize.validityalert', function(){
696
+ clearTimeout(resizeTimer);
697
+ resizeTimer = setTimeout(function(){
698
+ api.position(visual);
699
+ }, 9);
700
+ })
701
+ ;
702
+ }
703
+
704
+ if(!noFocusElem){
705
+ this.setFocus(visual, offset);
706
+ }
707
+ },
708
+ getOffsetFromBody: function(elem){
709
+ return webshims.getRelOffset(errorBubble, elem);
710
+ },
711
+ setFocus: function(visual, offset){
712
+ var focusElem = $(visual).getShadowFocusElement();
713
+ var scrollTop = webshims.scrollRoot.scrollTop();
714
+ var elemTop = ((offset || focusElem.offset()).top) - 30;
715
+ var smooth;
716
+
717
+ if(webshims.getID && alertElem == 'label'){
718
+ errorBubble.attr('for', webshims.getID(focusElem));
719
+ }
720
+
721
+ if(scrollTop > elemTop){
722
+ webshims.scrollRoot.animate(
723
+ {scrollTop: elemTop - 5},
724
+ {
725
+ queue: false,
726
+ duration: Math.max( Math.min( 600, (scrollTop - elemTop) * 1.5 ), 80 )
727
+ }
728
+ );
729
+ smooth = true;
730
+ }
731
+ try {
732
+ focusElem[0].focus();
733
+ } catch(e){}
734
+ if(smooth){
735
+ webshims.scrollRoot.scrollTop(scrollTop);
736
+ setTimeout(function(){
737
+ webshims.scrollRoot.scrollTop(scrollTop);
738
+ }, 0);
739
+ }
740
+ setTimeout(function(){
741
+ $(document).on('focusout.validityalert', boundHide);
742
+ }, 10);
743
+ },
744
+ getMessage: function(elem, message){
745
+ if (!message) {
746
+ message = getContentValidationMessage(elem[0]) || elem.prop('validationMessage');
747
+ }
748
+ if (message) {
749
+ $('span.va-box', errorBubble).text(message);
750
+ }
751
+ else {
752
+ this.hide();
753
+ }
754
+ },
755
+ position: function(elem, offset){
756
+ offset = offset ? $.extend({}, offset) : api.getOffsetFromBody(elem);
757
+ offset.top += elem.outerHeight();
758
+ errorBubble.css(offset);
759
+ },
760
+ show: function(){
761
+ if(errorBubble.css('display') === 'none'){
762
+ errorBubble.css({opacity: 0}).show();
763
+ }
764
+ errorBubble.addClass('va-visible').fadeTo(400, 1);
765
+ },
766
+ hide: function(){
767
+ errorBubble.removeClass('va-visible').fadeOut();
768
+ },
769
+ clear: function(){
770
+ clearTimeout(focusTimer);
771
+ clearTimeout(hideTimer);
772
+ $(document).unbind('.validityalert');
773
+ $(window).unbind('.validityalert');
774
+ errorBubble.stop().removeAttr('for');
775
+ },
776
+ _create: function(){
777
+ if(errorBubble){return;}
778
+ 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'});
779
+ webshims.ready('DOM', function(){
780
+ errorBubble.appendTo('body');
781
+ if($.fn.bgIframe && $.browser.msie && parseInt($.browser.version, 10) < 7){
782
+ errorBubble.bgIframe();
783
+ }
784
+ });
785
+ }
786
+ };
787
+
788
+
789
+ boundHide = $.proxy(api, 'hide');
790
+
791
+ return api;
792
+ })();
793
+
794
+
795
+ /* extension, but also used to fix native implementation workaround/bugfixes */
796
+ (function(){
797
+ var firstEvent,
798
+ invalids = [],
799
+ stopSubmitTimer,
800
+ form
801
+ ;
802
+
803
+ $(document).on('invalid', function(e){
804
+ if(e.wrongWebkitInvalid){return;}
805
+ var jElm = $(e.target);
806
+ var shadowElem = jElm.getShadowElement();
807
+ if(!shadowElem.hasClass(invalidClass)){
808
+ shadowElem.addClass(invalidClasses).removeClass(validClasses);
809
+ setTimeout(function(){
810
+ $(e.target).trigger('changedinvalid').trigger('changedvaliditystate');
811
+ }, 0);
812
+ }
813
+
814
+ if(!firstEvent){
815
+ //trigger firstinvalid
816
+ firstEvent = $.Event('firstinvalid');
817
+ firstEvent.isInvalidUIPrevented = e.isDefaultPrevented;
818
+ var firstSystemInvalid = $.Event('firstinvalidsystem');
819
+ $(document).triggerHandler(firstSystemInvalid, {element: e.target, form: e.target.form, isInvalidUIPrevented: e.isDefaultPrevented});
820
+ jElm.trigger(firstEvent);
821
+ }
822
+
823
+ //if firstinvalid was prevented all invalids will be also prevented
824
+ if( firstEvent && firstEvent.isDefaultPrevented() ){
825
+ e.preventDefault();
826
+ }
827
+ invalids.push(e.target);
828
+ e.extraData = 'fix';
829
+ clearTimeout(stopSubmitTimer);
830
+ stopSubmitTimer = setTimeout(function(){
831
+ var lastEvent = {type: 'lastinvalid', cancelable: false, invalidlist: $(invalids)};
832
+ //reset firstinvalid
833
+ firstEvent = false;
834
+ invalids = [];
835
+ $(e.target).trigger(lastEvent, lastEvent);
836
+ }, 9);
837
+ jElm = null;
838
+ shadowElem = null;
839
+ });
840
+ })();
841
+
842
+ $.fn.getErrorMessage = function(){
843
+ var message = '';
844
+ var elem = this[0];
845
+ if(elem){
846
+ message = getContentValidationMessage(elem) || $.prop(elem, 'customValidationMessage') || $.prop(elem, 'validationMessage');
847
+ }
848
+ return message;
849
+ };
850
+
851
+ if(options.replaceValidationUI){
852
+ webshims.ready('DOM forms', function(){
853
+ $(document).on('firstinvalid', function(e){
854
+ if(!e.isInvalidUIPrevented()){
855
+ e.preventDefault();
856
+ $.webshims.validityAlert.showFor( e.target, $(e.target).prop('customValidationMessage') );
857
+ }
858
+ });
859
+ });
860
+ }
861
+
862
+ });jQuery.webshims.register('form-message', function($, webshims, window, document, undefined, options){
863
+ "use strict";
864
+ var validityMessages = webshims.validityMessages;
865
+
866
+ var implementProperties = (options.overrideMessages || options.customMessages) ? ['customValidationMessage'] : [];
867
+
868
+ validityMessages['en'] = $.extend(true, {
869
+ typeMismatch: {
870
+ email: 'Please enter an email address.',
871
+ url: 'Please enter a URL.',
872
+ number: 'Please enter a number.',
873
+ date: 'Please enter a date.',
874
+ time: 'Please enter a time.',
875
+ range: 'Invalid input.',
876
+ "datetime-local": 'Please enter a datetime.'
877
+ },
878
+ rangeUnderflow: {
879
+ defaultMessage: 'Value must be greater than or equal to {%min}.'
880
+ },
881
+ rangeOverflow: {
882
+ defaultMessage: 'Value must be less than or equal to {%max}.'
883
+ },
884
+ stepMismatch: 'Invalid input.',
885
+ tooLong: 'Please enter at most {%maxlength} character(s). You entered {%valueLen}.',
886
+
887
+ patternMismatch: 'Invalid input. {%title}',
888
+ valueMissing: {
889
+ defaultMessage: 'Please fill out this field.',
890
+ checkbox: 'Please check this box if you want to proceed.'
891
+ }
892
+ }, (validityMessages['en'] || validityMessages['en-US'] || {}));
893
+
894
+
895
+ ['select', 'radio'].forEach(function(type){
896
+ validityMessages['en'].valueMissing[type] = 'Please select an option.';
897
+ });
898
+
899
+ ['date', 'time', 'datetime-local'].forEach(function(type){
900
+ validityMessages.en.rangeUnderflow[type] = 'Value must be at or after {%min}.';
901
+ });
902
+ ['date', 'time', 'datetime-local'].forEach(function(type){
903
+ validityMessages.en.rangeOverflow[type] = 'Value must be at or before {%max}.';
904
+ });
905
+
906
+ validityMessages['en-US'] = validityMessages['en-US'] || validityMessages['en'];
907
+ validityMessages[''] = validityMessages[''] || validityMessages['en-US'];
908
+
909
+ validityMessages['de'] = $.extend(true, {
910
+ typeMismatch: {
911
+ email: '{%value} ist keine zulässige E-Mail-Adresse',
912
+ url: '{%value} ist keine zulässige Webadresse',
913
+ number: '{%value} ist keine Nummer!',
914
+ date: '{%value} ist kein Datum',
915
+ time: '{%value} ist keine Uhrzeit',
916
+ range: '{%value} ist keine Nummer!',
917
+ "datetime-local": '{%value} ist kein Datum-Uhrzeit Format.'
918
+ },
919
+ rangeUnderflow: {
920
+ defaultMessage: '{%value} ist zu niedrig. {%min} ist der unterste Wert, den Sie benutzen können.'
921
+ },
922
+ rangeOverflow: {
923
+ defaultMessage: '{%value} ist zu hoch. {%max} ist der oberste Wert, den Sie benutzen können.'
924
+ },
925
+ stepMismatch: 'Der Wert {%value} ist in diesem Feld nicht zulässig. Hier sind nur bestimmte Werte zulässig. {%title}',
926
+ tooLong: 'Der eingegebene Text ist zu lang! Sie haben {%valueLen} Zeichen eingegeben, dabei sind {%maxlength} das Maximum.',
927
+ patternMismatch: '{%value} hat für dieses Eingabefeld ein falsches Format! {%title}',
928
+ valueMissing: {
929
+ defaultMessage: 'Bitte geben Sie einen Wert ein',
930
+ checkbox: 'Bitte aktivieren Sie das Kästchen'
931
+ }
932
+ }, (validityMessages['de'] || {}));
933
+
934
+ ['select', 'radio'].forEach(function(type){
935
+ validityMessages['de'].valueMissing[type] = 'Bitte wählen Sie eine Option aus';
936
+ });
937
+
938
+ ['date', 'time', 'datetime-local'].forEach(function(type){
939
+ validityMessages.de.rangeUnderflow[type] = '{%value} ist zu früh. {%min} ist die früheste Zeit, die Sie benutzen können.';
940
+ });
941
+ ['date', 'time', 'datetime-local'].forEach(function(type){
942
+ validityMessages.de.rangeOverflow[type] = '{%value} ist zu spät. {%max} ist die späteste Zeit, die Sie benutzen können.';
943
+ });
944
+
945
+ var currentValidationMessage = validityMessages[''];
946
+
947
+
948
+ webshims.createValidationMessage = function(elem, name){
949
+ var message = currentValidationMessage[name];
950
+ if(message && typeof message !== 'string'){
951
+ message = message[ $.prop(elem, 'type') ] || message[ (elem.nodeName || '').toLowerCase() ] || message[ 'defaultMessage' ];
952
+ }
953
+ if(message){
954
+ ['value', 'min', 'max', 'title', 'maxlength', 'label'].forEach(function(attr){
955
+ if(message.indexOf('{%'+attr) === -1){return;}
956
+ var val = ((attr == 'label') ? $.trim($('label[for="'+ elem.id +'"]', elem.form).text()).replace(/\*$|:$/, '') : $.attr(elem, attr)) || '';
957
+ if(name == 'patternMismatch' && attr == 'title' && !val){
958
+ webshims.error('no title for patternMismatch provided. Always add a title attribute.');
959
+ }
960
+ message = message.replace('{%'+ attr +'}', val);
961
+ if('value' == attr){
962
+ message = message.replace('{%valueLen}', val.length);
963
+ }
964
+ });
965
+ }
966
+ return message || '';
967
+ };
968
+
969
+
970
+ if(webshims.bugs.validationMessage || !Modernizr.formvalidation || webshims.bugs.bustedValidity){
971
+ implementProperties.push('validationMessage');
972
+ }
973
+
974
+ webshims.activeLang({
975
+ langObj: validityMessages,
976
+ module: 'form-core',
977
+ callback: function(langObj){
978
+ currentValidationMessage = langObj;
979
+ }
980
+ });
981
+
982
+ implementProperties.forEach(function(messageProp){
983
+ webshims.defineNodeNamesProperty(['fieldset', 'output', 'button'], messageProp, {
984
+ prop: {
985
+ value: '',
986
+ writeable: false
987
+ }
988
+ });
989
+ ['input', 'select', 'textarea'].forEach(function(nodeName){
990
+ var desc = webshims.defineNodeNameProperty(nodeName, messageProp, {
991
+ prop: {
992
+ get: function(){
993
+ var elem = this;
994
+ var message = '';
995
+ if(!$.prop(elem, 'willValidate')){
996
+ return message;
997
+ }
998
+
999
+ var validity = $.prop(elem, 'validity') || {valid: 1};
1000
+
1001
+ if(validity.valid){return message;}
1002
+ message = webshims.getContentValidationMessage(elem, validity);
1003
+
1004
+ if(message){return message;}
1005
+
1006
+ if(validity.customError && elem.nodeName){
1007
+ message = (Modernizr.formvalidation && !webshims.bugs.bustedValidity && desc.prop._supget) ? desc.prop._supget.call(elem) : webshims.data(elem, 'customvalidationMessage');
1008
+ if(message){return message;}
1009
+ }
1010
+ $.each(validity, function(name, prop){
1011
+ if(name == 'valid' || !prop){return;}
1012
+
1013
+ message = webshims.createValidationMessage(elem, name);
1014
+ if(message){
1015
+ return false;
1016
+ }
1017
+ });
1018
+ return message || '';
1019
+ },
1020
+ writeable: false
1021
+ }
1022
+ });
1023
+ });
1024
+
1025
+ });
1026
+ });jQuery.webshims.register('form-datalist', function($, webshims, window, document, undefined){
1027
+ "use strict";
1028
+ var doc = document;
1029
+
1030
+ /*
1031
+ * implement propType "element" currently only used for list-attribute (will be moved to dom-extend, if needed)
1032
+ */
1033
+ webshims.propTypes.element = function(descs){
1034
+ webshims.createPropDefault(descs, 'attr');
1035
+ if(descs.prop){return;}
1036
+ descs.prop = {
1037
+ get: function(){
1038
+ var elem = descs.attr.get.call(this);
1039
+ if(elem){
1040
+ elem = document.getElementById(elem);
1041
+ if(elem && descs.propNodeName && !$.nodeName(elem, descs.propNodeName)){
1042
+ elem = null;
1043
+ }
1044
+ }
1045
+ return elem || null;
1046
+ },
1047
+ writeable: false
1048
+ };
1049
+ };
1050
+
1051
+
1052
+ /*
1053
+ * Implements datalist element and list attribute
1054
+ */
1055
+
1056
+ (function(){
1057
+ var formsCFG = $.webshims.cfg.forms;
1058
+ var listSupport = Modernizr.input.list;
1059
+ if(listSupport && !formsCFG.customDatalist){return;}
1060
+
1061
+ var initializeDatalist = function(){
1062
+
1063
+
1064
+ if(!listSupport){
1065
+ webshims.defineNodeNameProperty('datalist', 'options', {
1066
+ prop: {
1067
+ writeable: false,
1068
+ get: function(){
1069
+ var elem = this;
1070
+ var select = $('select', elem);
1071
+ var options;
1072
+ if(select[0]){
1073
+ options = select[0].options;
1074
+ } else {
1075
+ options = $('option', elem).get();
1076
+ if(options.length){
1077
+ webshims.warn('you should wrap your option-elements for a datalist in a select element to support IE and other old browsers.');
1078
+ }
1079
+ }
1080
+ return options;
1081
+ }
1082
+ }
1083
+ });
1084
+ }
1085
+
1086
+ var inputListProto = {
1087
+ //override autocomplete
1088
+ autocomplete: {
1089
+ attr: {
1090
+ get: function(){
1091
+ var elem = this;
1092
+ var data = $.data(elem, 'datalistWidget');
1093
+ if(data){
1094
+ return data._autocomplete;
1095
+ }
1096
+ return ('autocomplete' in elem) ? elem.autocomplete : elem.getAttribute('autocomplete');
1097
+ },
1098
+ set: function(value){
1099
+ var elem = this;
1100
+ var data = $.data(elem, 'datalistWidget');
1101
+ if(data){
1102
+ data._autocomplete = value;
1103
+ if(value == 'off'){
1104
+ data.hideList();
1105
+ }
1106
+ } else {
1107
+ if('autocomplete' in elem){
1108
+ elem.autocomplete = value;
1109
+ } else {
1110
+ elem.setAttribute('autocomplete', value);
1111
+ }
1112
+ }
1113
+ }
1114
+ }
1115
+ }
1116
+ };
1117
+
1118
+ // if(formsCFG.customDatalist && (!listSupport || !('selectedOption') in $('<input />')[0])){
1119
+ // //currently not supported x-browser (FF4 has not implemented and is not polyfilled )
1120
+ // inputListProto.selectedOption = {
1121
+ // prop: {
1122
+ // writeable: false,
1123
+ // get: function(){
1124
+ // var elem = this;
1125
+ // var list = $.prop(elem, 'list');
1126
+ // var ret = null;
1127
+ // var value, options;
1128
+ // if(!list){return ret;}
1129
+ // value = $.prop(elem, 'value');
1130
+ // if(!value){return ret;}
1131
+ // options = $.prop(list, 'options');
1132
+ // if(!options.length){return ret;}
1133
+ // $.each(options, function(i, option){
1134
+ // if(value == $.prop(option, 'value')){
1135
+ // ret = option;
1136
+ // return false;
1137
+ // }
1138
+ // });
1139
+ // return ret;
1140
+ // }
1141
+ // }
1142
+ // };
1143
+ // }
1144
+
1145
+ if(!listSupport){
1146
+ inputListProto['list'] = {
1147
+ attr: {
1148
+ get: function(){
1149
+ var val = webshims.contentAttr(this, 'list');
1150
+ return (val == null) ? undefined : val;
1151
+ },
1152
+ set: function(value){
1153
+ var elem = this;
1154
+ webshims.contentAttr(elem, 'list', value);
1155
+ webshims.objectCreate(shadowListProto, undefined, {input: elem, id: value, datalist: $.prop(elem, 'list')});
1156
+ }
1157
+ },
1158
+ initAttr: true,
1159
+ reflect: true,
1160
+ propType: 'element',
1161
+ propNodeName: 'datalist'
1162
+ };
1163
+ } else {
1164
+ //options only return options, if option-elements are rooted: but this makes this part of HTML5 less backwards compatible
1165
+ if(!($('<datalist><select><option></option></select></datalist>').prop('options') || []).length ){
1166
+ webshims.defineNodeNameProperty('datalist', 'options', {
1167
+ prop: {
1168
+ writeable: false,
1169
+ get: function(){
1170
+ var options = this.options || [];
1171
+ if(!options.length){
1172
+ var elem = this;
1173
+ var select = $('select', elem);
1174
+ if(select[0] && select[0].options && select[0].options.length){
1175
+ options = select[0].options;
1176
+ }
1177
+ }
1178
+ return options;
1179
+ }
1180
+ }
1181
+ });
1182
+ }
1183
+ inputListProto['list'] = {
1184
+ attr: {
1185
+ get: function(){
1186
+ var val = webshims.contentAttr(this, 'list');
1187
+ if(val != null){
1188
+ this.removeAttribute('list');
1189
+ } else {
1190
+ val = $.data(this, 'datalistListAttr');
1191
+ }
1192
+
1193
+ return (val == null) ? undefined : val;
1194
+ },
1195
+ set: function(value){
1196
+ var elem = this;
1197
+ $.data(elem, 'datalistListAttr', value);
1198
+ webshims.objectCreate(shadowListProto, undefined, {input: elem, id: value, datalist: $.prop(elem, 'list')});
1199
+ }
1200
+ },
1201
+ initAttr: true,
1202
+ reflect: true,
1203
+ propType: 'element',
1204
+ propNodeName: 'datalist'
1205
+ };
1206
+ }
1207
+
1208
+
1209
+ webshims.defineNodeNameProperties('input', inputListProto);
1210
+
1211
+ if($.event.customEvent){
1212
+ $.event.customEvent.updateDatalist = true;
1213
+ $.event.customEvent.updateInput = true;
1214
+ $.event.customEvent.datalistselect = true;
1215
+ }
1216
+ webshims.addReady(function(context, contextElem){
1217
+ contextElem
1218
+ .filter('datalist > select, datalist, datalist > option, datalist > select > option')
1219
+ .closest('datalist')
1220
+ .triggerHandler('updateDatalist')
1221
+ ;
1222
+
1223
+ });
1224
+
1225
+
1226
+ };
1227
+
1228
+
1229
+ /*
1230
+ * ShadowList
1231
+ */
1232
+ var listidIndex = 0;
1233
+
1234
+ var noDatalistSupport = {
1235
+ submit: 1,
1236
+ button: 1,
1237
+ reset: 1,
1238
+ hidden: 1,
1239
+
1240
+ //ToDo
1241
+ range: 1,
1242
+ date: 1
1243
+ };
1244
+ var lteie6 = ($.browser.msie && parseInt($.browser.version, 10) < 7);
1245
+ var globStoredOptions = {};
1246
+ var getStoredOptions = function(name){
1247
+ if(!name){return [];}
1248
+ if(globStoredOptions[name]){
1249
+ return globStoredOptions[name];
1250
+ }
1251
+ var data;
1252
+ try {
1253
+ data = JSON.parse(localStorage.getItem('storedDatalistOptions'+name));
1254
+ } catch(e){}
1255
+ globStoredOptions[name] = data || [];
1256
+ return data || [];
1257
+ };
1258
+ var storeOptions = function(name, val){
1259
+ if(!name){return;}
1260
+ val = val || [];
1261
+ try {
1262
+ localStorage.setItem( 'storedDatalistOptions'+name, JSON.stringify(val) );
1263
+ } catch(e){}
1264
+ };
1265
+
1266
+ var getText = function(elem){
1267
+ return (elem.textContent || elem.innerText || $.text([ elem ]) || '');
1268
+ };
1269
+
1270
+ var shadowListProto = {
1271
+ _create: function(opts){
1272
+
1273
+ if(noDatalistSupport[$.prop(opts.input, 'type')]){return;}
1274
+ var datalist = opts.datalist;
1275
+ var data = $.data(opts.input, 'datalistWidget');
1276
+ if(datalist && data && data.datalist !== datalist){
1277
+ data.datalist = datalist;
1278
+ data.id = opts.id;
1279
+
1280
+ data.shadowList.prop('className', 'datalist-polyfill '+ (data.datalist.className || '') + ' '+ data.datalist.id +'-shadowdom');
1281
+ if(formsCFG.positionDatalist){
1282
+ data.shadowList.insertAfter(opts.input);
1283
+ } else {
1284
+ data.shadowList.appendTo('body');
1285
+ }
1286
+ $(data.datalist)
1287
+ .off('updateDatalist.datalistWidget')
1288
+ .on('updateDatalist.datalistWidget', $.proxy(data, '_resetListCached'))
1289
+ ;
1290
+ data._resetListCached();
1291
+ return;
1292
+ } else if(!datalist){
1293
+ if(data){
1294
+ data.destroy();
1295
+ }
1296
+ return;
1297
+ } else if(data && data.datalist === datalist){
1298
+ return;
1299
+ }
1300
+ listidIndex++;
1301
+ var that = this;
1302
+ this.hideList = $.proxy(that, 'hideList');
1303
+ this.timedHide = function(){
1304
+ clearTimeout(that.hideTimer);
1305
+ that.hideTimer = setTimeout(that.hideList, 9);
1306
+ };
1307
+ this.datalist = datalist;
1308
+ this.id = opts.id;
1309
+ this.hasViewableData = true;
1310
+ this._autocomplete = $.attr(opts.input, 'autocomplete');
1311
+ $.data(opts.input, 'datalistWidget', this);
1312
+ this.shadowList = $('<div class="datalist-polyfill '+ (this.datalist.className || '') + ' '+ this.datalist.id +'-shadowdom' +'" />');
1313
+
1314
+ if(formsCFG.positionDatalist || $(opts.input).hasClass('position-datalist')){
1315
+ this.shadowList.insertAfter(opts.input);
1316
+ } else {
1317
+ this.shadowList.appendTo('body');
1318
+ }
1319
+
1320
+ this.index = -1;
1321
+ this.input = opts.input;
1322
+ this.arrayOptions = [];
1323
+
1324
+ this.shadowList
1325
+ .delegate('li', 'mouseenter.datalistWidget mousedown.datalistWidget click.datalistWidget', function(e){
1326
+ var items = $('li:not(.hidden-item)', that.shadowList);
1327
+ var select = (e.type == 'mousedown' || e.type == 'click');
1328
+ that.markItem(items.index(e.currentTarget), select, items);
1329
+ if(e.type == 'click'){
1330
+ that.hideList();
1331
+ if(formsCFG.customDatalist){
1332
+ $(opts.input).trigger('datalistselect');
1333
+ }
1334
+ }
1335
+ return (e.type != 'mousedown');
1336
+ })
1337
+ .on('focusout', this.timedHide)
1338
+ ;
1339
+
1340
+ opts.input.setAttribute('autocomplete', 'off');
1341
+
1342
+ $(opts.input)
1343
+ .attr({
1344
+ //role: 'combobox',
1345
+ 'aria-haspopup': 'true'
1346
+ })
1347
+ .on({
1348
+ 'input.datalistWidget': function(){
1349
+ if(!that.triggeredByDatalist){
1350
+ that.changedValue = false;
1351
+ that.showHideOptions();
1352
+ }
1353
+ },
1354
+ 'keydown.datalistWidget': function(e){
1355
+ var keyCode = e.keyCode;
1356
+ var activeItem;
1357
+ var items;
1358
+ if(keyCode == 40 && !that.showList()){
1359
+ that.markItem(that.index + 1, true);
1360
+ return false;
1361
+ }
1362
+
1363
+ if(!that.isListVisible){return;}
1364
+
1365
+
1366
+ if(keyCode == 38){
1367
+ that.markItem(that.index - 1, true);
1368
+ return false;
1369
+ }
1370
+ if(!e.shiftKey && (keyCode == 33 || keyCode == 36)){
1371
+ that.markItem(0, true);
1372
+ return false;
1373
+ }
1374
+ if(!e.shiftKey && (keyCode == 34 || keyCode == 35)){
1375
+ items = $('li:not(.hidden-item)', that.shadowList);
1376
+ that.markItem(items.length - 1, true, items);
1377
+ return false;
1378
+ }
1379
+ if(keyCode == 13 || keyCode == 27){
1380
+ if (keyCode == 13){
1381
+ activeItem = $('li.active-item:not(.hidden-item)', that.shadowList);
1382
+ that.changeValue( $('li.active-item:not(.hidden-item)', that.shadowList) );
1383
+ }
1384
+ that.hideList();
1385
+ if(formsCFG.customDatalist && activeItem && activeItem[0]){
1386
+ $(opts.input).trigger('datalistselect');
1387
+ }
1388
+ return false;
1389
+ }
1390
+ },
1391
+ 'focus.datalistWidget': function(){
1392
+ if($(this).hasClass('list-focus')){
1393
+ that.showList();
1394
+ }
1395
+ },
1396
+ 'mousedown.datalistWidget': function(){
1397
+ if($(this).is(':focus')){
1398
+ that.showList();
1399
+ }
1400
+ },
1401
+ 'blur.datalistWidget': this.timedHide
1402
+ })
1403
+ ;
1404
+
1405
+
1406
+ $(this.datalist)
1407
+ .off('updateDatalist.datalistWidget')
1408
+ .on('updateDatalist.datalistWidget', $.proxy(this, '_resetListCached'))
1409
+ ;
1410
+
1411
+ this._resetListCached();
1412
+
1413
+ if(opts.input.form && (opts.input.name || opts.input.id)){
1414
+ $(opts.input.form).on('submit.datalistWidget'+opts.input.id, function(){
1415
+ if(!$(opts.input).hasClass('no-datalist-cache') && that._autocomplete != 'off'){
1416
+ var val = $.prop(opts.input, 'value');
1417
+ var name = (opts.input.name || opts.input.id) + $.prop(opts.input, 'type');
1418
+ if(!that.storedOptions){
1419
+ that.storedOptions = getStoredOptions( name );
1420
+ }
1421
+ if(val && that.storedOptions.indexOf(val) == -1){
1422
+ that.storedOptions.push(val);
1423
+ storeOptions(name, that.storedOptions );
1424
+ }
1425
+ }
1426
+ });
1427
+ }
1428
+ $(window).on('unload.datalist'+this.id+' beforeunload.datalist'+this.id, function(){
1429
+ that.destroy();
1430
+ });
1431
+ },
1432
+ destroy: function(){
1433
+ var autocomplete = $.attr(this.input, 'autocomplete');
1434
+ $(this.input)
1435
+ .off('.datalistWidget')
1436
+ .removeData('datalistWidget')
1437
+ ;
1438
+ this.shadowList.remove();
1439
+ $(document).off('.datalist'+this.id);
1440
+ $(window).off('.datalist'+this.id);
1441
+ if(this.input.form && this.input.id){
1442
+ $(this.input.form).off('submit.datalistWidget'+this.input.id);
1443
+ }
1444
+ this.input.removeAttribute('aria-haspopup');
1445
+ if(autocomplete === undefined){
1446
+ this.input.removeAttribute('autocomplete');
1447
+ } else {
1448
+ $(this.input).attr('autocomplete', autocomplete);
1449
+ }
1450
+ },
1451
+ _resetListCached: function(e){
1452
+ var that = this;
1453
+ var forceShow;
1454
+ this.needsUpdate = true;
1455
+ this.lastUpdatedValue = false;
1456
+ this.lastUnfoundValue = '';
1457
+
1458
+ if(!this.updateTimer){
1459
+ if(window.QUnit || (forceShow = (e && document.activeElement == that.input))){
1460
+ that.updateListOptions(forceShow);
1461
+ } else {
1462
+ webshims.ready('WINDOWLOAD', function(){
1463
+ that.updateTimer = setTimeout(function(){
1464
+ that.updateListOptions();
1465
+ that = null;
1466
+ listidIndex = 1;
1467
+ }, 200 + (100 * listidIndex));
1468
+ });
1469
+ }
1470
+ }
1471
+ },
1472
+ maskHTML: function(str){
1473
+ return str.replace(/</g, '&lt;').replace(/>/g, '&gt;');
1474
+ },
1475
+ updateListOptions: function(_forceShow){
1476
+ this.needsUpdate = false;
1477
+ clearTimeout(this.updateTimer);
1478
+ this.updateTimer = false;
1479
+ this.shadowList
1480
+ .css({
1481
+ fontSize: $.css(this.input, 'fontSize'),
1482
+ fontFamily: $.css(this.input, 'fontFamily')
1483
+ })
1484
+ ;
1485
+ this.searchStart = formsCFG.customDatalist && $(this.input).hasClass('search-start');
1486
+
1487
+ var list = [];
1488
+
1489
+ var values = [];
1490
+ var allOptions = [];
1491
+ var rElem, rItem, rOptions, rI, rLen, item;
1492
+ for(rOptions = $.prop(this.datalist, 'options'), rI = 0, rLen = rOptions.length; rI < rLen; rI++){
1493
+ rElem = rOptions[rI];
1494
+ if(rElem.disabled){return;}
1495
+ rItem = {
1496
+ value: $(rElem).val() || '',
1497
+ text: $.trim($.attr(rElem, 'label') || getText(rElem)),
1498
+ className: rElem.className || '',
1499
+ style: $.attr(rElem, 'style') || ''
1500
+ };
1501
+ if(!rItem.text){
1502
+ rItem.text = rItem.value;
1503
+ } else if(rItem.text != rItem.value){
1504
+ rItem.className += ' different-label-value';
1505
+ }
1506
+ values[rI] = rItem.value;
1507
+ allOptions[rI] = rItem;
1508
+ }
1509
+
1510
+ if(!this.storedOptions){
1511
+ this.storedOptions = ($(this.input).hasClass('no-datalist-cache') || this._autocomplete == 'off') ? [] : getStoredOptions((this.input.name || this.input.id) + $.prop(this.input, 'type'));
1512
+ }
1513
+
1514
+ this.storedOptions.forEach(function(val, i){
1515
+ if(values.indexOf(val) == -1){
1516
+ allOptions.push({value: val, text: val, className: 'stored-suggest', style: ''});
1517
+ }
1518
+ });
1519
+
1520
+ for(rI = 0, rLen = allOptions.length; rI < rLen; rI++){
1521
+ item = allOptions[rI];
1522
+ list[rI] = '<li class="'+ item.className +'" style="'+ item.style +'" tabindex="-1" role="listitem"><span class="option-label">'+ this.maskHTML(item.text) +'</span> <span class="option-value">'+ this.maskHTML(item.value) +'</span></li>';
1523
+ }
1524
+
1525
+ this.arrayOptions = allOptions;
1526
+ this.shadowList.html('<div class="datalist-outer-box"><div class="datalist-box"><ul role="list">'+ list.join("\n") +'</ul></div></div>');
1527
+
1528
+ if($.fn.bgIframe && lteie6){
1529
+ this.shadowList.bgIframe();
1530
+ }
1531
+
1532
+ if(_forceShow || this.isListVisible){
1533
+ this.showHideOptions();
1534
+ }
1535
+ },
1536
+ showHideOptions: function(_fromShowList){
1537
+ var value = $.prop(this.input, 'value').toLowerCase();
1538
+ //first check prevent infinite loop, second creates simple lazy optimization
1539
+ if(value === this.lastUpdatedValue || (this.lastUnfoundValue && value.indexOf(this.lastUnfoundValue) === 0)){
1540
+ return;
1541
+ }
1542
+
1543
+ this.lastUpdatedValue = value;
1544
+ var found = false;
1545
+ var startSearch = this.searchStart;
1546
+ var lis = $('li', this.shadowList);
1547
+ if(value){
1548
+ this.arrayOptions.forEach(function(item, i){
1549
+ var search;
1550
+ if(!('lowerText' in item)){
1551
+ if(item.text != item.value){
1552
+ item.lowerText = item.value.toLowerCase() + item.text.toLowerCase();
1553
+ } else {
1554
+ item.lowerText = item.text.toLowerCase();
1555
+ }
1556
+ }
1557
+ search = item.lowerText.indexOf(value);
1558
+ search = startSearch ? !search : search !== -1;
1559
+ if(search){
1560
+ $(lis[i]).removeClass('hidden-item');
1561
+ found = true;
1562
+ } else {
1563
+ $(lis[i]).addClass('hidden-item');
1564
+ }
1565
+ });
1566
+ } else if(lis.length) {
1567
+ lis.removeClass('hidden-item');
1568
+ found = true;
1569
+ }
1570
+
1571
+ this.hasViewableData = found;
1572
+ if(!_fromShowList && found){
1573
+ this.showList();
1574
+ }
1575
+ if(!found){
1576
+ this.lastUnfoundValue = value;
1577
+ this.hideList();
1578
+ }
1579
+ },
1580
+ setPos: function(){
1581
+ this.shadowList.css({marginTop: 0, marginLeft: 0, marginRight: 0, marginBottom: 0});
1582
+ var css = (formsCFG.positionDatalist) ? $(this.input).position() : webshims.getRelOffset(this.shadowList, this.input);
1583
+ css.top += $(this.input).outerHeight();
1584
+ css.width = $(this.input).outerWidth() - (parseInt(this.shadowList.css('borderLeftWidth'), 10) || 0) - (parseInt(this.shadowList.css('borderRightWidth'), 10) || 0);
1585
+ this.shadowList.css({marginTop: '', marginLeft: '', marginRight: '', marginBottom: ''}).css(css);
1586
+ return css;
1587
+ },
1588
+ showList: function(){
1589
+ if(this.isListVisible){return false;}
1590
+ if(this.needsUpdate){
1591
+ this.updateListOptions();
1592
+ }
1593
+ this.showHideOptions(true);
1594
+ if(!this.hasViewableData){return false;}
1595
+ this.isListVisible = true;
1596
+ var that = this;
1597
+
1598
+ that.setPos();
1599
+ that.shadowList.addClass('datalist-visible').find('li.active-item').removeClass('active-item');
1600
+
1601
+ $(window).unbind('.datalist'+that.id);
1602
+ $(document)
1603
+ .off('.datalist'+that.id)
1604
+ .on('mousedown.datalist'+that.id +' focusin.datalist'+that.id, function(e){
1605
+ if(e.target === that.input || that.shadowList[0] === e.target || $.contains( that.shadowList[0], e.target )){
1606
+ clearTimeout(that.hideTimer);
1607
+ setTimeout(function(){
1608
+ clearTimeout(that.hideTimer);
1609
+ }, 9);
1610
+ } else {
1611
+ that.timedHide();
1612
+ }
1613
+ })
1614
+ .on('updateshadowdom.datalist'+that.id, function(){
1615
+ that.setPos();
1616
+ })
1617
+ ;
1618
+ return true;
1619
+ },
1620
+ hideList: function(){
1621
+ if(!this.isListVisible){return false;}
1622
+ var that = this;
1623
+ var triggerChange = function(e){
1624
+ if(that.changedValue){
1625
+ $(that.input).trigger('change');
1626
+ }
1627
+ that.changedValue = false;
1628
+ };
1629
+
1630
+ that.shadowList.removeClass('datalist-visible list-item-active');
1631
+ that.index = -1;
1632
+ that.isListVisible = false;
1633
+ if(that.changedValue){
1634
+ that.triggeredByDatalist = true;
1635
+ webshims.triggerInlineForm && webshims.triggerInlineForm(that.input, 'input');
1636
+ if($(that.input).is(':focus')){
1637
+ $(that.input).one('blur', triggerChange);
1638
+ } else {
1639
+ triggerChange();
1640
+ }
1641
+ that.triggeredByDatalist = false;
1642
+ }
1643
+ $(document).unbind('.datalist'+that.id);
1644
+ $(window)
1645
+ .off('.datalist'+that.id)
1646
+ .one('resize.datalist'+that.id, function(){
1647
+ that.shadowList.css({top: 0, left: 0});
1648
+ })
1649
+ ;
1650
+ return true;
1651
+ },
1652
+ scrollIntoView: function(elem){
1653
+ var ul = $('ul', this.shadowList);
1654
+ var div = $('div.datalist-box', this.shadowList);
1655
+ var elemPos = elem.position();
1656
+ var containerHeight;
1657
+ elemPos.top -= (parseInt(ul.css('paddingTop'), 10) || 0) + (parseInt(ul.css('marginTop'), 10) || 0) + (parseInt(ul.css('borderTopWidth'), 10) || 0);
1658
+ if(elemPos.top < 0){
1659
+ div.scrollTop( div.scrollTop() + elemPos.top - 2);
1660
+ return;
1661
+ }
1662
+ elemPos.top += elem.outerHeight();
1663
+ containerHeight = div.height();
1664
+ if(elemPos.top > containerHeight){
1665
+ div.scrollTop( div.scrollTop() + (elemPos.top - containerHeight) + 2);
1666
+ }
1667
+ },
1668
+ changeValue: function(activeItem){
1669
+ if(!activeItem[0]){return;}
1670
+ var newValue = $('span.option-value', activeItem).text();
1671
+ var oldValue = $.prop(this.input, 'value');
1672
+ if(newValue != oldValue){
1673
+ $(this.input)
1674
+ .prop('value', newValue)
1675
+ .triggerHandler('updateInput')
1676
+ ;
1677
+ this.changedValue = true;
1678
+ }
1679
+ },
1680
+ markItem: function(index, doValue, items){
1681
+ var activeItem;
1682
+ var goesUp;
1683
+
1684
+ items = items || $('li:not(.hidden-item)', this.shadowList);
1685
+ if(!items.length){return;}
1686
+ if(index < 0){
1687
+ index = items.length - 1;
1688
+ } else if(index >= items.length){
1689
+ index = 0;
1690
+ }
1691
+ items.removeClass('active-item');
1692
+ this.shadowList.addClass('list-item-active');
1693
+ activeItem = items.filter(':eq('+ index +')').addClass('active-item');
1694
+
1695
+ if(doValue){
1696
+ this.changeValue(activeItem);
1697
+ this.scrollIntoView(activeItem);
1698
+ }
1699
+ this.index = index;
1700
+ }
1701
+ };
1702
+
1703
+ //init datalist update
1704
+ initializeDatalist();
1705
+ })();
1706
+
1754
1707
  });