webshims-rails 1.10.3 → 1.10.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +8 -8
  2. data/lib/webshims-rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/webshims/polyfiller.js +96 -73
  4. data/vendor/assets/javascripts/webshims/shims/color-picker.js +2415 -0
  5. data/vendor/assets/javascripts/webshims/shims/combos/1.js +248 -745
  6. data/vendor/assets/javascripts/webshims/shims/combos/10.js +771 -1206
  7. data/vendor/assets/javascripts/webshims/shims/combos/11.js +679 -1201
  8. data/vendor/assets/javascripts/webshims/shims/combos/12.js +46 -65
  9. data/vendor/assets/javascripts/webshims/shims/combos/13.js +45 -64
  10. data/vendor/assets/javascripts/webshims/shims/combos/14.js +94 -7
  11. data/vendor/assets/javascripts/webshims/shims/combos/15.js +557 -1189
  12. data/vendor/assets/javascripts/webshims/shims/combos/16.js +598 -1249
  13. data/vendor/assets/javascripts/webshims/shims/combos/17.js +697 -1208
  14. data/vendor/assets/javascripts/webshims/shims/combos/18.js +697 -1208
  15. data/vendor/assets/javascripts/webshims/shims/combos/19.js +145 -78
  16. data/vendor/assets/javascripts/webshims/shims/combos/2.js +472 -1280
  17. data/vendor/assets/javascripts/webshims/shims/combos/20.js +144 -77
  18. data/vendor/assets/javascripts/webshims/shims/combos/21.js +14 -15
  19. data/vendor/assets/javascripts/webshims/shims/combos/22.js +2 -2
  20. data/vendor/assets/javascripts/webshims/shims/combos/23.js +45 -64
  21. data/vendor/assets/javascripts/webshims/shims/combos/24.js +848 -0
  22. data/vendor/assets/javascripts/webshims/shims/combos/25.js +4373 -0
  23. data/vendor/assets/javascripts/webshims/shims/combos/26.js +1516 -0
  24. data/vendor/assets/javascripts/webshims/shims/combos/27.js +884 -0
  25. data/vendor/assets/javascripts/webshims/shims/combos/28.js +2067 -0
  26. data/vendor/assets/javascripts/webshims/shims/combos/29.js +1156 -0
  27. data/vendor/assets/javascripts/webshims/shims/combos/3.js +313 -700
  28. data/vendor/assets/javascripts/webshims/shims/combos/30.js +1868 -0
  29. data/vendor/assets/javascripts/webshims/shims/combos/31.js +1663 -0
  30. data/vendor/assets/javascripts/webshims/shims/combos/4.js +111 -20
  31. data/vendor/assets/javascripts/webshims/shims/combos/5.js +747 -1321
  32. data/vendor/assets/javascripts/webshims/shims/combos/6.js +837 -1809
  33. data/vendor/assets/javascripts/webshims/shims/combos/7.js +435 -1239
  34. data/vendor/assets/javascripts/webshims/shims/combos/8.js +360 -766
  35. data/vendor/assets/javascripts/webshims/shims/combos/9.js +843 -1676
  36. data/vendor/assets/javascripts/webshims/shims/details.js +1 -1
  37. data/vendor/assets/javascripts/webshims/shims/dom-extend.js +90 -3
  38. data/vendor/assets/javascripts/webshims/shims/filereader.js +386 -0
  39. data/vendor/assets/javascripts/webshims/shims/form-core.js +201 -680
  40. data/vendor/assets/javascripts/webshims/shims/form-datalist-lazy.js +418 -0
  41. data/vendor/assets/javascripts/webshims/shims/form-datalist.js +69 -467
  42. data/vendor/assets/javascripts/webshims/shims/form-message.js +21 -17
  43. data/vendor/assets/javascripts/webshims/shims/form-native-extend.js +19 -82
  44. data/vendor/assets/javascripts/webshims/shims/form-number-date-api.js +17 -6
  45. data/vendor/assets/javascripts/webshims/shims/form-number-date-ui.js +570 -1185
  46. data/vendor/assets/javascripts/webshims/shims/form-shim-extend.js +181 -28
  47. data/vendor/assets/javascripts/webshims/shims/form-validation.js +599 -0
  48. data/vendor/assets/javascripts/webshims/{extras/custom-validity.js → shims/form-validators.js} +33 -38
  49. data/vendor/assets/javascripts/webshims/shims/forms-picker.js +865 -0
  50. data/vendor/assets/javascripts/webshims/shims/geolocation.js +2 -2
  51. data/vendor/assets/javascripts/webshims/shims/i18n/formcfg-de.txt +37 -34
  52. data/vendor/assets/javascripts/webshims/shims/i18n/formcfg-en.txt +88 -48
  53. data/vendor/assets/javascripts/webshims/shims/i18n/formcfg-lt.js +74 -0
  54. data/vendor/assets/javascripts/webshims/shims/jpicker/ChangeLog.txt +121 -0
  55. data/vendor/assets/javascripts/webshims/shims/jpicker/ReadMe.txt +47 -0
  56. data/vendor/assets/javascripts/webshims/shims/jpicker/images/AlphaBar.png +0 -0
  57. data/vendor/assets/javascripts/webshims/shims/jpicker/images/Bars.png +0 -0
  58. data/vendor/assets/javascripts/webshims/shims/jpicker/images/Maps.png +0 -0
  59. data/vendor/assets/javascripts/webshims/shims/jpicker/images/NoColor.png +0 -0
  60. data/vendor/assets/javascripts/webshims/shims/jpicker/images/Thumbs.db +0 -0
  61. data/vendor/assets/javascripts/webshims/shims/jpicker/images/bar-opacity.png +0 -0
  62. data/vendor/assets/javascripts/webshims/shims/jpicker/images/map-opacity.png +0 -0
  63. data/vendor/assets/javascripts/webshims/shims/jpicker/images/mappoint.gif +0 -0
  64. data/vendor/assets/javascripts/webshims/shims/jpicker/images/picker.gif +0 -0
  65. data/vendor/assets/javascripts/webshims/shims/jpicker/images/preview-opacity.png +0 -0
  66. data/vendor/assets/javascripts/webshims/shims/jpicker/images/rangearrows.gif +0 -0
  67. data/vendor/assets/javascripts/webshims/shims/jpicker/jpicker.css +257 -0
  68. data/vendor/assets/javascripts/webshims/shims/json-storage.js +4 -4
  69. data/vendor/assets/javascripts/webshims/shims/mediaelement-core.js +44 -63
  70. data/vendor/assets/javascripts/webshims/shims/mediaelement-jaris.js +10 -11
  71. data/vendor/assets/javascripts/webshims/shims/mediaelement-native-fix.js +2 -1
  72. data/vendor/assets/javascripts/webshims/shims/mediaelement-yt.js +5 -3
  73. data/vendor/assets/javascripts/webshims/shims/range-ui.js +110 -17
  74. data/vendor/assets/javascripts/webshims/shims/styles/forms.png +0 -0
  75. data/vendor/assets/javascripts/webshims/shims/styles/range-track.png +0 -0
  76. data/vendor/assets/javascripts/webshims/shims/styles/scss/shim.scss +104 -21
  77. data/vendor/assets/javascripts/webshims/shims/styles/shim.css +90 -16
  78. data/vendor/assets/javascripts/webshims/shims/styles/vertical-range.png +0 -0
  79. data/vendor/assets/javascripts/webshims/shims/swf/filereader.swf +0 -0
  80. data/vendor/assets/javascripts/webshims/shims/swfmini.js +1 -1
  81. data/vendor/assets/javascripts/webshims/shims/track-ui.js +35 -3
  82. data/vendor/assets/javascripts/webshims/shims/track.js +1 -1
  83. metadata +33 -3
