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