jqtools-rails 0.1.1

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 (31) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +11 -0
  4. data/Gemfile.lock +37 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.rdoc +34 -0
  7. data/Rakefile +49 -0
  8. data/VERSION +1 -0
  9. data/jqtools-rails.gemspec +81 -0
  10. data/lib/jqtools-rails.rb +5 -0
  11. data/spec/jqtools-rails_spec.rb +7 -0
  12. data/spec/spec_helper.rb +12 -0
  13. data/vendor/assets/javascripts/dateinput/dateinput.js +791 -0
  14. data/vendor/assets/javascripts/jquery.tools.min.js +39 -0
  15. data/vendor/assets/javascripts/overlay/overlay.apple.js +155 -0
  16. data/vendor/assets/javascripts/overlay/overlay.js +293 -0
  17. data/vendor/assets/javascripts/rangeinput/rangeinput.js +471 -0
  18. data/vendor/assets/javascripts/scrollable/scrollable.autoscroll.js +96 -0
  19. data/vendor/assets/javascripts/scrollable/scrollable.js +368 -0
  20. data/vendor/assets/javascripts/scrollable/scrollable.navigator.js +134 -0
  21. data/vendor/assets/javascripts/tabs/tabs.js +319 -0
  22. data/vendor/assets/javascripts/tabs/tabs.slideshow.js +191 -0
  23. data/vendor/assets/javascripts/toolbox/toolbox.expose.js +224 -0
  24. data/vendor/assets/javascripts/toolbox/toolbox.flashembed.js +301 -0
  25. data/vendor/assets/javascripts/toolbox/toolbox.history.js +108 -0
  26. data/vendor/assets/javascripts/toolbox/toolbox.mousewheel.js +65 -0
  27. data/vendor/assets/javascripts/tooltip/tooltip.dynamic.js +154 -0
  28. data/vendor/assets/javascripts/tooltip/tooltip.js +358 -0
  29. data/vendor/assets/javascripts/tooltip/tooltip.slide.js +78 -0
  30. data/vendor/assets/javascripts/validator/validator.js +598 -0
  31. metadata +135 -0
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @license
3
+ * jQuery Tools @VERSION / Tooltip Slide Effect
4
+ *
5
+ * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
6
+ *
7
+ * http://flowplayer.org/tools/tooltip/slide.html
8
+ *
9
+ * Since: September 2009
10
+ * Date: @DATE
11
+ */
12
+ (function($) {
13
+
14
+ // version number
15
+ var t = $.tools.tooltip;
16
+
17
+ // extend global configuragion with effect specific defaults
18
+ $.extend(t.conf, {
19
+ direction: 'up', // down, left, right
20
+ bounce: false,
21
+ slideOffset: 10,
22
+ slideInSpeed: 200,
23
+ slideOutSpeed: 200,
24
+ slideFade: !$.browser.msie
25
+ });
26
+
27
+ // directions for slide effect
28
+ var dirs = {
29
+ up: ['-', 'top'],
30
+ down: ['+', 'top'],
31
+ left: ['-', 'left'],
32
+ right: ['+', 'left']
33
+ };
34
+
35
+ /* default effect: "slide" */
36
+ t.addEffect("slide",
37
+
38
+ // show effect
39
+ function(done) {
40
+
41
+ // variables
42
+ var conf = this.getConf(),
43
+ tip = this.getTip(),
44
+ params = conf.slideFade ? {opacity: conf.opacity} : {},
45
+ dir = dirs[conf.direction] || dirs.up;
46
+
47
+ // direction
48
+ params[dir[1]] = dir[0] +'='+ conf.slideOffset;
49
+
50
+ // perform animation
51
+ if (conf.slideFade) { tip.css({opacity:0}); }
52
+ tip.show().animate(params, conf.slideInSpeed, done);
53
+ },
54
+
55
+ // hide effect
56
+ function(done) {
57
+
58
+ // variables
59
+ var conf = this.getConf(),
60
+ offset = conf.slideOffset,
61
+ params = conf.slideFade ? {opacity: 0} : {},
62
+ dir = dirs[conf.direction] || dirs.up;
63
+
64
+ // direction
65
+ var sign = "" + dir[0];
66
+ if (conf.bounce) { sign = sign == '+' ? '-' : '+'; }
67
+ params[dir[1]] = sign +'='+ offset;
68
+
69
+ // perform animation
70
+ this.getTip().animate(params, conf.slideOutSpeed, function() {
71
+ $(this).hide();
72
+ done.call();
73
+ });
74
+ }
75
+ );
76
+
77
+ })(jQuery);
78
+
@@ -0,0 +1,598 @@
1
+ /**
2
+ * @license
3
+ * jQuery Tools Validator @VERSION - HTML5 is here. Now use it.
4
+ *
5
+ * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
6
+ *
7
+ * http://flowplayer.org/tools/form/validator/
8
+ *
9
+ * Since: Mar 2010
10
+ * Date: @DATE
11
+ */
12
+ /*jslint evil: true */
13
+ (function($) {
14
+
15
+ $.tools = $.tools || {version: '@VERSION'};
16
+
17
+ // globals
18
+ var typeRe = /\[type=([a-z]+)\]/,
19
+ numRe = /^-?[0-9]*(\.[0-9]+)?$/,
20
+ dateInput = $.tools.dateinput,
21
+
22
+ // http://net.tutsplus.com/tutorials/other/8-regular-expressions-you-should-know/
23
+ emailRe = /^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,6})$/i,
24
+ urlRe = /^(https?:\/\/)?[\da-z\.\-]+\.[a-z\.]{2,6}[#&+_\?\/\w \.\-=]*$/i,
25
+ v;
26
+
27
+ v = $.tools.validator = {
28
+
29
+ conf: {
30
+ grouped: false, // show all error messages at once inside the container
31
+ effect: 'default', // show/hide effect for error message. only 'default' is built-in
32
+ errorClass: 'invalid', // input field class name in case of validation error
33
+
34
+ // when to check for validity?
35
+ inputEvent: null, // change, blur, keyup, null
36
+ errorInputEvent: 'keyup', // change, blur, keyup, null
37
+ formEvent: 'submit', // submit, null
38
+
39
+ lang: 'en', // default language for error messages
40
+ message: '<div/>',
41
+ messageAttr: 'data-message', // name of the attribute for overridden error message
42
+ messageClass: 'error', // error message element's class name
43
+ offset: [0, 0],
44
+ position: 'center right',
45
+ singleError: false, // validate all inputs at once
46
+ speed: 'normal' // message's fade-in speed
47
+ },
48
+
49
+
50
+ /* The Error Messages */
51
+ messages: {
52
+ "*": { en: "Please correct this value" }
53
+ },
54
+
55
+ localize: function(lang, messages) {
56
+ $.each(messages, function(key, msg) {
57
+ v.messages[key] = v.messages[key] || {};
58
+ v.messages[key][lang] = msg;
59
+ });
60
+ },
61
+
62
+ localizeFn: function(key, messages) {
63
+ v.messages[key] = v.messages[key] || {};
64
+ $.extend(v.messages[key], messages);
65
+ },
66
+
67
+ /**
68
+ * Adds a new validator
69
+ */
70
+ fn: function(matcher, msg, fn) {
71
+
72
+ // no message supplied
73
+ if ($.isFunction(msg)) {
74
+ fn = msg;
75
+
76
+ // message(s) on second argument
77
+ } else {
78
+ if (typeof msg == 'string') { msg = {en: msg}; }
79
+ this.messages[matcher.key || matcher] = msg;
80
+ }
81
+
82
+ // check for "[type=xxx]" (not supported by jQuery)
83
+ var test = typeRe.exec(matcher);
84
+ if (test) { matcher = isType(test[1]); }
85
+
86
+ // add validator to the arsenal
87
+ fns.push([matcher, fn]);
88
+ },
89
+
90
+ /* Add new show/hide effect */
91
+ addEffect: function(name, showFn, closeFn) {
92
+ effects[name] = [showFn, closeFn];
93
+ }
94
+
95
+ };
96
+
97
+ /* calculate error message position relative to the input */
98
+ function getPosition(trigger, el, conf) {
99
+
100
+ // get origin top/left position
101
+ var top = trigger.offset().top,
102
+ left = trigger.offset().left,
103
+ pos = conf.position.split(/,?\s+/),
104
+ y = pos[0],
105
+ x = pos[1];
106
+
107
+ top -= el.outerHeight() - conf.offset[0];
108
+ left += trigger.outerWidth() + conf.offset[1];
109
+
110
+
111
+ // iPad position fix
112
+ if (/iPad/i.test(navigator.userAgent)) {
113
+ top -= $(window).scrollTop();
114
+ }
115
+
116
+ // adjust Y
117
+ var height = el.outerHeight() + trigger.outerHeight();
118
+ if (y == 'center') { top += height / 2; }
119
+ if (y == 'bottom') { top += height; }
120
+
121
+ // adjust X
122
+ var width = trigger.outerWidth();
123
+ if (x == 'center') { left -= (width + el.outerWidth()) / 2; }
124
+ if (x == 'left') { left -= width; }
125
+
126
+ return {top: top, left: left};
127
+ }
128
+
129
+
130
+
131
+ // $.is("[type=xxx]") or $.filter("[type=xxx]") not working in jQuery 1.3.2 or 1.4.2
132
+ function isType(type) {
133
+ function fn() {
134
+ return this.getAttribute("type") == type;
135
+ }
136
+ fn.key = "[type=" + type + "]";
137
+ return fn;
138
+ }
139
+
140
+
141
+ var fns = [], effects = {
142
+
143
+ 'default' : [
144
+
145
+ // show errors function
146
+ function(errs) {
147
+
148
+ var conf = this.getConf();
149
+
150
+ // loop errors
151
+ $.each(errs, function(i, err) {
152
+
153
+ // add error class
154
+ var input = err.input;
155
+ input.addClass(conf.errorClass);
156
+
157
+ // get handle to the error container
158
+ var msg = input.data("msg.el");
159
+
160
+ // create it if not present
161
+ if (!msg) {
162
+ msg = $(conf.message).addClass(conf.messageClass).appendTo(document.body);
163
+ input.data("msg.el", msg);
164
+ }
165
+
166
+ // clear the container
167
+ msg.css({visibility: 'hidden'}).find("p").remove();
168
+
169
+ // populate messages
170
+ $.each(err.messages, function(i, m) {
171
+ $("<p/>").html(m).appendTo(msg);
172
+ });
173
+
174
+ // make sure the width is not full body width so it can be positioned correctly
175
+ if (msg.outerWidth() == msg.parent().width()) {
176
+ msg.add(msg.find("p")).css({display: 'inline'});
177
+ }
178
+
179
+ // insert into correct position (relative to the field)
180
+ var pos = getPosition(input, msg, conf);
181
+
182
+ msg.css({ visibility: 'visible', position: 'absolute', top: pos.top, left: pos.left })
183
+ .fadeIn(conf.speed);
184
+ });
185
+
186
+
187
+ // hide errors function
188
+ }, function(inputs) {
189
+
190
+ var conf = this.getConf();
191
+ inputs.removeClass(conf.errorClass).each(function() {
192
+ var msg = $(this).data("msg.el");
193
+ if (msg) { msg.css({visibility: 'hidden'}); }
194
+ });
195
+ }
196
+ ]
197
+ };
198
+
199
+
200
+ /* sperial selectors */
201
+ $.each("email,url,number".split(","), function(i, key) {
202
+ $.expr[':'][key] = function(el) {
203
+ return el.getAttribute("type") === key;
204
+ };
205
+ });
206
+
207
+
208
+ /*
209
+ oninvalid() jQuery plugin.
210
+ Usage: $("input:eq(2)").oninvalid(function() { ... });
211
+ */
212
+ $.fn.oninvalid = function( fn ){
213
+ return this[fn ? "bind" : "trigger"]("OI", fn);
214
+ };
215
+
216
+
217
+ /******* built-in HTML5 standard validators *********/
218
+
219
+ v.fn(":email", "Please enter a valid email address", function(el, v) {
220
+ return !v || emailRe.test(v);
221
+ });
222
+
223
+ v.fn(":url", "Please enter a valid URL", function(el, v) {
224
+ return !v || urlRe.test(v);
225
+ });
226
+
227
+ v.fn(":number", "Please enter a numeric value.", function(el, v) {
228
+ return numRe.test(v);
229
+ });
230
+
231
+ v.fn("[max]", "Please enter a value no larger than $1", function(el, v) {
232
+
233
+ // skip empty values and dateinputs
234
+ if (v === '' || dateInput && el.is(":date")) { return true; }
235
+
236
+ var max = el.attr("max");
237
+ return parseFloat(v) <= parseFloat(max) ? true : [max];
238
+ });
239
+
240
+ v.fn("[min]", "Please enter a value of at least $1", function(el, v) {
241
+
242
+ // skip empty values and dateinputs
243
+ if (v === '' || dateInput && el.is(":date")) { return true; }
244
+
245
+ var min = el.attr("min");
246
+ return parseFloat(v) >= parseFloat(min) ? true : [min];
247
+ });
248
+
249
+ v.fn("[required]", "Please complete this mandatory field.", function(el, v) {
250
+ if (el.is(":checkbox")) { return el.is(":checked"); }
251
+ return !!v;
252
+ });
253
+
254
+ v.fn("[pattern]", function(el) {
255
+ var p = new RegExp("^" + el.attr("pattern") + "$");
256
+ return p.test(el.val());
257
+ });
258
+
259
+
260
+ function Validator(inputs, form, conf) {
261
+
262
+ // private variables
263
+ var self = this,
264
+ fire = form.add(self);
265
+
266
+ // make sure there are input fields available
267
+ inputs = inputs.not(":button, :image, :reset, :submit");
268
+
269
+ // Prevent default Firefox validation
270
+ form.attr("novalidate", "novalidate");
271
+
272
+ // utility function
273
+ function pushMessage(to, matcher, returnValue) {
274
+
275
+ // only one message allowed
276
+ if (!conf.grouped && to.length) { return; }
277
+
278
+ // the error message
279
+ var msg;
280
+
281
+ // substitutions are returned
282
+ if (returnValue === false || $.isArray(returnValue)) {
283
+ msg = v.messages[matcher.key || matcher] || v.messages["*"];
284
+ msg = msg[conf.lang] || v.messages["*"].en;
285
+
286
+ // substitution
287
+ var matches = msg.match(/\$\d/g);
288
+
289
+ if (matches && $.isArray(returnValue)) {
290
+ $.each(matches, function(i) {
291
+ msg = msg.replace(this, returnValue[i]);
292
+ });
293
+ }
294
+
295
+ // error message is returned directly
296
+ } else {
297
+ msg = returnValue[conf.lang] || returnValue;
298
+ }
299
+
300
+ to.push(msg);
301
+ }
302
+
303
+
304
+ // API methods
305
+ $.extend(self, {
306
+
307
+ getConf: function() {
308
+ return conf;
309
+ },
310
+
311
+ getForm: function() {
312
+ return form;
313
+ },
314
+
315
+ getInputs: function() {
316
+ return inputs;
317
+ },
318
+
319
+ reflow: function() {
320
+ inputs.each(function() {
321
+ var input = $(this),
322
+ msg = input.data("msg.el");
323
+
324
+ if (msg) {
325
+ var pos = getPosition(input, msg, conf);
326
+ msg.css({ top: pos.top, left: pos.left });
327
+ }
328
+ });
329
+ return self;
330
+ },
331
+
332
+ /* @param e - for internal use only */
333
+ invalidate: function(errs, e) {
334
+
335
+ // errors are given manually: { fieldName1: 'message1', fieldName2: 'message2' }
336
+ if (!e) {
337
+ var errors = [];
338
+ $.each(errs, function(key, val) {
339
+ var input = inputs.filter("[name='" + key + "']");
340
+ if (input.length) {
341
+
342
+ // trigger HTML5 ininvalid event
343
+ input.trigger("OI", [val]);
344
+
345
+ errors.push({ input: input, messages: [val]});
346
+ }
347
+ });
348
+
349
+ errs = errors;
350
+ e = $.Event();
351
+ }
352
+
353
+ // onFail callback
354
+ e.type = "onFail";
355
+ fire.trigger(e, [errs]);
356
+
357
+ // call the effect
358
+ if (!e.isDefaultPrevented()) {
359
+ effects[conf.effect][0].call(self, errs, e);
360
+ }
361
+
362
+ return self;
363
+ },
364
+
365
+ reset: function(els) {
366
+ els = els || inputs;
367
+ els.removeClass(conf.errorClass).each(function() {
368
+ var msg = $(this).data("msg.el");
369
+ if (msg) {
370
+ msg.remove();
371
+ $(this).data("msg.el", null);
372
+ }
373
+ }).unbind(conf.errorInputEvent || '');
374
+ return self;
375
+ },
376
+
377
+ destroy: function() {
378
+ form.unbind(conf.formEvent + ".V").unbind("reset.V");
379
+ inputs.unbind(conf.inputEvent + ".V").unbind("change.V");
380
+ return self.reset();
381
+ },
382
+
383
+
384
+ //{{{ checkValidity() - flesh and bone of this tool
385
+
386
+ /* @returns boolean */
387
+ checkValidity: function(els, e) {
388
+
389
+ els = els || inputs;
390
+ els = els.not(":disabled");
391
+ if (!els.length) { return true; }
392
+
393
+ e = e || $.Event();
394
+
395
+ // onBeforeValidate
396
+ e.type = "onBeforeValidate";
397
+ fire.trigger(e, [els]);
398
+ if (e.isDefaultPrevented()) { return e.result; }
399
+
400
+ // container for errors
401
+ var errs = [];
402
+
403
+ // loop trough the inputs
404
+ els.not(":radio:not(:checked)").each(function() {
405
+
406
+ // field and it's error message container
407
+ var msgs = [],
408
+ el = $(this).data("messages", msgs),
409
+ event = dateInput && el.is(":date") ? "onHide.v" : conf.errorInputEvent + ".v";
410
+
411
+ // cleanup previous validation event
412
+ el.unbind(event);
413
+
414
+
415
+ // loop all validator functions
416
+ $.each(fns, function() {
417
+ var fn = this, match = fn[0];
418
+
419
+ // match found
420
+ if (el.filter(match).length) {
421
+
422
+ // execute a validator function
423
+ var returnValue = fn[1].call(self, el, el.val());
424
+
425
+
426
+ // validation failed. multiple substitutions can be returned with an array
427
+ if (returnValue !== true) {
428
+
429
+ // onBeforeFail
430
+ e.type = "onBeforeFail";
431
+ fire.trigger(e, [el, match]);
432
+ if (e.isDefaultPrevented()) { return false; }
433
+
434
+ // overridden custom message
435
+ var msg = el.attr(conf.messageAttr);
436
+ if (msg) {
437
+ msgs = [msg];
438
+ return false;
439
+ } else {
440
+ pushMessage(msgs, match, returnValue);
441
+ }
442
+ }
443
+ }
444
+ });
445
+
446
+ if (msgs.length) {
447
+
448
+ errs.push({input: el, messages: msgs});
449
+
450
+ // trigger HTML5 ininvalid event
451
+ el.trigger("OI", [msgs]);
452
+
453
+ // begin validating upon error event type (such as keyup)
454
+ if (conf.errorInputEvent) {
455
+ el.bind(event, function(e) {
456
+ self.checkValidity(el, e);
457
+ });
458
+ }
459
+ }
460
+
461
+ if (conf.singleError && errs.length) { return false; }
462
+
463
+ });
464
+
465
+
466
+ // validation done. now check that we have a proper effect at hand
467
+ var eff = effects[conf.effect];
468
+ if (!eff) { throw "Validator: cannot find effect \"" + conf.effect + "\""; }
469
+
470
+ // errors found
471
+ if (errs.length) {
472
+ self.invalidate(errs, e);
473
+ return false;
474
+
475
+ // no errors
476
+ } else {
477
+
478
+ // call the effect
479
+ eff[1].call(self, els, e);
480
+
481
+ // onSuccess callback
482
+ e.type = "onSuccess";
483
+ fire.trigger(e, [els]);
484
+
485
+ els.unbind(conf.errorInputEvent + ".v");
486
+ }
487
+
488
+ return true;
489
+ }
490
+ //}}}
491
+
492
+ });
493
+
494
+ // callbacks
495
+ $.each("onBeforeValidate,onBeforeFail,onFail,onSuccess".split(","), function(i, name) {
496
+
497
+ // configuration
498
+ if ($.isFunction(conf[name])) {
499
+ $(self).bind(name, conf[name]);
500
+ }
501
+
502
+ // API methods
503
+ self[name] = function(fn) {
504
+ if (fn) { $(self).bind(name, fn); }
505
+ return self;
506
+ };
507
+ });
508
+
509
+
510
+ // form validation
511
+ if (conf.formEvent) {
512
+ form.bind(conf.formEvent + ".V", function(e) {
513
+ if (!self.checkValidity(null, e)) {
514
+ return e.preventDefault();
515
+ }
516
+ // Reset event type and target
517
+ e.target = form;
518
+ e.type = conf.formEvent;
519
+ });
520
+ }
521
+
522
+ // form reset
523
+ form.bind("reset.V", function() {
524
+ self.reset();
525
+ });
526
+
527
+ // disable browser's default validation mechanism
528
+ if (inputs[0] && inputs[0].validity) {
529
+ inputs.each(function() {
530
+ this.oninvalid = function() {
531
+ return false;
532
+ };
533
+ });
534
+ }
535
+
536
+ // Web Forms 2.0 compatibility
537
+ if (form[0]) {
538
+ form[0].checkValidity = self.checkValidity;
539
+ }
540
+
541
+ // input validation
542
+ if (conf.inputEvent) {
543
+ inputs.bind(conf.inputEvent + ".V", function(e) {
544
+ self.checkValidity($(this), e);
545
+ });
546
+ }
547
+
548
+ // checkboxes, selects and radios are checked separately
549
+ inputs.filter(":checkbox, select").filter("[required]").bind("change.V", function(e) {
550
+ var el = $(this);
551
+ if (this.checked || (el.is("select") && $(this).val())) {
552
+ effects[conf.effect][1].call(self, el, e);
553
+ }
554
+ });
555
+
556
+ var radios = inputs.filter(":radio").change(function(e) {
557
+ self.checkValidity(radios, e);
558
+ });
559
+
560
+ // reposition tooltips when window is resized
561
+ $(window).resize(function() {
562
+ self.reflow();
563
+ });
564
+ }
565
+
566
+
567
+ // jQuery plugin initialization
568
+ $.fn.validator = function(conf) {
569
+
570
+ var instance = this.data("validator");
571
+
572
+ // destroy existing instance
573
+ if (instance) {
574
+ instance.destroy();
575
+ this.removeData("validator");
576
+ }
577
+
578
+ // configuration
579
+ conf = $.extend(true, {}, v.conf, conf);
580
+
581
+ // selector is a form
582
+ if (this.is("form")) {
583
+ return this.each(function() {
584
+ var form = $(this);
585
+ instance = new Validator(form.find(":input"), form, conf);
586
+ form.data("validator", instance);
587
+ });
588
+
589
+ } else {
590
+ instance = new Validator(this, this.eq(0).closest("form"), conf);
591
+ return this.data("validator", instance);
592
+ }
593
+
594
+ };
595
+
596
+ })(jQuery);
597
+
598
+