webshims-rails 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/lib/webshims-rails/version.rb +2 -2
  2. data/vendor/assets/javascripts/webshims/extras/custom-validity.js +253 -253
  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/polyfiller.js +1 -1
  6. data/vendor/assets/javascripts/webshims/minified/shims/combos/10.js +1 -1
  7. data/vendor/assets/javascripts/webshims/minified/shims/combos/12.js +1 -1
  8. data/vendor/assets/javascripts/webshims/minified/shims/combos/16.js +1 -1
  9. data/vendor/assets/javascripts/webshims/minified/shims/combos/17.js +1 -1
  10. data/vendor/assets/javascripts/webshims/minified/shims/combos/19.js +1 -1
  11. data/vendor/assets/javascripts/webshims/minified/shims/combos/2.js +1 -1
  12. data/vendor/assets/javascripts/webshims/minified/shims/combos/20.js +1 -1
  13. data/vendor/assets/javascripts/webshims/minified/shims/combos/21.js +1 -1
  14. data/vendor/assets/javascripts/webshims/minified/shims/combos/22.js +1 -1
  15. data/vendor/assets/javascripts/webshims/minified/shims/combos/23.js +1 -1
  16. data/vendor/assets/javascripts/webshims/minified/shims/combos/24.js +1 -1
  17. data/vendor/assets/javascripts/webshims/minified/shims/combos/25.js +1 -1
  18. data/vendor/assets/javascripts/webshims/minified/shims/combos/26.js +1 -1
  19. data/vendor/assets/javascripts/webshims/minified/shims/combos/27.js +1 -1
  20. data/vendor/assets/javascripts/webshims/minified/shims/combos/3.js +1 -1
  21. data/vendor/assets/javascripts/webshims/minified/shims/combos/4.js +1 -1
  22. data/vendor/assets/javascripts/webshims/minified/shims/combos/5.js +1 -1
  23. data/vendor/assets/javascripts/webshims/minified/shims/combos/59.js +1 -1
  24. data/vendor/assets/javascripts/webshims/minified/shims/combos/8.js +1 -1
  25. data/vendor/assets/javascripts/webshims/minified/shims/combos/9.js +1 -1
  26. data/vendor/assets/javascripts/webshims/minified/shims/form-core.js +1 -1
  27. data/vendor/assets/javascripts/webshims/minified/shims/form-message.js +1 -1
  28. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-de.txt +33 -33
  29. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-en.txt +34 -34
  30. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-core.js +1 -1
  31. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-jaris.js +1 -1
  32. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-swf.js +1 -1
  33. data/vendor/assets/javascripts/webshims/minified/shims/swf/JarisFLVPlayer.swf +0 -0
  34. data/vendor/assets/javascripts/webshims/polyfiller.js +1188 -1188
  35. data/vendor/assets/javascripts/webshims/shims/FlashCanvasPro/README +82 -82
  36. data/vendor/assets/javascripts/webshims/shims/combos/1.js +1752 -1752
  37. data/vendor/assets/javascripts/webshims/shims/combos/10.js +3310 -3311
  38. data/vendor/assets/javascripts/webshims/shims/combos/11.js +1631 -1631
  39. data/vendor/assets/javascripts/webshims/shims/combos/12.js +1695 -1696
  40. data/vendor/assets/javascripts/webshims/shims/combos/13.js +1098 -1098
  41. data/vendor/assets/javascripts/webshims/shims/combos/14.js +477 -477
  42. data/vendor/assets/javascripts/webshims/shims/combos/15.js +317 -317
  43. data/vendor/assets/javascripts/webshims/shims/combos/16.js +2177 -2154
  44. data/vendor/assets/javascripts/webshims/shims/combos/17.js +2354 -2319
  45. data/vendor/assets/javascripts/webshims/shims/combos/18.js +1322 -1322
  46. data/vendor/assets/javascripts/webshims/shims/combos/19.js +2262 -2238
  47. data/vendor/assets/javascripts/webshims/shims/combos/2.js +2376 -2340
  48. data/vendor/assets/javascripts/webshims/shims/combos/20.js +1557 -1558
  49. data/vendor/assets/javascripts/webshims/shims/combos/21.js +1745 -1733
  50. data/vendor/assets/javascripts/webshims/shims/combos/22.js +2360 -2361
  51. data/vendor/assets/javascripts/webshims/shims/combos/23.js +2342 -2331
  52. data/vendor/assets/javascripts/webshims/shims/combos/24.js +2859 -2836
  53. data/vendor/assets/javascripts/webshims/shims/combos/25.js +1547 -1548
  54. data/vendor/assets/javascripts/webshims/shims/combos/26.js +2178 -2155
  55. data/vendor/assets/javascripts/webshims/shims/combos/27.js +3311 -3312
  56. data/vendor/assets/javascripts/webshims/shims/combos/3.js +3058 -3022
  57. data/vendor/assets/javascripts/webshims/shims/combos/4.js +807 -771
  58. data/vendor/assets/javascripts/webshims/shims/combos/5.js +1063 -1027
  59. data/vendor/assets/javascripts/webshims/shims/combos/59.js +1745 -1709
  60. data/vendor/assets/javascripts/webshims/shims/combos/6.js +384 -384
  61. data/vendor/assets/javascripts/webshims/shims/combos/7.js +640 -640
  62. data/vendor/assets/javascripts/webshims/shims/combos/8.js +1546 -1547
  63. data/vendor/assets/javascripts/webshims/shims/combos/9.js +2507 -2508
  64. data/vendor/assets/javascripts/webshims/shims/details.js +148 -148
  65. data/vendor/assets/javascripts/webshims/shims/dom-extend.js +949 -949
  66. data/vendor/assets/javascripts/webshims/shims/es5.js +802 -802
  67. data/vendor/assets/javascripts/webshims/shims/excanvas.js +924 -924
  68. data/vendor/assets/javascripts/webshims/shims/form-core.js +630 -606
  69. data/vendor/assets/javascripts/webshims/shims/form-datalist.js +681 -681
  70. data/vendor/assets/javascripts/webshims/shims/form-message.js +176 -164
  71. data/vendor/assets/javascripts/webshims/shims/form-native-extend.js +255 -255
  72. data/vendor/assets/javascripts/webshims/shims/form-number-date-api.js +383 -383
  73. data/vendor/assets/javascripts/webshims/shims/form-shim-extend.js +1568 -1568
  74. data/vendor/assets/javascripts/webshims/shims/geolocation.js +168 -168
  75. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-ar.js +32 -32
  76. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-ch-ZN.js +32 -32
  77. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-de.txt +33 -33
  78. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-el.js +32 -32
  79. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-en.txt +34 -34
  80. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-es.js +31 -31
  81. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-fr.js +32 -32
  82. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-he.js +32 -32
  83. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-hi.js +32 -32
  84. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-hu.js +32 -32
  85. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-it.js +32 -32
  86. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-ja.js +32 -32
  87. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-nl.js +32 -32
  88. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-pt-PT.js +32 -32
  89. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-ru.js +31 -31
  90. data/vendor/assets/javascripts/webshims/shims/i18n/errormessages-sv.js +32 -32
  91. data/vendor/assets/javascripts/webshims/shims/json-storage.js +308 -308
  92. data/vendor/assets/javascripts/webshims/shims/mediaelement-core.js +596 -597
  93. data/vendor/assets/javascripts/webshims/shims/mediaelement-jaris.js +891 -891
  94. data/vendor/assets/javascripts/webshims/shims/mediaelement-native-fix.js +98 -98
  95. data/vendor/assets/javascripts/webshims/shims/mediaelement-swf.js +960 -960
  96. data/vendor/assets/javascripts/webshims/shims/mediaelement-yt.js +543 -543
  97. data/vendor/assets/javascripts/webshims/shims/styles/shim.css +697 -697
  98. data/vendor/assets/javascripts/webshims/shims/swf/JarisFLVPlayer.swf +0 -0
  99. metadata +2 -4
  100. data/vendor/assets/javascripts/webshims/minified/shims/range-ui.js +0 -1
  101. data/vendor/assets/javascripts/webshims/shims/range-ui.js +0 -66
