html5forms-rails 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/Gemfile +11 -0
  3. data/README.md +208 -0
  4. data/Rakefile +49 -0
  5. data/VERSION +1 -0
  6. data/demos/html5-form-demo.html +79 -0
  7. data/html5forms-rails.gemspec +142 -0
  8. data/lib/html5forms.rb +6 -0
  9. data/vendor/assets/images/colorpicker/blank.gif +0 -0
  10. data/vendor/assets/images/colorpicker/colorpicker_background.png +0 -0
  11. data/vendor/assets/images/colorpicker/colorpicker_hex.png +0 -0
  12. data/vendor/assets/images/colorpicker/colorpicker_hsb_b.png +0 -0
  13. data/vendor/assets/images/colorpicker/colorpicker_hsb_h.png +0 -0
  14. data/vendor/assets/images/colorpicker/colorpicker_hsb_s.png +0 -0
  15. data/vendor/assets/images/colorpicker/colorpicker_indic.gif +0 -0
  16. data/vendor/assets/images/colorpicker/colorpicker_overlay.png +0 -0
  17. data/vendor/assets/images/colorpicker/colorpicker_rgb_b.png +0 -0
  18. data/vendor/assets/images/colorpicker/colorpicker_rgb_g.png +0 -0
  19. data/vendor/assets/images/colorpicker/colorpicker_rgb_r.png +0 -0
  20. data/vendor/assets/images/colorpicker/colorpicker_select.gif +0 -0
  21. data/vendor/assets/images/colorpicker/colorpicker_submit.png +0 -0
  22. data/vendor/assets/images/colorpicker/custom_background.png +0 -0
  23. data/vendor/assets/images/colorpicker/custom_hex.png +0 -0
  24. data/vendor/assets/images/colorpicker/custom_hsb_b.png +0 -0
  25. data/vendor/assets/images/colorpicker/custom_hsb_h.png +0 -0
  26. data/vendor/assets/images/colorpicker/custom_hsb_s.png +0 -0
  27. data/vendor/assets/images/colorpicker/custom_indic.gif +0 -0
  28. data/vendor/assets/images/colorpicker/custom_rgb_b.png +0 -0
  29. data/vendor/assets/images/colorpicker/custom_rgb_g.png +0 -0
  30. data/vendor/assets/images/colorpicker/custom_rgb_r.png +0 -0
  31. data/vendor/assets/images/colorpicker/custom_submit.png +0 -0
  32. data/vendor/assets/images/colorpicker/select.png +0 -0
  33. data/vendor/assets/images/colorpicker/select2.png +0 -0
  34. data/vendor/assets/images/colorpicker/slider.png +0 -0
  35. data/vendor/assets/images/h5f/form_validation.png +0 -0
  36. data/vendor/assets/images/html5form-shim/asterisk.png +0 -0
  37. data/vendor/assets/images/html5form-shim/down.png +0 -0
  38. data/vendor/assets/images/html5form-shim/fail.png +0 -0
  39. data/vendor/assets/images/html5form-shim/ok.png +0 -0
  40. data/vendor/assets/images/html5forms/jscolor/arrow.gif +0 -0
  41. data/vendor/assets/images/html5forms/jscolor/cross.gif +0 -0
  42. data/vendor/assets/images/html5forms/jscolor/hs.png +0 -0
  43. data/vendor/assets/images/html5forms/jscolor/hv.png +0 -0
  44. data/vendor/assets/images/html5forms/slider/slider-1.png +0 -0
  45. data/vendor/assets/images/html5forms/slider/slider-disabled-1.png +0 -0
  46. data/vendor/assets/images/html5forms/slider/slider-disabled.png +0 -0
  47. data/vendor/assets/images/html5forms/slider/slider.png +0 -0
  48. data/vendor/assets/javascripts/colorpicker.js +484 -0
  49. data/vendor/assets/javascripts/colorpicker.min.js +9 -0
  50. data/vendor/assets/javascripts/h5f.js +328 -0
  51. data/vendor/assets/javascripts/h5f.min.js +4 -0
  52. data/vendor/assets/javascripts/html5forms/EventHelpers.min.js +15 -0
  53. data/vendor/assets/javascripts/html5forms/autocomplete.min.js +1 -0
  54. data/vendor/assets/javascripts/html5forms/cssQuery-p.min.js +6 -0
  55. data/vendor/assets/javascripts/html5forms/dev/EventHelpers.js +486 -0
  56. data/vendor/assets/javascripts/html5forms/dev/autocomplete.js +387 -0
  57. data/vendor/assets/javascripts/html5forms/dev/cssQuery-p.js +6 -0
  58. data/vendor/assets/javascripts/html5forms/dev/html5.js +121 -0
  59. data/vendor/assets/javascripts/html5forms/dev/html5Forms.js +892 -0
  60. data/vendor/assets/javascripts/html5forms/dev/html5Widgets.js +1417 -0
  61. data/vendor/assets/javascripts/html5forms/dev/jscolor.js +840 -0
  62. data/vendor/assets/javascripts/html5forms/dev/slider.js +797 -0
  63. data/vendor/assets/javascripts/html5forms/dev/timer.js +137 -0
  64. data/vendor/assets/javascripts/html5forms/dev/visibleIf.js +1100 -0
  65. data/vendor/assets/javascripts/html5forms/html5.min.js +2 -0
  66. data/vendor/assets/javascripts/html5forms/html5Forms.min.js +1 -0
  67. data/vendor/assets/javascripts/html5forms/html5Widgets.min.js +20 -0
  68. data/vendor/assets/javascripts/html5forms/jscolor.min.js +10 -0
  69. data/vendor/assets/javascripts/html5forms/slider.min.js +25 -0
  70. data/vendor/assets/javascripts/html5forms/timer.min.js +1 -0
  71. data/vendor/assets/javascripts/html5forms/visibleIf.min.js +19 -0
  72. data/vendor/assets/javascripts/html5forms.fallback.js +115 -0
  73. data/vendor/assets/javascripts/html5forms.fallback.min.js +11 -0
  74. data/vendor/assets/javascripts/jquery.html5form-shim.js +402 -0
  75. data/vendor/assets/javascripts/jquery.html5form.min.js +4 -0
  76. data/vendor/assets/javascripts/jquery.placehold.min.js +7 -0
  77. data/vendor/assets/javascripts/ui.spinner.js +649 -0
  78. data/vendor/assets/javascripts/ui.spinner.min.js +7 -0
  79. data/vendor/assets/javascripts/webforms2/webforms2-msie.js +1 -0
  80. data/vendor/assets/javascripts/webforms2/webforms2-p.js +14 -0
  81. data/vendor/assets/javascripts/webforms2/webforms2.js +14 -0
  82. data/vendor/assets/javascripts/webforms2/webforms2_src.js +3195 -0
  83. data/vendor/assets/stylesheets/colorpicker.css +161 -0
  84. data/vendor/assets/stylesheets/h5f.css +86 -0
  85. data/vendor/assets/stylesheets/html5form-shim.css +109 -0
  86. data/vendor/assets/stylesheets/html5forms/number.css +35 -0
  87. data/vendor/assets/stylesheets/html5forms/slider.css +169 -0
  88. data/vendor/assets/stylesheets/html5forms/slider_ie.css +41 -0
  89. data/vendor/assets/stylesheets/html5forms/visibleIf.css +23 -0
  90. data/vendor/assets/stylesheets/html5forms.layout.css +116 -0
  91. data/vendor/assets/stylesheets/ui.spinner.css +3 -0
  92. data/vendor/assets/stylesheets/webforms2.css +42 -0
  93. metadata +221 -0
