jqtools-rails 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+