@@ -1,2341 +1,2377 @@
1
- //additional tests for partial implementation of forms features
2
- (function($){
3
- "use strict";
4
- var Modernizr = window.Modernizr;
5
- var webshims = $.webshims;
6
- var bugs = webshims.bugs;
7
- var form = $('<form action="#" style="width: 1px; height: 1px; overflow: hidden;"><select name="b" required="" /><input required="" name="a" /></form>');
8
- var testRequiredFind = function(){
9
- if(form[0].querySelector){
10
- try {
11
- bugs.findRequired = !(form[0].querySelector('select:required'));
12
- } catch(er){
13
- bugs.findRequired = false;
14
- }
15
- }
16
- };
17
- var inputElem = $('input', form).eq(0);
18
- var onDomextend = function(fn){
19
- webshims.loader.loadList(['dom-extend']);
20
- webshims.ready('dom-extend', fn);
21
- };
22
-
23
- bugs.findRequired = false;
24
- bugs.validationMessage = false;
25
-
26
- webshims.capturingEventPrevented = function(e){
27
- if(!e._isPolyfilled){
28
- var isDefaultPrevented = e.isDefaultPrevented;
29
- var preventDefault = e.preventDefault;
30
- e.preventDefault = function(){
31
- clearTimeout($.data(e.target, e.type + 'DefaultPrevented'));
32
- $.data(e.target, e.type + 'DefaultPrevented', setTimeout(function(){
33
- $.removeData(e.target, e.type + 'DefaultPrevented');
34
- }, 30));
35
- return preventDefault.apply(this, arguments);
36
- };
37
- e.isDefaultPrevented = function(){
38
- return !!(isDefaultPrevented.apply(this, arguments) || $.data(e.target, e.type + 'DefaultPrevented') || false);
39
- };
40
- e._isPolyfilled = true;
41
- }
42
- };
43
-
44
- if(!Modernizr.formvalidation || bugs.bustedValidity){
45
- testRequiredFind();
46
- return;
47
- }
48
-
49
- //create delegatable events
50
- webshims.capturingEvents(['input']);
51
- webshims.capturingEvents(['invalid'], true);
52
-
53
- if(window.opera || window.testGoodWithFix){
54
-
55
- form.appendTo('head');
56
-
57
- testRequiredFind();
58
- bugs.validationMessage = !(inputElem.prop('validationMessage'));
59
-
60
- webshims.reTest(['form-native-extend', 'form-message']);
61
-
62
- form.remove();
63
-
64
- $(function(){
65
- onDomextend(function(){
66
-
67
- //Opera shows native validation bubbles in case of input.checkValidity()
68
- // Opera 11.6/12 hasn't fixed this issue right, it's buggy
69
- var preventDefault = function(e){
70
- e.preventDefault();
71
- };
72
-
73
- ['form', 'input', 'textarea', 'select'].forEach(function(name){
74
- var desc = webshims.defineNodeNameProperty(name, 'checkValidity', {
75
- prop: {
76
- value: function(){
77
- if (!webshims.fromSubmit) {
78
- $(this).on('invalid.checkvalidity', preventDefault);
79
- }
80
-
81
- webshims.fromCheckValidity = true;
82
- var ret = desc.prop._supvalue.apply(this, arguments);
83
- if (!webshims.fromSubmit) {
84
- $(this).unbind('invalid.checkvalidity', preventDefault);
85
- }
86
- webshims.fromCheckValidity = false;
87
- return ret;
88
- }
89
- }
90
- });
91
- });
92
-
93
- });
94
- });
95
- }
96
-
97
- if($.browser.webkit && !webshims.bugs.bustedValidity){
98
- (function(){
99
- var elems = /^(?:textarea|input)$/i;
100
- var form = false;
101
-
102
- document.addEventListener('contextmenu', function(e){
103
- if(elems.test( e.target.nodeName || '') && (form = e.target.form)){
104
- setTimeout(function(){
105
- form = false;
106
- }, 1);
107
- }
108
- }, false);
109
-
110
- $(window).on('invalid', function(e){
111
- if(e.originalEvent && form && form == e.target.form){
112
- e.wrongWebkitInvalid = true;
113
- e.stopImmediatePropagation();
114
- }
115
- });
116
- })();
117
- }
118
- })(jQuery);
119
-
120
- jQuery.webshims.register('form-core', function($, webshims, window, document, undefined, options){
121
- "use strict";
122
-
123
- var groupTypes = {radio: 1};
124
- var checkTypes = {checkbox: 1, radio: 1};
125
- var emptyJ = $([]);
126
- var bugs = webshims.bugs;
127
- var getGroupElements = function(elem){
128
- elem = $(elem);
129
- var name;
130
- var form;
131
- var ret = emptyJ;
132
- if(groupTypes[elem[0].type]){
133
- form = elem.prop('form');
134
- name = elem[0].name;
135
- if(!name){
136
- ret = elem;
137
- } else if(form){
138
- ret = $(form[name]);
139
- } else {
140
- ret = $(document.getElementsByName(name)).filter(function(){
141
- return !$.prop(this, 'form');
142
- });
143
- }
144
- ret = ret.filter('[type="radio"]');
145
- }
146
- return ret;
147
- };
148
-
149
- var getContentValidationMessage = webshims.getContentValidationMessage = function(elem, validity, key){
150
- var message = $(elem).data('errormessage') || elem.getAttribute('x-moz-errormessage') || '';
151
- if(key && message[key]){
152
- message = message[key];
153
- }
154
- if(typeof message == 'object'){
155
- validity = validity || $.prop(elem, 'validity') || {valid: 1};
156
- if(!validity.valid){
157
- $.each(validity, function(name, prop){
158
- if(prop && name != 'valid' && message[name]){
159
- message = message[name];
160
- return false;
161
- }
162
- });
163
- }
164
- }
165
-
166
- if(typeof message == 'object'){
167
- message = message.defaultMessage;
168
- }
169
- return message || '';
170
- };
171
-
172
- /*
173
- * Selectors for all browsers
174
- */
175
- var rangeTypes = {number: 1, range: 1, date: 1/*, time: 1, 'datetime-local': 1, datetime: 1, month: 1, week: 1*/};
176
- var hasInvalid = function(elem){
177
- var ret = false;
178
- $($.prop(elem, 'elements')).each(function(){
179
- ret = $(this).is(':invalid');
180
- if(ret){
181
- return false;
182
- }
183
- });
184
- return ret;
185
- };
186
- $.extend($.expr[":"], {
187
- "valid-element": function(elem){
188
- return $.nodeName(elem, 'form') ? !hasInvalid(elem) :!!($.prop(elem, 'willValidate') && isValid(elem));
189
- },
190
- "invalid-element": function(elem){
191
- return $.nodeName(elem, 'form') ? hasInvalid(elem) : !!($.prop(elem, 'willValidate') && !isValid(elem));
192
- },
193
- "required-element": function(elem){
194
- return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required'));
195
- },
196
- "user-error": function(elem){
197
- return ($.prop(elem, 'willValidate') && $(elem).hasClass('user-error'));
198
- },
199
- "optional-element": function(elem){
200
- return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required') === false);
201
- },
202
- "in-range": function(elem){
203
- if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
204
- return false;
205
- }
206
- var val = $.prop(elem, 'validity');
207
- return !!(val && !val.rangeOverflow && !val.rangeUnderflow);
208
- },
209
- "out-of-range": function(elem){
210
- if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
211
- return false;
212
- }
213
- var val = $.prop(elem, 'validity');
214
- return !!(val && (val.rangeOverflow || val.rangeUnderflow));
215
- }
216
-
217
- });
218
-
219
- ['valid', 'invalid', 'required', 'optional'].forEach(function(name){
220
- $.expr[":"][name] = $.expr.filters[name+"-element"];
221
- });
222
-
223
-
224
- $.expr[":"].focus = function( elem ) {
225
- try {
226
- var doc = elem.ownerDocument;
227
- return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus());
228
- } catch(e){}
229
- return false;
230
- };
231
-
232
- var customEvents = $.event.customEvent || {};
233
- var isValid = function(elem){
234
- return ($.prop(elem, 'validity') || {valid: 1}).valid;
235
- };
236
-
237
- if (bugs.bustedValidity || bugs.findRequired) {
238
- (function(){
239
- var find = $.find;
240
- var matchesSelector = $.find.matchesSelector;
241
-
242
- var regExp = /(\:valid|\:invalid|\:optional|\:required|\:in-range|\:out-of-range)(?=[\s\[\~\.\+\>\:\#*]|$)/ig;
243
- var regFn = function(sel){
244
- return sel + '-element';
245
- };
246
-
247
- $.find = (function(){
248
- var slice = Array.prototype.slice;
249
- var fn = function(sel){
250
- var ar = arguments;
251
- ar = slice.call(ar, 1, ar.length);
252
- ar.unshift(sel.replace(regExp, regFn));
253
- return find.apply(this, ar);
254
- };
255
- for (var i in find) {
256
- if(find.hasOwnProperty(i)){
257
- fn[i] = find[i];
258
- }
259
- }
260
- return fn;
261
- })();
262
- if(!Modernizr.prefixed || Modernizr.prefixed("matchesSelector", document.documentElement)){
263
- $.find.matchesSelector = function(node, expr){
264
- expr = expr.replace(regExp, regFn);
265
- return matchesSelector.call(this, node, expr);
266
- };
267
- }
268
-
269
- })();
270
- }
271
-
272
- //ToDo needs testing
273
- var oldAttr = $.prop;
274
- var changeVals = {selectedIndex: 1, value: 1, checked: 1, disabled: 1, readonly: 1};
275
- $.prop = function(elem, name, val){
276
- var ret = oldAttr.apply(this, arguments);
277
- if(elem && 'form' in elem && changeVals[name] && val !== undefined && $(elem).hasClass(invalidClass)){
278
- if(isValid(elem)){
279
- $(elem).getShadowElement().removeClass(invalidClasses);
280
- if(name == 'checked' && val) {
281
- getGroupElements(elem).not(elem).removeClass(invalidClasses).removeAttr('aria-invalid');
282
- }
283
- }
284
- }
285
- return ret;
286
- };
287
-
288
- var returnValidityCause = function(validity, elem){
289
- var ret;
290
- $.each(validity, function(name, value){
291
- if(value){
292
- ret = (name == 'customError') ? $.prop(elem, 'validationMessage') : name;
293
- return false;
294
- }
295
- });
296
- return ret;
297
- };
298
-
299
- var isInGroup = function(name){
300
- var ret;
301
- try {
302
- ret = document.activeElement.name === name;
303
- } catch(e){}
304
- return ret;
305
- };
306
- /* form-ui-invalid/form-ui-valid are deprecated. use user-error/user-succes instead */
307
- var invalidClass = 'user-error';
308
- var invalidClasses = 'user-error form-ui-invalid';
309
- var validClass = 'user-success';
310
- var validClasses = 'user-success form-ui-valid';
311
- var switchValidityClass = function(e){
312
- var elem, timer;
313
- if(!e.target){return;}
314
- elem = $(e.target).getNativeElement()[0];
315
- if(elem.type == 'submit' || !$.prop(elem, 'willValidate')){return;}
316
- timer = $.data(elem, 'webshimsswitchvalidityclass');
317
- var switchClass = function(){
318
- if(e.type == 'focusout' && elem.type == 'radio' && isInGroup(elem.name)){return;}
319
- var validity = $.prop(elem, 'validity');
320
- var shadowElem = $(elem).getShadowElement();
321
- var addClass, removeClass, trigger, generaltrigger, validityCause;
322
-
323
- $(elem).trigger('refreshCustomValidityRules');
324
- if(validity.valid){
325
- if(!shadowElem.hasClass(validClass)){
326
- addClass = validClasses;
327
- removeClass = invalidClasses;
328
- generaltrigger = 'changedvaliditystate';
329
- trigger = 'changedvalid';
330
- if(checkTypes[elem.type] && elem.checked){
331
- getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass).removeAttr('aria-invalid');
332
- }
333
- $.removeData(elem, 'webshimsinvalidcause');
334
- }
335
- } else {
336
- validityCause = returnValidityCause(validity, elem);
337
- if($.data(elem, 'webshimsinvalidcause') != validityCause){
338
- $.data(elem, 'webshimsinvalidcause', validityCause);
339
- generaltrigger = 'changedvaliditystate';
340
- }
341
- if(!shadowElem.hasClass(invalidClass)){
342
- addClass = invalidClasses;
343
- removeClass = validClasses;
344
- if (checkTypes[elem.type] && !elem.checked) {
345
- getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass);
346
- }
347
- trigger = 'changedinvalid';
348
- }
349
- }
350
- if(addClass){
351
- shadowElem.addClass(addClass).removeClass(removeClass);
352
- //jQuery 1.6.1 IE9 bug (doubble trigger bug)
353
- setTimeout(function(){
354
- $(elem).trigger(trigger);
355
- }, 0);
356
- }
357
- if(generaltrigger){
358
- setTimeout(function(){
359
- $(elem).trigger(generaltrigger);
360
- }, 0);
361
- }
362
- $.removeData(e.target, 'webshimsswitchvalidityclass');
363
- };
364
-
365
- if(timer){
366
- clearTimeout(timer);
367
- }
368
- if(e.type == 'refreshvalidityui'){
369
- switchClass();
370
- } else {
371
- $.data(elem, 'webshimsswitchvalidityclass', setTimeout(switchClass, 9));
372
- }
373
- };
374
-
375
- $(document).on(options.validityUIEvents || 'focusout change refreshvalidityui', switchValidityClass);
376
- customEvents.changedvaliditystate = true;
377
- customEvents.refreshCustomValidityRules = true;
378
- customEvents.changedvalid = true;
379
- customEvents.changedinvalid = true;
380
- customEvents.refreshvalidityui = true;
381
-
382
-
383
- webshims.triggerInlineForm = function(elem, event){
384
- $(elem).trigger(event);
385
- };
386
-
387
- webshims.modules["form-core"].getGroupElements = getGroupElements;
388
-
389
-
390
- var setRoot = function(){
391
- webshims.scrollRoot = ($.browser.webkit || document.compatMode == 'BackCompat') ?
392
- $(document.body) :
393
- $(document.documentElement)
394
- ;
395
- };
396
- setRoot();
397
- webshims.ready('DOM', setRoot);
398
-
399
- webshims.getRelOffset = function(posElem, relElem){
400
- posElem = $(posElem);
401
- var offset = $(relElem).offset();
402
- var bodyOffset;
403
- $.swap($(posElem)[0], {visibility: 'hidden', display: 'inline-block', left: 0, top: 0}, function(){
404
- bodyOffset = posElem.offset();
405
- });
406
- offset.top -= bodyOffset.top;
407
- offset.left -= bodyOffset.left;
408
- return offset;
409
- };
410
-
411
- /* some extra validation UI */
412
- webshims.validityAlert = (function(){
413
- var alertElem = (!$.browser.msie || parseInt($.browser.version, 10) > 7) ? 'span' : 'label';
414
- var errorBubble;
415
- var hideTimer = false;
416
- var focusTimer = false;
417
- var resizeTimer = false;
418
- var boundHide;
419
-
420
- var api = {
421
- hideDelay: 5000,
422
-
423
- showFor: function(elem, message, noFocusElem, noBubble){
424
- api._create();
425
- elem = $(elem);
426
- var visual = $(elem).getShadowElement();
427
- var offset = api.getOffsetFromBody(visual);
428
- api.clear();
429
- if(noBubble){
430
- this.hide();
431
- } else {
432
- this.getMessage(elem, message);
433
- this.position(visual, offset);
434
-
435
- this.show();
436
- if(this.hideDelay){
437
- hideTimer = setTimeout(boundHide, this.hideDelay);
438
- }
439
- $(window)
440
- .on('resize.validityalert', function(){
441
- clearTimeout(resizeTimer);
442
- resizeTimer = setTimeout(function(){
443
- api.position(visual);
444
- }, 9);
445
- })
446
- ;
447
- }
448
-
449
- if(!noFocusElem){
450
- this.setFocus(visual, offset);
451
- }
452
- },
453
- getOffsetFromBody: function(elem){
454
- return webshims.getRelOffset(errorBubble, elem);
455
- },
456
- setFocus: function(visual, offset){
457
- var focusElem = $(visual).getShadowFocusElement();
458
- var scrollTop = webshims.scrollRoot.scrollTop();
459
- var elemTop = ((offset || focusElem.offset()).top) - 30;
460
- var smooth;
461
-
462
- if(webshims.getID && alertElem == 'label'){
463
- errorBubble.attr('for', webshims.getID(focusElem));
464
- }
465
-
466
- if(scrollTop > elemTop){
467
- webshims.scrollRoot.animate(
468
- {scrollTop: elemTop - 5},
469
- {
470
- queue: false,
471
- duration: Math.max( Math.min( 600, (scrollTop - elemTop) * 1.5 ), 80 )
472
- }
473
- );
474
- smooth = true;
475
- }
476
- try {
477
- focusElem[0].focus();
478
- } catch(e){}
479
- if(smooth){
480
- webshims.scrollRoot.scrollTop(scrollTop);
481
- setTimeout(function(){
482
- webshims.scrollRoot.scrollTop(scrollTop);
483
- }, 0);
484
- }
485
- setTimeout(function(){
486
- $(document).on('focusout.validityalert', boundHide);
487
- }, 10);
488
- },
489
- getMessage: function(elem, message){
490
- if (!message) {
491
- message = getContentValidationMessage(elem[0]) || elem.prop('validationMessage');
492
- }
493
- if (message) {
494
- $('span.va-box', errorBubble).text(message);
495
- }
496
- else {
497
- this.hide();
498
- }
499
- },
500
- position: function(elem, offset){
501
- offset = offset ? $.extend({}, offset) : api.getOffsetFromBody(elem);
502
- offset.top += elem.outerHeight();
503
- errorBubble.css(offset);
504
- },
505
- show: function(){
506
- if(errorBubble.css('display') === 'none'){
507
- errorBubble.css({opacity: 0}).show();
508
- }
509
- errorBubble.addClass('va-visible').fadeTo(400, 1);
510
- },
511
- hide: function(){
512
- errorBubble.removeClass('va-visible').fadeOut();
513
- },
514
- clear: function(){
515
- clearTimeout(focusTimer);
516
- clearTimeout(hideTimer);
517
- $(document).unbind('.validityalert');
518
- $(window).unbind('.validityalert');
519
- errorBubble.stop().removeAttr('for');
520
- },
521
- _create: function(){
522
- if(errorBubble){return;}
523
- 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'});
524
- webshims.ready('DOM', function(){
525
- errorBubble.appendTo('body');
526
- if($.fn.bgIframe && $.browser.msie && parseInt($.browser.version, 10) < 7){
527
- errorBubble.bgIframe();
528
- }
529
- });
530
- }
531
- };
532
-
533
-
534
- boundHide = $.proxy(api, 'hide');
535
-
536
- return api;
537
- })();
538
-
539
-
540
- /* extension, but also used to fix native implementation workaround/bugfixes */
541
- (function(){
542
- var firstEvent,
543
- invalids = [],
544
- stopSubmitTimer,
545
- form
546
- ;
547
-
548
- $(document).on('invalid', function(e){
549
- if(e.wrongWebkitInvalid){return;}
550
- var jElm = $(e.target);
551
- var shadowElem = jElm.getShadowElement();
552
- if(!shadowElem.hasClass(invalidClass)){
553
- shadowElem.addClass(invalidClasses).removeClass(validClasses);
554
- setTimeout(function(){
555
- $(e.target).trigger('changedinvalid').trigger('changedvaliditystate');
556
- }, 0);
557
- }
558
-
559
- if(!firstEvent){
560
- //trigger firstinvalid
561
- firstEvent = $.Event('firstinvalid');
562
- firstEvent.isInvalidUIPrevented = e.isDefaultPrevented;
563
- var firstSystemInvalid = $.Event('firstinvalidsystem');
564
- $(document).triggerHandler(firstSystemInvalid, {element: e.target, form: e.target.form, isInvalidUIPrevented: e.isDefaultPrevented});
565
- jElm.trigger(firstEvent);
566
- }
567
-
568
- //if firstinvalid was prevented all invalids will be also prevented
569
- if( firstEvent && firstEvent.isDefaultPrevented() ){
570
- e.preventDefault();
571
- }
572
- invalids.push(e.target);
573
- e.extraData = 'fix';
574
- clearTimeout(stopSubmitTimer);
575
- stopSubmitTimer = setTimeout(function(){
576
- var lastEvent = {type: 'lastinvalid', cancelable: false, invalidlist: $(invalids)};
577
- //reset firstinvalid
578
- firstEvent = false;
579
- invalids = [];
580
- $(e.target).trigger(lastEvent, lastEvent);
581
- }, 9);
582
- jElm = null;
583
- shadowElem = null;
584
- });
585
- })();
586
-
587
- $.fn.getErrorMessage = function(){
588
- var message = '';
589
- var elem = this[0];
590
- if(elem){
591
- message = getContentValidationMessage(elem) || $.prop(elem, 'customValidationMessage') || $.prop(elem, 'validationMessage');
592
- }
593
- return message;
594
- };
595
-
596
- if(options.replaceValidationUI){
597
- webshims.ready('DOM forms', function(){
598
- $(document).on('firstinvalid', function(e){
599
- if(!e.isInvalidUIPrevented()){
600
- e.preventDefault();
601
- $.webshims.validityAlert.showFor( e.target, $(e.target).prop('customValidationMessage') );
602
- }
603
- });
604
- });
605
- }
606
-
607
- });
608
- if(!Modernizr.formvalidation || jQuery.webshims.bugs.bustedValidity){
609
- jQuery.webshims.register('form-shim-extend', function($, webshims, window, document){
610
- "use strict";
611
- webshims.inputTypes = webshims.inputTypes || {};
612
- //some helper-functions
613
- var cfg = webshims.cfg.forms;
614
- var isSubmit;
615
-
616
- var isNumber = function(string){
617
- return (typeof string == 'number' || (string && string == string * 1));
618
- },
619
- typeModels = webshims.inputTypes,
620
- checkTypes = {
621
- radio: 1,
622
- checkbox: 1
623
- },
624
- getType = function(elem){
625
- return (elem.getAttribute('type') || elem.type || '').toLowerCase();
626
- }
627
- ;
628
-
629
- //API to add new input types
630
- webshims.addInputType = function(type, obj){
631
- typeModels[type] = obj;
632
- };
633
-
634
- //contsrain-validation-api
635
- var validityPrototype = {
636
- customError: false,
637
-
638
- typeMismatch: false,
639
- rangeUnderflow: false,
640
- rangeOverflow: false,
641
- stepMismatch: false,
642
- tooLong: false,
643
- patternMismatch: false,
644
- valueMissing: false,
645
-
646
- valid: true
647
- };
648
-
649
- var isPlaceholderOptionSelected = function(select){
650
- if(select.type == 'select-one' && select.size < 2){
651
- var option = $('> option:first-child', select);
652
- return !!option.prop('selected');
653
- }
654
- return false;
655
- };
656
-
657
- var validityRules = {
658
- valueMissing: function(input, val, cache){
659
- if(!input.prop('required')){return false;}
660
- var ret = false;
661
- if(!('type' in cache)){
662
- cache.type = getType(input[0]);
663
- }
664
- if(cache.nodeName == 'select'){
665
- ret = (!val && (input[0].selectedIndex < 0 || isPlaceholderOptionSelected(input[0]) ));
666
- } else if(checkTypes[cache.type]){
667
- ret = (cache.type == 'checkbox') ? !input.is(':checked') : !webshims.modules["form-core"].getGroupElements(input).filter(':checked')[0];
668
- } else {
669
- ret = !(val);
670
- }
671
- return ret;
672
- },
673
- tooLong: function(){
674
- return false;
675
- },
676
- typeMismatch: function (input, val, cache){
677
- if(val === '' || cache.nodeName == 'select'){return false;}
678
- var ret = false;
679
- if(!('type' in cache)){
680
- cache.type = getType(input[0]);
681
- }
682
-
683
- if(typeModels[cache.type] && typeModels[cache.type].mismatch){
684
- ret = typeModels[cache.type].mismatch(val, input);
685
- } else if('validity' in input[0]){
686
- ret = input[0].validity.typeMismatch;
687
- }
688
- return ret;
689
- },
690
- patternMismatch: function(input, val, cache) {
691
- if(val === '' || cache.nodeName == 'select'){return false;}
692
- var pattern = input.attr('pattern');
693
- if(!pattern){return false;}
694
- try {
695
- pattern = new RegExp('^(?:' + pattern + ')$');
696
- } catch(er){
697
- webshims.error('invalid pattern value: "'+ pattern +'" | '+ er);
698
- pattern = false;
699
- }
700
- if(!pattern){return false;}
701
- return !(pattern.test(val));
702
- }
703
- }
704
- ;
705
-
706
- webshims.addValidityRule = function(type, fn){
707
- validityRules[type] = fn;
708
- };
709
-
710
- $.event.special.invalid = {
711
- add: function(){
712
- $.event.special.invalid.setup.call(this.form || this);
713
- },
714
- setup: function(){
715
- var form = this.form || this;
716
- if( $.data(form, 'invalidEventShim') ){
717
- form = null;
718
- return;
719
- }
720
- $(form)
721
- .data('invalidEventShim', true)
722
- .on('submit', $.event.special.invalid.handler)
723
- ;
724
- webshims.moveToFirstEvent(form, 'submit');
725
- if(webshims.bugs.bustedValidity && $.nodeName(form, 'form')){
726
- (function(){
727
- var noValidate = form.getAttribute('novalidate');
728
- form.setAttribute('novalidate', 'novalidate');
729
- webshims.data(form, 'bustedNoValidate', (noValidate == null) ? null : noValidate);
730
- })();
731
- }
732
- form = null;
733
- },
734
- teardown: $.noop,
735
- handler: function(e, d){
736
-
737
- if( e.type != 'submit' || e.testedValidity || !e.originalEvent || !$.nodeName(e.target, 'form') || $.prop(e.target, 'noValidate') ){return;}
738
-
739
- isSubmit = true;
740
- e.testedValidity = true;
741
- var notValid = !($(e.target).checkValidity());
742
- if(notValid){
743
- e.stopImmediatePropagation();
744
- isSubmit = false;
745
- return false;
746
- }
747
- isSubmit = false;
748
- }
749
- };
750
-
751
- var addSubmitBubbles = function(form){
752
- if (!$.support.submitBubbles && form && typeof form == 'object' && !form._submit_attached ) {
753
-
754
- $.event.add( form, 'submit._submit', function( event ) {
755
- event._submit_bubble = true;
756
- });
757
-
758
- form._submit_attached = true;
759
- }
760
- };
761
- if(!$.support.submitBubbles && $.event.special.submit){
762
- $.event.special.submit.setup = function() {
763
- // Only need this for delegated form submit events
764
- if ( $.nodeName( this, "form" ) ) {
765
- return false;
766
- }
767
-
768
- // Lazy-add a submit handler when a descendant form may potentially be submitted
769
- $.event.add( this, "click._submit keypress._submit", function( e ) {
770
- // Node name check avoids a VML-related crash in IE (#9807)
771
- var elem = e.target,
772
- form = $.nodeName( elem, 'input' ) || $.nodeName( elem, 'button' ) ? $.prop(elem, 'form') : undefined;
773
- addSubmitBubbles(form);
774
-
775
- });
776
- // return undefined since we don't need an event listener
777
- };
778
- }
779
-
780
- $.event.special.submit = $.event.special.submit || {setup: function(){return false;}};
781
- var submitSetup = $.event.special.submit.setup;
782
- $.extend($.event.special.submit, {
783
- setup: function(){
784
- if($.nodeName(this, 'form')){
785
- $(this).on('invalid', $.noop);
786
- } else {
787
- $('form', this).on('invalid', $.noop);
788
- }
789
- return submitSetup.apply(this, arguments);
790
- }
791
- });
792
-
793
- $(window).on('invalid', $.noop);
794
-
795
-
796
- webshims.addInputType('email', {
797
- mismatch: (function(){
798
- //taken from http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address
799
- var test = cfg.emailReg || /^[a-zA-Z0-9.!#$%&'*+-\/=?\^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
800
- return function(val){
801
- return !test.test(val);
802
- };
803
- })()
804
- });
805
-
806
- webshims.addInputType('url', {
807
- mismatch: (function(){
808
- //taken from scott gonzales
809
- var test = cfg.urlReg || /^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i;
810
- return function(val){
811
- return !test.test(val);
812
- };
813
- })()
814
- });
815
-
816
- webshims.defineNodeNameProperty('input', 'type', {
817
- prop: {
818
- get: function(){
819
- var elem = this;
820
- var type = (elem.getAttribute('type') || '').toLowerCase();
821
- return (webshims.inputTypes[type]) ? type : elem.type;
822
- }
823
- }
824
- });
825
-
826
- // IDLs for constrain validation API
827
- //ToDo: add object to this list
828
- webshims.defineNodeNamesProperties(['button', 'fieldset', 'output'], {
829
- checkValidity: {
830
- value: function(){return true;}
831
- },
832
- willValidate: {
833
- value: false
834
- },
835
- setCustomValidity: {
836
- value: $.noop
837
- },
838
- validity: {
839
- writeable: false,
840
- get: function(){
841
- return $.extend({}, validityPrototype);
842
- }
843
- }
844
- }, 'prop');
845
-
846
- var baseCheckValidity = function(elem){
847
- var e,
848
- v = $.prop(elem, 'validity')
849
- ;
850
- if(v){
851
- $.data(elem, 'cachedValidity', v);
852
- } else {
853
- return true;
854
- }
855
- if( !v.valid ){
856
- e = $.Event('invalid');
857
- var jElm = $(elem).trigger(e);
858
- if(isSubmit && !baseCheckValidity.unhandledInvalids && !e.isDefaultPrevented()){
859
- webshims.validityAlert.showFor(jElm);
860
- baseCheckValidity.unhandledInvalids = true;
861
- }
862
- }
863
- $.removeData(elem, 'cachedValidity');
864
- return v.valid;
865
- };
866
- var rsubmittable = /^(?:select|textarea|input)/i;
867
- webshims.defineNodeNameProperty('form', 'checkValidity', {
868
- prop: {
869
- value: function(){
870
-
871
- var ret = true,
872
- elems = $($.prop(this, 'elements')).filter(function(){
873
- if(!rsubmittable.test(this.nodeName)){return false;}
874
- var shadowData = webshims.data(this, 'shadowData');
875
- return !shadowData || !shadowData.nativeElement || shadowData.nativeElement === this;
876
- })
877
- ;
878
-
879
- baseCheckValidity.unhandledInvalids = false;
880
- for(var i = 0, len = elems.length; i < len; i++){
881
- if( !baseCheckValidity(elems[i]) ){
882
- ret = false;
883
- }
884
- }
885
- return ret;
886
- }
887
- }
888
- });
889
-
890
- webshims.defineNodeNamesProperties(['input', 'textarea', 'select'], {
891
- checkValidity: {
892
- value: function(){
893
- baseCheckValidity.unhandledInvalids = false;
894
- return baseCheckValidity($(this).getNativeElement()[0]);
895
- }
896
- },
897
- setCustomValidity: {
898
- value: function(error){
899
- $.removeData(this, 'cachedValidity');
900
- webshims.data(this, 'customvalidationMessage', ''+error);
901
- }
902
- },
903
- willValidate: {
904
- writeable: false,
905
- get: (function(){
906
- var types = {
907
- button: 1,
908
- reset: 1,
909
- hidden: 1,
910
- image: 1
911
- }
912
- ;
913
- return function(){
914
- var elem = $(this).getNativeElement()[0];
915
- //elem.name && <- we don't use to make it easier for developers
916
- return !!(!elem.disabled && !elem.readOnly && !types[elem.type] );
917
- };
918
- })()
919
- },
920
- validity: {
921
- writeable: false,
922
- get: function(){
923
- var jElm = $(this).getNativeElement();
924
- var elem = jElm[0];
925
- var validityState = $.data(elem, 'cachedValidity');
926
- if(validityState){
927
- return validityState;
928
- }
929
- validityState = $.extend({}, validityPrototype);
930
-
931
- if( !$.prop(elem, 'willValidate') || elem.type == 'submit' ){
932
- return validityState;
933
- }
934
- var val = jElm.val(),
935
- cache = {nodeName: elem.nodeName.toLowerCase()}
936
- ;
937
-
938
- validityState.customError = !!(webshims.data(elem, 'customvalidationMessage'));
939
- if( validityState.customError ){
940
- validityState.valid = false;
941
- }
942
-
943
- $.each(validityRules, function(rule, fn){
944
- if (fn(jElm, val, cache)) {
945
- validityState[rule] = true;
946
- validityState.valid = false;
947
- }
948
- });
949
- $(this).getShadowFocusElement().attr('aria-invalid', validityState.valid ? 'false' : 'true');
950
- jElm = null;
951
- elem = null;
952
- return validityState;
953
- }
954
- }
955
- }, 'prop');
956
-
957
- webshims.defineNodeNamesBooleanProperty(['input', 'textarea', 'select'], 'required', {
958
- set: function(value){
959
- $(this).getShadowFocusElement().attr('aria-required', !!(value)+'');
960
- },
961
- initAttr: (!$.browser.msie || webshims.browserVersion > 7)//only if we have aria-support
962
- });
963
-
964
- webshims.reflectProperties(['input'], ['pattern']);
965
-
966
-
967
- if( !('maxLength' in document.createElement('textarea')) ){
968
- var constrainMaxLength = (function(){
969
- var timer;
970
- var curLength = 0;
971
- var lastElement = $([]);
972
- var max = 1e9;
973
- var constrainLength = function(){
974
- var nowValue = lastElement.prop('value');
975
- var nowLen = nowValue.length;
976
- if(nowLen > curLength && nowLen > max){
977
- nowLen = Math.max(curLength, max);
978
- lastElement.prop('value', nowValue.substr(0, nowLen ));
979
- }
980
- curLength = nowLen;
981
- };
982
- var remove = function(){
983
- clearTimeout(timer);
984
- lastElement.unbind('.maxlengthconstraint');
985
- };
986
- return function(element, maxLength){
987
- remove();
988
- if(maxLength > -1){
989
- max = maxLength;
990
- curLength = $.prop(element, 'value').length;
991
- lastElement = $(element);
992
- lastElement.on({
993
- 'keydown.maxlengthconstraint keypress.maxlengthconstraint paste.maxlengthconstraint cut.maxlengthconstraint': function(e){
994
- setTimeout(constrainLength, 0);
995
- },
996
- 'keyup.maxlengthconstraint': constrainLength,
997
- 'blur.maxlengthconstraint': remove
998
- });
999
- timer = setInterval(constrainLength, 200);
1000
- }
1001
- };
1002
- })();
1003
-
1004
- constrainMaxLength.update = function(element, maxLength){
1005
- if($(element).is(':focus')){
1006
- if(!maxLength){
1007
- maxLength = $.prop(element, 'maxlength');
1008
- }
1009
- constrainMaxLength(element, maxLength);
1010
- }
1011
- };
1012
-
1013
- $(document).on('focusin', function(e){
1014
- var maxLength;
1015
- if(e.target.nodeName == "TEXTAREA" && (maxLength = $.prop(e.target, 'maxlength')) > -1){
1016
- constrainMaxLength(e.target, maxLength);
1017
- }
1018
- });
1019
-
1020
- webshims.defineNodeNameProperty('textarea', 'maxlength', {
1021
- attr: {
1022
- set: function(val){
1023
- this.setAttribute('maxlength', ''+val);
1024
- constrainMaxLength.update(this);
1025
- },
1026
- get: function(){
1027
- var ret = this.getAttribute('maxlength');
1028
- return ret == null ? undefined : ret;
1029
- }
1030
- },
1031
- prop: {
1032
- set: function(val){
1033
- if(isNumber(val)){
1034
- if(val < 0){
1035
- throw('INDEX_SIZE_ERR');
1036
- }
1037
- val = parseInt(val, 10);
1038
- this.setAttribute('maxlength', val);
1039
- constrainMaxLength.update(this, val);
1040
- return;
1041
- }
1042
- this.setAttribute('maxlength', '0');
1043
- constrainMaxLength.update(this, 0);
1044
- },
1045
- get: function(){
1046
- var val = this.getAttribute('maxlength');
1047
- return (isNumber(val) && val >= 0) ? parseInt(val, 10) : -1;
1048
-
1049
- }
1050
- }
1051
- });
1052
- webshims.defineNodeNameProperty('textarea', 'maxLength', {
1053
- prop: {
1054
- set: function(val){
1055
- $.prop(this, 'maxlength', val);
1056
- },
1057
- get: function(){
1058
- return $.prop(this, 'maxlength');
1059
- }
1060
- }
1061
- });
1062
- }
1063
-
1064
-
1065
-
1066
- var submitterTypes = {submit: 1, button: 1, image: 1};
1067
- var formSubmitterDescriptors = {};
1068
- [
1069
- {
1070
- name: "enctype",
1071
- limitedTo: {
1072
- "application/x-www-form-urlencoded": 1,
1073
- "multipart/form-data": 1,
1074
- "text/plain": 1
1075
- },
1076
- defaultProp: "application/x-www-form-urlencoded",
1077
- proptype: "enum"
1078
- },
1079
- {
1080
- name: "method",
1081
- limitedTo: {
1082
- "get": 1,
1083
- "post": 1
1084
- },
1085
- defaultProp: "get",
1086
- proptype: "enum"
1087
- },
1088
- {
1089
- name: "action",
1090
- proptype: "url"
1091
- },
1092
- {
1093
- name: "target"
1094
- },
1095
- {
1096
- name: "novalidate",
1097
- propName: "noValidate",
1098
- proptype: "boolean"
1099
- }
1100
- ].forEach(function(desc){
1101
- var propName = 'form'+ (desc.propName || desc.name).replace(/^[a-z]/, function(f){
1102
- return f.toUpperCase();
1103
- });
1104
- var attrName = 'form'+ desc.name;
1105
- var formName = desc.name;
1106
- var eventName = 'click.webshimssubmittermutate'+formName;
1107
-
1108
- var changeSubmitter = function(){
1109
- var elem = this;
1110
- if( !('form' in elem) || !submitterTypes[elem.type] ){return;}
1111
- var form = $.prop(elem, 'form');
1112
- if(!form){return;}
1113
- var attr = $.attr(elem, attrName);
1114
- if(attr != null && ( !desc.limitedTo || attr.toLowerCase() === $.prop(elem, propName))){
1115
-
1116
- var oldAttr = $.attr(form, formName);
1117
-
1118
- $.attr(form, formName, attr);
1119
- setTimeout(function(){
1120
- if(oldAttr != null){
1121
- $.attr(form, formName, oldAttr);
1122
- } else {
1123
- try {
1124
- $(form).removeAttr(formName);
1125
- } catch(er){
1126
- form.removeAttribute(formName);
1127
- }
1128
- }
1129
- }, 9);
1130
- }
1131
- };
1132
-
1133
-
1134
-
1135
- switch(desc.proptype) {
1136
- case "url":
1137
- var urlForm = document.createElement('form');
1138
- formSubmitterDescriptors[propName] = {
1139
- prop: {
1140
- set: function(value){
1141
- $.attr(this, attrName, value);
1142
- },
1143
- get: function(){
1144
- var value = $.attr(this, attrName);
1145
- if(value == null){return '';}
1146
- urlForm.setAttribute('action', value);
1147
- return urlForm.action;
1148
- }
1149
- }
1150
- };
1151
- break;
1152
- case "boolean":
1153
- formSubmitterDescriptors[propName] = {
1154
- prop: {
1155
- set: function(val){
1156
- val = !!val;
1157
- if(val){
1158
- $.attr(this, 'formnovalidate', 'formnovalidate');
1159
- } else {
1160
- $(this).removeAttr('formnovalidate');
1161
- }
1162
- },
1163
- get: function(){
1164
- return $.attr(this, 'formnovalidate') != null;
1165
- }
1166
- }
1167
- };
1168
- break;
1169
- case "enum":
1170
- formSubmitterDescriptors[propName] = {
1171
- prop: {
1172
- set: function(value){
1173
- $.attr(this, attrName, value);
1174
- },
1175
- get: function(){
1176
- var value = $.attr(this, attrName);
1177
- return (!value || ( (value = value.toLowerCase()) && !desc.limitedTo[value] )) ? desc.defaultProp : value;
1178
- }
1179
- }
1180
- };
1181
- break;
1182
- default:
1183
- formSubmitterDescriptors[propName] = {
1184
- prop: {
1185
- set: function(value){
1186
- $.attr(this, attrName, value);
1187
- },
1188
- get: function(){
1189
- var value = $.attr(this, attrName);
1190
- return (value != null) ? value : "";
1191
- }
1192
- }
1193
- };
1194
- }
1195
-
1196
-
1197
- if(!formSubmitterDescriptors[attrName]){
1198
- formSubmitterDescriptors[attrName] = {};
1199
- }
1200
- formSubmitterDescriptors[attrName].attr = {
1201
- set: function(value){
1202
- formSubmitterDescriptors[attrName].attr._supset.call(this, value);
1203
- $(this).unbind(eventName).on(eventName, changeSubmitter);
1204
- },
1205
- get: function(){
1206
- return formSubmitterDescriptors[attrName].attr._supget.call(this);
1207
- }
1208
- };
1209
- formSubmitterDescriptors[attrName].initAttr = true;
1210
- formSubmitterDescriptors[attrName].removeAttr = {
1211
- value: function(){
1212
- $(this).unbind(eventName);
1213
- formSubmitterDescriptors[attrName].removeAttr._supvalue.call(this);
1214
- }
1215
- };
1216
- });
1217
-
1218
- webshims.defineNodeNamesProperties(['input', 'button'], formSubmitterDescriptors);
1219
-
1220
-
1221
- if(!$.support.getSetAttribute && $('<form novalidate></form>').attr('novalidate') == null){
1222
- webshims.defineNodeNameProperty('form', 'novalidate', {
1223
- attr: {
1224
- set: function(val){
1225
- this.setAttribute('novalidate', ''+val);
1226
- },
1227
- get: function(){
1228
- var ret = this.getAttribute('novalidate');
1229
- return ret == null ? undefined : ret;
1230
- }
1231
- }
1232
- });
1233
- } else if(webshims.bugs.bustedValidity){
1234
-
1235
- webshims.defineNodeNameProperty('form', 'novalidate', {
1236
- attr: {
1237
- set: function(val){
1238
- webshims.data(this, 'bustedNoValidate', ''+val);
1239
- },
1240
- get: function(){
1241
- var ret = webshims.data(this, 'bustedNoValidate');
1242
- return ret == null ? undefined : ret;
1243
- }
1244
- },
1245
- removeAttr: {
1246
- value: function(){
1247
- webshims.data(this, 'bustedNoValidate', null);
1248
- }
1249
- }
1250
- });
1251
-
1252
- $.each(['rangeUnderflow', 'rangeOverflow', 'stepMismatch'], function(i, name){
1253
- validityRules[name] = function(elem){
1254
- return (elem[0].validity || {})[name] || false;
1255
- };
1256
- });
1257
-
1258
- }
1259
-
1260
- webshims.defineNodeNameProperty('form', 'noValidate', {
1261
- prop: {
1262
- set: function(val){
1263
- val = !!val;
1264
- if(val){
1265
- $.attr(this, 'novalidate', 'novalidate');
1266
- } else {
1267
- $(this).removeAttr('novalidate');
1268
- }
1269
- },
1270
- get: function(){
1271
- return $.attr(this, 'novalidate') != null;
1272
- }
1273
- }
1274
- });
1275
-
1276
- if($.browser.webkit && Modernizr.inputtypes.date){
1277
- (function(){
1278
-
1279
- var noInputTriggerEvts = {updateInput: 1, input: 1},
1280
- fixInputTypes = {
1281
- date: 1,
1282
- time: 1,
1283
- "datetime-local": 1
1284
- },
1285
- noFocusEvents = {
1286
- focusout: 1,
1287
- blur: 1
1288
- },
1289
- changeEvts = {
1290
- updateInput: 1,
1291
- change: 1
1292
- },
1293
- observe = function(input){
1294
- var timer,
1295
- focusedin = true,
1296
- lastInputVal = input.prop('value'),
1297
- lastChangeVal = lastInputVal,
1298
- trigger = function(e){
1299
- //input === null
1300
- if(!input){return;}
1301
- var newVal = input.prop('value');
1302
-
1303
- if(newVal !== lastInputVal){
1304
- lastInputVal = newVal;
1305
- if(!e || !noInputTriggerEvts[e.type]){
1306
- input.trigger('input');
1307
- }
1308
- }
1309
- if(e && changeEvts[e.type]){
1310
- lastChangeVal = newVal;
1311
- }
1312
- if(!focusedin && newVal !== lastChangeVal){
1313
- input.trigger('change');
1314
- }
1315
- },
1316
- extraTimer,
1317
- extraTest = function(){
1318
- clearTimeout(extraTimer);
1319
- extraTimer = setTimeout(trigger, 9);
1320
- },
1321
- unbind = function(e){
1322
- clearInterval(timer);
1323
- setTimeout(function(){
1324
- if(e && noFocusEvents[e.type]){
1325
- focusedin = false;
1326
- }
1327
- if(input){
1328
- input.unbind('focusout blur', unbind).unbind('input change updateInput', trigger);
1329
- trigger();
1330
- }
1331
- input = null;
1332
- }, 1);
1333
-
1334
- }
1335
- ;
1336
-
1337
- clearInterval(timer);
1338
- timer = setInterval(trigger, 160);
1339
- extraTest();
1340
- input
1341
- .off({
1342
- 'focusout blur': unbind,
1343
- 'input change updateInput': trigger
1344
- })
1345
- .on({
1346
- 'focusout blur': unbind,
1347
- 'input updateInput change': trigger
1348
- })
1349
- ;
1350
- }
1351
- ;
1352
- if($.event.customEvent){
1353
- $.event.customEvent.updateInput = true;
1354
- }
1355
-
1356
- (function(){
1357
-
1358
- var correctValue = function(elem){
1359
- var i = 1;
1360
- var len = 3;
1361
- var abort, val;
1362
- if(elem.type == 'date' && (isSubmit || !$(elem).is(':focus'))){
1363
- val = elem.value;
1364
- if(val && val.length < 10 && (val = val.split('-')) && val.length == len){
1365
- for(; i < len; i++){
1366
- if(val[i].length == 1){
1367
- val[i] = '0'+val[i];
1368
- } else if(val[i].length != 2){
1369
- abort = true;
1370
- break;
1371
- }
1372
- }
1373
- if(!abort){
1374
- val = val.join('-');
1375
- $.prop(elem, 'value', val);
1376
- return val;
1377
- }
1378
- }
1379
- }
1380
- };
1381
- var inputCheckValidityDesc, formCheckValidityDesc, inputValueDesc, inputValidityDesc;
1382
-
1383
- inputCheckValidityDesc = webshims.defineNodeNameProperty('input', 'checkValidity', {
1384
- prop: {
1385
- value: function(){
1386
- correctValue(this);
1387
- return inputCheckValidityDesc.prop._supvalue.apply(this, arguments);
1388
- }
1389
- }
1390
- });
1391
-
1392
- formCheckValidityDesc = webshims.defineNodeNameProperty('form', 'checkValidity', {
1393
- prop: {
1394
- value: function(){
1395
- $('input', this).each(function(){
1396
- correctValue(this);
1397
- });
1398
- return formCheckValidityDesc.prop._supvalue.apply(this, arguments);
1399
- }
1400
- }
1401
- });
1402
-
1403
- inputValueDesc = webshims.defineNodeNameProperty('input', 'value', {
1404
- prop: {
1405
- set: function(){
1406
- return inputValueDesc.prop._supset.apply(this, arguments);
1407
- },
1408
- get: function(){
1409
- return correctValue(this) || inputValueDesc.prop._supget.apply(this, arguments);
1410
- }
1411
- }
1412
- });
1413
-
1414
- inputValidityDesc = webshims.defineNodeNameProperty('input', 'validity', {
1415
- prop: {
1416
- writeable: false,
1417
- get: function(){
1418
- correctValue(this);
1419
- return inputValidityDesc.prop._supget.apply(this, arguments);
1420
- }
1421
- }
1422
- });
1423
-
1424
- $(document).on('change', function(e){
1425
- correctValue(e.target);
1426
- });
1427
-
1428
- })();
1429
-
1430
- $(document)
1431
- .on('focusin', function(e){
1432
- if( e.target && fixInputTypes[e.target.type] && !e.target.readOnly && !e.target.disabled ){
1433
- observe($(e.target));
1434
- }
1435
- })
1436
- ;
1437
-
1438
-
1439
- })();
1440
- }
1441
-
1442
- webshims.addReady(function(context, contextElem){
1443
- //start constrain-validation
1444
- var focusElem;
1445
- $('form', context)
1446
- .add(contextElem.filter('form'))
1447
- .bind('invalid', $.noop)
1448
- ;
1449
-
1450
- try {
1451
- if(context == document && !('form' in (document.activeElement || {}))) {
1452
- focusElem = $('input[autofocus], select[autofocus], textarea[autofocus]', context).eq(0).getShadowFocusElement()[0];
1453
- if (focusElem && focusElem.offsetHeight && focusElem.offsetWidth) {
1454
- focusElem.focus();
1455
- }
1456
- }
1457
- }
1458
- catch (er) {}
1459
-
1460
- });
1461
-
1462
- if(!Modernizr.formattribute || !Modernizr.fieldsetdisabled){
1463
- (function(){
1464
- (function(prop, undefined){
1465
- $.prop = function(elem, name, value){
1466
- var ret;
1467
- if(elem && elem.nodeType == 1 && value === undefined && $.nodeName(elem, 'form') && elem.id){
1468
- ret = document.getElementsByName(name);
1469
- if(!ret || !ret.length){
1470
- ret = document.getElementById(name);
1471
- }
1472
- if(ret){
1473
- ret = $(ret).filter(function(){
1474
- return $.prop(this, 'form') == elem;
1475
- }).get();
1476
- if(ret.length){
1477
- return ret.length == 1 ? ret[0] : ret;
1478
- }
1479
- }
1480
- }
1481
- return prop.apply(this, arguments);
1482
- };
1483
- })($.prop, undefined);
1484
- var removeAddedElements = function(form){
1485
- var elements = $.data(form, 'webshimsAddedElements');
1486
- if(elements){
1487
- elements.remove();
1488
- $.removeData(form, 'webshimsAddedElements');
1489
- }
1490
- };
1491
- var rCRLF = /\r?\n/g,
1492
- rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
1493
- rselectTextarea = /^(?:select|textarea)/i;
1494
-
1495
- if(!Modernizr.formattribute){
1496
- webshims.defineNodeNamesProperty(['input', 'textarea', 'select', 'button', 'fieldset'], 'form', {
1497
- prop: {
1498
- get: function(){
1499
- var form = webshims.contentAttr(this, 'form');
1500
- if(form){
1501
- form = document.getElementById(form);
1502
- if(form && !$.nodeName(form, 'form')){
1503
- form = null;
1504
- }
1505
- }
1506
- return form || this.form;
1507
- },
1508
- writeable: false
1509
- }
1510
- });
1511
-
1512
-
1513
- webshims.defineNodeNamesProperty(['form'], 'elements', {
1514
- prop: {
1515
- get: function(){
1516
- var id = this.id;
1517
- var elements = $.makeArray(this.elements);
1518
- if(id){
1519
- elements = $(elements).add('input[form="'+ id +'"], select[form="'+ id +'"], textarea[form="'+ id +'"], button[form="'+ id +'"], fieldset[form="'+ id +'"]').not('.webshims-visual-hide > *').get();
1520
- }
1521
- return elements;
1522
- },
1523
- writeable: false
1524
- }
1525
- });
1526
-
1527
-
1528
-
1529
- $(function(){
1530
- var stopPropagation = function(e){
1531
- e.stopPropagation();
1532
- };
1533
- $(document).on('submit', function(e){
1534
-
1535
- if(!e.isDefaultPrevented()){
1536
- var form = e.target;
1537
- var id = form.id;
1538
- var elements;
1539
-
1540
-
1541
- if(id){
1542
- removeAddedElements(form);
1543
-
1544
- elements = $('input[form="'+ id +'"], select[form="'+ id +'"], textarea[form="'+ id +'"]')
1545
- .filter(function(){
1546
- return !this.disabled && this.name && this.form != form;
1547
- })
1548
- .clone()
1549
- ;
1550
- if(elements.length){
1551
- $.data(form, 'webshimsAddedElements', $('<div class="webshims-visual-hide" />').append(elements).appendTo(form));
1552
- setTimeout(function(){
1553
- removeAddedElements(form);
1554
- }, 9);
1555
- }
1556
- elements = null;
1557
- }
1558
- }
1559
- });
1560
-
1561
- $(document).on('click', function(e){
1562
- if(!e.isDefaultPrevented() && $(e.target).is('input[type="submit"][form], button[form], input[type="button"][form], input[type="image"][form], input[type="reset"][form]')){
1563
- var trueForm = $.prop(e.target, 'form');
1564
- var formIn = e.target.form;
1565
- var clone;
1566
- if(trueForm && trueForm != formIn){
1567
- clone = $(e.target)
1568
- .clone()
1569
- .removeAttr('form')
1570
- .addClass('webshims-visual-hide')
1571
- .on('click', stopPropagation)
1572
- .appendTo(trueForm)
1573
- ;
1574
- if(formIn){
1575
- e.preventDefault();
1576
- }
1577
- addSubmitBubbles(trueForm);
1578
- clone.trigger('click');
1579
- setTimeout(function(){
1580
- clone.remove();
1581
- clone = null;
1582
- }, 9);
1583
- }
1584
- }
1585
- });
1586
- });
1587
- }
1588
-
1589
- if(!Modernizr.fieldsetdisabled){
1590
- webshims.defineNodeNamesProperty(['fieldset'], 'elements', {
1591
- prop: {
1592
- get: function(){
1593
- //add listed elements without keygen, object, output
1594
- return $('input, select, textarea, button, fieldset', this).get() || [];
1595
- },
1596
- writeable: false
1597
- }
1598
- });
1599
- }
1600
-
1601
- $.fn.serializeArray = function() {
1602
- return this.map(function(){
1603
- var elements = $.prop(this, 'elements');
1604
- return elements ? $.makeArray( elements ) : this;
1605
- })
1606
- .filter(function(){
1607
- return this.name && !this.disabled &&
1608
- ( this.checked || rselectTextarea.test( this.nodeName ) ||
1609
- rinput.test( this.type ) );
1610
- })
1611
- .map(function( i, elem ){
1612
- var val = $( this ).val();
1613
-
1614
- return val == null ?
1615
- null :
1616
- $.isArray( val ) ?
1617
- $.map( val, function( val, i ){
1618
- return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
1619
- }) :
1620
- { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
1621
- }).get();
1622
- };
1623
-
1624
- })();
1625
- }
1626
-
1627
- try {
1628
- document.querySelector(':checked');
1629
- } catch(er){
1630
- (function(){
1631
- var checkInputs = {
1632
- radio: 1,
1633
- checkbox: 1
1634
- };
1635
- var selectChange = function(){
1636
- var options = this.options || [];
1637
- var i, len, option;
1638
- for(i = 0, len = options.length; i < len; i++){
1639
- option = $(options[i]);
1640
- option[$.prop(options[i], 'selected') ? 'addClass' : 'removeClass']('prop-checked');
1641
- }
1642
- };
1643
- var checkChange = function(){
1644
- var fn = $.prop(this, 'checked') ? 'addClass' : 'removeClass';
1645
- var className = this.className || '';
1646
- var parent;
1647
-
1648
- //IE8- has problems to update styles, we help
1649
- if( (className.indexOf('prop-checked') == -1) == (fn == 'addClass')){
1650
- $(this)[fn]('prop-checked');
1651
- if((parent = this.parentNode)){
1652
- parent.className = parent.className;
1653
- }
1654
- }
1655
- };
1656
-
1657
-
1658
- webshims.onNodeNamesPropertyModify('select', 'value', selectChange);
1659
- webshims.onNodeNamesPropertyModify('select', 'selectedIndex', selectChange);
1660
- webshims.onNodeNamesPropertyModify('option', 'selected', function(){
1661
- $(this).closest('select').each(selectChange);
1662
- });
1663
- webshims.onNodeNamesPropertyModify('input', 'checked', function(value, boolVal){
1664
- var type = this.type;
1665
- if(type == 'radio' && boolVal){
1666
- webshims.modules["form-core"].getGroupElements(this).each(checkChange);
1667
- } else if(checkInputs[type]) {
1668
- $(this).each(checkChange);
1669
- }
1670
- });
1671
-
1672
- $(document).on('change', function(e){
1673
-
1674
- if(checkInputs[e.target.type]){
1675
- if(e.target.type == 'radio'){
1676
- webshims.modules["form-core"].getGroupElements(e.target).each(checkChange);
1677
- } else {
1678
- $(e.target)[$.prop(e.target, 'checked') ? 'addClass' : 'removeClass']('prop-checked');
1679
- }
1680
- } else if(e.target.nodeName.toLowerCase() == 'select'){
1681
- $(e.target).each(selectChange);
1682
- }
1683
- });
1684
-
1685
- webshims.addReady(function(context, contextElem){
1686
- $('option, input', context)
1687
- .add(contextElem.filter('option, input'))
1688
- .each(function(){
1689
- var prop;
1690
- if(checkInputs[this.type]){
1691
- prop = 'checked';
1692
- } else if(this.nodeName.toLowerCase() == 'option'){
1693
- prop = 'selected';
1694
- }
1695
- if(prop){
1696
- $(this)[$.prop(this, prop) ? 'addClass' : 'removeClass']('prop-checked');
1697
- }
1698
-
1699
- })
1700
- ;
1701
- });
1702
- })();
1703
- }
1704
-
1705
- (function(){
1706
- Modernizr.textareaPlaceholder = !!('placeholder' in $('<textarea />')[0]);
1707
- var bustedTextarea = $.browser.webkit && Modernizr.textareaPlaceholder && webshims.browserVersion < 535;
1708
- if(Modernizr.input.placeholder && Modernizr.textareaPlaceholder && !bustedTextarea){return;}
1709
-
1710
- var isOver = (webshims.cfg.forms.placeholderType == 'over');
1711
- var isResponsive = (webshims.cfg.forms.responsivePlaceholder);
1712
- var polyfillElements = ['textarea'];
1713
- if(!Modernizr.input.placeholder){
1714
- polyfillElements.push('input');
1715
- }
1716
-
1717
- var setSelection = function(elem){
1718
- try {
1719
- if(elem.setSelectionRange){
1720
- elem.setSelectionRange(0, 0);
1721
- return true;
1722
- } else if(elem.createTextRange){
1723
- var range = elem.createTextRange();
1724
- range.collapse(true);
1725
- range.moveEnd('character', 0);
1726
- range.moveStart('character', 0);
1727
- range.select();
1728
- return true;
1729
- }
1730
- } catch(er){}
1731
- };
1732
-
1733
- var hidePlaceholder = function(elem, data, value, _onFocus){
1734
- if(value === false){
1735
- value = $.prop(elem, 'value');
1736
- }
1737
- if(!isOver && elem.type != 'password'){
1738
- if(!value && _onFocus && setSelection(elem)){
1739
- var selectTimer = setTimeout(function(){
1740
- setSelection(elem);
1741
- }, 9);
1742
- $(elem)
1743
- .off('.placeholderremove')
1744
- .on({
1745
- 'keydown.placeholderremove keypress.placeholderremove paste.placeholderremove input.placeholderremove': function(e){
1746
- if(e && (e.keyCode == 17 || e.keyCode == 16)){return;}
1747
- elem.value = $.prop(elem, 'value');
1748
- data.box.removeClass('placeholder-visible');
1749
- clearTimeout(selectTimer);
1750
- $(elem).unbind('.placeholderremove');
1751
- },
1752
- 'mousedown.placeholderremove drag.placeholderremove select.placeholderremove': function(e){
1753
- setSelection(elem);
1754
- clearTimeout(selectTimer);
1755
- selectTimer = setTimeout(function(){
1756
- setSelection(elem);
1757
- }, 9);
1758
- },
1759
- 'blur.placeholderremove': function(){
1760
- clearTimeout(selectTimer);
1761
- $(elem).unbind('.placeholderremove');
1762
- }
1763
- })
1764
- ;
1765
- return;
1766
- }
1767
- elem.value = value;
1768
- } else if(!value && _onFocus){
1769
- $(elem)
1770
- .off('.placeholderremove')
1771
- .on({
1772
- 'keydown.placeholderremove keypress.placeholderremove paste.placeholderremove input.placeholderremove': function(e){
1773
- if(e && (e.keyCode == 17 || e.keyCode == 16)){return;}
1774
- data.box.removeClass('placeholder-visible');
1775
- $(elem).unbind('.placeholderremove');
1776
- },
1777
- 'blur.placeholderremove': function(){
1778
- $(elem).unbind('.placeholderremove');
1779
- }
1780
- })
1781
- ;
1782
- return;
1783
- }
1784
- data.box.removeClass('placeholder-visible');
1785
- },
1786
- showPlaceholder = function(elem, data, placeholderTxt){
1787
- if(placeholderTxt === false){
1788
- placeholderTxt = $.prop(elem, 'placeholder');
1789
- }
1790
-
1791
- if(!isOver && elem.type != 'password'){
1792
- elem.value = placeholderTxt;
1793
- }
1794
- data.box.addClass('placeholder-visible');
1795
- },
1796
- changePlaceholderVisibility = function(elem, value, placeholderTxt, data, type){
1797
- if(!data){
1798
- data = $.data(elem, 'placeHolder');
1799
- if(!data){return;}
1800
- }
1801
- $(elem).unbind('.placeholderremove');
1802
- if(type == 'focus' || (!type && $(elem).is(':focus'))){
1803
- if(elem.type == 'password' || isOver || $(elem).hasClass('placeholder-visible')){
1804
- hidePlaceholder(elem, data, '', true);
1805
- }
1806
- return;
1807
- }
1808
- if(value === false){
1809
- value = $.prop(elem, 'value');
1810
- }
1811
- if(value){
1812
- hidePlaceholder(elem, data, value);
1813
- return;
1814
- }
1815
- if(placeholderTxt === false){
1816
- placeholderTxt = $.attr(elem, 'placeholder') || '';
1817
- }
1818
- if(placeholderTxt && !value){
1819
- showPlaceholder(elem, data, placeholderTxt);
1820
- } else {
1821
- hidePlaceholder(elem, data, value);
1822
- }
1823
- },
1824
- createPlaceholder = function(elem){
1825
- elem = $(elem);
1826
- var id = elem.prop('id'),
1827
- hasLabel = !!(elem.prop('title') || elem.attr('aria-labelledby'))
1828
- ;
1829
- if(!hasLabel && id){
1830
- hasLabel = !!( $('label[for="'+ id +'"]', elem[0].form)[0] );
1831
- }
1832
- if(!hasLabel){
1833
- if(!id){
1834
- id = $.webshims.getID(elem);
1835
- }
1836
- hasLabel = !!($('label #'+ id)[0]);
1837
- }
1838
- return $( hasLabel ? '<span class="placeholder-text"></span>' : '<label for="'+ id +'" class="placeholder-text"></label>');
1839
- },
1840
- pHolder = (function(){
1841
- var delReg = /\n|\r|\f|\t/g,
1842
- allowedPlaceholder = {
1843
- text: 1,
1844
- search: 1,
1845
- url: 1,
1846
- email: 1,
1847
- password: 1,
1848
- tel: 1,
1849
- number: 1
1850
- }
1851
- ;
1852
-
1853
- return {
1854
- create: function(elem){
1855
- var data = $.data(elem, 'placeHolder');
1856
- var form;
1857
- var responsiveElem;
1858
- if(data){return data;}
1859
- data = $.data(elem, 'placeHolder', {});
1860
-
1861
- $(elem).on('focus.placeholder blur.placeholder', function(e){
1862
- changePlaceholderVisibility(this, false, false, data, e.type );
1863
- data.box[e.type == 'focus' ? 'addClass' : 'removeClass']('placeholder-focused');
1864
- });
1865
-
1866
- if((form = $.prop(elem, 'form'))){
1867
- $(form).on('reset.placeholder', function(e){
1868
- setTimeout(function(){
1869
- changePlaceholderVisibility(elem, false, false, data, e.type );
1870
- }, 0);
1871
- });
1872
- }
1873
-
1874
- if(elem.type == 'password' || isOver){
1875
- data.text = createPlaceholder(elem);
1876
- if(isResponsive || $(elem).is('.responsive-width') || (elem.currentStyle || {width: ''}).width.indexOf('%') != -1){
1877
- responsiveElem = true;
1878
- data.box = data.text;
1879
- } else {
1880
- data.box = $(elem)
1881
- .wrap('<span class="placeholder-box placeholder-box-'+ (elem.nodeName || '').toLowerCase() +' placeholder-box-'+$.css(elem, 'float')+'" />')
1882
- .parent()
1883
- ;
1884
- }
1885
- data.text
1886
- .insertAfter(elem)
1887
- .on('mousedown.placeholder', function(){
1888
- changePlaceholderVisibility(this, false, false, data, 'focus');
1889
- try {
1890
- setTimeout(function(){
1891
- elem.focus();
1892
- }, 0);
1893
- } catch(e){}
1894
- return false;
1895
- })
1896
- ;
1897
-
1898
-
1899
- $.each(['lineHeight', 'fontSize', 'fontFamily', 'fontWeight'], function(i, style){
1900
- var prop = $.css(elem, style);
1901
- if(data.text.css(style) != prop){
1902
- data.text.css(style, prop);
1903
- }
1904
- });
1905
- $.each(['Left', 'Top'], function(i, side){
1906
- var size = (parseInt($.css(elem, 'padding'+ side), 10) || 0) + Math.max((parseInt($.css(elem, 'margin'+ side), 10) || 0), 0) + (parseInt($.css(elem, 'border'+ side +'Width'), 10) || 0);
1907
- data.text.css('padding'+ side, size);
1908
- });
1909
-
1910
- $(elem)
1911
- .on('updateshadowdom', function(){
1912
- var height, width;
1913
- if((width = elem.offsetWidth) || (height = elem.offsetHeight)){
1914
- data.text
1915
- .css({
1916
- width: width,
1917
- height: height
1918
- })
1919
- .css($(elem).position())
1920
- ;
1921
- }
1922
- })
1923
- .triggerHandler('updateshadowdom')
1924
- ;
1925
-
1926
- } else {
1927
- var reset = function(e){
1928
- if($(elem).hasClass('placeholder-visible')){
1929
- hidePlaceholder(elem, data, '');
1930
- if(e && e.type == 'submit'){
1931
- setTimeout(function(){
1932
- if(e.isDefaultPrevented()){
1933
- changePlaceholderVisibility(elem, false, false, data );
1934
- }
1935
- }, 9);
1936
- }
1937
- }
1938
- };
1939
-
1940
- $(window).on('beforeunload', reset);
1941
- data.box = $(elem);
1942
- if(form){
1943
- $(form).submit(reset);
1944
- }
1945
- }
1946
-
1947
- return data;
1948
- },
1949
- update: function(elem, val){
1950
- var type = ($.attr(elem, 'type') || $.prop(elem, 'type') || '').toLowerCase();
1951
- if(!allowedPlaceholder[type] && !$.nodeName(elem, 'textarea')){
1952
- webshims.error('placeholder not allowed on input[type="'+type+'"]');
1953
- if(type == 'date'){
1954
- webshims.error('but you can use data-placeholder for input[type="date"]');
1955
- }
1956
- return;
1957
- }
1958
-
1959
-
1960
- var data = pHolder.create(elem);
1961
- if(data.text){
1962
- data.text.text(val);
1963
- }
1964
-
1965
- changePlaceholderVisibility(elem, false, val, data);
1966
- }
1967
- };
1968
- })()
1969
- ;
1970
-
1971
- $.webshims.publicMethods = {
1972
- pHolder: pHolder
1973
- };
1974
- polyfillElements.forEach(function(nodeName){
1975
- var desc = webshims.defineNodeNameProperty(nodeName, 'placeholder', {
1976
- attr: {
1977
- set: function(val){
1978
- var elem = this;
1979
- if(bustedTextarea){
1980
- webshims.data(elem, 'textareaPlaceholder', val);
1981
- elem.placeholder = '';
1982
- } else {
1983
- webshims.contentAttr(elem, 'placeholder', val);
1984
- }
1985
- pHolder.update(elem, val);
1986
- },
1987
- get: function(){
1988
- var ret = (bustedTextarea) ? webshims.data(this, 'textareaPlaceholder') : '';
1989
- return ret || webshims.contentAttr(this, 'placeholder');
1990
- }
1991
- },
1992
- reflect: true,
1993
- initAttr: true
1994
- });
1995
- });
1996
-
1997
-
1998
- polyfillElements.forEach(function(name){
1999
- var placeholderValueDesc = {};
2000
- var desc;
2001
- ['attr', 'prop'].forEach(function(propType){
2002
- placeholderValueDesc[propType] = {
2003
- set: function(val){
2004
- var elem = this;
2005
- var placeholder;
2006
- if(bustedTextarea){
2007
- placeholder = webshims.data(elem, 'textareaPlaceholder');
2008
- }
2009
- if(!placeholder){
2010
- placeholder = webshims.contentAttr(elem, 'placeholder');
2011
- }
2012
- $.removeData(elem, 'cachedValidity');
2013
- var ret = desc[propType]._supset.call(elem, val);
2014
- if(placeholder && 'value' in elem){
2015
- changePlaceholderVisibility(elem, val, placeholder);
2016
- }
2017
- return ret;
2018
- },
2019
- get: function(){
2020
- var elem = this;
2021
- return $(elem).hasClass('placeholder-visible') ? '' : desc[propType]._supget.call(elem);
2022
- }
2023
- };
2024
- });
2025
- desc = webshims.defineNodeNameProperty(name, 'value', placeholderValueDesc);
2026
- });
2027
-
2028
- })();
2029
-
2030
- (function(){
2031
- var doc = document;
2032
- if( 'value' in document.createElement('output') ){return;}
2033
-
2034
- webshims.defineNodeNameProperty('output', 'value', {
2035
- prop: {
2036
- set: function(value){
2037
- var setVal = $.data(this, 'outputShim');
2038
- if(!setVal){
2039
- setVal = outputCreate(this);
2040
- }
2041
- setVal(value);
2042
- },
2043
- get: function(){
2044
- return webshims.contentAttr(this, 'value') || $(this).text() || '';
2045
- }
2046
- }
2047
- });
2048
-
2049
-
2050
- webshims.onNodeNamesPropertyModify('input', 'value', function(value, boolVal, type){
2051
- if(type == 'removeAttr'){return;}
2052
- var setVal = $.data(this, 'outputShim');
2053
- if(setVal){
2054
- setVal(value);
2055
- }
2056
- });
2057
-
2058
- var outputCreate = function(elem){
2059
- if(elem.getAttribute('aria-live')){return;}
2060
- elem = $(elem);
2061
- var value = (elem.text() || '').trim();
2062
- var id = elem.attr('id');
2063
- var htmlFor = elem.attr('for');
2064
- var shim = $('<input class="output-shim" type="text" disabled name="'+ (elem.attr('name') || '')+'" value="'+value+'" style="display: none !important;" />').insertAfter(elem);
2065
- var form = shim[0].form || doc;
2066
- var setValue = function(val){
2067
- shim[0].value = val;
2068
- val = shim[0].value;
2069
- elem.text(val);
2070
- webshims.contentAttr(elem[0], 'value', val);
2071
- };
2072
-
2073
- elem[0].defaultValue = value;
2074
- webshims.contentAttr(elem[0], 'value', value);
2075
-
2076
- elem.attr({'aria-live': 'polite'});
2077
- if(id){
2078
- shim.attr('id', id);
2079
- elem.attr('aria-labelledby', webshims.getID($('label[for="'+id+'"]', form)));
2080
- }
2081
- if(htmlFor){
2082
- id = webshims.getID(elem);
2083
- htmlFor.split(' ').forEach(function(control){
2084
- control = document.getElementById(control);
2085
- if(control){
2086
- control.setAttribute('aria-controls', id);
2087
- }
2088
- });
2089
- }
2090
- elem.data('outputShim', setValue );
2091
- shim.data('outputShim', setValue );
2092
- return setValue;
2093
- };
2094
-
2095
- webshims.addReady(function(context, contextElem){
2096
- $('output', context).add(contextElem.filter('output')).each(function(){
2097
- outputCreate(this);
2098
- });
2099
- });
2100
-
2101
- /*
2102
- * Implements input event in all browsers
2103
- */
2104
- (function(){
2105
- var noInputTriggerEvts = {updateInput: 1, input: 1},
2106
- noInputTypes = {
2107
- radio: 1,
2108
- checkbox: 1,
2109
- submit: 1,
2110
- button: 1,
2111
- image: 1,
2112
- reset: 1,
2113
- file: 1
2114
-
2115
- //pro forma
2116
- ,color: 1
2117
- //,range: 1
2118
- },
2119
- observe = function(input){
2120
- var timer,
2121
- lastVal = input.prop('value'),
2122
- trigger = function(e){
2123
- //input === null
2124
- if(!input){return;}
2125
- var newVal = input.prop('value');
2126
-
2127
- if(newVal !== lastVal){
2128
- lastVal = newVal;
2129
- if(!e || !noInputTriggerEvts[e.type]){
2130
- webshims.triggerInlineForm && webshims.triggerInlineForm(input[0], 'input');
2131
- }
2132
- }
2133
- },
2134
- extraTimer,
2135
- extraTest = function(){
2136
- clearTimeout(extraTimer);
2137
- extraTimer = setTimeout(trigger, 9);
2138
- },
2139
- unbind = function(){
2140
- input.unbind('focusout', unbind).unbind('keyup keypress keydown paste cut', extraTest).unbind('input change updateInput', trigger);
2141
- clearInterval(timer);
2142
- setTimeout(function(){
2143
- trigger();
2144
- input = null;
2145
- }, 1);
2146
-
2147
- }
2148
- ;
2149
-
2150
- clearInterval(timer);
2151
- timer = setInterval(trigger, 99);
2152
- extraTest();
2153
- input.on({
2154
- 'keyup keypress keydown paste cut': extraTest,
2155
- focusout: unbind,
2156
- 'input updateInput change': trigger
2157
- });
2158
- }
2159
- ;
2160
- if($.event.customEvent){
2161
- $.event.customEvent.updateInput = true;
2162
- }
2163
-
2164
- $(doc)
2165
- .on('focusin', function(e){
2166
- if( e.target && e.target.type && !e.target.readOnly && !e.target.disabled && (e.target.nodeName || '').toLowerCase() == 'input' && !noInputTypes[e.target.type] ){
2167
- observe($(e.target));
2168
- }
2169
- })
2170
- ;
2171
- })();
2172
- })();
2173
-
2174
- }); //webshims.ready end
2175
- }//end formvalidation
2176
-
2177
- jQuery.webshims.register('form-message', function($, webshims, window, document, undefined, options){
2178
- "use strict";
2179
- var validityMessages = webshims.validityMessages;
2180
-
2181
- var implementProperties = (options.overrideMessages || options.customMessages) ? ['customValidationMessage'] : [];
2182
-
2183
- validityMessages['en'] = $.extend(true, {
2184
- typeMismatch: {
2185
- email: 'Please enter an email address.',
2186
- url: 'Please enter a URL.',
2187
- number: 'Please enter a number.',
2188
- date: 'Please enter a date.',
2189
- time: 'Please enter a time.',
2190
- range: 'Invalid input.',
2191
- "datetime-local": 'Please enter a datetime.'
2192
- },
2193
- rangeUnderflow: {
2194
- defaultMessage: 'Value must be greater than or equal to {%min}.'
2195
- },
2196
- rangeOverflow: {
2197
- defaultMessage: 'Value must be less than or equal to {%max}.'
2198
- },
2199
- stepMismatch: 'Invalid input.',
2200
- tooLong: 'Please enter at most {%maxlength} character(s). You entered {%valueLen}.',
2201
-
2202
- patternMismatch: 'Invalid input. {%title}',
2203
- valueMissing: {
2204
- defaultMessage: 'Please fill out this field.',
2205
- checkbox: 'Please check this box if you want to proceed.'
2206
- }
2207
- }, (validityMessages['en'] || validityMessages['en-US'] || {}));
2208
-
2209
-
2210
- ['select', 'radio'].forEach(function(type){
2211
- validityMessages['en'].valueMissing[type] = 'Please select an option.';
2212
- });
2213
-
2214
- ['date', 'time', 'datetime-local'].forEach(function(type){
2215
- validityMessages.en.rangeUnderflow[type] = 'Value must be at or after {%min}.';
2216
- });
2217
- ['date', 'time', 'datetime-local'].forEach(function(type){
2218
- validityMessages.en.rangeOverflow[type] = 'Value must be at or before {%max}.';
2219
- });
2220
-
2221
- validityMessages['en-US'] = validityMessages['en-US'] || validityMessages['en'];
2222
- validityMessages[''] = validityMessages[''] || validityMessages['en-US'];
2223
-
2224
- validityMessages['de'] = $.extend(true, {
2225
- typeMismatch: {
2226
- email: '{%value} ist keine zulässige E-Mail-Adresse',
2227
- url: '{%value} ist keine zulässige Webadresse',
2228
- number: '{%value} ist keine Nummer!',
2229
- date: '{%value} ist kein Datum',
2230
- time: '{%value} ist keine Uhrzeit',
2231
- range: '{%value} ist keine Nummer!',
2232
- "datetime-local": '{%value} ist kein Datum-Uhrzeit Format.'
2233
- },
2234
- rangeUnderflow: {
2235
- defaultMessage: '{%value} ist zu niedrig. {%min} ist der unterste Wert, den Sie benutzen können.'
2236
- },
2237
- rangeOverflow: {
2238
- defaultMessage: '{%value} ist zu hoch. {%max} ist der oberste Wert, den Sie benutzen können.'
2239
- },
2240
- stepMismatch: 'Der Wert {%value} ist in diesem Feld nicht zulässig. Hier sind nur bestimmte Werte zulässig. {%title}',
2241
- tooLong: 'Der eingegebene Text ist zu lang! Sie haben {%valueLen} Zeichen eingegeben, dabei sind {%maxlength} das Maximum.',
2242
- patternMismatch: '{%value} hat für dieses Eingabefeld ein falsches Format! {%title}',
2243
- valueMissing: {
2244
- defaultMessage: 'Bitte geben Sie einen Wert ein',
2245
- checkbox: 'Bitte aktivieren Sie das Kästchen'
2246
- }
2247
- }, (validityMessages['de'] || {}));
2248
-
2249
- ['select', 'radio'].forEach(function(type){
2250
- validityMessages['de'].valueMissing[type] = 'Bitte wählen Sie eine Option aus';
2251
- });
2252
-
2253
- ['date', 'time', 'datetime-local'].forEach(function(type){
2254
- validityMessages.de.rangeUnderflow[type] = '{%value} ist zu früh. {%min} ist die früheste Zeit, die Sie benutzen können.';
2255
- });
2256
- ['date', 'time', 'datetime-local'].forEach(function(type){
2257
- validityMessages.de.rangeOverflow[type] = '{%value} ist zu spät. {%max} ist die späteste Zeit, die Sie benutzen können.';
2258
- });
2259
-
2260
- var currentValidationMessage = validityMessages[''];
2261
-
2262
-
2263
- webshims.createValidationMessage = function(elem, name){
2264
- var message = currentValidationMessage[name];
2265
- if(message && typeof message !== 'string'){
2266
- message = message[ $.prop(elem, 'type') ] || message[ (elem.nodeName || '').toLowerCase() ] || message[ 'defaultMessage' ];
2267
- }
2268
- if(message){
2269
- ['value', 'min', 'max', 'title', 'maxlength', 'label'].forEach(function(attr){
2270
- if(message.indexOf('{%'+attr) === -1){return;}
2271
- var val = ((attr == 'label') ? $.trim($('label[for="'+ elem.id +'"]', elem.form).text()).replace(/\*$|:$/, '') : $.attr(elem, attr)) || '';
2272
- if(name == 'patternMismatch' && attr == 'title' && !val){
2273
- webshims.error('no title for patternMismatch provided. Always add a title attribute.');
2274
- }
2275
- message = message.replace('{%'+ attr +'}', val);
2276
- if('value' == attr){
2277
- message = message.replace('{%valueLen}', val.length);
2278
- }
2279
- });
2280
- }
2281
- return message || '';
2282
- };
2283
-
2284
-
2285
- if(webshims.bugs.validationMessage || !Modernizr.formvalidation || webshims.bugs.bustedValidity){
2286
- implementProperties.push('validationMessage');
2287
- }
2288
-
2289
- webshims.activeLang({
2290
- langObj: validityMessages,
2291
- module: 'form-core',
2292
- callback: function(langObj){
2293
- currentValidationMessage = langObj;
2294
- }
2295
- });
2296
-
2297
- implementProperties.forEach(function(messageProp){
2298
- webshims.defineNodeNamesProperty(['fieldset', 'output', 'button'], messageProp, {
2299
- prop: {
2300
- value: '',
2301
- writeable: false
2302
- }
2303
- });
2304
- ['input', 'select', 'textarea'].forEach(function(nodeName){
2305
- var desc = webshims.defineNodeNameProperty(nodeName, messageProp, {
2306
- prop: {
2307
- get: function(){
2308
- var elem = this;
2309
- var message = '';
2310
- if(!$.prop(elem, 'willValidate')){
2311
- return message;
2312
- }
2313
-
2314
- var validity = $.prop(elem, 'validity') || {valid: 1};
2315
-
2316
- if(validity.valid){return message;}
2317
- message = webshims.getContentValidationMessage(elem, validity);
2318
-
2319
- if(message){return message;}
2320
-
2321
- if(validity.customError && elem.nodeName){
2322
- message = (Modernizr.formvalidation && !webshims.bugs.bustedValidity && desc.prop._supget) ? desc.prop._supget.call(elem) : webshims.data(elem, 'customvalidationMessage');
2323
- if(message){return message;}
2324
- }
2325
- $.each(validity, function(name, prop){
2326
- if(name == 'valid' || !prop){return;}
2327
-
2328
- message = webshims.createValidationMessage(elem, name);
2329
- if(message){
2330
- return false;
2331
- }
2332
- });
2333
- return message || '';
2334
- },
2335
- writeable: false
2336
- }
2337
- });
2338
- });
2339
-
2340
- });
1
+ //additional tests for partial implementation of forms features
2
+ (function($){
3
+ "use strict";
4
+ var Modernizr = window.Modernizr;
5
+ var webshims = $.webshims;
6
+ var bugs = webshims.bugs;
7
+ var form = $('<form action="#" style="width: 1px; height: 1px; overflow: hidden;"><select name="b" required="" /><input required="" name="a" /></form>');
8
+ var testRequiredFind = function(){
9
+ if(form[0].querySelector){
10
+ try {
11
+ bugs.findRequired = !(form[0].querySelector('select:required'));
12
+ } catch(er){
13
+ bugs.findRequired = false;
14
+ }
15
+ }
16
+ };
17
+ var inputElem = $('input', form).eq(0);
18
+ var onDomextend = function(fn){
19
+ webshims.loader.loadList(['dom-extend']);
20
+ webshims.ready('dom-extend', fn);
21
+ };
22
+
23
+ bugs.findRequired = false;
24
+ bugs.validationMessage = false;
25
+
26
+ webshims.capturingEventPrevented = function(e){
27
+ if(!e._isPolyfilled){
28
+ var isDefaultPrevented = e.isDefaultPrevented;
29
+ var preventDefault = e.preventDefault;
30
+ e.preventDefault = function(){
31
+ clearTimeout($.data(e.target, e.type + 'DefaultPrevented'));
32
+ $.data(e.target, e.type + 'DefaultPrevented', setTimeout(function(){
33
+ $.removeData(e.target, e.type + 'DefaultPrevented');
34
+ }, 30));
35
+ return preventDefault.apply(this, arguments);
36
+ };
37
+ e.isDefaultPrevented = function(){
38
+ return !!(isDefaultPrevented.apply(this, arguments) || $.data(e.target, e.type + 'DefaultPrevented') || false);
39
+ };
40
+ e._isPolyfilled = true;
41
+ }
42
+ };
43
+
44
+ if(!Modernizr.formvalidation || bugs.bustedValidity){
45
+ testRequiredFind();
46
+ return;
47
+ }
48
+
49
+ //create delegatable events
50
+ webshims.capturingEvents(['input']);
51
+ webshims.capturingEvents(['invalid'], true);
52
+
53
+ if(window.opera || window.testGoodWithFix){
54
+
55
+ form.appendTo('head');
56
+
57
+ testRequiredFind();
58
+ bugs.validationMessage = !(inputElem.prop('validationMessage'));
59
+
60
+ webshims.reTest(['form-native-extend', 'form-message']);
61
+
62
+ form.remove();
63
+
64
+ $(function(){
65
+ onDomextend(function(){
66
+
67
+ //Opera shows native validation bubbles in case of input.checkValidity()
68
+ // Opera 11.6/12 hasn't fixed this issue right, it's buggy
69
+ var preventDefault = function(e){
70
+ e.preventDefault();
71
+ };
72
+
73
+ ['form', 'input', 'textarea', 'select'].forEach(function(name){
74
+ var desc = webshims.defineNodeNameProperty(name, 'checkValidity', {
75
+ prop: {
76
+ value: function(){
77
+ if (!webshims.fromSubmit) {
78
+ $(this).on('invalid.checkvalidity', preventDefault);
79
+ }
80
+
81
+ webshims.fromCheckValidity = true;
82
+ var ret = desc.prop._supvalue.apply(this, arguments);
83
+ if (!webshims.fromSubmit) {
84
+ $(this).unbind('invalid.checkvalidity', preventDefault);
85
+ }
86
+ webshims.fromCheckValidity = false;
87
+ return ret;
88
+ }
89
+ }
90
+ });
91
+ });
92
+
93
+ });
94
+ });
95
+ }
96
+
97
+ if($.browser.webkit && !webshims.bugs.bustedValidity){
98
+ (function(){
99
+ var elems = /^(?:textarea|input)$/i;
100
+ var form = false;
101
+
102
+ document.addEventListener('contextmenu', function(e){
103
+ if(elems.test( e.target.nodeName || '') && (form = e.target.form)){
104
+ setTimeout(function(){
105
+ form = false;
106
+ }, 1);
107
+ }
108
+ }, false);
109
+
110
+ $(window).on('invalid', function(e){
111
+ if(e.originalEvent && form && form == e.target.form){
112
+ e.wrongWebkitInvalid = true;
113
+ e.stopImmediatePropagation();
114
+ }
115
+ });
116
+
117
+ })();
118
+ }
119
+ })(jQuery);
120
+
121
+ jQuery.webshims.register('form-core', function($, webshims, window, document, undefined, options){
122
+ "use strict";
123
+
124
+
125
+ var checkTypes = {checkbox: 1, radio: 1};
126
+ var emptyJ = $([]);
127
+ var bugs = webshims.bugs;
128
+ var groupTypes = {radio: 1};
129
+ var getGroupElements = function(elem){
130
+ elem = $(elem);
131
+ var name;
132
+ var form;
133
+ var ret = emptyJ;
134
+ if(groupTypes[elem[0].type]){
135
+ form = elem.prop('form');
136
+ name = elem[0].name;
137
+ if(!name){
138
+ ret = elem;
139
+ } else if(form){
140
+ ret = $(form[name]);
141
+ } else {
142
+ ret = $(document.getElementsByName(name)).filter(function(){
143
+ return !$.prop(this, 'form');
144
+ });
145
+ }
146
+ ret = ret.filter('[type="radio"]');
147
+ }
148
+ return ret;
149
+ };
150
+
151
+ var getContentValidationMessage = webshims.getContentValidationMessage = function(elem, validity, key){
152
+ var message = $(elem).data('errormessage') || elem.getAttribute('x-moz-errormessage') || '';
153
+ if(key && message[key]){
154
+ message = message[key];
155
+ }
156
+ if(typeof message == 'object'){
157
+ validity = validity || $.prop(elem, 'validity') || {valid: 1};
158
+ if(!validity.valid){
159
+ $.each(validity, function(name, prop){
160
+ if(prop && name != 'valid' && message[name]){
161
+ message = message[name];
162
+ return false;
163
+ }
164
+ });
165
+ }
166
+ }
167
+
168
+ if(typeof message == 'object'){
169
+ message = message.defaultMessage;
170
+ }
171
+ return message || '';
172
+ };
173
+
174
+ /*
175
+ * Selectors for all browsers
176
+ */
177
+ var rangeTypes = {number: 1, range: 1, date: 1/*, time: 1, 'datetime-local': 1, datetime: 1, month: 1, week: 1*/};
178
+ var hasInvalid = function(elem){
179
+ var ret = false;
180
+ $($.prop(elem, 'elements')).each(function(){
181
+ ret = $(this).is(':invalid');
182
+ if(ret){
183
+ return false;
184
+ }
185
+ });
186
+ return ret;
187
+ };
188
+ $.extend($.expr[":"], {
189
+ "valid-element": function(elem){
190
+ return $.nodeName(elem, 'form') ? !hasInvalid(elem) :!!($.prop(elem, 'willValidate') && isValid(elem));
191
+ },
192
+ "invalid-element": function(elem){
193
+ return $.nodeName(elem, 'form') ? hasInvalid(elem) : !!($.prop(elem, 'willValidate') && !isValid(elem));
194
+ },
195
+ "required-element": function(elem){
196
+ return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required'));
197
+ },
198
+ "user-error": function(elem){
199
+ return ($.prop(elem, 'willValidate') && $(elem).hasClass('user-error'));
200
+ },
201
+ "optional-element": function(elem){
202
+ return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required') === false);
203
+ },
204
+ "in-range": function(elem){
205
+ if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
206
+ return false;
207
+ }
208
+ var val = $.prop(elem, 'validity');
209
+ return !!(val && !val.rangeOverflow && !val.rangeUnderflow);
210
+ },
211
+ "out-of-range": function(elem){
212
+ if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
213
+ return false;
214
+ }
215
+ var val = $.prop(elem, 'validity');
216
+ return !!(val && (val.rangeOverflow || val.rangeUnderflow));
217
+ }
218
+
219
+ });
220
+
221
+ ['valid', 'invalid', 'required', 'optional'].forEach(function(name){
222
+ $.expr[":"][name] = $.expr.filters[name+"-element"];
223
+ });
224
+
225
+
226
+ $.expr[":"].focus = function( elem ) {
227
+ try {
228
+ var doc = elem.ownerDocument;
229
+ return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus());
230
+ } catch(e){}
231
+ return false;
232
+ };
233
+
234
+ if(Modernizr.formvalidation && $.browser.webkit && !webshims.bugs.bustedValidity && webshims.browserVersion < 27){
235
+ (function(){
236
+ var retriggerRadioValidity = function(){
237
+ var validity;
238
+ if((validity = this.validity) && !validity.customError){
239
+ this.setCustomValidity('');
240
+ }
241
+ };
242
+
243
+ webshims.addReady(function(context, insertedElement){
244
+ if(context !== document){
245
+ $('input[type="radio"]:invalid', context)
246
+ .add(insertedElement.filter('input[type="radio"]:invalid'))
247
+ .each(retriggerRadioValidity)
248
+ ;
249
+ }
250
+ });
251
+ })();
252
+ }
253
+
254
+ var customEvents = $.event.customEvent || {};
255
+ var isValid = function(elem){
256
+ return ($.prop(elem, 'validity') || {valid: 1}).valid;
257
+ };
258
+
259
+ if (bugs.bustedValidity || bugs.findRequired) {
260
+ (function(){
261
+ var find = $.find;
262
+ var matchesSelector = $.find.matchesSelector;
263
+
264
+ var regExp = /(\:valid|\:invalid|\:optional|\:required|\:in-range|\:out-of-range)(?=[\s\[\~\.\+\>\:\#*]|$)/ig;
265
+ var regFn = function(sel){
266
+ return sel + '-element';
267
+ };
268
+
269
+ $.find = (function(){
270
+ var slice = Array.prototype.slice;
271
+ var fn = function(sel){
272
+ var ar = arguments;
273
+ ar = slice.call(ar, 1, ar.length);
274
+ ar.unshift(sel.replace(regExp, regFn));
275
+ return find.apply(this, ar);
276
+ };
277
+ for (var i in find) {
278
+ if(find.hasOwnProperty(i)){
279
+ fn[i] = find[i];
280
+ }
281
+ }
282
+ return fn;
283
+ })();
284
+ if(!Modernizr.prefixed || Modernizr.prefixed("matchesSelector", document.documentElement)){
285
+ $.find.matchesSelector = function(node, expr){
286
+ expr = expr.replace(regExp, regFn);
287
+ return matchesSelector.call(this, node, expr);
288
+ };
289
+ }
290
+
291
+ })();
292
+ }
293
+
294
+ //ToDo needs testing
295
+ var oldAttr = $.prop;
296
+ var changeVals = {selectedIndex: 1, value: 1, checked: 1, disabled: 1, readonly: 1};
297
+ $.prop = function(elem, name, val){
298
+ var ret = oldAttr.apply(this, arguments);
299
+ if(elem && 'form' in elem && changeVals[name] && val !== undefined && $(elem).hasClass(invalidClass)){
300
+ if(isValid(elem)){
301
+ $(elem).getShadowElement().removeClass(invalidClasses);
302
+ if(name == 'checked' && val) {
303
+ getGroupElements(elem).not(elem).removeClass(invalidClasses).removeAttr('aria-invalid');
304
+ }
305
+ }
306
+ }
307
+ return ret;
308
+ };
309
+
310
+ var returnValidityCause = function(validity, elem){
311
+ var ret;
312
+ $.each(validity, function(name, value){
313
+ if(value){
314
+ ret = (name == 'customError') ? $.prop(elem, 'validationMessage') : name;
315
+ return false;
316
+ }
317
+ });
318
+ return ret;
319
+ };
320
+
321
+ var isInGroup = function(name){
322
+ var ret;
323
+ try {
324
+ ret = document.activeElement.name === name;
325
+ } catch(e){}
326
+ return ret;
327
+ };
328
+ /* form-ui-invalid/form-ui-valid are deprecated. use user-error/user-success instead */
329
+ var invalidClass = 'user-error';
330
+ var invalidClasses = 'user-error form-ui-invalid';
331
+ var validClass = 'user-success';
332
+ var validClasses = 'user-success form-ui-valid';
333
+ var switchValidityClass = function(e){
334
+ var elem, timer;
335
+ if(!e.target){return;}
336
+ elem = $(e.target).getNativeElement()[0];
337
+ if(elem.type == 'submit' || !$.prop(elem, 'willValidate')){return;}
338
+ timer = $.data(elem, 'webshimsswitchvalidityclass');
339
+ var switchClass = function(){
340
+ if(e.type == 'focusout' && elem.type == 'radio' && isInGroup(elem.name)){return;}
341
+ var validity = $.prop(elem, 'validity');
342
+ var shadowElem = $(elem).getShadowElement();
343
+ var addClass, removeClass, trigger, generaltrigger, validityCause;
344
+
345
+ $(elem).trigger('refreshCustomValidityRules');
346
+ if(validity.valid){
347
+ if(!shadowElem.hasClass(validClass)){
348
+ addClass = validClasses;
349
+ removeClass = invalidClasses;
350
+ generaltrigger = 'changedvaliditystate';
351
+ trigger = 'changedvalid';
352
+ if(checkTypes[elem.type] && elem.checked){
353
+ getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass).removeAttr('aria-invalid');
354
+ }
355
+ $.removeData(elem, 'webshimsinvalidcause');
356
+ }
357
+ } else {
358
+ validityCause = returnValidityCause(validity, elem);
359
+ if($.data(elem, 'webshimsinvalidcause') != validityCause){
360
+ $.data(elem, 'webshimsinvalidcause', validityCause);
361
+ generaltrigger = 'changedvaliditystate';
362
+ }
363
+ if(!shadowElem.hasClass(invalidClass)){
364
+ addClass = invalidClasses;
365
+ removeClass = validClasses;
366
+ if (checkTypes[elem.type] && !elem.checked) {
367
+ getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass);
368
+ }
369
+ trigger = 'changedinvalid';
370
+ }
371
+ }
372
+ if(addClass){
373
+ shadowElem.addClass(addClass).removeClass(removeClass);
374
+ //jQuery 1.6.1 IE9 bug (doubble trigger bug)
375
+ setTimeout(function(){
376
+ $(elem).trigger(trigger);
377
+ }, 0);
378
+ }
379
+ if(generaltrigger){
380
+ setTimeout(function(){
381
+ $(elem).trigger(generaltrigger);
382
+ }, 0);
383
+ }
384
+ $.removeData(e.target, 'webshimsswitchvalidityclass');
385
+ };
386
+
387
+ if(timer){
388
+ clearTimeout(timer);
389
+ }
390
+ if(e.type == 'refreshvalidityui'){
391
+ switchClass();
392
+ } else {
393
+ $.data(elem, 'webshimsswitchvalidityclass', setTimeout(switchClass, 9));
394
+ }
395
+ };
396
+
397
+ $(document).on(options.validityUIEvents || 'focusout change refreshvalidityui', switchValidityClass);
398
+ customEvents.changedvaliditystate = true;
399
+ customEvents.refreshCustomValidityRules = true;
400
+ customEvents.changedvalid = true;
401
+ customEvents.changedinvalid = true;
402
+ customEvents.refreshvalidityui = true;
403
+
404
+
405
+ webshims.triggerInlineForm = function(elem, event){
406
+ $(elem).trigger(event);
407
+ };
408
+
409
+ webshims.modules["form-core"].getGroupElements = getGroupElements;
410
+
411
+
412
+ var setRoot = function(){
413
+ webshims.scrollRoot = ($.browser.webkit || document.compatMode == 'BackCompat') ?
414
+ $(document.body) :
415
+ $(document.documentElement)
416
+ ;
417
+ };
418
+ setRoot();
419
+ webshims.ready('DOM', setRoot);
420
+
421
+ webshims.getRelOffset = function(posElem, relElem){
422
+ posElem = $(posElem);
423
+ var offset = $(relElem).offset();
424
+ var bodyOffset;
425
+ $.swap($(posElem)[0], {visibility: 'hidden', display: 'inline-block', left: 0, top: 0}, function(){
426
+ bodyOffset = posElem.offset();
427
+ });
428
+ offset.top -= bodyOffset.top;
429
+ offset.left -= bodyOffset.left;
430
+ return offset;
431
+ };
432
+
433
+ /* some extra validation UI */
434
+ webshims.validityAlert = (function(){
435
+ var alertElem = (!$.browser.msie || parseInt($.browser.version, 10) > 7) ? 'span' : 'label';
436
+ var errorBubble;
437
+ var hideTimer = false;
438
+ var focusTimer = false;
439
+ var resizeTimer = false;
440
+ var boundHide;
441
+
442
+ var api = {
443
+ hideDelay: 5000,
444
+
445
+ showFor: function(elem, message, noFocusElem, noBubble){
446
+ api._create();
447
+ elem = $(elem);
448
+ var visual = $(elem).getShadowElement();
449
+ var offset = api.getOffsetFromBody(visual);
450
+ api.clear();
451
+ if(noBubble){
452
+ this.hide();
453
+ } else {
454
+
455
+ this.getMessage(elem, message);
456
+ this.position(visual, offset);
457
+
458
+ this.show();
459
+ if(this.hideDelay){
460
+ hideTimer = setTimeout(boundHide, this.hideDelay);
461
+ }
462
+ $(window)
463
+ .on('resize.validityalert reposoverlay.validityalert', function(){
464
+ clearTimeout(resizeTimer);
465
+ resizeTimer = setTimeout(function(){
466
+ api.position(visual);
467
+ }, 9);
468
+ })
469
+ ;
470
+ }
471
+
472
+ if(!noFocusElem){
473
+ this.setFocus(visual, offset);
474
+ }
475
+ },
476
+ getOffsetFromBody: function(elem){
477
+ return webshims.getRelOffset(errorBubble, elem);
478
+ },
479
+ setFocus: function(visual, offset){
480
+ var focusElem = $(visual).getShadowFocusElement();
481
+ var scrollTop = webshims.scrollRoot.scrollTop();
482
+ var elemTop = ((offset || focusElem.offset()).top) - 30;
483
+ var smooth;
484
+
485
+ if(webshims.getID && alertElem == 'label'){
486
+ errorBubble.attr('for', webshims.getID(focusElem));
487
+ }
488
+
489
+ if(scrollTop > elemTop){
490
+ webshims.scrollRoot.animate(
491
+ {scrollTop: elemTop - 5},
492
+ {
493
+ queue: false,
494
+ duration: Math.max( Math.min( 600, (scrollTop - elemTop) * 1.5 ), 80 )
495
+ }
496
+ );
497
+ smooth = true;
498
+ }
499
+ try {
500
+ focusElem[0].focus();
501
+ } catch(e){}
502
+ if(smooth){
503
+ webshims.scrollRoot.scrollTop(scrollTop);
504
+ setTimeout(function(){
505
+ webshims.scrollRoot.scrollTop(scrollTop);
506
+ }, 0);
507
+ }
508
+ setTimeout(function(){
509
+ $(document).on('focusout.validityalert', boundHide);
510
+ }, 10);
511
+ $(window).triggerHandler('reposoverlay');
512
+ },
513
+ getMessage: function(elem, message){
514
+ if (!message) {
515
+ message = getContentValidationMessage(elem[0]) || elem.prop('customValidationMessage') || elem.prop('validationMessage');
516
+ }
517
+ if (message) {
518
+ $('span.va-box', errorBubble).text(message);
519
+ }
520
+ else {
521
+ this.hide();
522
+ }
523
+ },
524
+ position: function(elem, offset){
525
+ offset = offset ? $.extend({}, offset) : api.getOffsetFromBody(elem);
526
+ offset.top += elem.outerHeight();
527
+ errorBubble.css(offset);
528
+ },
529
+ show: function(){
530
+ if(errorBubble.css('display') === 'none'){
531
+ errorBubble.css({opacity: 0}).show();
532
+ }
533
+ errorBubble.addClass('va-visible').fadeTo(400, 1);
534
+ },
535
+ hide: function(){
536
+ errorBubble.removeClass('va-visible').fadeOut();
537
+ },
538
+ clear: function(){
539
+ clearTimeout(focusTimer);
540
+ clearTimeout(hideTimer);
541
+ $(document).unbind('.validityalert');
542
+ $(window).unbind('.validityalert');
543
+ errorBubble.stop().removeAttr('for');
544
+ },
545
+ _create: function(){
546
+ if(errorBubble){return;}
547
+ 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'});
548
+ webshims.ready('DOM', function(){
549
+ errorBubble.appendTo('body');
550
+ if($.fn.bgIframe && $.browser.msie && parseInt($.browser.version, 10) < 7){
551
+ errorBubble.bgIframe();
552
+ }
553
+ });
554
+ }
555
+ };
556
+
557
+
558
+ boundHide = $.proxy(api, 'hide');
559
+
560
+ return api;
561
+ })();
562
+
563
+
564
+ /* extension, but also used to fix native implementation workaround/bugfixes */
565
+ (function(){
566
+ var firstEvent,
567
+ invalids = [],
568
+ stopSubmitTimer,
569
+ form
570
+ ;
571
+
572
+ $(document).on('invalid', function(e){
573
+ if(e.wrongWebkitInvalid){return;}
574
+ var jElm = $(e.target);
575
+ var shadowElem = jElm.getShadowElement();
576
+ if(!shadowElem.hasClass(invalidClass)){
577
+ shadowElem.addClass(invalidClasses).removeClass(validClasses);
578
+ setTimeout(function(){
579
+ $(e.target).trigger('changedinvalid').trigger('changedvaliditystate');
580
+ }, 0);
581
+ }
582
+
583
+ if(!firstEvent){
584
+ //trigger firstinvalid
585
+ firstEvent = $.Event('firstinvalid');
586
+ firstEvent.isInvalidUIPrevented = e.isDefaultPrevented;
587
+ var firstSystemInvalid = $.Event('firstinvalidsystem');
588
+ $(document).triggerHandler(firstSystemInvalid, {element: e.target, form: e.target.form, isInvalidUIPrevented: e.isDefaultPrevented});
589
+ jElm.trigger(firstEvent);
590
+ }
591
+
592
+ //if firstinvalid was prevented all invalids will be also prevented
593
+ if( firstEvent && firstEvent.isDefaultPrevented() ){
594
+ e.preventDefault();
595
+ }
596
+ invalids.push(e.target);
597
+ e.extraData = 'fix';
598
+ clearTimeout(stopSubmitTimer);
599
+ stopSubmitTimer = setTimeout(function(){
600
+ var lastEvent = {type: 'lastinvalid', cancelable: false, invalidlist: $(invalids)};
601
+ //reset firstinvalid
602
+ firstEvent = false;
603
+ invalids = [];
604
+ $(e.target).trigger(lastEvent, lastEvent);
605
+ }, 9);
606
+ jElm = null;
607
+ shadowElem = null;
608
+ });
609
+ })();
610
+
611
+ $.fn.getErrorMessage = function(){
612
+ var message = '';
613
+ var elem = this[0];
614
+ if(elem){
615
+ message = getContentValidationMessage(elem) || $.prop(elem, 'customValidationMessage') || $.prop(elem, 'validationMessage');
616
+ }
617
+ return message;
618
+ };
619
+
620
+ if(options.replaceValidationUI){
621
+ webshims.ready('DOM forms', function(){
622
+ $(document).on('firstinvalid', function(e){
623
+ if(!e.isInvalidUIPrevented()){
624
+ e.preventDefault();
625
+ $.webshims.validityAlert.showFor( e.target );
626
+ }
627
+ });
628
+ });
629
+ }
630
+
631
+ });
632
+ if(!Modernizr.formvalidation || jQuery.webshims.bugs.bustedValidity){
633
+ jQuery.webshims.register('form-shim-extend', function($, webshims, window, document){
634
+ "use strict";
635
+ webshims.inputTypes = webshims.inputTypes || {};
636
+ //some helper-functions
637
+ var cfg = webshims.cfg.forms;
638
+ var isSubmit;
639
+
640
+ var isNumber = function(string){
641
+ return (typeof string == 'number' || (string && string == string * 1));
642
+ },
643
+ typeModels = webshims.inputTypes,
644
+ checkTypes = {
645
+ radio: 1,
646
+ checkbox: 1
647
+ },
648
+ getType = function(elem){
649
+ return (elem.getAttribute('type') || elem.type || '').toLowerCase();
650
+ }
651
+ ;
652
+
653
+ //API to add new input types
654
+ webshims.addInputType = function(type, obj){
655
+ typeModels[type] = obj;
656
+ };
657
+
658
+ //contsrain-validation-api
659
+ var validityPrototype = {
660
+ customError: false,
661
+
662
+ typeMismatch: false,
663
+ rangeUnderflow: false,
664
+ rangeOverflow: false,
665
+ stepMismatch: false,
666
+ tooLong: false,
667
+ patternMismatch: false,
668
+ valueMissing: false,
669
+
670
+ valid: true
671
+ };
672
+
673
+ var isPlaceholderOptionSelected = function(select){
674
+ if(select.type == 'select-one' && select.size < 2){
675
+ var option = $('> option:first-child', select);
676
+ return !!option.prop('selected');
677
+ }
678
+ return false;
679
+ };
680
+
681
+ var validityRules = {
682
+ valueMissing: function(input, val, cache){
683
+ if(!input.prop('required')){return false;}
684
+ var ret = false;
685
+ if(!('type' in cache)){
686
+ cache.type = getType(input[0]);
687
+ }
688
+ if(cache.nodeName == 'select'){
689
+ ret = (!val && (input[0].selectedIndex < 0 || isPlaceholderOptionSelected(input[0]) ));
690
+ } else if(checkTypes[cache.type]){
691
+ ret = (cache.type == 'checkbox') ? !input.is(':checked') : !webshims.modules["form-core"].getGroupElements(input).filter(':checked')[0];
692
+ } else {
693
+ ret = !(val);
694
+ }
695
+ return ret;
696
+ },
697
+ tooLong: function(){
698
+ return false;
699
+ },
700
+ typeMismatch: function (input, val, cache){
701
+ if(val === '' || cache.nodeName == 'select'){return false;}
702
+ var ret = false;
703
+ if(!('type' in cache)){
704
+ cache.type = getType(input[0]);
705
+ }
706
+
707
+ if(typeModels[cache.type] && typeModels[cache.type].mismatch){
708
+ ret = typeModels[cache.type].mismatch(val, input);
709
+ } else if('validity' in input[0]){
710
+ ret = input[0].validity.typeMismatch;
711
+ }
712
+ return ret;
713
+ },
714
+ patternMismatch: function(input, val, cache) {
715
+ if(val === '' || cache.nodeName == 'select'){return false;}
716
+ var pattern = input.attr('pattern');
717
+ if(!pattern){return false;}
718
+ try {
719
+ pattern = new RegExp('^(?:' + pattern + ')$');
720
+ } catch(er){
721
+ webshims.error('invalid pattern value: "'+ pattern +'" | '+ er);
722
+ pattern = false;
723
+ }
724
+ if(!pattern){return false;}
725
+ return !(pattern.test(val));
726
+ }
727
+ }
728
+ ;
729
+
730
+ webshims.addValidityRule = function(type, fn){
731
+ validityRules[type] = fn;
732
+ };
733
+
734
+ $.event.special.invalid = {
735
+ add: function(){
736
+ $.event.special.invalid.setup.call(this.form || this);
737
+ },
738
+ setup: function(){
739
+ var form = this.form || this;
740
+ if( $.data(form, 'invalidEventShim') ){
741
+ form = null;
742
+ return;
743
+ }
744
+ $(form)
745
+ .data('invalidEventShim', true)
746
+ .on('submit', $.event.special.invalid.handler)
747
+ ;
748
+ webshims.moveToFirstEvent(form, 'submit');
749
+ if(webshims.bugs.bustedValidity && $.nodeName(form, 'form')){
750
+ (function(){
751
+ var noValidate = form.getAttribute('novalidate');
752
+ form.setAttribute('novalidate', 'novalidate');
753
+ webshims.data(form, 'bustedNoValidate', (noValidate == null) ? null : noValidate);
754
+ })();
755
+ }
756
+ form = null;
757
+ },
758
+ teardown: $.noop,
759
+ handler: function(e, d){
760
+
761
+ if( e.type != 'submit' || e.testedValidity || !e.originalEvent || !$.nodeName(e.target, 'form') || $.prop(e.target, 'noValidate') ){return;}
762
+
763
+ isSubmit = true;
764
+ e.testedValidity = true;
765
+ var notValid = !($(e.target).checkValidity());
766
+ if(notValid){
767
+ e.stopImmediatePropagation();
768
+ isSubmit = false;
769
+ return false;
770
+ }
771
+ isSubmit = false;
772
+ }
773
+ };
774
+
775
+ var addSubmitBubbles = function(form){
776
+ if (!$.support.submitBubbles && form && typeof form == 'object' && !form._submit_attached ) {
777
+
778
+ $.event.add( form, 'submit._submit', function( event ) {
779
+ event._submit_bubble = true;
780
+ });
781
+
782
+ form._submit_attached = true;
783
+ }
784
+ };
785
+ if(!$.support.submitBubbles && $.event.special.submit){
786
+ $.event.special.submit.setup = function() {
787
+ // Only need this for delegated form submit events
788
+ if ( $.nodeName( this, "form" ) ) {
789
+ return false;
790
+ }
791
+
792
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
793
+ $.event.add( this, "click._submit keypress._submit", function( e ) {
794
+ // Node name check avoids a VML-related crash in IE (#9807)
795
+ var elem = e.target,
796
+ form = $.nodeName( elem, 'input' ) || $.nodeName( elem, 'button' ) ? $.prop(elem, 'form') : undefined;
797
+ addSubmitBubbles(form);
798
+
799
+ });
800
+ // return undefined since we don't need an event listener
801
+ };
802
+ }
803
+
804
+ $.event.special.submit = $.event.special.submit || {setup: function(){return false;}};
805
+ var submitSetup = $.event.special.submit.setup;
806
+ $.extend($.event.special.submit, {
807
+ setup: function(){
808
+ if($.nodeName(this, 'form')){
809
+ $(this).on('invalid', $.noop);
810
+ } else {
811
+ $('form', this).on('invalid', $.noop);
812
+ }
813
+ return submitSetup.apply(this, arguments);
814
+ }
815
+ });
816
+
817
+ $(window).on('invalid', $.noop);
818
+
819
+
820
+ webshims.addInputType('email', {
821
+ mismatch: (function(){
822
+ //taken from http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address
823
+ var test = cfg.emailReg || /^[a-zA-Z0-9.!#$%&'*+-\/=?\^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
824
+ return function(val){
825
+ return !test.test(val);
826
+ };
827
+ })()
828
+ });
829
+
830
+ webshims.addInputType('url', {
831
+ mismatch: (function(){
832
+ //taken from scott gonzales
833
+ var test = cfg.urlReg || /^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i;
834
+ return function(val){
835
+ return !test.test(val);
836
+ };
837
+ })()
838
+ });
839
+
840
+ webshims.defineNodeNameProperty('input', 'type', {
841
+ prop: {
842
+ get: function(){
843
+ var elem = this;
844
+ var type = (elem.getAttribute('type') || '').toLowerCase();
845
+ return (webshims.inputTypes[type]) ? type : elem.type;
846
+ }
847
+ }
848
+ });
849
+
850
+ // IDLs for constrain validation API
851
+ //ToDo: add object to this list
852
+ webshims.defineNodeNamesProperties(['button', 'fieldset', 'output'], {
853
+ checkValidity: {
854
+ value: function(){return true;}
855
+ },
856
+ willValidate: {
857
+ value: false
858
+ },
859
+ setCustomValidity: {
860
+ value: $.noop
861
+ },
862
+ validity: {
863
+ writeable: false,
864
+ get: function(){
865
+ return $.extend({}, validityPrototype);
866
+ }
867
+ }
868
+ }, 'prop');
869
+
870
+ var baseCheckValidity = function(elem){
871
+ var e,
872
+ v = $.prop(elem, 'validity')
873
+ ;
874
+ if(v){
875
+ $.data(elem, 'cachedValidity', v);
876
+ } else {
877
+ return true;
878
+ }
879
+ if( !v.valid ){
880
+ e = $.Event('invalid');
881
+ var jElm = $(elem).trigger(e);
882
+ if(isSubmit && !baseCheckValidity.unhandledInvalids && !e.isDefaultPrevented()){
883
+ webshims.validityAlert.showFor(jElm);
884
+ baseCheckValidity.unhandledInvalids = true;
885
+ }
886
+ }
887
+ $.removeData(elem, 'cachedValidity');
888
+ return v.valid;
889
+ };
890
+ var rsubmittable = /^(?:select|textarea|input)/i;
891
+ webshims.defineNodeNameProperty('form', 'checkValidity', {
892
+ prop: {
893
+ value: function(){
894
+
895
+ var ret = true,
896
+ elems = $($.prop(this, 'elements')).filter(function(){
897
+ if(!rsubmittable.test(this.nodeName)){return false;}
898
+ var shadowData = webshims.data(this, 'shadowData');
899
+ return !shadowData || !shadowData.nativeElement || shadowData.nativeElement === this;
900
+ })
901
+ ;
902
+
903
+ baseCheckValidity.unhandledInvalids = false;
904
+ for(var i = 0, len = elems.length; i < len; i++){
905
+ if( !baseCheckValidity(elems[i]) ){
906
+ ret = false;
907
+ }
908
+ }
909
+ return ret;
910
+ }
911
+ }
912
+ });
913
+
914
+ webshims.defineNodeNamesProperties(['input', 'textarea', 'select'], {
915
+ checkValidity: {
916
+ value: function(){
917
+ baseCheckValidity.unhandledInvalids = false;
918
+ return baseCheckValidity($(this).getNativeElement()[0]);
919
+ }
920
+ },
921
+ setCustomValidity: {
922
+ value: function(error){
923
+ $.removeData(this, 'cachedValidity');
924
+ webshims.data(this, 'customvalidationMessage', ''+error);
925
+ }
926
+ },
927
+ willValidate: {
928
+ writeable: false,
929
+ get: (function(){
930
+ var types = {
931
+ button: 1,
932
+ reset: 1,
933
+ hidden: 1,
934
+ image: 1
935
+ }
936
+ ;
937
+ return function(){
938
+ var elem = $(this).getNativeElement()[0];
939
+ //elem.name && <- we don't use to make it easier for developers
940
+ return !!(!elem.disabled && !elem.readOnly && !types[elem.type] );
941
+ };
942
+ })()
943
+ },
944
+ validity: {
945
+ writeable: false,
946
+ get: function(){
947
+ var jElm = $(this).getNativeElement();
948
+ var elem = jElm[0];
949
+ var validityState = $.data(elem, 'cachedValidity');
950
+ if(validityState){
951
+ return validityState;
952
+ }
953
+ validityState = $.extend({}, validityPrototype);
954
+
955
+ if( !$.prop(elem, 'willValidate') || elem.type == 'submit' ){
956
+ return validityState;
957
+ }
958
+ var val = jElm.val(),
959
+ cache = {nodeName: elem.nodeName.toLowerCase()}
960
+ ;
961
+
962
+ validityState.customError = !!(webshims.data(elem, 'customvalidationMessage'));
963
+ if( validityState.customError ){
964
+ validityState.valid = false;
965
+ }
966
+
967
+ $.each(validityRules, function(rule, fn){
968
+ if (fn(jElm, val, cache)) {
969
+ validityState[rule] = true;
970
+ validityState.valid = false;
971
+ }
972
+ });
973
+ $(this).getShadowFocusElement().attr('aria-invalid', validityState.valid ? 'false' : 'true');
974
+ jElm = null;
975
+ elem = null;
976
+ return validityState;
977
+ }
978
+ }
979
+ }, 'prop');
980
+
981
+ webshims.defineNodeNamesBooleanProperty(['input', 'textarea', 'select'], 'required', {
982
+ set: function(value){
983
+ $(this).getShadowFocusElement().attr('aria-required', !!(value)+'');
984
+ },
985
+ initAttr: (!$.browser.msie || webshims.browserVersion > 7)//only if we have aria-support
986
+ });
987
+
988
+ webshims.reflectProperties(['input'], ['pattern']);
989
+
990
+
991
+ if( !('maxLength' in document.createElement('textarea')) ){
992
+ var constrainMaxLength = (function(){
993
+ var timer;
994
+ var curLength = 0;
995
+ var lastElement = $([]);
996
+ var max = 1e9;
997
+ var constrainLength = function(){
998
+ var nowValue = lastElement.prop('value');
999
+ var nowLen = nowValue.length;
1000
+ if(nowLen > curLength && nowLen > max){
1001
+ nowLen = Math.max(curLength, max);
1002
+ lastElement.prop('value', nowValue.substr(0, nowLen ));
1003
+ }
1004
+ curLength = nowLen;
1005
+ };
1006
+ var remove = function(){
1007
+ clearTimeout(timer);
1008
+ lastElement.unbind('.maxlengthconstraint');
1009
+ };
1010
+ return function(element, maxLength){
1011
+ remove();
1012
+ if(maxLength > -1){
1013
+ max = maxLength;
1014
+ curLength = $.prop(element, 'value').length;
1015
+ lastElement = $(element);
1016
+ lastElement.on({
1017
+ 'keydown.maxlengthconstraint keypress.maxlengthconstraint paste.maxlengthconstraint cut.maxlengthconstraint': function(e){
1018
+ setTimeout(constrainLength, 0);
1019
+ },
1020
+ 'keyup.maxlengthconstraint': constrainLength,
1021
+ 'blur.maxlengthconstraint': remove
1022
+ });
1023
+ timer = setInterval(constrainLength, 200);
1024
+ }
1025
+ };
1026
+ })();
1027
+
1028
+ constrainMaxLength.update = function(element, maxLength){
1029
+ if($(element).is(':focus')){
1030
+ if(!maxLength){
1031
+ maxLength = $.prop(element, 'maxlength');
1032
+ }
1033
+ constrainMaxLength(element, maxLength);
1034
+ }
1035
+ };
1036
+
1037
+ $(document).on('focusin', function(e){
1038
+ var maxLength;
1039
+ if(e.target.nodeName == "TEXTAREA" && (maxLength = $.prop(e.target, 'maxlength')) > -1){
1040
+ constrainMaxLength(e.target, maxLength);
1041
+ }
1042
+ });
1043
+
1044
+ webshims.defineNodeNameProperty('textarea', 'maxlength', {
1045
+ attr: {
1046
+ set: function(val){
1047
+ this.setAttribute('maxlength', ''+val);
1048
+ constrainMaxLength.update(this);
1049
+ },
1050
+ get: function(){
1051
+ var ret = this.getAttribute('maxlength');
1052
+ return ret == null ? undefined : ret;
1053
+ }
1054
+ },
1055
+ prop: {
1056
+ set: function(val){
1057
+ if(isNumber(val)){
1058
+ if(val < 0){
1059
+ throw('INDEX_SIZE_ERR');
1060
+ }
1061
+ val = parseInt(val, 10);
1062
+ this.setAttribute('maxlength', val);
1063
+ constrainMaxLength.update(this, val);
1064
+ return;
1065
+ }
1066
+ this.setAttribute('maxlength', '0');
1067
+ constrainMaxLength.update(this, 0);
1068
+ },
1069
+ get: function(){
1070
+ var val = this.getAttribute('maxlength');
1071
+ return (isNumber(val) && val >= 0) ? parseInt(val, 10) : -1;
1072
+
1073
+ }
1074
+ }
1075
+ });
1076
+ webshims.defineNodeNameProperty('textarea', 'maxLength', {
1077
+ prop: {
1078
+ set: function(val){
1079
+ $.prop(this, 'maxlength', val);
1080
+ },
1081
+ get: function(){
1082
+ return $.prop(this, 'maxlength');
1083
+ }
1084
+ }
1085
+ });
1086
+ }
1087
+
1088
+
1089
+
1090
+ var submitterTypes = {submit: 1, button: 1, image: 1};
1091
+ var formSubmitterDescriptors = {};
1092
+ [
1093
+ {
1094
+ name: "enctype",
1095
+ limitedTo: {
1096
+ "application/x-www-form-urlencoded": 1,
1097
+ "multipart/form-data": 1,
1098
+ "text/plain": 1
1099
+ },
1100
+ defaultProp: "application/x-www-form-urlencoded",
1101
+ proptype: "enum"
1102
+ },
1103
+ {
1104
+ name: "method",
1105
+ limitedTo: {
1106
+ "get": 1,
1107
+ "post": 1
1108
+ },
1109
+ defaultProp: "get",
1110
+ proptype: "enum"
1111
+ },
1112
+ {
1113
+ name: "action",
1114
+ proptype: "url"
1115
+ },
1116
+ {
1117
+ name: "target"
1118
+ },
1119
+ {
1120
+ name: "novalidate",
1121
+ propName: "noValidate",
1122
+ proptype: "boolean"
1123
+ }
1124
+ ].forEach(function(desc){
1125
+ var propName = 'form'+ (desc.propName || desc.name).replace(/^[a-z]/, function(f){
1126
+ return f.toUpperCase();
1127
+ });
1128
+ var attrName = 'form'+ desc.name;
1129
+ var formName = desc.name;
1130
+ var eventName = 'click.webshimssubmittermutate'+formName;
1131
+
1132
+ var changeSubmitter = function(){
1133
+ var elem = this;
1134
+ if( !('form' in elem) || !submitterTypes[elem.type] ){return;}
1135
+ var form = $.prop(elem, 'form');
1136
+ if(!form){return;}
1137
+ var attr = $.attr(elem, attrName);
1138
+ if(attr != null && ( !desc.limitedTo || attr.toLowerCase() === $.prop(elem, propName))){
1139
+
1140
+ var oldAttr = $.attr(form, formName);
1141
+
1142
+ $.attr(form, formName, attr);
1143
+ setTimeout(function(){
1144
+ if(oldAttr != null){
1145
+ $.attr(form, formName, oldAttr);
1146
+ } else {
1147
+ try {
1148
+ $(form).removeAttr(formName);
1149
+ } catch(er){
1150
+ form.removeAttribute(formName);
1151
+ }
1152
+ }
1153
+ }, 9);
1154
+ }
1155
+ };
1156
+
1157
+
1158
+
1159
+ switch(desc.proptype) {
1160
+ case "url":
1161
+ var urlForm = document.createElement('form');
1162
+ formSubmitterDescriptors[propName] = {
1163
+ prop: {
1164
+ set: function(value){
1165
+ $.attr(this, attrName, value);
1166
+ },
1167
+ get: function(){
1168
+ var value = $.attr(this, attrName);
1169
+ if(value == null){return '';}
1170
+ urlForm.setAttribute('action', value);
1171
+ return urlForm.action;
1172
+ }
1173
+ }
1174
+ };
1175
+ break;
1176
+ case "boolean":
1177
+ formSubmitterDescriptors[propName] = {
1178
+ prop: {
1179
+ set: function(val){
1180
+ val = !!val;
1181
+ if(val){
1182
+ $.attr(this, 'formnovalidate', 'formnovalidate');
1183
+ } else {
1184
+ $(this).removeAttr('formnovalidate');
1185
+ }
1186
+ },
1187
+ get: function(){
1188
+ return $.attr(this, 'formnovalidate') != null;
1189
+ }
1190
+ }
1191
+ };
1192
+ break;
1193
+ case "enum":
1194
+ formSubmitterDescriptors[propName] = {
1195
+ prop: {
1196
+ set: function(value){
1197
+ $.attr(this, attrName, value);
1198
+ },
1199
+ get: function(){
1200
+ var value = $.attr(this, attrName);
1201
+ return (!value || ( (value = value.toLowerCase()) && !desc.limitedTo[value] )) ? desc.defaultProp : value;
1202
+ }
1203
+ }
1204
+ };
1205
+ break;
1206
+ default:
1207
+ formSubmitterDescriptors[propName] = {
1208
+ prop: {
1209
+ set: function(value){
1210
+ $.attr(this, attrName, value);
1211
+ },
1212
+ get: function(){
1213
+ var value = $.attr(this, attrName);
1214
+ return (value != null) ? value : "";
1215
+ }
1216
+ }
1217
+ };
1218
+ }
1219
+
1220
+
1221
+ if(!formSubmitterDescriptors[attrName]){
1222
+ formSubmitterDescriptors[attrName] = {};
1223
+ }
1224
+ formSubmitterDescriptors[attrName].attr = {
1225
+ set: function(value){
1226
+ formSubmitterDescriptors[attrName].attr._supset.call(this, value);
1227
+ $(this).unbind(eventName).on(eventName, changeSubmitter);
1228
+ },
1229
+ get: function(){
1230
+ return formSubmitterDescriptors[attrName].attr._supget.call(this);
1231
+ }
1232
+ };
1233
+ formSubmitterDescriptors[attrName].initAttr = true;
1234
+ formSubmitterDescriptors[attrName].removeAttr = {
1235
+ value: function(){
1236
+ $(this).unbind(eventName);
1237
+ formSubmitterDescriptors[attrName].removeAttr._supvalue.call(this);
1238
+ }
1239
+ };
1240
+ });
1241
+
1242
+ webshims.defineNodeNamesProperties(['input', 'button'], formSubmitterDescriptors);
1243
+
1244
+
1245
+ if(!$.support.getSetAttribute && $('<form novalidate></form>').attr('novalidate') == null){
1246
+ webshims.defineNodeNameProperty('form', 'novalidate', {
1247
+ attr: {
1248
+ set: function(val){
1249
+ this.setAttribute('novalidate', ''+val);
1250
+ },
1251
+ get: function(){
1252
+ var ret = this.getAttribute('novalidate');
1253
+ return ret == null ? undefined : ret;
1254
+ }
1255
+ }
1256
+ });
1257
+ } else if(webshims.bugs.bustedValidity){
1258
+
1259
+ webshims.defineNodeNameProperty('form', 'novalidate', {
1260
+ attr: {
1261
+ set: function(val){
1262
+ webshims.data(this, 'bustedNoValidate', ''+val);
1263
+ },
1264
+ get: function(){
1265
+ var ret = webshims.data(this, 'bustedNoValidate');
1266
+ return ret == null ? undefined : ret;
1267
+ }
1268
+ },
1269
+ removeAttr: {
1270
+ value: function(){
1271
+ webshims.data(this, 'bustedNoValidate', null);
1272
+ }
1273
+ }
1274
+ });
1275
+
1276
+ $.each(['rangeUnderflow', 'rangeOverflow', 'stepMismatch'], function(i, name){
1277
+ validityRules[name] = function(elem){
1278
+ return (elem[0].validity || {})[name] || false;
1279
+ };
1280
+ });
1281
+
1282
+ }
1283
+
1284
+ webshims.defineNodeNameProperty('form', 'noValidate', {
1285
+ prop: {
1286
+ set: function(val){
1287
+ val = !!val;
1288
+ if(val){
1289
+ $.attr(this, 'novalidate', 'novalidate');
1290
+ } else {
1291
+ $(this).removeAttr('novalidate');
1292
+ }
1293
+ },
1294
+ get: function(){
1295
+ return $.attr(this, 'novalidate') != null;
1296
+ }
1297
+ }
1298
+ });
1299
+
1300
+ if($.browser.webkit && Modernizr.inputtypes.date){
1301
+ (function(){
1302
+
1303
+ var noInputTriggerEvts = {updateInput: 1, input: 1},
1304
+ fixInputTypes = {
1305
+ date: 1,
1306
+ time: 1,
1307
+ "datetime-local": 1
1308
+ },
1309
+ noFocusEvents = {
1310
+ focusout: 1,
1311
+ blur: 1
1312
+ },
1313
+ changeEvts = {
1314
+ updateInput: 1,
1315
+ change: 1
1316
+ },
1317
+ observe = function(input){
1318
+ var timer,
1319
+ focusedin = true,
1320
+ lastInputVal = input.prop('value'),
1321
+ lastChangeVal = lastInputVal,
1322
+ trigger = function(e){
1323
+ //input === null
1324
+ if(!input){return;}
1325
+ var newVal = input.prop('value');
1326
+
1327
+ if(newVal !== lastInputVal){
1328
+ lastInputVal = newVal;
1329
+ if(!e || !noInputTriggerEvts[e.type]){
1330
+ input.trigger('input');
1331
+ }
1332
+ }
1333
+ if(e && changeEvts[e.type]){
1334
+ lastChangeVal = newVal;
1335
+ }
1336
+ if(!focusedin && newVal !== lastChangeVal){
1337
+ input.trigger('change');
1338
+ }
1339
+ },
1340
+ extraTimer,
1341
+ extraTest = function(){
1342
+ clearTimeout(extraTimer);
1343
+ extraTimer = setTimeout(trigger, 9);
1344
+ },
1345
+ unbind = function(e){
1346
+ clearInterval(timer);
1347
+ setTimeout(function(){
1348
+ if(e && noFocusEvents[e.type]){
1349
+ focusedin = false;
1350
+ }
1351
+ if(input){
1352
+ input.unbind('focusout blur', unbind).unbind('input change updateInput', trigger);
1353
+ trigger();
1354
+ }
1355
+ input = null;
1356
+ }, 1);
1357
+
1358
+ }
1359
+ ;
1360
+
1361
+ clearInterval(timer);
1362
+ timer = setInterval(trigger, 160);
1363
+ extraTest();
1364
+ input
1365
+ .off({
1366
+ 'focusout blur': unbind,
1367
+ 'input change updateInput': trigger
1368
+ })
1369
+ .on({
1370
+ 'focusout blur': unbind,
1371
+ 'input updateInput change': trigger
1372
+ })
1373
+ ;
1374
+ }
1375
+ ;
1376
+ if($.event.customEvent){
1377
+ $.event.customEvent.updateInput = true;
1378
+ }
1379
+
1380
+ (function(){
1381
+
1382
+ var correctValue = function(elem){
1383
+ var i = 1;
1384
+ var len = 3;
1385
+ var abort, val;
1386
+ if(elem.type == 'date' && (isSubmit || !$(elem).is(':focus'))){
1387
+ val = elem.value;
1388
+ if(val && val.length < 10 && (val = val.split('-')) && val.length == len){
1389
+ for(; i < len; i++){
1390
+ if(val[i].length == 1){
1391
+ val[i] = '0'+val[i];
1392
+ } else if(val[i].length != 2){
1393
+ abort = true;
1394
+ break;
1395
+ }
1396
+ }
1397
+ if(!abort){
1398
+ val = val.join('-');
1399
+ $.prop(elem, 'value', val);
1400
+ return val;
1401
+ }
1402
+ }
1403
+ }
1404
+ };
1405
+ var inputCheckValidityDesc, formCheckValidityDesc, inputValueDesc, inputValidityDesc;
1406
+
1407
+ inputCheckValidityDesc = webshims.defineNodeNameProperty('input', 'checkValidity', {
1408
+ prop: {
1409
+ value: function(){
1410
+ correctValue(this);
1411
+ return inputCheckValidityDesc.prop._supvalue.apply(this, arguments);
1412
+ }
1413
+ }
1414
+ });
1415
+
1416
+ formCheckValidityDesc = webshims.defineNodeNameProperty('form', 'checkValidity', {
1417
+ prop: {
1418
+ value: function(){
1419
+ $('input', this).each(function(){
1420
+ correctValue(this);
1421
+ });
1422
+ return formCheckValidityDesc.prop._supvalue.apply(this, arguments);
1423
+ }
1424
+ }
1425
+ });
1426
+
1427
+ inputValueDesc = webshims.defineNodeNameProperty('input', 'value', {
1428
+ prop: {
1429
+ set: function(){
1430
+ return inputValueDesc.prop._supset.apply(this, arguments);
1431
+ },
1432
+ get: function(){
1433
+ return correctValue(this) || inputValueDesc.prop._supget.apply(this, arguments);
1434
+ }
1435
+ }
1436
+ });
1437
+
1438
+ inputValidityDesc = webshims.defineNodeNameProperty('input', 'validity', {
1439
+ prop: {
1440
+ writeable: false,
1441
+ get: function(){
1442
+ correctValue(this);
1443
+ return inputValidityDesc.prop._supget.apply(this, arguments);
1444
+ }
1445
+ }
1446
+ });
1447
+
1448
+ $(document).on('change', function(e){
1449
+ correctValue(e.target);
1450
+ });
1451
+
1452
+ })();
1453
+
1454
+ $(document)
1455
+ .on('focusin', function(e){
1456
+ if( e.target && fixInputTypes[e.target.type] && !e.target.readOnly && !e.target.disabled ){
1457
+ observe($(e.target));
1458
+ }
1459
+ })
1460
+ ;
1461
+
1462
+
1463
+ })();
1464
+ }
1465
+
1466
+ webshims.addReady(function(context, contextElem){
1467
+ //start constrain-validation
1468
+ var focusElem;
1469
+ $('form', context)
1470
+ .add(contextElem.filter('form'))
1471
+ .bind('invalid', $.noop)
1472
+ ;
1473
+
1474
+ try {
1475
+ if(context == document && !('form' in (document.activeElement || {}))) {
1476
+ focusElem = $('input[autofocus], select[autofocus], textarea[autofocus]', context).eq(0).getShadowFocusElement()[0];
1477
+ if (focusElem && focusElem.offsetHeight && focusElem.offsetWidth) {
1478
+ focusElem.focus();
1479
+ }
1480
+ }
1481
+ }
1482
+ catch (er) {}
1483
+
1484
+ });
1485
+
1486
+ if(!Modernizr.formattribute || !Modernizr.fieldsetdisabled){
1487
+ (function(){
1488
+ (function(prop, undefined){
1489
+ $.prop = function(elem, name, value){
1490
+ var ret;
1491
+ if(elem && elem.nodeType == 1 && value === undefined && $.nodeName(elem, 'form') && elem.id){
1492
+ ret = document.getElementsByName(name);
1493
+ if(!ret || !ret.length){
1494
+ ret = document.getElementById(name);
1495
+ }
1496
+ if(ret){
1497
+ ret = $(ret).filter(function(){
1498
+ return $.prop(this, 'form') == elem;
1499
+ }).get();
1500
+ if(ret.length){
1501
+ return ret.length == 1 ? ret[0] : ret;
1502
+ }
1503
+ }
1504
+ }
1505
+ return prop.apply(this, arguments);
1506
+ };
1507
+ })($.prop, undefined);
1508
+ var removeAddedElements = function(form){
1509
+ var elements = $.data(form, 'webshimsAddedElements');
1510
+ if(elements){
1511
+ elements.remove();
1512
+ $.removeData(form, 'webshimsAddedElements');
1513
+ }
1514
+ };
1515
+ var rCRLF = /\r?\n/g,
1516
+ rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
1517
+ rselectTextarea = /^(?:select|textarea)/i;
1518
+
1519
+ if(!Modernizr.formattribute){
1520
+ webshims.defineNodeNamesProperty(['input', 'textarea', 'select', 'button', 'fieldset'], 'form', {
1521
+ prop: {
1522
+ get: function(){
1523
+ var form = webshims.contentAttr(this, 'form');
1524
+ if(form){
1525
+ form = document.getElementById(form);
1526
+ if(form && !$.nodeName(form, 'form')){
1527
+ form = null;
1528
+ }
1529
+ }
1530
+ return form || this.form;
1531
+ },
1532
+ writeable: false
1533
+ }
1534
+ });
1535
+
1536
+
1537
+ webshims.defineNodeNamesProperty(['form'], 'elements', {
1538
+ prop: {
1539
+ get: function(){
1540
+ var id = this.id;
1541
+ var elements = $.makeArray(this.elements);
1542
+ if(id){
1543
+ elements = $(elements).add('input[form="'+ id +'"], select[form="'+ id +'"], textarea[form="'+ id +'"], button[form="'+ id +'"], fieldset[form="'+ id +'"]').not('.webshims-visual-hide > *').get();
1544
+ }
1545
+ return elements;
1546
+ },
1547
+ writeable: false
1548
+ }
1549
+ });
1550
+
1551
+
1552
+
1553
+ $(function(){
1554
+ var stopPropagation = function(e){
1555
+ e.stopPropagation();
1556
+ };
1557
+ $(document).on('submit', function(e){
1558
+
1559
+ if(!e.isDefaultPrevented()){
1560
+ var form = e.target;
1561
+ var id = form.id;
1562
+ var elements;
1563
+
1564
+
1565
+ if(id){
1566
+ removeAddedElements(form);
1567
+
1568
+ elements = $('input[form="'+ id +'"], select[form="'+ id +'"], textarea[form="'+ id +'"]')
1569
+ .filter(function(){
1570
+ return !this.disabled && this.name && this.form != form;
1571
+ })
1572
+ .clone()
1573
+ ;
1574
+ if(elements.length){
1575
+ $.data(form, 'webshimsAddedElements', $('<div class="webshims-visual-hide" />').append(elements).appendTo(form));
1576
+ setTimeout(function(){
1577
+ removeAddedElements(form);
1578
+ }, 9);
1579
+ }
1580
+ elements = null;
1581
+ }
1582
+ }
1583
+ });
1584
+
1585
+ $(document).on('click', function(e){
1586
+ if(!e.isDefaultPrevented() && $(e.target).is('input[type="submit"][form], button[form], input[type="button"][form], input[type="image"][form], input[type="reset"][form]')){
1587
+ var trueForm = $.prop(e.target, 'form');
1588
+ var formIn = e.target.form;
1589
+ var clone;
1590
+ if(trueForm && trueForm != formIn){
1591
+ clone = $(e.target)
1592
+ .clone()
1593
+ .removeAttr('form')
1594
+ .addClass('webshims-visual-hide')
1595
+ .on('click', stopPropagation)
1596
+ .appendTo(trueForm)
1597
+ ;
1598
+ if(formIn){
1599
+ e.preventDefault();
1600
+ }
1601
+ addSubmitBubbles(trueForm);
1602
+ clone.trigger('click');
1603
+ setTimeout(function(){
1604
+ clone.remove();
1605
+ clone = null;
1606
+ }, 9);
1607
+ }
1608
+ }
1609
+ });
1610
+ });
1611
+ }
1612
+
1613
+ if(!Modernizr.fieldsetdisabled){
1614
+ webshims.defineNodeNamesProperty(['fieldset'], 'elements', {
1615
+ prop: {
1616
+ get: function(){
1617
+ //add listed elements without keygen, object, output
1618
+ return $('input, select, textarea, button, fieldset', this).get() || [];
1619
+ },
1620
+ writeable: false
1621
+ }
1622
+ });
1623
+ }
1624
+
1625
+ $.fn.serializeArray = function() {
1626
+ return this.map(function(){
1627
+ var elements = $.prop(this, 'elements');
1628
+ return elements ? $.makeArray( elements ) : this;
1629
+ })
1630
+ .filter(function(){
1631
+ return this.name && !this.disabled &&
1632
+ ( this.checked || rselectTextarea.test( this.nodeName ) ||
1633
+ rinput.test( this.type ) );
1634
+ })
1635
+ .map(function( i, elem ){
1636
+ var val = $( this ).val();
1637
+
1638
+ return val == null ?
1639
+ null :
1640
+ $.isArray( val ) ?
1641
+ $.map( val, function( val, i ){
1642
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
1643
+ }) :
1644
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
1645
+ }).get();
1646
+ };
1647
+
1648
+ })();
1649
+ }
1650
+
1651
+ try {
1652
+ document.querySelector(':checked');
1653
+ } catch(er){
1654
+ (function(){
1655
+ var checkInputs = {
1656
+ radio: 1,
1657
+ checkbox: 1
1658
+ };
1659
+ var selectChange = function(){
1660
+ var options = this.options || [];
1661
+ var i, len, option;
1662
+ for(i = 0, len = options.length; i < len; i++){
1663
+ option = $(options[i]);
1664
+ option[$.prop(options[i], 'selected') ? 'addClass' : 'removeClass']('prop-checked');
1665
+ }
1666
+ };
1667
+ var checkChange = function(){
1668
+ var fn = $.prop(this, 'checked') ? 'addClass' : 'removeClass';
1669
+ var className = this.className || '';
1670
+ var parent;
1671
+
1672
+ //IE8- has problems to update styles, we help
1673
+ if( (className.indexOf('prop-checked') == -1) == (fn == 'addClass')){
1674
+ $(this)[fn]('prop-checked');
1675
+ if((parent = this.parentNode)){
1676
+ parent.className = parent.className;
1677
+ }
1678
+ }
1679
+ };
1680
+
1681
+
1682
+ webshims.onNodeNamesPropertyModify('select', 'value', selectChange);
1683
+ webshims.onNodeNamesPropertyModify('select', 'selectedIndex', selectChange);
1684
+ webshims.onNodeNamesPropertyModify('option', 'selected', function(){
1685
+ $(this).closest('select').each(selectChange);
1686
+ });
1687
+ webshims.onNodeNamesPropertyModify('input', 'checked', function(value, boolVal){
1688
+ var type = this.type;
1689
+ if(type == 'radio' && boolVal){
1690
+ webshims.modules["form-core"].getGroupElements(this).each(checkChange);
1691
+ } else if(checkInputs[type]) {
1692
+ $(this).each(checkChange);
1693
+ }
1694
+ });
1695
+
1696
+ $(document).on('change', function(e){
1697
+
1698
+ if(checkInputs[e.target.type]){
1699
+ if(e.target.type == 'radio'){
1700
+ webshims.modules["form-core"].getGroupElements(e.target).each(checkChange);
1701
+ } else {
1702
+ $(e.target)[$.prop(e.target, 'checked') ? 'addClass' : 'removeClass']('prop-checked');
1703
+ }
1704
+ } else if(e.target.nodeName.toLowerCase() == 'select'){
1705
+ $(e.target).each(selectChange);
1706
+ }
1707
+ });
1708
+
1709
+ webshims.addReady(function(context, contextElem){
1710
+ $('option, input', context)
1711
+ .add(contextElem.filter('option, input'))
1712
+ .each(function(){
1713
+ var prop;
1714
+ if(checkInputs[this.type]){
1715
+ prop = 'checked';
1716
+ } else if(this.nodeName.toLowerCase() == 'option'){
1717
+ prop = 'selected';
1718
+ }
1719
+ if(prop){
1720
+ $(this)[$.prop(this, prop) ? 'addClass' : 'removeClass']('prop-checked');
1721
+ }
1722
+
1723
+ })
1724
+ ;
1725
+ });
1726
+ })();
1727
+ }
1728
+
1729
+ (function(){
1730
+ Modernizr.textareaPlaceholder = !!('placeholder' in $('<textarea />')[0]);
1731
+ var bustedTextarea = $.browser.webkit && Modernizr.textareaPlaceholder && webshims.browserVersion < 535;
1732
+ if(Modernizr.input.placeholder && Modernizr.textareaPlaceholder && !bustedTextarea){return;}
1733
+
1734
+ var isOver = (webshims.cfg.forms.placeholderType == 'over');
1735
+ var isResponsive = (webshims.cfg.forms.responsivePlaceholder);
1736
+ var polyfillElements = ['textarea'];
1737
+ if(!Modernizr.input.placeholder){
1738
+ polyfillElements.push('input');
1739
+ }
1740
+
1741
+ var setSelection = function(elem){
1742
+ try {
1743
+ if(elem.setSelectionRange){
1744
+ elem.setSelectionRange(0, 0);
1745
+ return true;
1746
+ } else if(elem.createTextRange){
1747
+ var range = elem.createTextRange();
1748
+ range.collapse(true);
1749
+ range.moveEnd('character', 0);
1750
+ range.moveStart('character', 0);
1751
+ range.select();
1752
+ return true;
1753
+ }
1754
+ } catch(er){}
1755
+ };
1756
+
1757
+ var hidePlaceholder = function(elem, data, value, _onFocus){
1758
+ if(value === false){
1759
+ value = $.prop(elem, 'value');
1760
+ }
1761
+ if(!isOver && elem.type != 'password'){
1762
+ if(!value && _onFocus && setSelection(elem)){
1763
+ var selectTimer = setTimeout(function(){
1764
+ setSelection(elem);
1765
+ }, 9);
1766
+ $(elem)
1767
+ .off('.placeholderremove')
1768
+ .on({
1769
+ 'keydown.placeholderremove keypress.placeholderremove paste.placeholderremove input.placeholderremove': function(e){
1770
+ if(e && (e.keyCode == 17 || e.keyCode == 16)){return;}
1771
+ elem.value = $.prop(elem, 'value');
1772
+ data.box.removeClass('placeholder-visible');
1773
+ clearTimeout(selectTimer);
1774
+ $(elem).unbind('.placeholderremove');
1775
+ },
1776
+ 'mousedown.placeholderremove drag.placeholderremove select.placeholderremove': function(e){
1777
+ setSelection(elem);
1778
+ clearTimeout(selectTimer);
1779
+ selectTimer = setTimeout(function(){
1780
+ setSelection(elem);
1781
+ }, 9);
1782
+ },
1783
+ 'blur.placeholderremove': function(){
1784
+ clearTimeout(selectTimer);
1785
+ $(elem).unbind('.placeholderremove');
1786
+ }
1787
+ })
1788
+ ;
1789
+ return;
1790
+ }
1791
+ elem.value = value;
1792
+ } else if(!value && _onFocus){
1793
+ $(elem)
1794
+ .off('.placeholderremove')
1795
+ .on({
1796
+ 'keydown.placeholderremove keypress.placeholderremove paste.placeholderremove input.placeholderremove': function(e){
1797
+ if(e && (e.keyCode == 17 || e.keyCode == 16)){return;}
1798
+ data.box.removeClass('placeholder-visible');
1799
+ $(elem).unbind('.placeholderremove');
1800
+ },
1801
+ 'blur.placeholderremove': function(){
1802
+ $(elem).unbind('.placeholderremove');
1803
+ }
1804
+ })
1805
+ ;
1806
+ return;
1807
+ }
1808
+ data.box.removeClass('placeholder-visible');
1809
+ },
1810
+ showPlaceholder = function(elem, data, placeholderTxt){
1811
+ if(placeholderTxt === false){
1812
+ placeholderTxt = $.prop(elem, 'placeholder');
1813
+ }
1814
+
1815
+ if(!isOver && elem.type != 'password'){
1816
+ elem.value = placeholderTxt;
1817
+ }
1818
+ data.box.addClass('placeholder-visible');
1819
+ },
1820
+ changePlaceholderVisibility = function(elem, value, placeholderTxt, data, type){
1821
+ if(!data){
1822
+ data = $.data(elem, 'placeHolder');
1823
+ if(!data){return;}
1824
+ }
1825
+ $(elem).unbind('.placeholderremove');
1826
+ if(type == 'focus' || (!type && $(elem).is(':focus'))){
1827
+ if(elem.type == 'password' || isOver || $(elem).hasClass('placeholder-visible')){
1828
+ hidePlaceholder(elem, data, '', true);
1829
+ }
1830
+ return;
1831
+ }
1832
+ if(value === false){
1833
+ value = $.prop(elem, 'value');
1834
+ }
1835
+ if(value){
1836
+ hidePlaceholder(elem, data, value);
1837
+ return;
1838
+ }
1839
+ if(placeholderTxt === false){
1840
+ placeholderTxt = $.attr(elem, 'placeholder') || '';
1841
+ }
1842
+ if(placeholderTxt && !value){
1843
+ showPlaceholder(elem, data, placeholderTxt);
1844
+ } else {
1845
+ hidePlaceholder(elem, data, value);
1846
+ }
1847
+ },
1848
+ createPlaceholder = function(elem){
1849
+ elem = $(elem);
1850
+ var id = elem.prop('id'),
1851
+ hasLabel = !!(elem.prop('title') || elem.attr('aria-labelledby'))
1852
+ ;
1853
+ if(!hasLabel && id){
1854
+ hasLabel = !!( $('label[for="'+ id +'"]', elem[0].form)[0] );
1855
+ }
1856
+ if(!hasLabel){
1857
+ if(!id){
1858
+ id = $.webshims.getID(elem);
1859
+ }
1860
+ hasLabel = !!($('label #'+ id)[0]);
1861
+ }
1862
+ return $( hasLabel ? '<span class="placeholder-text"></span>' : '<label for="'+ id +'" class="placeholder-text"></label>');
1863
+ },
1864
+ pHolder = (function(){
1865
+ var delReg = /\n|\r|\f|\t/g,
1866
+ allowedPlaceholder = {
1867
+ text: 1,
1868
+ search: 1,
1869
+ url: 1,
1870
+ email: 1,
1871
+ password: 1,
1872
+ tel: 1,
1873
+ number: 1
1874
+ }
1875
+ ;
1876
+
1877
+ return {
1878
+ create: function(elem){
1879
+ var data = $.data(elem, 'placeHolder');
1880
+ var form;
1881
+ var responsiveElem;
1882
+ if(data){return data;}
1883
+ data = $.data(elem, 'placeHolder', {});
1884
+
1885
+ $(elem).on('focus.placeholder blur.placeholder', function(e){
1886
+ changePlaceholderVisibility(this, false, false, data, e.type );
1887
+ data.box[e.type == 'focus' ? 'addClass' : 'removeClass']('placeholder-focused');
1888
+ });
1889
+
1890
+ if((form = $.prop(elem, 'form'))){
1891
+ $(form).on('reset.placeholder', function(e){
1892
+ setTimeout(function(){
1893
+ changePlaceholderVisibility(elem, false, false, data, e.type );
1894
+ }, 0);
1895
+ });
1896
+ }
1897
+
1898
+ if(elem.type == 'password' || isOver){
1899
+ data.text = createPlaceholder(elem);
1900
+ if(isResponsive || $(elem).is('.responsive-width') || (elem.currentStyle || {width: ''}).width.indexOf('%') != -1){
1901
+ responsiveElem = true;
1902
+ data.box = data.text;
1903
+ } else {
1904
+ data.box = $(elem)
1905
+ .wrap('<span class="placeholder-box placeholder-box-'+ (elem.nodeName || '').toLowerCase() +' placeholder-box-'+$.css(elem, 'float')+'" />')
1906
+ .parent()
1907
+ ;
1908
+ }
1909
+ data.text
1910
+ .insertAfter(elem)
1911
+ .on('mousedown.placeholder', function(){
1912
+ changePlaceholderVisibility(this, false, false, data, 'focus');
1913
+ try {
1914
+ setTimeout(function(){
1915
+ elem.focus();
1916
+ }, 0);
1917
+ } catch(e){}
1918
+ return false;
1919
+ })
1920
+ ;
1921
+
1922
+
1923
+ $.each(['lineHeight', 'fontSize', 'fontFamily', 'fontWeight'], function(i, style){
1924
+ var prop = $.css(elem, style);
1925
+ if(data.text.css(style) != prop){
1926
+ data.text.css(style, prop);
1927
+ }
1928
+ });
1929
+ $.each(['Left', 'Top'], function(i, side){
1930
+ var size = (parseInt($.css(elem, 'padding'+ side), 10) || 0) + Math.max((parseInt($.css(elem, 'margin'+ side), 10) || 0), 0) + (parseInt($.css(elem, 'border'+ side +'Width'), 10) || 0);
1931
+ data.text.css('padding'+ side, size);
1932
+ });
1933
+
1934
+ $(elem)
1935
+ .on('updateshadowdom', function(){
1936
+ var height, width;
1937
+ if((width = elem.offsetWidth) || (height = elem.offsetHeight)){
1938
+ data.text
1939
+ .css({
1940
+ width: width,
1941
+ height: height
1942
+ })
1943
+ .css($(elem).position())
1944
+ ;
1945
+ }
1946
+ })
1947
+ .triggerHandler('updateshadowdom')
1948
+ ;
1949
+
1950
+ } else {
1951
+ var reset = function(e){
1952
+ if($(elem).hasClass('placeholder-visible')){
1953
+ hidePlaceholder(elem, data, '');
1954
+ if(e && e.type == 'submit'){
1955
+ setTimeout(function(){
1956
+ if(e.isDefaultPrevented()){
1957
+ changePlaceholderVisibility(elem, false, false, data );
1958
+ }
1959
+ }, 9);
1960
+ }
1961
+ }
1962
+ };
1963
+
1964
+ $(window).on('beforeunload', reset);
1965
+ data.box = $(elem);
1966
+ if(form){
1967
+ $(form).submit(reset);
1968
+ }
1969
+ }
1970
+
1971
+ return data;
1972
+ },
1973
+ update: function(elem, val){
1974
+ var type = ($.attr(elem, 'type') || $.prop(elem, 'type') || '').toLowerCase();
1975
+ if(!allowedPlaceholder[type] && !$.nodeName(elem, 'textarea')){
1976
+ webshims.error('placeholder not allowed on input[type="'+type+'"]');
1977
+ if(type == 'date'){
1978
+ webshims.error('but you can use data-placeholder for input[type="date"]');
1979
+ }
1980
+ return;
1981
+ }
1982
+
1983
+
1984
+ var data = pHolder.create(elem);
1985
+ if(data.text){
1986
+ data.text.text(val);
1987
+ }
1988
+
1989
+ changePlaceholderVisibility(elem, false, val, data);
1990
+ }
1991
+ };
1992
+ })()
1993
+ ;
1994
+
1995
+ $.webshims.publicMethods = {
1996
+ pHolder: pHolder
1997
+ };
1998
+ polyfillElements.forEach(function(nodeName){
1999
+ var desc = webshims.defineNodeNameProperty(nodeName, 'placeholder', {
2000
+ attr: {
2001
+ set: function(val){
2002
+ var elem = this;
2003
+ if(bustedTextarea){
2004
+ webshims.data(elem, 'textareaPlaceholder', val);
2005
+ elem.placeholder = '';
2006
+ } else {
2007
+ webshims.contentAttr(elem, 'placeholder', val);
2008
+ }
2009
+ pHolder.update(elem, val);
2010
+ },
2011
+ get: function(){
2012
+ var ret = (bustedTextarea) ? webshims.data(this, 'textareaPlaceholder') : '';
2013
+ return ret || webshims.contentAttr(this, 'placeholder');
2014
+ }
2015
+ },
2016
+ reflect: true,
2017
+ initAttr: true
2018
+ });
2019
+ });
2020
+
2021
+
2022
+ polyfillElements.forEach(function(name){
2023
+ var placeholderValueDesc = {};
2024
+ var desc;
2025
+ ['attr', 'prop'].forEach(function(propType){
2026
+ placeholderValueDesc[propType] = {
2027
+ set: function(val){
2028
+ var elem = this;
2029
+ var placeholder;
2030
+ if(bustedTextarea){
2031
+ placeholder = webshims.data(elem, 'textareaPlaceholder');
2032
+ }
2033
+ if(!placeholder){
2034
+ placeholder = webshims.contentAttr(elem, 'placeholder');
2035
+ }
2036
+ $.removeData(elem, 'cachedValidity');
2037
+ var ret = desc[propType]._supset.call(elem, val);
2038
+ if(placeholder && 'value' in elem){
2039
+ changePlaceholderVisibility(elem, val, placeholder);
2040
+ }
2041
+ return ret;
2042
+ },
2043
+ get: function(){
2044
+ var elem = this;
2045
+ return $(elem).hasClass('placeholder-visible') ? '' : desc[propType]._supget.call(elem);
2046
+ }
2047
+ };
2048
+ });
2049
+ desc = webshims.defineNodeNameProperty(name, 'value', placeholderValueDesc);
2050
+ });
2051
+
2052
+ })();
2053
+
2054
+ (function(){
2055
+ var doc = document;
2056
+ if( 'value' in document.createElement('output') ){return;}
2057
+
2058
+ webshims.defineNodeNameProperty('output', 'value', {
2059
+ prop: {
2060
+ set: function(value){
2061
+ var setVal = $.data(this, 'outputShim');
2062
+ if(!setVal){
2063
+ setVal = outputCreate(this);
2064
+ }
2065
+ setVal(value);
2066
+ },
2067
+ get: function(){
2068
+ return webshims.contentAttr(this, 'value') || $(this).text() || '';
2069
+ }
2070
+ }
2071
+ });
2072
+
2073
+
2074
+ webshims.onNodeNamesPropertyModify('input', 'value', function(value, boolVal, type){
2075
+ if(type == 'removeAttr'){return;}
2076
+ var setVal = $.data(this, 'outputShim');
2077
+ if(setVal){
2078
+ setVal(value);
2079
+ }
2080
+ });
2081
+
2082
+ var outputCreate = function(elem){
2083
+ if(elem.getAttribute('aria-live')){return;}
2084
+ elem = $(elem);
2085
+ var value = (elem.text() || '').trim();
2086
+ var id = elem.attr('id');
2087
+ var htmlFor = elem.attr('for');
2088
+ var shim = $('<input class="output-shim" type="text" disabled name="'+ (elem.attr('name') || '')+'" value="'+value+'" style="display: none !important;" />').insertAfter(elem);
2089
+ var form = shim[0].form || doc;
2090
+ var setValue = function(val){
2091
+ shim[0].value = val;
2092
+ val = shim[0].value;
2093
+ elem.text(val);
2094
+ webshims.contentAttr(elem[0], 'value', val);
2095
+ };
2096
+
2097
+ elem[0].defaultValue = value;
2098
+ webshims.contentAttr(elem[0], 'value', value);
2099
+
2100
+ elem.attr({'aria-live': 'polite'});
2101
+ if(id){
2102
+ shim.attr('id', id);
2103
+ elem.attr('aria-labelledby', webshims.getID($('label[for="'+id+'"]', form)));
2104
+ }
2105
+ if(htmlFor){
2106
+ id = webshims.getID(elem);
2107
+ htmlFor.split(' ').forEach(function(control){
2108
+ control = document.getElementById(control);
2109
+ if(control){
2110
+ control.setAttribute('aria-controls', id);
2111
+ }
2112
+ });
2113
+ }
2114
+ elem.data('outputShim', setValue );
2115
+ shim.data('outputShim', setValue );
2116
+ return setValue;
2117
+ };
2118
+
2119
+ webshims.addReady(function(context, contextElem){
2120
+ $('output', context).add(contextElem.filter('output')).each(function(){
2121
+ outputCreate(this);
2122
+ });
2123
+ });
2124
+
2125
+ /*
2126
+ * Implements input event in all browsers
2127
+ */
2128
+ (function(){
2129
+ var noInputTriggerEvts = {updateInput: 1, input: 1},
2130
+ noInputTypes = {
2131
+ radio: 1,
2132
+ checkbox: 1,
2133
+ submit: 1,
2134
+ button: 1,
2135
+ image: 1,
2136
+ reset: 1,
2137
+ file: 1
2138
+
2139
+ //pro forma
2140
+ ,color: 1
2141
+ //,range: 1
2142
+ },
2143
+ observe = function(input){
2144
+ var timer,
2145
+ lastVal = input.prop('value'),
2146
+ trigger = function(e){
2147
+ //input === null
2148
+ if(!input){return;}
2149
+ var newVal = input.prop('value');
2150
+
2151
+ if(newVal !== lastVal){
2152
+ lastVal = newVal;
2153
+ if(!e || !noInputTriggerEvts[e.type]){
2154
+ webshims.triggerInlineForm && webshims.triggerInlineForm(input[0], 'input');
2155
+ }
2156
+ }
2157
+ },
2158
+ extraTimer,
2159
+ extraTest = function(){
2160
+ clearTimeout(extraTimer);
2161
+ extraTimer = setTimeout(trigger, 9);
2162
+ },
2163
+ unbind = function(){
2164
+ input.unbind('focusout', unbind).unbind('keyup keypress keydown paste cut', extraTest).unbind('input change updateInput', trigger);
2165
+ clearInterval(timer);
2166
+ setTimeout(function(){
2167
+ trigger();
2168
+ input = null;
2169
+ }, 1);
2170
+
2171
+ }
2172
+ ;
2173
+
2174
+ clearInterval(timer);
2175
+ timer = setInterval(trigger, 99);
2176
+ extraTest();
2177
+ input.on({
2178
+ 'keyup keypress keydown paste cut': extraTest,
2179
+ focusout: unbind,
2180
+ 'input updateInput change': trigger
2181
+ });
2182
+ }
2183
+ ;
2184
+ if($.event.customEvent){
2185
+ $.event.customEvent.updateInput = true;
2186
+ }
2187
+
2188
+ $(doc)
2189
+ .on('focusin', function(e){
2190
+ if( e.target && e.target.type && !e.target.readOnly && !e.target.disabled && (e.target.nodeName || '').toLowerCase() == 'input' && !noInputTypes[e.target.type] ){
2191
+ observe($(e.target));
2192
+ }
2193
+ })
2194
+ ;
2195
+ })();
2196
+ })();
2197
+
2198
+ }); //webshims.ready end
2199
+ }//end formvalidation
2200
+
2201
+ jQuery.webshims.register('form-message', function($, webshims, window, document, undefined, options){
2202
+ "use strict";
2203
+ var validityMessages = webshims.validityMessages;
2204
+
2205
+ var implementProperties = (options.overrideMessages || options.customMessages) ? ['customValidationMessage'] : [];
2206
+
2207
+ validityMessages['en'] = $.extend(true, {
2208
+ typeMismatch: {
2209
+ email: 'Please enter an email address.',
2210
+ url: 'Please enter a URL.',
2211
+ number: 'Please enter a number.',
2212
+ date: 'Please enter a date.',
2213
+ time: 'Please enter a time.',
2214
+ range: 'Invalid input.',
2215
+ "datetime-local": 'Please enter a datetime.'
2216
+ },
2217
+ rangeUnderflow: {
2218
+ defaultMessage: 'Value must be greater than or equal to {%min}.'
2219
+ },
2220
+ rangeOverflow: {
2221
+ defaultMessage: 'Value must be less than or equal to {%max}.'
2222
+ },
2223
+ stepMismatch: 'Invalid input.',
2224
+ tooLong: 'Please enter at most {%maxlength} character(s). You entered {%valueLen}.',
2225
+
2226
+ patternMismatch: 'Invalid input. {%title}',
2227
+ valueMissing: {
2228
+ defaultMessage: 'Please fill out this field.',
2229
+ checkbox: 'Please check this box if you want to proceed.'
2230
+ }
2231
+ }, (validityMessages['en'] || validityMessages['en-US'] || {}));
2232
+
2233
+
2234
+ ['select', 'radio'].forEach(function(type){
2235
+ if(typeof validityMessages['en'].valueMissing == 'object'){
2236
+ validityMessages['en'].valueMissing[type] = 'Please select an option.';
2237
+ }
2238
+ });
2239
+
2240
+ ['date', 'time', 'datetime-local'].forEach(function(type){
2241
+ if(typeof validityMessages['en'].rangeUnderflow == 'object'){
2242
+ validityMessages.en.rangeUnderflow[type] = 'Value must be at or after {%min}.';
2243
+ }
2244
+ });
2245
+ ['date', 'time', 'datetime-local'].forEach(function(type){
2246
+ if(typeof validityMessages['en'].rangeOverflow == 'object'){
2247
+ validityMessages.en.rangeOverflow[type] = 'Value must be at or before {%max}.';
2248
+ }
2249
+ });
2250
+
2251
+ validityMessages['en-US'] = validityMessages['en-US'] || validityMessages['en'];
2252
+ validityMessages[''] = validityMessages[''] || validityMessages['en-US'];
2253
+
2254
+ validityMessages['de'] = $.extend(true, {
2255
+ typeMismatch: {
2256
+ email: '{%value} ist keine zulässige E-Mail-Adresse',
2257
+ url: '{%value} ist keine zulässige Webadresse',
2258
+ number: '{%value} ist keine Nummer!',
2259
+ date: '{%value} ist kein Datum',
2260
+ time: '{%value} ist keine Uhrzeit',
2261
+ range: '{%value} ist keine Nummer!',
2262
+ "datetime-local": '{%value} ist kein Datum-Uhrzeit Format.'
2263
+ },
2264
+ rangeUnderflow: {
2265
+ defaultMessage: '{%value} ist zu niedrig. {%min} ist der unterste Wert, den Sie benutzen können.'
2266
+ },
2267
+ rangeOverflow: {
2268
+ defaultMessage: '{%value} ist zu hoch. {%max} ist der oberste Wert, den Sie benutzen können.'
2269
+ },
2270
+ stepMismatch: 'Der Wert {%value} ist in diesem Feld nicht zulässig. Hier sind nur bestimmte Werte zulässig. {%title}',
2271
+ tooLong: 'Der eingegebene Text ist zu lang! Sie haben {%valueLen} Zeichen eingegeben, dabei sind {%maxlength} das Maximum.',
2272
+ patternMismatch: '{%value} hat für dieses Eingabefeld ein falsches Format! {%title}',
2273
+ valueMissing: {
2274
+ defaultMessage: 'Bitte geben Sie einen Wert ein',
2275
+ checkbox: 'Bitte aktivieren Sie das Kästchen'
2276
+ }
2277
+ }, (validityMessages['de'] || {}));
2278
+
2279
+ ['select', 'radio'].forEach(function(type){
2280
+ if(typeof validityMessages['de'].valueMissing == 'object'){
2281
+ validityMessages['de'].valueMissing[type] = 'Bitte wählen Sie eine Option aus';
2282
+ }
2283
+ });
2284
+
2285
+ ['date', 'time', 'datetime-local'].forEach(function(type){
2286
+ if(typeof validityMessages['de'].rangeUnderflow == 'object'){
2287
+ validityMessages.de.rangeUnderflow[type] = '{%value} ist zu früh. {%min} ist die früheste Zeit, die Sie benutzen können.';
2288
+ }
2289
+ });
2290
+ ['date', 'time', 'datetime-local'].forEach(function(type){
2291
+ if(typeof validityMessages['de'].rangeOverflow == 'object'){
2292
+ validityMessages.de.rangeOverflow[type] = '{%value} ist zu spät. {%max} ist die späteste Zeit, die Sie benutzen können.';
2293
+ }
2294
+ });
2295
+
2296
+ var currentValidationMessage = validityMessages[''];
2297
+
2298
+
2299
+ webshims.createValidationMessage = function(elem, name){
2300
+ var message = currentValidationMessage[name];
2301
+ if(message && typeof message !== 'string'){
2302
+ message = message[ $.prop(elem, 'type') ] || message[ (elem.nodeName || '').toLowerCase() ] || message[ 'defaultMessage' ];
2303
+ }
2304
+ if(message){
2305
+ ['value', 'min', 'max', 'title', 'maxlength', 'label'].forEach(function(attr){
2306
+ if(message.indexOf('{%'+attr) === -1){return;}
2307
+ var val = ((attr == 'label') ? $.trim($('label[for="'+ elem.id +'"]', elem.form).text()).replace(/\*$|:$/, '') : $.attr(elem, attr)) || '';
2308
+ if(name == 'patternMismatch' && attr == 'title' && !val){
2309
+ webshims.error('no title for patternMismatch provided. Always add a title attribute.');
2310
+ }
2311
+ message = message.replace('{%'+ attr +'}', val);
2312
+ if('value' == attr){
2313
+ message = message.replace('{%valueLen}', val.length);
2314
+ }
2315
+ });
2316
+ }
2317
+ return message || '';
2318
+ };
2319
+
2320
+
2321
+ if(webshims.bugs.validationMessage || !Modernizr.formvalidation || webshims.bugs.bustedValidity){
2322
+ implementProperties.push('validationMessage');
2323
+ }
2324
+
2325
+ webshims.activeLang({
2326
+ langObj: validityMessages,
2327
+ module: 'form-core',
2328
+ callback: function(langObj){
2329
+ currentValidationMessage = langObj;
2330
+ }
2331
+ });
2332
+
2333
+ implementProperties.forEach(function(messageProp){
2334
+ webshims.defineNodeNamesProperty(['fieldset', 'output', 'button'], messageProp, {
2335
+ prop: {
2336
+ value: '',
2337
+ writeable: false
2338
+ }
2339
+ });
2340
+ ['input', 'select', 'textarea'].forEach(function(nodeName){
2341
+ var desc = webshims.defineNodeNameProperty(nodeName, messageProp, {
2342
+ prop: {
2343
+ get: function(){
2344
+ var elem = this;
2345
+ var message = '';
2346
+ if(!$.prop(elem, 'willValidate')){
2347
+ return message;
2348
+ }
2349
+
2350
+ var validity = $.prop(elem, 'validity') || {valid: 1};
2351
+
2352
+ if(validity.valid){return message;}
2353
+ message = webshims.getContentValidationMessage(elem, validity);
2354
+
2355
+ if(message){return message;}
2356
+
2357
+ if(validity.customError && elem.nodeName){
2358
+ message = (Modernizr.formvalidation && !webshims.bugs.bustedValidity && desc.prop._supget) ? desc.prop._supget.call(elem) : webshims.data(elem, 'customvalidationMessage');
2359
+ if(message){return message;}
2360
+ }
2361
+ $.each(validity, function(name, prop){
2362
+ if(name == 'valid' || !prop){return;}
2363
+
2364
+ message = webshims.createValidationMessage(elem, name);
2365
+ if(message){
2366
+ return false;
2367
+ }
2368
+ });
2369
+ return message || '';
2370
+ },
2371
+ writeable: false
2372
+ }
2373
+ });
2374
+ });
2375
+
2376
+ });
2341
2377
  });