@@ -0,0 +1,1417 @@
1
+ /*******************************************************************************
2
+ * This notice must be untouched at all times.
3
+ *
4
+ * This javascript library contains helper routines to assist with event
5
+ * handling consinstently among browsers
6
+ *
7
+ * html5Widgets.js v.1.1 by Zoltan Hawryluk
8
+ * latest version and documentation available at http://www.useragentman.com/
9
+ *
10
+ * Changelog:
11
+ * version 1.0: initial release
12
+ * version 1.1: implemented oninput method for form elements for unsupported browsers
13
+ * fix IE9 to ensure backspace and delete keys fire an oninput event.
14
+ * version 1.2: Added Number Element Widget
15
+ *
16
+ * released under the MIT License:
17
+ * http://www.opensource.org/licenses/mit-license.php
18
+ *
19
+ *******************************************************************************/
20
+
21
+ var html5Widgets = new function(){
22
+ var me = this;
23
+
24
+
25
+ var delayEventTimeout = null;
26
+
27
+ me.inputNodes = new Array();
28
+ me.outputNodes = new Array();
29
+ me.formElements = null;
30
+ me.placeholderNodes = new Array();
31
+ me.dummyLink = document.createElement('input');
32
+ var quoteRe = /\"/g;
33
+
34
+ var dummyIDCount = 0;
35
+ var supportsNatively = new Object();
36
+
37
+ var isBadChrome = navigator.userAgent.indexOf('Chrome');
38
+ var valueRe = /this\.value/g;
39
+ var varRe = /([a-zA-Z][a-zA-Z0-9]*\.value)/g;
40
+ var isDebug;
41
+
42
+ var isIE9 = false;
43
+
44
+ /*@cc_on
45
+ @if (@_jscript_version == 9)
46
+ isIE9 = true;
47
+ @end
48
+ @*/
49
+
50
+
51
+
52
+ me.init = function(){
53
+
54
+ if (EventHelpers.hasPageLoadHappened(arguments)) {
55
+ return;
56
+ }
57
+
58
+ supportsNatively['oninput'] = EventHelpers.isSupported('input', 'form');
59
+
60
+ isDebug = CSSHelpers.isMemberOfClass(document.body, 'html5Widgets-debug')
61
+
62
+ // dummy link setup
63
+ me.type = 'text'
64
+ me.dummyLink.style.position = 'absolute';
65
+ me.dummyLink.style.top = '-200px';
66
+ document.body.appendChild(me.dummyLink)
67
+
68
+ var inputSupport = Modernizr.input
69
+
70
+ if (!inputSupport['placeholder']) {
71
+ setPlaceholders();
72
+ }
73
+ indexOutputNodes();
74
+ insertElements();
75
+
76
+ me.resolveOutputs();
77
+
78
+ /* document.getElementById('supports').innerHTML =
79
+ DebugHelpers.getProperties(Modernizr.inputtypes, 'inputtypes') + " " +
80
+ DebugHelpers.getProperties(Modernizr.input, 'input') + " " +
81
+ DebugHelpers.getProperties(Modernizr, 'Modernizr'); */
82
+
83
+ }
84
+
85
+
86
+
87
+ function supports_input_placeholder() {
88
+ var i = document.createElement('input');
89
+ return 'placeholder' in i;
90
+ }
91
+
92
+ function setPlaceholders() {
93
+
94
+ var nodes = [document.getElementsByTagName('input'), document.getElementsByTagName('textarea')];
95
+
96
+ for (var i=0; i<nodes.length; i++) {
97
+ for (var j=0; j<nodes[i].length; j++) {
98
+ var node = nodes[i][j];
99
+
100
+ if (DOMHelpers.getAttributeValue(node, 'placeholder')) {
101
+ me.placeholderNodes.push(new PlaceholderInput(node));
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+
108
+
109
+
110
+
111
+ function getNextDummyID () {
112
+ dummyIDCount ++;
113
+ return "id" + dummyIDCount;
114
+ }
115
+
116
+ function indexOutputNodes () {
117
+ var outputElements = document.getElementsByTagName('output');
118
+ for (var i=0; i<outputElements.length; i++) {
119
+ var outputEl = outputElements[i];
120
+ if (outputEl.value != undefined && outputEl.onforminput != undefined) {
121
+
122
+ // this browser supports the output tag .. bail
123
+ supportsNatively["output"] = true;
124
+ break;
125
+ }
126
+ me.outputNodes.push(new OutputElement(outputEl))
127
+ }
128
+
129
+ me.formElements = document.getElementsByTagName('form');
130
+
131
+ }
132
+
133
+ function setOutputEvents(nodeName) {
134
+ var formElements = document.getElementsByTagName(nodeName);
135
+
136
+ for (var i=0; i<formElements.length; i++) {
137
+ var formElement = formElements[i];
138
+ // first - set event to resolve output tags
139
+ EventHelpers.addEvent(formElement, 'change', me.resolveOutputs);
140
+ EventHelpers.addEvent(formElement, 'keyup', me.resolveOutputs);
141
+ EventHelpers.addEvent(formElement, 'cut', me.resolveOutputs);
142
+ }
143
+ }
144
+
145
+
146
+ function insertElements(){
147
+ var inputSupport = Modernizr.inputtypes;
148
+
149
+
150
+ // Remove the onload event as we are creating the sliders with a JS call
151
+ if (window.fdSliderController) {
152
+ fdSliderController.removeOnLoadEvent();
153
+ }
154
+
155
+ var formElementTypes = ["input", "select", "textarea"];
156
+ for (var i=0; i<formElementTypes.length; i++) {
157
+ setOutputEvents(formElementTypes[i]);
158
+ }
159
+
160
+ var formElements = document.getElementsByTagName('input');
161
+
162
+ // leave if this browser supports the range type.
163
+ if (formElements.length <= 0) {
164
+ return;
165
+ }
166
+
167
+ for (var i = 0; i < formElements.length; i++) {
168
+
169
+
170
+ var formElement = formElements[i];
171
+
172
+
173
+ //var elType = getAttributeValue(formElement, 'type');
174
+ var elType = DOMHelpers.getAttributeValue(formElement, 'type');
175
+ //jslog.debug(elType)
176
+ if (!formElement.name) {
177
+ formElement.name = getNextDummyID();
178
+ }
179
+
180
+ switch (elType) {
181
+
182
+ case "range":
183
+
184
+ if (!inputSupport.range) {
185
+
186
+ me.inputNodes.push(new RangeElement(formElement));
187
+ }
188
+
189
+ break;
190
+
191
+ case "date":
192
+ case "week":
193
+ case "month":
194
+ case "datetime":
195
+ case "datetime-local":
196
+
197
+ // check to see if the browser supports the type.
198
+ if (!inputSupport[elType] || (window.html5Forms && html5Forms.forceJSDatePicker)) {
199
+ me.inputNodes.push(new CalendarElement(formElement, elType));
200
+ }
201
+ break;
202
+ case "color":
203
+ if (!inputSupport.color || isBadChrome) {
204
+ me.inputNodes.push(new ColorElement(formElement, elType));
205
+ }
206
+
207
+ break;
208
+ case "number":
209
+
210
+ if (!inputSupport.number) {
211
+ me.inputNodes.push(new NumberElement(formElement, elType));
212
+ }
213
+
214
+ break;
215
+ }
216
+
217
+ }
218
+
219
+
220
+
221
+ if (window.fdSliderController) {
222
+ fdSliderController.redrawAll();
223
+ }
224
+
225
+ if (window.jscolor) {
226
+ jscolor.init();
227
+ }
228
+ }
229
+
230
+
231
+
232
+
233
+ function delayedFireEvent(el, ev, callback){
234
+
235
+ if (!document.createEventObject ) {
236
+ me.fireEvent(el, ev);
237
+ if (callback) {
238
+ callback();
239
+ }
240
+ }
241
+ else {
242
+
243
+
244
+ if (delayEventTimeout != null) {
245
+ clearTimeout(delayEventTimeout)
246
+ }
247
+
248
+ delayEventTimeout = setTimeout(
249
+ function(){
250
+ EventHelpers.fireEvent(el, ev);
251
+
252
+ if (callback) {
253
+ callback();
254
+ }
255
+ }
256
+ , 1);
257
+
258
+ }
259
+ }
260
+
261
+ me.fireEvent = function(el, ev){
262
+ EventHelpers.fireEvent(el, ev);
263
+ }
264
+
265
+ me.resolveOutputs = function (e) {
266
+
267
+ // This resolves the onforminput events on the output nodes
268
+ for (var i=0; i<me.outputNodes.length; i++) {
269
+ var outputNode = me.outputNodes[i];
270
+ outputNode.resolve();
271
+ }
272
+
273
+ // This resolves the oninput events on the form nodes
274
+ if (!supportsNatively['oninput']) {
275
+ for (var i=0; i<me.formElements.length; i++) {
276
+ var formNode = me.formElements[i];
277
+ var oninput = DOMHelpers.getAttributeValue(formNode, 'oninput');
278
+ if (oninput) {
279
+ eval(me.getValueFormula(oninput, formNode));
280
+ }
281
+ }
282
+ } else if (isIE9 && e) {
283
+ // must deal with buggy implementation - delete and backspace don't fire
284
+ // the oninput event
285
+ var input = EventHelpers.getEventTarget(e);
286
+ switch (e.type) {
287
+
288
+ case "keyup":
289
+ var key = EventHelpers.getKey(e);
290
+
291
+ switch (key) {
292
+ case 8:
293
+ case 46:
294
+ case 88:
295
+ EventHelpers.fireEvent(input.form, 'input');
296
+ }
297
+ break;
298
+ case "cut":
299
+ delayedFireEvent(input.form, 'input');
300
+ break;
301
+ }
302
+
303
+ }
304
+ }
305
+
306
+ me.hideInput = function (node) {
307
+
308
+ node.style.position = 'absolute';
309
+ node.style.top = '-1000px';
310
+ node.style.left = '-1000px';
311
+ node.style.visibility = 'hidden'
312
+ }
313
+
314
+ me.getValueFormula = function(expr, parentForm) {
315
+ var formula = expr
316
+ if (formula == null) {
317
+ return null;
318
+ }
319
+ formula = formula
320
+ .replace(valueRe, 'value')
321
+ .replace(varRe, 'document.forms["' + parentForm.id + '"].$1');
322
+ return formula;
323
+ }
324
+
325
+
326
+ function showError(err) {
327
+ if (isDebug) {
328
+ alert(err);
329
+ }
330
+ throw(err);
331
+ }
332
+
333
+
334
+
335
+ /*
336
+ * Range Element
337
+ */
338
+
339
+ function RangeElement(node){
340
+ var me = this,
341
+ parentForm,
342
+ hasFiredChangeEvent = false;
343
+
344
+ me.node = node;
345
+ me.sliderNode = null;
346
+
347
+
348
+ function init (){
349
+ parentForm = DOMHelpers.getAncestorByTagName(node, 'form');
350
+ var min = parseFloat(DOMHelpers.getAttributeValue(me.node, 'min'));
351
+ var max = parseFloat(DOMHelpers.getAttributeValue(me.node, 'max'));
352
+
353
+ if (!window.fdSliderController) {
354
+ showError("slider.js must be included in order for the range element to work in this browser. See documentation for more details.");
355
+ }
356
+
357
+ if (isNaN(min)) {
358
+ min = 0;
359
+ }
360
+
361
+ if (isNaN(max)) {
362
+ max = 100;
363
+ }
364
+
365
+
366
+ var step = DOMHelpers.getAttributeValue(me.node, 'step');
367
+
368
+ if (step == null) {
369
+ step = "1"
370
+ } else if (typeof(step) == 'number') {
371
+ step = step + "";
372
+ }
373
+
374
+ // Must add id if not there (Requirement of the script)
375
+ if (!me.node.id) {
376
+ me.node.id = "HTML5Form-slider" + getNextDummyID();
377
+ }
378
+
379
+
380
+
381
+ // Create an Object to hold the slider's initialisation data
382
+ var options = {
383
+ // A reference to the input
384
+ inp: me.node,
385
+ // A String containing the increment value (and the return precision, in this case 2 decimal places "x.20")
386
+ inc: step,
387
+ // Maximum keyboard increment (automatically uses double the normal increment if not given)
388
+ maxInc: step,
389
+ // Numeric range
390
+ range: [min, max],
391
+ // Callback functions
392
+ callbacks: {
393
+ "update": [me.changeEvent]
394
+ },
395
+ // String representing the classNames to give the created slider
396
+ classNames: "html5Widgets-slider fd_jump",
397
+ // Tween the handle onclick?
398
+ tween: false,
399
+ // Is this a vertical slider
400
+ vertical: false,
401
+ // Do we hide the associated input on slider creation
402
+ hideInput: false,
403
+ // Does the handle jump to the nearest click value point when the bar is clicked (tween cannot then be true)
404
+ clickJump: true,
405
+ // Full ARIA required
406
+ fullARIA: false,
407
+ // Do we disable the mouseWheel for this slider
408
+ noMouseWheel: false
409
+
410
+ };
411
+
412
+ // Create the slider
413
+ fdSliderController.createSlider(options);
414
+
415
+ //tweak styles
416
+ me.sliderNode = document.getElementById('fd-slider-' + me.node.id);
417
+ me.sliderNode.style.width = me.node.offsetWidth + "px";
418
+
419
+ elDisplay = me.node.style.display
420
+ if (elDisplay != 'block') {
421
+ me.sliderNode.style.display = 'inline-block';
422
+ //me.sliderNode.style.paddingTop = "0.9em";
423
+ }
424
+
425
+ html5Widgets.hideInput(me.node);
426
+
427
+ document.getElementById('fd-slider-' + me.node.id).style.zIndex = '0';
428
+
429
+ me.node.tabIndex = "-1";
430
+ me.node.type = "text";
431
+
432
+ // Event Handling
433
+ EventHelpers.addEvent(me.node, 'change', changeOriginalNodeEvent);
434
+ }
435
+
436
+ me.changeEvent = function (e){
437
+ var oninput = DOMHelpers.getAttributeValue(parentForm, 'oninput');
438
+
439
+ if (oninput) {
440
+ eval(html5Widgets.getValueFormula(oninput, parentForm));
441
+ }
442
+
443
+ /* The if statement is to prevent this to continuously fire in an endless loop */
444
+ if (!hasFiredChangeEvent) {
445
+ hasFiredChangeEvent = true;
446
+ delayedFireEvent(me.node, 'change', function () {
447
+ hasFiredChangeEvent = false;
448
+ });
449
+ }
450
+ }
451
+
452
+ function changeOriginalNodeEvent(e) {
453
+
454
+ fdSliderController.updateSlider(me.node.id);
455
+ }
456
+
457
+ init();
458
+
459
+ }
460
+
461
+ function CalendarElement (node, type) {
462
+ var me = this;
463
+
464
+ me.node = node;
465
+ me.type = type;
466
+
467
+ var badDateTimeValueRe =
468
+ /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}Z{0,1}$/;
469
+ var displayDateTimeValueRe =
470
+ /^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$/;
471
+ var originalVisibilityState;
472
+
473
+ function init() {
474
+
475
+ if (!window.Calendar && isDebug) {
476
+ showError("jscalendar scripts and CSS must be included for date and time form elements to work. See documentation for more details. ")
477
+ }
478
+
479
+ // Must add id if not there (Requirement of the script)
480
+ if (!me.node.id) {
481
+ me.node.id = "HTML5Form-calendar" + getNextDummyID();
482
+ }
483
+
484
+ /*
485
+ * If this is the result of coming back to the page from history,
486
+ * then it may have an old reformatted version in it from a previous
487
+ * submit. Let's re-format it back.
488
+ */
489
+
490
+ prepareForDisplay();
491
+
492
+
493
+ var formatString = "";
494
+ switch (me.type) {
495
+ case 'date':
496
+ formatString = "%Y-%m-%d";
497
+ break;
498
+ case 'month':
499
+ formatString = "%Y-%m";
500
+ break;
501
+ case 'week':
502
+ formatString = "%Y-W%W";
503
+ break;
504
+ case 'datetime':
505
+ placeUTCInfo();
506
+ case 'datetime-local':
507
+ case 'datetime':
508
+ formatString = "%Y-%m-%d %H:%M"
509
+ break;
510
+ }
511
+
512
+ /*
513
+ * Chrome, unfortunately, only implements type="date", and it's
514
+ * implementation displays the data in DD/MM/YYYY format. Even
515
+ * though it submits the data in YYYY-MM-DD format, this can
516
+ * be confusing to users if there is a, say, datetime widget
517
+ * with a date widget and they show different formats. In order
518
+ * to fix this, I change the type to "text" so that it uses the
519
+ * polyfill instead of the native one. Note that type="date"
520
+ * widgets in Chrome are only changed to type="text" when
521
+ * html5Forms.js's script tag has its
522
+ * data-webforms2-force-js-date-picker attribute set to "true".
523
+ */
524
+ me.node.type = 'text';
525
+
526
+ //me.node.readOnly = true;
527
+
528
+
529
+
530
+ Calendar.setup(
531
+ {
532
+ eventName :"click",
533
+ showsTime : type.indexOf('time') >= 0,
534
+ cache : true,
535
+ inputField : me.node.id, // ID of the input field
536
+ ifFormat : formatString, // the date format
537
+ button : me.node.id // ID of the button
538
+ }
539
+ );
540
+
541
+
542
+
543
+
544
+
545
+ EventHelpers.addEvent(me.node, 'click', forceCalToTop);
546
+ EventHelpers.addEvent(me.node, 'focus', focusEvent)
547
+ EventHelpers.addEvent(me.node, 'keypress', openCalendar);
548
+ EventHelpers.addEvent(me.node, 'blur', closeCalendar);
549
+
550
+ EventHelpers.addEvent(me.node, 'keypress', keydownEvent)
551
+ //me.node.type = "text";
552
+
553
+ // this will call submitEvent() after the form has been validated by
554
+ // webforms2.js
555
+ if (window.$wf2) {
556
+ $wf2.callBeforeValidation.push(prepareForSubmission);
557
+ $wf2.callAfterValidation.push(validationEvent);
558
+ }
559
+
560
+ }
561
+
562
+ function placeUTCInfo() {
563
+
564
+ var label = document.createElement('span');
565
+ label.innerHTML = "UTC";
566
+ label.style.paddingLeft = "5px";
567
+
568
+ DOMHelpers.insertAfter(me.node, label);
569
+
570
+ var width = label.offsetWidth;
571
+
572
+ me.node.style.width = (me.node.offsetWidth - 5 - width) + 'px';
573
+
574
+ }
575
+
576
+ function prepareForSubmission() {
577
+ var splitVals;
578
+
579
+ switch (me.type) {
580
+ case "datetime":
581
+ case "datetime-local":
582
+
583
+ originalVisibilityState = me.node.style.visibility;
584
+ me.node.style.visibility = 'hidden';
585
+ if (me.node.value.match(displayDateTimeValueRe)) {
586
+ splitVals = me.node.value.split(' ');
587
+ me.node.value = splitVals[0] + "T" + splitVals[1];
588
+ }
589
+
590
+ switch (me.type) {
591
+ case "datetime-local":
592
+ break;
593
+ case "datetime":
594
+ if (me.node.value != "") {
595
+ me.node.value += "Z";
596
+ }
597
+ }
598
+
599
+ }
600
+ }
601
+
602
+ function prepareForDisplay() {
603
+ switch(me.type) {
604
+ case "datetime":
605
+ case "datetime-local":
606
+ if ( me.node.value.match(badDateTimeValueRe)) {
607
+ me.node.value = me.node.value.replace(/T/, ' ').replace(/Z/, '');
608
+ }
609
+ if (originalVisibilityState != null) {
610
+ me.node.style.visibility = originalVisibilityState;
611
+ }
612
+
613
+ }
614
+
615
+
616
+ }
617
+
618
+ function validationEvent(e, hasValidated) {
619
+ if (!hasValidated) {
620
+ prepareForDisplay();
621
+ }
622
+ }
623
+
624
+ function forceCalToTop(e) {
625
+ var cal = window.calendar;
626
+
627
+ cal.element.style.zIndex = 100;
628
+ }
629
+
630
+ function focusEvent(e) {
631
+ var el = EventHelpers.getEventTarget(e);
632
+ EventHelpers.fireEvent(el, 'click')
633
+ }
634
+
635
+ function openCalendar(e) {
636
+
637
+ var cal = window.calendar;
638
+
639
+ cal.element.style.zIndex = 100;
640
+ if (cal.open != undefined) {
641
+ cal.open();
642
+ }
643
+ //EventHelpers.fireEvent(this, 'blur');
644
+ //EventHelpers.fireEvent(this, 'focus');
645
+ }
646
+
647
+ function closeCalendar(e){
648
+
649
+ var cal = window.calendar;
650
+ if (cal) {
651
+ cal.hide();
652
+ }
653
+ }
654
+
655
+ function keydownEvent(e) {
656
+
657
+ var c = EventHelpers.getKey(e);
658
+
659
+ switch(c){
660
+ case 13:
661
+ html5Widgets.dummyLink.focus();
662
+ this.focus();
663
+ EventHelpers.preventDefault(e);
664
+ openCalendar(e);
665
+ break;
666
+ case 9:
667
+ closeCalendar(e);
668
+ break;
669
+ default:
670
+ EventHelpers.preventDefault(e);
671
+ break;
672
+ }
673
+
674
+
675
+ }
676
+
677
+ function submitEvent(e) {
678
+ prepareForSubmission();
679
+ }
680
+
681
+ init();
682
+
683
+ }
684
+
685
+
686
+
687
+
688
+
689
+
690
+
691
+ /*
692
+ * Output Element
693
+ */
694
+ function OutputElement (node) {
695
+ var me = this;
696
+ me.node = node;
697
+
698
+ var value;
699
+ var valueFormula;
700
+ var parentForm;
701
+
702
+
703
+
704
+ function init () {
705
+ parentForm = DOMHelpers.getAncestorByTagName(node, 'form');
706
+ if (!parentForm.id) {
707
+ parentForm.id = getNextDummyID();
708
+ }
709
+
710
+ valueFormula = html5Widgets.getValueFormula(DOMHelpers.getAttributeValue(me.node, 'onforminput'), parentForm);
711
+ }
712
+
713
+
714
+
715
+ me.resolve = function () {
716
+ if (valueFormula == null) {
717
+ return;
718
+ } else {
719
+ eval(valueFormula);
720
+ me.node.innerHTML = value;
721
+ me.node.value = value;
722
+ }
723
+
724
+ }
725
+
726
+
727
+ init();
728
+ }
729
+
730
+ function ColorElement (node) {
731
+ var me = this;
732
+
733
+ /* note: color picker setPad() is what you are looking for */
734
+ me.node = node;
735
+
736
+ function init () {
737
+ if (!window.jscolor) {
738
+ showError('jscolor script must be included in order for the color input type to work in this browser. See documentation for more details.')
739
+ }
740
+ CSSHelpers.addClass(me.node, 'color');
741
+ CSSHelpers.addClass(me.node, '{hash:true,caps:false}');
742
+ me.node.type = "text";
743
+ }
744
+
745
+
746
+ init();
747
+ }
748
+
749
+ /*
750
+ * NumberElement: refactored from http://www.kethinov.com/jsstepper.php.
751
+ */
752
+
753
+ function NumberElement (node) {
754
+ var me = this,
755
+ min = parseFloat(DOMHelpers.getAttributeValue(node, 'min')),
756
+ max = parseFloat(DOMHelpers.getAttributeValue(node, 'max')),
757
+ step = parseFloat(DOMHelpers.getAttributeValue(node, 'step'));
758
+
759
+ me.node = node;
760
+
761
+
762
+
763
+ if (isNaN(step)) {
764
+ // we don't have to create the up and down arraw widgets
765
+ return;
766
+ }
767
+
768
+ EventHelpers.addEvent(node, 'keyup', keyUpEvent);
769
+
770
+
771
+ function keyUpEvent() {
772
+
773
+ if (isNumeric(this.value)) {
774
+
775
+ /* if (this.value > max) this.value = max;
776
+ else if (this.value < min) this.value = this.min; */
777
+
778
+ } else if (this.value != '') {
779
+ var val = parseFloat(this.value);
780
+ if (isNaN(val)) {
781
+ this.value = '';
782
+ } else {
783
+ this.value = val;
784
+ }
785
+ }
786
+
787
+ }
788
+
789
+
790
+
791
+ function nearestValid(value, direction) {
792
+
793
+ var n = (value - min)/step,
794
+ r;
795
+ //alert(StringHelpers.sprintf("n: %s, value: %s, min: %s, step: %s", n, value, min, step))
796
+ if (n == parseInt(n)) {
797
+ r = value;
798
+ } else {
799
+
800
+ if (direction < 0) {
801
+ n = Math.floor(n + 1);
802
+ } else {
803
+ n = Math.ceil(n -1);
804
+ }
805
+
806
+ r = min + step * n;
807
+ }
808
+
809
+ if (r > max) {
810
+ r -= step;
811
+ } else if (r < min) {
812
+ r+= step
813
+ }
814
+
815
+ return r;
816
+ }
817
+
818
+ function buttonMouseDownEvent(e) {
819
+
820
+ var buttonType = this.className;
821
+ var stepMult = step;
822
+ if (buttonType == 'dnbutton') {
823
+ stepMult = -step;
824
+ }
825
+
826
+
827
+ var min = this.min;
828
+ var max = this.max;
829
+ if (
830
+ (stepMult < 0 && (node.value > min || isNaN(min))) ||
831
+ (stepMult > 0 && (node.value < max || isNaN(max)))
832
+ ) {
833
+ setValue(me.node, nearestValid(parseFloat(node.value) + stepMult, stepMult));
834
+ }
835
+
836
+ var delayedOnce = false;
837
+ var date = new Date();
838
+ var curDate = null;
839
+
840
+ this.interval = setInterval(function() {
841
+ if (!delayedOnce) {
842
+ curDate = new Date();
843
+ if (curDate - date > 500) delayedOnce = true;
844
+ }
845
+ else if (
846
+ (stepMult < 0 && (node.value > min || isNaN(min))) ||
847
+ (stepMult > 0 && (node.value < max || isNaN(max)))
848
+ ) {
849
+ setValue(me.node, nearestValid(parseFloat(node.value) + stepMult, stepMult));
850
+ }
851
+ }, 50);
852
+ EventHelpers.preventDefault(e);
853
+ }
854
+
855
+ function setValue(node, value) {
856
+ if (isNaN(value)) {
857
+ node.value = '';
858
+ } else {
859
+ node.value = value;
860
+ }
861
+ }
862
+
863
+ function buttonClickEvent(e) {
864
+ clearInterval(this.interval);
865
+ EventHelpers.preventDefault(e);
866
+ }
867
+ function buttonMouseUpEvent(e) {
868
+ clearInterval(this.interval);
869
+ EventHelpers.preventDefault(e);
870
+ }
871
+
872
+ function isNumeric(n) {
873
+ return !isNaN(parseFloat(n)) && isFinite(n);
874
+ }
875
+
876
+
877
+ function hasNativeSpinner() {
878
+ try {
879
+ return window.getComputedStyle(me.node, '-webkit-inner-spin-button').WebkitAppearance != undefined;
880
+ } catch (ex) {
881
+ return false;
882
+ }
883
+ }
884
+
885
+ function init () {
886
+ var upbutton = document.createElement('a');
887
+ upbutton.className = 'upbutton';
888
+ upbutton.appendChild(document.createTextNode("\u25B2"));
889
+ upbutton.targInput = node;
890
+ upbutton.max = max;
891
+
892
+ var dnbutton = document.createElement('a');
893
+ dnbutton.className = 'dnbutton';
894
+ dnbutton.appendChild(document.createTextNode("\u25BC"));
895
+ dnbutton.targInput = node;
896
+ dnbutton.min = min;
897
+ dnbutton.max = max;
898
+
899
+ EventHelpers.addEvent(upbutton, 'mousedown', buttonMouseDownEvent);
900
+ EventHelpers.addEvent(dnbutton, 'mousedown', buttonMouseDownEvent);
901
+
902
+ EventHelpers.addEvent(upbutton, 'click', buttonClickEvent);
903
+ EventHelpers.addEvent(upbutton, 'mouseup', buttonMouseUpEvent);
904
+ EventHelpers.addEvent(dnbutton, 'click', buttonClickEvent);
905
+ EventHelpers.addEvent(dnbutton, 'mouseup', buttonMouseUpEvent);
906
+
907
+
908
+ if (!hasNativeSpinner()) {
909
+ var controlsNode = document.createElement('div');
910
+ controlsNode.className = 'html5-numberControls';
911
+ controlsNode.appendChild(upbutton);
912
+ controlsNode.appendChild(dnbutton);
913
+
914
+ var wrapperNode = document.createElement('div')
915
+ wrapperNode.className = 'html5-numberWrapper';
916
+ wrapperNode.appendChild(controlsNode);
917
+ var parentNode = node.parentNode;
918
+
919
+
920
+
921
+
922
+ parentNode.insertBefore(wrapperNode, node);
923
+
924
+
925
+ var nodeWidth = node.offsetWidth;
926
+ var nodeStyle = CSSHelpers.getCurrentStyle(node);
927
+
928
+ node.style.width = (nodeWidth - upbutton.offsetWidth -9) + 'px';
929
+ wrapperNode.style.width = nodeWidth + 'px';
930
+ wrapperNode.style.marginTop = nodeStyle.marginTop;
931
+ wrapperNode.style.height = (node.offsetHeight) + 'px';
932
+ }
933
+
934
+
935
+
936
+ }
937
+ /* Finally: if the form field has a value onload that is not a number, remove it
938
+ if (!isNumeric(node.value)) {
939
+ node.value = '';
940
+ EventHelpers.fireEvent(node, 'change');
941
+ }*/
942
+ init();
943
+ }
944
+
945
+ function PlaceholderInput (node) {
946
+ var me = this;
947
+
948
+ me.node = node;
949
+
950
+ var form, defaultText;
951
+
952
+ function init () {
953
+ defaultText = DOMHelpers.getAttributeValue(node, 'placeholder');
954
+ form = DOMHelpers.getAncestorByTagName(node, 'form');
955
+
956
+ me.setPlaceholderText(true);
957
+ EventHelpers.addEvent(me.node, 'blur', blurEvent);
958
+ EventHelpers.addEvent(me.node, 'focus', focusEvent);
959
+
960
+ if (me.node.form) {
961
+ EventHelpers.addEvent(me.node.form, 'submit', removePlaceholderText);
962
+ }
963
+
964
+ if (window.$wf2) {
965
+ if ($wf2.callBeforeValidation != undefined) {
966
+ $wf2.callBeforeValidation.push(removePlaceholderText);
967
+ }
968
+
969
+ if ($wf2.callAfterValidation != undefined) {
970
+ $wf2.callAfterValidation.push(postValidationEvent);
971
+ }
972
+ }
973
+ }
974
+
975
+ me.setPlaceholderText = function (isLoadEvent) {
976
+ //jslog.debug(StringHelpers.sprintf('initiator: %s', this));
977
+ var isAutofocus = DOMHelpers.getAttributeValue(me.node, 'autofocus') != null;
978
+
979
+
980
+ if (me.node.value == "" || (isLoadEvent && me.node.value == defaultText)) {
981
+ CSSHelpers.addClass(me.node, 'html5-hasPlaceholderText');
982
+ me.node.value = defaultText;
983
+
984
+ }
985
+
986
+ if (isLoadEvent && isAutofocus && me.node.value == defaultText ) {
987
+ CSSHelpers.removeClass(me.node, 'html5-hasPlaceholderText');
988
+ me.node.value = '';
989
+ }
990
+
991
+
992
+
993
+ }
994
+
995
+ function focusEvent(e) {
996
+
997
+ CSSHelpers.addClass(me.node, 'html5-hasFocus');
998
+ removePlaceholderText();
999
+ }
1000
+
1001
+ function blurEvent(e) {
1002
+ //jslog.debug('removed focus on ' + me.node.name)
1003
+ CSSHelpers.removeClass(me.node, 'html5-hasFocus');
1004
+ me.setPlaceholderText();
1005
+ }
1006
+
1007
+ function removePlaceholderText() {
1008
+ //jslog.debug('removePlaceholderText() for ' + me.node.name)
1009
+ if (CSSHelpers.isMemberOfClass(me.node, 'html5-hasPlaceholderText')) {
1010
+ me.node.value = "";
1011
+ CSSHelpers.removeClass(me.node, 'html5-hasPlaceholderText');
1012
+ }
1013
+ }
1014
+
1015
+ function postValidationEvent(e, didValidate) {
1016
+ ////jslog.debug(StringHelpers.sprintf('post Validation: %s, didValidate = %s, has focus = %s', me.node.name, didValidate, CSSHelpers.isMemberOfClass(me.node, 'html5-hasFocus') ) )
1017
+ if (!didValidate && !CSSHelpers.isMemberOfClass(me.node, 'html5-hasFocus')) {
1018
+ me.setPlaceholderText();
1019
+ }
1020
+ }
1021
+
1022
+ init();
1023
+ }
1024
+
1025
+ var CSSHelpers = new function () {
1026
+ var me = this;
1027
+
1028
+ var blankRe = new RegExp('\\s');
1029
+
1030
+ /**
1031
+ * Generates a regular expression string that can be used to detect a class name
1032
+ * in a tag's class attribute. It is used by a few methods, so I
1033
+ * centralized it.
1034
+ *
1035
+ * @param {String} className - a name of a CSS class.
1036
+ */
1037
+
1038
+ function getClassReString(className) {
1039
+ return '\\s'+className+'\\s|^' + className + '\\s|\\s' + className + '$|' + '^' + className +'$';
1040
+ }
1041
+
1042
+ function getClassPrefixReString(className) {
1043
+ return '\\s'+className+'-[0-9a-zA-Z_]+\\s|^' + className + '[0-9a-zA-Z_]+\\s|\\s' + className + '[0-9a-zA-Z_]+$|' + '^' + className +'[0-9a-zA-Z_]+$';
1044
+ }
1045
+
1046
+
1047
+ /**
1048
+ * Make an HTML object be a member of a certain class.
1049
+ *
1050
+ * @param {Object} obj - an HTML object
1051
+ * @param {String} className - a CSS class name.
1052
+ */
1053
+ me.addClass = function (obj, className) {
1054
+
1055
+ if (blankRe.test(className)) {
1056
+ return;
1057
+ }
1058
+
1059
+ // only add class if the object is not a member of it yet.
1060
+ if (!me.isMemberOfClass(obj, className)) {
1061
+ obj.className += " " + className;
1062
+ }
1063
+
1064
+ }
1065
+
1066
+ /**
1067
+ * Make an HTML object *not* be a member of a certain class.
1068
+ *
1069
+ * @param {Object} obj - an HTML object
1070
+ * @param {Object} className - a CSS class name.
1071
+ */
1072
+ me.removeClass = function (obj, className) {
1073
+
1074
+ if (blankRe.test(className)) {
1075
+ return;
1076
+ }
1077
+
1078
+
1079
+ var re = new RegExp(getClassReString(className) , "g");
1080
+
1081
+ var oldClassName = obj.className;
1082
+
1083
+
1084
+ if (obj.className) {
1085
+ obj.className = oldClassName.replace(re, ' ');
1086
+ }
1087
+
1088
+ }
1089
+
1090
+ /**
1091
+ * Determines if an HTML object is a member of a specific class.
1092
+ * @param {Object} obj - an HTML object.
1093
+ * @param {Object} className - the CSS class name.
1094
+ */
1095
+ me.isMemberOfClass = function (obj, className) {
1096
+
1097
+ if (blankRe.test(className))
1098
+ return false;
1099
+
1100
+ var re = new RegExp(getClassReString(className) , "g");
1101
+
1102
+ return (re.test(obj.className));
1103
+
1104
+
1105
+ }
1106
+
1107
+ /* from http://blog.stchur.com/2006/06/21/css-computed-style/ */
1108
+ me.getCurrentStyle = function(obj)
1109
+ {
1110
+ var computedStyle;
1111
+ if (typeof obj.currentStyle != 'undefined')
1112
+ { computedStyle = obj.currentStyle; }
1113
+ else
1114
+ { computedStyle = document.defaultView.getComputedStyle(obj, null); }
1115
+
1116
+ return computedStyle;
1117
+ }
1118
+ }
1119
+
1120
+
1121
+
1122
+ var DOMHelpers = new function () {
1123
+ var me = this;
1124
+
1125
+ /**
1126
+ * Given an HTML or XML object, find the an attribute by name.
1127
+ *
1128
+ * @param {Object} obj - a DOM object.
1129
+ * @param {String} attrName - the name of an attribute inside the DOM object.
1130
+ * @return {Object} - the attribute object or null if there isn't one.
1131
+ */
1132
+ me.getAttributeByName = function (obj, attrName) {
1133
+ var i;
1134
+
1135
+ var attributes = obj.attributes;
1136
+ for (i=0; i<attributes.length; i++) {
1137
+ var attr = attributes[i]
1138
+ if (attr.nodeName == attrName && attr.specified) {
1139
+ return attr;
1140
+ }
1141
+ }
1142
+ return null;
1143
+ }
1144
+ /**
1145
+ * Given an HTML or XML object, find the value of an attribute.
1146
+ *
1147
+ * @param {Object} obj - a DOM object.
1148
+ * @param {String} attrName - the name of an attribute inside the DOM object.
1149
+ * @return {String} - the value of the attribute.
1150
+ */
1151
+ me.getAttributeValue = function (obj, attrName) {
1152
+ var attr = me.getAttributeByName(obj, attrName);
1153
+
1154
+ if (attr != null) {
1155
+ return attr.nodeValue;
1156
+ } else {
1157
+ var typeRe = new RegExp(attrName + '=(\\"([a-zA-Z\-]*)\\"|[a-zA-Z\-]*)');
1158
+ //jslog.debug(XMLHelpers.getOuterXML(obj))
1159
+ var typeVal = XMLHelpers.getOuterXML(obj).split('>')[0].match(typeRe);
1160
+ //jslog.debug(typeVal)
1161
+ if (typeVal && typeVal.length >= 1) {
1162
+ return typeVal[1].replace(quoteRe, '');
1163
+ } else {
1164
+ return null;
1165
+ }
1166
+
1167
+ }
1168
+ }
1169
+
1170
+ me.insertAfter = function (refNode, nodeToInsert) {
1171
+ var parent = refNode.parentNode;
1172
+
1173
+ var nextSibling = refNode.nextSibling;
1174
+ if (nextSibling) {
1175
+ parent.insertBefore(nodeToInsert, nextSibling);
1176
+ } else {
1177
+ parent.appendChild(nodeToInsert);
1178
+ }
1179
+ }
1180
+
1181
+ /**
1182
+ * Given an tag, find the first ancestor tag of a given tag name.
1183
+ *
1184
+ * @param {Object} obj - a HTML or XML tag.
1185
+ * @param {String} tagName - the name of the ancestor tag to find.
1186
+ * @return {Object} - the ancestor tag, or null if not found.
1187
+ */
1188
+ me.getAncestorByTagName = function(obj, tagName) {
1189
+
1190
+ for (var node = obj.parentNode;
1191
+ node.nodeName.toLowerCase() != 'body';
1192
+ node = node.parentNode) {
1193
+
1194
+ if (tagName.toLowerCase() == node.nodeName.toLowerCase()) {
1195
+ return node;
1196
+ }
1197
+
1198
+ }
1199
+ return null;
1200
+ }
1201
+
1202
+ me.removeNode = function (node) {
1203
+ var parentNode = node.parentNode;
1204
+ if (parentNode) {
1205
+ parentNode.removeChild(node);
1206
+ }
1207
+ }
1208
+
1209
+ }
1210
+
1211
+ var StringHelpers = new function () {
1212
+ var me = this;
1213
+
1214
+ /*******************************************************************************
1215
+ * Function sprintf(format_string,arguments...) Javascript emulation of the C
1216
+ * printf function (modifiers and argument types "p" and "n" are not supported
1217
+ * due to language restrictions)
1218
+ *
1219
+ * Copyright 2003 K&L Productions. All rights reserved
1220
+ * http://www.klproductions.com
1221
+ *
1222
+ * Terms of use: This function can be used free of charge IF this header is not
1223
+ * modified and remains with the function code.
1224
+ *
1225
+ * Legal: Use this code at your own risk. K&L Productions assumes NO
1226
+ * resposibility for anything.
1227
+ ******************************************************************************/
1228
+ me.sprintf = function (fstring)
1229
+ { var pad = function(str,ch,len)
1230
+ { var ps='';
1231
+ for(var i=0; i<Math.abs(len); i++) ps+=ch;
1232
+ return len>0?str+ps:ps+str;
1233
+ }
1234
+ var processFlags = function(flags,width,rs,arg)
1235
+ { var pn = function(flags,arg,rs)
1236
+ { if(arg>=0)
1237
+ { if(flags.indexOf(' ')>=0) rs = ' ' + rs;
1238
+ else if(flags.indexOf('+')>=0) rs = '+' + rs;
1239
+ }
1240
+ else
1241
+ rs = '-' + rs;
1242
+ return rs;
1243
+ }
1244
+ var iWidth = parseInt(width,10);
1245
+ if(width.charAt(0) == '0')
1246
+ { var ec=0;
1247
+ if(flags.indexOf(' ')>=0 || flags.indexOf('+')>=0) ec++;
1248
+ if(rs.length<(iWidth-ec)) rs = pad(rs,'0',rs.length-(iWidth-ec));
1249
+ return pn(flags,arg,rs);
1250
+ }
1251
+ rs = pn(flags,arg,rs);
1252
+ if(rs.length<iWidth)
1253
+ { if(flags.indexOf('-')<0) rs = pad(rs,' ',rs.length-iWidth);
1254
+ else rs = pad(rs,' ',iWidth - rs.length);
1255
+ }
1256
+ return rs;
1257
+ }
1258
+ var converters = new Array();
1259
+ converters['c'] = function(flags,width,precision,arg)
1260
+ { if(typeof(arg) == 'number') return String.fromCharCode(arg);
1261
+ if(typeof(arg) == 'string') return arg.charAt(0);
1262
+ return '';
1263
+ }
1264
+ converters['d'] = function(flags,width,precision,arg)
1265
+ { return converters['i'](flags,width,precision,arg);
1266
+ }
1267
+ converters['u'] = function(flags,width,precision,arg)
1268
+ { return converters['i'](flags,width,precision,Math.abs(arg));
1269
+ }
1270
+ converters['i'] = function(flags,width,precision,arg)
1271
+ { var iPrecision=parseInt(precision);
1272
+ var rs = ((Math.abs(arg)).toString().split('.'))[0];
1273
+ if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
1274
+ return processFlags(flags,width,rs,arg);
1275
+ }
1276
+ converters['E'] = function(flags,width,precision,arg)
1277
+ { return (converters['e'](flags,width,precision,arg)).toUpperCase();
1278
+ }
1279
+ converters['e'] = function(flags,width,precision,arg)
1280
+ { iPrecision = parseInt(precision);
1281
+ if(isNaN(iPrecision)) iPrecision = 6;
1282
+ rs = (Math.abs(arg)).toExponential(iPrecision);
1283
+ if(rs.indexOf('.')<0 && flags.indexOf('#')>=0) rs = rs.replace(/^(.*)(e.*)$/,'$1.$2');
1284
+ return processFlags(flags,width,rs,arg);
1285
+ }
1286
+ converters['f'] = function(flags,width,precision,arg)
1287
+ { iPrecision = parseInt(precision);
1288
+ if(isNaN(iPrecision)) iPrecision = 6;
1289
+ rs = (Math.abs(arg)).toFixed(iPrecision);
1290
+ if(rs.indexOf('.')<0 && flags.indexOf('#')>=0) rs = rs + '.';
1291
+ return processFlags(flags,width,rs,arg);
1292
+ }
1293
+ converters['G'] = function(flags,width,precision,arg)
1294
+ { return (converters['g'](flags,width,precision,arg)).toUpperCase();
1295
+ }
1296
+ converters['g'] = function(flags,width,precision,arg)
1297
+ { iPrecision = parseInt(precision);
1298
+ absArg = Math.abs(arg);
1299
+ rse = absArg.toExponential();
1300
+ rsf = absArg.toFixed(6);
1301
+ if(!isNaN(iPrecision))
1302
+ { rsep = absArg.toExponential(iPrecision);
1303
+ rse = rsep.length < rse.length ? rsep : rse;
1304
+ rsfp = absArg.toFixed(iPrecision);
1305
+ rsf = rsfp.length < rsf.length ? rsfp : rsf;
1306
+ }
1307
+ if(rse.indexOf('.')<0 && flags.indexOf('#')>=0) rse = rse.replace(/^(.*)(e.*)$/,'$1.$2');
1308
+ if(rsf.indexOf('.')<0 && flags.indexOf('#')>=0) rsf = rsf + '.';
1309
+ rs = rse.length<rsf.length ? rse : rsf;
1310
+ return processFlags(flags,width,rs,arg);
1311
+ }
1312
+ converters['o'] = function(flags,width,precision,arg)
1313
+ { var iPrecision=parseInt(precision);
1314
+ var rs = Math.round(Math.abs(arg)).toString(8);
1315
+ if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
1316
+ if(flags.indexOf('#')>=0) rs='0'+rs;
1317
+ return processFlags(flags,width,rs,arg);
1318
+ }
1319
+ converters['X'] = function(flags,width,precision,arg)
1320
+ { return (converters['x'](flags,width,precision,arg)).toUpperCase();
1321
+ }
1322
+ converters['x'] = function(flags,width,precision,arg)
1323
+ { var iPrecision=parseInt(precision);
1324
+ arg = Math.abs(arg);
1325
+ var rs = Math.round(arg).toString(16);
1326
+ if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
1327
+ if(flags.indexOf('#')>=0) rs='0x'+rs;
1328
+ return processFlags(flags,width,rs,arg);
1329
+ }
1330
+ converters['s'] = function(flags,width,precision,arg)
1331
+ { var iPrecision=parseInt(precision);
1332
+ var rs = arg;
1333
+ if(rs.length > iPrecision) rs = rs.substring(0,iPrecision);
1334
+ return processFlags(flags,width,rs,0);
1335
+ }
1336
+ farr = fstring.split('%');
1337
+ retstr = farr[0];
1338
+ fpRE = /^([-+ #]*)(\d*)\.?(\d*)([cdieEfFgGosuxX])(.*)$/;
1339
+ for(var i=1; i<farr.length; i++)
1340
+ { fps=fpRE.exec(farr[i]);
1341
+ if(!fps) continue;
1342
+ if(arguments[i]!=null) retstr+=converters[fps[4]](fps[1],fps[2],fps[3],arguments[i]);
1343
+ retstr += fps[5];
1344
+ }
1345
+ return retstr;
1346
+ }
1347
+ }
1348
+
1349
+ var XMLHelpers = new function () {
1350
+ var me = this;
1351
+
1352
+ /**
1353
+ * Given an XML node, return the XML inside as a string and the XML string of the node itself.
1354
+ * Similar to Internet Explorer's outerHTML property, except it is for XML, not HTML.
1355
+ * Created with information from http://www.codingforums.com/showthread.php?t=31489
1356
+ * and http://www.mercurytide.co.uk/whitepapers/issues-working-with-ajax/
1357
+ *
1358
+ * @param {Object} node - a DOM object.
1359
+ * @param {Object} options - a JS object containing options. To date,
1360
+ * the only one supported is "insertClosingTags", when set to
1361
+ * true, converts self closing tags, like <td />, to <td></td>.
1362
+ * @return {String} - the XML String inside the object.
1363
+ */
1364
+ me.getOuterXML = function (node, options) {
1365
+ var r;
1366
+ // Internet Explorer
1367
+ if (node.xml) {
1368
+ r = node.xml;
1369
+
1370
+ // Everyone else
1371
+ } else if (node.outerHTML) {
1372
+ r = node.outerHTML;
1373
+ } else if (window.XMLSerializer) {
1374
+
1375
+ var serializer = new XMLSerializer();
1376
+ var text = serializer.serializeToString(node);
1377
+ r = text;
1378
+ } else {
1379
+ return null;
1380
+ }
1381
+
1382
+ /*
1383
+ * If the XML is actually HTML and you are inserting it into an HTML
1384
+ * document, you must use the "insertClosingTags" option, otherwise
1385
+ * Opera will not like you, especially if you have empty <td> tags.
1386
+ */
1387
+ if (options) {
1388
+ if (options.insertClosingTags) {
1389
+ r = r.replace(selfClosingTagRe, "<$1></$1>");
1390
+ }
1391
+ }
1392
+ return r;
1393
+ }
1394
+ }
1395
+
1396
+
1397
+ // default styles
1398
+ var placeholderCSS = 'color: #999999; font-style: italic';
1399
+ var placeholderRequiredCSS = 'color: #ffcccc !important;'
1400
+
1401
+ var sb = "";
1402
+
1403
+ // has to be two seperate rules, or some browsers, like firefox, will not use the rule.
1404
+ if (document.getElementsByTagName('body').length == 0) {
1405
+ sb = '<style type="text/css" id="testCSS">' +
1406
+ StringHelpers.sprintf('.html5-hasPlaceholderText{%s} input::-webkit-input-placeholder {%s}', placeholderCSS, placeholderCSS) +
1407
+ '</style>';
1408
+
1409
+
1410
+ document.write(sb);
1411
+ }
1412
+ }
1413
+
1414
+
1415
+
1416
+ EventHelpers.addPageLoadEvent('html5Widgets.init');
1417
+