html5forms-rails 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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,892 @@
1
+ var html5Forms = new function () {
2
+ var me = this;
3
+
4
+ var scriptNode = null,
5
+ scriptDir = null,
6
+ isScriptCompressed = false,
7
+
8
+ // WebKit less than 534 doesn't show validation UI - we need to check for this (from http://stackoverflow.com/questions/6030522/html5-form-validation-modernizr-safari)
9
+ hasNativeBubbles = navigator.userAgent.indexOf('WebKit') < 0 || parseInt(navigator.userAgent.match(/AppleWebKit\/([^ ]*)/)[1].split('.')[0]) > 534,
10
+ hasBadValidationImplementation = !hasNativeBubbles; // making another var for this in case we have more criteria in the future.
11
+
12
+
13
+ var globalEvent = document.addEventListener?document.createEvent("HTMLEvents"):null;
14
+
15
+ function getBrowserLanguage() {
16
+ var r = navigator.language;
17
+ if (!r) {
18
+ r = navigator.browserLanguage;
19
+ }
20
+ return r;
21
+ }
22
+
23
+
24
+ me.start = function () {
25
+
26
+ var split = navigator.userAgent.split('Firefox/');
27
+
28
+ //Firefox 3.6 gives a wierd error when using the Twitter API
29
+ //unless you do this onload.
30
+ if (split.length>=1 && parseFloat(split[1]) <= 3.6) {
31
+ EventHelpers.addEvent(window, 'load', me.init);
32
+ } else {
33
+ me.init();
34
+ }
35
+ }
36
+
37
+ me.init = function () {
38
+ var scriptNodes = document.getElementsByTagName('script');
39
+
40
+ for (var i=0; i<scriptNodes.length; i++) {
41
+ scriptNode = scriptNodes[i];
42
+
43
+ if (scriptNode.src.match('html5Forms(_src|-p|)\.js')) {
44
+ scriptNode = scriptNode;
45
+ scriptDir = getScriptDir();
46
+ if (scriptNode.src.indexOf('html5Forms-p.js') >= 0) {
47
+ isScriptCompressed = true;
48
+ }
49
+ break;
50
+ }
51
+ }
52
+
53
+ if (scriptNode) {
54
+ if (window.yepnope) {
55
+ var inputSupport = Modernizr.inputtypes;
56
+ /* let's load the supporting scripts according to what is in data-webforms2-support */
57
+ var supportArray = scriptNode.getAttribute('data-webforms2-support');
58
+ me.forceJSValidation = (scriptNode.getAttribute('data-webforms2-force-js-validation') == 'true');
59
+ me.turnOffValidation = (scriptNode.getAttribute('data-webforms2-turn-off-validation') == 'true');
60
+ me.forceJSDatePicker = (scriptNode.getAttribute('data-webforms2-force-js-date-picker') == 'true');
61
+ if (!supportArray) {
62
+ return;
63
+ } else if (trim(supportArray) == 'all') {
64
+ supportArray="validation,number,color,date,ouput,range,placeholder";
65
+ }
66
+
67
+ supportArray = supportArray.split(',');
68
+ var toLoad = [];
69
+ var toRunAfterLoad = [];
70
+ var loadHTML5Widgets = false;
71
+
72
+
73
+ for (var i=0; i<supportArray.length; i++) {
74
+ var supportReq = trim(supportArray[i]);
75
+
76
+ switch(supportReq) {
77
+
78
+ case "validation":
79
+ case "autofocus":
80
+ if (me.turnOffValidation) {
81
+ //me.turnOffNativeValidation();
82
+ EventHelpers.addPageLoadEvent('html5Forms.turnOffNativeValidation')
83
+ } else {
84
+
85
+ if (!Modernizr.input.required || hasBadValidationImplementation || me.forceJSValidation) {
86
+
87
+ if (isScriptCompressed) {
88
+ toLoad = toLoad.concat([
89
+ scriptDir + '../html5forms/weston.ruter.net/webforms2/webforms2-p.js']);
90
+ } else {
91
+ toLoad = toLoad.concat([
92
+ scriptDir + '../html5forms/weston.ruter.net/webforms2/webforms2_src.js']);
93
+ }
94
+
95
+ if (supportReq == 'autofocus') {
96
+ loadHTML5Widgets = true;
97
+ }
98
+
99
+ }
100
+ }
101
+ break;
102
+ case "number":
103
+ if (!inputSupport.number) {
104
+ toLoad = toLoad.concat([
105
+ scriptDir + '../../shared/css/number.css']);
106
+ loadHTML5Widgets = true;
107
+ }
108
+ break;
109
+ case "color":
110
+ if (!inputSupport.color) {
111
+
112
+ toLoad = toLoad.concat([ scriptDir + '../html5forms/jscolor/jscolor.js']);
113
+
114
+ loadHTML5Widgets = true;
115
+ }
116
+ break;
117
+
118
+ case "datetime":
119
+ case "date":
120
+ var lang = scriptNode.getAttribute('data-lang');
121
+
122
+
123
+ /* If data-lang is not set, or is set to an unsupported language, use English by default. */
124
+ if (!lang ||
125
+ !lang.match(/^(af|al|bg|big5|br|ca|cn|cs|da|de|du|el|en|es|fi|fr|he|hr|hu|it|jp|ko|ko|lt|lt|lv|nl|no|pl|pl|pt|ro|ru|si|sk|sp|sv|tr|zh)$/)){
126
+
127
+
128
+ lang = getBrowserLanguage().split('-')[0];
129
+ }
130
+
131
+
132
+
133
+ if (!inputSupport.date || me.forceJSDatePicker) {
134
+ toLoad = toLoad.concat([
135
+ scriptDir + '../html5forms/jscalendar-1.0/calendar-win2k-1.css',
136
+ scriptDir + '../html5forms/jscalendar-1.0/calendar.js',
137
+ scriptDir + '../html5forms/jscalendar-1.0/lang/calendar-' + lang + '.js',
138
+ scriptDir + '../html5forms/jscalendar-1.0/calendar-setup.js']);
139
+ loadHTML5Widgets = true;
140
+ }
141
+ break;
142
+
143
+ case "output":
144
+ if(!supportsOutput()) {
145
+
146
+ loadHTML5Widgets = true;
147
+ }
148
+ break;
149
+
150
+ case "range":
151
+ /* yepnope({
152
+ load: ['ie6!' + scriptDir + '../../shared/css/slider.css']
153
+ }); */
154
+
155
+ if(!inputSupport.range) {
156
+ toLoad = toLoad.concat([ scriptDir + '../../shared/css/slider.css',
157
+ scriptDir + '../html5forms/frequency-decoder.com/slider.js']);
158
+
159
+
160
+ loadHTML5Widgets = true;
161
+ toRunAfterLoad.push('fdSliderController.redrawAll');
162
+
163
+ }
164
+ break;
165
+ case "placeholder":
166
+ case "autofocus":
167
+ if (!Modernizr.input[supportReq]) {
168
+ loadHTML5Widgets = true;
169
+ }
170
+ }
171
+ }
172
+
173
+
174
+ if (toLoad.length == 0) {
175
+ loadWidgets();
176
+
177
+ // allow browsers that don't need webforms2 to handle custom error messages populated
178
+ // in the data-errormessage attribute
179
+ if (document.addEventListener) {
180
+ document.addEventListener('DOMContentLoaded', setupExtraFeatures, false);
181
+ }
182
+ } else {
183
+ yepnope({
184
+ load: toLoad,
185
+ complete: function (){
186
+ loadWidgets();
187
+ setupExtraFeatures();
188
+ }
189
+ });
190
+ }
191
+ }
192
+ }
193
+
194
+ function loadWidgets() {
195
+
196
+ yepnope({
197
+ test: loadHTML5Widgets,
198
+ yep: scriptDir + '../html5forms/html5Widgets.js',
199
+ complete: function () {
200
+ if (loadHTML5Widgets) {
201
+ for (var i=0; i<toRunAfterLoad.length; i++) {
202
+ eval(toRunAfterLoad[i] + '()');
203
+ }
204
+ EventHelpers.init();
205
+ html5Widgets.init();
206
+ //toRunAfterLoad.push('html5Widgets.init');
207
+ }
208
+ }
209
+ })
210
+
211
+ }
212
+
213
+
214
+
215
+ /*
216
+ * This should work even when webforms2 is not loaded.
217
+ * It sets up extra features for HTML5Forms like:
218
+ * 1) Setting custom error messages on form elements.
219
+ * 2) setting up isBlank and isBlurred classes.
220
+ * 3) settung up form.wf2_submitAttempted
221
+ */
222
+ function setupExtraFeatures() {
223
+ var nodeNames = ["input", "select", "textarea"];
224
+ for (var i=0; i<nodeNames.length; i++) {
225
+ var nodes = document.getElementsByTagName(nodeNames[i]);
226
+
227
+ for (var j=0; j<nodes.length; j++) {
228
+ var node = nodes[j];
229
+ setErrorMessageEvents(node);
230
+ setCustomClassesEvents(node);
231
+ setNodeClasses(node, true);
232
+ }
233
+
234
+ if (i==0 && node.type=="submit") {
235
+ EventHelpers.addEvent(node, 'click', submitClickEvent);
236
+ }
237
+ }
238
+
239
+ var forms = document.getElementsByTagName('form');
240
+ for (var i=0; i<forms.length; i++) {
241
+ EventHelpers.addEvent(forms[i], 'submit', submitEvent);
242
+ EventHelpers.addEvent(forms[i], 'reset', resetEvent);
243
+ }
244
+ }
245
+
246
+ function submitEvent(e) {
247
+ var target = EventHelpers.getEventTarget(e);
248
+ markSubmitAttempt(target);
249
+ }
250
+
251
+ function resetEvent(e) {
252
+ var target = EventHelpers.getEventTarget(e);
253
+
254
+ resetForm(target);
255
+ }
256
+ function submitClickEvent(e) {
257
+ var target = EventHelpers.getEventTarget(e);
258
+ markSubmitAttempt(target.form);
259
+ }
260
+
261
+ function markSubmitAttempt(form) {
262
+ me.css.addClass(form, 'wf2_submitAttempted');
263
+ }
264
+
265
+ function removeSubmitAttempt(form) {
266
+ me.css.removeClass(form, 'wf2_submitAttempted');
267
+ }
268
+
269
+ function resetForm(form) {
270
+ removeSubmitAttempt(form);
271
+ var nodeNames = ["input", "select", "textarea"];
272
+ for (var i=0; i<nodeNames.length; i++) {
273
+ var nodes = form.getElementsByTagName(nodeNames[i]);
274
+
275
+ for (var j=0; j<nodes.length; j++) {
276
+ var node = nodes[j];
277
+
278
+ me.css.removeClass(node, 'wf2_lostFocus');
279
+ me.css.removeClass(node, 'wf2_notBlank');
280
+ me.css.addClass(node, 'wf2_isBlank');
281
+ }
282
+
283
+ }
284
+ }
285
+
286
+ function setCustomClassesEvents(node) {
287
+ EventHelpers.addEvent(node, 'keyup', nodeChangeEvent);
288
+ EventHelpers.addEvent(node, 'change', nodeChangeEvent);
289
+ EventHelpers.addEvent(node, 'blur', nodeBlurEvent);
290
+ }
291
+
292
+ function nodeChangeEvent(e) {
293
+ var node = EventHelpers.getEventTarget(e);
294
+ setNodeClasses(node);
295
+ }
296
+
297
+ function setNodeClasses(node, isLoadEvent) {
298
+ if (node.value === '') {
299
+
300
+ me.css.addClass(node, 'wf2_isBlank');
301
+ me.css.removeClass(node, 'wf2_notBlank');
302
+ } else {
303
+ me.css.addClass(node, 'wf2_notBlank');
304
+ me.css.removeClass(node, 'wf2_isBlank');
305
+ }
306
+
307
+ if (isLoadEvent && node.nodeName == 'SELECT') {
308
+ node.setAttribute('data-wf2-initialvalue', node.value)
309
+ }
310
+
311
+ if ((node.nodeName == 'SELECT' && me.getAttributeValue(node, 'data-wf2-initialvalue') != node.value)
312
+ || (node.nodeName != 'SELECT' && me.getAttributeValue(node, 'value') != node.value)) {
313
+ me.css.removeClass(node, 'wf2_defaultValue');
314
+ me.css.addClass(node, 'wf2_notDefaultValue');
315
+ } else {
316
+ me.css.addClass(node, 'wf2_defaultValue');
317
+ me.css.removeClass(node, 'wf2_notDefaultValue');
318
+ }
319
+ }
320
+
321
+ function nodeBlurEvent(e) {
322
+ var node = EventHelpers.getEventTarget(e);
323
+
324
+ me.css.addClass(node, 'wf2_lostFocus');
325
+ }
326
+
327
+ function setErrorMessageEvents(node) {
328
+ var message = me.getAttributeValue(node, 'data-errormessage');
329
+ if (message) {
330
+ if(document.addEventListener){
331
+ node.addEventListener('invalid', showCustomMessageEvent, false);
332
+ node.addEventListener('focus', showCustomMessageEvent, false);
333
+
334
+ // Opera doesn't work well with this.
335
+ if (!window.opera) {
336
+ node.addEventListener('keypress', clearMessageIfValidEvent, false);
337
+ }
338
+
339
+ node.addEventListener('input', clearMessageIfValidEvent, false);
340
+
341
+ if (node.nodeName == 'SELECT') {
342
+ node.addEventListener('change', clearMessageIfValidEvent, false);
343
+ node.addEventListener('click', clearMessageIfValidEvent, false);
344
+ }
345
+ } else {
346
+ var invalidEvent = ' this.setCustomValidity("' + message + '");';
347
+ if (node.oninvalid) {
348
+ node.oninvalid += invalidEvent;
349
+ } else {
350
+ node.oninvalid = invalidEvent;
351
+ }
352
+ node.oninvalid = new Function('event', node.oninvalid);
353
+
354
+ // IE freaks a little on keypress here, so change to keydown.
355
+ node.attachEvent('onkeydown', clearMessageIfValidEvent);
356
+ node.attachEvent('oninput', clearMessageIfValidEvent);
357
+
358
+ if (node.nodeName == 'SELECT') {
359
+ node.attachEvent('change', clearMessageIfValidEvent, false);
360
+ node.attachEvent('click', clearMessageIfValidEvent, false);
361
+ }
362
+ }
363
+
364
+
365
+ clearMessageIfValid(node);
366
+
367
+ }
368
+ }
369
+
370
+ function showCustomMessageEvent(event) {
371
+ var node = event.currentTarget || event.srcElement;
372
+ showCustomMessage(node);
373
+ }
374
+
375
+ function showCustomMessage(node) {
376
+ if (node.validity.valid) {
377
+ return;
378
+ }
379
+ var message = me.getAttributeValue(node, 'data-errormessage');
380
+ node.setCustomValidity(message)
381
+ //console.log('set custom validity')
382
+ }
383
+
384
+ function clearMessageIfValidEvent (event) {
385
+ //console.log(event.type)
386
+ var node = event.currentTarget || event.srcElement;
387
+ clearMessageIfValid(node);
388
+ }
389
+
390
+ function clearMessageIfValid(node) {
391
+ if (!node.setCustomValidity) {
392
+ // this happens when webforms2 is not loaded yet. Bail.
393
+ return;
394
+ }
395
+
396
+ node.setCustomValidity('');
397
+ if (!node.checkValidity()) {
398
+ showCustomMessage(node);
399
+ //console.log('invalid')
400
+ if (document.addEventListener) {
401
+ globalEvent.initEvent('invalid', true, true); // event type,bubbling,cancelable
402
+ node.dispatchEvent(globalEvent);
403
+ }
404
+ } else {
405
+ //console.log('valid')
406
+ }
407
+ }
408
+
409
+ }
410
+
411
+ me.turnOffNativeValidation = function () {
412
+
413
+ var formNodes = document.getElementsByTagName('form');
414
+ for (var i=0; i<formNodes.length; i++) {
415
+ formNodes[i].setAttribute('novalidate', 'novalidate');
416
+ }
417
+ }
418
+
419
+ var supportsOutput = function () {
420
+ var outputEl = document.createElement('output');
421
+ return (outputEl.value != undefined && (outputEl.onforminput !== undefined || outputEl.oninput !== undefined));
422
+
423
+ }
424
+
425
+ var getScriptDir = function () {
426
+ var arr = scriptNode.src.split('/');
427
+ arr.pop();
428
+
429
+ return arr.join('/') + '/';
430
+ }
431
+
432
+ me.getAttributeByName = function (obj, attrName) {
433
+ var i;
434
+
435
+ var attributes = obj.attributes;
436
+ for (var i=0; i<attributes.length; i++) {
437
+ var attr = attributes[i]
438
+ if (attr.nodeName == attrName && attr.specified) {
439
+ return attr;
440
+ }
441
+ }
442
+ return null;
443
+ }
444
+
445
+ me.getAttributeValue = function (obj, attrName) {
446
+ var attr = me.getAttributeByName(obj, attrName);
447
+
448
+ if (attr != null) {
449
+ return attr.nodeValue;
450
+ } else {
451
+ return null;
452
+ }
453
+ }
454
+
455
+ var initWhitespaceRe = /^\s\s*/;
456
+ var endWhitespaceRe = /\s\s*$/;
457
+
458
+ function trim(str) {
459
+ return str.replace(initWhitespaceRe, '')
460
+ .replace(endWhitespaceRe, '');
461
+ }
462
+
463
+ me.css = new function () {
464
+ var me = this;
465
+
466
+ var blankRe = new RegExp('\\s');
467
+
468
+ /**
469
+ * Generates a regular expression string that can be used to detect a class name
470
+ * in a tag's class attribute. It is used by a few methods, so I
471
+ * centralized it.
472
+ *
473
+ * @param {String} className - a name of a CSS class.
474
+ */
475
+
476
+ function getClassReString(className) {
477
+ return '\\s'+className+'\\s|^' + className + '\\s|\\s' + className + '$|' + '^' + className +'$';
478
+ }
479
+
480
+ function getClassPrefixReString(className) {
481
+ 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_]+$';
482
+ }
483
+
484
+
485
+ /**
486
+ * Make an HTML object be a member of a certain class.
487
+ *
488
+ * @param {Object} obj - an HTML object
489
+ * @param {String} className - a CSS class name.
490
+ */
491
+ me.addClass = function (obj, className) {
492
+
493
+ if (blankRe.test(className)) {
494
+ return;
495
+ }
496
+
497
+ // only add class if the object is not a member of it yet.
498
+ if (!me.isMemberOfClass(obj, className)) {
499
+ obj.className += " " + className;
500
+ }
501
+
502
+ }
503
+
504
+ /**
505
+ * Make an HTML object *not* be a member of a certain class.
506
+ *
507
+ * @param {Object} obj - an HTML object
508
+ * @param {Object} className - a CSS class name.
509
+ */
510
+ me.removeClass = function (obj, className) {
511
+
512
+ if (blankRe.test(className)) {
513
+ return;
514
+ }
515
+
516
+
517
+ var re = new RegExp(getClassReString(className) , "g");
518
+
519
+ var oldClassName = obj.className;
520
+
521
+
522
+ if (obj.className) {
523
+ obj.className = oldClassName.replace(re, ' ');
524
+ }
525
+
526
+
527
+ }
528
+
529
+ /**
530
+ * Determines if an HTML object is a member of a specific class.
531
+ * @param {Object} obj - an HTML object.
532
+ * @param {Object} className - the CSS class name.
533
+ */
534
+ me.isMemberOfClass = function (obj, className) {
535
+
536
+ if (blankRe.test(className))
537
+ return false;
538
+
539
+ var re = new RegExp(getClassReString(className) , "g");
540
+
541
+ return (re.test(obj.className));
542
+
543
+
544
+ }
545
+
546
+ }
547
+
548
+ }
549
+
550
+ /*******************************************************************************
551
+ * This notice must be untouched at all times.
552
+ *
553
+ * This javascript library contains helper routines to assist with event
554
+ * handling consistently among browsers
555
+ *
556
+ * EventHelpers.js v.1.4 available at http://www.useragentman.com/
557
+ *
558
+ * released under the MIT License:
559
+ * http://www.opensource.org/licenses/mit-license.php
560
+ *
561
+ * Chagelog: 1.4: fix fireEvent to work correctly for IE9.
562
+ *
563
+ *******************************************************************************/
564
+ var EventHelpers = new function(){
565
+ var me = this;
566
+
567
+ var safariTimer;
568
+ var isSafari = /WebKit/i.test(navigator.userAgent);
569
+ var isIEPolling = false;
570
+ var globalEvent;
571
+ var safariVer = navigator.userAgent.match(/Version\/([^\s]*)/);
572
+
573
+ if (safariVer != null && safariVer.length == 2) {
574
+ safariVer = parseFloat(safariVer[1]);
575
+ }
576
+
577
+
578
+ me.init = function () {
579
+ if (me.hasPageLoadHappened(arguments)) {
580
+ return;
581
+ }
582
+
583
+ /* This is for fireEvent */
584
+ if (document.createEvent) {
585
+ globalEvent = document.createEvent("HTMLEvents");
586
+ } else if (document.createEventObject){
587
+ // dispatch for IE8 and lower.
588
+ globalEvent = document.createEventObject();
589
+ }
590
+
591
+ me.docIsLoaded = true;
592
+ }
593
+
594
+ /**
595
+ * Adds an event to the document. Examples of usage:
596
+ * me.addEvent(window, "load", myFunction);
597
+ * me.addEvent(docunent, "keydown", keyPressedFunc);
598
+ * me.addEvent(document, "keyup", keyPressFunc);
599
+ *
600
+ * @author Scott Andrew - http://www.scottandrew.com/weblog/articles/cbs-events
601
+ * @author John Resig - http://ejohn.org/projects/flexible-javascript-events/
602
+ * @param {Object} obj - a javascript object.
603
+ * @param {String} evType - an event to attach to the object.
604
+ * @param {Function} fn - the function that is attached to the event.
605
+ */
606
+ me.addEvent = function(obj, evType, fn){
607
+
608
+ if (obj.addEventListener) {
609
+ obj.addEventListener(evType, fn, false);
610
+ } else if (obj.attachEvent) {
611
+ obj['e' + evType + fn] = fn;
612
+ obj[evType + fn] = function(){
613
+ obj["e" + evType + fn](self.event);
614
+ }
615
+ obj.attachEvent("on" + evType, obj[evType + fn]);
616
+ }
617
+ }
618
+
619
+
620
+ /**
621
+ * Removes an event that is attached to a javascript object.
622
+ *
623
+ * @author Scott Andrew - http://www.scottandrew.com/weblog/articles/cbs-events
624
+ * @author John Resig - http://ejohn.org/projects/flexible-javascript-events/ * @param {Object} obj - a javascript object.
625
+ * @param {String} evType - an event attached to the object.
626
+ * @param {Function} fn - the function that is called when the event fires.
627
+ */
628
+ me.removeEvent = function(obj, evType, fn){
629
+
630
+ if (obj.removeEventListener) {
631
+ obj.removeEventListener(evType, fn, false);
632
+ } else if (obj.detachEvent) {
633
+ try {
634
+ obj.detachEvent("on" + evType, obj[evType + fn]);
635
+ obj[evType + fn] = null;
636
+ obj["e" + evType + fn] = null;
637
+ }
638
+ catch (ex) {
639
+ // do nothing;
640
+ }
641
+ }
642
+ }
643
+
644
+
645
+ /**
646
+ * Find the HTML object that fired an Event.
647
+ *
648
+ * @param {Object} e - an HTML object
649
+ * @return {Object} - the HTML object that fired the event.
650
+ */
651
+ me.getEventTarget = function(e){
652
+ // first, IE method for mouse events(also supported by Safari and Opera)
653
+ if (e.toElement) {
654
+ return e.toElement;
655
+ // W3C
656
+ } else if (e.currentTarget) {
657
+ return e.currentTarget;
658
+
659
+ // MS way
660
+ } else if (e.srcElement) {
661
+ return e.srcElement;
662
+ } else {
663
+ return null;
664
+ }
665
+ }
666
+
667
+
668
+
669
+
670
+ /**
671
+ * Given an event fired by the keyboard, find the key associated with that event.
672
+ *
673
+ * @param {Object} e - an event object.
674
+ * @return {String} - the ASCII character code representing the key associated with the event.
675
+ */
676
+ me.getKey = function(e){
677
+ if (e.keyCode) {
678
+ return e.keyCode;
679
+ } else if (e.event && e.event.keyCode) {
680
+ return window.event.keyCode;
681
+ } else if (e.which) {
682
+ return e.which;
683
+ }
684
+ }
685
+
686
+ function mylog(s) {
687
+ if (window.console && window.console.log) {
688
+ console.log(s);
689
+ }
690
+
691
+ }
692
+ /**
693
+ * Will execute a function when the page's DOM has fully loaded (and before all attached images, iframes,
694
+ * etc., are).
695
+ *
696
+ * Usage:
697
+ *
698
+ * EventHelpers.addPageLoadEvent('init');
699
+ *
700
+ * where the function init() has this code at the beginning:
701
+ *
702
+ * function init() {
703
+ *
704
+ * if (EventHelpers.hasPageLoadHappened(arguments)) return;
705
+ *
706
+ * // rest of code
707
+ * ....
708
+ * }
709
+ *
710
+ * @author This code is based off of code from http://dean.edwards.name/weblog/2005/09/busted/ by Dean
711
+ * Edwards, with a modification by me.
712
+ *
713
+ * @param {String} funcName - a string containing the function to be called.
714
+ */
715
+ me.addPageLoadEvent = function(funcName, timerForIE){
716
+
717
+ var func = eval(funcName);
718
+
719
+ // for Internet Explorer < 9 (using conditional comments)
720
+ /*@cc_on @*/
721
+ /*@if (@_win32 && @_jscript_version < 10)
722
+ if (timerForIE) {
723
+ isIEPolling = true;
724
+ } else {
725
+ pageLoadEventArray.push(func);
726
+ return;
727
+ }
728
+ /*@end @*/
729
+
730
+ // if document is already loaded, then just execute.
731
+ if (!isIEPolling && /loaded|complete|interactive/.test(document.readyState)) {
732
+ mylog('execute immediately')
733
+ func();
734
+ return;
735
+ }
736
+
737
+
738
+
739
+
740
+ if ((isSafari && safariVer < 3.1) || isIEPolling) { // sniff
741
+ mylog('polling')
742
+ pageLoadEventArray.push(func);
743
+
744
+ if (!safariTimer) {
745
+
746
+ safariTimer = setInterval(function(){
747
+ if (/loaded|complete/.test(document.readyState)) {
748
+ clearInterval(safariTimer);
749
+
750
+ /*
751
+ * call the onload handler
752
+ * func();
753
+ */
754
+ me.runPageLoadEvents();
755
+ return;
756
+ }
757
+ set = true;
758
+ }, 10);
759
+ }
760
+ /* for Mozilla */
761
+ } else if (document.addEventListener) {
762
+
763
+ document.addEventListener("DOMContentLoaded", func, null);
764
+ mylog("DOMContentLoaded " + document.readyState);
765
+ /* Others */
766
+ } else {
767
+ mylog('window.load')
768
+ me.addEvent(window, 'load', func);
769
+ }
770
+ }
771
+
772
+ var pageLoadEventArray = new Array();
773
+
774
+ me.runPageLoadEvents = function(e){
775
+ if (isSafari || isIEPolling || e.srcElement.readyState == "complete") {
776
+
777
+ for (var i = 0; i < pageLoadEventArray.length; i++) {
778
+ pageLoadEventArray[i]();
779
+ }
780
+ }
781
+ }
782
+ /**
783
+ * Determines if either addPageLoadEvent('funcName') or addEvent(window, 'load', funcName)
784
+ * has been executed.
785
+ *
786
+ * @see addPageLoadEvent
787
+ * @param {Function} funcArgs - the arguments of the containing. function
788
+ */
789
+ me.hasPageLoadHappened = function(funcArgs){
790
+ // If the function already been called, return true;
791
+ if (funcArgs.callee.done)
792
+ return true;
793
+
794
+ // flag this function so we don't do the same thing twice
795
+ funcArgs.callee.done = true;
796
+ }
797
+
798
+
799
+
800
+ /**
801
+ * Used in an event method/function to indicate that the default behaviour of the event
802
+ * should *not* happen.
803
+ *
804
+ * @param {Object} e - an event object.
805
+ * @return {Boolean} - always false
806
+ */
807
+ me.preventDefault = function(e){
808
+
809
+ if (e.preventDefault) {
810
+ e.preventDefault();
811
+ }
812
+
813
+ try {
814
+ e.returnValue = false;
815
+ }
816
+ catch (ex) {
817
+ // do nothing
818
+ }
819
+
820
+ }
821
+
822
+
823
+ /*
824
+ * Fires an event manually.
825
+ * @author Scott Andrew - http://www.scottandrew.com/weblog/articles/cbs-events
826
+ * @author John Resig - http://ejohn.org/projects/flexible-javascript-events/
827
+ * @param {Object} obj - a javascript object.
828
+ * @param {String} evType - an event attached to the object.
829
+ * @param {Function} fn - the function that is called when the event fires.
830
+ *
831
+ */
832
+ me.fireEvent = function (element,event, options){
833
+
834
+ if(!element) {
835
+ return;
836
+ }
837
+
838
+ if (element.dispatchEvent) {
839
+ // dispatch for firefox + ie9 + others
840
+ globalEvent.initEvent(event, true, true); // event type,bubbling,cancelable
841
+ return !element.dispatchEvent(globalEvent);
842
+ } else if (document.createEventObject){
843
+ return element.fireEvent('on' + event, globalEvent)
844
+ } else {
845
+ return false;
846
+ }
847
+ }
848
+
849
+ /*
850
+ * Detects whether the event "eventName" is supported on a tag with name
851
+ * "nodeName". Based on code from
852
+ * http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
853
+ */
854
+ me.isSupported = function (eventName, nodeName) {
855
+ var el = document.createElement(nodeName);
856
+ eventName = 'on' + eventName;
857
+ var isSupported = (eventName in el);
858
+ if (!isSupported) {
859
+ el.setAttribute(eventName, 'return;');
860
+ isSupported = typeof el[eventName] == 'function';
861
+ }
862
+ el = null;
863
+ return isSupported;
864
+ }
865
+
866
+
867
+ /* EventHelpers.init () */
868
+ function init(){
869
+ // Conditional comment alert: Do not remove comments. Leave intact.
870
+ // The detection if the page is secure or not is important. If
871
+ // this logic is removed, Internet Explorer will give security
872
+ // alerts.
873
+ /*@cc_on @*/
874
+ /*@if (@_win32)
875
+
876
+ document.write('<script id="__ie_onload" defer src="' +
877
+
878
+ ((location.protocol == 'https:') ? '//0' : 'javascript:void(0)') + '"><\/script>');
879
+
880
+ var script = document.getElementById("__ie_onload");
881
+
882
+ me.addEvent(script, 'readystatechange', me.runPageLoadEvents);
883
+
884
+ /*@end @*/
885
+
886
+ }
887
+ if (!window.html5Forms) {
888
+ init();
889
+ }
890
+ }
891
+
892
+ html5Forms.start();