-/*
-
-Uniform v2.1.0
-Copyright © 2009 Josh Pyles / Pixelmatrix Design LLC
-http://pixelmatrixdesign.com
-
-Requires jQuery 1.3 or newer
-
-Much thanks to Thomas Reynolds and Buck Wilson for their help and advice on
-this.
-
-Disabling text selection is made possible by Mathias Bynens
-<http://mathiasbynens.be/> and his noSelect plugin.
-<https://github.com/mathiasbynens/jquery-noselect>, which is embedded.
-
-Also, thanks to David Kaneda and Eugene Bond for their contributions to the
-plugin.
-
-Tyler Akins has also rewritten chunks of the plugin, helped close many issues,
-and ensured version 2 got out the door.
-
-License:
-MIT License - http://www.opensource.org/licenses/mit-license.php
-
-Enjoy!
-
-*/
-/*global jQuery, window, document, navigator*/
-
-(function ($, undef) {
- "use strict";
-
- /**
- * Use .prop() if jQuery supports it, otherwise fall back to .attr()
- *
- * @param jQuery $el jQuery'd element on which we're calling attr/prop
- * @param ... All other parameters are passed to jQuery's function
- * @return The result from jQuery
- */
- function attrOrProp($el) {
- var args = Array.prototype.slice.call(arguments, 1);
-
- if ($el.prop) {
- // jQuery 1.6+
- return $el.prop.apply($el, args);
- }
-
- // jQuery 1.5 and below
- return $el.attr.apply($el, args);
- }
-
- /**
- * For backwards compatibility with older jQuery libraries, only bind
- * one thing at a time. Also, this function adds our namespace to
- * events in one consistent location, shrinking the minified code.
- *
- * The properties on the events object are the names of the events
- * that we are supposed to add to. It can be a space separated list.
- * The namespace will be added automatically.
- *
- * @param jQuery $el
- * @param Object options Uniform options for this element
- * @param Object events Events to bind, properties are event names
- */
- function bindMany($el, options, events) {
- var name, namespaced;
-
- for (name in events) {
- if (events.hasOwnProperty(name)) {
- namespaced = name.replace(/ |$/g, options.eventNamespace);
- $el.bind(namespaced, events[name]);
- }
- }
- }
-
- /**
- * Bind the hover, active, focus, and blur UI updates
- *
- * @param jQuery $el Original element
- * @param jQuery $target Target for the events (our div/span)
- * @param Object options Uniform options for the element $target
- */
- function bindUi($el, $target, options) {
- bindMany($el, options, {
- focus: function () {
- $target.addClass(options.focusClass);
- },
- blur: function () {
- $target.removeClass(options.focusClass);
- $target.removeClass(options.activeClass);
- },
- mouseenter: function () {
- $target.addClass(options.hoverClass);
- },
- mouseleave: function () {
- $target.removeClass(options.hoverClass);
- $target.removeClass(options.activeClass);
- },
- "mousedown touchbegin": function () {
- if (!$el.is(":disabled")) {
- $target.addClass(options.activeClass);
- }
- },
- "mouseup touchend": function () {
- $target.removeClass(options.activeClass);
- }
- });
- }
-
- /**
- * Remove the hover, focus, active classes.
- *
- * @param jQuery $el Element with classes
- * @param Object options Uniform options for the element
- */
- function classClearStandard($el, options) {
- $el.removeClass(options.hoverClass + " " + options.focusClass + " " + options.activeClass);
- }
-
- /**
- * Add or remove a class, depending on if it's "enabled"
- *
- * @param jQuery $el Element that has the class added/removed
- * @param String className Class or classes to add/remove
- * @param Boolean enabled True to add the class, false to remove
- */
- function classUpdate($el, className, enabled) {
- if (enabled) {
- $el.addClass(className);
- } else {
- $el.removeClass(className);
- }
- }
-
- /**
- * Updating the "checked" property can be a little tricky. This
- * changed in jQuery 1.6 and now we can pass booleans to .prop().
- * Prior to that, one either adds an attribute ("checked=checked") or
- * removes the attribute.
- *
- * @param jQuery $tag Our Uniform span/div
- * @param jQuery $el Original form element
- * @param Object options Uniform options for this element
- */
- function classUpdateChecked($tag, $el, options) {
- var c = "checked",
- isChecked = $el.is(":" + c);
-
- if ($el.prop) {
- // jQuery 1.6+
- $el.prop(c, isChecked);
- } else {
- // jQuery 1.5 and below
- if (isChecked) {
- $el.attr(c, c);
- } else {
- $el.removeAttr(c);
- }
- }
-
- classUpdate($tag, options.checkedClass, isChecked);
- }
-
- /**
- * Set or remove the "disabled" class for disabled elements, based on
- * if the
- *
- * @param jQuery $tag Our Uniform span/div
- * @param jQuery $el Original form element
- * @param Object options Uniform options for this element
- */
- function classUpdateDisabled($tag, $el, options) {
- classUpdate($tag, options.disabledClass, $el.is(":disabled"));
- }
-
- /**
- * Wrap an element inside of a container or put the container next
- * to the element. See the code for examples of the different methods.
- *
- * Returns the container that was added to the HTML.
- *
- * @param jQuery $el Element to wrap
- * @param jQuery $container Add this new container around/near $el
- * @param String method One of "after", "before" or "wrap"
- * @return $container after it has been cloned for adding to $el
- */
- function divSpanWrap($el, $container, method) {
- switch (method) {
- case "after":
- // Result: <element /> <container />
- $el.after($container);
- return $el.next();
- case "before":
- // Result: <container /> <element />
- $el.before($container);
- return $el.prev();
- case "wrap":
- // Result: <container> <element /> </container>
- $el.wrap($container);
- return $el.parent();
- }
-
- return null;
- }
-
-
- /**
- * Create a div/span combo for uniforming an element
- *
- * @param jQuery $el Element to wrap
- * @param Object options Options for the element, set by the user
- * @param Object divSpanConfig Options for how we wrap the div/span
- * @return Object Contains the div and span as properties
- */
- function divSpan($el, options, divSpanConfig) {
- var $div, $span, id;
-
- if (!divSpanConfig) {
- divSpanConfig = {};
- }
-
- divSpanConfig = $.extend({
- bind: {},
- divClass: null,
- divWrap: "wrap",
- spanClass: null,
- spanHtml: null,
- spanWrap: "wrap"
- }, divSpanConfig);
-
- $div = $('<div />');
- $span = $('<span />');
-
- // Automatically hide this div/span if the element is hidden.
- // Do not hide if the element is hidden because a parent is hidden.
- if (options.autoHide && $el.is(':hidden') && $el.css('display') === 'none') {
- $div.hide();
- }
-
- if (divSpanConfig.divClass) {
- $div.addClass(divSpanConfig.divClass);
- }
-
- if (options.wrapperClass) {
- $div.addClass(options.wrapperClass);
- }
-
- if (divSpanConfig.spanClass) {
- $span.addClass(divSpanConfig.spanClass);
- }
-
- id = attrOrProp($el, 'id');
-
- if (options.useID && id) {
- attrOrProp($div, 'id', options.idPrefix + '-' + id);
- }
-
- if (divSpanConfig.spanHtml) {
- $span.html(divSpanConfig.spanHtml);
- }
-
- $div = divSpanWrap($el, $div, divSpanConfig.divWrap);
- $span = divSpanWrap($el, $span, divSpanConfig.spanWrap);
- classUpdateDisabled($div, $el, options);
- return {
- div: $div,
- span: $span
- };
- }
-
-
- /**
- * Wrap an element with a span to apply a global wrapper class
- *
- * @param jQuery $el Element to wrap
- * @param object options
- * @return jQuery Wrapper element
- */
- function wrapWithWrapperClass($el, options) {
- var $span;
-
- if (!options.wrapperClass) {
- return null;
- }
-
- $span = $('<span />').addClass(options.wrapperClass);
- $span = divSpanWrap($el, $span, "wrap");
- return $span;
- }
-
-
- /**
- * Test if high contrast mode is enabled.
- *
- * In high contrast mode, background images can not be set and
- * they are always returned as 'none'.
- *
- * @return boolean True if in high contrast mode
- */
- function highContrast() {
- var c, $div, el, rgb;
-
- // High contrast mode deals with white and black
- rgb = 'rgb(120,2,153)';
- $div = $('<div style="width:0;height:0;color:' + rgb + '">');
- $('body').append($div);
- el = $div.get(0);
-
- // $div.css() will get the style definition, not
- // the actually displaying style
- if (window.getComputedStyle) {
- c = window.getComputedStyle(el, '').color;
- } else {
- c = (el.currentStyle || el.style || {}).color;
- }
-
- $div.remove();
- return c.replace(/ /g, '') !== rgb;
- }
-
-
- /**
- * Change text into safe HTML
- *
- * @param String text
- * @return String HTML version
- */
- function htmlify(text) {
- if (!text) {
- return "";
- }
-
- return $('<span />').text(text).html();
- }
-
- /**
- * If not MSIE, return false.
- * If it is, return the version number.
- *
- * @return false|number
- */
- function isMsie() {
- return navigator.cpuClass && !navigator.product;
- }
-
- /**
- * Return true if this version of IE allows styling
- *
- * @return boolean
- */
- function isMsieSevenOrNewer() {
- if (typeof window.XMLHttpRequest !== 'undefined') {
- return true;
- }
-
- return false;
- }
-
- /**
- * Test if the element is a multiselect
- *
- * @param jQuery $el Element
- * @return boolean true/false
- */
- function isMultiselect($el) {
- var elSize;
-
- if ($el[0].multiple) {
- return true;
- }
-
- elSize = attrOrProp($el, "size");
-
- if (!elSize || elSize <= 1) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Meaningless utility function. Used mostly for improving minification.
- *
- * @return false
- */
- function returnFalse() {
- return false;
- }
-
- /**
- * noSelect plugin, very slightly modified
- * http://mths.be/noselect v1.0.3
- *
- * @param jQuery $elem Element that we don't want to select
- * @param Object options Uniform options for the element
- */
- function noSelect($elem, options) {
- var none = 'none';
- bindMany($elem, options, {
- 'selectstart dragstart mousedown': returnFalse
- });
-
- $elem.css({
- MozUserSelect: none,
- msUserSelect: none,
- webkitUserSelect: none,
- userSelect: none
- });
- }
-
- /**
- * Updates the filename tag based on the value of the real input
- * element.
- *
- * @param jQuery $el Actual form element
- * @param jQuery $filenameTag Span/div to update
- * @param Object options Uniform options for this element
- */
- function setFilename($el, $filenameTag, options) {
- var filename = $el.val();
-
- if (filename === "") {
- filename = options.fileDefaultHtml;
- } else {
- filename = filename.split(/[\/\\]+/);
- filename = filename[(filename.length - 1)];
- }
-
- $filenameTag.text(filename);
- }
-
-
- /**
- * Function from jQuery to swap some CSS values, run a callback,
- * then restore the CSS. Modified to pass JSLint and handle undefined
- * values with 'use strict'.
- *
- * @param jQuery $el Element
- * @param object newCss CSS values to swap out
- * @param Function callback Function to run
- */
- function swap($elements, newCss, callback) {
- var restore, item;
-
- restore = [];
-
- $elements.each(function () {
- var name;
-
- for (name in newCss) {
- if (Object.prototype.hasOwnProperty.call(newCss, name)) {
- restore.push({
- el: this,
- name: name,
- old: this.style[name]
- });
-
- this.style[name] = newCss[name];
- }
- }
- });
-
- callback();
-
- while (restore.length) {
- item = restore.pop();
- item.el.style[item.name] = item.old;
- }
- }
-
-
- /**
- * The browser doesn't provide sizes of elements that are not visible.
- * This will clone an element and add it to the DOM for calculations.
- *
- * @param jQuery $el
- * @param String method
- */
- function sizingInvisible($el, callback) {
- var targets;
-
- // We wish to target ourselves and any parents as long as
- // they are not visible
- targets = $el.parents();
- targets.push($el[0]);
- targets = targets.not(':visible');
- swap(targets, {
- visibility: "hidden",
- display: "block",
- position: "absolute"
- }, callback);
- }
-
-
- /**
- * Standard way to unwrap the div/span combination from an element
- *
- * @param jQuery $el Element that we wish to preserve
- * @param Object options Uniform options for the element
- * @return Function This generated function will perform the given work
- */
- function unwrapUnwrapUnbindFunction($el, options) {
- return function () {
- $el.unwrap().unwrap().unbind(options.eventNamespace);
- };
- }
-
- var allowStyling = true, // False if IE6 or other unsupported browsers
- highContrastTest = false, // Was the high contrast test ran?
- uniformHandlers = [ // Objects that take care of "unification"
- {
- // Buttons
- match: function ($el) {
- return $el.is("a, button, :submit, :reset, input[type='button']");
- },
- apply: function ($el, options) {
- var $div, defaultSpanHtml, ds, getHtml, doingClickEvent;
- defaultSpanHtml = options.submitDefaultHtml;
-
- if ($el.is(":reset")) {
- defaultSpanHtml = options.resetDefaultHtml;
- }
-
- if ($el.is("a, button")) {
- // Use the HTML inside the tag
- getHtml = function () {
- return $el.html() || defaultSpanHtml;
- };
- } else {
- // Use the value property of the element
- getHtml = function () {
- return htmlify(attrOrProp($el, "value")) || defaultSpanHtml;
- };
- }
-
- ds = divSpan($el, options, {
- divClass: options.buttonClass,
- spanHtml: getHtml(),
- });
- $div = ds.div;
- bindUi($el, $div, options);
- doingClickEvent = false;
- bindMany($div, options, {
- "click touchend": function () {
- var ev, res, target, href;
-
- if (doingClickEvent) {
- return;
- }
-
- if ($el.is(':disabled')) {
- return;
- }
-
- doingClickEvent = true;
-
- if ($el[0].dispatchEvent) {
- ev = document.createEvent("MouseEvents");
- ev.initEvent("click", true, true);
- res = $el[0].dispatchEvent(ev);
-
- if ($el.is('a') && res) {
- target = attrOrProp($el, 'target');
- href = attrOrProp($el, 'href');
-
- if (!target || target === '_self') {
- document.location.href = href;
- } else {
- window.open(href, target);
- }
- }
- } else {
- $el.click();
- }
-
- doingClickEvent = false;
- }
- });
- noSelect($div, options);
- return {
- remove: function () {
- // Move $el out
- $div.after($el);
-
- // Remove div and span
- $div.remove();
-
- // Unbind events
- $el.unbind(options.eventNamespace);
- return $el;
- },
- update: function () {
- classClearStandard($div, options);
- classUpdateDisabled($div, $el, options);
- $el.detach();
- ds.span.html(getHtml()).append($el);
- }
- };
- }
- },
- {
- // Checkboxes
- match: function ($el) {
- return $el.is(":checkbox");
- },
- apply: function ($el, options) {
- var ds, $div, $span;
- ds = divSpan($el, options, {
- divClass: options.checkboxClass
- });
- $div = ds.div;
- $span = ds.span;
-
- // Add focus classes, toggling, active, etc.
- bindUi($el, $div, options);
- bindMany($el, options, {
- "click touchend": function () {
- classUpdateChecked($span, $el, options);
- }
- });
- classUpdateChecked($span, $el, options);
- return {
- remove: unwrapUnwrapUnbindFunction($el, options),
- update: function () {
- classClearStandard($div, options);
- $span.removeClass(options.checkedClass);
- classUpdateChecked($span, $el, options);
- classUpdateDisabled($div, $el, options);
- }
- };
- }
- },
- {
- // File selection / uploads
- match: function ($el) {
- return $el.is(":file");
- },
- apply: function ($el, options) {
- var ds, $div, $filename, $button;
-
- // The "span" is the button
- ds = divSpan($el, options, {
- divClass: options.fileClass,
- spanClass: options.fileButtonClass,
- spanHtml: options.fileButtonHtml,
- spanWrap: "after"
- });
- $div = ds.div;
- $button = ds.span;
- $filename = $("<span />").html(options.fileDefaultHtml);
- $filename.addClass(options.filenameClass);
- $filename = divSpanWrap($el, $filename, "after");
-
- // Set the size
- if (!attrOrProp($el, "size")) {
- attrOrProp($el, "size", $div.width() / 10);
- }
-
- // Actions
- function filenameUpdate() {
- setFilename($el, $filename, options);
- }
-
- bindUi($el, $div, options);
-
- // Account for input saved across refreshes
- filenameUpdate();
-
- // IE7 doesn't fire onChange until blur or second fire.
- if (isMsie()) {
- // IE considers browser chrome blocking I/O, so it
- // suspends tiemouts until after the file has
- // been selected.
- bindMany($el, options, {
- click: function () {
- $el.trigger("change");
- setTimeout(filenameUpdate, 0);
- }
- });
- } else {
- // All other browsers behave properly
- bindMany($el, options, {
- change: filenameUpdate
- });
- }
-
- noSelect($filename, options);
- noSelect($button, options);
- return {
- remove: function () {
- // Remove filename and button
- $filename.remove();
- $button.remove();
-
- // Unwrap parent div, remove events
- return $el.unwrap().unbind(options.eventNamespace);
- },
- update: function () {
- classClearStandard($div, options);
- setFilename($el, $filename, options);
- classUpdateDisabled($div, $el, options);
- }
- };
- }
- },
- {
- // Input fields (text)
- match: function ($el) {
- if ($el.is("input")) {
- var t = (" " + attrOrProp($el, "type") + " ").toLowerCase(),
- allowed = " color date datetime datetime-local email month number password search tel text time url week ";
- return allowed.indexOf(t) >= 0;
- }
-
- return false;
- },
- apply: function ($el, options) {
- var elType, $wrapper;
-
- elType = attrOrProp($el, "type");
- $el.addClass(options.inputClass);
- $wrapper = wrapWithWrapperClass($el, options);
- bindUi($el, $el, options);
-
- if (options.inputAddTypeAsClass) {
- $el.addClass(elType);
- }
-
- return {
- remove: function () {
- $el.removeClass(options.inputClass);
-
- if (options.inputAddTypeAsClass) {
- $el.removeClass(elType);
- }
-
- if ($wrapper) {
- $el.unwrap();
- }
- },
- update: returnFalse
- };
- }
- },
- {
- // Radio buttons
- match: function ($el) {
- return $el.is(":radio");
- },
- apply: function ($el, options) {
- var ds, $div, $span;
- ds = divSpan($el, options, {
- divClass: options.radioClass
- });
- $div = ds.div;
- $span = ds.span;
-
- // Add classes for focus, handle active, checked
- bindUi($el, $div, options);
- bindMany($el, options, {
- "click touchend": function () {
- // Find all radios with the same name, then update
- // them with $.uniform.update() so the right
- // per-element options are used
- $.uniform.update($(':radio[name="' + attrOrProp($el, "name") + '"]'));
- }
- });
- classUpdateChecked($span, $el, options);
- return {
- remove: unwrapUnwrapUnbindFunction($el, options),
- update: function () {
- classClearStandard($div, options);
- classUpdateChecked($span, $el, options);
- classUpdateDisabled($div, $el, options);
- }
- };
- }
- },
- {
- // Select lists, but do not style multiselects here
- match: function ($el) {
- if ($el.is("select") && !isMultiselect($el)) {
- return true;
- }
-
- return false;
- },
- apply: function ($el, options) {
- var ds, $div, $span, origElemWidth;
-
- if (options.selectAutoWidth) {
- sizingInvisible($el, function () {
- origElemWidth = $el.width();
- });
- }
-
- ds = divSpan($el, options, {
- divClass: options.selectClass,
- spanHtml: ($el.find(":selected:first") || $el.find("option:first")).html(),
- spanWrap: "before"
- });
- $div = ds.div;
- $span = ds.span;
-
- if (options.selectAutoWidth) {
- // Use the width of the select and adjust the
- // span and div accordingly
- sizingInvisible($el, function () {
- // Force "display: block" - related to bug #287
- swap($([ $span[0], $div[0] ]), {
- display: "block"
- }, function () {
- var spanPad;
- spanPad = $span.outerWidth() - $span.width();
- $div.width(origElemWidth + spanPad);
- $span.width(origElemWidth);
- });
- });
- } else {
- // Force the select to fill the size of the div
- $div.addClass('fixedWidth');
- }
-
- // Take care of events
- bindUi($el, $div, options);
- bindMany($el, options, {
- change: function () {
- $span.html($el.find(":selected").html());
- $div.removeClass(options.activeClass);
- },
- "click touchend": function () {
- // IE7 and IE8 may not update the value right
- // until after click event - issue #238
- var selHtml = $el.find(":selected").html();
-
- if ($span.html() !== selHtml) {
- // Change was detected
- // Fire the change event on the select tag
- $el.trigger('change');
- }
- },
- keyup: function () {
- $span.html($el.find(":selected").html());
- }
- });
- noSelect($span, options);
- return {
- remove: function () {
- // Remove sibling span
- $span.remove();
-
- // Unwrap parent div
- $el.unwrap().unbind(options.eventNamespace);
- return $el;
- },
- update: function () {
- if (options.selectAutoWidth) {
- // Easier to remove and reapply formatting
- $.uniform.restore($el);
- $el.uniform(options);
- } else {
- classClearStandard($div, options);
-
- // Reset current selected text
- $span.html($el.find(":selected").html());
- classUpdateDisabled($div, $el, options);
- }
- }
- };
- }
- },
- {
- // Select lists - multiselect lists only
- match: function ($el) {
- if ($el.is("select") && isMultiselect($el)) {
- return true;
- }
-
- return false;
- },
- apply: function ($el, options) {
- var $wrapper;
-
- $el.addClass(options.selectMultiClass);
- $wrapper = wrapWithWrapperClass($el, options);
- bindUi($el, $el, options);
-
- return {
- remove: function () {
- $el.removeClass(options.selectMultiClass);
-
- if ($wrapper) {
- $el.unwrap();
- }
- },
- update: returnFalse
- };
- }
- },
- {
- // Textareas
- match: function ($el) {
- return $el.is("textarea");
- },
- apply: function ($el, options) {
- var $wrapper;
-
- $el.addClass(options.textareaClass);
- $wrapper = wrapWithWrapperClass($el, options);
- bindUi($el, $el, options);
-
- return {
- remove: function () {
- $el.removeClass(options.textareaClass);
-
- if ($wrapper) {
- $el.unwrap();
- }
- },
- update: returnFalse
- };
- }
- }
- ];
-
- // IE6 can't be styled - can't set opacity on select
- if (isMsie() && !isMsieSevenOrNewer()) {
- allowStyling = false;
- }
-
- $.uniform = {
- // Default options that can be overridden globally or when uniformed
- // globally: $.uniform.defaults.fileButtonHtml = "Pick A File";
- // on uniform: $('input').uniform({fileButtonHtml: "Pick a File"});
- defaults: {
- activeClass: "active",
- autoHide: true,
- buttonClass: "button",
- checkboxClass: "checker",
- checkedClass: "checked",
- disabledClass: "disabled",
- eventNamespace: ".uniform",
- fileButtonClass: "action",
- fileButtonHtml: "Choose File",
- fileClass: "uploader",
- fileDefaultHtml: "No file selected",
- filenameClass: "filename",
- focusClass: "focus",
- hoverClass: "hover",
- idPrefix: "uniform",
- inputAddTypeAsClass: true,
- inputClass: "uniform-input",
- radioClass: "radio",
- resetDefaultHtml: "Reset",
- resetSelector: false, // We'll use our own function when you don't specify one
- selectAutoWidth: true,
- selectClass: "selector",
- selectMultiClass: "uniform-multiselect",
- submitDefaultHtml: "Submit", // Only text allowed
- textareaClass: "uniform",
- useID: true,
- wrapperClass: null
- },
-
- // All uniformed elements - DOM objects
- elements: []
- };
-
- $.fn.uniform = function (options) {
- var el = this;
- options = $.extend({}, $.uniform.defaults, options);
-
- // If we are in high contrast mode, do not allow styling
- if (!highContrastTest) {
- highContrastTest = true;
-
- if (highContrast()) {
- allowStyling = false;
- }
- }
-
- // Only uniform on browsers that work
- if (!allowStyling) {
- return this;
- }
-
- // Code for specifying a reset button
- if (options.resetSelector) {
- $(options.resetSelector).mouseup(function () {
- window.setTimeout(function () {
- $.uniform.update(el);
- }, 10);
- });
- }
-
- return this.each(function () {
- var $el = $(this), i, handler, callbacks;
-
- // Avoid uniforming elements already uniformed - just update
- if ($el.data("uniformed")) {
- $.uniform.update($el);
- return;
- }
-
- // See if we have any handler for this type of element
- for (i = 0; i < uniformHandlers.length; i = i + 1) {
- handler = uniformHandlers[i];
-
- if (handler.match($el, options)) {
- callbacks = handler.apply($el, options);
- $el.data("uniformed", callbacks);
-
- // Store element in our global array
- $.uniform.elements.push($el.get(0));
- return;
- }
- }
-
- // Could not style this element
- });
- };
-
- $.uniform.restore = $.fn.uniform.restore = function (elem) {
- if (elem === undef) {
- elem = $.uniform.elements;
- }
-
- $(elem).each(function () {
- var $el = $(this), index, elementData;
- elementData = $el.data("uniformed");
-
- // Skip elements that are not uniformed
- if (!elementData) {
- return;
- }
-
- // Unbind events, remove additional markup that was added
- elementData.remove();
-
- // Remove item from list of uniformed elements
- index = $.inArray(this, $.uniform.elements);
-
- if (index >= 0) {
- $.uniform.elements.splice(index, 1);
- }
-
- $el.removeData("uniformed");
- });
- };
-
- $.uniform.update = $.fn.uniform.update = function (elem) {
- if (elem === undef) {
- elem = $.uniform.elements;
- }
-
- $(elem).each(function () {
- var $el = $(this), elementData;
- elementData = $el.data("uniformed");
-
- // Skip elements that are not uniformed
- if (!elementData) {
- return;
- }
-
- elementData.update($el, elementData.options);
- });
- };
-}(jQuery));
+/*\r
+\r
+Uniform v2.1.0\r
+Copyright © 2009 Josh Pyles / Pixelmatrix Design LLC\r
+http://pixelmatrixdesign.com\r
+\r
+Requires jQuery 1.3 or newer\r
+\r
+Much thanks to Thomas Reynolds and Buck Wilson for their help and advice on\r
+this.\r
+\r
+Disabling text selection is made possible by Mathias Bynens\r
+<http://mathiasbynens.be/> and his noSelect plugin.\r
+<https://github.com/mathiasbynens/jquery-noselect>, which is embedded.\r
+\r
+Also, thanks to David Kaneda and Eugene Bond for their contributions to the\r
+plugin.\r
+\r
+Tyler Akins has also rewritten chunks of the plugin, helped close many issues,\r
+and ensured version 2 got out the door.\r
+\r
+License:\r
+MIT License - http://www.opensource.org/licenses/mit-license.php\r
+\r
+Enjoy!\r
+\r
+*/\r
+/*global jQuery, window, document, navigator*/\r
+\r
+(function ($, undef) {\r
+ "use strict";\r
+\r
+ /**\r
+ * Use .prop() if jQuery supports it, otherwise fall back to .attr()\r
+ *\r
+ * @param jQuery $el jQuery'd element on which we're calling attr/prop\r
+ * @param ... All other parameters are passed to jQuery's function\r
+ * @return The result from jQuery\r
+ */\r
+ function attrOrProp($el) {\r
+ var args = Array.prototype.slice.call(arguments, 1);\r
+\r
+ if ($el.prop) {\r
+ // jQuery 1.6+\r
+ return $el.prop.apply($el, args);\r
+ }\r
+\r
+ // jQuery 1.5 and below\r
+ return $el.attr.apply($el, args);\r
+ }\r
+\r
+ /**\r
+ * For backwards compatibility with older jQuery libraries, only bind\r
+ * one thing at a time. Also, this function adds our namespace to\r
+ * events in one consistent location, shrinking the minified code.\r
+ *\r
+ * The properties on the events object are the names of the events\r
+ * that we are supposed to add to. It can be a space separated list.\r
+ * The namespace will be added automatically.\r
+ *\r
+ * @param jQuery $el\r
+ * @param Object options Uniform options for this element\r
+ * @param Object events Events to bind, properties are event names\r
+ */\r
+ function bindMany($el, options, events) {\r
+ var name, namespaced;\r
+\r
+ for (name in events) {\r
+ if (events.hasOwnProperty(name)) {\r
+ namespaced = name.replace(/ |$/g, options.eventNamespace);\r
+ $el.bind(namespaced, events[name]);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Bind the hover, active, focus, and blur UI updates\r
+ *\r
+ * @param jQuery $el Original element\r
+ * @param jQuery $target Target for the events (our div/span)\r
+ * @param Object options Uniform options for the element $target\r
+ */\r
+ function bindUi($el, $target, options) {\r
+ bindMany($el, options, {\r
+ focus: function () {\r
+ $target.addClass(options.focusClass);\r
+ },\r
+ blur: function () {\r
+ $target.removeClass(options.focusClass);\r
+ $target.removeClass(options.activeClass);\r
+ },\r
+ mouseenter: function () {\r
+ $target.addClass(options.hoverClass);\r
+ },\r
+ mouseleave: function () {\r
+ $target.removeClass(options.hoverClass);\r
+ $target.removeClass(options.activeClass);\r
+ },\r
+ "mousedown touchbegin": function () {\r
+ if (!$el.is(":disabled")) {\r
+ $target.addClass(options.activeClass);\r
+ }\r
+ },\r
+ "mouseup touchend": function () {\r
+ $target.removeClass(options.activeClass);\r
+ }\r
+ });\r
+ }\r
+\r
+ /**\r
+ * Remove the hover, focus, active classes.\r
+ *\r
+ * @param jQuery $el Element with classes\r
+ * @param Object options Uniform options for the element\r
+ */\r
+ function classClearStandard($el, options) {\r
+ $el.removeClass(options.hoverClass + " " + options.focusClass + " " + options.activeClass);\r
+ }\r
+\r
+ /**\r
+ * Add or remove a class, depending on if it's "enabled"\r
+ *\r
+ * @param jQuery $el Element that has the class added/removed\r
+ * @param String className Class or classes to add/remove\r
+ * @param Boolean enabled True to add the class, false to remove\r
+ */\r
+ function classUpdate($el, className, enabled) {\r
+ if (enabled) {\r
+ $el.addClass(className);\r
+ } else {\r
+ $el.removeClass(className);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Updating the "checked" property can be a little tricky. This\r
+ * changed in jQuery 1.6 and now we can pass booleans to .prop().\r
+ * Prior to that, one either adds an attribute ("checked=checked") or\r
+ * removes the attribute.\r
+ *\r
+ * @param jQuery $tag Our Uniform span/div\r
+ * @param jQuery $el Original form element\r
+ * @param Object options Uniform options for this element\r
+ */\r
+ function classUpdateChecked($tag, $el, options) {\r
+ var c = "checked",\r
+ isChecked = $el.is(":" + c);\r
+\r
+ if ($el.prop) {\r
+ // jQuery 1.6+\r
+ $el.prop(c, isChecked);\r
+ } else {\r
+ // jQuery 1.5 and below\r
+ if (isChecked) {\r
+ $el.attr(c, c);\r
+ } else {\r
+ $el.removeAttr(c);\r
+ }\r
+ }\r
+\r
+ classUpdate($tag, options.checkedClass, isChecked);\r
+ }\r
+\r
+ /**\r
+ * Set or remove the "disabled" class for disabled elements, based on\r
+ * if the \r
+ *\r
+ * @param jQuery $tag Our Uniform span/div\r
+ * @param jQuery $el Original form element\r
+ * @param Object options Uniform options for this element\r
+ */\r
+ function classUpdateDisabled($tag, $el, options) {\r
+ classUpdate($tag, options.disabledClass, $el.is(":disabled"));\r
+ }\r
+\r
+ /**\r
+ * Wrap an element inside of a container or put the container next\r
+ * to the element. See the code for examples of the different methods.\r
+ *\r
+ * Returns the container that was added to the HTML.\r
+ *\r
+ * @param jQuery $el Element to wrap\r
+ * @param jQuery $container Add this new container around/near $el\r
+ * @param String method One of "after", "before" or "wrap"\r
+ * @return $container after it has been cloned for adding to $el\r
+ */\r
+ function divSpanWrap($el, $container, method) {\r
+ switch (method) {\r
+ case "after":\r
+ // Result: <element /> <container />\r
+ $el.after($container);\r
+ return $el.next();\r
+ case "before":\r
+ // Result: <container /> <element />\r
+ $el.before($container);\r
+ return $el.prev();\r
+ case "wrap":\r
+ // Result: <container> <element /> </container>\r
+ $el.wrap($container);\r
+ return $el.parent();\r
+ }\r
+\r
+ return null;\r
+ }\r
+\r
+\r
+ /**\r
+ * Create a div/span combo for uniforming an element\r
+ *\r
+ * @param jQuery $el Element to wrap\r
+ * @param Object options Options for the element, set by the user\r
+ * @param Object divSpanConfig Options for how we wrap the div/span\r
+ * @return Object Contains the div and span as properties\r
+ */\r
+ function divSpan($el, options, divSpanConfig) {\r
+ var $div, $span, id;\r
+\r
+ if (!divSpanConfig) {\r
+ divSpanConfig = {};\r
+ }\r
+\r
+ divSpanConfig = $.extend({\r
+ bind: {},\r
+ divClass: null,\r
+ divWrap: "wrap",\r
+ spanClass: null,\r
+ spanHtml: null,\r
+ spanWrap: "wrap"\r
+ }, divSpanConfig);\r
+\r
+ $div = $('<div />');\r
+ $span = $('<span />');\r
+\r
+ // Automatically hide this div/span if the element is hidden.\r
+ // Do not hide if the element is hidden because a parent is hidden.\r
+ if (options.autoHide && $el.is(':hidden') && $el.css('display') === 'none') {\r
+ $div.hide();\r
+ }\r
+\r
+ if (divSpanConfig.divClass) {\r
+ $div.addClass(divSpanConfig.divClass);\r
+ }\r
+\r
+ if (options.wrapperClass) {\r
+ $div.addClass(options.wrapperClass);\r
+ }\r
+\r
+ if (divSpanConfig.spanClass) {\r
+ $span.addClass(divSpanConfig.spanClass);\r
+ }\r
+\r
+ id = attrOrProp($el, 'id');\r
+\r
+ if (options.useID && id) {\r
+ attrOrProp($div, 'id', options.idPrefix + '-' + id);\r
+ }\r
+\r
+ if (divSpanConfig.spanHtml) {\r
+ $span.html(divSpanConfig.spanHtml);\r
+ }\r
+\r
+ $div = divSpanWrap($el, $div, divSpanConfig.divWrap);\r
+ $span = divSpanWrap($el, $span, divSpanConfig.spanWrap);\r
+ classUpdateDisabled($div, $el, options);\r
+ return {\r
+ div: $div,\r
+ span: $span\r
+ };\r
+ }\r
+\r
+\r
+ /**\r
+ * Wrap an element with a span to apply a global wrapper class\r
+ *\r
+ * @param jQuery $el Element to wrap\r
+ * @param object options\r
+ * @return jQuery Wrapper element\r
+ */\r
+ function wrapWithWrapperClass($el, options) {\r
+ var $span;\r
+\r
+ if (!options.wrapperClass) {\r
+ return null;\r
+ }\r
+\r
+ $span = $('<span />').addClass(options.wrapperClass);\r
+ $span = divSpanWrap($el, $span, "wrap");\r
+ return $span;\r
+ }\r
+\r
+\r
+ /**\r
+ * Test if high contrast mode is enabled.\r
+ *\r
+ * In high contrast mode, background images can not be set and\r
+ * they are always returned as 'none'.\r
+ *\r
+ * @return boolean True if in high contrast mode\r
+ */\r
+ function highContrast() {\r
+ var c, $div, el, rgb;\r
+\r
+ // High contrast mode deals with white and black\r
+ rgb = 'rgb(120,2,153)';\r
+ $div = $('<div style="width:0;height:0;color:' + rgb + '">');\r
+ $('body').append($div);\r
+ el = $div.get(0);\r
+\r
+ // $div.css() will get the style definition, not\r
+ // the actually displaying style\r
+ if (window.getComputedStyle) {\r
+ c = window.getComputedStyle(el, '').color;\r
+ } else {\r
+ c = (el.currentStyle || el.style || {}).color;\r
+ }\r
+\r
+ $div.remove();\r
+ return c.replace(/ /g, '') !== rgb;\r
+ }\r
+\r
+\r
+ /**\r
+ * Change text into safe HTML\r
+ *\r
+ * @param String text\r
+ * @return String HTML version\r
+ */\r
+ function htmlify(text) {\r
+ if (!text) {\r
+ return "";\r
+ }\r
+\r
+ return $('<span />').text(text).html();\r
+ }\r
+\r
+ /**\r
+ * If not MSIE, return false.\r
+ * If it is, return the version number.\r
+ *\r
+ * @return false|number\r
+ */\r
+ function isMsie() {\r
+ return navigator.cpuClass && !navigator.product;\r
+ }\r
+\r
+ /**\r
+ * Return true if this version of IE allows styling\r
+ *\r
+ * @return boolean\r
+ */\r
+ function isMsieSevenOrNewer() {\r
+ if (typeof window.XMLHttpRequest !== 'undefined') {\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Test if the element is a multiselect\r
+ *\r
+ * @param jQuery $el Element\r
+ * @return boolean true/false\r
+ */\r
+ function isMultiselect($el) {\r
+ var elSize;\r
+\r
+ if ($el[0].multiple) {\r
+ return true;\r
+ }\r
+\r
+ elSize = attrOrProp($el, "size");\r
+\r
+ if (!elSize || elSize <= 1) {\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Meaningless utility function. Used mostly for improving minification.\r
+ *\r
+ * @return false\r
+ */\r
+ function returnFalse() {\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * noSelect plugin, very slightly modified\r
+ * http://mths.be/noselect v1.0.3\r
+ *\r
+ * @param jQuery $elem Element that we don't want to select\r
+ * @param Object options Uniform options for the element\r
+ */\r
+ function noSelect($elem, options) {\r
+ var none = 'none';\r
+ bindMany($elem, options, {\r
+ 'selectstart dragstart mousedown': returnFalse\r
+ });\r
+\r
+ $elem.css({\r
+ MozUserSelect: none,\r
+ msUserSelect: none,\r
+ webkitUserSelect: none,\r
+ userSelect: none\r
+ });\r
+ }\r
+\r
+ /**\r
+ * Updates the filename tag based on the value of the real input\r
+ * element.\r
+ *\r
+ * @param jQuery $el Actual form element\r
+ * @param jQuery $filenameTag Span/div to update\r
+ * @param Object options Uniform options for this element\r
+ */\r
+ function setFilename($el, $filenameTag, options) {\r
+ var filename = $el.val();\r
+\r
+ if (filename === "") {\r
+ filename = options.fileDefaultHtml;\r
+ } else {\r
+ filename = filename.split(/[\/\\]+/);\r
+ filename = filename[(filename.length - 1)];\r
+ }\r
+\r
+ $filenameTag.text(filename);\r
+ }\r
+\r
+\r
+ /**\r
+ * Function from jQuery to swap some CSS values, run a callback,\r
+ * then restore the CSS. Modified to pass JSLint and handle undefined\r
+ * values with 'use strict'.\r
+ *\r
+ * @param jQuery $el Element\r
+ * @param object newCss CSS values to swap out\r
+ * @param Function callback Function to run\r
+ */\r
+ function swap($elements, newCss, callback) {\r
+ var restore, item;\r
+\r
+ restore = [];\r
+\r
+ $elements.each(function () {\r
+ var name;\r
+\r
+ for (name in newCss) {\r
+ if (Object.prototype.hasOwnProperty.call(newCss, name)) {\r
+ restore.push({\r
+ el: this,\r
+ name: name,\r
+ old: this.style[name]\r
+ });\r
+\r
+ this.style[name] = newCss[name];\r
+ }\r
+ }\r
+ });\r
+\r
+ callback();\r
+\r
+ while (restore.length) {\r
+ item = restore.pop();\r
+ item.el.style[item.name] = item.old;\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * The browser doesn't provide sizes of elements that are not visible.\r
+ * This will clone an element and add it to the DOM for calculations.\r
+ *\r
+ * @param jQuery $el\r
+ * @param String method\r
+ */\r
+ function sizingInvisible($el, callback) {\r
+ var targets;\r
+\r
+ // We wish to target ourselves and any parents as long as\r
+ // they are not visible\r
+ targets = $el.parents();\r
+ targets.push($el[0]);\r
+ targets = targets.not(':visible');\r
+ swap(targets, {\r
+ visibility: "hidden",\r
+ display: "block",\r
+ position: "absolute"\r
+ }, callback);\r
+ }\r
+\r
+\r
+ /**\r
+ * Standard way to unwrap the div/span combination from an element\r
+ *\r
+ * @param jQuery $el Element that we wish to preserve\r
+ * @param Object options Uniform options for the element\r
+ * @return Function This generated function will perform the given work\r
+ */\r
+ function unwrapUnwrapUnbindFunction($el, options) {\r
+ return function () {\r
+ $el.unwrap().unwrap().unbind(options.eventNamespace);\r
+ };\r
+ }\r
+\r
+ var allowStyling = true, // False if IE6 or other unsupported browsers\r
+ highContrastTest = false, // Was the high contrast test ran?\r
+ uniformHandlers = [ // Objects that take care of "unification"\r
+ {\r
+ // Buttons\r
+ match: function ($el) {\r
+ return $el.is("a, button, :submit, :reset, input[type='button']");\r
+ },\r
+ apply: function ($el, options) {\r
+ var $div, defaultSpanHtml, ds, getHtml, doingClickEvent;\r
+ defaultSpanHtml = options.submitDefaultHtml;\r
+\r
+ if ($el.is(":reset")) {\r
+ defaultSpanHtml = options.resetDefaultHtml;\r
+ }\r
+\r
+ if ($el.is("a, button")) {\r
+ // Use the HTML inside the tag\r
+ getHtml = function () {\r
+ return $el.html() || defaultSpanHtml;\r
+ };\r
+ } else {\r
+ // Use the value property of the element\r
+ getHtml = function () {\r
+ return htmlify(attrOrProp($el, "value")) || defaultSpanHtml;\r
+ };\r
+ }\r
+\r
+ ds = divSpan($el, options, {\r
+ divClass: options.buttonClass,\r
+ spanHtml: getHtml(),\r
+ });\r
+ $div = ds.div;\r
+ bindUi($el, $div, options);\r
+ doingClickEvent = false;\r
+ bindMany($div, options, {\r
+ "click touchend": function () {\r
+ var ev, res, target, href;\r
+\r
+ if (doingClickEvent) {\r
+ return;\r
+ }\r
+\r
+ if ($el.is(':disabled')) {\r
+ return;\r
+ }\r
+\r
+ doingClickEvent = true;\r
+\r
+ if ($el[0].dispatchEvent) {\r
+ ev = document.createEvent("MouseEvents");\r
+ ev.initEvent("click", true, true);\r
+ res = $el[0].dispatchEvent(ev);\r
+\r
+ if ($el.is('a') && res) {\r
+ target = attrOrProp($el, 'target');\r
+ href = attrOrProp($el, 'href');\r
+\r
+ if (!target || target === '_self') {\r
+ document.location.href = href;\r
+ } else {\r
+ window.open(href, target);\r
+ }\r
+ }\r
+ } else {\r
+ $el.click();\r
+ }\r
+\r
+ doingClickEvent = false;\r
+ }\r
+ });\r
+ noSelect($div, options);\r
+ return {\r
+ remove: function () {\r
+ // Move $el out\r
+ $div.after($el);\r
+\r
+ // Remove div and span\r
+ $div.remove();\r
+\r
+ // Unbind events\r
+ $el.unbind(options.eventNamespace);\r
+ return $el;\r
+ },\r
+ update: function () {\r
+ classClearStandard($div, options);\r
+ classUpdateDisabled($div, $el, options);\r
+ $el.detach();\r
+ ds.span.html(getHtml()).append($el);\r
+ }\r
+ };\r
+ }\r
+ },\r
+ {\r
+ // Checkboxes\r
+ match: function ($el) {\r
+ return $el.is(":checkbox");\r
+ },\r
+ apply: function ($el, options) {\r
+ var ds, $div, $span;\r
+ ds = divSpan($el, options, {\r
+ divClass: options.checkboxClass\r
+ });\r
+ $div = ds.div;\r
+ $span = ds.span;\r
+\r
+ // Add focus classes, toggling, active, etc.\r
+ bindUi($el, $div, options);\r
+ bindMany($el, options, {\r
+ "click touchend": function () {\r
+ classUpdateChecked($span, $el, options);\r
+ }\r
+ });\r
+ classUpdateChecked($span, $el, options);\r
+ return {\r
+ remove: unwrapUnwrapUnbindFunction($el, options),\r
+ update: function () {\r
+ classClearStandard($div, options);\r
+ $span.removeClass(options.checkedClass);\r
+ classUpdateChecked($span, $el, options);\r
+ classUpdateDisabled($div, $el, options);\r
+ }\r
+ };\r
+ }\r
+ },\r
+ {\r
+ // File selection / uploads\r
+ match: function ($el) {\r
+ return $el.is(":file");\r
+ },\r
+ apply: function ($el, options) {\r
+ var ds, $div, $filename, $button;\r
+\r
+ // The "span" is the button\r
+ ds = divSpan($el, options, {\r
+ divClass: options.fileClass,\r
+ spanClass: options.fileButtonClass,\r
+ spanHtml: options.fileButtonHtml,\r
+ spanWrap: "after"\r
+ });\r
+ $div = ds.div;\r
+ $button = ds.span;\r
+ $filename = $("<span />").html(options.fileDefaultHtml);\r
+ $filename.addClass(options.filenameClass);\r
+ $filename = divSpanWrap($el, $filename, "after");\r
+\r
+ // Set the size\r
+ if (!attrOrProp($el, "size")) {\r
+ attrOrProp($el, "size", $div.width() / 10);\r
+ }\r
+\r
+ // Actions\r
+ function filenameUpdate() {\r
+ setFilename($el, $filename, options);\r
+ }\r
+\r
+ bindUi($el, $div, options);\r
+\r
+ // Account for input saved across refreshes\r
+ filenameUpdate();\r
+\r
+ // IE7 doesn't fire onChange until blur or second fire.\r
+ if (isMsie()) {\r
+ // IE considers browser chrome blocking I/O, so it\r
+ // suspends tiemouts until after the file has\r
+ // been selected.\r
+ bindMany($el, options, {\r
+ click: function () {\r
+ $el.trigger("change");\r
+ setTimeout(filenameUpdate, 0);\r
+ }\r
+ });\r
+ } else {\r
+ // All other browsers behave properly\r
+ bindMany($el, options, {\r
+ change: filenameUpdate\r
+ });\r
+ }\r
+\r
+ noSelect($filename, options);\r
+ noSelect($button, options);\r
+ return {\r
+ remove: function () {\r
+ // Remove filename and button\r
+ $filename.remove();\r
+ $button.remove();\r
+\r
+ // Unwrap parent div, remove events\r
+ return $el.unwrap().unbind(options.eventNamespace);\r
+ },\r
+ update: function () {\r
+ classClearStandard($div, options);\r
+ setFilename($el, $filename, options);\r
+ classUpdateDisabled($div, $el, options);\r
+ }\r
+ };\r
+ }\r
+ },\r
+ {\r
+ // Input fields (text)\r
+ match: function ($el) {\r
+ if ($el.is("input")) {\r
+ var t = (" " + attrOrProp($el, "type") + " ").toLowerCase(),\r
+ allowed = " color date datetime datetime-local email month number password search tel text time url week ";\r
+ return allowed.indexOf(t) >= 0;\r
+ }\r
+\r
+ return false;\r
+ },\r
+ apply: function ($el, options) {\r
+ var elType, $wrapper;\r
+\r
+ elType = attrOrProp($el, "type");\r
+ $el.addClass(options.inputClass);\r
+ $wrapper = wrapWithWrapperClass($el, options);\r
+ bindUi($el, $el, options);\r
+\r
+ if (options.inputAddTypeAsClass) {\r
+ $el.addClass(elType);\r
+ }\r
+\r
+ return {\r
+ remove: function () {\r
+ $el.removeClass(options.inputClass);\r
+\r
+ if (options.inputAddTypeAsClass) {\r
+ $el.removeClass(elType);\r
+ }\r
+\r
+ if ($wrapper) {\r
+ $el.unwrap();\r
+ }\r
+ },\r
+ update: returnFalse\r
+ };\r
+ }\r
+ },\r
+ {\r
+ // Radio buttons\r
+ match: function ($el) {\r
+ return $el.is(":radio");\r
+ },\r
+ apply: function ($el, options) {\r
+ var ds, $div, $span;\r
+ ds = divSpan($el, options, {\r
+ divClass: options.radioClass\r
+ });\r
+ $div = ds.div;\r
+ $span = ds.span;\r
+\r
+ // Add classes for focus, handle active, checked\r
+ bindUi($el, $div, options);\r
+ bindMany($el, options, {\r
+ "click touchend": function () {\r
+ // Find all radios with the same name, then update\r
+ // them with $.uniform.update() so the right\r
+ // per-element options are used\r
+ $.uniform.update($(':radio[name="' + attrOrProp($el, "name") + '"]'));\r
+ }\r
+ });\r
+ classUpdateChecked($span, $el, options);\r
+ return {\r
+ remove: unwrapUnwrapUnbindFunction($el, options),\r
+ update: function () {\r
+ classClearStandard($div, options);\r
+ classUpdateChecked($span, $el, options);\r
+ classUpdateDisabled($div, $el, options);\r
+ }\r
+ };\r
+ }\r
+ },\r
+ {\r
+ // Select lists, but do not style multiselects here\r
+ match: function ($el) {\r
+ if ($el.is("select") && !isMultiselect($el)) {\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ },\r
+ apply: function ($el, options) {\r
+ var ds, $div, $span, origElemWidth;\r
+\r
+ if (options.selectAutoWidth) {\r
+ sizingInvisible($el, function () {\r
+ origElemWidth = $el.width();\r
+ });\r
+ }\r
+\r
+ ds = divSpan($el, options, {\r
+ divClass: options.selectClass,\r
+ spanHtml: ($el.find(":selected:first") || $el.find("option:first")).html(),\r
+ spanWrap: "before"\r
+ });\r
+ $div = ds.div;\r
+ $span = ds.span;\r
+\r
+ if (options.selectAutoWidth) {\r
+ // Use the width of the select and adjust the\r
+ // span and div accordingly\r
+ sizingInvisible($el, function () {\r
+ // Force "display: block" - related to bug #287\r
+ swap($([ $span[0], $div[0] ]), {\r
+ display: "block"\r
+ }, function () {\r
+ var spanPad;\r
+ spanPad = $span.outerWidth() - $span.width();\r
+ $div.width(origElemWidth + spanPad);\r
+ $span.width(origElemWidth);\r
+ });\r
+ });\r
+ } else {\r
+ // Force the select to fill the size of the div\r
+ $div.addClass('fixedWidth');\r
+ }\r
+\r
+ // Take care of events\r
+ bindUi($el, $div, options);\r
+ bindMany($el, options, {\r
+ change: function () {\r
+ $span.html($el.find(":selected").html());\r
+ $div.removeClass(options.activeClass);\r
+ },\r
+ "click touchend": function () {\r
+ // IE7 and IE8 may not update the value right\r
+ // until after click event - issue #238\r
+ var selHtml = $el.find(":selected").html();\r
+\r
+ if ($span.html() !== selHtml) {\r
+ // Change was detected\r
+ // Fire the change event on the select tag\r
+ $el.trigger('change');\r
+ }\r
+ },\r
+ keyup: function () {\r
+ $span.html($el.find(":selected").html());\r
+ }\r
+ });\r
+ noSelect($span, options);\r
+ return {\r
+ remove: function () {\r
+ // Remove sibling span\r
+ $span.remove();\r
+\r
+ // Unwrap parent div\r
+ $el.unwrap().unbind(options.eventNamespace);\r
+ return $el;\r
+ },\r
+ update: function () {\r
+ if (options.selectAutoWidth) {\r
+ // Easier to remove and reapply formatting\r
+ $.uniform.restore($el);\r
+ $el.uniform(options);\r
+ } else {\r
+ classClearStandard($div, options);\r
+\r
+ // Reset current selected text\r
+ $span.html($el.find(":selected").html());\r
+ classUpdateDisabled($div, $el, options);\r
+ }\r
+ }\r
+ };\r
+ }\r
+ },\r
+ {\r
+ // Select lists - multiselect lists only\r
+ match: function ($el) {\r
+ if ($el.is("select") && isMultiselect($el)) {\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ },\r
+ apply: function ($el, options) {\r
+ var $wrapper;\r
+\r
+ $el.addClass(options.selectMultiClass);\r
+ $wrapper = wrapWithWrapperClass($el, options);\r
+ bindUi($el, $el, options);\r
+\r
+ return {\r
+ remove: function () {\r
+ $el.removeClass(options.selectMultiClass);\r
+\r
+ if ($wrapper) {\r
+ $el.unwrap();\r
+ }\r
+ },\r
+ update: returnFalse\r
+ };\r
+ }\r
+ },\r
+ {\r
+ // Textareas\r
+ match: function ($el) {\r
+ return $el.is("textarea");\r
+ },\r
+ apply: function ($el, options) {\r
+ var $wrapper;\r
+\r
+ $el.addClass(options.textareaClass);\r
+ $wrapper = wrapWithWrapperClass($el, options);\r
+ bindUi($el, $el, options);\r
+\r
+ return {\r
+ remove: function () {\r
+ $el.removeClass(options.textareaClass);\r
+\r
+ if ($wrapper) {\r
+ $el.unwrap();\r
+ }\r
+ },\r
+ update: returnFalse\r
+ };\r
+ }\r
+ }\r
+ ];\r
+\r
+ // IE6 can't be styled - can't set opacity on select\r
+ if (isMsie() && !isMsieSevenOrNewer()) {\r
+ allowStyling = false;\r
+ }\r
+\r
+ $.uniform = {\r
+ // Default options that can be overridden globally or when uniformed\r
+ // globally: $.uniform.defaults.fileButtonHtml = "Pick A File";\r
+ // on uniform: $('input').uniform({fileButtonHtml: "Pick a File"});\r
+ defaults: {\r
+ activeClass: "active",\r
+ autoHide: true,\r
+ buttonClass: "button",\r
+ checkboxClass: "checker",\r
+ checkedClass: "checked",\r
+ disabledClass: "disabled",\r
+ eventNamespace: ".uniform",\r
+ fileButtonClass: "action",\r
+ fileButtonHtml: "Choose File",\r
+ fileClass: "uploader",\r
+ fileDefaultHtml: "No file selected",\r
+ filenameClass: "filename",\r
+ focusClass: "focus",\r
+ hoverClass: "hover",\r
+ idPrefix: "uniform",\r
+ inputAddTypeAsClass: true,\r
+ inputClass: "uniform-input",\r
+ radioClass: "radio",\r
+ resetDefaultHtml: "Reset",\r
+ resetSelector: false, // We'll use our own function when you don't specify one\r
+ selectAutoWidth: true,\r
+ selectClass: "selector",\r
+ selectMultiClass: "uniform-multiselect",\r
+ submitDefaultHtml: "Submit", // Only text allowed\r
+ textareaClass: "uniform",\r
+ useID: true,\r
+ wrapperClass: null\r
+ },\r
+\r
+ // All uniformed elements - DOM objects\r
+ elements: []\r
+ };\r
+\r
+ $.fn.uniform = function (options) {\r
+ var el = this;\r
+ options = $.extend({}, $.uniform.defaults, options);\r
+\r
+ // If we are in high contrast mode, do not allow styling\r
+ if (!highContrastTest) {\r
+ highContrastTest = true;\r
+\r
+ if (highContrast()) {\r
+ allowStyling = false;\r
+ }\r
+ }\r
+\r
+ // Only uniform on browsers that work\r
+ if (!allowStyling) {\r
+ return this;\r
+ }\r
+\r
+ // Code for specifying a reset button\r
+ if (options.resetSelector) {\r
+ $(options.resetSelector).mouseup(function () {\r
+ window.setTimeout(function () {\r
+ $.uniform.update(el);\r
+ }, 10);\r
+ });\r
+ }\r
+\r
+ return this.each(function () {\r
+ var $el = $(this), i, handler, callbacks;\r
+\r
+ // Avoid uniforming elements already uniformed - just update\r
+ if ($el.data("uniformed")) {\r
+ $.uniform.update($el);\r
+ return;\r
+ }\r
+\r
+ // See if we have any handler for this type of element\r
+ for (i = 0; i < uniformHandlers.length; i = i + 1) {\r
+ handler = uniformHandlers[i];\r
+\r
+ if (handler.match($el, options)) {\r
+ callbacks = handler.apply($el, options);\r
+ $el.data("uniformed", callbacks);\r
+\r
+ // Store element in our global array\r
+ $.uniform.elements.push($el.get(0));\r
+ return;\r
+ }\r
+ }\r
+\r
+ // Could not style this element\r
+ });\r
+ };\r
+\r
+ $.uniform.restore = $.fn.uniform.restore = function (elem) {\r
+ if (elem === undef) {\r
+ elem = $.uniform.elements;\r
+ }\r
+\r
+ $(elem).each(function () {\r
+ var $el = $(this), index, elementData;\r
+ elementData = $el.data("uniformed");\r
+\r
+ // Skip elements that are not uniformed\r
+ if (!elementData) {\r
+ return;\r
+ }\r
+\r
+ // Unbind events, remove additional markup that was added\r
+ elementData.remove();\r
+\r
+ // Remove item from list of uniformed elements\r
+ index = $.inArray(this, $.uniform.elements);\r
+\r
+ if (index >= 0) {\r
+ $.uniform.elements.splice(index, 1);\r
+ }\r
+\r
+ $el.removeData("uniformed");\r
+ });\r
+ };\r
+\r
+ $.uniform.update = $.fn.uniform.update = function (elem) {\r
+ if (elem === undef) {\r
+ elem = $.uniform.elements;\r
+ }\r
+\r
+ $(elem).each(function () {\r
+ var $el = $(this), elementData;\r
+ elementData = $el.data("uniformed");\r
+\r
+ // Skip elements that are not uniformed\r
+ if (!elementData) {\r
+ return;\r
+ }\r
+\r
+ elementData.update($el, elementData.options);\r
+ });\r
+ };\r
+}(jQuery));\r