webshims-rails 0.4.4 → 0.4.5

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