webshims-rails 0.4.7 → 1.10.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. checksums.yaml +15 -0
  2. data/lib/webshims-rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/webshims/extras/custom-validity.js +1 -1
  4. data/vendor/assets/javascripts/webshims/extras/mousepress.js +1 -1
  5. data/vendor/assets/javascripts/webshims/polyfiller.js +197 -166
  6. data/vendor/assets/javascripts/webshims/shims/combos/1.js +1711 -1609
  7. data/vendor/assets/javascripts/webshims/shims/combos/10.js +2575 -2253
  8. data/vendor/assets/javascripts/webshims/shims/combos/11.js +2452 -1476
  9. data/vendor/assets/javascripts/webshims/shims/combos/12.js +1405 -1159
  10. data/vendor/assets/javascripts/webshims/shims/combos/13.js +1316 -963
  11. data/vendor/assets/javascripts/webshims/shims/combos/14.js +1862 -179
  12. data/vendor/assets/javascripts/webshims/shims/combos/15.js +4327 -287
  13. data/vendor/assets/javascripts/webshims/shims/combos/16.js +3887 -586
  14. data/vendor/assets/javascripts/webshims/shims/combos/17.js +2911 -2159
  15. data/vendor/assets/javascripts/webshims/shims/combos/18.js +3425 -1730
  16. data/vendor/assets/javascripts/webshims/shims/combos/19.js +2854 -1203
  17. data/vendor/assets/javascripts/webshims/shims/combos/2.js +3351 -2130
  18. data/vendor/assets/javascripts/webshims/shims/combos/20.js +2426 -581
  19. data/vendor/assets/javascripts/webshims/shims/combos/21.js +1915 -1574
  20. data/vendor/assets/javascripts/webshims/shims/combos/22.js +864 -2275
  21. data/vendor/assets/javascripts/webshims/shims/combos/23.js +609 -1811
  22. data/vendor/assets/javascripts/webshims/shims/combos/3.js +1655 -2736
  23. data/vendor/assets/javascripts/webshims/shims/combos/4.js +1037 -603
  24. data/vendor/assets/javascripts/webshims/shims/combos/5.js +3100 -773
  25. data/vendor/assets/javascripts/webshims/shims/combos/6.js +3631 -840
  26. data/vendor/assets/javascripts/webshims/shims/combos/7.js +3596 -1354
  27. data/vendor/assets/javascripts/webshims/shims/combos/8.js +1731 -188
  28. data/vendor/assets/javascripts/webshims/shims/combos/9.js +3243 -1431
  29. data/vendor/assets/javascripts/webshims/shims/dom-extend.js +107 -18
  30. data/vendor/assets/javascripts/webshims/shims/es5.js +1 -0
  31. data/vendor/assets/javascripts/webshims/shims/form-core.js +553 -464
  32. data/vendor/assets/javascripts/webshims/shims/form-datalist.js +160 -154
  33. data/vendor/assets/javascripts/webshims/shims/form-message.js +73 -49
  34. data/vendor/assets/javascripts/webshims/shims/form-native-extend.js +18 -1
  35. data/vendor/assets/javascripts/webshims/shims/form-number-date-api.js +161 -36
  36. data/vendor/assets/javascripts/webshims/shims/form-number-date-ui.js +2130 -813
  37. data/vendor/assets/javascripts/webshims/shims/form-shim-extend.js +206 -58
  38. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-ar.js → formcfg-ar.js} +30 -0
  39. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-ch-ZN.js → formcfg-ch-ZN.js} +31 -0
  40. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-de.txt → formcfg-de.txt} +50 -11
  41. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-el.js → formcfg-el.js} +31 -0
  42. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-en.txt → formcfg-en.txt} +44 -11
  43. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-es.js → formcfg-es.js} +31 -0
  44. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-fr.js → formcfg-fr.js} +31 -0
  45. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-he.js → formcfg-he.js} +31 -0
  46. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-hi.js → formcfg-hi.js} +31 -0
  47. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-hu.js → formcfg-hu.js} +31 -0
  48. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-it.js → formcfg-it.js} +31 -0
  49. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-ja.js → formcfg-ja.js} +31 -0
  50. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-nl.js → formcfg-nl.js} +31 -0
  51. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-pt-PT.js → formcfg-pt-PT.js} +31 -0
  52. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-ru.js → formcfg-ru.js} +31 -0
  53. data/vendor/assets/javascripts/webshims/shims/i18n/{errormessages-sv.js → formcfg-sv.js} +32 -0
  54. data/vendor/assets/javascripts/webshims/shims/json-storage.js +16 -10
  55. data/vendor/assets/javascripts/webshims/shims/mediaelement-core.js +155 -122
  56. data/vendor/assets/javascripts/webshims/shims/mediaelement-jaris.js +76 -41
  57. data/vendor/assets/javascripts/webshims/shims/mediaelement-yt.js +8 -16
  58. data/vendor/assets/javascripts/webshims/shims/range-ui.js +388 -0
  59. data/vendor/assets/javascripts/webshims/shims/styles/config.rb +12 -0
  60. data/vendor/assets/javascripts/webshims/shims/styles/forms.png +0 -0
  61. data/vendor/assets/javascripts/webshims/shims/styles/scss/shim.scss +1186 -0
  62. data/vendor/assets/javascripts/webshims/shims/styles/shim.css +868 -548
  63. data/vendor/assets/javascripts/webshims/shims/styles/vertical-range.png +0 -0
  64. data/vendor/assets/javascripts/webshims/shims/swf/JarisFLVPlayer.swf +0 -0
  65. data/vendor/assets/javascripts/webshims/shims/swfmini.js +497 -0
  66. data/vendor/assets/javascripts/webshims/shims/track-ui.js +3 -0
  67. data/vendor/assets/javascripts/webshims/shims/track.js +29 -29
  68. metadata +26 -125
  69. data/vendor/assets/javascripts/webshims/minified/extras/custom-validity.js +0 -1
  70. data/vendor/assets/javascripts/webshims/minified/extras/modernizr-custom.js +0 -1
  71. data/vendor/assets/javascripts/webshims/minified/extras/mousepress.js +0 -1
  72. data/vendor/assets/javascripts/webshims/minified/polyfiller.js +0 -1
  73. data/vendor/assets/javascripts/webshims/minified/shims/FlashCanvas/canvas2png.js +0 -1
  74. data/vendor/assets/javascripts/webshims/minified/shims/FlashCanvas/flashcanvas.js +0 -1
  75. data/vendor/assets/javascripts/webshims/minified/shims/FlashCanvas/flashcanvas.swf +0 -0
  76. data/vendor/assets/javascripts/webshims/minified/shims/FlashCanvas/proxy.php +0 -73
  77. data/vendor/assets/javascripts/webshims/minified/shims/FlashCanvas/save.php +0 -49
  78. data/vendor/assets/javascripts/webshims/minified/shims/FlashCanvasPro/canvas2png.js +0 -1
  79. data/vendor/assets/javascripts/webshims/minified/shims/FlashCanvasPro/flash10canvas.swf +0 -0
  80. data/vendor/assets/javascripts/webshims/minified/shims/FlashCanvasPro/flash9canvas.swf +0 -0
  81. data/vendor/assets/javascripts/webshims/minified/shims/FlashCanvasPro/flashcanvas.js +0 -1
  82. data/vendor/assets/javascripts/webshims/minified/shims/FlashCanvasPro/proxy.php +0 -73
  83. data/vendor/assets/javascripts/webshims/minified/shims/FlashCanvasPro/save.php +0 -49
  84. data/vendor/assets/javascripts/webshims/minified/shims/combos/1.js +0 -1
  85. data/vendor/assets/javascripts/webshims/minified/shims/combos/10.js +0 -1
  86. data/vendor/assets/javascripts/webshims/minified/shims/combos/11.js +0 -1
  87. data/vendor/assets/javascripts/webshims/minified/shims/combos/12.js +0 -1
  88. data/vendor/assets/javascripts/webshims/minified/shims/combos/13.js +0 -1
  89. data/vendor/assets/javascripts/webshims/minified/shims/combos/14.js +0 -1
  90. data/vendor/assets/javascripts/webshims/minified/shims/combos/15.js +0 -1
  91. data/vendor/assets/javascripts/webshims/minified/shims/combos/16.js +0 -1
  92. data/vendor/assets/javascripts/webshims/minified/shims/combos/17.js +0 -1
  93. data/vendor/assets/javascripts/webshims/minified/shims/combos/18.js +0 -1
  94. data/vendor/assets/javascripts/webshims/minified/shims/combos/19.js +0 -1
  95. data/vendor/assets/javascripts/webshims/minified/shims/combos/2.js +0 -1
  96. data/vendor/assets/javascripts/webshims/minified/shims/combos/20.js +0 -1
  97. data/vendor/assets/javascripts/webshims/minified/shims/combos/21.js +0 -1
  98. data/vendor/assets/javascripts/webshims/minified/shims/combos/22.js +0 -1
  99. data/vendor/assets/javascripts/webshims/minified/shims/combos/23.js +0 -1
  100. data/vendor/assets/javascripts/webshims/minified/shims/combos/24.js +0 -1
  101. data/vendor/assets/javascripts/webshims/minified/shims/combos/25.js +0 -1
  102. data/vendor/assets/javascripts/webshims/minified/shims/combos/26.js +0 -1
  103. data/vendor/assets/javascripts/webshims/minified/shims/combos/27.js +0 -1
  104. data/vendor/assets/javascripts/webshims/minified/shims/combos/3.js +0 -1
  105. data/vendor/assets/javascripts/webshims/minified/shims/combos/4.js +0 -1
  106. data/vendor/assets/javascripts/webshims/minified/shims/combos/5.js +0 -1
  107. data/vendor/assets/javascripts/webshims/minified/shims/combos/59.js +0 -1
  108. data/vendor/assets/javascripts/webshims/minified/shims/combos/6.js +0 -1
  109. data/vendor/assets/javascripts/webshims/minified/shims/combos/7.js +0 -1
  110. data/vendor/assets/javascripts/webshims/minified/shims/combos/8.js +0 -1
  111. data/vendor/assets/javascripts/webshims/minified/shims/combos/9.js +0 -1
  112. data/vendor/assets/javascripts/webshims/minified/shims/details.js +0 -1
  113. data/vendor/assets/javascripts/webshims/minified/shims/dom-extend.js +0 -1
  114. data/vendor/assets/javascripts/webshims/minified/shims/es5.js +0 -1
  115. data/vendor/assets/javascripts/webshims/minified/shims/excanvas.js +0 -1
  116. data/vendor/assets/javascripts/webshims/minified/shims/form-core.js +0 -1
  117. data/vendor/assets/javascripts/webshims/minified/shims/form-datalist.js +0 -1
  118. data/vendor/assets/javascripts/webshims/minified/shims/form-message.js +0 -1
  119. data/vendor/assets/javascripts/webshims/minified/shims/form-native-extend.js +0 -1
  120. data/vendor/assets/javascripts/webshims/minified/shims/form-number-date-api.js +0 -1
  121. data/vendor/assets/javascripts/webshims/minified/shims/form-number-date-ui.js +0 -1
  122. data/vendor/assets/javascripts/webshims/minified/shims/form-shim-extend.js +0 -1
  123. data/vendor/assets/javascripts/webshims/minified/shims/geolocation.js +0 -1
  124. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-ar.js +0 -1
  125. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-ch-ZN.js +0 -1
  126. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-de.txt +0 -33
  127. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-el.js +0 -1
  128. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-en.txt +0 -34
  129. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-es.js +0 -1
  130. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-fr.js +0 -1
  131. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-he.js +0 -1
  132. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-hi.js +0 -1
  133. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-hu.js +0 -1
  134. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-it.js +0 -1
  135. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-ja.js +0 -1
  136. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-nl.js +0 -1
  137. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-pt-PT.js +0 -1
  138. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-ru.js +0 -1
  139. data/vendor/assets/javascripts/webshims/minified/shims/i18n/errormessages-sv.js +0 -1
  140. data/vendor/assets/javascripts/webshims/minified/shims/json-storage.js +0 -1
  141. data/vendor/assets/javascripts/webshims/minified/shims/jwplayer/license.txt +0 -1
  142. data/vendor/assets/javascripts/webshims/minified/shims/jwplayer/player.swf +0 -0
  143. data/vendor/assets/javascripts/webshims/minified/shims/jwplayer/readme.html +0 -87
  144. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-core.js +0 -1
  145. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-jaris.js +0 -1
  146. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-native-fix.js +0 -1
  147. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-swf.js +0 -1
  148. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-yt.js +0 -1
  149. data/vendor/assets/javascripts/webshims/minified/shims/styles/details-arrows.png +0 -0
  150. data/vendor/assets/javascripts/webshims/minified/shims/styles/forms.png +0 -0
  151. data/vendor/assets/javascripts/webshims/minified/shims/styles/polyfill-loader.gif +0 -0
  152. data/vendor/assets/javascripts/webshims/minified/shims/styles/shim.css +0 -1
  153. data/vendor/assets/javascripts/webshims/minified/shims/swf/JarisFLVPlayer.swf +0 -0
  154. data/vendor/assets/javascripts/webshims/minified/shims/swf/jwwebshims.swf +0 -0
  155. data/vendor/assets/javascripts/webshims/minified/shims/swf/localStorage.swf +0 -0
  156. data/vendor/assets/javascripts/webshims/minified/shims/track-ui.js +0 -1
  157. data/vendor/assets/javascripts/webshims/minified/shims/track.js +0 -1
  158. data/vendor/assets/javascripts/webshims/shims/FlashCanvas/README +0 -62
  159. data/vendor/assets/javascripts/webshims/shims/FlashCanvasPro/README +0 -82
  160. data/vendor/assets/javascripts/webshims/shims/combos/24.js +0 -2872
  161. data/vendor/assets/javascripts/webshims/shims/combos/25.js +0 -2376
  162. data/vendor/assets/javascripts/webshims/shims/combos/26.js +0 -3009
  163. data/vendor/assets/javascripts/webshims/shims/combos/27.js +0 -4150
  164. data/vendor/assets/javascripts/webshims/shims/combos/59.js +0 -1747
  165. data/vendor/assets/javascripts/webshims/shims/jwplayer/license.txt +0 -1
  166. data/vendor/assets/javascripts/webshims/shims/jwplayer/player.swf +0 -0
  167. data/vendor/assets/javascripts/webshims/shims/jwplayer/readme.html +0 -87
  168. data/vendor/assets/javascripts/webshims/shims/mediaelement-swf.js +0 -972
