uniformjs-aristo-rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1068 @@
1
+ /*
2
+
3
+ Uniform v2.1.0
4
+ Copyright © 2009 Josh Pyles / Pixelmatrix Design LLC
5
+ http://pixelmatrixdesign.com
6
+
7
+ Requires jQuery 1.3 or newer
8
+
9
+ Much thanks to Thomas Reynolds and Buck Wilson for their help and advice on
10
+ this.
11
+
12
+ Disabling text selection is made possible by Mathias Bynens
13
+ <http://mathiasbynens.be/> and his noSelect plugin.
14
+ <https://github.com/mathiasbynens/jquery-noselect>, which is embedded.
15
+
16
+ Also, thanks to David Kaneda and Eugene Bond for their contributions to the
17
+ plugin.
18
+
19
+ Tyler Akins has also rewritten chunks of the plugin, helped close many issues,
20
+ and ensured version 2 got out the door.
21
+
22
+ License:
23
+ MIT License - http://www.opensource.org/licenses/mit-license.php
24
+
25
+ Enjoy!
26
+
27
+ */
28
+ /*global jQuery, window, document, navigator*/
29
+
30
+ (function ($, undef) {
31
+ "use strict";
32
+
33
+ /**
34
+ * Use .prop() if jQuery supports it, otherwise fall back to .attr()
35
+ *
36
+ * @param jQuery $el jQuery'd element on which we're calling attr/prop
37
+ * @param ... All other parameters are passed to jQuery's function
38
+ * @return The result from jQuery
39
+ */
40
+ function attrOrProp($el) {
41
+ var args = Array.prototype.slice.call(arguments, 1);
42
+
43
+ if ($el.prop) {
44
+ // jQuery 1.6+
45
+ return $el.prop.apply($el, args);
46
+ }
47
+
48
+ // jQuery 1.5 and below
49
+ return $el.attr.apply($el, args);
50
+ }
51
+
52
+ /**
53
+ * For backwards compatibility with older jQuery libraries, only bind
54
+ * one thing at a time. Also, this function adds our namespace to
55
+ * events in one consistent location, shrinking the minified code.
56
+ *
57
+ * The properties on the events object are the names of the events
58
+ * that we are supposed to add to. It can be a space separated list.
59
+ * The namespace will be added automatically.
60
+ *
61
+ * @param jQuery $el
62
+ * @param Object options Uniform options for this element
63
+ * @param Object events Events to bind, properties are event names
64
+ */
65
+ function bindMany($el, options, events) {
66
+ var name, namespaced;
67
+
68
+ for (name in events) {
69
+ if (events.hasOwnProperty(name)) {
70
+ namespaced = name.replace(/ |$/g, options.eventNamespace);
71
+ $el.bind(namespaced, events[name]);
72
+ }
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Bind the hover, active, focus, and blur UI updates
78
+ *
79
+ * @param jQuery $el Original element
80
+ * @param jQuery $target Target for the events (our div/span)
81
+ * @param Object options Uniform options for the element $target
82
+ */
83
+ function bindUi($el, $target, options) {
84
+ bindMany($el, options, {
85
+ focus: function () {
86
+ $target.addClass(options.focusClass);
87
+ },
88
+ blur: function () {
89
+ $target.removeClass(options.focusClass);
90
+ $target.removeClass(options.activeClass);
91
+ },
92
+ mouseenter: function () {
93
+ $target.addClass(options.hoverClass);
94
+ },
95
+ mouseleave: function () {
96
+ $target.removeClass(options.hoverClass);
97
+ $target.removeClass(options.activeClass);
98
+ },
99
+ "mousedown touchbegin": function () {
100
+ if (!$el.is(":disabled")) {
101
+ $target.addClass(options.activeClass);
102
+ }
103
+ },
104
+ "mouseup touchend": function () {
105
+ $target.removeClass(options.activeClass);
106
+ }
107
+ });
108
+ }
109
+
110
+ /**
111
+ * Remove the hover, focus, active classes.
112
+ *
113
+ * @param jQuery $el Element with classes
114
+ * @param Object options Uniform options for the element
115
+ */
116
+ function classClearStandard($el, options) {
117
+ $el.removeClass(options.hoverClass + " " + options.focusClass + " " + options.activeClass);
118
+ }
119
+
120
+ /**
121
+ * Add or remove a class, depending on if it's "enabled"
122
+ *
123
+ * @param jQuery $el Element that has the class added/removed
124
+ * @param String className Class or classes to add/remove
125
+ * @param Boolean enabled True to add the class, false to remove
126
+ */
127
+ function classUpdate($el, className, enabled) {
128
+ if (enabled) {
129
+ $el.addClass(className);
130
+ } else {
131
+ $el.removeClass(className);
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Updating the "checked" property can be a little tricky. This
137
+ * changed in jQuery 1.6 and now we can pass booleans to .prop().
138
+ * Prior to that, one either adds an attribute ("checked=checked") or
139
+ * removes the attribute.
140
+ *
141
+ * @param jQuery $tag Our Uniform span/div
142
+ * @param jQuery $el Original form element
143
+ * @param Object options Uniform options for this element
144
+ */
145
+ function classUpdateChecked($tag, $el, options) {
146
+ var c = "checked",
147
+ isChecked = $el.is(":" + c);
148
+
149
+ if ($el.prop) {
150
+ // jQuery 1.6+
151
+ $el.prop(c, isChecked);
152
+ } else {
153
+ // jQuery 1.5 and below
154
+ if (isChecked) {
155
+ $el.attr(c, c);
156
+ } else {
157
+ $el.removeAttr(c);
158
+ }
159
+ }
160
+
161
+ classUpdate($tag, options.checkedClass, isChecked);
162
+ }
163
+
164
+ /**
165
+ * Set or remove the "disabled" class for disabled elements, based on
166
+ * if the
167
+ *
168
+ * @param jQuery $tag Our Uniform span/div
169
+ * @param jQuery $el Original form element
170
+ * @param Object options Uniform options for this element
171
+ */
172
+ function classUpdateDisabled($tag, $el, options) {
173
+ classUpdate($tag, options.disabledClass, $el.is(":disabled"));
174
+ }
175
+
176
+ /**
177
+ * Wrap an element inside of a container or put the container next
178
+ * to the element. See the code for examples of the different methods.
179
+ *
180
+ * Returns the container that was added to the HTML.
181
+ *
182
+ * @param jQuery $el Element to wrap
183
+ * @param jQuery $container Add this new container around/near $el
184
+ * @param String method One of "after", "before" or "wrap"
185
+ * @return $container after it has been cloned for adding to $el
186
+ */
187
+ function divSpanWrap($el, $container, method) {
188
+ switch (method) {
189
+ case "after":
190
+ // Result: <element /> <container />
191
+ $el.after($container);
192
+ return $el.next();
193
+ case "before":
194
+ // Result: <container /> <element />
195
+ $el.before($container);
196
+ return $el.prev();
197
+ case "wrap":
198
+ // Result: <container> <element /> </container>
199
+ $el.wrap($container);
200
+ return $el.parent();
201
+ }
202
+
203
+ return null;
204
+ }
205
+
206
+
207
+ /**
208
+ * Create a div/span combo for uniforming an element
209
+ *
210
+ * @param jQuery $el Element to wrap
211
+ * @param Object options Options for the element, set by the user
212
+ * @param Object divSpanConfig Options for how we wrap the div/span
213
+ * @return Object Contains the div and span as properties
214
+ */
215
+ function divSpan($el, options, divSpanConfig) {
216
+ var $div, $span, id;
217
+
218
+ if (!divSpanConfig) {
219
+ divSpanConfig = {};
220
+ }
221
+
222
+ divSpanConfig = $.extend({
223
+ bind: {},
224
+ divClass: null,
225
+ divWrap: "wrap",
226
+ spanClass: null,
227
+ spanHtml: null,
228
+ spanWrap: "wrap"
229
+ }, divSpanConfig);
230
+
231
+ $div = $('<div />');
232
+ $span = $('<span />');
233
+
234
+ // Automatically hide this div/span if the element is hidden.
235
+ // Do not hide if the element is hidden because a parent is hidden.
236
+ if (options.autoHide && $el.is(':hidden') && $el.css('display') === 'none') {
237
+ $div.hide();
238
+ }
239
+
240
+ if (divSpanConfig.divClass) {
241
+ $div.addClass(divSpanConfig.divClass);
242
+ }
243
+
244
+ if (options.wrapperClass) {
245
+ $div.addClass(options.wrapperClass);
246
+ }
247
+
248
+ if (divSpanConfig.spanClass) {
249
+ $span.addClass(divSpanConfig.spanClass);
250
+ }
251
+
252
+ id = attrOrProp($el, 'id');
253
+
254
+ if (options.useID && id) {
255
+ attrOrProp($div, 'id', options.idPrefix + '-' + id);
256
+ }
257
+
258
+ if (divSpanConfig.spanHtml) {
259
+ $span.html(divSpanConfig.spanHtml);
260
+ }
261
+
262
+ $div = divSpanWrap($el, $div, divSpanConfig.divWrap);
263
+ $span = divSpanWrap($el, $span, divSpanConfig.spanWrap);
264
+ classUpdateDisabled($div, $el, options);
265
+ return {
266
+ div: $div,
267
+ span: $span
268
+ };
269
+ }
270
+
271
+
272
+ /**
273
+ * Wrap an element with a span to apply a global wrapper class
274
+ *
275
+ * @param jQuery $el Element to wrap
276
+ * @param object options
277
+ * @return jQuery Wrapper element
278
+ */
279
+ function wrapWithWrapperClass($el, options) {
280
+ var $span;
281
+
282
+ if (!options.wrapperClass) {
283
+ return null;
284
+ }
285
+
286
+ $span = $('<span />').addClass(options.wrapperClass);
287
+ $span = divSpanWrap($el, $span, "wrap");
288
+ return $span;
289
+ }
290
+
291
+
292
+ /**
293
+ * Test if high contrast mode is enabled.
294
+ *
295
+ * In high contrast mode, background images can not be set and
296
+ * they are always returned as 'none'.
297
+ *
298
+ * @return boolean True if in high contrast mode
299
+ */
300
+ function highContrast() {
301
+ var c, $div, el, rgb;
302
+
303
+ // High contrast mode deals with white and black
304
+ rgb = 'rgb(120,2,153)';
305
+ $div = $('<div style="width:0;height:0;color:' + rgb + '">');
306
+ $('body').append($div);
307
+ el = $div.get(0);
308
+
309
+ // $div.css() will get the style definition, not
310
+ // the actually displaying style
311
+ if (window.getComputedStyle) {
312
+ c = window.getComputedStyle(el, '').color;
313
+ } else {
314
+ c = (el.currentStyle || el.style || {}).color;
315
+ }
316
+
317
+ $div.remove();
318
+ return c.replace(/ /g, '') !== rgb;
319
+ }
320
+
321
+
322
+ /**
323
+ * Change text into safe HTML
324
+ *
325
+ * @param String text
326
+ * @return String HTML version
327
+ */
328
+ function htmlify(text) {
329
+ if (!text) {
330
+ return "";
331
+ }
332
+
333
+ return $('<span />').text(text).html();
334
+ }
335
+
336
+ /**
337
+ * If not MSIE, return false.
338
+ * If it is, return the version number.
339
+ *
340
+ * @return false|number
341
+ */
342
+ function isMsie() {
343
+ return navigator.cpuClass && !navigator.product;
344
+ }
345
+
346
+ /**
347
+ * Return true if this version of IE allows styling
348
+ *
349
+ * @return boolean
350
+ */
351
+ function isMsieSevenOrNewer() {
352
+ if (typeof window.XMLHttpRequest !== 'undefined') {
353
+ return true;
354
+ }
355
+
356
+ return false;
357
+ }
358
+
359
+ /**
360
+ * Test if the element is a multiselect
361
+ *
362
+ * @param jQuery $el Element
363
+ * @return boolean true/false
364
+ */
365
+ function isMultiselect($el) {
366
+ var elSize;
367
+
368
+ if ($el[0].multiple) {
369
+ return true;
370
+ }
371
+
372
+ elSize = attrOrProp($el, "size");
373
+
374
+ if (!elSize || elSize <= 1) {
375
+ return false;
376
+ }
377
+
378
+ return true;
379
+ }
380
+
381
+ /**
382
+ * Meaningless utility function. Used mostly for improving minification.
383
+ *
384
+ * @return false
385
+ */
386
+ function returnFalse() {
387
+ return false;
388
+ }
389
+
390
+ /**
391
+ * noSelect plugin, very slightly modified
392
+ * http://mths.be/noselect v1.0.3
393
+ *
394
+ * @param jQuery $elem Element that we don't want to select
395
+ * @param Object options Uniform options for the element
396
+ */
397
+ function noSelect($elem, options) {
398
+ var none = 'none';
399
+ bindMany($elem, options, {
400
+ 'selectstart dragstart mousedown': returnFalse
401
+ });
402
+
403
+ $elem.css({
404
+ MozUserSelect: none,
405
+ msUserSelect: none,
406
+ webkitUserSelect: none,
407
+ userSelect: none
408
+ });
409
+ }
410
+
411
+ /**
412
+ * Updates the filename tag based on the value of the real input
413
+ * element.
414
+ *
415
+ * @param jQuery $el Actual form element
416
+ * @param jQuery $filenameTag Span/div to update
417
+ * @param Object options Uniform options for this element
418
+ */
419
+ function setFilename($el, $filenameTag, options) {
420
+ var filename = $el.val();
421
+
422
+ if (filename === "") {
423
+ filename = options.fileDefaultHtml;
424
+ } else {
425
+ filename = filename.split(/[\/\\]+/);
426
+ filename = filename[(filename.length - 1)];
427
+ }
428
+
429
+ $filenameTag.text(filename);
430
+ }
431
+
432
+
433
+ /**
434
+ * Function from jQuery to swap some CSS values, run a callback,
435
+ * then restore the CSS. Modified to pass JSLint and handle undefined
436
+ * values with 'use strict'.
437
+ *
438
+ * @param jQuery $el Element
439
+ * @param object newCss CSS values to swap out
440
+ * @param Function callback Function to run
441
+ */
442
+ function swap($elements, newCss, callback) {
443
+ var restore, item;
444
+
445
+ restore = [];
446
+
447
+ $elements.each(function () {
448
+ var name;
449
+
450
+ for (name in newCss) {
451
+ if (Object.prototype.hasOwnProperty.call(newCss, name)) {
452
+ restore.push({
453
+ el: this,
454
+ name: name,
455
+ old: this.style[name]
456
+ });
457
+
458
+ this.style[name] = newCss[name];
459
+ }
460
+ }
461
+ });
462
+
463
+ callback();
464
+
465
+ while (restore.length) {
466
+ item = restore.pop();
467
+ item.el.style[item.name] = item.old;
468
+ }
469
+ }
470
+
471
+
472
+ /**
473
+ * The browser doesn't provide sizes of elements that are not visible.
474
+ * This will clone an element and add it to the DOM for calculations.
475
+ *
476
+ * @param jQuery $el
477
+ * @param String method
478
+ */
479
+ function sizingInvisible($el, callback) {
480
+ var targets;
481
+
482
+ // We wish to target ourselves and any parents as long as
483
+ // they are not visible
484
+ targets = $el.parents();
485
+ targets.push($el[0]);
486
+ targets = targets.not(':visible');
487
+ swap(targets, {
488
+ visibility: "hidden",
489
+ display: "block",
490
+ position: "absolute"
491
+ }, callback);
492
+ }
493
+
494
+
495
+ /**
496
+ * Standard way to unwrap the div/span combination from an element
497
+ *
498
+ * @param jQuery $el Element that we wish to preserve
499
+ * @param Object options Uniform options for the element
500
+ * @return Function This generated function will perform the given work
501
+ */
502
+ function unwrapUnwrapUnbindFunction($el, options) {
503
+ return function () {
504
+ $el.unwrap().unwrap().unbind(options.eventNamespace);
505
+ };
506
+ }
507
+
508
+ var allowStyling = true, // False if IE6 or other unsupported browsers
509
+ highContrastTest = false, // Was the high contrast test ran?
510
+ uniformHandlers = [ // Objects that take care of "unification"
511
+ {
512
+ // Buttons
513
+ match: function ($el) {
514
+ return $el.is("a, button, :submit, :reset, input[type='button']");
515
+ },
516
+ apply: function ($el, options) {
517
+ var $div, defaultSpanHtml, ds, getHtml, doingClickEvent;
518
+ defaultSpanHtml = options.submitDefaultHtml;
519
+
520
+ if ($el.is(":reset")) {
521
+ defaultSpanHtml = options.resetDefaultHtml;
522
+ }
523
+
524
+ if ($el.is("a, button")) {
525
+ // Use the HTML inside the tag
526
+ getHtml = function () {
527
+ return $el.html() || defaultSpanHtml;
528
+ };
529
+ } else {
530
+ // Use the value property of the element
531
+ getHtml = function () {
532
+ return htmlify(attrOrProp($el, "value")) || defaultSpanHtml;
533
+ };
534
+ }
535
+
536
+ ds = divSpan($el, options, {
537
+ divClass: options.buttonClass,
538
+ spanHtml: getHtml()
539
+ });
540
+ $div = ds.div;
541
+ bindUi($el, $div, options);
542
+ doingClickEvent = false;
543
+ bindMany($div, options, {
544
+ "click touchend": function () {
545
+ var ev, res, target, href;
546
+
547
+ if (doingClickEvent) {
548
+ return;
549
+ }
550
+
551
+ if ($el.is(':disabled')) {
552
+ return;
553
+ }
554
+
555
+ doingClickEvent = true;
556
+
557
+ if ($el[0].dispatchEvent) {
558
+ ev = document.createEvent("MouseEvents");
559
+ ev.initEvent("click", true, true);
560
+ res = $el[0].dispatchEvent(ev);
561
+
562
+ if ($el.is('a') && res) {
563
+ target = attrOrProp($el, 'target');
564
+ href = attrOrProp($el, 'href');
565
+
566
+ if (!target || target === '_self') {
567
+ document.location.href = href;
568
+ } else {
569
+ window.open(href, target);
570
+ }
571
+ }
572
+ } else {
573
+ $el.click();
574
+ }
575
+
576
+ doingClickEvent = false;
577
+ }
578
+ });
579
+ noSelect($div, options);
580
+ return {
581
+ remove: function () {
582
+ // Move $el out
583
+ $div.after($el);
584
+
585
+ // Remove div and span
586
+ $div.remove();
587
+
588
+ // Unbind events
589
+ $el.unbind(options.eventNamespace);
590
+ return $el;
591
+ },
592
+ update: function () {
593
+ classClearStandard($div, options);
594
+ classUpdateDisabled($div, $el, options);
595
+ $el.detach();
596
+ ds.span.html(getHtml()).append($el);
597
+ }
598
+ };
599
+ }
600
+ },
601
+ {
602
+ // Checkboxes
603
+ match: function ($el) {
604
+ return $el.is(":checkbox");
605
+ },
606
+ apply: function ($el, options) {
607
+ var ds, $div, $span;
608
+ ds = divSpan($el, options, {
609
+ divClass: options.checkboxClass
610
+ });
611
+ $div = ds.div;
612
+ $span = ds.span;
613
+
614
+ // Add focus classes, toggling, active, etc.
615
+ bindUi($el, $div, options);
616
+ bindMany($el, options, {
617
+ "click touchend": function () {
618
+ classUpdateChecked($span, $el, options);
619
+ }
620
+ });
621
+ classUpdateChecked($span, $el, options);
622
+ return {
623
+ remove: unwrapUnwrapUnbindFunction($el, options),
624
+ update: function () {
625
+ classClearStandard($div, options);
626
+ $span.removeClass(options.checkedClass);
627
+ classUpdateChecked($span, $el, options);
628
+ classUpdateDisabled($div, $el, options);
629
+ }
630
+ };
631
+ }
632
+ },
633
+ {
634
+ // File selection / uploads
635
+ match: function ($el) {
636
+ return $el.is(":file");
637
+ },
638
+ apply: function ($el, options) {
639
+ var ds, $div, $filename, $button;
640
+
641
+ // The "span" is the button
642
+ ds = divSpan($el, options, {
643
+ divClass: options.fileClass,
644
+ spanClass: options.fileButtonClass,
645
+ spanHtml: options.fileButtonHtml,
646
+ spanWrap: "after"
647
+ });
648
+ $div = ds.div;
649
+ $button = ds.span;
650
+ $filename = $("<span />").html(options.fileDefaultHtml);
651
+ $filename.addClass(options.filenameClass);
652
+ $filename = divSpanWrap($el, $filename, "after");
653
+
654
+ // Set the size
655
+ if (!attrOrProp($el, "size")) {
656
+ attrOrProp($el, "size", $div.width() / 10);
657
+ }
658
+
659
+ // Actions
660
+ function filenameUpdate() {
661
+ setFilename($el, $filename, options);
662
+ }
663
+
664
+ bindUi($el, $div, options);
665
+
666
+ // Account for input saved across refreshes
667
+ filenameUpdate();
668
+
669
+ // IE7 doesn't fire onChange until blur or second fire.
670
+ if (isMsie()) {
671
+ // IE considers browser chrome blocking I/O, so it
672
+ // suspends tiemouts until after the file has
673
+ // been selected.
674
+ bindMany($el, options, {
675
+ click: function () {
676
+ $el.trigger("change");
677
+ setTimeout(filenameUpdate, 0);
678
+ }
679
+ });
680
+ } else {
681
+ // All other browsers behave properly
682
+ bindMany($el, options, {
683
+ change: filenameUpdate
684
+ });
685
+ }
686
+
687
+ noSelect($filename, options);
688
+ noSelect($button, options);
689
+ return {
690
+ remove: function () {
691
+ // Remove filename and button
692
+ $filename.remove();
693
+ $button.remove();
694
+
695
+ // Unwrap parent div, remove events
696
+ return $el.unwrap().unbind(options.eventNamespace);
697
+ },
698
+ update: function () {
699
+ classClearStandard($div, options);
700
+ setFilename($el, $filename, options);
701
+ classUpdateDisabled($div, $el, options);
702
+ }
703
+ };
704
+ }
705
+ },
706
+ {
707
+ // Input fields (text)
708
+ match: function ($el) {
709
+ if ($el.is("input")) {
710
+ var t = (" " + attrOrProp($el, "type") + " ").toLowerCase(),
711
+ allowed = " color date datetime datetime-local email month number password search tel text time url week ";
712
+ return allowed.indexOf(t) >= 0;
713
+ }
714
+
715
+ return false;
716
+ },
717
+ apply: function ($el, options) {
718
+ var elType, $wrapper;
719
+
720
+ elType = attrOrProp($el, "type");
721
+ $el.addClass(options.inputClass);
722
+ $wrapper = wrapWithWrapperClass($el, options);
723
+ bindUi($el, $el, options);
724
+
725
+ if (options.inputAddTypeAsClass) {
726
+ $el.addClass(elType);
727
+ }
728
+
729
+ return {
730
+ remove: function () {
731
+ $el.removeClass(options.inputClass);
732
+
733
+ if (options.inputAddTypeAsClass) {
734
+ $el.removeClass(elType);
735
+ }
736
+
737
+ if ($wrapper) {
738
+ $el.unwrap();
739
+ }
740
+ },
741
+ update: returnFalse
742
+ };
743
+ }
744
+ },
745
+ {
746
+ // Radio buttons
747
+ match: function ($el) {
748
+ return $el.is(":radio");
749
+ },
750
+ apply: function ($el, options) {
751
+ var ds, $div, $span;
752
+ ds = divSpan($el, options, {
753
+ divClass: options.radioClass
754
+ });
755
+ $div = ds.div;
756
+ $span = ds.span;
757
+
758
+ // Add classes for focus, handle active, checked
759
+ bindUi($el, $div, options);
760
+ bindMany($el, options, {
761
+ "click touchend": function () {
762
+ // Find all radios with the same name, then update
763
+ // them with $.uniform.update() so the right
764
+ // per-element options are used
765
+ $.uniform.update($(':radio[name="' + attrOrProp($el, "name") + '"]'));
766
+ }
767
+ });
768
+ classUpdateChecked($span, $el, options);
769
+ return {
770
+ remove: unwrapUnwrapUnbindFunction($el, options),
771
+ update: function () {
772
+ classClearStandard($div, options);
773
+ classUpdateChecked($span, $el, options);
774
+ classUpdateDisabled($div, $el, options);
775
+ }
776
+ };
777
+ }
778
+ },
779
+ {
780
+ // Select lists, but do not style multiselects here
781
+ match: function ($el) {
782
+ if ($el.is("select") && !isMultiselect($el)) {
783
+ return true;
784
+ }
785
+
786
+ return false;
787
+ },
788
+ apply: function ($el, options) {
789
+ var ds, $div, $span, origElemWidth;
790
+
791
+ if (options.selectAutoWidth) {
792
+ sizingInvisible($el, function () {
793
+ origElemWidth = $el.width();
794
+ });
795
+ }
796
+
797
+ ds = divSpan($el, options, {
798
+ divClass: options.selectClass,
799
+ spanHtml: ($el.find(":selected:first") || $el.find("option:first")).html(),
800
+ spanWrap: "before"
801
+ });
802
+ $div = ds.div;
803
+ $span = ds.span;
804
+
805
+ if (options.selectAutoWidth) {
806
+ // Use the width of the select and adjust the
807
+ // span and div accordingly
808
+ sizingInvisible($el, function () {
809
+ // Force "display: block" - related to bug #287
810
+ swap($([ $span[0], $div[0] ]), {
811
+ display: "block"
812
+ }, function () {
813
+ var spanPad;
814
+ //spanPad = $span.outerWidth() - $span.width();
815
+ //$div.width(origElemWidth + spanPad);
816
+ //$span.width(origElemWidth);
817
+ });
818
+ });
819
+ } else {
820
+ // Force the select to fill the size of the div
821
+ $div.addClass('fixedWidth');
822
+ }
823
+
824
+ // Take care of events
825
+ bindUi($el, $div, options);
826
+ bindMany($el, options, {
827
+ change: function () {
828
+ $span.html($el.find(":selected").html());
829
+ $div.removeClass(options.activeClass);
830
+ },
831
+ "click touchend": function () {
832
+ // IE7 and IE8 may not update the value right
833
+ // until after click event - issue #238
834
+ var selHtml = $el.find(":selected").html();
835
+
836
+ if ($span.html() !== selHtml) {
837
+ // Change was detected
838
+ // Fire the change event on the select tag
839
+ $el.trigger('change');
840
+ }
841
+ },
842
+ keyup: function () {
843
+ $span.html($el.find(":selected").html());
844
+ }
845
+ });
846
+ noSelect($span, options);
847
+ return {
848
+ remove: function () {
849
+ // Remove sibling span
850
+ $span.remove();
851
+
852
+ // Unwrap parent div
853
+ $el.unwrap().unbind(options.eventNamespace);
854
+ return $el;
855
+ },
856
+ update: function () {
857
+ if (options.selectAutoWidth) {
858
+ // Easier to remove and reapply formatting
859
+ $.uniform.restore($el);
860
+ $el.uniform(options);
861
+ } else {
862
+ classClearStandard($div, options);
863
+
864
+ // Reset current selected text
865
+ $span.html($el.find(":selected").html());
866
+ classUpdateDisabled($div, $el, options);
867
+ }
868
+ }
869
+ };
870
+ }
871
+ },
872
+ {
873
+ // Select lists - multiselect lists only
874
+ match: function ($el) {
875
+ if ($el.is("select") && isMultiselect($el)) {
876
+ return true;
877
+ }
878
+
879
+ return false;
880
+ },
881
+ apply: function ($el, options) {
882
+ var $wrapper;
883
+
884
+ $el.addClass(options.selectMultiClass);
885
+ $wrapper = wrapWithWrapperClass($el, options);
886
+ bindUi($el, $el, options);
887
+
888
+ return {
889
+ remove: function () {
890
+ $el.removeClass(options.selectMultiClass);
891
+
892
+ if ($wrapper) {
893
+ $el.unwrap();
894
+ }
895
+ },
896
+ update: returnFalse
897
+ };
898
+ }
899
+ },
900
+ {
901
+ // Textareas
902
+ match: function ($el) {
903
+ return $el.is("textarea");
904
+ },
905
+ apply: function ($el, options) {
906
+ var $wrapper;
907
+
908
+ $el.addClass(options.textareaClass);
909
+ $wrapper = wrapWithWrapperClass($el, options);
910
+ bindUi($el, $el, options);
911
+
912
+ return {
913
+ remove: function () {
914
+ $el.removeClass(options.textareaClass);
915
+
916
+ if ($wrapper) {
917
+ $el.unwrap();
918
+ }
919
+ },
920
+ update: returnFalse
921
+ };
922
+ }
923
+ }
924
+ ];
925
+
926
+ // IE6 can't be styled - can't set opacity on select
927
+ if (isMsie() && !isMsieSevenOrNewer()) {
928
+ allowStyling = false;
929
+ }
930
+
931
+ $.uniform = {
932
+ // Default options that can be overridden globally or when uniformed
933
+ // globally: $.uniform.defaults.fileButtonHtml = "Pick A File";
934
+ // on uniform: $('input').uniform({fileButtonHtml: "Pick a File"});
935
+ defaults: {
936
+ activeClass: "active",
937
+ autoHide: true,
938
+ buttonClass: "button",
939
+ checkboxClass: "checker",
940
+ checkedClass: "checked",
941
+ disabledClass: "disabled",
942
+ eventNamespace: ".uniform",
943
+ fileButtonClass: "action",
944
+ fileButtonHtml: "Choose File",
945
+ fileClass: "uploader",
946
+ fileDefaultHtml: "Seleccione un archivo",
947
+ filenameClass: "filename",
948
+ focusClass: "focus",
949
+ hoverClass: "hover",
950
+ idPrefix: "uniform",
951
+ inputAddTypeAsClass: true,
952
+ inputClass: "uniform-input",
953
+ radioClass: "radio",
954
+ resetDefaultHtml: "Reset",
955
+ resetSelector: false, // We'll use our own function when you don't specify one
956
+ selectAutoWidth: true,
957
+ selectClass: "selector",
958
+ selectMultiClass: "uniform-multiselect",
959
+ submitDefaultHtml: "Submit", // Only text allowed
960
+ textareaClass: "uniform",
961
+ useID: true,
962
+ wrapperClass: null
963
+ },
964
+
965
+ // All uniformed elements - DOM objects
966
+ elements: []
967
+ };
968
+
969
+ $.fn.uniform = function (options) {
970
+ var el = this;
971
+ options = $.extend({}, $.uniform.defaults, options);
972
+
973
+ // If we are in high contrast mode, do not allow styling
974
+ if (!highContrastTest) {
975
+ highContrastTest = true;
976
+
977
+ if (highContrast()) {
978
+ allowStyling = false;
979
+ }
980
+ }
981
+
982
+ // Only uniform on browsers that work
983
+ if (!allowStyling) {
984
+ return this;
985
+ }
986
+
987
+ // Code for specifying a reset button
988
+ if (options.resetSelector) {
989
+ $(options.resetSelector).mouseup(function () {
990
+ window.setTimeout(function () {
991
+ $.uniform.update(el);
992
+ }, 10);
993
+ });
994
+ }
995
+
996
+ return this.each(function () {
997
+ var $el = $(this), i, handler, callbacks;
998
+
999
+ // Avoid uniforming elements already uniformed - just update
1000
+ if ($el.data("uniformed")) {
1001
+ $.uniform.update($el);
1002
+ return;
1003
+ }
1004
+
1005
+ // See if we have any handler for this type of element
1006
+ for (i = 0; i < uniformHandlers.length; i = i + 1) {
1007
+ handler = uniformHandlers[i];
1008
+
1009
+ if (handler.match($el, options)) {
1010
+ callbacks = handler.apply($el, options);
1011
+ $el.data("uniformed", callbacks);
1012
+
1013
+ // Store element in our global array
1014
+ $.uniform.elements.push($el.get(0));
1015
+ return;
1016
+ }
1017
+ }
1018
+
1019
+ // Could not style this element
1020
+ });
1021
+ };
1022
+
1023
+ $.uniform.restore = $.fn.uniform.restore = function (elem) {
1024
+ if (elem === undef) {
1025
+ elem = $.uniform.elements;
1026
+ }
1027
+
1028
+ $(elem).each(function () {
1029
+ var $el = $(this), index, elementData;
1030
+ elementData = $el.data("uniformed");
1031
+
1032
+ // Skip elements that are not uniformed
1033
+ if (!elementData) {
1034
+ return;
1035
+ }
1036
+
1037
+ // Unbind events, remove additional markup that was added
1038
+ elementData.remove();
1039
+
1040
+ // Remove item from list of uniformed elements
1041
+ index = $.inArray(this, $.uniform.elements);
1042
+
1043
+ if (index >= 0) {
1044
+ $.uniform.elements.splice(index, 1);
1045
+ }
1046
+
1047
+ $el.removeData("uniformed");
1048
+ });
1049
+ };
1050
+
1051
+ $.uniform.update = $.fn.uniform.update = function (elem) {
1052
+ if (elem === undef) {
1053
+ elem = $.uniform.elements;
1054
+ }
1055
+
1056
+ $(elem).each(function () {
1057
+ var $el = $(this), elementData;
1058
+ elementData = $el.data("uniformed");
1059
+
1060
+ // Skip elements that are not uniformed
1061
+ if (!elementData) {
1062
+ return;
1063
+ }
1064
+
1065
+ elementData.update($el, elementData.options);
1066
+ });
1067
+ };
1068
+ }(jQuery));