webshims-rails 0.3 → 0.4

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