@@ -1,11 +1,11 @@
1
- jQuery.webshims.register('form-native-extend', function($, webshims, window, doc, undefined, options){
1
+ webshims.register('form-native-extend', function($, webshims, window, doc, undefined, options){
2
2
  "use strict";
3
3
  var Modernizr = window.Modernizr;
4
4
  var modernizrInputTypes = Modernizr.inputtypes;
5
5
  if(!Modernizr.formvalidation || webshims.bugs.bustedValidity){return;}
6
6
  var typeModels = webshims.inputTypes;
7
+ var runTest = false;
7
8
  var validityRules = {};
8
-
9
9
  var updateValidity = (function(){
10
10
  var timer;
11
11
  var getValidity = function(){
@@ -14,13 +14,14 @@ jQuery.webshims.register('form-native-extend', function($, webshims, window, doc
14
14
  var update = function(){
15
15
  $('input').each(getValidity);
16
16
  };
17
- return function(fast){
17
+ return function(){
18
18
  clearTimeout(timer);
19
19
  timer = setTimeout(update, 9);
20
20
  };
21
21
  })();
22
22
  webshims.addInputType = function(type, obj){
23
23
  typeModels[type] = obj;
24
+ runTest = true;
24
25
  //update validity of all implemented input types
25
26
  if($.isDOMReady && Modernizr.formvalidation && !webshims.bugs.bustedValidity){
26
27
  updateValidity();
@@ -44,26 +45,16 @@ jQuery.webshims.register('form-native-extend', function($, webshims, window, doc
44
45
  return ret;
45
46
  });
46
47
 
47
- var overrideNativeMessages = options.overrideMessages;
48
-
49
- var overrideValidity = (!modernizrInputTypes.number || !modernizrInputTypes.time || !modernizrInputTypes.range || overrideNativeMessages);
48
+ var formsExtModule = webshims.modules['form-number-date-api'];
49
+ var overrideValidity = formsExtModule.loaded && !formsExtModule.test();
50
50
  var validityProps = ['customError','typeMismatch','rangeUnderflow','rangeOverflow','stepMismatch','tooLong','patternMismatch','valueMissing','valid'];
51
51
 
52
- var validityChanger = (overrideNativeMessages)? ['value', 'checked'] : ['value'];
52
+ var validityChanger = ['value'];
53
53
  var validityElements = [];
54
54
  var testValidity = function(elem, init){
55
- if(!elem){return;}
55
+ if(!elem && !runTest){return;}
56
56
  var type = (elem.getAttribute && elem.getAttribute('type') || elem.type || '').toLowerCase();
57
-
58
- if(!overrideNativeMessages && !typeModels[type]){
59
- return;
60
- }
61
-
62
- if(overrideNativeMessages && !init && type == 'radio' && elem.name){
63
- $(doc.getElementsByName( elem.name )).each(function(){
64
- $.prop(this, 'validity');
65
- });
66
- } else {
57
+ if(typeModels[type]){
67
58
  $.prop(elem, 'validity');
68
59
  }
69
60
  };
@@ -77,9 +68,7 @@ jQuery.webshims.register('form-native-extend', function($, webshims, window, doc
77
68
  var elem = (name == 'input') ? $(this).getNativeElement()[0] : this;
78
69
  desc.prop._supvalue.call(elem, error);
79
70
 
80
- if(webshims.bugs.validationMessage){
81
- webshims.data(elem, 'customvalidationMessage', error);
82
- }
71
+
83
72
  if(overrideValidity){
84
73
  webshims.data(elem, 'hasCustomError', !!(error));
85
74
  testValidity(elem);
@@ -91,18 +80,13 @@ jQuery.webshims.register('form-native-extend', function($, webshims, window, doc
91
80
  });
92
81
 
93
82
 
94
- if(overrideValidity || overrideNativeMessages){
83
+ if(overrideValidity){
95
84
  validityChanger.push('min');
96
85
  validityChanger.push('max');
97
86
  validityChanger.push('step');
98
87
  validityElements.push('input');
99
88
  }
100
- if(overrideNativeMessages){
101
- validityChanger.push('required');
102
- validityChanger.push('pattern');
103
- validityElements.push('select');
104
- validityElements.push('textarea');
105
- }
89
+
106
90
 
107
91
  if(overrideValidity){
108
92
  var stopValidity;
@@ -156,7 +140,7 @@ jQuery.webshims.register('form-native-extend', function($, webshims, window, doc
156
140
 
157
141
  $.each(validityRules, function(rule, fn){
158
142
  validityState[rule] = fn(jElm, val, cache, validityState);
159
- if( validityState[rule] && (validityState.valid || !setCustomMessage) && (overrideNativeMessages || (typeModels[cache.type] && typeModels[cache.type].mismatch)) ) {
143
+ if( validityState[rule] && (validityState.valid || !setCustomMessage) && ((typeModels[cache.type] && typeModels[cache.type].mismatch)) ) {
160
144
  oldSetCustomValidity[nodeName].call(elem, webshims.createValidationMessage(elem, rule));
161
145
  validityState.valid = false;
162
146
  setCustomMessage = true;
@@ -165,13 +149,6 @@ jQuery.webshims.register('form-native-extend', function($, webshims, window, doc
165
149
  if(validityState.valid){
166
150
  oldSetCustomValidity[nodeName].call(elem, '');
167
151
  webshims.data(elem, 'hasCustomError', false);
168
- } else if(overrideNativeMessages && !setCustomMessage && !customError){
169
- $.each(validityState, function(name, prop){
170
- if(name !== 'valid' && prop){
171
- oldSetCustomValidity[nodeName].call(elem, webshims.createValidationMessage(elem, name));
172
- return false;
173
- }
174
- });
175
152
  }
176
153
  return validityState;
177
154
  },
@@ -191,27 +168,12 @@ jQuery.webshims.register('form-native-extend', function($, webshims, window, doc
191
168
  var inputThrottle;
192
169
  var testPassValidity = function(e){
193
170
  if(!('form' in e.target)){return;}
194
- var form = e.target.form;
195
171
  clearTimeout(inputThrottle);
196
172
  testValidity(e.target);
197
- if(form && overrideNativeMessages){
198
- $('input', form).each(function(){
199
- if(this.type == 'password'){
200
- testValidity(this);
201
- }
202
- });
203
- }
204
173
  };
205
174
 
206
175
  doc.addEventListener('change', testPassValidity, true);
207
176
 
208
- if(overrideNativeMessages){
209
- doc.addEventListener('blur', testPassValidity, true);
210
- doc.addEventListener('keydown', function(e){
211
- if(e.keyCode != 13){return;}
212
- testPassValidity(e);
213
- }, true);
214
- }
215
177
 
216
178
  doc.addEventListener('input', function(e){
217
179
  clearTimeout(inputThrottle);
@@ -224,46 +186,21 @@ jQuery.webshims.register('form-native-extend', function($, webshims, window, doc
224
186
  var validityElementsSel = validityElements.join(',');
225
187
 
226
188
  webshims.addReady(function(context, elem){
227
- $(validityElementsSel, context).add(elem.filter(validityElementsSel)).each(function(){
228
- $.prop(this, 'validity');
229
- });
189
+ if(runTest){
190
+ $(validityElementsSel, context).add(elem.filter(validityElementsSel)).each(function(){
191
+ testValidity(this);
192
+ });
193
+ }
230
194
  });
231
195
 
232
196
 
233
- if(overrideNativeMessages){
234
- webshims.ready('DOM form-message', function(){
235
- webshims.activeLang({
236
- register: 'form-core',
237
- callback: function(){
238
- $('input, select, textarea')
239
- .getNativeElement()
240
- .each(function(){
241
- if(webshims.data(this, 'hasCustomError')){return;}
242
- var elem = this;
243
- var validity = $.prop(elem, 'validity') || {valid: true};
244
- var nodeName;
245
- if(validity.valid){return;}
246
- nodeName = (elem.nodeName || '').toLowerCase();
247
- $.each(validity, function(name, prop){
248
- if(name !== 'valid' && prop){
249
- oldSetCustomValidity[nodeName].call(elem, webshims.createValidationMessage(elem, name));
250
- return false;
251
- }
252
- });
253
- })
254
- ;
255
- }
256
- });
257
- });
258
- }
259
-
260
197
  } //end: overrideValidity
261
198
 
262
199
  webshims.defineNodeNameProperty('input', 'type', {
263
200
  prop: {
264
201
  get: function(){
265
202
  var elem = this;
266
- var type = (elem.getAttribute('type') || '').toLowerCase();
203
+ var type = (elem.getAttribute && elem.getAttribute('type') || '').toLowerCase();
267
204
  return (webshims.inputTypes[type]) ? type : elem.type;
268
205
  }
269
206
  }
@@ -271,9 +208,11 @@ jQuery.webshims.register('form-native-extend', function($, webshims, window, doc
271
208
 
272
209
 
273
210
  });
274
- jQuery.webshims.register('form-number-date-api', function($, webshims, window, document, undefined){
211
+ webshims.register('form-number-date-api', function($, webshims, window, document, undefined, options){
275
212
  "use strict";
276
-
213
+ if(!webshims.addInputType){
214
+ webshims.error("you can not call forms-ext feature after calling forms feature. call both at once instead: $.webshims.polyfill('forms forms-ext')");
215
+ }
277
216
 
278
217
  if(!webshims.getStep){
279
218
  webshims.getStep = function(elem, type){
@@ -543,7 +482,14 @@ jQuery.webshims.register('form-number-date-api', function($, webshims, window, d
543
482
  minDefault: 0,
544
483
  maxDefault: 100
545
484
  },
546
-
485
+ color: {
486
+ mismatch: (function(){
487
+ var cReg = /^\u0023[a-f0-9]{6}$/;
488
+ return function(val){
489
+ return (!val || val.length != 7 || !(cReg.test(val)));
490
+ };
491
+ })()
492
+ },
547
493
  date: {
548
494
  mismatch: function(val){
549
495
  if(!val || !val.split || !(/\d$/.test(val))){return true;}
@@ -741,20 +687,22 @@ jQuery.webshims.register('form-number-date-api', function($, webshims, window, d
741
687
  // }
742
688
  };
743
689
 
744
- if(typeBugs || !supportsType('range') || !supportsType('time')){
690
+ if(typeBugs || !supportsType('range') || !supportsType('time') || !supportsType('month')){
745
691
  typeProtos.range = $.extend({}, typeProtos.number, typeProtos.range);
746
692
  typeProtos.time = $.extend({}, typeProtos.date, typeProtos.time);
747
693
  typeProtos.month = $.extend({}, typeProtos.date, typeProtos.month);
748
694
  // typeProtos['datetime-local'] = $.extend({}, typeProtos.date, typeProtos.time, typeProtos['datetime-local']);
749
695
  }
750
696
 
697
+
698
+
751
699
  //'datetime-local'
752
- ['number', 'month', 'range', 'date', 'time'].forEach(function(type){
700
+ ['number', 'month', 'range', 'date', 'time', 'color'].forEach(function(type){
753
701
  if(typeBugs || !supportsType(type)){
754
702
  webshims.addInputType(type, typeProtos[type]);
755
703
  }
756
704
  });
757
-
705
+
758
706
  if($('<input />').prop('labels') == null){
759
707
  webshims.defineNodeNamesProperty('button, input, keygen, meter, output, progress, select, textarea', 'labels', {
760
708
  prop: {
@@ -824,6 +772,7 @@ jQuery.webshims.register('form-number-date-api', function($, webshims, window, d
824
772
  var oVal = val;
825
773
  var thumbStyle = {};
826
774
  var rangeStyle = {};
775
+
827
776
  if(!_noNormalize && parseFloat(val, 10) != val){
828
777
  val = o.min + ((o.max - o.min) / 2);
829
778
  }
@@ -833,6 +782,7 @@ jQuery.webshims.register('form-number-date-api', function($, webshims, window, d
833
782
  }
834
783
  left = 100 * ((val - o.min) / (o.max - o.min));
835
784
 
785
+ if(this._init && val == o.value && oVal == val){return;}
836
786
  this.options.value = val;
837
787
  this.thumb.stop();
838
788
  this.range.stop();
@@ -902,24 +852,30 @@ jQuery.webshims.register('form-number-date-api', function($, webshims, window, d
902
852
  $('.ws-range-ticks', trail).remove();
903
853
 
904
854
 
905
- $(this.orig).jProp('list').find('option').each(function(){
906
- o.options[$.prop(this, 'value')] = $.prop(this, 'label');
855
+ $(this.orig).jProp('list').find('option:not([disabled])').each(function(){
856
+ o.options[$.prop(this, 'value')] = $.prop(this, 'label') || '';
907
857
  });
908
858
 
909
859
  $.each(o.options, function(val, label){
910
860
  if(!isNumber(val) || val < min || val > max){return;}
911
861
  var left = 100 * ((val - min) / (max - min));
912
- var title = o.showLabels ? ' title="'+ label +'"' : '';
862
+ var title = o.showLabels && label ? ' title="'+ label +'"' : '';
913
863
  if(that.vertical){
914
864
  left = Math.abs(left - 100);
915
865
  }
916
- trail.append('<span class="ws-range-ticks"'+ title +' style="'+(that.dirs.left)+': '+left+'%;" />');
866
+
867
+ that.posCenter(
868
+ $('<span class="ws-range-ticks"'+ title +' data-label="'+label+'" style="'+(that.dirs.left)+': '+left+'%;" />').appendTo(trail)
869
+ );
917
870
  });
918
871
  },
919
872
  readonly: function(val){
920
873
  val = !!val;
921
874
  this.options.readonly = val;
922
875
  this.element.attr('aria-readonly', ''+val);
876
+ if(this._init){
877
+ this.updateMetrics();
878
+ }
923
879
  },
924
880
  disabled: function(val){
925
881
  val = !!val;
@@ -929,6 +885,9 @@ jQuery.webshims.register('form-number-date-api', function($, webshims, window, d
929
885
  } else {
930
886
  this.element.attr({tabindex: this.options.tabindex, 'aria-disabled': 'false'});
931
887
  }
888
+ if(this._init){
889
+ this.updateMetrics();
890
+ }
932
891
  },
933
892
  tabindex: function(val){
934
893
  this.options.tabindex = val;
@@ -1008,6 +967,24 @@ jQuery.webshims.register('form-number-date-api', function($, webshims, window, d
1008
967
 
1009
968
  return val;
1010
969
  },
970
+ addRemoveClass: function(cName, add){
971
+ var isIn = this.element.prop('className').indexOf(cName) != -1;
972
+ var action;
973
+ if(!add && isIn){
974
+ action = 'removeClass';
975
+ this.element.removeClass(cName);
976
+ this.updateMetrics();
977
+ } else if(add && !isIn){
978
+ action = 'addClass';
979
+
980
+ }
981
+ if(action){
982
+ this.element[action](cName);
983
+ if(this._init){
984
+ this.updateMetrics();
985
+ }
986
+ }
987
+ },
1011
988
  addBindings: function(){
1012
989
  var leftOffset, widgetUnits, hasFocus;
1013
990
  var that = this;
@@ -1047,25 +1024,36 @@ jQuery.webshims.register('form-number-date-api', function($, webshims, window, d
1047
1024
  that.value(val, false, animate);
1048
1025
  eventTimer.call('input', val);
1049
1026
  }
1027
+ if(e && e.type == 'mousemove'){
1028
+ e.preventDefault();
1029
+ }
1050
1030
  };
1051
-
1052
1031
  var remove = function(e){
1053
1032
  if(e && e.type == 'mouseup'){
1054
1033
  eventTimer.call('input', o.value);
1055
1034
  eventTimer.call('change', o.value);
1056
1035
  }
1057
- that.element.removeClass('ws-active');
1036
+ that.addRemoveClass('ws-active');
1058
1037
  $(document).off('mousemove', setValueFromPos).off('mouseup', remove);
1038
+ $(window).off('blur', removeWin);
1039
+ };
1040
+ var removeWin = function(e){
1041
+ if(e.target == window){remove();}
1059
1042
  };
1060
1043
  var add = function(e){
1044
+ var outerWidth;
1061
1045
  e.preventDefault();
1062
1046
  $(document).off('mousemove', setValueFromPos).off('mouseup', remove);
1047
+ $(window).off('blur', removeWin);
1063
1048
  if(!o.readonly && !o.disabled){
1064
- leftOffset = that.element.focus().addClass('ws-active').offset();
1065
- widgetUnits = that.element[that.dirs.width]();
1049
+ that.element.focus();
1050
+ that.addRemoveClass('ws-active', true);
1051
+ leftOffset = that.element.focus().offset();
1052
+ widgetUnits = that.element[that.dirs.innerWidth]();
1066
1053
  if(!widgetUnits || !leftOffset){return;}
1054
+ outerWidth = that.thumb[that.dirs.outerWidth]();
1067
1055
  leftOffset = leftOffset[that.dirs.pos];
1068
- widgetUnits = 100 / (widgetUnits - ((that.thumb[that.dirs.outerWidth]() || 2) / 2));
1056
+ widgetUnits = 100 / widgetUnits;
1069
1057
  setValueFromPos(e, o.animate);
1070
1058
  $(document)
1071
1059
  .on({
@@ -1073,6 +1061,7 @@ jQuery.webshims.register('form-number-date-api', function($, webshims, window, d
1073
1061
  mousemove: setValueFromPos
1074
1062
  })
1075
1063
  ;
1064
+ $(window).on('blur', removeWin);
1076
1065
  e.stopPropagation();
1077
1066
  }
1078
1067
  };
@@ -1082,18 +1071,20 @@ jQuery.webshims.register('form-number-date-api', function($, webshims, window, d
1082
1071
  if(!o.disabled){
1083
1072
  eventTimer.init('input', o.value);
1084
1073
  eventTimer.init('change', o.value);
1085
- that.element.addClass('ws-focus');
1074
+ that.addRemoveClass('ws-focus', true);
1075
+ that.updateMetrics();
1086
1076
  }
1087
1077
  hasFocus = true;
1088
1078
  },
1089
1079
  blur: function(e){
1090
1080
  that.element.removeClass('ws-focus ws-active');
1081
+ that.updateMetrics();
1091
1082
  hasFocus = false;
1092
1083
  eventTimer.init('input', o.value);
1093
1084
  eventTimer.call('change', o.value);
1094
1085
  },
1095
1086
  keyup: function(){
1096
- that.element.removeClass('ws-active');
1087
+ that.addRemoveClass('ws-active');
1097
1088
  eventTimer.call('input', o.value);
1098
1089
  eventTimer.call('change', o.value);
1099
1090
  },
@@ -1118,7 +1109,7 @@ jQuery.webshims.register('form-number-date-api', function($, webshims, window, d
1118
1109
  step = false;
1119
1110
  }
1120
1111
  if (step) {
1121
- that.element.addClass('ws-active');
1112
+ that.addRemoveClass('ws-active', true);
1122
1113
  eventTimer.call('input', o.value);
1123
1114
  e.preventDefault();
1124
1115
  }
@@ -1140,38 +1131,88 @@ jQuery.webshims.register('form-number-date-api', function($, webshims, window, d
1140
1131
  this.thumb.on({
1141
1132
  mousedown: add
1142
1133
  });
1134
+ $(function(){
1135
+ webshims.ready('dom-support', function(){
1136
+ that.element.onWSOff('updateshadowdom', function(){
1137
+ that.updateMetrics();
1138
+ });
1139
+ });
1140
+ if(!$.fn.onWSOff){
1141
+ webshims._polyfill(['dom-support']);
1142
+ }
1143
+ });
1144
+ },
1145
+ posCenter: function(elem, outerWidth){
1146
+ var temp;
1147
+ if(this.options.calcCenter && (!this._init || this.element[0].offsetWidth)){
1148
+ if(!elem){
1149
+ elem = this.thumb;
1150
+ }
1151
+ if(!outerWidth){
1152
+ outerWidth = elem[this.dirs.outerWidth]();
1153
+ }
1154
+ outerWidth = outerWidth / -2;
1155
+ elem.css(this.dirs.marginLeft, outerWidth);
1156
+
1157
+ if(this.options.calcTrail && elem[0] == this.thumb[0]){
1158
+ temp = this.element[this.dirs.innerHeight]();
1159
+ elem.css(this.dirs.marginTop, (elem[this.dirs.outerHeight]() - temp) / -2);
1160
+ this.range.css(this.dirs.marginTop, (this.range[this.dirs.outerHeight]() - temp) / -2 );
1161
+ outerWidth *= -1;
1162
+ this.trail
1163
+ .css(this.dirs.left, outerWidth)
1164
+ .css(this.dirs.right, outerWidth)
1165
+ ;
1166
+ }
1167
+ }
1143
1168
  },
1144
1169
  updateMetrics: function(){
1145
1170
  var width = this.element.innerWidth();
1146
1171
  this.vertical = (width && this.element.innerHeight() - width > 10);
1147
1172
 
1148
1173
  this.dirs = this.vertical ?
1149
- {mouse: 'pageY', pos: 'top', min: 'max', max: 'min', left: 'top', width: 'height', outerWidth: 'outerHeight'} :
1150
- {mouse: 'pageX', pos: 'left', min: 'min', max: 'max', left: 'left', width: 'width', outerWidth: 'outerWidth'}
1174
+ {mouse: 'pageY', pos: 'top', min: 'max', max: 'min', left: 'top', right: 'bottom', width: 'height', innerWidth: 'innerHeight', innerHeight: 'innerWidth', outerWidth: 'outerHeight', outerHeight: 'outerWidth', marginTop: 'marginLeft', marginLeft: 'marginTop'} :
1175
+ {mouse: 'pageX', pos: 'left', min: 'min', max: 'max', left: 'left', right: 'right', width: 'width', innerWidth: 'innerWidth', innerHeight: 'innerHeight', outerWidth: 'outerWidth', outerHeight: 'outerHeight', marginTop: 'marginTop', marginLeft: 'marginLeft'}
1151
1176
  ;
1152
1177
  this.element
1153
1178
  [this.vertical ? 'addClass' : 'removeClass']('vertical-range')
1154
1179
  [this.vertical ? 'addClass' : 'removeClass']('horizontal-range')
1155
1180
  ;
1181
+ this.posCenter();
1156
1182
  }
1157
1183
  };
1158
1184
 
1159
1185
  $.fn.rangeUI = function(opts){
1160
- opts = $.extend({readonly: false, disabled: false, tabindex: 0, min: 0, step: 1, max: 100, value: 50, input: $.noop, change: $.noop, _change: $.noop, showLabels: true, options: {}}, opts);
1186
+ opts = $.extend({
1187
+ readonly: false,
1188
+ disabled: false,
1189
+ tabindex: 0,
1190
+ min: 0,
1191
+ step: 1,
1192
+ max: 100,
1193
+ value: 50,
1194
+ input: $.noop,
1195
+ change: $.noop,
1196
+ _change: $.noop,
1197
+ showLabels: true,
1198
+ options: {},
1199
+ calcCenter: true,
1200
+ calcTrail: true
1201
+ }, opts);
1161
1202
  return this.each(function(){
1162
- $.webshims.objectCreate(rangeProto, {
1203
+ webshims.objectCreate(rangeProto, {
1163
1204
  element: {
1164
1205
  value: $(this)
1165
1206
  }
1166
1207
  }, opts);
1167
1208
  });
1168
1209
  };
1169
- jQuery.webshims.isReady('range-ui', true);
1210
+ webshims.isReady('range-ui', true);
1170
1211
  })(jQuery);
1171
- jQuery.webshims.register('form-number-date-ui', function($, webshims, window, document, undefined, options){
1212
+ webshims.register('form-number-date-ui', function($, webshims, window, document, undefined, options){
1172
1213
  "use strict";
1173
1214
  var curCfg;
1174
- var formcfg = $.webshims.formcfg;
1215
+ var formcfg = webshims.formcfg;
1175
1216
 
1176
1217
  var stopPropagation = function(e){
1177
1218
  e.stopImmediatePropagation(e);
@@ -1189,7 +1230,7 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1189
1230
  date: {
1190
1231
  _create: function(){
1191
1232
  var obj = {
1192
- splits: [$('<input type="text" class="yy" size="4" maxlength />')[0], $('<input type="text" class="mm" maxlength="2" size="2" />')[0], $('<input type="text" class="dd ws-spin" maxlength="2" size="2" />')[0]]
1233
+ splits: [$('<input type="text" class="yy" size="4" inputmode="numeric" />')[0], $('<input type="text" class="mm" inputmode="numeric" maxlength="2" size="2" />')[0], $('<input type="text" class="dd ws-spin" inputmode="numeric" maxlength="2" size="2" />')[0]]
1193
1234
  };
1194
1235
  obj.elements = [obj.splits[0], $('<span class="ws-input-seperator" />')[0], obj.splits[1], $('<span class="ws-input-seperator" />')[0], obj.splits[2]];
1195
1236
  return obj;
@@ -1215,7 +1256,7 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1215
1256
  month: {
1216
1257
  _create: function(){
1217
1258
  var obj = {
1218
- splits: [$('<input type="text" class="yy" size="4" />')[0], $('<input type="text" class="mm ws-spin" />')[0]]
1259
+ splits: [$('<input type="text" class="yy" inputmode="numeric" size="4" />')[0], $('<input type="text" class="mm ws-spin" />')[0]]
1219
1260
  };
1220
1261
  obj.elements = [obj.splits[0], $('<span class="ws-input-seperator" />')[0], obj.splits[1]];
1221
1262
  return obj;
@@ -1235,6 +1276,23 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1235
1276
  }
1236
1277
  }
1237
1278
  };
1279
+
1280
+ var steps = {
1281
+ number: {
1282
+ step: 1
1283
+ },
1284
+ time: {
1285
+ step: 60
1286
+ },
1287
+ month: {
1288
+ step: 1,
1289
+ start: new Date()
1290
+ },
1291
+ date: {
1292
+ step: 1,
1293
+ start: new Date()
1294
+ }
1295
+ };
1238
1296
  var labelWidth = (function(){
1239
1297
  var getId = function(){
1240
1298
  return webshims.getID(this);
@@ -1259,7 +1317,8 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1259
1317
 
1260
1318
  (function(){
1261
1319
  var monthDigits = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
1262
- formcfg.de = {
1320
+
1321
+ formcfg.de = $.extend(true, {
1263
1322
  numberFormat: {
1264
1323
  ",": ".",
1265
1324
  ".": ","
@@ -1293,9 +1352,9 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1293
1352
  showMonthAfterYear: false,
1294
1353
  yearSuffix: ''
1295
1354
  }
1296
- };
1355
+ }, formcfg.de || {});
1297
1356
 
1298
- formcfg.en = {
1357
+ formcfg.en = $.extend(true, {
1299
1358
  numberFormat: {
1300
1359
  ".": ".",
1301
1360
  ",": ","
@@ -1327,13 +1386,17 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1327
1386
  "showMonthAfterYear": false,
1328
1387
  "yearSuffix": ""
1329
1388
  }
1330
- };
1389
+ }, formcfg['en'] || {});
1390
+ if(!formcfg['en-US']){
1391
+ formcfg['en-US'] = formcfg['en'];
1392
+ }
1393
+ if(!formcfg['']){
1394
+ formcfg[''] = formcfg['en-US'];
1395
+ }
1331
1396
 
1332
- formcfg['en-US'] = formcfg['en-US'] || formcfg['en'];
1333
- formcfg[''] = formcfg[''] || formcfg['en-US'];
1334
1397
  curCfg = formcfg[''];
1335
1398
 
1336
- var createMonthKeys = function(langCfg){
1399
+ var processLangCFG = function(langCfg){
1337
1400
  if(!langCfg.date.monthkeys){
1338
1401
  var create = function(i, name){
1339
1402
  var strNum;
@@ -1349,24 +1412,25 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1349
1412
  $.each(langCfg.date.monthNames, create);
1350
1413
  $.each(langCfg.date.monthNamesShort, create);
1351
1414
  }
1415
+ if(!langCfg.colorSigns){
1416
+ langCfg.colorSigns = '#abcdefABCDEF';
1417
+ }
1352
1418
  };
1353
1419
 
1354
- createMonthKeys(curCfg);
1355
-
1356
- $.webshims.ready('dom-extend', function(){
1357
- $.webshims.activeLang({
1358
- register: 'form-core',
1359
- callback: function(){
1360
- $.each(arguments, function(i, val){
1361
- if(formcfg[val]){
1362
- curCfg = formcfg[val];
1363
- createMonthKeys(curCfg);
1364
- $(document).triggerHandler('wslocalechange');
1365
- return false;
1366
- }
1367
- });
1368
- }
1369
- });
1420
+ processLangCFG(curCfg);
1421
+
1422
+ $.webshims.activeLang({
1423
+ register: 'form-core',
1424
+ callback: function(){
1425
+ $.each(arguments, function(i, val){
1426
+ if(formcfg[val]){
1427
+ curCfg = formcfg[val];
1428
+ processLangCFG(curCfg);
1429
+ $(document).triggerHandler('wslocalechange');
1430
+ return false;
1431
+ }
1432
+ });
1433
+ }
1370
1434
  });
1371
1435
  })();
1372
1436
 
@@ -1386,8 +1450,6 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1386
1450
  return val * 1;
1387
1451
  };
1388
1452
 
1389
- var createOpts = ['step', 'min', 'max', 'readonly', 'title', 'disabled', 'tabindex', 'placeholder', 'value'];
1390
-
1391
1453
 
1392
1454
  var formatVal = {
1393
1455
  number: function(val){
@@ -1426,6 +1488,16 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1426
1488
  }
1427
1489
 
1428
1490
  return val;
1491
+ },
1492
+ color: function(val, opts){
1493
+ var ret = '#000000';
1494
+ if(val){
1495
+ val = val.toLowerCase();
1496
+ if(val.length == 7 && createHelper('color').isValid(val)) {
1497
+ ret = val;
1498
+ }
1499
+ }
1500
+ return ret;
1429
1501
  }
1430
1502
  };
1431
1503
 
@@ -1440,7 +1512,7 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1440
1512
 
1441
1513
  var p = (!opts.splitInput) ? val.trim().split(/[\.\s-\/\\]+/) : val;
1442
1514
 
1443
- if(p.length == 2){
1515
+ if(p.length == 2 && p[0] && p[1]){
1444
1516
  p[0] = curCfg.date.monthkeys[p[0]] || p[0];
1445
1517
  p[1] = curCfg.date.monthkeys[p[1]] || p[1];
1446
1518
  if(p[1].length == 2){
@@ -1470,27 +1542,25 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1470
1542
  ([addZero(val[obj.yy]), addZero(val[obj.mm]), addZero(val[obj.dd])]).join('-') :
1471
1543
  ''
1472
1544
  ;
1473
- }
1474
- };
1475
-
1476
- var steps = {
1477
- number: {
1478
- step: 1
1479
- },
1480
- time: {
1481
- step: 60
1482
1545
  },
1483
- month: {
1484
- step: 1,
1485
- start: new Date()
1486
- },
1487
- date: {
1488
- step: 1,
1489
- start: new Date()
1546
+ color: function(val, opts){
1547
+ var ret = '#000000';
1548
+ if(val){
1549
+ val = val.toLowerCase();
1550
+ if (val.indexOf('#') !== 0) {
1551
+ val = '#' + val;
1552
+ }
1553
+ if(val.length == 4){
1554
+ val = '#' + val.charAt(1) + val.charAt(1) + val.charAt(2) + val.charAt(2) + val.charAt(3) + val.charAt(3);
1555
+ }
1556
+ if(val.length == 7 && createHelper('color').isValid(val)) {
1557
+ ret = val;
1558
+ }
1559
+ }
1560
+ return ret;
1490
1561
  }
1491
1562
  };
1492
1563
 
1493
-
1494
1564
  var placeholderFormat = {
1495
1565
  date: function(val, opts){
1496
1566
  var hintValue = (val || '').split('-');
@@ -1535,6 +1605,9 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1535
1605
  asValue: function(val){
1536
1606
  var type = (typeof val == 'object') ? 'valueAsDate' : 'valueAsNumber';
1537
1607
  return input.prop(type, val).prop('value');
1608
+ },
1609
+ isValid: function(val){
1610
+ return input.prop('value', val).is(':valid') && input.prop('value') == val;
1538
1611
  }
1539
1612
  };
1540
1613
  }
@@ -1544,247 +1617,116 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1544
1617
 
1545
1618
  steps.range = steps.number;
1546
1619
 
1547
-
1548
- var spinBtnProto = {
1620
+ var wsWidgetProto = {
1549
1621
  _create: function(){
1550
- var i;
1622
+ var i, that, timedMirror;
1551
1623
  var o = this.options;
1552
- var helper = createHelper(o.type);
1624
+ var createOpts = this.createOpts;
1625
+
1553
1626
  this.type = o.type;
1554
1627
  this.orig = o.orig;
1555
1628
 
1556
- this.elemHelper = $('<input type="'+ this.type+'" />');
1557
- this.asNumber = helper.asNumber;
1558
- this.asValue = helper.asValue;
1629
+ this.buttonWrapper = $('<span class="input-buttons '+this.type+'-input-buttons"></span>').insertAfter(this.element);
1630
+ this.options.containerElements.push(this.buttonWrapper[0]);
1559
1631
 
1560
- this.buttonWrapper = $('<span class="input-buttons '+this.type+'-input-buttons"><span unselectable="on" class="step-controls"><span class="step-up"></span><span class="step-down"></span></span></span>')
1561
- .insertAfter(this.element)
1562
- ;
1632
+ o.mirrorValidity = o.mirrorValidity && this.orig && Modernizr.formvalidation && !webshims.bugs.bustedValidity;
1563
1633
 
1564
- if(o.splitInput){
1634
+ if(o.splitInput && this._addSplitInputs){
1565
1635
  this._addSplitInputs();
1566
1636
  } else {
1567
1637
  this.inputElements = this.element;
1568
1638
  }
1569
1639
 
1570
- this.options.containerElements.push(this.buttonWrapper[0]);
1571
-
1572
- if(typeof steps[this.type].start == 'object'){
1640
+ if( steps[this.type] && typeof steps[this.type].start == 'object'){
1573
1641
  steps[this.type].start = this.asNumber(steps[this.type].start);
1574
1642
  }
1575
1643
 
1576
-
1577
-
1578
1644
  for(i = 0; i < createOpts.length; i++){
1579
- this[createOpts[i]](o[createOpts[i]]);
1580
- }
1581
-
1582
- this.element.data('wsspinner', this);
1583
-
1584
- this.addBindings();
1585
-
1586
- if(!o.min && typeof o.relMin == 'number'){
1587
- o.min = this.asValue(this.getRelNumber(o.relMin));
1588
- $.prop(this.orig, 'min', o.min);
1645
+ if(o[createOpts[i]] != null){
1646
+ this[createOpts[i]](o[createOpts[i]], o[createOpts[i]]);
1647
+ }
1589
1648
  }
1590
-
1591
- if(!o.max && typeof o.relMax == 'number'){
1592
- o.max = this.asValue(this.getRelNumber(o.relMax));
1593
- $.prop(this.orig, 'max', o.max);
1649
+ if(this.type == 'color'){
1650
+ this.inputElements.prop('maxLength', 7);
1594
1651
  }
1652
+ this.addBindings();
1653
+ $(this.element).data('wsWidget'+o.type, this);
1595
1654
 
1596
1655
  this._init = true;
1597
- },
1598
- _addSplitInputs: function(){
1599
- if(!this.inputElements){
1600
- var create = splitInputs[this.type]._create();
1601
- this.splits = create.splits;
1602
- this.inputElements = $(create.elements).prependTo(this.element).filter('input');
1603
- }
1604
- },
1605
- parseValue: function(){
1606
- var value = this.inputElements.map(function(){
1607
- return $.prop(this, 'value');
1608
- }).get();
1609
- if(!this.options.splitInput){
1610
- value = value[0];
1611
- }
1612
- return parseVal[this.type](value, this.options);
1613
- },
1614
- formatValue: function(val, noSplit){
1615
- return formatVal[this.type](val, noSplit === false ? false : this.options);
1616
- },
1617
- placeholder: function(val){
1618
- var options = this.options;
1619
- options.placeholder = val;
1620
- var placeholder = val;
1621
- if(placeholderFormat[this.type]){
1622
- placeholder = placeholderFormat[this.type](val, this.options);
1623
- }
1624
- if(options.splitInput && typeof placeholder == 'object'){
1625
- $.each(this.splits, function(i, elem){
1626
- $.prop(elem, 'placeholder', placeholder[i]);
1656
+
1657
+ if(o.mirrorValidity){
1658
+ that = this;
1659
+ timedMirror = function(){
1660
+ clearTimeout(timedMirror._timerDealy);
1661
+ timedMirror._timerDealy = setTimeout(timedMirror._wsexec, 9);
1662
+ };
1663
+ timedMirror._wsexec = function(){
1664
+ clearTimeout(timedMirror._timerDealy);
1665
+ that.mirrorValidity(true);
1666
+ };
1667
+
1668
+ timedMirror();
1669
+ $(this.orig).on('change input', function(e){
1670
+ if(e.type == 'input'){
1671
+ timedMirror();
1672
+ } else {
1673
+ timedMirror._wsexec();
1674
+ }
1627
1675
  });
1628
- } else {
1629
- this.element.prop('placeholder', placeholder);
1630
1676
  }
1631
1677
  },
1632
- getRelNumber: function(rel){
1633
- var start = steps[this.type].start || 0;
1634
- if(rel){
1635
- start += rel;
1678
+ mirrorValidity: function(_noTest){
1679
+ //
1680
+ if(this._init && this.options.mirrorValidity){
1681
+ if(!_noTest){
1682
+ $.prop(this.orig, 'validity');
1683
+ }
1684
+ var message = $(this.orig).getErrorMessage();
1685
+ if(message !== this.lastErrorMessage){
1686
+ this.inputElements.prop('setCustomValidity', function(i, val){
1687
+ if(val._supvalue){
1688
+ val._supvalue.call(this, message);
1689
+ }
1690
+ });
1691
+ this.lastErrorMessage = message;
1692
+ }
1636
1693
  }
1637
- return start;
1638
1694
  },
1639
- addZero: addZero,
1640
- _setStartInRange: function(){
1641
- var start = this.getRelNumber(this.options.relDefaultValue);
1642
- if(!isNaN(this.minAsNumber) && start < this.minAsNumber){
1643
- start = this.minAsNumber;
1644
- } else if(!isNaN(this.maxAsNumber) && start > this.maxAsNumber){
1645
- start = this.maxAsNumber;
1646
- }
1647
- this.elemHelper.prop('valueAsNumber', start);
1648
- this.options.defValue = this.elemHelper.prop('value');
1695
+ addBindings: function(){
1696
+ var isFocused;
1649
1697
 
1650
- },
1651
- reorderInputs: function(){
1652
- if(splitInputs[this.type]){
1653
- var element = this.element;
1654
- splitInputs[this.type].sort(element);
1655
- setTimeout(function(){
1656
- var data = webshims.data(element);
1657
- if(data && data.shadowData){
1658
- data.shadowData.shadowFocusElement = element.find('input')[0] || element[0];
1698
+ var that = this;
1699
+ var o = this.options;
1700
+
1701
+ var eventTimer = (function(){
1702
+ var events = {};
1703
+ return {
1704
+ init: function(name, curVal, fn){
1705
+ if(!events[name]){
1706
+ events[name] = {fn: fn};
1707
+ $(that.orig).on(name, function(){
1708
+ events[name].val = $.prop(that.orig, 'value');
1709
+ });
1710
+ }
1711
+ events[name].val = curVal;
1712
+ },
1713
+ call: function(name, val){
1714
+ if(events[name] && events[name].val != val){
1715
+ clearTimeout(events[name].timer);
1716
+ events[name].val = val;
1717
+ events[name].timer = setTimeout(function(){
1718
+ events[name].fn(val, that);
1719
+ }, 9);
1720
+ }
1659
1721
  }
1660
- }, 9);
1661
- }
1662
- },
1663
- value: function(val){
1664
- this.valueAsNumber = this.asNumber(val);
1665
- this.options.value = val;
1666
- if(isNaN(this.valueAsNumber) || (!isNaN(this.minAsNumber) && this.valueAsNumber < this.minAsNumber) || (!isNaN(this.maxAsNumber) && this.valueAsNumber > this.maxAsNumber)){
1667
- this._setStartInRange();
1668
- } else {
1669
- this.elemHelper.prop('value', val);
1670
- this.options.defValue = "";
1671
- }
1722
+ };
1723
+ })();
1724
+ var initChangeEvents = function(){
1725
+ eventTimer.init('input', $.prop(that.orig, 'value'), that.options.input);
1726
+ eventTimer.init('change', $.prop(that.orig, 'value'), that.options.change);
1727
+ };
1672
1728
 
1673
- val = formatVal[this.type](val, this.options);
1674
- if(this.options.splitInput){
1675
-
1676
- $.each(this.splits, function(i, elem){
1677
- $.prop(elem, 'value', val[i]);
1678
- });
1679
- } else {
1680
- this.element.prop('value', val);
1681
- }
1682
-
1683
- this._propertyChange('value');
1684
- },
1685
- initDataList: function(){
1686
- var listTimer;
1687
- var that = this;
1688
- var updateList = function(){
1689
- $(that.orig)
1690
- .jProp('list')
1691
- .off('updateDatalist', updateList)
1692
- .on('updateDatalist', updateList)
1693
- ;
1694
- clearTimeout(listTimer);
1695
- listTimer = setTimeout(function(){
1696
- if(that.list){
1697
- that.list();
1698
- }
1699
- }, 9);
1700
-
1701
- };
1702
-
1703
- $(this.orig).onTrigger('listdatalistchange', updateList);
1704
- },
1705
- getOptions: function(){
1706
- var options = {};
1707
- var datalist = $(this.orig).jProp('list');
1708
- datalist.find('option').each(function(){
1709
- options[$.prop(this, 'value')] = $.prop(this, 'label');
1710
- });
1711
- return [options, datalist.data('label')];
1712
- },
1713
- list: function(val){
1714
- if(this.type == 'number' || this.type == 'time'){
1715
- this.element.attr('list', $.attr(this.orig, 'list'));
1716
- }
1717
- this.options.list = val;
1718
- this._propertyChange('list');
1719
- },
1720
- _propertyChange: $.noop,
1721
- tabindex: function(val){
1722
- this.options.tabindex = val;
1723
- this.inputElements.prop('tabindex', this.options.tabindex);
1724
- },
1725
- title: function(val){
1726
- this.options.title = val;
1727
- this.element.prop('title', this.options.title);
1728
- },
1729
-
1730
- min: function(val){
1731
- this.elemHelper.prop('min', val);
1732
- this.minAsNumber = this.asNumber(val);
1733
- if(this.valueAsNumber != null && isNaN(this.valueAsNumber)){
1734
- this._setStartInRange();
1735
- }
1736
- this.options.min = val;
1737
- this._propertyChange('min');
1738
- },
1739
- max: function(val){
1740
- this.elemHelper.prop('max', val);
1741
- this.maxAsNumber = this.asNumber(val);
1742
- if(this.valueAsNumber != null && isNaN(this.valueAsNumber)){
1743
- this._setStartInRange();
1744
- }
1745
- this.options.max = val;
1746
- this._propertyChange('max');
1747
- },
1748
- step: function(val){
1749
- var defStep = steps[this.type];
1750
- this.options.step = val;
1751
- this.elemHelper.prop('step', retDefault(val, defStep.step));
1752
- },
1753
- addBindings: function(){
1754
- var isFocused;
1755
-
1756
- var that = this;
1757
- var o = this.options;
1758
-
1759
- var eventTimer = (function(){
1760
- var events = {};
1761
- return {
1762
- init: function(name, curVal, fn){
1763
- if(!events[name]){
1764
- events[name] = {fn: fn};
1765
- $(that.orig).on(name, function(){
1766
- events[name].val = $.prop(that.orig, 'value');
1767
- });
1768
- }
1769
- events[name].val = curVal;
1770
- },
1771
- call: function(name, val){
1772
- if(events[name] && events[name].val != val){
1773
- clearTimeout(events[name].timer);
1774
- events[name].val = val;
1775
- events[name].timer = setTimeout(function(){
1776
- events[name].fn(val, that);
1777
- }, 9);
1778
- }
1779
- }
1780
- };
1781
- })();
1782
- var initChangeEvents = function(){
1783
- eventTimer.init('input', $.prop(that.orig, 'value'), that.options.input);
1784
- eventTimer.init('change', $.prop(that.orig, 'value'), that.options.change);
1785
- };
1786
-
1787
- var step = {};
1729
+ var step = {};
1788
1730
 
1789
1731
  var preventBlur = function(e){
1790
1732
  if(preventBlur.prevent){
@@ -1801,6 +1743,9 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1801
1743
  var val;
1802
1744
  clearTimeout(timer);
1803
1745
  val = that.parseValue();
1746
+ if(that.type == 'color'){
1747
+ that.inputElements.val(val);
1748
+ }
1804
1749
  $.prop(that.orig, 'value', val);
1805
1750
  eventTimer.call('input', val);
1806
1751
  if(!e || e.type != 'wsupdatevalue'){
@@ -1837,6 +1782,7 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1837
1782
  ;
1838
1783
  setTimeout(function(){
1839
1784
  if(that.popover){
1785
+ that.popover.element.on('wspopoverhide', onBlur);
1840
1786
  $('> *', that.popover.element)
1841
1787
  .on({
1842
1788
  'focusin': onFocus,
@@ -1917,7 +1863,7 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1917
1863
  e.preventDefault();
1918
1864
  }
1919
1865
  }
1920
- }
1866
+ };
1921
1867
  })()
1922
1868
  };
1923
1869
  var mouseDownInit = function(){
@@ -1941,28 +1887,6 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1941
1887
  };
1942
1888
  })();
1943
1889
 
1944
- ['stepUp', 'stepDown'].forEach(function(name){
1945
- step[name] = function(factor){
1946
- if(!o.disabled && !o.readonly){
1947
- if(!isFocused){
1948
- mouseDownInit();
1949
- }
1950
- var ret = false;
1951
- if (!factor) {
1952
- factor = 1;
1953
- }
1954
- try {
1955
- that.elemHelper[name](factor);
1956
- ret = that.elemHelper.prop('value');
1957
- that.value(ret);
1958
- eventTimer.call('input', ret);
1959
- } catch (er) {}
1960
- return ret;
1961
- }
1962
- };
1963
- });
1964
-
1965
-
1966
1890
 
1967
1891
  this.buttonWrapper.on('mousedown', mouseDownInit);
1968
1892
 
@@ -1979,960 +1903,415 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
1979
1903
 
1980
1904
  this.inputElements.on(elementEvts);
1981
1905
 
1982
- if(!o.noSpinbtn){
1983
- spinEvents[$.fn.mwheelIntent ? 'mwheelIntent' : 'mousewheel'] = function(e, delta){
1984
- if(delta && isFocused && !o.disabled){
1985
- step[delta > 0 ? 'stepUp' : 'stepDown']();
1986
- e.preventDefault();
1987
- }
1988
- };
1989
- spinEvents.keydown = function(e){
1990
- if(o.list || e.isDefaultPrevented() || $.attr(this, 'list')){return;}
1991
- var stepped = true;
1992
- var code = e.keyCode;
1993
- if (code == 38) {
1994
- step.stepUp();
1995
- } else if (code == 40) {
1996
- step.stepDown();
1906
+ if(steps[this.type]){
1907
+ ['stepUp', 'stepDown'].forEach(function(name){
1908
+ step[name] = function(factor){
1909
+ if(!o.disabled && !o.readonly){
1910
+ if(!isFocused){
1911
+ mouseDownInit();
1912
+ }
1913
+ var ret = false;
1914
+ if (!factor) {
1915
+ factor = 1;
1916
+ }
1917
+ try {
1918
+ that.elemHelper[name](factor);
1919
+ ret = that.elemHelper.prop('value');
1920
+ that.value(ret);
1921
+ eventTimer.call('input', ret);
1922
+ } catch (er) {}
1923
+ return ret;
1924
+ }
1925
+ };
1926
+ });
1927
+ if(!o.noSpinbtn){
1928
+ spinEvents[$.fn.mwheelIntent ? 'mwheelIntent' : 'mousewheel'] = function(e, delta){
1929
+ if(delta && isFocused && !o.disabled){
1930
+ step[delta > 0 ? 'stepUp' : 'stepDown']();
1931
+ e.preventDefault();
1932
+ }
1933
+ };
1934
+ spinEvents.keydown = function(e){
1935
+ if(o.list || e.isDefaultPrevented() || $.attr(this, 'list')){return;}
1936
+ var stepped = true;
1937
+ var code = e.keyCode;
1938
+ if (code == 38) {
1939
+ step.stepUp();
1940
+ } else if (code == 40) {
1941
+ step.stepDown();
1942
+ } else {
1943
+ stepped = false;
1944
+ }
1945
+ if(stepped){
1946
+ e.preventDefault();
1947
+ }
1948
+ };
1949
+
1950
+ spinElement.attr({'autocomplete': 'off', role: 'spinbutton'}).on(spinEvents);
1951
+ }
1952
+ $(this.buttonWrapper)
1953
+ .on('mousepressstart mousepressend', '.step-up, .step-down', mousePress)
1954
+ .on('mousedown mousepress', '.step-up', function(e){
1955
+ step.stepUp();
1956
+ })
1957
+ .on('mousedown mousepress', '.step-down', function(e){
1958
+ step.stepDown();
1959
+ })
1960
+ ;
1961
+ }
1962
+ if(this.type != 'color'){
1963
+ (function(){
1964
+ var localeChange ;
1965
+ if(!o.splitInput){
1966
+ localeChange = function(){
1967
+ if(o.value){
1968
+ that.value(o.value);
1969
+ }
1970
+
1971
+ if(placeholderFormat[that.type] && o.placeholder){
1972
+ that.placeholder(o.placeholder);
1973
+ }
1974
+ };
1997
1975
  } else {
1998
- stepped = false;
1999
- }
2000
- if(stepped){
2001
- e.preventDefault();
1976
+ localeChange = function(){
1977
+ that.reorderInputs();
1978
+ };
1979
+ that.reorderInputs();
2002
1980
  }
2003
- };
2004
-
2005
- spinElement.attr({'autocomplete': 'off', role: 'spinbutton'}).on(spinEvents);
1981
+ $(that.orig).onWSOff('wslocalechange', localeChange);
1982
+ })();
2006
1983
  }
2007
1984
 
1985
+ initChangeEvents();
1986
+ },
1987
+ value: function(val){
1988
+ if(!this._init || val !== this.options.value){
1989
+ this.element.val(this.formatValue(val));
1990
+ this.options.value = val;
1991
+ this._propertyChange('value');
1992
+ this.mirrorValidity();
1993
+ }
2008
1994
 
2009
- if(!o.splitInput){
2010
- $(document).on('wslocalechange',function(){
2011
- if(o.value){
2012
- that.value(o.value);
2013
- }
2014
-
2015
- if(placeholderFormat[that.type] && o.placeholder){
2016
- that.placeholder(o.placeholder);
2017
- }
1995
+ },
1996
+ required: function(val, boolVal){
1997
+ this.inputElements.attr({'aria-required': ''+boolVal});
1998
+ this.mirrorValidity();
1999
+ },
2000
+ parseValue: function(){
2001
+ var value = this.inputElements.map(function(){
2002
+ return $.prop(this, 'value');
2003
+ }).get();
2004
+ if(!this.options.splitInput){
2005
+ value = value[0];
2006
+ }
2007
+ return parseVal[this.type](value, this.options);
2008
+ },
2009
+ formatValue: function(val, noSplit){
2010
+ return formatVal[this.type](val, noSplit === false ? false : this.options);
2011
+ },
2012
+ createOpts: ['readonly', 'title', 'disabled', 'tabindex', 'placeholder', 'value', 'required'],
2013
+ placeholder: function(val){
2014
+ var options = this.options;
2015
+ options.placeholder = val;
2016
+ var placeholder = val;
2017
+ if(placeholderFormat[this.type]){
2018
+ placeholder = placeholderFormat[this.type](val, this.options);
2019
+ }
2020
+ if(options.splitInput && typeof placeholder == 'object'){
2021
+ $.each(this.splits, function(i, elem){
2022
+ $.prop(elem, 'placeholder', placeholder[i]);
2018
2023
  });
2019
2024
  } else {
2020
- $(document).onTrigger('wslocalechange',function(){
2021
- that.reorderInputs();
2022
- });
2025
+ this.element.prop('placeholder', placeholder);
2023
2026
  }
2024
-
2025
- $('.step-up', this.buttonWrapper)
2026
- .on({
2027
- 'mousepressstart mousepressend': mousePress,
2028
- 'mousedown mousepress': function(e){
2029
- step.stepUp();
2030
- }
2031
- })
2032
- ;
2033
- $('.step-down', this.buttonWrapper)
2034
- .on({
2035
- 'mousepressstart mousepressend': mousePress,
2036
- 'mousedown mousepress': function(e){
2037
- step.stepDown();
2027
+ },
2028
+ initDataList: function(){
2029
+ var listTimer;
2030
+ var that = this;
2031
+ var updateList = function(){
2032
+ $(that.orig)
2033
+ .jProp('list')
2034
+ .off('updateDatalist', updateList)
2035
+ .on('updateDatalist', updateList)
2036
+ ;
2037
+ clearTimeout(listTimer);
2038
+ listTimer = setTimeout(function(){
2039
+ if(that.list){
2040
+ that.list();
2038
2041
  }
2039
- })
2040
- ;
2041
- initChangeEvents();
2042
+ }, 9);
2043
+
2044
+ };
2045
+
2046
+ $(this.orig).onTrigger('listdatalistchange', updateList);
2047
+ },
2048
+ getOptions: function(){
2049
+ var options = {};
2050
+ var datalist = $(this.orig).jProp('list');
2051
+ datalist.find('option').each(function(){
2052
+ options[$.prop(this, 'value')] = $.prop(this, 'label');
2053
+ });
2054
+ return [options, datalist.data('label')];
2055
+ },
2056
+ list: function(val){
2057
+ if(this.type == 'number' || this.type == 'time'){
2058
+ this.element.attr('list', $.attr(this.orig, 'list'));
2059
+ }
2060
+ this.options.list = val;
2061
+ this._propertyChange('list');
2062
+ },
2063
+ _propertyChange: $.noop,
2064
+ tabindex: function(val){
2065
+ this.options.tabindex = val;
2066
+ this.inputElements.prop('tabindex', this.options.tabindex);
2067
+ $('button', this.buttonWrapper).prop('tabindex', this.options.tabindex);
2068
+ },
2069
+ title: function(val){
2070
+ if(!val && this.orig && $.attr(this.orig, 'title') == null){
2071
+ val = null;
2072
+ }
2073
+ this.options.title = val;
2074
+ if(val == null){
2075
+ this.inputElements.removeAttr('title');
2076
+ } else {
2077
+ this.inputElements.prop('title', this.options.title);
2078
+ }
2042
2079
  }
2043
2080
  };
2044
2081
 
2082
+
2045
2083
  ['readonly', 'disabled'].forEach(function(name){
2046
- spinBtnProto[name] = function(val){
2047
- if(this.options[name] != val || !this._init){
2048
- this.options[name] = !!val;
2049
- if(name == 'readonly' && this.options.noInput){
2050
- this.element
2051
- .prop(name, true)
2052
- .attr({'aria-readonly': this.options[name]})
2053
- ;
2054
- } else {
2055
- this.element.prop(name, this.options[name]);
2056
- }
2084
+ var isDisabled = name == 'disabled';
2085
+ wsWidgetProto[name] = function(val, boolVal){
2086
+ if(this.options[name] != boolVal || !this._init){
2087
+ this.options[name] = !!boolVal;
2088
+ this.inputElements.prop(name, this.options[name]);
2057
2089
  this.buttonWrapper[this.options[name] ? 'addClass' : 'removeClass']('ws-'+name);
2090
+ if(isDisabled){
2091
+ $('button', this.buttonWrapper).prop('disabled', this.options[name]);
2092
+ }
2058
2093
  }
2059
2094
  };
2060
2095
  });
2061
2096
 
2062
-
2063
- $.fn.spinbtnUI = function(opts){
2064
- opts = $.extend({
2065
- monthNames: 'monthNames',
2066
- size: 1,
2067
- startView: 0
2068
- }, opts);
2069
- return this.each(function(){
2070
- $.webshims.objectCreate(spinBtnProto, {
2071
- element: {
2072
- value: $(this)
2073
- }
2074
- }, opts);
2075
- });
2076
- };
2077
- })();
2078
-
2079
- (function(){
2080
- var picker = {};
2081
- var disable = {
2082
-
2083
- };
2084
-
2085
- var getDateArray = function(date){
2086
- var ret = [date.getFullYear(), addZero(date.getMonth() + 1), addZero(date.getDate())];
2087
- ret.month = ret[0]+'-'+ret[1];
2088
- ret.date = ret[0]+'-'+ret[1]+'-'+ret[2];
2089
- return ret;
2090
- };
2091
- var today = getDateArray(new Date());
2092
-
2093
- var _setFocus = function(element, _noFocus){
2094
- var setFocus, that;
2095
- element = $(element || this.activeButton);
2096
- this.activeButton.attr({tabindex: '-1', 'aria-selected': 'false'});
2097
- this.activeButton = element.attr({tabindex: '0', 'aria-selected': 'true'});
2098
- this.index = this.buttons.index(this.activeButton[0]);
2099
-
2100
- clearTimeout(this.timer);
2101
-
2102
- if(!this.popover.openedByFocus && !_noFocus){
2103
- that = this;
2104
- setFocus = function(noTrigger){
2105
- clearTimeout(that.timer);
2106
- that.timer = setTimeout(function(){
2107
- if(element[0]){
2108
- element[0].focus();
2109
- if(noTrigger !== true && !element.is(':focus')){
2110
- setFocus(true);
2111
- }
2112
- }
2113
- }, that.popover.isVisible ? 99 : 360);
2114
- };
2115
- this.popover.activateElement(element);
2116
- setFocus();
2117
- }
2118
-
2119
- };
2120
-
2121
- var _initialFocus = function(){
2122
- var sel;
2123
- if(this.popover.navedInitFocus){
2124
- sel = this.popover.navedInitFocus.sel || this.popover.navedInitFocus;
2125
- if((!this.activeButton || !this.activeButton[0]) && this.buttons[sel]){
2126
- this.activeButton = this.buttons[sel]();
2127
- } else if(sel){
2128
- this.activeButton = $(sel, this.element);
2129
- }
2130
-
2131
- if(!this.activeButton[0] && this.popover.navedInitFocus.alt){
2132
- this.activeButton = this.buttons[this.popover.navedInitFocus.alt]();
2133
- }
2134
- }
2135
-
2136
- if(!this.activeButton || !this.activeButton[0]){
2137
- this.activeButton = this.buttons.filter('.checked-value');
2138
- }
2139
-
2140
- if(!this.activeButton[0]){
2141
- this.activeButton = this.buttons.filter('.this-value');
2142
- }
2143
- if(!this.activeButton[0]){
2144
- this.activeButton = this.buttons.eq(0);
2145
- }
2146
-
2147
- this.setFocus(this.activeButton, this.opts.noFocus);
2148
- };
2149
-
2150
-
2151
- webshims.ListBox = function (element, popover, opts){
2152
- this.element = $('ul', element);
2153
- this.popover = popover;
2154
- this.opts = opts || {};
2155
- this.buttons = $('button:not(:disabled)', this.element);
2156
-
2157
-
2158
- this.ons(this);
2159
- this._initialFocus();
2160
- };
2161
-
2162
- webshims.ListBox.prototype = {
2163
- setFocus: _setFocus,
2164
- _initialFocus: _initialFocus,
2165
- prev: function(){
2166
- var index = this.index - 1;
2167
- if(index < 0){
2168
- if(this.opts.prev){
2169
- this.popover.navedInitFocus = 'last';
2170
- this.popover.actionFn(this.opts.prev);
2171
- this.popover.navedInitFocus = false;
2172
- }
2173
- } else {
2174
- this.setFocus(this.buttons.eq(index));
2175
- }
2176
- },
2177
- next: function(){
2178
- var index = this.index + 1;
2179
- if(index >= this.buttons.length){
2180
- if(this.opts.next){
2181
- this.popover.navedInitFocus = 'first';
2182
- this.popover.actionFn(this.opts.next);
2183
- this.popover.navedInitFocus = false;
2184
- }
2185
- } else {
2186
- this.setFocus(this.buttons.eq(index));
2187
- }
2188
- },
2189
- ons: function(that){
2190
- this.element
2191
- .on({
2192
- 'keydown': function(e){
2193
- var handled;
2194
- var key = e.keyCode;
2195
- if(e.ctrlKey){return;}
2196
- if(key == 36 || key == 33){
2197
- that.setFocus(that.buttons.eq(0));
2198
- handled = true;
2199
- } else if(key == 34 || key == 35){
2200
- that.setFocus(that.buttons.eq(that.buttons.length - 1));
2201
- handled = true;
2202
- } else if(key == 38 || key == 37){
2203
- that.prev();
2204
- handled = true;
2205
- } else if(key == 40 || key == 39){
2206
- that.next();
2207
- handled = true;
2208
- }
2209
- if(handled){
2210
- return false;
2211
- }
2212
- }
2213
- })
2214
- ;
2215
- }
2216
- };
2217
-
2218
- webshims.Grid = function (element, popover, opts){
2219
- this.element = $('tbody', element);
2220
- this.popover = popover;
2221
- this.opts = opts || {};
2222
- this.buttons = $('button:not(:disabled,.othermonth)', this.element);
2223
-
2224
- this.ons(this);
2225
-
2226
- this._initialFocus();
2227
- if(this.popover.openedByFocus){
2228
- this.popover.activeElement = this.activeButton;
2229
- }
2230
- };
2231
-
2232
-
2233
-
2234
- webshims.Grid.prototype = {
2235
- setFocus: _setFocus,
2236
- _initialFocus: _initialFocus,
2237
-
2238
- first: function(){
2239
- this.setFocus(this.buttons.eq(0));
2240
- },
2241
- last: function(){
2242
- this.setFocus(this.buttons.eq(this.buttons.length - 1));
2243
- },
2244
- upPage: function(){
2245
- $('.ws-picker-header > button:not(:disabled)', this.popover.element).trigger('click');
2246
- },
2247
- downPage: function(){
2248
- this.activeButton.filter(':not([data-action="changeInput"])').trigger('click');
2249
- },
2250
- ons: function(that){
2251
- this.element
2252
- .on({
2253
- 'keydown': function(e){
2254
- var handled;
2255
- var key = e.keyCode;
2256
-
2257
- if(e.shiftKey){return;}
2258
-
2259
- if((e.ctrlKey && key == 40)){
2260
- handled = 'downPage';
2261
- } else if((e.ctrlKey && key == 38)){
2262
- handled = 'upPage';
2263
- } else if(key == 33 || (e.ctrlKey && key == 37)){
2264
- handled = 'prevPage';
2265
- } else if(key == 34 || (e.ctrlKey && key == 39)){
2266
- handled = 'nextPage';
2267
- } else if(e.keyCode == 36 || e.keyCode == 33){
2268
- handled = 'first';
2269
- } else if(e.keyCode == 35){
2270
- handled = 'last';
2271
- } else if(e.keyCode == 38){
2272
- handled = 'up';
2273
- } else if(e.keyCode == 37){
2274
- handled = 'prev';
2275
- } else if(e.keyCode == 40){
2276
- handled = 'down';
2277
- } else if(e.keyCode == 39){
2278
- handled = 'next';
2279
- }
2280
- if(handled){
2281
- that[handled]();
2282
- return false;
2283
- }
2284
- }
2285
- })
2286
- ;
2287
- }
2288
- };
2289
- $.each({
2290
- prevPage: {get: 'last', action: 'prev'},
2291
- nextPage: {get: 'first', action: 'next'}
2292
- }, function(name, val){
2293
- webshims.Grid.prototype[name] = function(){
2294
- if(this.opts[val.action]){
2295
- this.popover.navedInitFocus = {
2296
- sel: 'button[data-id="'+ this.activeButton.attr('data-id') +'"]:not(:disabled,.othermonth)',
2297
- alt: val.get
2298
- };
2299
- this.popover.actionFn(this.opts[val.action]);
2300
- this.popover.navedInitFocus = false;
2301
- }
2302
- };
2303
- });
2304
-
2305
- $.each({
2306
- up: {traverse: 'prevAll', get: 'last', action: 'prev', reverse: true},
2307
- down: {traverse: 'nextAll', get: 'first', action: 'next'}
2308
- }, function(name, val){
2309
- webshims.Grid.prototype[name] = function(){
2310
- var cellIndex = this.activeButton.closest('td').prop('cellIndex');
2311
- var sel = 'td:nth-child('+(cellIndex + 1)+') button:not(:disabled,.othermonth)';
2312
- var button = this.activeButton.closest('tr')[val.traverse]();
2313
-
2314
- if(val.reverse){
2315
- button = $(button.get().reverse());
2316
- }
2317
- button = button.find(sel)[val.get]();
2318
-
2319
- if(!button[0]){
2320
- if(this.opts[val.action]){
2321
- this.popover.navedInitFocus = sel+':'+val.get;
2322
- this.popover.actionFn(this.opts[val.action]);
2323
- this.popover.navedInitFocus = false;
2324
- }
2325
- } else {
2326
- this.setFocus(button.eq(0));
2327
- }
2328
- };
2329
- });
2330
-
2331
- $.each({
2332
- prev: {traverse: 'prevAll',get: 'last', reverse: true},
2333
- next: {traverse: 'nextAll', get: 'first'}
2334
- }, function(name, val){
2335
- webshims.Grid.prototype[name] = function(){
2336
- var sel = 'button:not(:disabled,.othermonth)';
2337
- var button = this.activeButton.closest('td')[val.traverse]('td');
2338
- if(val.reverse){
2339
- button = $(button.get().reverse());
2340
- }
2341
- button = button.find(sel)[val.get]();
2342
- if(!button[0]){
2343
- button = this.activeButton.closest('tr')[val.traverse]('tr');
2344
- if(val.reverse){
2345
- button = $(button.get().reverse());
2346
- }
2347
- button = button.find(sel)[val.get]();
2348
- }
2349
-
2350
- if(!button[0]){
2351
- if(this.opts[name]){
2352
- this.popover.navedInitFocus = val.get;
2353
- this.popover.actionFn(this.opts[name]);
2354
- this.popover.navedInitFocus = false;
2355
- }
2356
- } else {
2357
- this.setFocus(button.eq(0));
2358
- }
2359
- };
2360
- });
2361
-
2362
- picker.getWeek = function(date){
2363
- var onejan = new Date(date.getFullYear(),0,1);
2364
- return Math.ceil((((date - onejan) / 86400000) + onejan.getDay()+1)/7);
2365
- };
2366
- picker.getYearList = function(value, data){
2367
- var j, i, val, disabled, lis, prevDisabled, nextDisabled, classStr, classArray, start;
2368
-
2369
-
2370
- var size = data.options.size;
2371
- var max = data.options.max.split('-');
2372
- var min = data.options.min.split('-');
2373
- var currentValue = data.options.value.split('-');
2374
- var xthCorrect = 0;
2375
- var enabled = 0;
2376
- var str = '';
2377
- var rowNum = 0;
2378
-
2379
- if(data.options.useDecadeBase == 'max' && max[0]){
2380
- xthCorrect = 11 - (max[0] % 12);
2381
- } else if(data.options.useDecadeBase == 'min' && min[0]){
2382
- xthCorrect = 11 - (min[0] % 12);
2383
- }
2384
-
2385
- value = value[0] * 1;
2386
- start = value - ((value + xthCorrect) % (12 * size));
2387
-
2388
-
2389
-
2390
- for(j = 0; j < size; j++){
2391
- if(j){
2392
- start += 12;
2393
- } else {
2394
- prevDisabled = picker.isInRange([start-1], max, min) ? {'data-action': 'setYearList','value': start-1} : false;
2395
- }
2396
-
2397
- str += '<div class="year-list picker-list ws-index-'+ j +'"><div class="ws-picker-header"><button disabled="disabled">'+ start +' – '+(start + 11)+'</button></div>';
2398
- lis = [];
2399
- for(i = 0; i < 12; i++){
2400
- val = start + i ;
2401
- classArray = [];
2402
- if( !picker.isInRange([val], max, min) ){
2403
- disabled = ' disabled=""';
2404
- } else {
2405
- disabled = '';
2406
- enabled++;
2407
- }
2408
-
2409
- if(val == today[0]){
2410
- classArray.push('this-value');
2411
- }
2412
-
2413
- if(currentValue[0] == val){
2414
- classArray.push('checked-value');
2415
- }
2416
-
2417
- classStr = classArray.length ? ' class="'+ (classArray.join(' ')) +'"' : '';
2418
-
2419
- if(i && !(i % 3)){
2420
- rowNum++;
2421
- lis.push('</tr><tr class="ws-row-'+ rowNum +'">');
2422
- }
2423
- lis.push('<td class="ws-item-'+ i +'" role="presentation"><button data-id="year-'+ i +'" type="button"'+ disabled + classStr +' data-action="setMonthList" value="'+val+'" tabindex="-1" role="gridcell">'+val+'</button></td>');
2424
- }
2425
- if(j == size - 1){
2426
- nextDisabled = picker.isInRange([val+1], max, min) ? {'data-action': 'setYearList','value': val+1} : false;
2427
- }
2428
- str += '<div class="picker-grid"><table role="grid" aria-label="'+ start +' – '+(start + 11)+'"><tbody><tr class="ws-row-0">'+ (lis.join(''))+ '</tr></tbody></table></div></div>';
2429
- }
2430
-
2431
- return {
2432
- enabled: enabled,
2433
- main: str,
2434
- next: nextDisabled,
2435
- prev: prevDisabled,
2436
- type: 'Grid'
2437
- };
2438
- };
2439
-
2440
-
2441
- picker.getMonthList = function(value, data){
2442
-
2443
- var j, i, name, val, disabled, lis, fullyDisabled, prevDisabled, nextDisabled, classStr, classArray;
2444
- var o = data.options;
2445
- var size = o.size;
2446
- var max = o.max.split('-');
2447
- var min = o.min.split('-');
2448
- var currentValue = o.value.split('-');
2449
- var enabled = 0;
2450
- var rowNum = 0;
2451
- var str = '';
2452
-
2453
- value = value[0] - Math.floor((size - 1) / 2);
2454
- for(j = 0; j < size; j++){
2455
- if(j){
2456
- value++;
2457
- } else {
2458
- prevDisabled = picker.isInRange([value-1], max, min) ? {'data-action': 'setMonthList','value': value-1} : false;
2459
- }
2460
- if(j == size - 1){
2461
- nextDisabled = picker.isInRange([value+1], max, min) ? {'data-action': 'setMonthList','value': value+1} : false;
2462
- }
2463
- lis = [];
2464
-
2465
- if( !picker.isInRange([value, '01'], max, min) && !picker.isInRange([value, '12'], max, min)){
2466
- disabled = ' disabled=""';
2467
- fullyDisabled = true;
2468
- } else {
2469
- fullyDisabled = false;
2470
- disabled = '';
2471
- }
2097
+ var spinBtnProto = $.extend({}, wsWidgetProto, {
2098
+ _create: function(){
2099
+ var o = this.options;
2100
+ var helper = createHelper(o.type);
2472
2101
 
2473
- if(o.minView >= 1){
2474
- disabled = ' disabled=""';
2475
- }
2102
+ this.elemHelper = $('<input type="'+ o.type+'" />');
2103
+ this.asNumber = helper.asNumber;
2104
+ this.asValue = helper.asValue;
2476
2105
 
2477
- str += '<div class="month-list picker-list ws-index-'+ j +'"><div class="ws-picker-header">';
2106
+ wsWidgetProto._create.apply(this, arguments);
2107
+ this._init = false;
2478
2108
 
2479
- str += o.selectNav ?
2480
- '<select data-action="setMonthList" class="year-select">'+ picker.createYearSelect(value, max, min).join('') +'</select>' :
2481
- '<button data-action="setYearList"'+disabled+' value="'+ value +'" tabindex="-1">'+ value +'</button>';
2482
- str += '</div>';
2109
+ this.buttonWrapper.html('<span unselectable="on" class="step-controls"><span class="step-up"></span><span class="step-down"></span></span>');
2483
2110
 
2484
- for(i = 0; i < 12; i++){
2485
- val = curCfg.date.monthkeys[i+1];
2486
- name = (curCfg.date[o.monthNames] || curCfg.date.monthNames)[i];
2487
- classArray = [];
2488
- if(fullyDisabled || !picker.isInRange([value, val], max, min) ){
2489
- disabled = ' disabled=""';
2490
- } else {
2491
- disabled = '';
2492
- enabled++;
2493
- }
2494
-
2495
- if(value == today[0] && today[1] == val){
2496
- classArray.push('this-value');
2497
- }
2498
-
2499
- if(currentValue[0] == value && currentValue[1] == val){
2500
- classArray.push('checked-value');
2501
- }
2502
-
2503
- classStr = (classArray.length) ? ' class="'+ (classArray.join(' ')) +'"' : '';
2504
- if(i && !(i % 3)){
2505
- rowNum++;
2506
- lis.push('</tr><tr class="ws-row-'+ rowNum +'">');
2507
- }
2508
-
2509
- lis.push('<td class="ws-item-'+ i +'" role="presentation"><button data-id="month-'+ i +'" type="button"'+ disabled + classStr +' data-action="'+ (data.type == 'month' ? 'changeInput' : 'setDayList' ) +'" value="'+value+'-'+val+'" tabindex="-1" role="gridcell" aria-label="'+ curCfg.date.monthNames[i] +'">'+name+'</button></td>');
2510
-
2111
+ if(this.type == 'number'){
2112
+ this.inputElements.attr('inputmode', 'numeric');
2511
2113
  }
2512
2114
 
2513
- str += '<div class="picker-grid"><table role="grid" aria-label="'+value+'"><tbody><tr class="ws-row-0">'+ (lis.join(''))+ '</tr></tbody></table></div></div>';
2514
- }
2515
-
2516
- return {
2517
- enabled: enabled,
2518
- main: str,
2519
- prev: prevDisabled,
2520
- next: nextDisabled,
2521
- type: 'Grid'
2522
- };
2523
- };
2524
-
2525
-
2526
- picker.getDayList = function(value, data){
2527
-
2528
- var j, i, k, day, nDay, name, val, disabled, lis, prevDisabled, nextDisabled, addTr, week, rowNum;
2529
-
2530
- var lastMotnh, curMonth, otherMonth, dateArray, monthName, fullMonthName, buttonStr, date2, classArray;
2531
- var o = data.options;
2532
- var size = o.size;
2533
- var max = o.max.split('-');
2534
- var min = o.min.split('-');
2535
- var currentValue = o.value.split('-');
2536
- var monthNames = curCfg.date[o.monthNamesHead] || curCfg.date[o.monthNames] || curCfg.date.monthNames;
2537
- var enabled = 0;
2538
- var str = [];
2539
- var date = new Date(value[0], value[1] - 1, 1);
2540
-
2541
- date.setMonth(date.getMonth() - Math.floor((size - 1) / 2));
2542
-
2543
- for(j = 0; j < size; j++){
2544
- date.setDate(1);
2545
- lastMotnh = date.getMonth();
2546
- rowNum = 0;
2547
- if(!j){
2548
- date2 = new Date(date.getTime());
2549
- date2.setDate(-1);
2550
- dateArray = getDateArray(date2);
2551
- prevDisabled = picker.isInRange(dateArray, max, min) ? {'data-action': 'setDayList','value': dateArray[0]+'-'+dateArray[1]} : false;
2552
- }
2553
-
2554
- dateArray = getDateArray(date);
2555
-
2556
- str.push('<div class="day-list picker-list ws-index-'+ j +'"><div class="ws-picker-header">');
2557
- if( o.selectNav ){
2558
- monthName = ['<select data-action="setDayList" class="month-select" tabindex="0">'+ picker.createMonthSelect(dateArray, max, min, monthNames).join('') +'</select>', '<select data-action="setDayList" class="year-select" tabindex="0">'+ picker.createYearSelect(dateArray[0], max, min, '-'+dateArray[1]).join('') +'</select>'];
2559
- if(curCfg.date.showMonthAfterYear){
2560
- monthName.reverse();
2561
- }
2562
- str.push( monthName.join(' ') );
2563
- }
2564
2115
 
2565
- fullMonthName = [curCfg.date.monthNames[(dateArray[1] * 1) - 1], dateArray[0]];
2566
- monthName = [monthNames[(dateArray[1] * 1) - 1], dateArray[0]];
2567
- if(curCfg.date.showMonthAfterYear){
2568
- monthName.reverse();
2569
- fullMonthName.reverse();
2116
+ if(!o.min && typeof o.relMin == 'number'){
2117
+ o.min = this.asValue(this.getRelNumber(o.relMin));
2118
+ $.prop(this.orig, 'min', o.min);
2570
2119
  }
2571
2120
 
2572
- if(!data.options.selectNav) {
2573
- str.push(
2574
- '<button data-action="setMonthList"'+ (o.minView >= 2 ? ' disabled="" ' : '') +' value="'+ dateArray.date +'" tabindex="-1">'+ monthName.join(' ') +'</button>'
2575
- );
2121
+ if(!o.max && typeof o.relMax == 'number'){
2122
+ o.max = this.asValue(this.getRelNumber(o.relMax));
2123
+ $.prop(this.orig, 'max', o.max);
2576
2124
  }
2577
-
2578
-
2579
- str.push('</div><div class="picker-grid"><table role="grid" aria-label="'+ fullMonthName.join(' ') +'"><thead><tr>');
2580
-
2581
- if(data.options.showWeek){
2582
- str.push('<th class="week-header">'+ curCfg.date.weekHeader +'</th>');
2125
+ this._init = true;
2126
+ },
2127
+ createOpts: ['step', 'min', 'max', 'readonly', 'title', 'disabled', 'tabindex', 'placeholder', 'value', 'required'],
2128
+ _addSplitInputs: function(){
2129
+ if(!this.inputElements){
2130
+ var create = splitInputs[this.type]._create();
2131
+ this.splits = create.splits;
2132
+ this.inputElements = $(create.elements).prependTo(this.element).filter('input');
2583
2133
  }
2584
- for(k = curCfg.date.firstDay; k < curCfg.date.dayNamesShort.length; k++){
2585
- str.push('<th class="day-'+ k +'"><abbr title="'+ curCfg.date.dayNames[k] +'">'+ curCfg.date.dayNamesShort[k] +'</abbr></th>');
2134
+ },
2135
+
2136
+ getRelNumber: function(rel){
2137
+ var start = steps[this.type].start || 0;
2138
+ if(rel){
2139
+ start += rel;
2586
2140
  }
2587
- k = curCfg.date.firstDay;
2588
- while(k--){
2589
- str.push('<th class="day-'+ k +'"><abbr title="'+ curCfg.date.dayNames[k] +'">'+ curCfg.date.dayNamesShort[k] +'</abbr></th>');
2141
+ return start;
2142
+ },
2143
+ addZero: addZero,
2144
+ _setStartInRange: function(){
2145
+ var start = this.getRelNumber(this.options.relDefaultValue);
2146
+ if(!isNaN(this.minAsNumber) && start < this.minAsNumber){
2147
+ start = this.minAsNumber;
2148
+ } else if(!isNaN(this.maxAsNumber) && start > this.maxAsNumber){
2149
+ start = this.maxAsNumber;
2590
2150
  }
2591
- str.push('</tr></thead><tbody><tr class="ws-row-0">');
2151
+ this.elemHelper.prop('valueAsNumber', start);
2152
+ this.options.defValue = this.elemHelper.prop('value');
2592
2153
 
2593
- if(data.options.showWeek) {
2594
- week = picker.getWeek(date);
2595
- str.push('<td class="week-cell">'+ week +'</td>');
2154
+ },
2155
+ reorderInputs: function(){
2156
+ if(splitInputs[this.type]){
2157
+ var element = this.element;
2158
+ splitInputs[this.type].sort(element);
2159
+ setTimeout(function(){
2160
+ var data = webshims.data(element);
2161
+ if(data && data.shadowData){
2162
+ data.shadowData.shadowFocusElement = element.find('input')[0] || element[0];
2163
+ }
2164
+ }, 9);
2596
2165
  }
2166
+ },
2167
+ value: function(val){
2597
2168
 
2598
- for (i = 0; i < 99; i++) {
2599
- addTr = (i && !(i % 7));
2600
- curMonth = date.getMonth();
2601
- otherMonth = lastMotnh != curMonth;
2602
- day = date.getDay();
2603
- classArray = [];
2604
-
2605
- if(addTr && otherMonth ){
2606
- str.push('</tr>');
2607
- break;
2608
- }
2609
- if(addTr){
2610
- rowNum++;
2611
- str.push('</tr><tr class="ws-row-'+ rowNum +'">');
2612
- if(data.options.showWeek) {
2613
- week++;
2614
- str.push('<td class="week-cell">'+ week +'</td>');
2615
- }
2616
- }
2169
+ if(!this._init || this.options.value !== val){
2170
+ this.valueAsNumber = this.asNumber(val);
2171
+ this.options.value = val;
2617
2172
 
2618
- if(!i){
2619
-
2620
- if(day != curCfg.date.firstDay){
2621
- nDay = day - curCfg.date.firstDay;
2622
- if(nDay < 0){
2623
- nDay += 7;
2624
- }
2625
- date.setDate(date.getDate() - nDay);
2626
- day = date.getDay();
2627
- curMonth = date.getMonth();
2628
- otherMonth = lastMotnh != curMonth;
2629
- }
2630
- }
2631
-
2632
- dateArray = getDateArray(date);
2633
- buttonStr = '<td role="presentation" class="day-'+ day +'"><button data-id="day-'+ date.getDate() +'" role="gridcell" data-action="changeInput" value="'+ (dateArray.join('-')) +'"';
2634
-
2635
- if(otherMonth){
2636
- classArray.push('othermonth');
2173
+ if(isNaN(this.valueAsNumber) || (!isNaN(this.minAsNumber) && this.valueAsNumber < this.minAsNumber) || (!isNaN(this.maxAsNumber) && this.valueAsNumber > this.maxAsNumber)){
2174
+ this._setStartInRange();
2637
2175
  } else {
2638
- classArray.push('day-'+date.getDate());
2176
+ this.elemHelper.prop('value', val);
2177
+ this.options.defValue = "";
2639
2178
  }
2640
2179
 
2641
- if(dateArray[0] == today[0] && today[1] == dateArray[1] && today[2] == dateArray[2]){
2642
- classArray.push('this-value');
2643
- }
2644
-
2645
- if(currentValue[0] == dateArray[0] && dateArray[1] == currentValue[1] && dateArray[2] == currentValue[2]){
2646
- classArray.push('checked-value');
2647
- }
2648
-
2649
- if(classArray.length){
2650
- buttonStr += ' class="'+ classArray.join(' ') +'"';
2651
- }
2652
-
2653
- if(!picker.isInRange(dateArray, max, min) || (data.options.disableDays && $.inArray(day, data.options.disableDays) != -1)){
2654
- buttonStr += ' disabled=""';
2180
+ val = formatVal[this.type](val, this.options);
2181
+ if(this.options.splitInput){
2182
+ $.each(this.splits, function(i, elem){
2183
+ $.prop(elem, 'value', val[i]);
2184
+ });
2185
+ } else {
2186
+ this.element.prop('value', val);
2655
2187
  }
2656
-
2657
- str.push(buttonStr+' tabindex="-1">'+ date.getDate() +'</button></td>');
2658
-
2659
- date.setDate(date.getDate() + 1);
2660
- }
2661
- str.push('</tbody></table></div></div>');
2662
- if(j == size - 1){
2663
- dateArray = getDateArray(date);
2664
- dateArray[2] = 1;
2665
- nextDisabled = picker.isInRange(dateArray, max, min) ? {'data-action': 'setDayList','value': dateArray.date} : false;
2188
+ this._propertyChange('value');
2189
+ this.mirrorValidity();
2666
2190
  }
2191
+ },
2192
+ step: function(val){
2193
+ var defStep = steps[this.type];
2194
+ this.options.step = val;
2195
+ this.elemHelper.prop('step', retDefault(val, defStep.step));
2196
+ this.mirrorValidity();
2667
2197
  }
2668
-
2669
-
2670
- return {
2671
- enabled: 9,
2672
- main: str.join(''),
2673
- prev: prevDisabled,
2674
- next: nextDisabled,
2675
- type: 'Grid'
2676
- };
2677
- };
2198
+ });
2678
2199
 
2679
- picker.isInRange = function(values, max, min){
2680
- var i;
2681
- var ret = true;
2682
- for(i = 0; i < values.length; i++){
2683
-
2684
- if(min[i] && min[i] > values[i]){
2685
- ret = false;
2686
- break;
2687
- } else if( !(min[i] && min[i] == values[i]) ){
2688
- break;
2689
- }
2690
- }
2691
- if(ret){
2692
- for(i = 0; i < values.length; i++){
2693
-
2694
- if((max[i] && max[i] < values[i])){
2695
- ret = false;
2696
- break;
2697
- } else if( !(max[i] && max[i] == values[i]) ){
2698
- break;
2699
- }
2200
+ $.each({min: 1, max: -1}, function(name, factor){
2201
+ var numName = name +'AsNumber';
2202
+ spinBtnProto[name] = function(val){
2203
+ this.elemHelper.prop(name, val);
2204
+ this[numName] = this.asNumber(val);
2205
+ if(this.valueAsNumber != null && (isNaN(this.valueAsNumber) || (!isNaN(this[numName]) && (this.valueAsNumber * factor) < (this[numName] * factor)))){
2206
+ this._setStartInRange();
2700
2207
  }
2701
- }
2702
- return ret;
2703
- };
2208
+ this.options[name] = val;
2209
+ this._propertyChange(name);
2210
+ this.mirrorValidity();
2211
+ };
2212
+ });
2704
2213
 
2705
- picker.createMonthSelect = function(value, max, min, monthNames){
2706
- if(!monthNames){
2707
- monthNames = curCfg.date.monthNames;
2708
- }
2709
-
2710
- var selected;
2711
- var i = 0;
2712
- var options = [];
2713
- var tempVal = value[1]-1;
2714
- for(; i < monthNames.length; i++){
2715
- selected = tempVal == i ? ' selected=""' : '';
2716
- if(selected || picker.isInRange([value[0], i+1], max, min)){
2717
- options.push('<option value="'+ value[0]+'-'+addZero(i+1) + '"'+selected+'>'+ monthNames[i] +'</option>');
2718
- }
2719
- }
2720
- return options;
2214
+ $.fn.wsBaseWidget = function(opts){
2215
+ opts = $.extend({}, opts);
2216
+ return this.each(function(){
2217
+ $.webshims.objectCreate(wsWidgetProto, {
2218
+ element: {
2219
+ value: $(this)
2220
+ }
2221
+ }, opts);
2222
+ });
2721
2223
  };
2722
2224
 
2723
- picker.createYearSelect = function(value, max, min, valueAdd){
2724
-
2725
- var temp;
2726
- var goUp = true;
2727
- var goDown = true;
2728
- var options = ['<option selected="">'+ value + '</option>'];
2729
- var i = 0;
2730
- if(!valueAdd){
2731
- valueAdd = '';
2732
- }
2733
- while(i < 8 && (goUp || goDown)){
2734
- i++;
2735
- temp = value-i;
2736
- if(goUp && picker.isInRange([temp], max, min)){
2737
- options.unshift('<option value="'+ (temp+valueAdd) +'">'+ temp +'</option>');
2738
- } else {
2739
- goUp = false;
2740
- }
2741
- temp = value + i;
2742
- if(goDown && picker.isInRange([temp], max, min)){
2743
- options.push('<option value="'+ (temp+valueAdd) +'">'+ temp +'</option>');
2744
- } else {
2745
- goDown = false;
2746
- }
2747
- }
2748
- return options;
2225
+ $.fn.spinbtnUI = function(opts){
2226
+ opts = $.extend({
2227
+ monthNames: 'monthNames',
2228
+ size: 1,
2229
+ startView: 0
2230
+ }, opts);
2231
+ return this.each(function(){
2232
+ $.webshims.objectCreate(spinBtnProto, {
2233
+ element: {
2234
+ value: $(this)
2235
+ }
2236
+ }, opts);
2237
+ });
2749
2238
  };
2750
-
2751
- var actions = {
2752
- changeInput: function(val, popover, data){
2753
- popover.stopOpen = true;
2754
- data.element.getShadowFocusElement().focus();
2755
- setTimeout(function(){
2756
- popover.stopOpen = false;
2757
- }, 9);
2758
- popover.hide();
2759
- data.setChange(val);
2239
+ })();
2240
+
2241
+ (function(){
2242
+ var picker = {};
2243
+
2244
+ var loadPicker = function(type, name){
2245
+ type = (type == 'color' ? 'color' : 'forms')+'-picker';
2246
+ if(!loadPicker[name+'Loaded'+type]){
2247
+ loadPicker[name+'Loaded'+type] = true;
2248
+ webshims.ready(name, function(){
2249
+ webshims.loader.loadList([type]);
2250
+ });
2760
2251
  }
2252
+ return type;
2761
2253
  };
2254
+ options.addZero = addZero;
2255
+ webshims.loader.addModule('forms-picker', {
2256
+ noAutoCallback: true,
2257
+ options: options
2258
+ });
2259
+ webshims.loader.addModule('color-picker', {
2260
+ noAutoCallback: true,
2261
+ css: 'jpicker/jpicker.css',
2262
+ options: options
2263
+ });
2762
2264
 
2763
- (function(){
2764
- var retNames = function(name){
2765
- return 'get'+name+'List';
2766
- };
2767
- var retSetNames = function(name){
2768
- return 'set'+name+'List';
2769
- };
2770
- var stops = {
2771
- date: 'Day',
2772
- week: 'Day',
2773
- month: 'Month'
2774
- };
2775
-
2776
- $.each({'setYearList' : ['Year', 'Month', 'Day'], 'setMonthList': ['Month', 'Day'], 'setDayList': ['Day']}, function(setName, names){
2777
- var getNames = names.map(retNames);
2778
- var setNames = names.map(retSetNames);
2779
- actions[setName] = function(val, popover, data, startAt){
2780
- val = ''+val;
2781
- var o = data.options;
2782
- var values = val.split('-');
2783
- if(!startAt){
2784
- startAt = 0;
2785
- }
2786
- $.each(getNames, function(i, item){
2787
- if(i >= startAt){
2788
- var content = picker[item](values, data);
2789
-
2790
- if( values.length < 2 || content.enabled > 1 || stops[data.type] === names[i]){
2791
- popover.element
2792
- .attr({'data-currentview': setNames[i]})
2793
- .addClass('ws-size-'+o.size)
2794
- .data('pickercontent', {
2795
- data: data,
2796
- content: content,
2797
- values: values
2798
- })
2799
- ;
2800
- popover.bodyElement.html(content.main);
2801
- if(content.prev){
2802
- popover.prevElement
2803
- .attr(content.prev)
2804
- .prop({disabled: false})
2805
- ;
2806
- } else {
2807
- popover.prevElement
2808
- .removeAttr('data-action')
2809
- .prop({disabled: true})
2810
- ;
2811
- }
2812
- if(content.next){
2813
- popover.nextElement
2814
- .attr(content.next)
2815
- .prop({disabled: false})
2816
- ;
2817
- } else {
2818
- popover.nextElement
2819
- .removeAttr('data-action')
2820
- .prop({disabled: true})
2821
- ;
2822
- }
2823
- if(webshims[content.type]){
2824
- new webshims[content.type](popover.bodyElement.children(), popover, content);
2825
- }
2826
- popover.element.trigger('pickerchange');
2827
- return false;
2265
+ picker._genericSetFocus = function(element, _noFocus){
2266
+ element = $(element || this.activeButton);
2267
+ if(!this.popover.openedByFocus && !_noFocus){
2268
+ var that = this;
2269
+ var setFocus = function(noTrigger){
2270
+ clearTimeout(that.timer);
2271
+ that.timer = setTimeout(function(){
2272
+ if(element[0]){
2273
+ element[0].focus();
2274
+ if(noTrigger !== true && !element.is(':focus')){
2275
+ setFocus(true);
2828
2276
  }
2829
2277
  }
2830
- });
2278
+ }, that.popover.isVisible ? 99 : 360);
2831
2279
  };
2832
- });
2833
- })();
2834
-
2835
- picker.commonInit = function(data, popover){
2836
- var actionfn = function(e){
2837
- if(!$(this).is('.othermonth') || $(this).css('cursor') == 'pointer'){
2838
- popover.actionFn({
2839
- 'data-action': $.attr(this, 'data-action'),
2840
- value: $(this).val() || $.attr(this, 'value')
2841
- });
2842
- }
2843
- return false;
2844
- };
2845
- var id = new Date().getTime();
2846
- var generateList = function(o, max, min){
2847
- var options = [];
2848
- var label = '';
2849
- var labelId = '';
2850
- o.options = data.getOptions() || {};
2851
- $('div.ws-options', popover.contentElement).remove();
2852
- $.each(o.options[0], function(val, label){
2853
- var disabled = picker.isInRange(val.split('-'), o.maxS, o.minS) ?
2854
- '' :
2855
- ' disabled="" '
2856
- ;
2857
- options.push('<li role="presentation"><button value="'+ val +'" '+disabled+' data-action="changeInput" tabindex="-1" role="option">'+ (label || data.formatValue(val, false)) +'</button></li>');
2858
- });
2859
- if(options.length){
2860
- id++;
2861
- if(o.options[1]){
2862
- labelId = 'datalist-'+id;
2863
- label = '<h5 id="'+labelId+'">'+ o.options[1] +'</h5>';
2864
- labelId = ' aria-labelledbyid="'+ labelId +'" ';
2865
- }
2866
- new webshims.ListBox($('<div class="ws-options">'+label+'<ul role="listbox" '+ labelId +'>'+ options.join('') +'</div>').insertAfter(popover.bodyElement)[0], popover, {noFocus: true});
2867
- }
2868
- };
2869
- var updateContent = function(){
2870
- if(popover.isDirty){
2871
- var o = data.options;
2872
- o.maxS = o.max.split('-');
2873
- o.minS = o.min.split('-');
2874
-
2875
- $('button', popover.buttonRow).each(function(){
2876
- var text;
2877
- if($(this).is('.ws-empty')){
2878
- text = curCfg.date.clear;
2879
- if(!text){
2880
- text = formcfg[''].date.clear || 'clear';
2881
- webshims.warn("could not get clear text from form cfg");
2882
- }
2883
- } else if($(this).is('.ws-current')){
2884
- text = (curCfg[data.type] || {}).currentText;
2885
- if(!text){
2886
- text = (formcfg[''][[data.type]] || {}).currentText || 'current';
2887
- webshims.warn("could not get currentText from form cfg");
2888
- }
2889
- $.prop(this, 'disabled', !picker.isInRange(today[data.type].split('-'), o.maxS, o.minS));
2890
- }
2891
- if(text){
2892
- $(this).text(text).attr({'aria-label': text});
2893
- if(webshims.assumeARIA){
2894
- $.attr(this, 'aria-label', text);
2895
- }
2896
- }
2897
-
2898
- });
2899
- popover.nextElement.attr({'aria-label': curCfg.date.nextText});
2900
- $('> span', popover.nextElement).html(curCfg.date.nextText);
2901
- popover.prevElement.attr({'aria-label': curCfg.date.prevText});
2902
- $('> span', popover.prevElement).html(curCfg.date.prevText);
2903
-
2904
- generateList(o, o.maxS, o.minS);
2905
-
2906
- }
2907
- $('button.ws-empty', popover.buttonRow).prop('disabled', $.prop(data.orig, 'required'));
2908
- popover.isDirty = false;
2909
- };
2910
-
2911
- popover.actionFn = function(obj){
2912
- if(actions[obj['data-action']]){
2913
- actions[obj['data-action']](obj.value, popover, data, 0);
2914
- } else {
2915
- webshims.warn('no action for '+ obj['data-action']);
2916
- }
2917
- };
2918
-
2919
- popover.contentElement.html('<button class="ws-prev" tabindex="0"><span></span></button> <button class="ws-next" tabindex="0"><span></span></button><div class="ws-picker-body"></div><div class="ws-button-row"><button type="button" class="ws-current" data-action="changeInput" value="'+today[data.type]+'" tabindex="0"></button> <button type="button" data-action="changeInput" value="" class="ws-empty" tabindex="0"></button></div>');
2920
- popover.nextElement = $('button.ws-next', popover.contentElement);
2921
- popover.prevElement = $('button.ws-prev', popover.contentElement);
2922
- popover.bodyElement = $('div.ws-picker-body', popover.contentElement);
2923
- popover.buttonRow = $('div.ws-button-row', popover.contentElement);
2280
+ this.popover.activateElement(element);
2281
+ setFocus();
2282
+ }
2283
+ };
2284
+
2285
+ picker._actions = {
2286
+ changeInput: function(val, popover, data){
2287
+ picker._actions.cancel(val, popover, data);
2288
+ data.setChange(val);
2289
+ },
2290
+ cancel: function(val, popover, data){
2291
+ popover.stopOpen = true;
2292
+ data.element.getShadowFocusElement().focus();
2293
+ setTimeout(function(){
2294
+ popover.stopOpen = false;
2295
+ }, 9);
2296
+ popover.hide();
2297
+ }
2298
+ };
2299
+
2300
+
2301
+ picker.commonInit = function(data, popover){
2302
+ var tabbable;
2924
2303
 
2925
2304
  popover.isDirty = true;
2926
2305
 
2927
- popover.contentElement
2928
- .on('click', 'button[data-action]', actionfn)
2929
- .on('change', 'select[data-action]', actionfn)
2930
- ;
2931
-
2306
+ popover.element.on('updatepickercontent pickerchange', function(){
2307
+ tabbable = false;
2308
+ });
2932
2309
  popover.contentElement.on({
2933
2310
  keydown: function(e){
2934
2311
  if(e.keyCode == 9){
2935
- var tabbable = $('[tabindex="0"]:not(:disabled)', this).filter(':visible');
2312
+ if(!tabbable){
2313
+ tabbable = $('input:not(:disabled), [tabindex="0"]:not(:disabled)', this).filter(':visible');
2314
+ }
2936
2315
  var index = tabbable.index(e.target);
2937
2316
  if(e.shiftKey && index <= 0){
2938
2317
  tabbable.last().focus();
@@ -2950,18 +2329,11 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
2950
2329
  }
2951
2330
  });
2952
2331
 
2953
- $(data.options.orig).on('input', function(){
2954
- var currentView;
2955
- if(data.options.updateOnInput && popover.isVisible && data.options.value && (currentView = popover.element.attr('data-currentview'))){
2956
- actions[currentView]( data.options.value , popover, data, 0);
2957
- }
2958
- });
2959
-
2960
2332
  data._propertyChange = (function(){
2961
2333
  var timer;
2962
2334
  var update = function(){
2963
2335
  if(popover.isVisible){
2964
- updateContent();
2336
+ popover.element.triggerHandler('updatepickercontent');
2965
2337
  }
2966
2338
  };
2967
2339
  return function(prop){
@@ -2987,50 +2359,51 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
2987
2359
  popover.element.on({
2988
2360
  wspopoverbeforeshow: function(){
2989
2361
  data.element.triggerHandler('wsupdatevalue');
2990
- updateContent();
2362
+ popover.element.triggerHandler('updatepickercontent');
2991
2363
  }
2992
2364
  });
2993
2365
 
2994
- $(document).onTrigger('wslocalechange', data._propertyChange);
2366
+
2367
+ $(data.orig).on('remove', function(e){
2368
+ if(!e.originalEvent){
2369
+ $(document).off('wslocalechange', data._propertyChange);
2370
+ }
2371
+ });
2995
2372
  };
2996
2373
 
2374
+
2997
2375
  picker._common = function(data){
2998
2376
  var popover = webshims.objectCreate(webshims.wsPopover, {}, {prepareFor: data.element});
2999
2377
  var opener = $('<button type="button" class="ws-popover-opener"><span /></button>').appendTo(data.buttonWrapper);
3000
2378
  var options = data.options;
3001
- var init = false;
3002
2379
 
2380
+ var showPickerContent = function(){
2381
+ (picker[data.type].showPickerContent || picker.showPickerContent)(data, popover);
2382
+ };
3003
2383
  var show = function(){
2384
+ var type = loadPicker(data.type, 'DOM');
3004
2385
  if(!options.disabled && !options.readonly && !popover.isVisible){
3005
- if(!init){
3006
- picker.commonInit(data, popover);
3007
- }
3008
-
3009
- if(!init || data.options.restartView) {
3010
- actions.setYearList( options.defValue || options.value, popover, data, data.options.startView);
3011
- } else {
3012
- actions[popover.element.attr('data-currentview') || 'setYearList']( options.defValue || options.value, popover, data, 0);
3013
- }
3014
-
3015
- init = true;
2386
+ webshims.ready(type, showPickerContent);
3016
2387
  popover.show(data.element);
3017
2388
  }
3018
2389
  };
3019
2390
 
3020
2391
  options.containerElements.push(popover.element[0]);
3021
2392
 
3022
- if(!options.startView){
3023
- options.startView = 0;
3024
- }
3025
- if(!options.minView){
3026
- options.minView = 0;
3027
- }
3028
- if(options.startView < options.minView){
3029
- options.minView = options.startView;
3030
- webshims.warn("wrong config for minView/startView.");
3031
- }
3032
- if(!options.size){
3033
- options.size = 1;
2393
+ if(data.type != 'color'){
2394
+ if(!options.startView){
2395
+ options.startView = 0;
2396
+ }
2397
+ if(!options.minView){
2398
+ options.minView = 0;
2399
+ }
2400
+ if(options.startView < options.minView){
2401
+ options.startView = options.minView;
2402
+ webshims.warn("wrong config for minView/startView.");
2403
+ }
2404
+ if(!options.size){
2405
+ options.size = 1;
2406
+ }
3034
2407
  }
3035
2408
 
3036
2409
  popover.element
@@ -3057,10 +2430,15 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
3057
2430
  labelWidth(popover.element.children('div.ws-po-outerbox').attr({role: 'group'}), options.labels, true);
3058
2431
  labelWidth(opener, options.labels, true);
3059
2432
 
2433
+ if(options.tabindex != null){
2434
+ opener.attr({tabindex: options.tabindex});
2435
+ }
2436
+
2437
+ if(options.disabled){
2438
+ opener.prop({disabled: true});
2439
+ }
2440
+
3060
2441
  opener
3061
- .attr({
3062
- 'tabindex': options.labels.length ? 0 : '-1'
3063
- })
3064
2442
  .on({
3065
2443
  mousedown: function(){
3066
2444
  stopPropagation.apply(this, arguments);
@@ -3105,10 +2483,51 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
3105
2483
  });
3106
2484
  })();
3107
2485
  data.popover = popover;
2486
+ data.opener = opener;
2487
+ $(data.orig).on('remove', function(e){
2488
+ if(!e.originalEvent){
2489
+ opener.remove();
2490
+ popover.element.remove();
2491
+ }
2492
+ });
2493
+
2494
+ loadPicker(data.type, 'WINDOWLOAD');
3108
2495
  };
3109
2496
 
3110
2497
  picker.month = picker._common;
3111
- picker.date = picker.month;
2498
+ picker.date = picker._common;
2499
+ picker.color = function(data){
2500
+ var ret = picker._common.apply(this, arguments);
2501
+ var alpha = $(data.orig).data('alphacontrol');
2502
+ var colorIndicator = data.opener
2503
+ .prepend('<span class="ws-color-indicator-bg"><span class="ws-color-indicator" /></span>')
2504
+ .find('.ws-color-indicator')
2505
+ ;
2506
+ var showColor = function(){
2507
+ colorIndicator.css({backgroundColor: $.prop(this, 'value') || '#000'})
2508
+ };
2509
+ var showOpacity = (function(){
2510
+ var timer;
2511
+ var show = function(){
2512
+ try {
2513
+ var value = data.alpha.prop('valueAsNumber') / (data.alpha.prop('max') || 1);
2514
+ if(!isNaN(value)){
2515
+ colorIndicator.css({opacity: value});
2516
+ }
2517
+ } catch(er){}
2518
+
2519
+ };
2520
+ return function(e){
2521
+ clearTimeout(timer);
2522
+ timer = setTimeout(show, !e || e.type == 'change' ? 4: 40);
2523
+ };
2524
+ })();
2525
+ data.alpha = (alpha) ? $('#'+alpha) : $([]);
2526
+
2527
+ $(data.orig).on('wsupdatevalue change', showColor).each(showColor);
2528
+ data.alpha.on('wsupdatevalue change input', showOpacity).each(showOpacity);
2529
+ return ret;
2530
+ };
3112
2531
 
3113
2532
  webshims.picker = picker;
3114
2533
  })();
@@ -3129,6 +2548,7 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
3129
2548
  'max',
3130
2549
  'step',
3131
2550
  'title',
2551
+ 'required',
3132
2552
  'placeholder'
3133
2553
  ];
3134
2554
 
@@ -3137,11 +2557,11 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
3137
2557
 
3138
2558
  $.each(copyProps.concat(copyAttrs), function(i, name){
3139
2559
  var fnName = name.replace(/^data\-/, '');
3140
- webshims.onNodeNamesPropertyModify('input', name, function(val){
2560
+ webshims.onNodeNamesPropertyModify('input', name, function(val, boolVal){
3141
2561
  if(!stopCircular){
3142
2562
  var shadowData = webshims.data(this, 'shadowData');
3143
2563
  if(shadowData && shadowData.data && shadowData.nativeElement === this && shadowData.data[fnName]){
3144
- shadowData.data[fnName](val);
2564
+ shadowData.data[fnName](val, boolVal);
3145
2565
  }
3146
2566
  }
3147
2567
  });
@@ -3172,6 +2592,7 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
3172
2592
  var sizeInput = function(data){
3173
2593
  var init;
3174
2594
  var updateStyles = function(){
2595
+ $(data.orig).removeClass('ws-important-hide');
3175
2596
  $.style( data.orig, 'display', '' );
3176
2597
  var hasButtons, marginR, marginL;
3177
2598
  var correctWidth = 0.6;
@@ -3205,13 +2626,14 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
3205
2626
  data.element.outerWidth( $(data.orig).outerWidth() - correctWidth );
3206
2627
  }
3207
2628
  init = true;
3208
- $.style( data.orig, 'display', 'none' );
2629
+ $(data.orig).addClass('ws-important-hide');
3209
2630
  };
3210
- $(document).onTrigger('updateshadowdom', updateStyles);
2631
+ data.element.onWSOff('updateshadowdom', updateStyles, true);
3211
2632
  };
3212
2633
 
3213
2634
 
3214
2635
  var implementType = function(){
2636
+
3215
2637
  var type = $.prop(this, 'type');
3216
2638
 
3217
2639
  var i, opts, data, optsName, labels;
@@ -3266,7 +2688,7 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
3266
2688
  data.shim.options.containerElements.push(data.shim.element[0]);
3267
2689
 
3268
2690
  labelWidth($(this).getShadowFocusElement(), labels);
3269
- $.attr(this, 'required', $.attr(this, 'required'));
2691
+
3270
2692
  $(this).on('change', function(e){
3271
2693
  if(!stopCircular){
3272
2694
  data.shim.value($.prop(this, 'value'));
@@ -3325,18 +2747,13 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
3325
2747
 
3326
2748
  if(opts.calculateWidth){
3327
2749
  sizeInput(data.shim);
2750
+ } else {
2751
+ $(this).css({display: 'none'});
3328
2752
  }
3329
- $(this).css({display: 'none'});
3330
2753
  }
2754
+
3331
2755
  };
3332
2756
 
3333
- if(!modernizrInputTypes.range || options.replaceUI){
3334
- extendType('range', {
3335
- _create: function(opts, set){
3336
- return $('<span />').insertAfter(opts.orig).rangeUI(opts).data('rangeUi');
3337
- }
3338
- });
3339
- }
3340
2757
 
3341
2758
  if(Modernizr.formvalidation){
3342
2759
  ['input', 'form'].forEach(function(name){
@@ -3353,12 +2770,20 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
3353
2770
  });
3354
2771
  }
3355
2772
 
2773
+ if(!modernizrInputTypes.range || options.replaceUI){
2774
+ extendType('range', {
2775
+ _create: function(opts, set){
2776
+ var data = $('<span />').insertAfter(opts.orig).rangeUI(opts).data('rangeUi');
2777
+ return data;
2778
+ }
2779
+ });
2780
+ }
3356
2781
 
3357
- ['number', 'time', 'month', 'date'].forEach(function(name){
3358
- if(!modernizrInputTypes[name] || options.replaceUI){
2782
+ var isStupid = navigator.userAgent.indexOf('MSIE 10.0') != -1 && navigator.userAgent.indexOf('Touch') == -1;
2783
+ ['number', 'time', 'month', 'date', 'color'].forEach(function(name){
2784
+ if(!modernizrInputTypes[name] || options.replaceUI || (name == 'number' && isStupid)){
3359
2785
  extendType(name, {
3360
2786
  _create: function(opts, set){
3361
-
3362
2787
  if(opts.splitInput && !splitInputs[name]){
3363
2788
  webshims.warn('splitInput not supported for '+ name);
3364
2789
  opts.splitInput = false;
@@ -3366,11 +2791,12 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
3366
2791
  var markup = opts.splitInput ?
3367
2792
  '<span class="ws-'+name+' ws-input" role="group"></span>' :
3368
2793
  '<input class="ws-'+name+'" type="text" />';
3369
- var data = $(markup) //role="spinbutton"???
3370
- .insertAfter(opts.orig)
3371
- .spinbtnUI(opts)
3372
- .data('wsspinner')
3373
- ;
2794
+ var data = $(markup).insertAfter(opts.orig);
2795
+ if(steps[name]){
2796
+ data = data.spinbtnUI(opts).data('wsWidget'+name);
2797
+ } else {
2798
+ data = data.wsBaseWidget(opts).data('wsWidget'+name);
2799
+ }
3374
2800
  if(webshims.picker && webshims.picker[name]){
3375
2801
  webshims.picker[name](data);
3376
2802
  }
@@ -3392,9 +2818,37 @@ jQuery.webshims.register('form-number-date-ui', function($, webshims, window, do
3392
2818
  });
3393
2819
 
3394
2820
 
3395
- jQuery.webshims.register('form-datalist', function($, webshims, window, document, undefined, options){
2821
+ webshims.register('form-datalist', function($, webshims, window, document, undefined, options){
3396
2822
  "use strict";
3397
- var doc = document;
2823
+ var doc = document;
2824
+ var lazyLoad = function(name){
2825
+ if(!name || typeof name != 'string'){
2826
+ name = 'DOM';
2827
+ }
2828
+ if(!lazyLoad[name+'Loaded']){
2829
+ lazyLoad[name+'Loaded'] = true;
2830
+ webshims.ready(name, function(){
2831
+ webshims.loader.loadList(['form-datalist-lazy']);
2832
+ });
2833
+ }
2834
+ };
2835
+ var noDatalistSupport = {
2836
+ submit: 1,
2837
+ button: 1,
2838
+ reset: 1,
2839
+ hidden: 1,
2840
+
2841
+ range: 1,
2842
+ date: 1,
2843
+ month: 1
2844
+ };
2845
+ if(webshims.modules["form-number-date-ui"].loaded){
2846
+ $.extend(noDatalistSupport, {
2847
+ number: 1,
2848
+ time: 1
2849
+ });
2850
+ }
2851
+
3398
2852
 
3399
2853
  /*
3400
2854
  * implement propType "element" currently only used for list-attribute (will be moved to dom-extend, if needed)
@@ -3430,28 +2884,6 @@ jQuery.webshims.register('form-datalist', function($, webshims, window, document
3430
2884
  var initializeDatalist = function(){
3431
2885
 
3432
2886
 
3433
- if(!listSupport){
3434
- webshims.defineNodeNameProperty('datalist', 'options', {
3435
- prop: {
3436
- writeable: false,
3437
- get: function(){
3438
- var elem = this;
3439
- var select = $('select', elem);
3440
- var options;
3441
- if(select[0]){
3442
- options = select[0].options;
3443
- } else {
3444
- options = $('option', elem).get();
3445
- if(options.length){
3446
- webshims.warn('you should wrap your option-elements for a datalist in a select element to support IE and other old browsers.');
3447
- }
3448
- }
3449
- return options;
3450
- }
3451
- }
3452
- });
3453
- }
3454
-
3455
2887
  var inputListProto = {
3456
2888
  //override autocomplete
3457
2889
  autocomplete: {
@@ -3511,27 +2943,8 @@ jQuery.webshims.register('form-datalist', function($, webshims, window, document
3511
2943
  };
3512
2944
  }
3513
2945
 
3514
- if(!listSupport){
3515
-
3516
- inputListProto['list'] = {
3517
- attr: {
3518
- get: function(){
3519
- var val = webshims.contentAttr(this, 'list');
3520
- return (val == null) ? undefined : val;
3521
- },
3522
- set: function(value){
3523
- var elem = this;
3524
- webshims.contentAttr(elem, 'list', value);
3525
- webshims.objectCreate(shadowListProto, undefined, {input: elem, id: value, datalist: $.prop(elem, 'list')});
3526
- $(elem).triggerHandler('listdatalistchange');
3527
- }
3528
- },
3529
- initAttr: true,
3530
- reflect: true,
3531
- propType: 'element',
3532
- propNodeName: 'datalist'
3533
- };
3534
- } else {
2946
+
2947
+ if(listSupport){
3535
2948
  //options only return options, if option-elements are rooted: but this makes this part of HTML5 less backwards compatible
3536
2949
  if(!($('<datalist><select><option></option></select></datalist>').prop('options') || []).length ){
3537
2950
  webshims.defineNodeNameProperty('datalist', 'options', {
@@ -3551,13 +2964,15 @@ jQuery.webshims.register('form-datalist', function($, webshims, window, document
3551
2964
  }
3552
2965
  });
3553
2966
  }
3554
- inputListProto['list'] = {
2967
+ inputListProto.list = {
3555
2968
  attr: {
3556
2969
  get: function(){
3557
2970
  var val = webshims.contentAttr(this, 'list');
3558
2971
  if(val != null){
3559
2972
  $.data(this, 'datalistListAttr', val);
3560
- this.removeAttribute('list');
2973
+ if(!noDatalistSupport[$.prop(this, 'type')] && !noDatalistSupport[$.attr(this, 'type')]){
2974
+ this.removeAttribute('list');
2975
+ }
3561
2976
  } else {
3562
2977
  val = $.data(this, 'datalistListAttr');
3563
2978
  }
@@ -3567,7 +2982,15 @@ jQuery.webshims.register('form-datalist', function($, webshims, window, document
3567
2982
  set: function(value){
3568
2983
  var elem = this;
3569
2984
  $.data(elem, 'datalistListAttr', value);
3570
- webshims.objectCreate(shadowListProto, undefined, {input: elem, id: value, datalist: $.prop(elem, 'list')});
2985
+ if (!noDatalistSupport[$.prop(this, 'type')] && !noDatalistSupport[$.attr(this, 'type')]) {
2986
+ webshims.objectCreate(shadowListProto, undefined, {
2987
+ input: elem,
2988
+ id: value,
2989
+ datalist: $.prop(elem, 'list')
2990
+ });
2991
+ } else {
2992
+ elem.setAttribute('list', value);
2993
+ }
3571
2994
  $(elem).triggerHandler('listdatalistchange');
3572
2995
  }
3573
2996
  },
@@ -3587,62 +3010,14 @@ jQuery.webshims.register('form-datalist', function($, webshims, window, document
3587
3010
  .each(function(){
3588
3011
  $(this).triggerHandler('updateDatalist');
3589
3012
  })
3590
-
3591
3013
  ;
3592
-
3593
3014
  });
3594
-
3595
-
3596
3015
  };
3597
3016
 
3598
3017
 
3599
3018
  /*
3600
3019
  * ShadowList
3601
3020
  */
3602
- var listidIndex = 0;
3603
- var noDatalistSupport = {
3604
- submit: 1,
3605
- button: 1,
3606
- reset: 1,
3607
- hidden: 1,
3608
-
3609
- range: 1,
3610
- date: 1,
3611
- month: 1
3612
- };
3613
- if(webshims.modules["form-number-date-ui"].loaded){
3614
- $.extend(noDatalistSupport, {
3615
- number: 1,
3616
- time: 1
3617
- });
3618
- }
3619
-
3620
- var globStoredOptions = {};
3621
- var getStoredOptions = function(name){
3622
- if(!name){return [];}
3623
- if(globStoredOptions[name]){
3624
- return globStoredOptions[name];
3625
- }
3626
- var data;
3627
- try {
3628
- data = JSON.parse(localStorage.getItem('storedDatalistOptions'+name));
3629
- } catch(e){}
3630
- globStoredOptions[name] = data || [];
3631
- return data || [];
3632
- };
3633
- var storeOptions = function(name, val){
3634
- if(!name){return;}
3635
- val = val || [];
3636
- try {
3637
- localStorage.setItem( 'storedDatalistOptions'+name, JSON.stringify(val) );
3638
- } catch(e){}
3639
- };
3640
-
3641
- var getText = function(elem){
3642
- return (elem.textContent || elem.innerText || $.text([ elem ]) || '');
3643
- };
3644
- var lReg = /</g;
3645
- var gReg = />/g;
3646
3021
 
3647
3022
  var shadowListProto = {
3648
3023
  _create: function(opts){
@@ -3650,6 +3025,7 @@ jQuery.webshims.register('form-datalist', function($, webshims, window, document
3650
3025
  if(noDatalistSupport[$.prop(opts.input, 'type')] || noDatalistSupport[$.attr(opts.input, 'type')]){return;}
3651
3026
  var datalist = opts.datalist;
3652
3027
  var data = $.data(opts.input, 'datalistWidget');
3028
+ var that = this;
3653
3029
  if(datalist && data && data.datalist !== datalist){
3654
3030
  data.datalist = datalist;
3655
3031
  data.id = opts.id;
@@ -3670,9 +3046,8 @@ jQuery.webshims.register('form-datalist', function($, webshims, window, document
3670
3046
  } else if(data && data.datalist === datalist){
3671
3047
  return;
3672
3048
  }
3673
- listidIndex++;
3674
- var that = this;
3675
- this.hideList = $.proxy(that, 'hideList');
3049
+
3050
+
3676
3051
 
3677
3052
  this.datalist = datalist;
3678
3053
  this.id = opts.id;
@@ -3680,121 +3055,21 @@ jQuery.webshims.register('form-datalist', function($, webshims, window, document
3680
3055
  this._autocomplete = $.attr(opts.input, 'autocomplete');
3681
3056
  $.data(opts.input, 'datalistWidget', this);
3682
3057
 
3683
- this.popover = webshims.objectCreate(webshims.wsPopover, {}, options.datalistPopover);
3684
- this.shadowList = this.popover.element.addClass('datalist-polyfill');
3685
-
3686
-
3687
- this.index = -1;
3688
- this.input = opts.input;
3689
- this.arrayOptions = [];
3690
-
3691
- this.shadowList
3692
- .delegate('li', 'mouseenter.datalistWidget mousedown.datalistWidget click.datalistWidget', function(e){
3693
- var items = $('li:not(.hidden-item)', that.shadowList);
3694
- var select = (e.type == 'mousedown' || e.type == 'click');
3695
- that.markItem(items.index(e.currentTarget), select, items);
3696
- if(e.type == 'click'){
3697
- that.hideList();
3698
- if(formsCFG.customDatalist){
3699
- $(opts.input).getNativeElement().trigger('datalistselect');
3700
- }
3701
- }
3702
- return (e.type != 'mousedown');
3703
- })
3704
- ;
3705
-
3706
- opts.input.setAttribute('autocomplete', 'off');
3707
-
3708
- $(opts.input)
3709
- .attr({
3710
- //role: 'combobox',
3711
- 'aria-haspopup': 'true'
3712
- })
3713
- .on({
3714
- 'input.datalistWidget': function(){
3715
- if(!that.triggeredByDatalist){
3716
- that.changedValue = false;
3717
- that.showHideOptions();
3718
- }
3719
- },
3720
- 'keydown.datalistWidget': function(e){
3721
- var keyCode = e.keyCode;
3722
- var activeItem;
3723
- var items;
3724
- if(keyCode == 40 && !that.showList()){
3725
- that.markItem(that.index + 1, true);
3726
- return false;
3727
- }
3728
-
3729
- if(!that.popover.isVisible){return;}
3730
-
3731
-
3732
- if(keyCode == 38){
3733
- that.markItem(that.index - 1, true);
3734
- return false;
3735
- }
3736
- if(!e.shiftKey && (keyCode == 33 || keyCode == 36)){
3737
- that.markItem(0, true);
3738
- return false;
3739
- }
3740
- if(!e.shiftKey && (keyCode == 34 || keyCode == 35)){
3741
- items = $('li:not(.hidden-item)', that.shadowList);
3742
- that.markItem(items.length - 1, true, items);
3743
- return false;
3744
- }
3745
- if(keyCode == 13 || keyCode == 27){
3746
- if (keyCode == 13){
3747
- activeItem = $('li.active-item:not(.hidden-item)', that.shadowList);
3748
- that.changeValue( $('li.active-item:not(.hidden-item)', that.shadowList) );
3749
- }
3750
- that.hideList();
3751
- if(formsCFG.customDatalist && activeItem && activeItem[0]){
3752
- $(opts.input).getNativeElement().trigger('datalistselect');
3753
- }
3754
- return false;
3755
- }
3756
- },
3757
- 'focus.datalistWidget': function(){
3758
- if($(this).hasClass('list-focus')){
3759
- that.showList();
3760
- }
3761
- },
3762
- 'mousedown.datalistWidget': function(){
3763
- if($(this).is(':focus')){
3764
- that.showList();
3765
- }
3766
- }
3767
- })
3768
- ;
3769
-
3058
+ lazyLoad('WINDOWLOAD');
3770
3059
 
3771
- $(this.datalist)
3772
- .off('updateDatalist.datalistWidget')
3773
- .on('updateDatalist.datalistWidget', $.proxy(this, '_resetListCached'))
3774
- ;
3775
-
3776
- this._resetListCached();
3777
-
3778
- if(opts.input.form && (opts.input.name || opts.input.id)){
3779
- $(opts.input.form).on('submit.datalistWidget'+opts.input.id, function(){
3780
- if(!$(opts.input).hasClass('no-datalist-cache') && that._autocomplete != 'off'){
3781
- var val = $.prop(opts.input, 'value');
3782
- var name = (opts.input.name || opts.input.id) + $.prop(opts.input, 'type');
3783
- if(!that.storedOptions){
3784
- that.storedOptions = getStoredOptions( name );
3785
- }
3786
- if(val && that.storedOptions.indexOf(val) == -1){
3787
- that.storedOptions.push(val);
3788
- storeOptions(name, that.storedOptions );
3789
- }
3060
+ if(webshims.isReady('form-datalist-lazy')){
3061
+ this._lazyCreate(opts);
3062
+ } else {
3063
+ $(opts.input).one('focus', lazyLoad);
3064
+ webshims.ready('form-datalist-lazy', function(){
3065
+ if(!that._destroyed){
3066
+ that._lazyCreate(opts);
3790
3067
  }
3791
3068
  });
3792
3069
  }
3793
- $(window).on('unload.datalist'+this.id+' beforeunload.datalist'+this.id, function(){
3794
- that.destroy();
3795
- });
3796
3070
  },
3797
- destroy: function(){
3071
+ destroy: function(e){
3072
+ var input;
3798
3073
  var autocomplete = $.attr(this.input, 'autocomplete');
3799
3074
  $(this.input)
3800
3075
  .off('.datalistWidget')
@@ -3812,268 +3087,21 @@ jQuery.webshims.register('form-datalist', function($, webshims, window, document
3812
3087
  } else {
3813
3088
  $(this.input).attr('autocomplete', autocomplete);
3814
3089
  }
3815
- },
3816
- _resetListCached: function(e){
3817
- var that = this;
3818
- var forceShow;
3819
- this.needsUpdate = true;
3820
- this.lastUpdatedValue = false;
3821
- this.lastUnfoundValue = '';
3822
-
3823
- if(!this.updateTimer){
3824
- if(window.QUnit || (forceShow = ($(that.input).is(':focus') && ($(that.input).hasClass('list-focus') || $.prop(that.input, 'value'))) )){
3825
- that.updateListOptions(forceShow);
3826
- } else {
3827
- webshims.ready('WINDOWLOAD', function(){
3828
- that.updateTimer = setTimeout(function(){
3829
- that.updateListOptions();
3830
- that = null;
3831
- listidIndex = 1;
3832
- }, 200 + (100 * listidIndex));
3833
- });
3834
- }
3835
- }
3836
- },
3837
- updateListOptions: function(_forceShow){
3838
- this.needsUpdate = false;
3839
- clearTimeout(this.updateTimer);
3840
- this.updateTimer = false;
3841
-
3842
- this.searchStart = formsCFG.customDatalist && $(this.input).hasClass('search-start');
3843
- this.addMarkElement = options.addMark || $(this.input).hasClass('mark-option-text');
3844
-
3845
- var list = [];
3846
-
3847
- var values = [];
3848
- var allOptions = [];
3849
- var rElem, rItem, rOptions, rI, rLen, item, value;
3850
- for(rOptions = $.prop(this.datalist, 'options'), rI = 0, rLen = rOptions.length; rI < rLen; rI++){
3851
- rElem = rOptions[rI];
3852
- if(!rElem.disabled && (value = $(rElem).val())){
3853
- rItem = {
3854
- value: value.replace(lReg, '&lt;').replace(gReg, '&gt;'),
3855
- label: $.trim($.attr(rElem, 'label') || getText(rElem)).replace(lReg, '&lt;').replace(gReg, '&gt;'),
3856
- className: rElem.className || ''
3857
- };
3858
-
3859
- if(rItem.label){
3860
- rItem.className += ' has-option-label';
3861
- }
3862
- values.push(rItem.value);
3863
- allOptions.push(rItem);
3864
- }
3865
- }
3866
-
3867
- if(!this.storedOptions){
3868
- this.storedOptions = ($(this.input).hasClass('no-datalist-cache') || this._autocomplete == 'off') ? [] : getStoredOptions((this.input.name || this.input.id) + $.prop(this.input, 'type'));
3869
- }
3870
-
3871
- this.storedOptions.forEach(function(val, i){
3872
- if(values.indexOf(val) == -1){
3873
- allOptions.push({value: val, label: '', className: 'stored-suggest', style: ''});
3874
- }
3875
- });
3876
-
3877
- for(rI = 0, rLen = allOptions.length; rI < rLen; rI++){
3878
- item = allOptions[rI];
3879
- list[rI] = '<li class="'+ item.className +'" tabindex="-1" role="listitem">'+ this.getOptionContent(item) +'</li>';
3880
- }
3881
-
3882
- this.arrayOptions = allOptions;
3883
- this.popover.contentElement.html('<div class="datalist-box"><ul role="list">'+ list.join("\n") +'</ul></div>');
3884
-
3885
-
3886
- if(_forceShow || this.popover.isVisible){
3887
- this.showHideOptions();
3888
- }
3889
- },
3890
- getOptionContent: function(item){
3891
- var content = '';
3892
- if(options.getOptionContent){
3893
- content = options.apply(this, arguments) || '';
3894
- } else {
3895
- content = '<span class="option-value">'+ item.value +'</span>';
3896
- if(item.label){
3897
- content += ' <span class="option-label">'+ item.label +'</span>';
3898
- }
3899
- }
3900
- return content;
3901
- },
3902
- showHideOptions: function(_fromShowList){
3903
- var value = $.prop(this.input, 'value').toLowerCase();
3904
-
3905
- //first check prevent infinite loop, second creates simple lazy optimization
3906
- if(value === this.lastUpdatedValue){
3907
- return;
3908
- }
3909
- if(this.lastUnfoundValue && value.indexOf(this.lastUnfoundValue) === 0){
3910
- this.hideList();
3911
- return;
3912
- }
3913
-
3914
-
3915
- this.lastUpdatedValue = value;
3916
- var found = false;
3917
- var startSearch = this.searchStart;
3918
- var lis = $('li', this.shadowList);
3919
- var that = this;
3920
- if(value){
3921
-
3922
- this.arrayOptions.forEach(function(item, i){
3923
- var search, searchIndex, foundName;
3924
- if(!('lowerValue' in item)){
3925
- item.lowerValue = item.value.toLowerCase();
3926
- if(item.label && item.label != item.value ){
3927
- item.lowerLabel = item.label.toLowerCase();
3928
- }
3929
- }
3930
-
3931
- if(value != item.lowerValue && item.lowerLabel != value){
3932
- searchIndex = item.lowerValue.indexOf(value);
3933
- search = startSearch ? !searchIndex : searchIndex !== -1;
3934
- if(search){
3935
- foundName = 'value';
3936
- } else if(item.lowerLabel){
3937
- searchIndex = item.lowerLabel.indexOf(value);
3938
- search = startSearch ? !searchIndex : searchIndex !== -1;
3939
- foundName = 'label';
3940
- }
3941
- }
3942
-
3943
- if(search){
3944
- that.addMark($(lis[i]).removeClass('hidden-item'), item, foundName, searchIndex, value.length);
3945
- found = true;
3946
- } else {
3947
- $(lis[i]).addClass('hidden-item');
3948
- }
3949
- });
3950
- } else if(lis.length) {
3951
- this.removeMark(lis.removeClass('hidden-item'));
3952
- found = true;
3953
- }
3954
-
3955
- this.hasViewableData = found;
3956
- if(!_fromShowList && found){
3957
- this.showList();
3958
- }
3959
-
3960
- if(!found){
3961
- this.lastUnfoundValue = value;
3962
- this.hideList();
3963
- } else {
3964
- this.lastUnfoundValue = false;
3965
- }
3966
- },
3967
- otherType: {
3968
- value: 'label',
3969
- label: 'value'
3970
- },
3971
- addMark: function(elem, item, prop, start, length){
3972
- if(this.addMarkElement){
3973
- var text = item[prop].substr(start, length);
3974
- text = item[prop].replace(text ,'<mark>'+ text +'</mark>');
3975
- $('.option-'+ this.otherType[prop] +' > mark', elem).each(this._replaceMark);
3976
- $('.option-'+prop, elem).html(text);
3977
-
3978
- }
3979
- },
3980
- _replaceMark: function(){
3981
- var content = $(this).html();
3982
- $(this).replaceWith(content);
3983
- },
3984
- removeMark: function(lis){
3985
- if(this.addMarkElement){
3986
- $('mark', lis).each(this._replaceMark);
3987
- }
3988
- },
3989
- showList: function(){
3990
- if(this.popover.isVisible){return false;}
3991
- if(this.needsUpdate){
3992
- this.updateListOptions();
3993
- }
3994
- this.showHideOptions(true);
3995
- if(!this.hasViewableData){return false;}
3996
- var that = this;
3997
-
3998
- that.shadowList.find('li.active-item').removeClass('active-item');
3999
- that.popover.show(this.input);
4000
-
4001
-
4002
- return true;
4003
- },
4004
- hideList: function(){
4005
- if(!this.popover.isVisible){return false;}
4006
- var that = this;
4007
-
4008
-
4009
- this.popover.hide();
4010
- that.shadowList.removeClass('datalist-visible list-item-active');
4011
- that.index = -1;
4012
- if(that.changedValue){
4013
- that.triggeredByDatalist = true;
4014
- $(that.input).trigger('input').trigger('change');
4015
- that.changedValue = false;
4016
- that.triggeredByDatalist = false;
4017
- }
4018
-
4019
- return true;
4020
- },
4021
- scrollIntoView: function(elem){
4022
- var ul = $('ul', this.shadowList);
4023
- var div = $('div.datalist-box', this.shadowList);
4024
- var elemPos = elem.position();
4025
- var containerHeight;
4026
- elemPos.top -= (parseInt(ul.css('paddingTop'), 10) || 0) + (parseInt(ul.css('marginTop'), 10) || 0) + (parseInt(ul.css('borderTopWidth'), 10) || 0);
4027
- if(elemPos.top < 0){
4028
- div.scrollTop( div.scrollTop() + elemPos.top - 2);
4029
- return;
4030
- }
4031
- elemPos.top += elem.outerHeight();
4032
- containerHeight = div.height();
4033
- if(elemPos.top > containerHeight){
4034
- div.scrollTop( div.scrollTop() + (elemPos.top - containerHeight) + 2);
4035
- }
4036
- },
4037
- changeValue: function(activeItem){
4038
- if(!activeItem[0]){return;}
4039
- var spinner;
4040
- var newValue = $('span.option-value', activeItem).text();
4041
- var oldValue = $.prop(this.input, 'value');
4042
- if(newValue != oldValue){
4043
-
4044
- $(this.input)
4045
- .prop('value', newValue)
4046
- .triggerHandler('updateInput')
4047
- ;
4048
- this.changedValue = true;
4049
- if((spinner = $.data(this.input, 'wsspinner')) && spinner.setInput){
4050
- spinner.setInput(newValue);
4051
- }
3090
+ if(e && e.type == 'beforeunload'){
3091
+ input = this.input;
3092
+ setTimeout(function(){
3093
+ $.attr(input, 'list', $.attr(input, 'list'));
3094
+ }, 9);
4052
3095
  }
4053
- },
4054
- markItem: function(index, doValue, items){
4055
- var activeItem;
4056
- var goesUp;
4057
-
4058
- items = items || $('li:not(.hidden-item)', this.shadowList);
4059
- if(!items.length){return;}
4060
- if(index < 0){
4061
- index = items.length - 1;
4062
- } else if(index >= items.length){
4063
- index = 0;
4064
- }
4065
- items.removeClass('active-item');
4066
- this.shadowList.addClass('list-item-active');
4067
- activeItem = items.filter(':eq('+ index +')').addClass('active-item');
4068
-
4069
- if(doValue){
4070
- this.changeValue(activeItem);
4071
- this.scrollIntoView(activeItem);
4072
- }
4073
- this.index = index;
3096
+ this._destroyed = true;
4074
3097
  }
4075
3098
  };
4076
3099
 
3100
+ webshims.loader.addModule('form-datalist-lazy', {
3101
+ noAutoCallback: true,
3102
+ options: $.extend(options, {shadowListProto: shadowListProto})
3103
+ });
3104
+
4077
3105
  //init datalist update
4078
3106
  initializeDatalist();
4079
3107
  })();