@@ -1,2206 +1,1784 @@
1
- //additional tests for partial implementation of forms features
2
- (function($){
1
+ //DOM-Extension helper
2
+ jQuery.webshims.register('dom-extend', function($, webshims, window, document, undefined){
3
3
  "use strict";
4
- var isWebkit = /webkit/i.test(navigator.userAgent);
5
- var Modernizr = window.Modernizr;
6
- var webshims = $.webshims;
7
- var bugs = webshims.bugs;
8
- var form = $('<form action="#" style="width: 1px; height: 1px; overflow: hidden;"><select name="b" required="" /><input required="" name="a" /></form>');
9
- var testRequiredFind = function(){
10
- if(form[0].querySelector){
11
- try {
12
- bugs.findRequired = !(form[0].querySelector('select:required'));
13
- } catch(er){
14
- bugs.findRequired = false;
15
- }
16
- }
17
- };
18
- var inputElem = $('input', form).eq(0);
19
- var onDomextend = function(fn){
20
- webshims.loader.loadList(['dom-extend']);
21
- webshims.ready('dom-extend', fn);
22
- };
23
4
 
24
- bugs.findRequired = false;
25
- bugs.validationMessage = false;
26
-
27
- webshims.capturingEventPrevented = function(e){
28
- if(!e._isPolyfilled){
29
- var isDefaultPrevented = e.isDefaultPrevented;
30
- var preventDefault = e.preventDefault;
31
- e.preventDefault = function(){
32
- clearTimeout($.data(e.target, e.type + 'DefaultPrevented'));
33
- $.data(e.target, e.type + 'DefaultPrevented', setTimeout(function(){
34
- $.removeData(e.target, e.type + 'DefaultPrevented');
35
- }, 30));
36
- return preventDefault.apply(this, arguments);
37
- };
38
- e.isDefaultPrevented = function(){
39
- return !!(isDefaultPrevented.apply(this, arguments) || $.data(e.target, e.type + 'DefaultPrevented') || false);
40
- };
41
- e._isPolyfilled = true;
42
- }
43
- };
5
+ webshims.assumeARIA = Modernizr.localstorage || Modernizr.video || Modernizr.boxsizing;
44
6
 
45
- if(!Modernizr.formvalidation || bugs.bustedValidity){
46
- testRequiredFind();
47
- } else {
48
- //create delegatable events
49
- webshims.capturingEvents(['input']);
50
- webshims.capturingEvents(['invalid'], true);
51
-
52
- if(window.opera || window.testGoodWithFix){
53
-
54
- form.appendTo('head');
55
-
56
- testRequiredFind();
57
- bugs.validationMessage = !(inputElem.prop('validationMessage'));
58
-
59
- webshims.reTest(['form-native-extend', 'form-message']);
60
-
61
- form.remove();
62
-
63
- $(function(){
64
- onDomextend(function(){
65
-
66
- //Opera shows native validation bubbles in case of input.checkValidity()
67
- // Opera 11.6/12 hasn't fixed this issue right, it's buggy
68
- var preventDefault = function(e){
69
- e.preventDefault();
70
- };
71
-
72
- ['form', 'input', 'textarea', 'select'].forEach(function(name){
73
- var desc = webshims.defineNodeNameProperty(name, 'checkValidity', {
74
- prop: {
75
- value: function(){
76
- if (!webshims.fromSubmit) {
77
- $(this).on('invalid.checkvalidity', preventDefault);
78
- }
79
-
80
- webshims.fromCheckValidity = true;
81
- var ret = desc.prop._supvalue.apply(this, arguments);
82
- if (!webshims.fromSubmit) {
83
- $(this).unbind('invalid.checkvalidity', preventDefault);
84
- }
85
- webshims.fromCheckValidity = false;
86
- return ret;
87
- }
88
- }
89
- });
90
- });
91
-
92
- });
93
- });
94
- }
95
-
96
- if(isWebkit && !webshims.bugs.bustedValidity){
97
- (function(){
98
- var elems = /^(?:textarea|input)$/i;
99
- var form = false;
100
-
101
- document.addEventListener('contextmenu', function(e){
102
- if(elems.test( e.target.nodeName || '') && (form = e.target.form)){
103
- setTimeout(function(){
104
- form = false;
105
- }, 1);
106
- }
107
- }, false);
108
-
109
- $(window).on('invalid', function(e){
110
- if(e.originalEvent && form && form == e.target.form){
111
- e.wrongWebkitInvalid = true;
112
- e.stopImmediatePropagation();
113
- }
114
- });
115
-
116
- })();
117
- }
7
+ if($('<input type="email" />').attr('type') == 'text' || $('<form />').attr('novalidate') === "" || ('required' in $('<input />')[0].attributes)){
8
+ webshims.error("IE browser modes are busted in IE10. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools");
118
9
  }
119
10
 
11
+ if(!$.parseHTML){
12
+ webshims.error("Webshims needs jQuery 1.8+ to work properly. Please update your jQuery version or downgrade webshims.");
13
+ }
120
14
 
121
-
122
- jQuery.webshims.register('form-core', function($, webshims, window, document, undefined, options){
123
- "use strict";
124
-
125
-
126
- var checkTypes = {checkbox: 1, radio: 1};
127
- var emptyJ = $([]);
128
- var bugs = webshims.bugs;
129
- var groupTypes = {radio: 1};
130
- var getGroupElements = function(elem){
131
- elem = $(elem);
132
- var name;
133
- var form;
134
- var ret = emptyJ;
135
- if(groupTypes[elem[0].type]){
136
- form = elem.prop('form');
137
- name = elem[0].name;
138
- if(!name){
139
- ret = elem;
140
- } else if(form){
141
- ret = $(form[name]);
142
- } else {
143
- ret = $(document.getElementsByName(name)).filter(function(){
144
- return !$.prop(this, 'form');
145
- });
146
- }
147
- ret = ret.filter('[type="radio"]');
148
- }
149
- return ret;
15
+ //shortcus
16
+ var modules = webshims.modules;
17
+ var listReg = /\s*,\s*/;
18
+
19
+ //proxying attribute
20
+ var olds = {};
21
+ var havePolyfill = {};
22
+ var extendedProps = {};
23
+ var extendQ = {};
24
+ var modifyProps = {};
25
+
26
+ var oldVal = $.fn.val;
27
+ var singleVal = function(elem, name, val, pass, _argless){
28
+ return (_argless) ? oldVal.call($(elem)) : oldVal.call($(elem), val);
150
29
  };
151
30
 
152
- var getContentValidationMessage = webshims.getContentValidationMessage = function(elem, validity, key){
153
- var message = $(elem).data('errormessage') || elem.getAttribute('x-moz-errormessage') || '';
154
- if(key && message[key]){
155
- message = message[key];
31
+
32
+ $.fn.val = function(val){
33
+ var elem = this[0];
34
+ if(arguments.length && val == null){
35
+ val = '';
156
36
  }
157
- if(typeof message == 'object'){
158
- validity = validity || $.prop(elem, 'validity') || {valid: 1};
159
- if(!validity.valid){
160
- $.each(validity, function(name, prop){
161
- if(prop && name != 'valid' && message[name]){
162
- message = message[name];
163
- return false;
164
- }
165
- });
166
- }
37
+ if(!arguments.length){
38
+ if(!elem || elem.nodeType !== 1){return oldVal.call(this);}
39
+ return $.prop(elem, 'value', val, 'val', true);
167
40
  }
168
-
169
- if(typeof message == 'object'){
170
- message = message.defaultMessage;
41
+ if($.isArray(val)){
42
+ return oldVal.apply(this, arguments);
171
43
  }
172
- return message || '';
173
- };
174
-
175
- /*
176
- * Selectors for all browsers
177
- */
178
- var rangeTypes = {number: 1, range: 1, date: 1/*, time: 1, 'datetime-local': 1, datetime: 1, month: 1, week: 1*/};
179
- var hasInvalid = function(elem){
180
- var ret = false;
181
- $($.prop(elem, 'elements')).each(function(){
182
- ret = $(this).is(':invalid');
183
- if(ret){
184
- return false;
44
+ var isFunction = $.isFunction(val);
45
+ return this.each(function(i){
46
+ elem = this;
47
+ if(elem.nodeType === 1){
48
+ if(isFunction){
49
+ var genVal = val.call( elem, i, $.prop(elem, 'value', undefined, 'val', true));
50
+ if(genVal == null){
51
+ genVal = '';
52
+ }
53
+ $.prop(elem, 'value', genVal, 'val') ;
54
+ } else {
55
+ $.prop(elem, 'value', val, 'val');
56
+ }
185
57
  }
186
58
  });
187
- return ret;
188
59
  };
189
- $.extend($.expr[":"], {
190
- "valid-element": function(elem){
191
- return $.nodeName(elem, 'form') ? !hasInvalid(elem) :!!($.prop(elem, 'willValidate') && isValid(elem));
192
- },
193
- "invalid-element": function(elem){
194
- return $.nodeName(elem, 'form') ? hasInvalid(elem) : !!($.prop(elem, 'willValidate') && !isValid(elem));
195
- },
196
- "required-element": function(elem){
197
- return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required'));
198
- },
199
- "user-error": function(elem){
200
- return ($.prop(elem, 'willValidate') && $(elem).hasClass('user-error'));
201
- },
202
- "optional-element": function(elem){
203
- return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required') === false);
204
- },
205
- "in-range": function(elem){
206
- if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
207
- return false;
60
+ $.fn.onTrigger = function(evt, fn){
61
+ return this.on(evt, fn).each(fn);
62
+ };
63
+
64
+ var dataID = '_webshimsLib'+ (Math.round(Math.random() * 1000));
65
+ var elementData = function(elem, key, val){
66
+ elem = elem.jquery ? elem[0] : elem;
67
+ if(!elem){return val || {};}
68
+ var data = $.data(elem, dataID);
69
+ if(val !== undefined){
70
+ if(!data){
71
+ data = $.data(elem, dataID, {});
208
72
  }
209
- var val = $.prop(elem, 'validity');
210
- return !!(val && !val.rangeOverflow && !val.rangeUnderflow);
211
- },
212
- "out-of-range": function(elem){
213
- if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
214
- return false;
73
+ if(key){
74
+ data[key] = val;
215
75
  }
216
- var val = $.prop(elem, 'validity');
217
- return !!(val && (val.rangeOverflow || val.rangeUnderflow));
218
76
  }
219
77
 
220
- });
221
-
222
- ['valid', 'invalid', 'required', 'optional'].forEach(function(name){
223
- $.expr[":"][name] = $.expr.filters[name+"-element"];
224
- });
225
-
226
-
227
- $.expr[":"].focus = function( elem ) {
228
- try {
229
- var doc = elem.ownerDocument;
230
- return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus());
231
- } catch(e){}
232
- return false;
78
+ return key ? data && data[key] : data;
233
79
  };
80
+
81
+
82
+ [{name: 'getNativeElement', prop: 'nativeElement'}, {name: 'getShadowElement', prop: 'shadowElement'}, {name: 'getShadowFocusElement', prop: 'shadowFocusElement'}].forEach(function(data){
83
+ $.fn[data.name] = function(){
84
+ var elems = [];
85
+ this.each(function(){
86
+ var shadowData = elementData(this, 'shadowData');
87
+ var elem = shadowData && shadowData[data.prop] || this;
88
+ if($.inArray(elem, elems) == -1){
89
+ elems.push(elem);
90
+ }
91
+ });
92
+ return this.pushStack(elems);
93
+ };
94
+ });
234
95
 
235
- if(Modernizr.formvalidation && isWebkit && !webshims.bugs.bustedValidity){
96
+ if($.Tween.propHooks._default && $.css){
236
97
  (function(){
237
- var retriggerRadioValidity = function(){
238
- var validity;
239
- if((validity = this.validity) && !validity.customError){
240
- this.setCustomValidity('');
98
+ var isjQ8 = false;
99
+ try {
100
+ isjQ8 = $.css($('<b style="width: 10px" />')[0], 'width', '') == '10px';
101
+ } catch(er){
102
+ webshims.error(er);
103
+ }
104
+ var css = isjQ8 ?
105
+ function(elem, prop){
106
+ return $.css( elem, prop, false, "" );
107
+ } :
108
+ function(elem, prop){
109
+ return $.css( elem, prop, "" );
241
110
  }
242
- };
243
-
244
- webshims.addReady(function(context, insertedElement){
245
- if(context !== document){
246
- $('input[type="radio"]:invalid', context)
247
- .add(insertedElement.filter('input[type="radio"]:invalid'))
248
- .each(retriggerRadioValidity)
249
- ;
111
+ ;
112
+
113
+ $.extend($.Tween.propHooks._default, {
114
+ get: function( tween ) {
115
+ var result;
116
+
117
+ if ( (tween.elem[ tween.prop ] != null || havePolyfill[ tween.prop ]) &&
118
+ (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
119
+ return havePolyfill[ tween.prop ] ? $.prop(tween.elem, tween.prop) : tween.elem[ tween.prop ];
120
+ }
121
+
122
+ // passing an empty string as a 3rd parameter to .css will automatically
123
+ // attempt a parseFloat and fallback to a string if the parse fails
124
+ // so, simple values such as "10px" are parsed to Float.
125
+ // complex values such as "rotate(1rad)" are returned as is.
126
+ result = css( tween.elem, tween.prop );
127
+ // Empty strings, null, undefined and "auto" are converted to 0.
128
+ return !result || result === "auto" ? 0 : result;
129
+ },
130
+ set: function( tween ) {
131
+ // use step hook for back compat - use cssHook if its there - use .style if its
132
+ // available and use plain properties where available
133
+ if ( jQuery.fx.step[ tween.prop ] ) {
134
+ jQuery.fx.step[ tween.prop ]( tween );
135
+ } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
136
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
137
+ } else if( !havePolyfill[ tween.prop ] ) {
138
+ tween.elem[ tween.prop ] = tween.now;
139
+ } else {
140
+ $.prop(tween.elem, tween.prop, tween.now);
141
+ }
250
142
  }
251
143
  });
252
144
  })();
253
145
  }
254
146
 
255
- var customEvents = $.event.customEvent || {};
256
- var isValid = function(elem){
257
- return ($.prop(elem, 'validity') || {valid: 1}).valid;
258
- };
259
147
 
260
- if (bugs.bustedValidity || bugs.findRequired) {
261
- (function(){
262
- var find = $.find;
263
- var matchesSelector = $.find.matchesSelector;
148
+ ['removeAttr', 'prop', 'attr'].forEach(function(type){
149
+ olds[type] = $[type];
150
+ $[type] = function(elem, name, value, pass, _argless){
151
+ var isVal = (pass == 'val');
152
+ var oldMethod = !isVal ? olds[type] : singleVal;
153
+ if( !elem || !havePolyfill[name] || elem.nodeType !== 1 || (!isVal && pass && type == 'attr' && $.attrFn[name]) ){
154
+ return oldMethod(elem, name, value, pass, _argless);
155
+ }
264
156
 
265
- var regExp = /(\:valid|\:invalid|\:optional|\:required|\:in-range|\:out-of-range)(?=[\s\[\~\.\+\>\:\#*]|$)/ig;
266
- var regFn = function(sel){
267
- return sel + '-element';
268
- };
157
+ var nodeName = (elem.nodeName || '').toLowerCase();
158
+ var desc = extendedProps[nodeName];
159
+ var curType = (type == 'attr' && (value === false || value === null)) ? 'removeAttr' : type;
160
+ var propMethod;
161
+ var oldValMethod;
162
+ var ret;
269
163
 
270
- $.find = (function(){
271
- var slice = Array.prototype.slice;
272
- var fn = function(sel){
273
- var ar = arguments;
274
- ar = slice.call(ar, 1, ar.length);
275
- ar.unshift(sel.replace(regExp, regFn));
276
- return find.apply(this, ar);
277
- };
278
- for (var i in find) {
279
- if(find.hasOwnProperty(i)){
280
- fn[i] = find[i];
281
- }
282
- }
283
- return fn;
284
- })();
285
- if(!Modernizr.prefixed || Modernizr.prefixed("matchesSelector", document.documentElement)){
286
- $.find.matchesSelector = function(node, expr){
287
- expr = expr.replace(regExp, regFn);
288
- return matchesSelector.call(this, node, expr);
289
- };
290
- }
291
164
 
292
- })();
293
- }
294
-
295
- //ToDo needs testing
296
- var oldAttr = $.prop;
297
- var changeVals = {selectedIndex: 1, value: 1, checked: 1, disabled: 1, readonly: 1};
298
- $.prop = function(elem, name, val){
299
- var ret = oldAttr.apply(this, arguments);
300
- if(elem && 'form' in elem && changeVals[name] && val !== undefined && $(elem).hasClass(invalidClass)){
301
- if(isValid(elem)){
302
- $(elem).getShadowElement().removeClass(invalidClasses);
303
- if(name == 'checked' && val) {
304
- getGroupElements(elem).not(elem).removeClass(invalidClasses).removeAttr('aria-invalid');
305
- }
165
+ if(!desc){
166
+ desc = extendedProps['*'];
306
167
  }
307
- }
308
- return ret;
309
- };
310
-
311
- var returnValidityCause = function(validity, elem){
312
- var ret;
313
- $.each(validity, function(name, value){
314
- if(value){
315
- ret = (name == 'customError') ? $.prop(elem, 'validationMessage') : name;
316
- return false;
168
+ if(desc){
169
+ desc = desc[name];
170
+ }
171
+
172
+ if(desc){
173
+ propMethod = desc[curType];
317
174
  }
318
- });
319
- return ret;
320
- };
321
-
322
- var isInGroup = function(name){
323
- var ret;
324
- try {
325
- ret = document.activeElement.name === name;
326
- } catch(e){}
327
- return ret;
328
- };
329
- /* form-ui-invalid/form-ui-valid are deprecated. use user-error/user-success instead */
330
- var invalidClass = 'user-error';
331
- var invalidClasses = 'user-error form-ui-invalid';
332
- var validClass = 'user-success';
333
- var validClasses = 'user-success form-ui-valid';
334
- var switchValidityClass = function(e){
335
- var elem, timer;
336
- if(!e.target){return;}
337
- elem = $(e.target).getNativeElement()[0];
338
- if(elem.type == 'submit' || !$.prop(elem, 'willValidate')){return;}
339
- timer = $.data(elem, 'webshimsswitchvalidityclass');
340
- var switchClass = function(){
341
- if(e.type == 'focusout' && elem.type == 'radio' && isInGroup(elem.name)){return;}
342
- var validity = $.prop(elem, 'validity');
343
- var shadowElem = $(elem).getShadowElement();
344
- var addClass, removeClass, trigger, generaltrigger, validityCause;
345
175
 
346
- $(elem).trigger('refreshCustomValidityRules');
347
- if(validity.valid){
348
- if(!shadowElem.hasClass(validClass)){
349
- addClass = validClasses;
350
- removeClass = invalidClasses;
351
- generaltrigger = 'changedvaliditystate';
352
- trigger = 'changedvalid';
353
- if(checkTypes[elem.type] && elem.checked){
354
- getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass).removeAttr('aria-invalid');
176
+ if(propMethod){
177
+ if(name == 'value'){
178
+ oldValMethod = propMethod.isVal;
179
+ propMethod.isVal = isVal;
180
+ }
181
+ if(curType === 'removeAttr'){
182
+ return propMethod.value.call(elem);
183
+ } else if(value === undefined){
184
+ return (propMethod.get) ?
185
+ propMethod.get.call(elem) :
186
+ propMethod.value
187
+ ;
188
+ } else if(propMethod.set) {
189
+ if(type == 'attr' && value === true){
190
+ value = name;
355
191
  }
356
- $.removeData(elem, 'webshimsinvalidcause');
192
+
193
+ ret = propMethod.set.call(elem, value);
194
+ }
195
+ if(name == 'value'){
196
+ propMethod.isVal = oldValMethod;
357
197
  }
358
198
  } else {
359
- validityCause = returnValidityCause(validity, elem);
360
- if($.data(elem, 'webshimsinvalidcause') != validityCause){
361
- $.data(elem, 'webshimsinvalidcause', validityCause);
362
- generaltrigger = 'changedvaliditystate';
199
+ ret = oldMethod(elem, name, value, pass, _argless);
200
+ }
201
+ if((value !== undefined || curType === 'removeAttr') && modifyProps[nodeName] && modifyProps[nodeName][name]){
202
+
203
+ var boolValue;
204
+ if(curType == 'removeAttr'){
205
+ boolValue = false;
206
+ } else if(curType == 'prop'){
207
+ boolValue = !!(value);
208
+ } else {
209
+ boolValue = true;
363
210
  }
364
- if(!shadowElem.hasClass(invalidClass)){
365
- addClass = invalidClasses;
366
- removeClass = validClasses;
367
- if (checkTypes[elem.type] && !elem.checked) {
368
- getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass);
211
+
212
+ modifyProps[nodeName][name].forEach(function(fn){
213
+ if(!fn.only || (fn.only = 'prop' && type == 'prop') || (fn.only == 'attr' && type != 'prop')){
214
+ fn.call(elem, value, boolValue, (isVal) ? 'val' : curType, type);
369
215
  }
370
- trigger = 'changedinvalid';
371
- }
372
- }
373
- if(addClass){
374
- shadowElem.addClass(addClass).removeClass(removeClass);
375
- //jQuery 1.6.1 IE9 bug (doubble trigger bug)
376
- setTimeout(function(){
377
- $(elem).trigger(trigger);
378
- }, 0);
379
- }
380
- if(generaltrigger){
381
- setTimeout(function(){
382
- $(elem).trigger(generaltrigger);
383
- }, 0);
216
+ });
384
217
  }
385
- $.removeData(e.target, 'webshimsswitchvalidityclass');
218
+ return ret;
386
219
  };
387
220
 
388
- if(timer){
389
- clearTimeout(timer);
390
- }
391
- if(e.type == 'refreshvalidityui'){
392
- switchClass();
393
- } else {
394
- $.data(elem, 'webshimsswitchvalidityclass', setTimeout(switchClass, 9));
395
- }
396
- };
397
-
398
- $(document).on(options.validityUIEvents || 'focusout change refreshvalidityui', switchValidityClass);
399
- customEvents.changedvaliditystate = true;
400
- customEvents.refreshCustomValidityRules = true;
401
- customEvents.changedvalid = true;
402
- customEvents.changedinvalid = true;
403
- customEvents.refreshvalidityui = true;
404
-
405
-
406
- webshims.triggerInlineForm = function(elem, event){
407
- $(elem).trigger(event);
408
- };
409
-
410
- webshims.modules["form-core"].getGroupElements = getGroupElements;
411
-
412
-
413
- var setRoot = function(){
414
- webshims.scrollRoot = (isWebkit || document.compatMode == 'BackCompat') ?
415
- $(document.body) :
416
- $(document.documentElement)
417
- ;
418
- };
419
- setRoot();
420
- webshims.ready('DOM', setRoot);
421
-
422
- webshims.getRelOffset = function(posElem, relElem){
423
- posElem = $(posElem);
424
- var offset = $(relElem).offset();
425
- var bodyOffset;
426
- $.swap($(posElem)[0], {visibility: 'hidden', display: 'inline-block', left: 0, top: 0}, function(){
427
- bodyOffset = posElem.offset();
428
- });
429
- offset.top -= bodyOffset.top;
430
- offset.left -= bodyOffset.left;
431
- return offset;
432
- };
433
-
434
- /* some extra validation UI */
435
- webshims.validityAlert = (function(){
436
- var alertElem = 'span';
437
- var errorBubble;
438
- var hideTimer = false;
439
- var focusTimer = false;
440
- var resizeTimer = false;
441
- var boundHide;
442
-
443
- var api = {
444
- hideDelay: 5000,
221
+ extendQ[type] = function(nodeName, prop, desc){
445
222
 
446
- showFor: function(elem, message, noFocusElem, noBubble){
447
- api._create();
448
- elem = $(elem);
449
- var visual = $(elem).getShadowElement();
450
- var offset = api.getOffsetFromBody(visual);
451
- api.clear();
452
- if(noBubble){
453
- this.hide();
454
- } else {
455
-
456
- this.getMessage(elem, message);
457
- this.position(visual, offset);
458
-
459
- this.show();
460
- if(this.hideDelay){
461
- hideTimer = setTimeout(boundHide, this.hideDelay);
462
- }
463
- $(window)
464
- .on('resize.validityalert reposoverlay.validityalert', function(){
465
- clearTimeout(resizeTimer);
466
- resizeTimer = setTimeout(function(){
467
- api.position(visual);
468
- }, 9);
469
- })
470
- ;
223
+ if(!extendedProps[nodeName]){
224
+ extendedProps[nodeName] = {};
225
+ }
226
+ if(!extendedProps[nodeName][prop]){
227
+ extendedProps[nodeName][prop] = {};
228
+ }
229
+ var oldDesc = extendedProps[nodeName][prop][type];
230
+ var getSup = function(propType, descriptor, oDesc){
231
+ if(descriptor && descriptor[propType]){
232
+ return descriptor[propType];
471
233
  }
472
-
473
- if(!noFocusElem){
474
- this.setFocus(visual, offset);
234
+ if(oDesc && oDesc[propType]){
235
+ return oDesc[propType];
475
236
  }
476
- },
477
- getOffsetFromBody: function(elem){
478
- return webshims.getRelOffset(errorBubble, elem);
479
- },
480
- setFocus: function(visual, offset){
481
- var focusElem = $(visual).getShadowFocusElement();
482
- var scrollTop = webshims.scrollRoot.scrollTop();
483
- var elemTop = ((offset || focusElem.offset()).top) - 30;
484
- var smooth;
485
-
486
- if(webshims.getID && alertElem == 'label'){
487
- errorBubble.attr('for', webshims.getID(focusElem));
237
+ if(type == 'prop' && prop == 'value'){
238
+ return function(value){
239
+ var elem = this;
240
+ return (desc.isVal) ?
241
+ singleVal(elem, prop, value, false, (arguments.length === 0)) :
242
+ olds[type](elem, prop, value)
243
+ ;
244
+ };
488
245
  }
489
-
490
- if(scrollTop > elemTop){
491
- webshims.scrollRoot.animate(
492
- {scrollTop: elemTop - 5},
493
- {
494
- queue: false,
495
- duration: Math.max( Math.min( 600, (scrollTop - elemTop) * 1.5 ), 80 )
496
- }
497
- );
498
- smooth = true;
246
+ if(type == 'prop' && propType == 'value' && desc.value.apply){
247
+ return function(value){
248
+ var sup = olds[type](this, prop);
249
+ if(sup && sup.apply){
250
+ sup = sup.apply(this, arguments);
251
+ }
252
+ return sup;
253
+ };
499
254
  }
500
- try {
501
- focusElem[0].focus();
502
- } catch(e){}
503
- if(smooth){
504
- webshims.scrollRoot.scrollTop(scrollTop);
505
- setTimeout(function(){
506
- webshims.scrollRoot.scrollTop(scrollTop);
507
- }, 0);
255
+ return function(value){
256
+ return olds[type](this, prop, value);
257
+ };
258
+ };
259
+ extendedProps[nodeName][prop][type] = desc;
260
+ if(desc.value === undefined){
261
+ if(!desc.set){
262
+ desc.set = desc.writeable ?
263
+ getSup('set', desc, oldDesc) :
264
+ (webshims.cfg.useStrict && prop == 'prop') ?
265
+ function(){throw(prop +' is readonly on '+ nodeName);} :
266
+ function(){webshims.info(prop +' is readonly on '+ nodeName);}
267
+ ;
508
268
  }
509
- setTimeout(function(){
510
- $(document).on('focusout.validityalert', boundHide);
511
- }, 10);
512
- $(window).triggerHandler('reposoverlay');
513
- },
514
- getMessage: function(elem, message){
515
- if (!message) {
516
- message = getContentValidationMessage(elem[0]) || elem.prop('customValidationMessage') || elem.prop('validationMessage');
269
+ if(!desc.get){
270
+ desc.get = getSup('get', desc, oldDesc);
517
271
  }
518
- if (message) {
519
- $('span.va-box', errorBubble).text(message);
272
+
273
+ }
274
+
275
+ ['value', 'get', 'set'].forEach(function(descProp){
276
+ if(desc[descProp]){
277
+ desc['_sup'+descProp] = getSup(descProp, oldDesc);
520
278
  }
521
- else {
522
- this.hide();
523
- }
524
- },
525
- position: function(elem, offset){
526
- offset = offset ? $.extend({}, offset) : api.getOffsetFromBody(elem);
527
- offset.top += elem.outerHeight();
528
- errorBubble.css(offset);
529
- },
530
- show: function(){
531
- if(errorBubble.css('display') === 'none'){
532
- errorBubble.css({opacity: 0}).show();
533
- }
534
- errorBubble.addClass('va-visible').fadeTo(400, 1);
535
- },
536
- hide: function(){
537
- errorBubble.removeClass('va-visible').fadeOut();
538
- },
539
- clear: function(){
540
- clearTimeout(focusTimer);
541
- clearTimeout(hideTimer);
542
- $(document).unbind('.validityalert');
543
- $(window).unbind('.validityalert');
544
- errorBubble.stop().removeAttr('for');
545
- },
546
- _create: function(){
547
- if(errorBubble){return;}
548
- 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'});
549
- webshims.ready('DOM', function(){
550
- errorBubble.appendTo('body');
551
- if($.fn.bgIframe){
552
- errorBubble.bgIframe();
553
- }
554
- });
555
- }
279
+ });
556
280
  };
557
281
 
558
-
559
- boundHide = $.proxy(api, 'hide');
560
-
561
- return api;
562
- })();
563
-
564
-
565
- /* extension, but also used to fix native implementation workaround/bugfixes */
566
- (function(){
567
- var firstEvent,
568
- invalids = [],
569
- stopSubmitTimer,
570
- form
571
- ;
572
-
573
- $(document).on('invalid', function(e){
574
- if(e.wrongWebkitInvalid){return;}
575
- var jElm = $(e.target);
576
- var shadowElem = jElm.getShadowElement();
577
- if(!shadowElem.hasClass(invalidClass)){
578
- shadowElem.addClass(invalidClasses).removeClass(validClasses);
579
- setTimeout(function(){
580
- $(e.target).trigger('changedinvalid').trigger('changedvaliditystate');
581
- }, 0);
582
- }
583
-
584
- if(!firstEvent){
585
- //trigger firstinvalid
586
- firstEvent = $.Event('firstinvalid');
587
- firstEvent.isInvalidUIPrevented = e.isDefaultPrevented;
588
- var firstSystemInvalid = $.Event('firstinvalidsystem');
589
- $(document).triggerHandler(firstSystemInvalid, {element: e.target, form: e.target.form, isInvalidUIPrevented: e.isDefaultPrevented});
590
- jElm.trigger(firstEvent);
591
- }
592
-
593
- //if firstinvalid was prevented all invalids will be also prevented
594
- if( firstEvent && firstEvent.isDefaultPrevented() ){
595
- e.preventDefault();
596
- }
597
- invalids.push(e.target);
598
- e.extraData = 'fix';
599
- clearTimeout(stopSubmitTimer);
600
- stopSubmitTimer = setTimeout(function(){
601
- var lastEvent = {type: 'lastinvalid', cancelable: false, invalidlist: $(invalids)};
602
- //reset firstinvalid
603
- firstEvent = false;
604
- invalids = [];
605
- $(e.target).trigger(lastEvent, lastEvent);
606
- }, 9);
607
- jElm = null;
608
- shadowElem = null;
609
- });
610
- })();
611
-
612
- $.fn.getErrorMessage = function(){
613
- var message = '';
614
- var elem = this[0];
615
- if(elem){
616
- message = getContentValidationMessage(elem) || $.prop(elem, 'customValidationMessage') || $.prop(elem, 'validationMessage');
617
- }
618
- return message;
619
- };
620
-
621
- if(options.replaceValidationUI){
622
- webshims.ready('DOM forms', function(){
623
- $(document).on('firstinvalid', function(e){
624
- if(!e.isInvalidUIPrevented()){
625
- e.preventDefault();
626
- $.webshims.validityAlert.showFor( e.target );
627
- }
628
- });
629
- });
630
- }
631
- });
632
-
633
- })(jQuery);
634
- if(!Modernizr.formvalidation || jQuery.webshims.bugs.bustedValidity){
635
- jQuery.webshims.register('form-shim-extend', function($, webshims, window, document){
636
- "use strict";
637
- webshims.inputTypes = webshims.inputTypes || {};
638
- //some helper-functions
639
- var cfg = webshims.cfg.forms;
640
- var isSubmit;
641
-
642
- var isNumber = function(string){
643
- return (typeof string == 'number' || (string && string == string * 1));
644
- },
645
- typeModels = webshims.inputTypes,
646
- checkTypes = {
647
- radio: 1,
648
- checkbox: 1
649
- },
650
- getType = function(elem){
651
- return (elem.getAttribute('type') || elem.type || '').toLowerCase();
652
- }
653
- ;
654
-
655
- //API to add new input types
656
- webshims.addInputType = function(type, obj){
657
- typeModels[type] = obj;
658
- };
659
-
660
- //contsrain-validation-api
661
- var validityPrototype = {
662
- customError: false,
663
-
664
- typeMismatch: false,
665
- rangeUnderflow: false,
666
- rangeOverflow: false,
667
- stepMismatch: false,
668
- tooLong: false,
669
- patternMismatch: false,
670
- valueMissing: false,
282
+ });
671
283
 
672
- valid: true
673
- };
674
-
675
- var isPlaceholderOptionSelected = function(select){
676
- if(select.type == 'select-one' && select.size < 2){
677
- var option = $('> option:first-child', select);
678
- return !!option.prop('selected');
679
- }
680
- return false;
681
- };
682
-
683
- var validityRules = {
684
- valueMissing: function(input, val, cache){
685
- if(!input.prop('required')){return false;}
686
- var ret = false;
687
- if(!('type' in cache)){
688
- cache.type = getType(input[0]);
689
- }
690
- if(cache.nodeName == 'select'){
691
- ret = (!val && (input[0].selectedIndex < 0 || isPlaceholderOptionSelected(input[0]) ));
692
- } else if(checkTypes[cache.type]){
693
- ret = (cache.type == 'checkbox') ? !input.is(':checked') : !webshims.modules["form-core"].getGroupElements(input).filter(':checked')[0];
284
+ var extendNativeValue = (function(){
285
+ var UNKNOWN = webshims.getPrototypeOf(document.createElement('foobar'));
286
+ var has = Object.prototype.hasOwnProperty;
287
+ //see also: https://github.com/lojjic/PIE/issues/40 | https://prototype.lighthouseapp.com/projects/8886/tickets/1107-ie8-fatal-crash-when-prototypejs-is-loaded-with-rounded-cornershtc
288
+ var isExtendNativeSave = Modernizr.advancedObjectProperties && Modernizr.objectAccessor;
289
+ return function(nodeName, prop, desc){
290
+ var elem , elemProto;
291
+ if( isExtendNativeSave && (elem = document.createElement(nodeName)) && (elemProto = webshims.getPrototypeOf(elem)) && UNKNOWN !== elemProto && ( !elem[prop] || !has.call(elem, prop) ) ){
292
+ var sup = elem[prop];
293
+ desc._supvalue = function(){
294
+ if(sup && sup.apply){
295
+ return sup.apply(this, arguments);
296
+ }
297
+ return sup;
298
+ };
299
+ elemProto[prop] = desc.value;
694
300
  } else {
695
- ret = !(val);
696
- }
697
- return ret;
698
- },
699
- tooLong: function(){
700
- return false;
701
- },
702
- typeMismatch: function (input, val, cache){
703
- if(val === '' || cache.nodeName == 'select'){return false;}
704
- var ret = false;
705
- if(!('type' in cache)){
706
- cache.type = getType(input[0]);
707
- }
708
-
709
- if(typeModels[cache.type] && typeModels[cache.type].mismatch){
710
- ret = typeModels[cache.type].mismatch(val, input);
711
- } else if('validity' in input[0]){
712
- ret = input[0].validity.typeMismatch;
713
- }
714
- return ret;
715
- },
716
- patternMismatch: function(input, val, cache) {
717
- if(val === '' || cache.nodeName == 'select'){return false;}
718
- var pattern = input.attr('pattern');
719
- if(!pattern){return false;}
720
- try {
721
- pattern = new RegExp('^(?:' + pattern + ')$');
722
- } catch(er){
723
- webshims.error('invalid pattern value: "'+ pattern +'" | '+ er);
724
- pattern = false;
301
+ desc._supvalue = function(){
302
+ var data = elementData(this, 'propValue');
303
+ if(data && data[prop] && data[prop].apply){
304
+ return data[prop].apply(this, arguments);
305
+ }
306
+ return data && data[prop];
307
+ };
308
+ initProp.extendValue(nodeName, prop, desc.value);
725
309
  }
726
- if(!pattern){return false;}
727
- return !(pattern.test(val));
728
- }
729
- }
730
- ;
731
-
732
- webshims.addValidityRule = function(type, fn){
733
- validityRules[type] = fn;
734
- };
735
-
736
- $.event.special.invalid = {
737
- add: function(){
738
- $.event.special.invalid.setup.call(this.form || this);
739
- },
740
- setup: function(){
741
- var form = this.form || this;
742
- if( $.data(form, 'invalidEventShim') ){
743
- form = null;
744
- return;
745
- }
746
- $(form)
747
- .data('invalidEventShim', true)
748
- .on('submit', $.event.special.invalid.handler)
749
- ;
750
- webshims.moveToFirstEvent(form, 'submit');
751
- if(webshims.bugs.bustedValidity && $.nodeName(form, 'form')){
752
- (function(){
753
- var noValidate = form.getAttribute('novalidate');
754
- form.setAttribute('novalidate', 'novalidate');
755
- webshims.data(form, 'bustedNoValidate', (noValidate == null) ? null : noValidate);
756
- })();
757
- }
758
- form = null;
759
- },
760
- teardown: $.noop,
761
- handler: function(e, d){
310
+ desc.value._supvalue = desc._supvalue;
311
+ };
312
+ })();
762
313
 
763
- if( e.type != 'submit' || e.testedValidity || !e.originalEvent || !$.nodeName(e.target, 'form') || $.prop(e.target, 'noValidate') ){return;}
314
+ var initProp = (function(){
764
315
 
765
- isSubmit = true;
766
- e.testedValidity = true;
767
- var notValid = !($(e.target).checkValidity());
768
- if(notValid){
769
- e.stopImmediatePropagation();
770
- isSubmit = false;
771
- return false;
772
- }
773
- isSubmit = false;
774
- }
775
- };
776
-
777
- var addSubmitBubbles = function(form){
778
- if (!$.support.submitBubbles && form && typeof form == 'object' && !form._submit_attached ) {
779
-
780
- $.event.add( form, 'submit._submit', function( event ) {
781
- event._submit_bubble = true;
782
- });
316
+ var initProps = {};
783
317
 
784
- form._submit_attached = true;
785
- }
786
- };
787
- if(!$.support.submitBubbles && $.event.special.submit){
788
- $.event.special.submit.setup = function() {
789
- // Only need this for delegated form submit events
790
- if ( $.nodeName( this, "form" ) ) {
791
- return false;
792
- }
793
-
794
- // Lazy-add a submit handler when a descendant form may potentially be submitted
795
- $.event.add( this, "click._submit keypress._submit", function( e ) {
796
- // Node name check avoids a VML-related crash in IE (#9807)
797
- var elem = e.target,
798
- form = $.nodeName( elem, 'input' ) || $.nodeName( elem, 'button' ) ? $.prop(elem, 'form') : undefined;
799
- addSubmitBubbles(form);
800
-
801
- });
802
- // return undefined since we don't need an event listener
803
- };
804
- }
805
-
806
- $.event.special.submit = $.event.special.submit || {setup: function(){return false;}};
807
- var submitSetup = $.event.special.submit.setup;
808
- $.extend($.event.special.submit, {
809
- setup: function(){
810
- if($.nodeName(this, 'form')){
811
- $(this).on('invalid', $.noop);
812
- } else {
813
- $('form', this).on('invalid', $.noop);
814
- }
815
- return submitSetup.apply(this, arguments);
816
- }
817
- });
818
-
819
- $(window).on('invalid', $.noop);
820
-
821
-
822
- webshims.addInputType('email', {
823
- mismatch: (function(){
824
- //taken from http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address
825
- var test = cfg.emailReg || /^[a-zA-Z0-9.!#$%&'*+-\/=?\^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
826
- return function(val){
827
- return !test.test(val);
828
- };
829
- })()
830
- });
831
-
832
- webshims.addInputType('url', {
833
- mismatch: (function(){
834
- //taken from scott gonzales
835
- var test = cfg.urlReg || /^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i;
836
- return function(val){
837
- return !test.test(val);
838
- };
839
- })()
840
- });
841
-
842
- webshims.defineNodeNameProperty('input', 'type', {
843
- prop: {
844
- get: function(){
845
- var elem = this;
846
- var type = (elem.getAttribute('type') || '').toLowerCase();
847
- return (webshims.inputTypes[type]) ? type : elem.type;
848
- }
849
- }
850
- });
851
-
852
- // IDLs for constrain validation API
853
- //ToDo: add object to this list
854
- webshims.defineNodeNamesProperties(['button', 'fieldset', 'output'], {
855
- checkValidity: {
856
- value: function(){return true;}
857
- },
858
- willValidate: {
859
- value: false
860
- },
861
- setCustomValidity: {
862
- value: $.noop
863
- },
864
- validity: {
865
- writeable: false,
866
- get: function(){
867
- return $.extend({}, validityPrototype);
868
- }
869
- }
870
- }, 'prop');
871
-
872
- var baseCheckValidity = function(elem){
873
- var e,
874
- v = $.prop(elem, 'validity')
875
- ;
876
- if(v){
877
- $.data(elem, 'cachedValidity', v);
878
- } else {
879
- return true;
880
- }
881
- if( !v.valid ){
882
- e = $.Event('invalid');
883
- var jElm = $(elem).trigger(e);
884
- if(isSubmit && !baseCheckValidity.unhandledInvalids && !e.isDefaultPrevented()){
885
- webshims.validityAlert.showFor(jElm);
886
- baseCheckValidity.unhandledInvalids = true;
887
- }
888
- }
889
- $.removeData(elem, 'cachedValidity');
890
- return v.valid;
891
- };
892
- var rsubmittable = /^(?:select|textarea|input)/i;
893
- webshims.defineNodeNameProperty('form', 'checkValidity', {
894
- prop: {
895
- value: function(){
896
-
897
- var ret = true,
898
- elems = $($.prop(this, 'elements')).filter(function(){
899
- if(!rsubmittable.test(this.nodeName)){return false;}
900
- var shadowData = webshims.data(this, 'shadowData');
901
- return !shadowData || !shadowData.nativeElement || shadowData.nativeElement === this;
902
- })
903
- ;
904
-
905
- baseCheckValidity.unhandledInvalids = false;
906
- for(var i = 0, len = elems.length; i < len; i++){
907
- if( !baseCheckValidity(elems[i]) ){
908
- ret = false;
909
- }
910
- }
911
- return ret;
912
- }
913
- }
914
- });
915
-
916
- webshims.defineNodeNamesProperties(['input', 'textarea', 'select'], {
917
- checkValidity: {
918
- value: function(){
919
- baseCheckValidity.unhandledInvalids = false;
920
- return baseCheckValidity($(this).getNativeElement()[0]);
921
- }
922
- },
923
- setCustomValidity: {
924
- value: function(error){
925
- $.removeData(this, 'cachedValidity');
926
- webshims.data(this, 'customvalidationMessage', ''+error);
927
- }
928
- },
929
- willValidate: {
930
- writeable: false,
931
- get: (function(){
932
- var types = {
933
- button: 1,
934
- reset: 1,
935
- hidden: 1,
936
- image: 1
318
+ webshims.addReady(function(context, contextElem){
319
+ var nodeNameCache = {};
320
+ var getElementsByName = function(name){
321
+ if(!nodeNameCache[name]){
322
+ nodeNameCache[name] = $(context.getElementsByTagName(name));
323
+ if(contextElem[0] && $.nodeName(contextElem[0], name)){
324
+ nodeNameCache[name] = nodeNameCache[name].add(contextElem);
325
+ }
937
326
  }
938
- ;
939
- return function(){
940
- var elem = $(this).getNativeElement()[0];
941
- //elem.name && <- we don't use to make it easier for developers
942
- return !!(!elem.disabled && !elem.readOnly && !types[elem.type] );
943
327
  };
944
- })()
945
- },
946
- validity: {
947
- writeable: false,
948
- get: function(){
949
- var jElm = $(this).getNativeElement();
950
- var elem = jElm[0];
951
- var validityState = $.data(elem, 'cachedValidity');
952
- if(validityState){
953
- return validityState;
954
- }
955
- validityState = $.extend({}, validityPrototype);
956
328
 
957
- if( !$.prop(elem, 'willValidate') || elem.type == 'submit' ){
958
- return validityState;
959
- }
960
- var val = jElm.val(),
961
- cache = {nodeName: elem.nodeName.toLowerCase()}
962
- ;
963
329
 
964
- validityState.customError = !!(webshims.data(elem, 'customvalidationMessage'));
965
- if( validityState.customError ){
966
- validityState.valid = false;
967
- }
968
-
969
- $.each(validityRules, function(rule, fn){
970
- if (fn(jElm, val, cache)) {
971
- validityState[rule] = true;
972
- validityState.valid = false;
330
+ $.each(initProps, function(name, fns){
331
+ getElementsByName(name);
332
+ if(!fns || !fns.forEach){
333
+ webshims.warn('Error: with '+ name +'-property. methods: '+ fns);
334
+ return;
973
335
  }
336
+ fns.forEach(function(fn){
337
+ nodeNameCache[name].each(fn);
338
+ });
974
339
  });
975
- $(this).getShadowFocusElement().attr('aria-invalid', validityState.valid ? 'false' : 'true');
976
- jElm = null;
977
- elem = null;
978
- return validityState;
979
- }
980
- }
981
- }, 'prop');
982
-
983
- webshims.defineNodeNamesBooleanProperty(['input', 'textarea', 'select'], 'required', {
984
- set: function(value){
985
- $(this).getShadowFocusElement().attr('aria-required', !!(value)+'');
986
- },
987
- initAttr: (Modernizr.localstorage)//only if we have aria-support
988
- });
989
-
990
- webshims.reflectProperties(['input'], ['pattern']);
991
-
992
-
993
- if( !('maxLength' in document.createElement('textarea')) ){
994
- var constrainMaxLength = (function(){
995
- var timer;
996
- var curLength = 0;
997
- var lastElement = $([]);
998
- var max = 1e9;
999
- var constrainLength = function(){
1000
- var nowValue = lastElement.prop('value');
1001
- var nowLen = nowValue.length;
1002
- if(nowLen > curLength && nowLen > max){
1003
- nowLen = Math.max(curLength, max);
1004
- lastElement.prop('value', nowValue.substr(0, nowLen ));
340
+ nodeNameCache = null;
341
+ });
342
+
343
+ var tempCache;
344
+ var emptyQ = $([]);
345
+ var createNodeNameInit = function(nodeName, fn){
346
+ if(!initProps[nodeName]){
347
+ initProps[nodeName] = [fn];
348
+ } else {
349
+ initProps[nodeName].push(fn);
350
+ }
351
+ if($.isDOMReady){
352
+ (tempCache || $( document.getElementsByTagName(nodeName) )).each(fn);
1005
353
  }
1006
- curLength = nowLen;
1007
- };
1008
- var remove = function(){
1009
- clearTimeout(timer);
1010
- lastElement.unbind('.maxlengthconstraint');
1011
354
  };
1012
- return function(element, maxLength){
1013
- remove();
1014
- if(maxLength > -1){
1015
- max = maxLength;
1016
- curLength = $.prop(element, 'value').length;
1017
- lastElement = $(element);
1018
- lastElement.on({
1019
- 'keydown.maxlengthconstraint keypress.maxlengthconstraint paste.maxlengthconstraint cut.maxlengthconstraint': function(e){
1020
- setTimeout(constrainLength, 0);
1021
- },
1022
- 'keyup.maxlengthconstraint': constrainLength,
1023
- 'blur.maxlengthconstraint': remove
355
+
356
+ var elementExtends = {};
357
+ return {
358
+ createTmpCache: function(nodeName){
359
+ if($.isDOMReady){
360
+ tempCache = tempCache || $( document.getElementsByTagName(nodeName) );
361
+ }
362
+ return tempCache || emptyQ;
363
+ },
364
+ flushTmpCache: function(){
365
+ tempCache = null;
366
+ },
367
+ content: function(nodeName, prop){
368
+ createNodeNameInit(nodeName, function(){
369
+ var val = $.attr(this, prop);
370
+ if(val != null){
371
+ $.attr(this, prop, val);
372
+ }
373
+ });
374
+ },
375
+ createElement: function(nodeName, fn){
376
+ createNodeNameInit(nodeName, fn);
377
+ },
378
+ extendValue: function(nodeName, prop, value){
379
+ createNodeNameInit(nodeName, function(){
380
+ $(this).each(function(){
381
+ var data = elementData(this, 'propValue', {});
382
+ data[prop] = this[prop];
383
+ this[prop] = value;
384
+ });
1024
385
  });
1025
- timer = setInterval(constrainLength, 200);
1026
386
  }
1027
387
  };
1028
388
  })();
1029
-
1030
- constrainMaxLength.update = function(element, maxLength){
1031
- if($(element).is(':focus')){
1032
- if(!maxLength){
1033
- maxLength = $.prop(element, 'maxlength');
1034
- }
1035
- constrainMaxLength(element, maxLength);
389
+
390
+ var createPropDefault = function(descs, removeType){
391
+ if(descs.defaultValue === undefined){
392
+ descs.defaultValue = '';
1036
393
  }
1037
- };
1038
-
1039
- $(document).on('focusin', function(e){
1040
- var maxLength;
1041
- if(e.target.nodeName == "TEXTAREA" && (maxLength = $.prop(e.target, 'maxlength')) > -1){
1042
- constrainMaxLength(e.target, maxLength);
394
+ if(!descs.removeAttr){
395
+ descs.removeAttr = {
396
+ value: function(){
397
+ descs[removeType || 'prop'].set.call(this, descs.defaultValue);
398
+ descs.removeAttr._supvalue.call(this);
399
+ }
400
+ };
1043
401
  }
1044
- });
402
+ if(!descs.attr){
403
+ descs.attr = {};
404
+ }
405
+ };
1045
406
 
1046
- webshims.defineNodeNameProperty('textarea', 'maxlength', {
1047
- attr: {
1048
- set: function(val){
1049
- this.setAttribute('maxlength', ''+val);
1050
- constrainMaxLength.update(this);
1051
- },
1052
- get: function(){
1053
- var ret = this.getAttribute('maxlength');
1054
- return ret == null ? undefined : ret;
407
+ $.extend(webshims, {
408
+
409
+ getID: (function(){
410
+ var ID = new Date().getTime();
411
+ return function(elem){
412
+ elem = $(elem);
413
+ var id = elem.prop('id');
414
+ if(!id){
415
+ ID++;
416
+ id = 'ID-'+ ID;
417
+ elem.eq(0).prop('id', id);
418
+ }
419
+ return id;
420
+ };
421
+ })(),
422
+ implement: function(elem, type){
423
+ var data = elementData(elem, 'implemented') || elementData(elem, 'implemented', {});
424
+ if(data[type]){
425
+ webshims.info(type +' already implemented for element #'+elem.id);
426
+ return false;
1055
427
  }
428
+ data[type] = true;
429
+ return true;
1056
430
  },
1057
- prop: {
1058
- set: function(val){
1059
- if(isNumber(val)){
1060
- if(val < 0){
1061
- throw('INDEX_SIZE_ERR');
1062
- }
1063
- val = parseInt(val, 10);
1064
- this.setAttribute('maxlength', val);
1065
- constrainMaxLength.update(this, val);
1066
- return;
431
+ extendUNDEFProp: function(obj, props){
432
+ $.each(props, function(name, prop){
433
+ if( !(name in obj) ){
434
+ obj[name] = prop;
435
+ }
436
+ });
437
+ },
438
+ //http://www.w3.org/TR/html5/common-dom-interfaces.html#reflect
439
+ createPropDefault: createPropDefault,
440
+ data: elementData,
441
+ moveToFirstEvent: function(elem, eventType, bindType){
442
+ var events = ($._data(elem, 'events') || {})[eventType];
443
+ var fn;
444
+
445
+ if(events && events.length > 1){
446
+ fn = events.pop();
447
+ if(!bindType){
448
+ bindType = 'bind';
449
+ }
450
+ if(bindType == 'bind' && events.delegateCount){
451
+ events.splice( events.delegateCount, 0, fn);
452
+ } else {
453
+ events.unshift( fn );
1067
454
  }
1068
- this.setAttribute('maxlength', '0');
1069
- constrainMaxLength.update(this, 0);
1070
- },
1071
- get: function(){
1072
- var val = this.getAttribute('maxlength');
1073
- return (isNumber(val) && val >= 0) ? parseInt(val, 10) : -1;
455
+
1074
456
 
1075
457
  }
1076
- }
1077
- });
1078
- webshims.defineNodeNameProperty('textarea', 'maxLength', {
1079
- prop: {
1080
- set: function(val){
1081
- $.prop(this, 'maxlength', val);
1082
- },
1083
- get: function(){
1084
- return $.prop(this, 'maxlength');
1085
- }
1086
- }
1087
- });
1088
- }
1089
-
1090
-
1091
-
1092
- var submitterTypes = {submit: 1, button: 1, image: 1};
1093
- var formSubmitterDescriptors = {};
1094
- [
1095
- {
1096
- name: "enctype",
1097
- limitedTo: {
1098
- "application/x-www-form-urlencoded": 1,
1099
- "multipart/form-data": 1,
1100
- "text/plain": 1
1101
- },
1102
- defaultProp: "application/x-www-form-urlencoded",
1103
- proptype: "enum"
1104
- },
1105
- {
1106
- name: "method",
1107
- limitedTo: {
1108
- "get": 1,
1109
- "post": 1
458
+ elem = null;
1110
459
  },
1111
- defaultProp: "get",
1112
- proptype: "enum"
1113
- },
1114
- {
1115
- name: "action",
1116
- proptype: "url"
1117
- },
1118
- {
1119
- name: "target"
1120
- },
1121
- {
1122
- name: "novalidate",
1123
- propName: "noValidate",
1124
- proptype: "boolean"
1125
- }
1126
- ].forEach(function(desc){
1127
- var propName = 'form'+ (desc.propName || desc.name).replace(/^[a-z]/, function(f){
1128
- return f.toUpperCase();
1129
- });
1130
- var attrName = 'form'+ desc.name;
1131
- var formName = desc.name;
1132
- var eventName = 'click.webshimssubmittermutate'+formName;
1133
-
1134
- var changeSubmitter = function(){
1135
- var elem = this;
1136
- if( !('form' in elem) || !submitterTypes[elem.type] ){return;}
1137
- var form = $.prop(elem, 'form');
1138
- if(!form){return;}
1139
- var attr = $.attr(elem, attrName);
1140
- if(attr != null && ( !desc.limitedTo || attr.toLowerCase() === $.prop(elem, propName))){
460
+ addShadowDom: (function(){
461
+ var resizeTimer;
462
+ var lastHeight;
463
+ var lastWidth;
1141
464
 
1142
- var oldAttr = $.attr(form, formName);
465
+ var docObserve = {
466
+ init: false,
467
+ runs: 0,
468
+ test: function(){
469
+ var height = docObserve.getHeight();
470
+ var width = docObserve.getWidth();
471
+
472
+ if(height != docObserve.height || width != docObserve.width){
473
+ docObserve.height = height;
474
+ docObserve.width = width;
475
+ docObserve.handler({type: 'docresize'});
476
+ docObserve.runs++;
477
+ if(docObserve.runs < 9){
478
+ setTimeout(docObserve.test, 90);
479
+ }
480
+ } else {
481
+ docObserve.runs = 0;
482
+ }
483
+ },
484
+ handler: function(e){
485
+ clearTimeout(resizeTimer);
486
+ resizeTimer = setTimeout(function(){
487
+ if(e.type == 'resize'){
488
+ var width = $(window).width();
489
+ var height = $(window).width();
490
+ if(height == lastHeight && width == lastWidth){
491
+ return;
492
+ }
493
+ lastHeight = height;
494
+ lastWidth = width;
495
+
496
+ docObserve.height = docObserve.getHeight();
497
+ docObserve.width = docObserve.getWidth();
498
+
499
+ }
500
+ $(document).triggerHandler('updateshadowdom');
501
+ }, (e.type == 'resize') ? 50 : 9);
502
+ },
503
+ _create: function(){
504
+ $.each({ Height: "getHeight", Width: "getWidth" }, function(name, type){
505
+ var body = document.body;
506
+ var doc = document.documentElement;
507
+ docObserve[type] = function(){
508
+ return Math.max(
509
+ body[ "scroll" + name ], doc[ "scroll" + name ],
510
+ body[ "offset" + name ], doc[ "offset" + name ],
511
+ doc[ "client" + name ]
512
+ );
513
+ };
514
+ });
515
+ },
516
+ start: function(){
517
+ if(!this.init && document.body){
518
+ this.init = true;
519
+ this._create();
520
+ this.height = docObserve.getHeight();
521
+ this.width = docObserve.getWidth();
522
+ setInterval(this.test, 600);
523
+ $(this.test);
524
+ webshims.ready('WINDOWLOAD', this.test);
525
+ $(window).bind('resize', this.handler);
526
+ (function(){
527
+ var oldAnimate = $.fn.animate;
528
+ var animationTimer;
529
+
530
+ $.fn.animate = function(){
531
+ clearTimeout(animationTimer);
532
+ animationTimer = setTimeout(function(){
533
+ docObserve.test();
534
+ }, 99);
535
+
536
+ return oldAnimate.apply(this, arguments);
537
+ };
538
+ })();
539
+ }
540
+ }
541
+ };
1143
542
 
1144
- $.attr(form, formName, attr);
1145
- setTimeout(function(){
1146
- if(oldAttr != null){
1147
- $.attr(form, formName, oldAttr);
1148
- } else {
1149
- try {
1150
- $(form).removeAttr(formName);
1151
- } catch(er){
1152
- form.removeAttribute(formName);
543
+
544
+ webshims.docObserve = function(){
545
+ webshims.ready('DOM', function(){
546
+ docObserve.start();
547
+ });
548
+ };
549
+ return function(nativeElem, shadowElem, opts){
550
+ opts = opts || {};
551
+ if(nativeElem.jquery){
552
+ nativeElem = nativeElem[0];
553
+ }
554
+ if(shadowElem.jquery){
555
+ shadowElem = shadowElem[0];
556
+ }
557
+ var nativeData = $.data(nativeElem, dataID) || $.data(nativeElem, dataID, {});
558
+ var shadowData = $.data(shadowElem, dataID) || $.data(shadowElem, dataID, {});
559
+ var shadowFocusElementData = {};
560
+ if(!opts.shadowFocusElement){
561
+ opts.shadowFocusElement = shadowElem;
562
+ } else if(opts.shadowFocusElement){
563
+ if(opts.shadowFocusElement.jquery){
564
+ opts.shadowFocusElement = opts.shadowFocusElement[0];
1153
565
  }
566
+ shadowFocusElementData = $.data(opts.shadowFocusElement, dataID) || $.data(opts.shadowFocusElement, dataID, shadowFocusElementData);
1154
567
  }
1155
- }, 9);
1156
- }
1157
- };
1158
-
1159
-
1160
-
1161
- switch(desc.proptype) {
1162
- case "url":
1163
- var urlForm = document.createElement('form');
1164
- formSubmitterDescriptors[propName] = {
1165
- prop: {
1166
- set: function(value){
1167
- $.attr(this, attrName, value);
568
+
569
+ nativeData.hasShadow = shadowElem;
570
+ shadowFocusElementData.nativeElement = shadowData.nativeElement = nativeElem;
571
+ shadowFocusElementData.shadowData = shadowData.shadowData = nativeData.shadowData = {
572
+ nativeElement: nativeElem,
573
+ shadowElement: shadowElem,
574
+ shadowFocusElement: opts.shadowFocusElement
575
+ };
576
+ if(opts.shadowChilds){
577
+ opts.shadowChilds.each(function(){
578
+ elementData(this, 'shadowData', shadowData.shadowData);
579
+ });
580
+ }
581
+
582
+ if(opts.data){
583
+ shadowFocusElementData.shadowData.data = shadowData.shadowData.data = nativeData.shadowData.data = opts.data;
584
+ }
585
+ opts = null;
586
+ webshims.docObserve();
587
+ };
588
+ })(),
589
+ propTypes: {
590
+ standard: function(descs, name){
591
+ createPropDefault(descs);
592
+ if(descs.prop){return;}
593
+ descs.prop = {
594
+ set: function(val){
595
+ descs.attr.set.call(this, ''+val);
1168
596
  },
1169
597
  get: function(){
1170
- var value = $.attr(this, attrName);
1171
- if(value == null){return '';}
1172
- urlForm.setAttribute('action', value);
1173
- return urlForm.action;
598
+ return descs.attr.get.call(this) || descs.defaultValue;
1174
599
  }
1175
- }
1176
- };
1177
- break;
1178
- case "boolean":
1179
- formSubmitterDescriptors[propName] = {
1180
- prop: {
600
+ };
601
+
602
+ },
603
+ "boolean": function(descs, name){
604
+
605
+ createPropDefault(descs);
606
+ if(descs.prop){return;}
607
+ descs.prop = {
1181
608
  set: function(val){
1182
- val = !!val;
1183
609
  if(val){
1184
- $.attr(this, 'formnovalidate', 'formnovalidate');
610
+ descs.attr.set.call(this, "");
1185
611
  } else {
1186
- $(this).removeAttr('formnovalidate');
612
+ descs.removeAttr.value.call(this);
1187
613
  }
1188
614
  },
1189
615
  get: function(){
1190
- return $.attr(this, 'formnovalidate') != null;
1191
- }
1192
- }
1193
- };
1194
- break;
1195
- case "enum":
1196
- formSubmitterDescriptors[propName] = {
1197
- prop: {
1198
- set: function(value){
1199
- $.attr(this, attrName, value);
1200
- },
1201
- get: function(){
1202
- var value = $.attr(this, attrName);
1203
- return (!value || ( (value = value.toLowerCase()) && !desc.limitedTo[value] )) ? desc.defaultProp : value;
1204
- }
1205
- }
1206
- };
1207
- break;
1208
- default:
1209
- formSubmitterDescriptors[propName] = {
1210
- prop: {
1211
- set: function(value){
1212
- $.attr(this, attrName, value);
1213
- },
1214
- get: function(){
1215
- var value = $.attr(this, attrName);
1216
- return (value != null) ? value : "";
616
+ return descs.attr.get.call(this) != null;
1217
617
  }
618
+ };
619
+ },
620
+ "src": (function(){
621
+ var anchor = document.createElement('a');
622
+ anchor.style.display = "none";
623
+ return function(descs, name){
624
+
625
+ createPropDefault(descs);
626
+ if(descs.prop){return;}
627
+ descs.prop = {
628
+ set: function(val){
629
+ descs.attr.set.call(this, val);
630
+ },
631
+ get: function(){
632
+ var href = this.getAttribute(name);
633
+ var ret;
634
+ if(href == null){return '';}
635
+
636
+ anchor.setAttribute('href', href+'' );
637
+
638
+ if(!$.support.hrefNormalized){
639
+ try {
640
+ $(anchor).insertAfter(this);
641
+ ret = anchor.getAttribute('href', 4);
642
+ } catch(er){
643
+ ret = anchor.getAttribute('href', 4);
644
+ }
645
+ $(anchor).detach();
646
+ }
647
+ return ret || anchor.href;
648
+ }
649
+ };
650
+ };
651
+ })(),
652
+ enumarated: function(descs, name){
653
+
654
+ createPropDefault(descs);
655
+ if(descs.prop){return;}
656
+ descs.prop = {
657
+ set: function(val){
658
+ descs.attr.set.call(this, val);
659
+ },
660
+ get: function(){
661
+ var val = (descs.attr.get.call(this) || '').toLowerCase();
662
+ if(!val || descs.limitedTo.indexOf(val) == -1){
663
+ val = descs.defaultValue;
664
+ }
665
+ return val;
666
+ }
667
+ };
1218
668
  }
1219
- };
1220
- }
1221
-
1222
-
1223
- if(!formSubmitterDescriptors[attrName]){
1224
- formSubmitterDescriptors[attrName] = {};
1225
- }
1226
- formSubmitterDescriptors[attrName].attr = {
1227
- set: function(value){
1228
- formSubmitterDescriptors[attrName].attr._supset.call(this, value);
1229
- $(this).unbind(eventName).on(eventName, changeSubmitter);
669
+
670
+ // ,unsignedLong: $.noop
671
+ // ,"doubble": $.noop
672
+ // ,"long": $.noop
673
+ // ,tokenlist: $.noop
674
+ // ,settableTokenlist: $.noop
1230
675
  },
1231
- get: function(){
1232
- return formSubmitterDescriptors[attrName].attr._supget.call(this);
1233
- }
1234
- };
1235
- formSubmitterDescriptors[attrName].initAttr = true;
1236
- formSubmitterDescriptors[attrName].removeAttr = {
1237
- value: function(){
1238
- $(this).unbind(eventName);
1239
- formSubmitterDescriptors[attrName].removeAttr._supvalue.call(this);
1240
- }
1241
- };
1242
- });
1243
-
1244
- webshims.defineNodeNamesProperties(['input', 'button'], formSubmitterDescriptors);
1245
-
1246
-
1247
- if(!$.support.getSetAttribute && $('<form novalidate></form>').attr('novalidate') == null){
1248
- webshims.defineNodeNameProperty('form', 'novalidate', {
1249
- attr: {
1250
- set: function(val){
1251
- this.setAttribute('novalidate', ''+val);
1252
- },
1253
- get: function(){
1254
- var ret = this.getAttribute('novalidate');
1255
- return ret == null ? undefined : ret;
1256
- }
1257
- }
1258
- });
1259
- } else if(webshims.bugs.bustedValidity){
1260
-
1261
- webshims.defineNodeNameProperty('form', 'novalidate', {
1262
- attr: {
1263
- set: function(val){
1264
- webshims.data(this, 'bustedNoValidate', ''+val);
1265
- },
1266
- get: function(){
1267
- var ret = webshims.data(this, 'bustedNoValidate');
1268
- return ret == null ? undefined : ret;
676
+ reflectProperties: function(nodeNames, props){
677
+ if(typeof props == 'string'){
678
+ props = props.split(listReg);
1269
679
  }
680
+ props.forEach(function(prop){
681
+ webshims.defineNodeNamesProperty(nodeNames, prop, {
682
+ prop: {
683
+ set: function(val){
684
+ $.attr(this, prop, val);
685
+ },
686
+ get: function(){
687
+ return $.attr(this, prop) || '';
688
+ }
689
+ }
690
+ });
691
+ });
1270
692
  },
1271
- removeAttr: {
1272
- value: function(){
1273
- webshims.data(this, 'bustedNoValidate', null);
693
+ defineNodeNameProperty: function(nodeName, prop, descs){
694
+ havePolyfill[prop] = true;
695
+
696
+ if(descs.reflect){
697
+ webshims.propTypes[descs.propType || 'standard'](descs, prop);
1274
698
  }
1275
- }
1276
- });
1277
-
1278
- $.each(['rangeUnderflow', 'rangeOverflow', 'stepMismatch'], function(i, name){
1279
- validityRules[name] = function(elem){
1280
- return (elem[0].validity || {})[name] || false;
1281
- };
1282
- });
1283
-
1284
- }
1285
-
1286
- webshims.defineNodeNameProperty('form', 'noValidate', {
1287
- prop: {
1288
- set: function(val){
1289
- val = !!val;
1290
- if(val){
1291
- $.attr(this, 'novalidate', 'novalidate');
1292
- } else {
1293
- $(this).removeAttr('novalidate');
699
+
700
+ ['prop', 'attr', 'removeAttr'].forEach(function(type){
701
+ var desc = descs[type];
702
+ if(desc){
703
+ if(type === 'prop'){
704
+ desc = $.extend({writeable: true}, desc);
705
+ } else {
706
+ desc = $.extend({}, desc, {writeable: true});
707
+ }
708
+
709
+ extendQ[type](nodeName, prop, desc);
710
+ if(nodeName != '*' && webshims.cfg.extendNative && type == 'prop' && desc.value && $.isFunction(desc.value)){
711
+ extendNativeValue(nodeName, prop, desc);
712
+ }
713
+ descs[type] = desc;
714
+ }
715
+ });
716
+ if(descs.initAttr){
717
+ initProp.content(nodeName, prop);
1294
718
  }
719
+ return descs;
1295
720
  },
1296
- get: function(){
1297
- return $.attr(this, 'novalidate') != null;
1298
- }
1299
- }
1300
- });
1301
-
1302
- if(Modernizr.inputtypes.date && /webkit/i.test(navigator.userAgent)){
1303
- (function(){
1304
721
 
1305
- var noInputTriggerEvts = {updateInput: 1, input: 1},
1306
- fixInputTypes = {
1307
- date: 1,
1308
- time: 1
1309
- },
1310
- noFocusEvents = {
1311
- focusout: 1,
1312
- blur: 1
1313
- },
1314
- changeEvts = {
1315
- updateInput: 1,
1316
- change: 1
1317
- },
1318
- observe = function(input){
1319
- var timer,
1320
- focusedin = true,
1321
- lastInputVal = input.prop('value'),
1322
- lastChangeVal = lastInputVal,
1323
- trigger = function(e){
1324
- //input === null
1325
- if(!input){return;}
1326
- var newVal = input.prop('value');
1327
-
1328
- if(newVal !== lastInputVal){
1329
- lastInputVal = newVal;
1330
- if(!e || !noInputTriggerEvts[e.type]){
1331
- input.trigger('input');
1332
- }
1333
- }
1334
- if(e && changeEvts[e.type]){
1335
- lastChangeVal = newVal;
1336
- }
1337
- if(!focusedin && newVal !== lastChangeVal){
1338
- input.trigger('change');
1339
- }
1340
- },
1341
- extraTimer,
1342
- extraTest = function(){
1343
- clearTimeout(extraTimer);
1344
- extraTimer = setTimeout(trigger, 9);
1345
- },
1346
- unbind = function(e){
1347
- clearInterval(timer);
1348
- setTimeout(function(){
1349
- if(e && noFocusEvents[e.type]){
1350
- focusedin = false;
1351
- }
1352
- if(input){
1353
- input.unbind('focusout blur', unbind).unbind('input change updateInput', trigger);
1354
- trigger();
722
+ defineNodeNameProperties: function(name, descs, propType, _noTmpCache){
723
+ var olddesc;
724
+ for(var prop in descs){
725
+ if(!_noTmpCache && descs[prop].initAttr){
726
+ initProp.createTmpCache(name);
727
+ }
728
+ if(propType){
729
+ if(descs[prop][propType]){
730
+ //webshims.log('override: '+ name +'['+prop +'] for '+ propType);
731
+ } else {
732
+ descs[prop][propType] = {};
733
+ ['value', 'set', 'get'].forEach(function(copyProp){
734
+ if(copyProp in descs[prop]){
735
+ descs[prop][propType][copyProp] = descs[prop][copyProp];
736
+ delete descs[prop][copyProp];
1355
737
  }
1356
- input = null;
1357
- }, 1);
1358
-
738
+ });
1359
739
  }
1360
- ;
1361
-
1362
- clearInterval(timer);
1363
- timer = setInterval(trigger, 160);
1364
- extraTest();
1365
- input
1366
- .off({
1367
- 'focusout blur': unbind,
1368
- 'input change updateInput': trigger
1369
- })
1370
- .on({
1371
- 'focusout blur': unbind,
1372
- 'input updateInput change': trigger
1373
- })
1374
- ;
740
+ }
741
+ descs[prop] = webshims.defineNodeNameProperty(name, prop, descs[prop]);
1375
742
  }
1376
- ;
1377
- if($.event.customEvent){
1378
- $.event.customEvent.updateInput = true;
1379
- }
743
+ if(!_noTmpCache){
744
+ initProp.flushTmpCache();
745
+ }
746
+ return descs;
747
+ },
1380
748
 
1381
- (function(){
749
+ createElement: function(nodeName, create, descs){
750
+ var ret;
751
+ if($.isFunction(create)){
752
+ create = {
753
+ after: create
754
+ };
755
+ }
756
+ initProp.createTmpCache(nodeName);
757
+ if(create.before){
758
+ initProp.createElement(nodeName, create.before);
759
+ }
760
+ if(descs){
761
+ ret = webshims.defineNodeNameProperties(nodeName, descs, false, true);
762
+ }
763
+ if(create.after){
764
+ initProp.createElement(nodeName, create.after);
765
+ }
766
+ initProp.flushTmpCache();
767
+ return ret;
768
+ },
769
+ onNodeNamesPropertyModify: function(nodeNames, props, desc, only){
770
+ if(typeof nodeNames == 'string'){
771
+ nodeNames = nodeNames.split(listReg);
772
+ }
773
+ if($.isFunction(desc)){
774
+ desc = {set: desc};
775
+ }
1382
776
 
1383
- var correctValue = function(elem){
1384
- var i = 1;
1385
- var len = 3;
1386
- var abort, val;
1387
- if(elem.type == 'date' && (isSubmit || !$(elem).is(':focus'))){
1388
- val = elem.value;
1389
- if(val && val.length < 10 && (val = val.split('-')) && val.length == len){
1390
- for(; i < len; i++){
1391
- if(val[i].length == 1){
1392
- val[i] = '0'+val[i];
1393
- } else if(val[i].length != 2){
1394
- abort = true;
1395
- break;
1396
- }
1397
- }
1398
- if(!abort){
1399
- val = val.join('-');
1400
- $.prop(elem, 'value', val);
1401
- return val;
1402
- }
1403
- }
777
+ nodeNames.forEach(function(name){
778
+ if(!modifyProps[name]){
779
+ modifyProps[name] = {};
1404
780
  }
1405
- };
1406
- var inputCheckValidityDesc, formCheckValidityDesc, inputValueDesc, inputValidityDesc;
1407
-
1408
- inputCheckValidityDesc = webshims.defineNodeNameProperty('input', 'checkValidity', {
1409
- prop: {
1410
- value: function(){
1411
- correctValue(this);
1412
- return inputCheckValidityDesc.prop._supvalue.apply(this, arguments);
1413
- }
781
+ if(typeof props == 'string'){
782
+ props = props.split(listReg);
1414
783
  }
1415
- });
1416
-
1417
- formCheckValidityDesc = webshims.defineNodeNameProperty('form', 'checkValidity', {
1418
- prop: {
1419
- value: function(){
1420
- $('input', this).each(function(){
1421
- correctValue(this);
1422
- });
1423
- return formCheckValidityDesc.prop._supvalue.apply(this, arguments);
1424
- }
784
+ if(desc.initAttr){
785
+ initProp.createTmpCache(name);
1425
786
  }
787
+ props.forEach(function(prop){
788
+ if(!modifyProps[name][prop]){
789
+ modifyProps[name][prop] = [];
790
+ havePolyfill[prop] = true;
791
+ }
792
+ if(desc.set){
793
+ if(only){
794
+ desc.set.only = only;
795
+ }
796
+ modifyProps[name][prop].push(desc.set);
797
+ }
798
+
799
+ if(desc.initAttr){
800
+ initProp.content(name, prop);
801
+ }
802
+ });
803
+ initProp.flushTmpCache();
804
+
1426
805
  });
1427
-
1428
- inputValueDesc = webshims.defineNodeNameProperty('input', 'value', {
1429
- prop: {
1430
- set: function(){
1431
- return inputValueDesc.prop._supset.apply(this, arguments);
806
+ },
807
+ defineNodeNamesBooleanProperty: function(elementNames, prop, descs){
808
+ if(!descs){
809
+ descs = {};
810
+ }
811
+ if($.isFunction(descs)){
812
+ descs.set = descs;
813
+ }
814
+ webshims.defineNodeNamesProperty(elementNames, prop, {
815
+ attr: {
816
+ set: function(val){
817
+ this.setAttribute(prop, val);
818
+ if(descs.set){
819
+ descs.set.call(this, true);
820
+ }
1432
821
  },
1433
822
  get: function(){
1434
- return correctValue(this) || inputValueDesc.prop._supget.apply(this, arguments);
823
+ var ret = this.getAttribute(prop);
824
+ return (ret == null) ? undefined : prop;
1435
825
  }
1436
- }
1437
- });
1438
-
1439
- inputValidityDesc = webshims.defineNodeNameProperty('input', 'validity', {
1440
- prop: {
1441
- writeable: false,
1442
- get: function(){
1443
- correctValue(this);
1444
- return inputValidityDesc.prop._supget.apply(this, arguments);
826
+ },
827
+ removeAttr: {
828
+ value: function(){
829
+ this.removeAttribute(prop);
830
+ if(descs.set){
831
+ descs.set.call(this, false);
832
+ }
1445
833
  }
1446
- }
1447
- });
1448
-
1449
- $(document).on('change', function(e){
1450
- correctValue(e.target);
834
+ },
835
+ reflect: true,
836
+ propType: 'boolean',
837
+ initAttr: descs.initAttr || false
1451
838
  });
839
+ },
840
+ contentAttr: function(elem, name, val){
841
+ if(!elem.nodeName){return;}
842
+ var attr;
843
+ if(val === undefined){
844
+ attr = (elem.attributes[name] || {});
845
+ val = attr.specified ? attr.value : null;
846
+ return (val == null) ? undefined : val;
847
+ }
1452
848
 
1453
- })();
1454
-
1455
- $(document)
1456
- .on('focusin', function(e){
1457
- if( e.target && fixInputTypes[e.target.type] && !e.target.readOnly && !e.target.disabled ){
1458
- observe($(e.target));
849
+ if(typeof val == 'boolean'){
850
+ if(!val){
851
+ elem.removeAttribute(name);
852
+ } else {
853
+ elem.setAttribute(name, name);
1459
854
  }
1460
- })
1461
- ;
1462
-
1463
-
1464
- })();
1465
- }
1466
-
1467
- webshims.addReady(function(context, contextElem){
1468
- //start constrain-validation
1469
- var focusElem;
1470
- $('form', context)
1471
- .add(contextElem.filter('form'))
1472
- .bind('invalid', $.noop)
1473
- ;
1474
-
1475
- try {
1476
- if(context == document && !('form' in (document.activeElement || {}))) {
1477
- focusElem = $('input[autofocus], select[autofocus], textarea[autofocus]', context).eq(0).getShadowFocusElement()[0];
1478
- if (focusElem && focusElem.offsetHeight && focusElem.offsetWidth) {
1479
- focusElem.focus();
855
+ } else {
856
+ elem.setAttribute(name, val);
1480
857
  }
1481
- }
1482
- }
1483
- catch (er) {}
1484
-
1485
- });
1486
-
1487
- if(!Modernizr.formattribute || !Modernizr.fieldsetdisabled){
1488
- (function(){
1489
- (function(prop, undefined){
1490
- $.prop = function(elem, name, value){
1491
- var ret;
1492
- if(elem && elem.nodeType == 1 && value === undefined && $.nodeName(elem, 'form') && elem.id){
1493
- ret = document.getElementsByName(name);
1494
- if(!ret || !ret.length){
1495
- ret = document.getElementById(name);
858
+ },
859
+
860
+ // set current Lang:
861
+ // - webshims.activeLang(lang:string);
862
+ // get current lang
863
+ // - webshims.activeLang();
864
+ // get current lang
865
+ // webshims.activeLang({
866
+ // register: moduleName:string,
867
+ // callback: callback:function
868
+ // });
869
+ // get/set including removeLang
870
+ // - webshims.activeLang({
871
+ // module: moduleName:string,
872
+ // callback: callback:function,
873
+ // langObj: languageObj:array/object
874
+ // });
875
+ activeLang: (function(){
876
+ var callbacks = [];
877
+ var registeredCallbacks = {};
878
+ var currentLang;
879
+ var shortLang;
880
+ var notLocal = /:\/\/|^\.*\//;
881
+ var loadRemoteLang = function(data, lang, options){
882
+ var langSrc;
883
+ if(lang && options && $.inArray(lang, options.availabeLangs || []) !== -1){
884
+ data.loading = true;
885
+ langSrc = options.langSrc;
886
+ if(!notLocal.test(langSrc)){
887
+ langSrc = webshims.cfg.basePath+langSrc;
1496
888
  }
1497
- if(ret){
1498
- ret = $(ret).filter(function(){
1499
- return $.prop(this, 'form') == elem;
1500
- }).get();
1501
- if(ret.length){
1502
- return ret.length == 1 ? ret[0] : ret;
889
+ webshims.loader.loadScript(langSrc+lang+'.js', function(){
890
+ if(data.langObj[lang]){
891
+ data.loading = false;
892
+ callLang(data, true);
893
+ } else {
894
+ $(function(){
895
+ if(data.langObj[lang]){
896
+ callLang(data, true);
897
+ }
898
+ data.loading = false;
899
+ });
1503
900
  }
1504
- }
901
+ });
902
+ return true;
1505
903
  }
1506
- return prop.apply(this, arguments);
904
+ return false;
1507
905
  };
1508
- })($.prop, undefined);
1509
- var removeAddedElements = function(form){
1510
- var elements = $.data(form, 'webshimsAddedElements');
1511
- if(elements){
1512
- elements.remove();
1513
- $.removeData(form, 'webshimsAddedElements');
1514
- }
1515
- };
1516
- var rCRLF = /\r?\n/g,
1517
- rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
1518
- rselectTextarea = /^(?:select|textarea)/i;
1519
-
1520
- if(!Modernizr.formattribute){
1521
- webshims.defineNodeNamesProperty(['input', 'textarea', 'select', 'button', 'fieldset'], 'form', {
1522
- prop: {
1523
- get: function(){
1524
- var form = webshims.contentAttr(this, 'form');
1525
- if(form){
1526
- form = document.getElementById(form);
1527
- if(form && !$.nodeName(form, 'form')){
1528
- form = null;
1529
- }
1530
- }
1531
- return form || this.form;
1532
- },
1533
- writeable: false
906
+ var callRegister = function(module){
907
+ if(registeredCallbacks[module]){
908
+ registeredCallbacks[module].forEach(function(data){
909
+ data.callback(currentLang, shortLang, '');
910
+ });
1534
911
  }
1535
- });
1536
-
1537
-
1538
- webshims.defineNodeNamesProperty(['form'], 'elements', {
1539
- prop: {
1540
- get: function(){
1541
- var id = this.id;
1542
- var elements = $.makeArray(this.elements);
1543
- if(id){
1544
- elements = $(elements).add('input[form="'+ id +'"], select[form="'+ id +'"], textarea[form="'+ id +'"], button[form="'+ id +'"], fieldset[form="'+ id +'"]').not('.webshims-visual-hide > *').get();
1545
- }
1546
- return elements;
1547
- },
1548
- writeable: false
912
+ };
913
+ var callLang = function(data, _noLoop){
914
+ if(data.activeLang != currentLang && data.activeLang !== shortLang){
915
+ var options = modules[data.module].options;
916
+ if( data.langObj[currentLang] || (shortLang && data.langObj[shortLang]) ){
917
+ data.activeLang = currentLang;
918
+ data.callback(data.langObj[currentLang] || data.langObj[shortLang], currentLang);
919
+ callRegister(data.module);
920
+ } else if( !_noLoop &&
921
+ !loadRemoteLang(data, currentLang, options) &&
922
+ !loadRemoteLang(data, shortLang, options) &&
923
+ data.langObj[''] && data.activeLang !== '' ) {
924
+ data.activeLang = '';
925
+ data.callback(data.langObj[''], currentLang);
926
+ callRegister(data.module);
927
+ }
1549
928
  }
1550
- });
1551
-
929
+ };
1552
930
 
1553
931
 
1554
- $(function(){
1555
- var stopPropagation = function(e){
1556
- e.stopPropagation();
1557
- };
1558
- $(document).on('submit', function(e){
932
+ var activeLang = function(lang){
933
+
934
+ if(typeof lang == 'string' && lang !== currentLang){
935
+ currentLang = lang;
936
+ shortLang = currentLang.split('-')[0];
937
+ if(currentLang == shortLang){
938
+ shortLang = false;
939
+ }
940
+ $.each(callbacks, function(i, data){
941
+ callLang(data);
942
+ });
943
+ } else if(typeof lang == 'object'){
1559
944
 
1560
- if(!e.isDefaultPrevented()){
1561
- var form = e.target;
1562
- var id = form.id;
1563
- var elements;
1564
-
1565
-
1566
- if(id){
1567
- removeAddedElements(form);
1568
-
1569
- elements = $('input[form="'+ id +'"], select[form="'+ id +'"], textarea[form="'+ id +'"]')
1570
- .filter(function(){
1571
- return !this.disabled && this.name && this.form != form;
1572
- })
1573
- .clone()
1574
- ;
1575
- if(elements.length){
1576
- $.data(form, 'webshimsAddedElements', $('<div class="webshims-visual-hide" />').append(elements).appendTo(form));
1577
- setTimeout(function(){
1578
- removeAddedElements(form);
1579
- }, 9);
1580
- }
1581
- elements = null;
945
+ if(lang.register){
946
+ if(!registeredCallbacks[lang.register]){
947
+ registeredCallbacks[lang.register] = [];
1582
948
  }
1583
- }
1584
- });
1585
-
1586
- $(document).on('click', function(e){
1587
- if(!e.isDefaultPrevented() && $(e.target).is('input[type="submit"][form], button[form], input[type="button"][form], input[type="image"][form], input[type="reset"][form]')){
1588
- var trueForm = $.prop(e.target, 'form');
1589
- var formIn = e.target.form;
1590
- var clone;
1591
- if(trueForm && trueForm != formIn){
1592
- clone = $(e.target)
1593
- .clone()
1594
- .removeAttr('form')
1595
- .addClass('webshims-visual-hide')
1596
- .on('click', stopPropagation)
1597
- .appendTo(trueForm)
1598
- ;
1599
- if(formIn){
1600
- e.preventDefault();
1601
- }
1602
- addSubmitBubbles(trueForm);
1603
- clone.trigger('click');
1604
- setTimeout(function(){
1605
- clone.remove();
1606
- clone = null;
1607
- }, 9);
949
+ registeredCallbacks[lang.register].push(lang);
950
+ lang.callback(currentLang, shortLang, '');
951
+ } else {
952
+ if(!lang.activeLang){
953
+ lang.activeLang = '';
1608
954
  }
955
+ callbacks.push(lang);
956
+ callLang(lang);
1609
957
  }
1610
- });
1611
- });
1612
- }
1613
-
1614
- if(!Modernizr.fieldsetdisabled){
1615
- webshims.defineNodeNamesProperty(['fieldset'], 'elements', {
1616
- prop: {
1617
- get: function(){
1618
- //add listed elements without keygen, object, output
1619
- return $('input, select, textarea, button, fieldset', this).get() || [];
1620
- },
1621
- writeable: false
1622
958
  }
1623
- });
1624
- }
1625
-
1626
- $.fn.serializeArray = function() {
1627
- return this.map(function(){
1628
- var elements = $.prop(this, 'elements');
1629
- return elements ? $.makeArray( elements ) : this;
1630
- })
1631
- .filter(function(){
1632
- return this.name && !this.disabled &&
1633
- ( this.checked || rselectTextarea.test( this.nodeName ) ||
1634
- rinput.test( this.type ) );
1635
- })
1636
- .map(function( i, elem ){
1637
- var val = $( this ).val();
1638
-
1639
- return val == null ?
1640
- null :
1641
- $.isArray( val ) ?
1642
- $.map( val, function( val, i ){
1643
- return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
1644
- }) :
1645
- { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
1646
- }).get();
959
+ return currentLang;
1647
960
  };
1648
-
1649
- })();
1650
- }
1651
-
1652
- try {
1653
- document.querySelector(':checked');
1654
- } catch(er){
1655
- (function(){
1656
- var checkInputs = {
1657
- radio: 1,
1658
- checkbox: 1
1659
- };
1660
- var selectChange = function(){
1661
- var options = this.options || [];
1662
- var i, len, option;
1663
- for(i = 0, len = options.length; i < len; i++){
1664
- option = $(options[i]);
1665
- option[$.prop(options[i], 'selected') ? 'addClass' : 'removeClass']('prop-checked');
1666
- }
1667
- };
1668
- var checkChange = function(){
1669
- var fn = $.prop(this, 'checked') ? 'addClass' : 'removeClass';
1670
- var className = this.className || '';
1671
- var parent;
1672
961
 
1673
- //IE8- has problems to update styles, we help
1674
- if( (className.indexOf('prop-checked') == -1) == (fn == 'addClass')){
1675
- $(this)[fn]('prop-checked');
1676
- if((parent = this.parentNode)){
1677
- parent.className = parent.className;
1678
- }
1679
- }
962
+ return activeLang;
963
+ })()
964
+ });
965
+
966
+ $.each({
967
+ defineNodeNamesProperty: 'defineNodeNameProperty',
968
+ defineNodeNamesProperties: 'defineNodeNameProperties',
969
+ createElements: 'createElement'
970
+ }, function(name, baseMethod){
971
+ webshims[name] = function(names, a, b, c){
972
+ if(typeof names == 'string'){
973
+ names = names.split(listReg);
974
+ }
975
+ var retDesc = {};
976
+ names.forEach(function(nodeName){
977
+ retDesc[nodeName] = webshims[baseMethod](nodeName, a, b, c);
978
+ });
979
+ return retDesc;
1680
980
  };
1681
-
1682
-
1683
- webshims.onNodeNamesPropertyModify('select', 'value', selectChange);
1684
- webshims.onNodeNamesPropertyModify('select', 'selectedIndex', selectChange);
1685
- webshims.onNodeNamesPropertyModify('option', 'selected', function(){
1686
- $(this).closest('select').each(selectChange);
1687
- });
1688
- webshims.onNodeNamesPropertyModify('input', 'checked', function(value, boolVal){
1689
- var type = this.type;
1690
- if(type == 'radio' && boolVal){
1691
- webshims.modules["form-core"].getGroupElements(this).each(checkChange);
1692
- } else if(checkInputs[type]) {
1693
- $(this).each(checkChange);
1694
- }
1695
- });
1696
-
1697
- $(document).on('change', function(e){
1698
-
1699
- if(checkInputs[e.target.type]){
1700
- if(e.target.type == 'radio'){
1701
- webshims.modules["form-core"].getGroupElements(e.target).each(checkChange);
1702
- } else {
1703
- $(e.target)[$.prop(e.target, 'checked') ? 'addClass' : 'removeClass']('prop-checked');
1704
- }
1705
- } else if(e.target.nodeName.toLowerCase() == 'select'){
1706
- $(e.target).each(selectChange);
1707
- }
1708
- });
1709
-
1710
- webshims.addReady(function(context, contextElem){
1711
- $('option, input', context)
1712
- .add(contextElem.filter('option, input'))
1713
- .each(function(){
1714
- var prop;
1715
- if(checkInputs[this.type]){
1716
- prop = 'checked';
1717
- } else if(this.nodeName.toLowerCase() == 'option'){
1718
- prop = 'selected';
1719
- }
1720
- if(prop){
1721
- $(this)[$.prop(this, prop) ? 'addClass' : 'removeClass']('prop-checked');
1722
- }
1723
-
1724
- })
1725
- ;
1726
- });
1727
- })();
1728
- }
1729
-
1730
- (function(){
1731
- Modernizr.textareaPlaceholder = !!('placeholder' in $('<textarea />')[0]);
1732
- if(Modernizr.input.placeholder && Modernizr.textareaPlaceholder){return;}
981
+ });
982
+
983
+ webshims.isReady('webshimLocalization', true);
984
+ });
985
+ //html5a11y
986
+ (function($, document){
987
+ if(!$.webshims.assumeARIA || ('content' in document.createElement('template'))){return;}
988
+
989
+ $(function(){
990
+ var main = $('main').attr({role: 'main'});
991
+ if(main.length > 1){
992
+ webshims.error('only one main element allowed in document');
993
+ } else if(main.is('article *, section *')) {
994
+ webshims.error('main not allowed inside of article/section elements');
995
+ }
996
+ });
1733
997
 
1734
- var isOver = (webshims.cfg.forms.placeholderType == 'over');
1735
- var isResponsive = (webshims.cfg.forms.responsivePlaceholder);
1736
- var polyfillElements = ['textarea'];
1737
- if(!Modernizr.input.placeholder){
1738
- polyfillElements.push('input');
998
+ if(('hidden' in document.createElement('a'))){
999
+ return;
1739
1000
  }
1740
1001
 
1741
- var setSelection = function(elem){
1742
- try {
1743
- if(elem.setSelectionRange){
1744
- elem.setSelectionRange(0, 0);
1745
- return true;
1746
- } else if(elem.createTextRange){
1747
- var range = elem.createTextRange();
1748
- range.collapse(true);
1749
- range.moveEnd('character', 0);
1750
- range.moveStart('character', 0);
1751
- range.select();
1752
- return true;
1753
- }
1754
- } catch(er){}
1002
+ var elemMappings = {
1003
+ article: "article",
1004
+ aside: "complementary",
1005
+ section: "region",
1006
+ nav: "navigation",
1007
+ address: "contentinfo"
1008
+ };
1009
+ var addRole = function(elem, role){
1010
+ var hasRole = elem.getAttribute('role');
1011
+ if (!hasRole) {
1012
+ elem.setAttribute('role', role);
1013
+ }
1755
1014
  };
1756
1015
 
1757
- var hidePlaceholder = function(elem, data, value, _onFocus){
1758
- if(value === false){
1759
- value = $.prop(elem, 'value');
1760
- }
1761
- if(!isOver && elem.type != 'password'){
1762
- if(!value && _onFocus && setSelection(elem)){
1763
- var selectTimer = setTimeout(function(){
1764
- setSelection(elem);
1765
- }, 9);
1766
- $(elem)
1767
- .off('.placeholderremove')
1768
- .on({
1769
- 'keydown.placeholderremove keypress.placeholderremove paste.placeholderremove input.placeholderremove': function(e){
1770
- if(e && (e.keyCode == 17 || e.keyCode == 16)){return;}
1771
- elem.value = $.prop(elem, 'value');
1772
- data.box.removeClass('placeholder-visible');
1773
- clearTimeout(selectTimer);
1774
- $(elem).unbind('.placeholderremove');
1775
- },
1776
- 'mousedown.placeholderremove drag.placeholderremove select.placeholderremove': function(e){
1777
- setSelection(elem);
1778
- clearTimeout(selectTimer);
1779
- selectTimer = setTimeout(function(){
1780
- setSelection(elem);
1781
- }, 9);
1782
- },
1783
- 'blur.placeholderremove': function(){
1784
- clearTimeout(selectTimer);
1785
- $(elem).unbind('.placeholderremove');
1786
- }
1787
- })
1788
- ;
1789
- return;
1790
- }
1791
- elem.value = value;
1792
- } else if(!value && _onFocus){
1793
- $(elem)
1794
- .off('.placeholderremove')
1795
- .on({
1796
- 'keydown.placeholderremove keypress.placeholderremove paste.placeholderremove input.placeholderremove': function(e){
1797
- if(e && (e.keyCode == 17 || e.keyCode == 16)){return;}
1798
- data.box.removeClass('placeholder-visible');
1799
- $(elem).unbind('.placeholderremove');
1800
- },
1801
- 'blur.placeholderremove': function(){
1802
- $(elem).unbind('.placeholderremove');
1803
- }
1804
- })
1805
- ;
1806
- return;
1807
- }
1808
- data.box.removeClass('placeholder-visible');
1809
- },
1810
- showPlaceholder = function(elem, data, placeholderTxt){
1811
- if(placeholderTxt === false){
1812
- placeholderTxt = $.prop(elem, 'placeholder');
1016
+
1017
+ $.webshims.addReady(function(context, contextElem){
1018
+ $.each(elemMappings, function(name, role){
1019
+ var elems = $(name, context).add(contextElem.filter(name));
1020
+ for (var i = 0, len = elems.length; i < len; i++) {
1021
+ addRole(elems[i], role);
1813
1022
  }
1023
+ });
1024
+ if (context === document) {
1025
+ var header = document.getElementsByTagName('header')[0];
1026
+ var footers = document.getElementsByTagName('footer');
1027
+ var footerLen = footers.length;
1814
1028
 
1815
- if(!isOver && elem.type != 'password'){
1816
- elem.value = placeholderTxt;
1029
+ if (header && !$(header).closest('section, article')[0]) {
1030
+ addRole(header, 'banner');
1817
1031
  }
1818
- data.box.addClass('placeholder-visible');
1819
- },
1820
- changePlaceholderVisibility = function(elem, value, placeholderTxt, data, type){
1821
- if(!data){
1822
- data = $.data(elem, 'placeHolder');
1823
- if(!data){return;}
1824
- }
1825
- $(elem).unbind('.placeholderremove');
1826
- if(type == 'focus' || (!type && $(elem).is(':focus'))){
1827
- if(elem.type == 'password' || isOver || $(elem).hasClass('placeholder-visible')){
1828
- hidePlaceholder(elem, data, '', true);
1829
- }
1032
+ if (!footerLen) {
1830
1033
  return;
1831
1034
  }
1832
- if(value === false){
1833
- value = $.prop(elem, 'value');
1035
+ var footer = footers[footerLen - 1];
1036
+ if (!$(footer).closest('section, article')[0]) {
1037
+ addRole(footer, 'contentinfo');
1834
1038
  }
1835
- if(value){
1836
- hidePlaceholder(elem, data, value);
1837
- return;
1838
- }
1839
- if(placeholderTxt === false){
1840
- placeholderTxt = $.attr(elem, 'placeholder') || '';
1841
- }
1842
- if(placeholderTxt && !value){
1843
- showPlaceholder(elem, data, placeholderTxt);
1844
- } else {
1845
- hidePlaceholder(elem, data, value);
1846
- }
1847
- },
1848
- createPlaceholder = function(elem){
1849
- elem = $(elem);
1850
- var id = elem.prop('id'),
1851
- hasLabel = !!(elem.prop('title') || elem.attr('aria-labelledby'))
1852
- ;
1853
- if(!hasLabel && id){
1854
- hasLabel = !!( $('label[for="'+ id +'"]', elem[0].form)[0] );
1855
- }
1856
- if(!hasLabel){
1857
- if(!id){
1858
- id = $.webshims.getID(elem);
1859
- }
1860
- hasLabel = !!($('label #'+ id)[0]);
1039
+ }
1040
+ });
1041
+
1042
+ })(jQuery, document);
1043
+
1044
+ //additional tests for partial implementation of forms features
1045
+ (function($){
1046
+ "use strict";
1047
+ var isWebkit = 'webkitURL' in window;
1048
+ var Modernizr = window.Modernizr;
1049
+ var webshims = $.webshims;
1050
+ var bugs = webshims.bugs;
1051
+ var form = $('<form action="#" style="width: 1px; height: 1px; overflow: hidden;"><select name="b" required="" /><input required="" name="a" /></form>');
1052
+ var testRequiredFind = function(){
1053
+ if(form[0].querySelector){
1054
+ try {
1055
+ bugs.findRequired = !(form[0].querySelector('select:required'));
1056
+ } catch(er){
1057
+ bugs.findRequired = false;
1861
1058
  }
1862
- return $( hasLabel ? '<span class="placeholder-text"></span>' : '<label for="'+ id +'" class="placeholder-text"></label>');
1863
- },
1864
- pHolder = (function(){
1865
- var delReg = /\n|\r|\f|\t/g,
1866
- allowedPlaceholder = {
1867
- text: 1,
1868
- search: 1,
1869
- url: 1,
1870
- email: 1,
1871
- password: 1,
1872
- tel: 1,
1873
- number: 1
1874
- }
1875
- ;
1059
+ }
1060
+ };
1061
+ var inputElem = $('input', form).eq(0);
1062
+ var onDomextend = function(fn){
1063
+ webshims.loader.loadList(['dom-extend']);
1064
+ webshims.ready('dom-extend', fn);
1065
+ };
1066
+
1067
+ bugs.findRequired = false;
1068
+ bugs.validationMessage = false;
1069
+
1070
+ webshims.capturingEventPrevented = function(e){
1071
+ if(!e._isPolyfilled){
1072
+ var isDefaultPrevented = e.isDefaultPrevented;
1073
+ var preventDefault = e.preventDefault;
1074
+ e.preventDefault = function(){
1075
+ clearTimeout($.data(e.target, e.type + 'DefaultPrevented'));
1076
+ $.data(e.target, e.type + 'DefaultPrevented', setTimeout(function(){
1077
+ $.removeData(e.target, e.type + 'DefaultPrevented');
1078
+ }, 30));
1079
+ return preventDefault.apply(this, arguments);
1080
+ };
1081
+ e.isDefaultPrevented = function(){
1082
+ return !!(isDefaultPrevented.apply(this, arguments) || $.data(e.target, e.type + 'DefaultPrevented') || false);
1083
+ };
1084
+ e._isPolyfilled = true;
1085
+ }
1086
+ };
1087
+
1088
+ if(!Modernizr.formvalidation || bugs.bustedValidity){
1089
+ testRequiredFind();
1090
+ } else {
1091
+ //create delegatable events
1092
+ webshims.capturingEvents(['invalid'], true);
1093
+
1094
+ if(window.opera || window.testGoodWithFix){
1876
1095
 
1877
- return {
1878
- create: function(elem){
1879
- var data = $.data(elem, 'placeHolder');
1880
- var form;
1881
- var responsiveElem;
1882
- if(data){return data;}
1883
- data = $.data(elem, 'placeHolder', {});
1884
-
1885
- $(elem).on('focus.placeholder blur.placeholder', function(e){
1886
- changePlaceholderVisibility(this, false, false, data, e.type );
1887
- data.box[e.type == 'focus' ? 'addClass' : 'removeClass']('placeholder-focused');
1888
- });
1096
+ form.appendTo('head');
1097
+
1098
+ testRequiredFind();
1099
+ bugs.validationMessage = !(inputElem.prop('validationMessage'));
1100
+
1101
+ webshims.reTest(['form-native-extend', 'form-message']);
1102
+
1103
+ form.remove();
1104
+
1105
+ $(function(){
1106
+ onDomextend(function(){
1889
1107
 
1890
- if((form = $.prop(elem, 'form'))){
1891
- $(form).on('reset.placeholder', function(e){
1892
- setTimeout(function(){
1893
- changePlaceholderVisibility(elem, false, false, data, e.type );
1894
- }, 0);
1895
- });
1896
- }
1108
+ //Opera shows native validation bubbles in case of input.checkValidity()
1109
+ // Opera 11.6/12 hasn't fixed this issue right, it's buggy
1110
+ var preventDefault = function(e){
1111
+ e.preventDefault();
1112
+ };
1897
1113
 
1898
- if(elem.type == 'password' || isOver){
1899
- data.text = createPlaceholder(elem);
1900
- if(isResponsive || $(elem).is('.responsive-width') || (elem.currentStyle || {width: ''}).width.indexOf('%') != -1){
1901
- responsiveElem = true;
1902
- data.box = data.text;
1903
- } else {
1904
- data.box = $(elem)
1905
- .wrap('<span class="placeholder-box placeholder-box-'+ (elem.nodeName || '').toLowerCase() +' placeholder-box-'+$.css(elem, 'float')+'" />')
1906
- .parent()
1907
- ;
1908
- }
1909
- data.text
1910
- .insertAfter(elem)
1911
- .on('mousedown.placeholder', function(){
1912
- changePlaceholderVisibility(this, false, false, data, 'focus');
1913
- try {
1914
- setTimeout(function(){
1915
- elem.focus();
1916
- }, 0);
1917
- } catch(e){}
1918
- return false;
1919
- })
1920
- ;
1921
-
1922
-
1923
- $.each(['lineHeight', 'fontSize', 'fontFamily', 'fontWeight'], function(i, style){
1924
- var prop = $.css(elem, style);
1925
- if(data.text.css(style) != prop){
1926
- data.text.css(style, prop);
1927
- }
1928
- });
1929
- $.each(['Left', 'Top'], function(i, side){
1930
- var size = (parseInt($.css(elem, 'padding'+ side), 10) || 0) + Math.max((parseInt($.css(elem, 'margin'+ side), 10) || 0), 0) + (parseInt($.css(elem, 'border'+ side +'Width'), 10) || 0);
1931
- data.text.css('padding'+ side, size);
1932
- });
1933
-
1934
- $(document)
1935
- .onTrigger('updateshadowdom', function(){
1936
- var height, width;
1937
- if((width = elem.offsetWidth) || (height = elem.offsetHeight)){
1938
- data.text
1939
- .css({
1940
- width: width,
1941
- height: height
1942
- })
1943
- .css($(elem).position())
1944
- ;
1945
- }
1946
- })
1947
- ;
1948
-
1949
- } else {
1950
- var reset = function(e){
1951
- if($(elem).hasClass('placeholder-visible')){
1952
- hidePlaceholder(elem, data, '');
1953
- if(e && e.type == 'submit'){
1954
- setTimeout(function(){
1955
- if(e.isDefaultPrevented()){
1956
- changePlaceholderVisibility(elem, false, false, data );
1957
- }
1958
- }, 9);
1114
+ ['form', 'input', 'textarea', 'select'].forEach(function(name){
1115
+ var desc = webshims.defineNodeNameProperty(name, 'checkValidity', {
1116
+ prop: {
1117
+ value: function(){
1118
+ if (!webshims.fromSubmit) {
1119
+ $(this).on('invalid.checkvalidity', preventDefault);
1120
+ }
1121
+
1122
+ webshims.fromCheckValidity = true;
1123
+ var ret = desc.prop._supvalue.apply(this, arguments);
1124
+ if (!webshims.fromSubmit) {
1125
+ $(this).unbind('invalid.checkvalidity', preventDefault);
1126
+ }
1127
+ webshims.fromCheckValidity = false;
1128
+ return ret;
1959
1129
  }
1960
1130
  }
1961
- };
1962
-
1963
- $(window).on('beforeunload', reset);
1964
- data.box = $(elem);
1965
- if(form){
1966
- $(form).submit(reset);
1967
- }
1968
- }
1131
+ });
1132
+ });
1969
1133
 
1970
- return data;
1971
- },
1972
- update: function(elem, val){
1973
- var type = ($.attr(elem, 'type') || $.prop(elem, 'type') || '').toLowerCase();
1974
- if(!allowedPlaceholder[type] && !$.nodeName(elem, 'textarea')){
1975
- webshims.error('placeholder not allowed on input[type="'+type+'"]');
1976
- if(type == 'date'){
1977
- webshims.error('but you can use data-placeholder for input[type="date"]');
1978
- }
1979
- return;
1134
+ });
1135
+ });
1136
+ }
1137
+
1138
+ if(isWebkit && !webshims.bugs.bustedValidity){
1139
+ (function(){
1140
+ var elems = /^(?:textarea|input)$/i;
1141
+ var form = false;
1142
+
1143
+ document.addEventListener('contextmenu', function(e){
1144
+ if(elems.test( e.target.nodeName || '') && (form = e.target.form)){
1145
+ setTimeout(function(){
1146
+ form = false;
1147
+ }, 1);
1980
1148
  }
1981
-
1982
-
1983
- var data = pHolder.create(elem);
1984
- if(data.text){
1985
- data.text.text(val);
1149
+ }, false);
1150
+
1151
+ $(window).on('invalid', function(e){
1152
+ if(e.originalEvent && form && form == e.target.form){
1153
+ e.wrongWebkitInvalid = true;
1154
+ e.stopImmediatePropagation();
1986
1155
  }
1987
-
1988
- changePlaceholderVisibility(elem, false, val, data);
1989
- }
1990
- };
1991
- })()
1992
- ;
1156
+ });
1157
+
1158
+ })();
1159
+ }
1160
+ }
1161
+
1162
+ $.webshims.register('form-core', function($, webshims, window, document, undefined, options){
1993
1163
 
1994
- $.webshims.publicMethods = {
1995
- pHolder: pHolder
1996
- };
1997
- polyfillElements.forEach(function(nodeName){
1998
- var desc = webshims.defineNodeNameProperty(nodeName, 'placeholder', {
1999
- attr: {
2000
- set: function(val){
2001
- var elem = this;
2002
- webshims.contentAttr(elem, 'placeholder', val);
2003
- pHolder.update(elem, val);
2004
- },
2005
- get: function(){
2006
- return webshims.contentAttr(this, 'placeholder');
1164
+ var checkTypes = {checkbox: 1, radio: 1};
1165
+ var emptyJ = $([]);
1166
+ var bugs = webshims.bugs;
1167
+ var getGroupElements = function(elem){
1168
+ elem = $(elem);
1169
+ var name;
1170
+ var form;
1171
+ var ret = emptyJ;
1172
+ if(elem[0].type == 'radio'){
1173
+ form = elem.prop('form');
1174
+ name = elem[0].name;
1175
+ if(!name){
1176
+ ret = elem;
1177
+ } else if(form){
1178
+ ret = $(form[name]);
1179
+ } else {
1180
+ ret = $(document.getElementsByName(name)).filter(function(){
1181
+ return !$.prop(this, 'form');
1182
+ });
1183
+ }
1184
+ ret = ret.filter('[type="radio"]');
1185
+ }
1186
+ return ret;
1187
+ };
1188
+
1189
+ var getContentValidationMessage = webshims.getContentValidationMessage = function(elem, validity, key){
1190
+ var message = $(elem).data('errormessage') || elem.getAttribute('x-moz-errormessage') || '';
1191
+ if(key && message[key]){
1192
+ message = message[key];
1193
+ }
1194
+ if(typeof message == 'object'){
1195
+ validity = validity || $.prop(elem, 'validity') || {valid: 1};
1196
+ if(!validity.valid){
1197
+ $.each(validity, function(name, prop){
1198
+ if(prop && name != 'valid' && message[name]){
1199
+ message = message[name];
1200
+ return false;
1201
+ }
1202
+ });
1203
+ }
1204
+ }
1205
+
1206
+ if(typeof message == 'object'){
1207
+ message = message.defaultMessage;
1208
+ }
1209
+ return message || '';
1210
+ };
1211
+
1212
+ /*
1213
+ * Selectors for all browsers
1214
+ */
1215
+ var rangeTypes = {number: 1, range: 1, date: 1/*, time: 1, 'datetime-local': 1, datetime: 1, month: 1, week: 1*/};
1216
+ var hasInvalid = function(elem){
1217
+ var ret = false;
1218
+ $($.prop(elem, 'elements')).each(function(){
1219
+ ret = $(this).is(':invalid');
1220
+ if(ret){
1221
+ return false;
1222
+ }
1223
+ });
1224
+ return ret;
1225
+ };
1226
+ $.extend($.expr[":"], {
1227
+ "valid-element": function(elem){
1228
+ return $.nodeName(elem, 'form') ? !hasInvalid(elem) :!!($.prop(elem, 'willValidate') && isValid(elem));
1229
+ },
1230
+ "invalid-element": function(elem){
1231
+ return $.nodeName(elem, 'form') ? hasInvalid(elem) : !!($.prop(elem, 'willValidate') && !isValid(elem));
1232
+ },
1233
+ "required-element": function(elem){
1234
+ return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required'));
1235
+ },
1236
+ "user-error": function(elem){
1237
+ return ($.prop(elem, 'willValidate') && $(elem).hasClass('user-error'));
1238
+ },
1239
+ "optional-element": function(elem){
1240
+ return !!($.prop(elem, 'willValidate') && $.prop(elem, 'required') === false);
1241
+ },
1242
+ "in-range": function(elem){
1243
+ if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
1244
+ return false;
2007
1245
  }
1246
+ var val = $.prop(elem, 'validity');
1247
+ return !!(val && !val.rangeOverflow && !val.rangeUnderflow);
2008
1248
  },
2009
- reflect: true,
2010
- initAttr: true
1249
+ "out-of-range": function(elem){
1250
+ if(!rangeTypes[$.prop(elem, 'type')] || !$.prop(elem, 'willValidate')){
1251
+ return false;
1252
+ }
1253
+ var val = $.prop(elem, 'validity');
1254
+ return !!(val && (val.rangeOverflow || val.rangeUnderflow));
1255
+ }
1256
+
2011
1257
  });
2012
- });
2013
-
2014
-
2015
- polyfillElements.forEach(function(name){
2016
- var placeholderValueDesc = {};
2017
- var desc;
2018
- ['attr', 'prop'].forEach(function(propType){
2019
- placeholderValueDesc[propType] = {
2020
- set: function(val){
2021
- var elem = this;
2022
- var placeholder = webshims.contentAttr(elem, 'placeholder');
2023
-
2024
-
2025
- $.removeData(elem, 'cachedValidity');
2026
- var ret = desc[propType]._supset.call(elem, val);
2027
- if(placeholder && 'value' in elem){
2028
- changePlaceholderVisibility(elem, val, placeholder);
1258
+
1259
+ ['valid', 'invalid', 'required', 'optional'].forEach(function(name){
1260
+ $.expr[":"][name] = $.expr.filters[name+"-element"];
1261
+ });
1262
+
1263
+
1264
+ $.expr[":"].focus = function( elem ) {
1265
+ try {
1266
+ var doc = elem.ownerDocument;
1267
+ return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus());
1268
+ } catch(e){}
1269
+ return false;
1270
+ };
1271
+
1272
+
1273
+ var customEvents = $.event.customEvent || {};
1274
+ var isValid = function(elem){
1275
+ return ($.prop(elem, 'validity') || {valid: 1}).valid;
1276
+ };
1277
+
1278
+ if (bugs.bustedValidity || bugs.findRequired) {
1279
+ (function(){
1280
+ var find = $.find;
1281
+ var matchesSelector = $.find.matchesSelector;
1282
+
1283
+ var regExp = /(\:valid|\:invalid|\:optional|\:required|\:in-range|\:out-of-range)(?=[\s\[\~\.\+\>\:\#*]|$)/ig;
1284
+ var regFn = function(sel){
1285
+ return sel + '-element';
1286
+ };
1287
+
1288
+ $.find = (function(){
1289
+ var slice = Array.prototype.slice;
1290
+ var fn = function(sel){
1291
+ var ar = arguments;
1292
+ ar = slice.call(ar, 1, ar.length);
1293
+ ar.unshift(sel.replace(regExp, regFn));
1294
+ return find.apply(this, ar);
1295
+ };
1296
+ for (var i in find) {
1297
+ if(find.hasOwnProperty(i)){
1298
+ fn[i] = find[i];
1299
+ }
2029
1300
  }
2030
- return ret;
2031
- },
2032
- get: function(){
2033
- var elem = this;
2034
- return $(elem).hasClass('placeholder-visible') ? '' : desc[propType]._supget.call(elem);
1301
+ return fn;
1302
+ })();
1303
+ if(!Modernizr.prefixed || Modernizr.prefixed("matchesSelector", document.documentElement)){
1304
+ $.find.matchesSelector = function(node, expr){
1305
+ expr = expr.replace(regExp, regFn);
1306
+ return matchesSelector.call(this, node, expr);
1307
+ };
2035
1308
  }
2036
- };
2037
- });
2038
- desc = webshims.defineNodeNameProperty(name, 'value', placeholderValueDesc);
2039
- });
2040
-
2041
- })();
2042
-
2043
- (function(){
2044
- var doc = document;
2045
- if( 'value' in document.createElement('output') ){return;}
1309
+
1310
+ })();
1311
+ }
2046
1312
 
2047
- webshims.defineNodeNameProperty('output', 'value', {
2048
- prop: {
2049
- set: function(value){
2050
- var setVal = $.data(this, 'outputShim');
2051
- if(!setVal){
2052
- setVal = outputCreate(this);
1313
+ //ToDo needs testing
1314
+ var oldAttr = $.prop;
1315
+ var changeVals = {selectedIndex: 1, value: 1, checked: 1, disabled: 1, readonly: 1};
1316
+ $.prop = function(elem, name, val){
1317
+ var ret = oldAttr.apply(this, arguments);
1318
+ if(elem && 'form' in elem && changeVals[name] && val !== undefined && $(elem).hasClass(invalidClass)){
1319
+ if(isValid(elem)){
1320
+ $(elem).getShadowElement().removeClass(invalidClass);
1321
+ if(name == 'checked' && val) {
1322
+ getGroupElements(elem).not(elem).removeClass(invalidClass).removeAttr('aria-invalid');
2053
1323
  }
2054
- setVal(value);
2055
- },
2056
- get: function(){
2057
- return webshims.contentAttr(this, 'value') || $(this).text() || '';
2058
1324
  }
2059
1325
  }
2060
- });
2061
-
1326
+ return ret;
1327
+ };
2062
1328
 
2063
- webshims.onNodeNamesPropertyModify('input', 'value', function(value, boolVal, type){
2064
- if(type == 'removeAttr'){return;}
2065
- var setVal = $.data(this, 'outputShim');
2066
- if(setVal){
2067
- setVal(value);
2068
- }
2069
- });
1329
+ var returnValidityCause = function(validity, elem){
1330
+ var ret;
1331
+ $.each(validity, function(name, value){
1332
+ if(value){
1333
+ ret = (name == 'customError') ? $.prop(elem, 'validationMessage') : name;
1334
+ return false;
1335
+ }
1336
+ });
1337
+ return ret;
1338
+ };
2070
1339
 
2071
- var outputCreate = function(elem){
2072
- if(elem.getAttribute('aria-live')){return;}
2073
- elem = $(elem);
2074
- var value = (elem.text() || '').trim();
2075
- var id = elem.attr('id');
2076
- var htmlFor = elem.attr('for');
2077
- var shim = $('<input class="output-shim" type="text" disabled name="'+ (elem.attr('name') || '')+'" value="'+value+'" style="display: none !important;" />').insertAfter(elem);
2078
- var form = shim[0].form || doc;
2079
- var setValue = function(val){
2080
- shim[0].value = val;
2081
- val = shim[0].value;
2082
- elem.text(val);
2083
- webshims.contentAttr(elem[0], 'value', val);
1340
+ var isInGroup = function(name){
1341
+ var ret;
1342
+ try {
1343
+ ret = document.activeElement.name === name;
1344
+ } catch(e){}
1345
+ return ret;
1346
+ };
1347
+ /* form-ui-invalid/form-ui-valid are deprecated. use user-error/user-success instead */
1348
+ var invalidClass = 'user-error';
1349
+ var validClass = 'user-success';
1350
+ var stopChangeTypes = {
1351
+ time: 1,
1352
+ date: 1,
1353
+ month: 1,
1354
+ datetime: 1,
1355
+ week: 1,
1356
+ 'datetime-local': 1
1357
+ };
1358
+ var switchValidityClass = function(e){
1359
+ var elem, timer;
1360
+ if(!e.target){return;}
1361
+ elem = $(e.target).getNativeElement()[0];
1362
+ if(elem.type == 'submit' || !$.prop(elem, 'willValidate')){return;}
1363
+ timer = $.data(elem, 'webshimsswitchvalidityclass');
1364
+ var switchClass = function(){
1365
+ if(e.type == 'focusout' && elem.type == 'radio' && isInGroup(elem.name)){return;}
1366
+ var validity = $.prop(elem, 'validity');
1367
+ var shadowElem = $(elem).getShadowElement();
1368
+ var addClass, removeClass, trigger, generaltrigger, validityCause;
1369
+
1370
+ if(isWebkit && e.type == 'change' && !bugs.bustedValidity && stopChangeTypes[shadowElem.prop('type')] && shadowElem.is(':focus')){return;}
1371
+
1372
+ $(elem).trigger('refreshCustomValidityRules');
1373
+
1374
+ if(validity.valid){
1375
+ if(!shadowElem.hasClass(validClass)){
1376
+ addClass = validClass;
1377
+ removeClass = invalidClass;
1378
+ generaltrigger = 'changedvaliditystate';
1379
+ trigger = 'changedvalid';
1380
+ if(checkTypes[elem.type] && elem.checked){
1381
+ getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass).removeAttr('aria-invalid');
1382
+ }
1383
+ $.removeData(elem, 'webshimsinvalidcause');
1384
+ }
1385
+ } else {
1386
+ validityCause = returnValidityCause(validity, elem);
1387
+ if($.data(elem, 'webshimsinvalidcause') != validityCause){
1388
+ $.data(elem, 'webshimsinvalidcause', validityCause);
1389
+ generaltrigger = 'changedvaliditystate';
1390
+ }
1391
+ if(!shadowElem.hasClass(invalidClass)){
1392
+ addClass = invalidClass;
1393
+ removeClass = validClass;
1394
+ if (checkTypes[elem.type] && !elem.checked) {
1395
+ getGroupElements(elem).not(elem).removeClass(removeClass).addClass(addClass);
1396
+ }
1397
+ trigger = 'changedinvalid';
1398
+ }
1399
+ }
1400
+
1401
+ if(addClass){
1402
+ shadowElem.addClass(addClass).removeClass(removeClass);
1403
+ //jQuery 1.6.1 IE9 bug (doubble trigger bug)
1404
+ setTimeout(function(){
1405
+ $(elem).trigger(trigger);
1406
+ }, 0);
1407
+ }
1408
+ if(generaltrigger){
1409
+ setTimeout(function(){
1410
+ $(elem).trigger(generaltrigger);
1411
+ }, 0);
1412
+ }
1413
+
1414
+ $.removeData(elem, 'webshimsswitchvalidityclass');
2084
1415
  };
2085
1416
 
2086
- elem[0].defaultValue = value;
2087
- webshims.contentAttr(elem[0], 'value', value);
2088
-
2089
- elem.attr({'aria-live': 'polite'});
2090
- if(id){
2091
- shim.attr('id', id);
2092
- elem.attr('aria-labelledby', webshims.getID($('label[for="'+id+'"]', form)));
1417
+ if(timer){
1418
+ clearTimeout(timer);
1419
+ }
1420
+ if(e.type == 'refreshvalidityui'){
1421
+ switchClass();
1422
+ } else {
1423
+ $.data(elem, 'webshimsswitchvalidityclass', setTimeout(switchClass, 9));
2093
1424
  }
2094
- if(htmlFor){
2095
- id = webshims.getID(elem);
2096
- htmlFor.split(' ').forEach(function(control){
2097
- control = document.getElementById(control);
2098
- if(control){
2099
- control.setAttribute('aria-controls', id);
1425
+ };
1426
+
1427
+ $(document).on(options.validityUIEvents || 'focusout change refreshvalidityui', switchValidityClass);
1428
+ customEvents.changedvaliditystate = true;
1429
+ customEvents.refreshCustomValidityRules = true;
1430
+ customEvents.changedvalid = true;
1431
+ customEvents.changedinvalid = true;
1432
+ customEvents.refreshvalidityui = true;
1433
+
1434
+
1435
+ webshims.triggerInlineForm = function(elem, event){
1436
+ $(elem).trigger(event);
1437
+ };
1438
+
1439
+ webshims.modules["form-core"].getGroupElements = getGroupElements;
1440
+
1441
+
1442
+ var setRoot = function(){
1443
+ webshims.scrollRoot = (isWebkit || document.compatMode == 'BackCompat') ?
1444
+ $(document.body) :
1445
+ $(document.documentElement)
1446
+ ;
1447
+ };
1448
+ var minWidth = (Modernizr.boxSizing || Modernizr['display-table'] || $.support.getSetAttribute) ?
1449
+ 'minWidth' :
1450
+ 'width'
1451
+ ;
1452
+ setRoot();
1453
+ webshims.ready('DOM', setRoot);
1454
+
1455
+ webshims.getRelOffset = function(posElem, relElem){
1456
+ posElem = $(posElem);
1457
+ var offset = $(relElem).offset();
1458
+ var bodyOffset;
1459
+ $.swap($(posElem)[0], {visibility: 'hidden', display: 'inline-block', left: 0, top: 0}, function(){
1460
+ bodyOffset = posElem.offset();
1461
+ });
1462
+ offset.top -= bodyOffset.top;
1463
+ offset.left -= bodyOffset.left;
1464
+ return offset;
1465
+ };
1466
+
1467
+ webshims.wsPopover = {
1468
+ _create: function(){
1469
+ this.options = $.extend({}, webshims.cfg.wspopover, this.options);
1470
+ this.id = webshims.wsPopover.id++;
1471
+ this.eventns = '.wsoverlay'+this.id;
1472
+ this.timers = {};
1473
+ this.element = $('<div class="ws-popover" tabindex="-1"><div class="ws-po-outerbox"><div class="ws-po-arrow"><div class="ws-po-arrowbox" /></div><div class="ws-po-box" /></div></div>');
1474
+ this.contentElement = $('.ws-po-box', this.element);
1475
+ this.lastElement = $([]);
1476
+ this.bindElement();
1477
+
1478
+ this.element.data('wspopover', this);
1479
+
1480
+ },
1481
+ options: {},
1482
+ content: function(html){
1483
+ this.contentElement.html(html);
1484
+ },
1485
+ bindElement: function(){
1486
+ var that = this;
1487
+ var stopBlur = function(){
1488
+ that.stopBlur = false;
1489
+ };
1490
+ this.preventBlur = function(e){
1491
+ that.stopBlur = true;
1492
+ clearTimeout(that.timers.stopBlur);
1493
+ that.timers.stopBlur = setTimeout(stopBlur, 9);
1494
+ };
1495
+ this.element.on({
1496
+ 'mousedown': this.preventBlur
1497
+ });
1498
+ },
1499
+
1500
+ isInElement: function(container, contained){
1501
+ return container == contained || $.contains(container, contained);
1502
+ },
1503
+ show: function(element){
1504
+ var e = $.Event('wspopoverbeforeshow');
1505
+ this.element.trigger(e);
1506
+ if(e.isDefaultPrevented() || this.isVisible){return;}
1507
+ this.isVisible = true;
1508
+ element = $(element || this.options.prepareFor).getNativeElement() ;
1509
+
1510
+ var that = this;
1511
+ var visual = $(element).getShadowElement();
1512
+
1513
+ this.clear();
1514
+ this.element.removeClass('ws-po-visible').css('display', 'none');
1515
+
1516
+ this.prepareFor(element, visual);
1517
+
1518
+ this.position(visual);
1519
+ that.timers.show = setTimeout(function(){
1520
+ that.element.css('display', '');
1521
+ that.timers.show = setTimeout(function(){
1522
+ that.element.addClass('ws-po-visible').trigger('wspopovershow');
1523
+ }, 9);
1524
+ }, 9);
1525
+ $(document).on('focusin'+this.eventns+' mousedown'+this.eventns, function(e){
1526
+ if(that.options.hideOnBlur && !that.stopBlur && !that.isInElement(that.lastElement[0] || document.body, e.target) && !that.isInElement(element[0] || document.body, e.target) && !that.isInElement(that.element[0], e.target)){
1527
+ that.hide();
2100
1528
  }
2101
1529
  });
1530
+ $(window).on('resize'+this.eventns + ' pospopover'+this.eventns, function(){
1531
+ clearTimeout(that.timers.repos);
1532
+ that.timers.repos = setTimeout(function(){
1533
+ that.position(visual);
1534
+ }, 900);
1535
+ });
1536
+ },
1537
+ prepareFor: function(element, visual){
1538
+ var onBlur;
1539
+ var opts = $.extend({}, this.options, $(element.prop('form') || []).data('wspopover') || {}, element.data('wspopover'));
1540
+ var that = this;
1541
+ var css = {};
1542
+ this.lastElement = $(element).getShadowFocusElement();
1543
+ if(opts.appendTo == 'element'){
1544
+ this.element.insertAfter(element);
1545
+ } else {
1546
+ this.element.appendTo(opts.appendTo);
1547
+ }
1548
+
1549
+ this.element.attr({
1550
+ 'data-class': element.prop('className'),
1551
+ 'data-id': element.prop('id')
1552
+ });
1553
+
1554
+ css[minWidth] = opts.constrainWidth ? visual.outerWidth() : '';
1555
+
1556
+ this.element.css(css);
1557
+
1558
+ if(opts.hideOnBlur){
1559
+ onBlur = function(e){
1560
+ if(that.stopBlur){
1561
+ e.stopImmediatePropagation();
1562
+ } else {
1563
+ that.hide();
1564
+ }
1565
+ };
1566
+
1567
+ that.timers.bindBlur = setTimeout(function(){
1568
+ that.lastElement.off(that.eventns).on('focusout'+that.eventns + ' blur'+that.eventns, onBlur);
1569
+ that.lastElement.getNativeElement().off(that.eventns);
1570
+ }, 10);
1571
+
1572
+
1573
+ }
1574
+
1575
+ if(!this.prepared){
1576
+
1577
+ if($.fn.bgIframe){
1578
+ this.element.bgIframe();
1579
+ }
1580
+ }
1581
+ this.prepared = true;
1582
+ },
1583
+ clear: function(){
1584
+ $(window).off(this.eventns);
1585
+ $(document).off(this.eventns);
1586
+
1587
+ this.stopBlur = false;
1588
+ $.each(this.timers, function(timerName, val){
1589
+ clearTimeout(val);
1590
+ });
1591
+ },
1592
+ hide: function(){
1593
+ var e = $.Event('wspopoverbeforehide');
1594
+ this.element.trigger(e);
1595
+ if(e.isDefaultPrevented() || !this.isVisible){return;}
1596
+ this.isVisible = false;
1597
+ var that = this;
1598
+ var forceHide = function(){
1599
+ that.element.css('display', 'none').attr({'data-id': '', 'data-class': '', 'hidden': 'hidden'});
1600
+ clearTimeout(that.timers.forcehide);
1601
+ };
1602
+ this.clear();
1603
+ this.element.removeClass('ws-po-visible').trigger('wspopoverhide');
1604
+ $(window).on('resize'+this.eventns, forceHide);
1605
+ that.timers.forcehide = setTimeout(forceHide, 999);
1606
+ },
1607
+ position: function(element){
1608
+ var offset = webshims.getRelOffset(this.element.css({marginTop: 0, marginLeft: 0, marginRight: 0, marginBottom: 0}).removeAttr('hidden'), element);
1609
+ offset.top += element.outerHeight();
1610
+ this.element.css({marginTop: '', marginLeft: '', marginRight: '', marginBottom: ''}).css(offset);
2102
1611
  }
2103
- elem.data('outputShim', setValue );
2104
- shim.data('outputShim', setValue );
2105
- return setValue;
2106
1612
  };
2107
-
2108
- webshims.addReady(function(context, contextElem){
2109
- $('output', context).add(contextElem.filter('output')).each(function(){
2110
- outputCreate(this);
2111
- });
2112
- });
2113
1613
 
2114
- /*
2115
- * Implements input event in all browsers
2116
- */
2117
- (function(){
2118
- var noInputTriggerEvts = {updateInput: 1, input: 1},
2119
- noInputTypes = {
2120
- radio: 1,
2121
- checkbox: 1,
2122
- submit: 1,
2123
- button: 1,
2124
- image: 1,
2125
- reset: 1,
2126
- file: 1
1614
+ webshims.wsPopover.id = 0;
1615
+
1616
+ /* some extra validation UI */
1617
+ webshims.validityAlert = (function(){
1618
+
1619
+
1620
+ var focusTimer = false;
1621
+
1622
+ var api = webshims.objectCreate(webshims.wsPopover, {}, options.messagePopover);
1623
+ var boundHide = api.hide.bind(api);
1624
+
1625
+ api.element.addClass('validity-alert').attr({role: 'alert'});
1626
+ $.extend(api, {
1627
+ hideDelay: 5000,
1628
+ showFor: function(elem, message, noFocusElem, noBubble){
2127
1629
 
2128
- //pro forma
2129
- ,color: 1
2130
- //,range: 1
1630
+ elem = $(elem).getNativeElement();
1631
+ this.clear();
1632
+ this.hide();
1633
+ if(!noBubble){
1634
+ this.getMessage(elem, message);
1635
+
1636
+ this.show(elem);
1637
+ if(this.hideDelay){
1638
+ this.timers.delayedHide = setTimeout(boundHide, this.hideDelay);
1639
+ }
1640
+
1641
+ }
1642
+
1643
+ if(!noFocusElem){
1644
+ this.setFocus(elem);
1645
+ }
2131
1646
  },
2132
- observe = function(input){
2133
- var timer,
2134
- lastVal = input.prop('value'),
2135
- trigger = function(e){
2136
- //input === null
2137
- if(!input){return;}
2138
- var newVal = input.prop('value');
2139
-
2140
- if(newVal !== lastVal){
2141
- lastVal = newVal;
2142
- if(!e || !noInputTriggerEvts[e.type]){
2143
- webshims.triggerInlineForm && webshims.triggerInlineForm(input[0], 'input');
2144
- }
1647
+ setFocus: function(element){
1648
+ var focusElem = $(element).getShadowFocusElement();
1649
+ var scrollTop = webshims.scrollRoot.scrollTop();
1650
+ var elemTop = focusElem.offset().top - 30;
1651
+ var smooth;
1652
+
1653
+ if(scrollTop > elemTop){
1654
+ webshims.scrollRoot.animate(
1655
+ {scrollTop: elemTop - 5},
1656
+ {
1657
+ queue: false,
1658
+ duration: Math.max( Math.min( 600, (scrollTop - elemTop) * 1.5 ), 80 )
2145
1659
  }
2146
- },
2147
- extraTimer,
2148
- extraTest = function(){
2149
- clearTimeout(extraTimer);
2150
- extraTimer = setTimeout(trigger, 9);
2151
- },
2152
- unbind = function(){
2153
- input.unbind('focusout', unbind).unbind('keyup keypress keydown paste cut', extraTest).unbind('input change updateInput', trigger);
2154
- clearInterval(timer);
2155
- setTimeout(function(){
2156
- trigger();
2157
- input = null;
2158
- }, 1);
2159
-
2160
- }
2161
- ;
1660
+ );
1661
+ smooth = true;
1662
+ }
1663
+ try {
1664
+ focusElem[0].focus();
1665
+ } catch(e){}
1666
+ if(smooth){
1667
+ webshims.scrollRoot.scrollTop(scrollTop);
1668
+ setTimeout(function(){
1669
+ webshims.scrollRoot.scrollTop(scrollTop);
1670
+ }, 0);
1671
+ }
2162
1672
 
2163
- clearInterval(timer);
2164
- timer = setInterval(trigger, 99);
2165
- extraTest();
2166
- input.on({
2167
- 'keyup keypress keydown paste cut': extraTest,
2168
- focusout: unbind,
2169
- 'input updateInput change': trigger
2170
- });
1673
+ $(window).triggerHandler('pospopover'+this.eventns);
1674
+ },
1675
+ getMessage: function(elem, message){
1676
+ if (!message) {
1677
+ message = getContentValidationMessage(elem[0]) || elem.prop('customValidationMessage') || elem.prop('validationMessage');
1678
+ }
1679
+ if (message) {
1680
+ api.contentElement.text(message);
1681
+ } else {
1682
+ this.hide();
1683
+ }
2171
1684
  }
2172
- ;
2173
- if($.event.customEvent){
2174
- $.event.customEvent.updateInput = true;
2175
- }
1685
+ });
2176
1686
 
2177
- $(doc)
2178
- .on('focusin', function(e){
2179
- if( e.target && e.target.type && !e.target.readOnly && !e.target.disabled && (e.target.nodeName || '').toLowerCase() == 'input' && !noInputTypes[e.target.type] ){
2180
- observe($(e.target));
2181
- }
2182
- })
1687
+
1688
+ return api;
1689
+ })();
1690
+
1691
+
1692
+ /* extension, but also used to fix native implementation workaround/bugfixes */
1693
+ (function(){
1694
+ var firstEvent,
1695
+ invalids = [],
1696
+ stopSubmitTimer,
1697
+ form
2183
1698
  ;
1699
+
1700
+ $(document).on('invalid', function(e){
1701
+ if(e.wrongWebkitInvalid){return;}
1702
+ var jElm = $(e.target);
1703
+ var shadowElem = jElm.getShadowElement();
1704
+ if(!shadowElem.hasClass(invalidClass)){
1705
+ shadowElem.addClass(invalidClass).removeClass(validClass);
1706
+ setTimeout(function(){
1707
+ $(e.target).trigger('changedinvalid').trigger('changedvaliditystate');
1708
+ }, 0);
1709
+ }
1710
+
1711
+ if(!firstEvent){
1712
+ //trigger firstinvalid
1713
+ firstEvent = $.Event('firstinvalid');
1714
+ firstEvent.isInvalidUIPrevented = e.isDefaultPrevented;
1715
+ var firstSystemInvalid = $.Event('firstinvalidsystem');
1716
+ $(document).triggerHandler(firstSystemInvalid, {element: e.target, form: e.target.form, isInvalidUIPrevented: e.isDefaultPrevented});
1717
+ jElm.trigger(firstEvent);
1718
+ }
1719
+
1720
+ //if firstinvalid was prevented all invalids will be also prevented
1721
+ if( firstEvent && firstEvent.isDefaultPrevented() ){
1722
+ e.preventDefault();
1723
+ }
1724
+ invalids.push(e.target);
1725
+ e.extraData = 'fix';
1726
+ clearTimeout(stopSubmitTimer);
1727
+ stopSubmitTimer = setTimeout(function(){
1728
+ var lastEvent = {type: 'lastinvalid', cancelable: false, invalidlist: $(invalids)};
1729
+ //reset firstinvalid
1730
+ firstEvent = false;
1731
+ invalids = [];
1732
+ $(e.target).trigger(lastEvent, lastEvent);
1733
+ }, 9);
1734
+ jElm = null;
1735
+ shadowElem = null;
1736
+ });
2184
1737
  })();
2185
- })();
2186
-
2187
- }); //webshims.ready end
2188
- }//end formvalidation
1738
+
1739
+ $.fn.getErrorMessage = function(){
1740
+ var message = '';
1741
+ var elem = this[0];
1742
+ if(elem){
1743
+ message = getContentValidationMessage(elem) || $.prop(elem, 'customValidationMessage') || $.prop(elem, 'validationMessage');
1744
+ }
1745
+ return message;
1746
+ };
1747
+
1748
+ if(options.replaceValidationUI){
1749
+ if(options.overrideMessages && (options.customMessages || options.customMessages == null)){
1750
+ options.customMessages = true;
1751
+ options.overrideMessages = false;
1752
+ webshims.info("set overrideMessages to false. Use customMessages instead");
1753
+ }
1754
+ webshims.ready('DOM forms', function(){
1755
+ $(document).on('firstinvalid', function(e){
1756
+ if(!e.isInvalidUIPrevented()){
1757
+ e.preventDefault();
1758
+ $.webshims.validityAlert.showFor( e.target );
1759
+ }
1760
+ });
1761
+ });
1762
+ }
1763
+ });
2189
1764
 
1765
+ })(jQuery);
2190
1766
  jQuery.webshims.register('form-message', function($, webshims, window, document, undefined, options){
2191
1767
  "use strict";
2192
1768
  var validityMessages = webshims.validityMessages;
2193
1769
 
2194
1770
  var implementProperties = (options.overrideMessages || options.customMessages) ? ['customValidationMessage'] : [];
2195
1771
 
2196
- validityMessages['en'] = $.extend(true, {
1772
+ validityMessages.en = $.extend(true, {
2197
1773
  typeMismatch: {
1774
+ defaultMessage: 'Please enter a valid value.',
2198
1775
  email: 'Please enter an email address.',
2199
1776
  url: 'Please enter a URL.',
2200
1777
  number: 'Please enter a number.',
2201
1778
  date: 'Please enter a date.',
2202
1779
  time: 'Please enter a time.',
2203
1780
  range: 'Invalid input.',
1781
+ month: 'Please enter a valid value.',
2204
1782
  "datetime-local": 'Please enter a datetime.'
2205
1783
  },
2206
1784
  rangeUnderflow: {
@@ -2211,43 +1789,42 @@ jQuery.webshims.register('form-message', function($, webshims, window, document,
2211
1789
  },
2212
1790
  stepMismatch: 'Invalid input.',
2213
1791
  tooLong: 'Please enter at most {%maxlength} character(s). You entered {%valueLen}.',
2214
-
2215
1792
  patternMismatch: 'Invalid input. {%title}',
2216
1793
  valueMissing: {
2217
1794
  defaultMessage: 'Please fill out this field.',
2218
1795
  checkbox: 'Please check this box if you want to proceed.'
2219
1796
  }
2220
- }, (validityMessages['en'] || validityMessages['en-US'] || {}));
2221
-
2222
-
2223
- ['select', 'radio'].forEach(function(type){
2224
- if(typeof validityMessages['en'].valueMissing == 'object'){
2225
- validityMessages['en'].valueMissing[type] = 'Please select an option.';
2226
- }
2227
- });
1797
+ }, (validityMessages.en || validityMessages['en-US'] || {}));
2228
1798
 
2229
- ['date', 'time', 'datetime-local'].forEach(function(type){
2230
- if(typeof validityMessages['en'].rangeUnderflow == 'object'){
1799
+ if(typeof validityMessages['en'].valueMissing == 'object'){
1800
+ ['select', 'radio'].forEach(function(type){
1801
+ validityMessages.en.valueMissing[type] = 'Please select an option.';
1802
+ });
1803
+ }
1804
+ if(typeof validityMessages.en.rangeUnderflow == 'object'){
1805
+ ['date', 'time', 'datetime-local', 'month'].forEach(function(type){
2231
1806
  validityMessages.en.rangeUnderflow[type] = 'Value must be at or after {%min}.';
2232
- }
2233
- });
2234
- ['date', 'time', 'datetime-local'].forEach(function(type){
2235
- if(typeof validityMessages['en'].rangeOverflow == 'object'){
1807
+ });
1808
+ }
1809
+ if(typeof validityMessages.en.rangeOverflow == 'object'){
1810
+ ['date', 'time', 'datetime-local', 'month'].forEach(function(type){
2236
1811
  validityMessages.en.rangeOverflow[type] = 'Value must be at or before {%max}.';
2237
- }
2238
- });
1812
+ });
1813
+ }
2239
1814
 
2240
- validityMessages['en-US'] = validityMessages['en-US'] || validityMessages['en'];
1815
+ validityMessages['en-US'] = validityMessages['en-US'] || validityMessages.en;
2241
1816
  validityMessages[''] = validityMessages[''] || validityMessages['en-US'];
2242
1817
 
2243
- validityMessages['de'] = $.extend(true, {
1818
+ validityMessages.de = $.extend(true, {
2244
1819
  typeMismatch: {
2245
- email: '{%value} ist keine zulässige E-Mail-Adresse',
2246
- url: '{%value} ist keine zulässige Webadresse',
2247
- number: '{%value} ist keine Nummer!',
2248
- date: '{%value} ist kein Datum',
2249
- time: '{%value} ist keine Uhrzeit',
2250
- range: '{%value} ist keine Nummer!',
1820
+ defaultMessage: '{%value} ist in diesem Feld nicht zulässig.',
1821
+ email: '{%value} ist keine gültige E-Mail-Adresse.',
1822
+ url: '{%value} ist kein(e) gültige(r) Webadresse/Pfad.',
1823
+ number: '{%value} ist keine Nummer.',
1824
+ date: '{%value} ist kein Datum.',
1825
+ time: '{%value} ist keine Uhrzeit.',
1826
+ month: '{%value} ist in diesem Feld nicht zulässig.',
1827
+ range: '{%value} ist keine Nummer.',
2251
1828
  "datetime-local": '{%value} ist kein Datum-Uhrzeit Format.'
2252
1829
  },
2253
1830
  rangeUnderflow: {
@@ -2258,51 +1835,73 @@ jQuery.webshims.register('form-message', function($, webshims, window, document,
2258
1835
  },
2259
1836
  stepMismatch: 'Der Wert {%value} ist in diesem Feld nicht zulässig. Hier sind nur bestimmte Werte zulässig. {%title}',
2260
1837
  tooLong: 'Der eingegebene Text ist zu lang! Sie haben {%valueLen} Zeichen eingegeben, dabei sind {%maxlength} das Maximum.',
2261
- patternMismatch: '{%value} hat für dieses Eingabefeld ein falsches Format! {%title}',
1838
+ patternMismatch: '{%value} hat für dieses Eingabefeld ein falsches Format. {%title}',
2262
1839
  valueMissing: {
2263
- defaultMessage: 'Bitte geben Sie einen Wert ein',
2264
- checkbox: 'Bitte aktivieren Sie das Kästchen'
2265
- }
2266
- }, (validityMessages['de'] || {}));
2267
-
2268
- ['select', 'radio'].forEach(function(type){
2269
- if(typeof validityMessages['de'].valueMissing == 'object'){
2270
- validityMessages['de'].valueMissing[type] = 'Bitte wählen Sie eine Option aus';
1840
+ defaultMessage: 'Bitte geben Sie einen Wert ein.',
1841
+ checkbox: 'Bitte aktivieren Sie das Kästchen.'
2271
1842
  }
2272
- });
1843
+ }, (validityMessages.de || {}));
2273
1844
 
2274
- ['date', 'time', 'datetime-local'].forEach(function(type){
2275
- if(typeof validityMessages['de'].rangeUnderflow == 'object'){
1845
+ if(typeof validityMessages.de.valueMissing == 'object'){
1846
+ ['select', 'radio'].forEach(function(type){
1847
+ validityMessages.de.valueMissing[type] = 'Bitte wählen Sie eine Option aus.';
1848
+ });
1849
+ }
1850
+ if(typeof validityMessages.de.rangeUnderflow == 'object'){
1851
+ ['date', 'time', 'datetime-local', 'month'].forEach(function(type){
2276
1852
  validityMessages.de.rangeUnderflow[type] = '{%value} ist zu früh. {%min} ist die früheste Zeit, die Sie benutzen können.';
2277
- }
2278
- });
2279
- ['date', 'time', 'datetime-local'].forEach(function(type){
2280
- if(typeof validityMessages['de'].rangeOverflow == 'object'){
1853
+ });
1854
+ }
1855
+ if(typeof validityMessages.de.rangeOverflow == 'object'){
1856
+ ['date', 'time', 'datetime-local', 'month'].forEach(function(type){
2281
1857
  validityMessages.de.rangeOverflow[type] = '{%value} ist zu spät. {%max} ist die späteste Zeit, die Sie benutzen können.';
2282
- }
2283
- });
1858
+ });
1859
+ }
2284
1860
 
2285
1861
  var currentValidationMessage = validityMessages[''];
2286
-
2287
-
2288
- webshims.createValidationMessage = function(elem, name){
2289
- var message = currentValidationMessage[name];
1862
+ var getMessageFromObj = function(message, elem){
2290
1863
  if(message && typeof message !== 'string'){
2291
1864
  message = message[ $.prop(elem, 'type') ] || message[ (elem.nodeName || '').toLowerCase() ] || message[ 'defaultMessage' ];
2292
1865
  }
1866
+ return message || '';
1867
+ };
1868
+ var valueVals = {
1869
+ value: 1,
1870
+ min: 1,
1871
+ max: 1
1872
+ };
1873
+
1874
+ webshims.createValidationMessage = function(elem, name){
1875
+ var spinner;
1876
+ var message = getMessageFromObj(currentValidationMessage[name], elem);
1877
+
1878
+ if(!message){
1879
+ message = getMessageFromObj(validityMessages[''][name], elem) || 'invalid value';
1880
+ webshims.info('could not find errormessage for: '+ name +' / '+ $.prop(elem, 'type') +'. in language: '+$.webshims.activeLang());
1881
+ }
2293
1882
  if(message){
2294
1883
  ['value', 'min', 'max', 'title', 'maxlength', 'label'].forEach(function(attr){
2295
1884
  if(message.indexOf('{%'+attr) === -1){return;}
2296
- var val = ((attr == 'label') ? $.trim($('label[for="'+ elem.id +'"]', elem.form).text()).replace(/\*$|:$/, '') : $.attr(elem, attr)) || '';
1885
+ var val = ((attr == 'label') ? $.trim($('label[for="'+ elem.id +'"]', elem.form).text()).replace(/\*$|:$/, '') : $.prop(elem, attr)) || '';
2297
1886
  if(name == 'patternMismatch' && attr == 'title' && !val){
2298
1887
  webshims.error('no title for patternMismatch provided. Always add a title attribute.');
2299
1888
  }
1889
+ if(valueVals[attr]){
1890
+ if(!spinner){
1891
+ spinner = $(elem).getShadowElement().data('wsspinner');
1892
+ }
1893
+ if(spinner && spinner.formatValue){
1894
+ val = spinner.formatValue(val, false);
1895
+ }
1896
+ }
2300
1897
  message = message.replace('{%'+ attr +'}', val);
2301
1898
  if('value' == attr){
2302
1899
  message = message.replace('{%valueLen}', val.length);
2303
1900
  }
1901
+
2304
1902
  });
2305
1903
  }
1904
+
2306
1905
  return message || '';
2307
1906
  };
2308
1907
 
@@ -2315,6 +1914,7 @@ jQuery.webshims.register('form-message', function($, webshims, window, document,
2315
1914
  langObj: validityMessages,
2316
1915
  module: 'form-core',
2317
1916
  callback: function(langObj){
1917
+
2318
1918
  currentValidationMessage = langObj;
2319
1919
  }
2320
1920
  });
@@ -2363,685 +1963,4 @@ jQuery.webshims.register('form-message', function($, webshims, window, document,
2363
1963
  });
2364
1964
 
2365
1965
  });
2366
- });
2367
- jQuery.webshims.register('form-datalist', function($, webshims, window, document, undefined){
2368
- "use strict";
2369
- var doc = document;
2370
-
2371
- /*
2372
- * implement propType "element" currently only used for list-attribute (will be moved to dom-extend, if needed)
2373
- */
2374
- webshims.propTypes.element = function(descs){
2375
- webshims.createPropDefault(descs, 'attr');
2376
- if(descs.prop){return;}
2377
- descs.prop = {
2378
- get: function(){
2379
- var elem = descs.attr.get.call(this);
2380
- if(elem){
2381
- elem = document.getElementById(elem);
2382
- if(elem && descs.propNodeName && !$.nodeName(elem, descs.propNodeName)){
2383
- elem = null;
2384
- }
2385
- }
2386
- return elem || null;
2387
- },
2388
- writeable: false
2389
- };
2390
- };
2391
-
2392
-
2393
- /*
2394
- * Implements datalist element and list attribute
2395
- */
2396
-
2397
- (function(){
2398
- var formsCFG = $.webshims.cfg.forms;
2399
- var listSupport = Modernizr.input.list;
2400
- if(listSupport && !formsCFG.customDatalist){return;}
2401
-
2402
- var initializeDatalist = function(){
2403
-
2404
-
2405
- if(!listSupport){
2406
- webshims.defineNodeNameProperty('datalist', 'options', {
2407
- prop: {
2408
- writeable: false,
2409
- get: function(){
2410
- var elem = this;
2411
- var select = $('select', elem);
2412
- var options;
2413
- if(select[0]){
2414
- options = select[0].options;
2415
- } else {
2416
- options = $('option', elem).get();
2417
- if(options.length){
2418
- webshims.warn('you should wrap your option-elements for a datalist in a select element to support IE and other old browsers.');
2419
- }
2420
- }
2421
- return options;
2422
- }
2423
- }
2424
- });
2425
- }
2426
-
2427
- var inputListProto = {
2428
- //override autocomplete
2429
- autocomplete: {
2430
- attr: {
2431
- get: function(){
2432
- var elem = this;
2433
- var data = $.data(elem, 'datalistWidget');
2434
- if(data){
2435
- return data._autocomplete;
2436
- }
2437
- return ('autocomplete' in elem) ? elem.autocomplete : elem.getAttribute('autocomplete');
2438
- },
2439
- set: function(value){
2440
- var elem = this;
2441
- var data = $.data(elem, 'datalistWidget');
2442
- if(data){
2443
- data._autocomplete = value;
2444
- if(value == 'off'){
2445
- data.hideList();
2446
- }
2447
- } else {
2448
- if('autocomplete' in elem){
2449
- elem.autocomplete = value;
2450
- } else {
2451
- elem.setAttribute('autocomplete', value);
2452
- }
2453
- }
2454
- }
2455
- }
2456
- }
2457
- };
2458
-
2459
- // if(formsCFG.customDatalist && (!listSupport || !('selectedOption') in $('<input />')[0])){
2460
- // //currently not supported x-browser (FF4 has not implemented and is not polyfilled )
2461
- // inputListProto.selectedOption = {
2462
- // prop: {
2463
- // writeable: false,
2464
- // get: function(){
2465
- // var elem = this;
2466
- // var list = $.prop(elem, 'list');
2467
- // var ret = null;
2468
- // var value, options;
2469
- // if(!list){return ret;}
2470
- // value = $.prop(elem, 'value');
2471
- // if(!value){return ret;}
2472
- // options = $.prop(list, 'options');
2473
- // if(!options.length){return ret;}
2474
- // $.each(options, function(i, option){
2475
- // if(value == $.prop(option, 'value')){
2476
- // ret = option;
2477
- // return false;
2478
- // }
2479
- // });
2480
- // return ret;
2481
- // }
2482
- // }
2483
- // };
2484
- // }
2485
-
2486
- if(!listSupport){
2487
- inputListProto['list'] = {
2488
- attr: {
2489
- get: function(){
2490
- var val = webshims.contentAttr(this, 'list');
2491
- return (val == null) ? undefined : val;
2492
- },
2493
- set: function(value){
2494
- var elem = this;
2495
- webshims.contentAttr(elem, 'list', value);
2496
- webshims.objectCreate(shadowListProto, undefined, {input: elem, id: value, datalist: $.prop(elem, 'list')});
2497
- }
2498
- },
2499
- initAttr: true,
2500
- reflect: true,
2501
- propType: 'element',
2502
- propNodeName: 'datalist'
2503
- };
2504
- } else {
2505
- //options only return options, if option-elements are rooted: but this makes this part of HTML5 less backwards compatible
2506
- if(!($('<datalist><select><option></option></select></datalist>').prop('options') || []).length ){
2507
- webshims.defineNodeNameProperty('datalist', 'options', {
2508
- prop: {
2509
- writeable: false,
2510
- get: function(){
2511
- var options = this.options || [];
2512
- if(!options.length){
2513
- var elem = this;
2514
- var select = $('select', elem);
2515
- if(select[0] && select[0].options && select[0].options.length){
2516
- options = select[0].options;
2517
- }
2518
- }
2519
- return options;
2520
- }
2521
- }
2522
- });
2523
- }
2524
- inputListProto['list'] = {
2525
- attr: {
2526
- get: function(){
2527
- var val = webshims.contentAttr(this, 'list');
2528
- if(val != null){
2529
- this.removeAttribute('list');
2530
- } else {
2531
- val = $.data(this, 'datalistListAttr');
2532
- }
2533
-
2534
- return (val == null) ? undefined : val;
2535
- },
2536
- set: function(value){
2537
- var elem = this;
2538
- $.data(elem, 'datalistListAttr', value);
2539
- webshims.objectCreate(shadowListProto, undefined, {input: elem, id: value, datalist: $.prop(elem, 'list')});
2540
- }
2541
- },
2542
- initAttr: true,
2543
- reflect: true,
2544
- propType: 'element',
2545
- propNodeName: 'datalist'
2546
- };
2547
- }
2548
-
2549
-
2550
- webshims.defineNodeNameProperties('input', inputListProto);
2551
-
2552
- if($.event.customEvent){
2553
- $.event.customEvent.updateDatalist = true;
2554
- $.event.customEvent.updateInput = true;
2555
- $.event.customEvent.datalistselect = true;
2556
- }
2557
- webshims.addReady(function(context, contextElem){
2558
- contextElem
2559
- .filter('datalist > select, datalist, datalist > option, datalist > select > option')
2560
- .closest('datalist')
2561
- .triggerHandler('updateDatalist')
2562
- ;
2563
-
2564
- });
2565
-
2566
-
2567
- };
2568
-
2569
-
2570
- /*
2571
- * ShadowList
2572
- */
2573
- var listidIndex = 0;
2574
-
2575
- var noDatalistSupport = {
2576
- submit: 1,
2577
- button: 1,
2578
- reset: 1,
2579
- hidden: 1,
2580
-
2581
- //ToDo
2582
- range: 1,
2583
- date: 1
2584
- };
2585
- var globStoredOptions = {};
2586
- var getStoredOptions = function(name){
2587
- if(!name){return [];}
2588
- if(globStoredOptions[name]){
2589
- return globStoredOptions[name];
2590
- }
2591
- var data;
2592
- try {
2593
- data = JSON.parse(localStorage.getItem('storedDatalistOptions'+name));
2594
- } catch(e){}
2595
- globStoredOptions[name] = data || [];
2596
- return data || [];
2597
- };
2598
- var storeOptions = function(name, val){
2599
- if(!name){return;}
2600
- val = val || [];
2601
- try {
2602
- localStorage.setItem( 'storedDatalistOptions'+name, JSON.stringify(val) );
2603
- } catch(e){}
2604
- };
2605
-
2606
- var getText = function(elem){
2607
- return (elem.textContent || elem.innerText || $.text([ elem ]) || '');
2608
- };
2609
-
2610
- var shadowListProto = {
2611
- _create: function(opts){
2612
-
2613
- if(noDatalistSupport[$.prop(opts.input, 'type')]){return;}
2614
- var datalist = opts.datalist;
2615
- var data = $.data(opts.input, 'datalistWidget');
2616
- if(datalist && data && data.datalist !== datalist){
2617
- data.datalist = datalist;
2618
- data.id = opts.id;
2619
-
2620
- data.shadowList.prop('className', 'datalist-polyfill '+ (data.datalist.className || '') + ' '+ data.datalist.id +'-shadowdom');
2621
- if(formsCFG.positionDatalist){
2622
- data.shadowList.insertAfter(opts.input);
2623
- } else {
2624
- data.shadowList.appendTo('body');
2625
- }
2626
- $(data.datalist)
2627
- .off('updateDatalist.datalistWidget')
2628
- .on('updateDatalist.datalistWidget', $.proxy(data, '_resetListCached'))
2629
- ;
2630
- data._resetListCached();
2631
- return;
2632
- } else if(!datalist){
2633
- if(data){
2634
- data.destroy();
2635
- }
2636
- return;
2637
- } else if(data && data.datalist === datalist){
2638
- return;
2639
- }
2640
- listidIndex++;
2641
- var that = this;
2642
- this.hideList = $.proxy(that, 'hideList');
2643
- this.timedHide = function(){
2644
- clearTimeout(that.hideTimer);
2645
- that.hideTimer = setTimeout(that.hideList, 9);
2646
- };
2647
- this.datalist = datalist;
2648
- this.id = opts.id;
2649
- this.hasViewableData = true;
2650
- this._autocomplete = $.attr(opts.input, 'autocomplete');
2651
- $.data(opts.input, 'datalistWidget', this);
2652
- this.shadowList = $('<div class="datalist-polyfill '+ (this.datalist.className || '') + ' '+ this.datalist.id +'-shadowdom' +'" />');
2653
-
2654
- if(formsCFG.positionDatalist || $(opts.input).hasClass('position-datalist')){
2655
- this.shadowList.insertAfter(opts.input);
2656
- } else {
2657
- this.shadowList.appendTo('body');
2658
- }
2659
-
2660
- this.index = -1;
2661
- this.input = opts.input;
2662
- this.arrayOptions = [];
2663
-
2664
- this.shadowList
2665
- .delegate('li', 'mouseenter.datalistWidget mousedown.datalistWidget click.datalistWidget', function(e){
2666
- var items = $('li:not(.hidden-item)', that.shadowList);
2667
- var select = (e.type == 'mousedown' || e.type == 'click');
2668
- that.markItem(items.index(e.currentTarget), select, items);
2669
- if(e.type == 'click'){
2670
- that.hideList();
2671
- if(formsCFG.customDatalist){
2672
- $(opts.input).trigger('datalistselect');
2673
- }
2674
- }
2675
- return (e.type != 'mousedown');
2676
- })
2677
- .on('focusout', this.timedHide)
2678
- ;
2679
-
2680
- opts.input.setAttribute('autocomplete', 'off');
2681
-
2682
- $(opts.input)
2683
- .attr({
2684
- //role: 'combobox',
2685
- 'aria-haspopup': 'true'
2686
- })
2687
- .on({
2688
- 'input.datalistWidget': function(){
2689
- if(!that.triggeredByDatalist){
2690
- that.changedValue = false;
2691
- that.showHideOptions();
2692
- }
2693
- },
2694
- 'keydown.datalistWidget': function(e){
2695
- var keyCode = e.keyCode;
2696
- var activeItem;
2697
- var items;
2698
- if(keyCode == 40 && !that.showList()){
2699
- that.markItem(that.index + 1, true);
2700
- return false;
2701
- }
2702
-
2703
- if(!that.isListVisible){return;}
2704
-
2705
-
2706
- if(keyCode == 38){
2707
- that.markItem(that.index - 1, true);
2708
- return false;
2709
- }
2710
- if(!e.shiftKey && (keyCode == 33 || keyCode == 36)){
2711
- that.markItem(0, true);
2712
- return false;
2713
- }
2714
- if(!e.shiftKey && (keyCode == 34 || keyCode == 35)){
2715
- items = $('li:not(.hidden-item)', that.shadowList);
2716
- that.markItem(items.length - 1, true, items);
2717
- return false;
2718
- }
2719
- if(keyCode == 13 || keyCode == 27){
2720
- if (keyCode == 13){
2721
- activeItem = $('li.active-item:not(.hidden-item)', that.shadowList);
2722
- that.changeValue( $('li.active-item:not(.hidden-item)', that.shadowList) );
2723
- }
2724
- that.hideList();
2725
- if(formsCFG.customDatalist && activeItem && activeItem[0]){
2726
- $(opts.input).trigger('datalistselect');
2727
- }
2728
- return false;
2729
- }
2730
- },
2731
- 'focus.datalistWidget': function(){
2732
- if($(this).hasClass('list-focus')){
2733
- that.showList();
2734
- }
2735
- },
2736
- 'mousedown.datalistWidget': function(){
2737
- if($(this).is(':focus')){
2738
- that.showList();
2739
- }
2740
- },
2741
- 'blur.datalistWidget': this.timedHide
2742
- })
2743
- ;
2744
-
2745
-
2746
- $(this.datalist)
2747
- .off('updateDatalist.datalistWidget')
2748
- .on('updateDatalist.datalistWidget', $.proxy(this, '_resetListCached'))
2749
- ;
2750
-
2751
- this._resetListCached();
2752
-
2753
- if(opts.input.form && (opts.input.name || opts.input.id)){
2754
- $(opts.input.form).on('submit.datalistWidget'+opts.input.id, function(){
2755
- if(!$(opts.input).hasClass('no-datalist-cache') && that._autocomplete != 'off'){
2756
- var val = $.prop(opts.input, 'value');
2757
- var name = (opts.input.name || opts.input.id) + $.prop(opts.input, 'type');
2758
- if(!that.storedOptions){
2759
- that.storedOptions = getStoredOptions( name );
2760
- }
2761
- if(val && that.storedOptions.indexOf(val) == -1){
2762
- that.storedOptions.push(val);
2763
- storeOptions(name, that.storedOptions );
2764
- }
2765
- }
2766
- });
2767
- }
2768
- $(window).on('unload.datalist'+this.id+' beforeunload.datalist'+this.id, function(){
2769
- that.destroy();
2770
- });
2771
- },
2772
- destroy: function(){
2773
- var autocomplete = $.attr(this.input, 'autocomplete');
2774
- $(this.input)
2775
- .off('.datalistWidget')
2776
- .removeData('datalistWidget')
2777
- ;
2778
- this.shadowList.remove();
2779
- $(document).off('.datalist'+this.id);
2780
- $(window).off('.datalist'+this.id);
2781
- if(this.input.form && this.input.id){
2782
- $(this.input.form).off('submit.datalistWidget'+this.input.id);
2783
- }
2784
- this.input.removeAttribute('aria-haspopup');
2785
- if(autocomplete === undefined){
2786
- this.input.removeAttribute('autocomplete');
2787
- } else {
2788
- $(this.input).attr('autocomplete', autocomplete);
2789
- }
2790
- },
2791
- _resetListCached: function(e){
2792
- var that = this;
2793
- var forceShow;
2794
- this.needsUpdate = true;
2795
- this.lastUpdatedValue = false;
2796
- this.lastUnfoundValue = '';
2797
-
2798
- if(!this.updateTimer){
2799
- if(window.QUnit || (forceShow = (e && document.activeElement == that.input))){
2800
- that.updateListOptions(forceShow);
2801
- } else {
2802
- webshims.ready('WINDOWLOAD', function(){
2803
- that.updateTimer = setTimeout(function(){
2804
- that.updateListOptions();
2805
- that = null;
2806
- listidIndex = 1;
2807
- }, 200 + (100 * listidIndex));
2808
- });
2809
- }
2810
- }
2811
- },
2812
- maskHTML: function(str){
2813
- return str.replace(/</g, '&lt;').replace(/>/g, '&gt;');
2814
- },
2815
- updateListOptions: function(_forceShow){
2816
- this.needsUpdate = false;
2817
- clearTimeout(this.updateTimer);
2818
- this.updateTimer = false;
2819
- this.shadowList
2820
- .css({
2821
- fontSize: $.css(this.input, 'fontSize'),
2822
- fontFamily: $.css(this.input, 'fontFamily')
2823
- })
2824
- ;
2825
- this.searchStart = formsCFG.customDatalist && $(this.input).hasClass('search-start');
2826
-
2827
- var list = [];
2828
-
2829
- var values = [];
2830
- var allOptions = [];
2831
- var rElem, rItem, rOptions, rI, rLen, item;
2832
- for(rOptions = $.prop(this.datalist, 'options'), rI = 0, rLen = rOptions.length; rI < rLen; rI++){
2833
- rElem = rOptions[rI];
2834
- if(rElem.disabled){return;}
2835
- rItem = {
2836
- value: $(rElem).val() || '',
2837
- text: $.trim($.attr(rElem, 'label') || getText(rElem)),
2838
- className: rElem.className || '',
2839
- style: $.attr(rElem, 'style') || ''
2840
- };
2841
- if(!rItem.text){
2842
- rItem.text = rItem.value;
2843
- } else if(rItem.text != rItem.value){
2844
- rItem.className += ' different-label-value';
2845
- }
2846
- values[rI] = rItem.value;
2847
- allOptions[rI] = rItem;
2848
- }
2849
-
2850
- if(!this.storedOptions){
2851
- this.storedOptions = ($(this.input).hasClass('no-datalist-cache') || this._autocomplete == 'off') ? [] : getStoredOptions((this.input.name || this.input.id) + $.prop(this.input, 'type'));
2852
- }
2853
-
2854
- this.storedOptions.forEach(function(val, i){
2855
- if(values.indexOf(val) == -1){
2856
- allOptions.push({value: val, text: val, className: 'stored-suggest', style: ''});
2857
- }
2858
- });
2859
-
2860
- for(rI = 0, rLen = allOptions.length; rI < rLen; rI++){
2861
- item = allOptions[rI];
2862
- 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>';
2863
- }
2864
-
2865
- this.arrayOptions = allOptions;
2866
- this.shadowList.html('<div class="datalist-outer-box"><div class="datalist-box"><ul role="list">'+ list.join("\n") +'</ul></div></div>');
2867
-
2868
- if($.fn.bgIframe){
2869
- this.shadowList.bgIframe();
2870
- }
2871
-
2872
- if(_forceShow || this.isListVisible){
2873
- this.showHideOptions();
2874
- }
2875
- },
2876
- showHideOptions: function(_fromShowList){
2877
- var value = $.prop(this.input, 'value').toLowerCase();
2878
- //first check prevent infinite loop, second creates simple lazy optimization
2879
- if(value === this.lastUpdatedValue || (this.lastUnfoundValue && value.indexOf(this.lastUnfoundValue) === 0)){
2880
- return;
2881
- }
2882
-
2883
- this.lastUpdatedValue = value;
2884
- var found = false;
2885
- var startSearch = this.searchStart;
2886
- var lis = $('li', this.shadowList);
2887
- if(value){
2888
- this.arrayOptions.forEach(function(item, i){
2889
- var search;
2890
- if(!('lowerText' in item)){
2891
- if(item.text != item.value){
2892
- item.lowerText = item.value.toLowerCase() + item.text.toLowerCase();
2893
- } else {
2894
- item.lowerText = item.text.toLowerCase();
2895
- }
2896
- }
2897
- search = item.lowerText.indexOf(value);
2898
- search = startSearch ? !search : search !== -1;
2899
- if(search){
2900
- $(lis[i]).removeClass('hidden-item');
2901
- found = true;
2902
- } else {
2903
- $(lis[i]).addClass('hidden-item');
2904
- }
2905
- });
2906
- } else if(lis.length) {
2907
- lis.removeClass('hidden-item');
2908
- found = true;
2909
- }
2910
-
2911
- this.hasViewableData = found;
2912
- if(!_fromShowList && found){
2913
- this.showList();
2914
- }
2915
- if(!found){
2916
- this.lastUnfoundValue = value;
2917
- this.hideList();
2918
- }
2919
- },
2920
- setPos: function(){
2921
- this.shadowList.css({marginTop: 0, marginLeft: 0, marginRight: 0, marginBottom: 0});
2922
- var css = (formsCFG.positionDatalist) ? $(this.input).position() : webshims.getRelOffset(this.shadowList, this.input);
2923
- css.top += $(this.input).outerHeight();
2924
- css.width = $(this.input).outerWidth() - (parseInt(this.shadowList.css('borderLeftWidth'), 10) || 0) - (parseInt(this.shadowList.css('borderRightWidth'), 10) || 0);
2925
- this.shadowList.css({marginTop: '', marginLeft: '', marginRight: '', marginBottom: ''}).css(css);
2926
- return css;
2927
- },
2928
- showList: function(){
2929
- if(this.isListVisible){return false;}
2930
- if(this.needsUpdate){
2931
- this.updateListOptions();
2932
- }
2933
- this.showHideOptions(true);
2934
- if(!this.hasViewableData){return false;}
2935
- this.isListVisible = true;
2936
- var that = this;
2937
-
2938
- that.setPos();
2939
- that.shadowList.addClass('datalist-visible').find('li.active-item').removeClass('active-item');
2940
-
2941
- $(window).unbind('.datalist'+that.id);
2942
- $(document)
2943
- .off('.datalist'+that.id)
2944
- .on('mousedown.datalist'+that.id +' focusin.datalist'+that.id, function(e){
2945
- if(e.target === that.input || that.shadowList[0] === e.target || $.contains( that.shadowList[0], e.target )){
2946
- clearTimeout(that.hideTimer);
2947
- setTimeout(function(){
2948
- clearTimeout(that.hideTimer);
2949
- }, 9);
2950
- } else {
2951
- that.timedHide();
2952
- }
2953
- })
2954
- .on('updateshadowdom.datalist'+that.id, function(){
2955
- that.setPos();
2956
- })
2957
- ;
2958
- return true;
2959
- },
2960
- hideList: function(){
2961
- if(!this.isListVisible){return false;}
2962
- var that = this;
2963
- var triggerChange = function(e){
2964
- if(that.changedValue){
2965
- $(that.input).trigger('change');
2966
- }
2967
- that.changedValue = false;
2968
- };
2969
-
2970
- that.shadowList.removeClass('datalist-visible list-item-active');
2971
- that.index = -1;
2972
- that.isListVisible = false;
2973
- if(that.changedValue){
2974
- that.triggeredByDatalist = true;
2975
- webshims.triggerInlineForm && webshims.triggerInlineForm(that.input, 'input');
2976
- if($(that.input).is(':focus')){
2977
- $(that.input).one('blur', triggerChange);
2978
- } else {
2979
- triggerChange();
2980
- }
2981
- that.triggeredByDatalist = false;
2982
- }
2983
- $(document).unbind('.datalist'+that.id);
2984
- $(window)
2985
- .off('.datalist'+that.id)
2986
- .one('resize.datalist'+that.id, function(){
2987
- that.shadowList.css({top: 0, left: 0});
2988
- })
2989
- ;
2990
- return true;
2991
- },
2992
- scrollIntoView: function(elem){
2993
- var ul = $('ul', this.shadowList);
2994
- var div = $('div.datalist-box', this.shadowList);
2995
- var elemPos = elem.position();
2996
- var containerHeight;
2997
- elemPos.top -= (parseInt(ul.css('paddingTop'), 10) || 0) + (parseInt(ul.css('marginTop'), 10) || 0) + (parseInt(ul.css('borderTopWidth'), 10) || 0);
2998
- if(elemPos.top < 0){
2999
- div.scrollTop( div.scrollTop() + elemPos.top - 2);
3000
- return;
3001
- }
3002
- elemPos.top += elem.outerHeight();
3003
- containerHeight = div.height();
3004
- if(elemPos.top > containerHeight){
3005
- div.scrollTop( div.scrollTop() + (elemPos.top - containerHeight) + 2);
3006
- }
3007
- },
3008
- changeValue: function(activeItem){
3009
- if(!activeItem[0]){return;}
3010
- var newValue = $('span.option-value', activeItem).text();
3011
- var oldValue = $.prop(this.input, 'value');
3012
- if(newValue != oldValue){
3013
- $(this.input)
3014
- .prop('value', newValue)
3015
- .triggerHandler('updateInput')
3016
- ;
3017
- this.changedValue = true;
3018
- }
3019
- },
3020
- markItem: function(index, doValue, items){
3021
- var activeItem;
3022
- var goesUp;
3023
-
3024
- items = items || $('li:not(.hidden-item)', this.shadowList);
3025
- if(!items.length){return;}
3026
- if(index < 0){
3027
- index = items.length - 1;
3028
- } else if(index >= items.length){
3029
- index = 0;
3030
- }
3031
- items.removeClass('active-item');
3032
- this.shadowList.addClass('list-item-active');
3033
- activeItem = items.filter(':eq('+ index +')').addClass('active-item');
3034
-
3035
- if(doValue){
3036
- this.changeValue(activeItem);
3037
- this.scrollIntoView(activeItem);
3038
- }
3039
- this.index = index;
3040
- }
3041
- };
3042
-
3043
- //init datalist update
3044
- initializeDatalist();
3045
- })();
3046
-
3047
1966
  });