Created
August 21, 2012 23:45
-
-
Save davidpelaez/3420545 to your computer and use it in GitHub Desktop.
Modified version of customForms to affect markup when checkbox state changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* jQuery Custom Forms Plugin 1.0 | |
* www.ZURB.com | |
* Copyright 2010, ZURB | |
* Free to use under the MIT license. | |
* http://www.opensource.org/licenses/mit-license.php | |
*/ | |
(function( $ ){ | |
/** | |
* Helper object used to quickly adjust all hidden parent element's, display and visibility properties. | |
* This is currently used for the custom drop downs. When the dropdowns are contained within a reveal modal | |
* we cannot accurately determine the list-item elements width property, since the modal's display property is set | |
* to 'none'. | |
* | |
* This object will help us work around that problem. | |
* | |
* NOTE: This could also be plugin. | |
* | |
* @function hiddenFix | |
*/ | |
var hiddenFix = function() { | |
return { | |
/** | |
* Sets all hidden parent elements and self to visibile. | |
* | |
* @method adjust | |
* @param {jQuery Object} $child | |
*/ | |
// We'll use this to temporarily store style properties. | |
tmp : [], | |
// We'll use this to set hidden parent elements. | |
hidden : null, | |
adjust : function( $child ) { | |
// Internal reference. | |
var _self = this; | |
// Set all hidden parent elements, including this element. | |
_self.hidden = $child.parents().andSelf().filter( ":hidden" ); | |
// Loop through all hidden elements. | |
_self.hidden.each( function() { | |
// Cache the element. | |
var $elem = $( this ); | |
// Store the style attribute. | |
// Undefined if element doesn't have a style attribute. | |
_self.tmp.push( $elem.attr( 'style' ) ); | |
// Set the element's display property to block, | |
// but ensure it's visibility is hidden. | |
$elem.css( { 'visibility' : 'hidden', 'display' : 'block' } ); | |
}); | |
}, // end adjust | |
/** | |
* Resets the elements previous state. | |
* | |
* @method reset | |
*/ | |
reset : function() { | |
// Internal reference. | |
var _self = this; | |
// Loop through our hidden element collection. | |
_self.hidden.each( function( i ) { | |
// Cache this element. | |
var $elem = $( this ), | |
_tmp = _self.tmp[ i ]; // Get the stored 'style' value for this element. | |
// If the stored value is undefined. | |
if( _tmp === undefined ) | |
// Remove the style attribute. | |
$elem.removeAttr( 'style' ); | |
else | |
// Otherwise, reset the element style attribute. | |
$elem.attr( 'style', _tmp ); | |
}); | |
// Reset the tmp array. | |
_self.tmp = []; | |
// Reset the hidden elements variable. | |
_self.hidden = null; | |
} // end reset | |
}; // end return | |
}; | |
jQuery.foundation = jQuery.foundation || {}; | |
jQuery.foundation.customForms = jQuery.foundation.customForms || {}; | |
$.foundation.customForms.appendCustomMarkup = function ( options ) { | |
var defaults = { | |
disable_class: "js-disable-custom" | |
}; | |
options = $.extend( defaults, options ); | |
function appendCustomMarkup(idx, sel) { | |
var $this = $(sel).hide(), | |
type = $this.attr('type'), | |
$span = $this.next('span.custom.' + type); | |
if ($span.length === 0) { | |
$span = $('<span class="custom ' + type + '"></span>').insertAfter($this); | |
} | |
$span.toggleClass('checked', $this.is(':checked')); | |
$span.toggleClass('disabled', $this.is(':disabled')); | |
} | |
function appendCustomSelect(idx, sel) { | |
var hiddenFixObj = hiddenFix(); | |
// | |
// jQueryify the <select> element and cache it. | |
// | |
var $this = $( sel ), | |
// | |
// Find the custom drop down element. | |
// | |
$customSelect = $this.next( 'div.custom.dropdown' ), | |
// | |
// Find the custom select element within the custom drop down. | |
// | |
$customList = $customSelect.find( 'ul' ), | |
// | |
// Find the custom a.current element. | |
// | |
$selectCurrent = $customSelect.find( ".current" ), | |
// | |
// Find the custom a.selector element (the drop-down icon). | |
// | |
$selector = $customSelect.find( ".selector" ), | |
// | |
// Get the <options> from the <select> element. | |
// | |
$options = $this.find( 'option' ), | |
// | |
// Filter down the selected options | |
// | |
$selectedOption = $options.filter( ':selected' ), | |
// | |
// Initial max width. | |
// | |
maxWidth = 0, | |
// | |
// We'll use this variable to create the <li> elements for our custom select. | |
// | |
liHtml = '', | |
// | |
// We'll use this to cache the created <li> elements within our custom select. | |
// | |
$listItems | |
; | |
var $currentSelect = false; | |
// | |
// Should we not create a custom list? | |
// | |
if ( $this.hasClass( 'no-custom' ) ) return; | |
// | |
// Did we not create a custom select element yet? | |
// | |
if ( $customSelect.length === 0 ) { | |
// | |
// Let's create our custom select element! | |
// | |
// | |
// Determine what select size to use. | |
// | |
var customSelectSize = $this.hasClass( 'small' ) ? 'small' : | |
$this.hasClass( 'medium' ) ? 'medium' : | |
$this.hasClass( 'large' ) ? 'large' : | |
$this.hasClass( 'expand' ) ? 'expand' : '' | |
; | |
// | |
// Build our custom list. | |
// | |
$customSelect = $('<div class="' + ['custom', 'dropdown', customSelectSize ].join( ' ' ) + '"><a href="#" class="selector"></a><ul /></div>"'); | |
// | |
// Grab the selector element | |
// | |
$selector = $customSelect.find( ".selector" ); | |
// | |
// Grab the unordered list element from the custom list. | |
// | |
$customList = $customSelect.find( "ul" ); | |
// | |
// Build our <li> elements. | |
// | |
liHtml = $options.map( function() { return "<li>" + $( this ).html() + "</li>"; } ).get().join( '' ); | |
// | |
// Append our <li> elements to the custom list (<ul>). | |
// | |
$customList.append( liHtml ); | |
// | |
// Insert the the currently selected list item before all other elements. | |
// Then, find the element and assign it to $currentSelect. | |
// | |
$currentSelect = $customSelect.prepend( '<a href="#" class="current">' + $selectedOption.html() + '</a>' ).find( ".current" ); | |
// | |
// Add the custom select element after the <select> element. | |
// | |
$this.after( $customSelect ) | |
// | |
//then hide the <select> element. | |
// | |
.hide(); | |
} else { | |
// | |
// Create our list item <li> elements. | |
// | |
liHtml = $options.map( function() { return "<li>" + $( this ).html() + "</li>"; } ).get().join( '' ); | |
// | |
// Refresh the ul with options from the select in case the supplied markup doesn't match. | |
// Clear what's currently in the <ul> element. | |
// | |
$customList.html( '' ) | |
// | |
// Populate the list item <li> elements. | |
// | |
.append( liHtml ); | |
} // endif $customSelect.length === 0 | |
// | |
// Determine whether or not the custom select element should be disabled. | |
// | |
$customSelect.toggleClass( 'disabled', $this.is( ':disabled' ) ); | |
// | |
// Cache our List item elements. | |
// | |
$listItems = $customList.find( 'li' ); | |
// | |
// Determine which elements to select in our custom list. | |
// | |
$options.each( function ( index ) { | |
if ( this.selected ) { | |
// | |
// Add the selected class to the current li element | |
// | |
$listItems.eq( index ).addClass( 'selected' ); | |
// | |
// Update the current element with the option value. | |
// | |
if ($currentSelect) { | |
$currentSelect.html( $( this ).html() ); | |
} | |
} | |
}); | |
// | |
// Update the custom <ul> list width property. | |
// | |
$customList.css( 'width', 'inherit' ); | |
// | |
// Set the custom select width property. | |
// | |
$customSelect.css( 'width', 'inherit' ); | |
// | |
// If we're not specifying a predetermined form size. | |
// | |
if ( !$customSelect.is( '.small, .medium, .large, .expand' ) ) { | |
// ------------------------------------------------------------------------------------ | |
// This is a work-around for when elements are contained within hidden parents. | |
// For example, when custom-form elements are inside of a hidden reveal modal. | |
// | |
// We need to display the current custom list element as well as hidden parent elements | |
// in order to properly calculate the list item element's width property. | |
// ------------------------------------------------------------------------------------- | |
// | |
// Show the drop down. | |
// This should ensure that the list item's width values are properly calculated. | |
// | |
$customSelect.addClass( 'open' ); | |
// | |
// Quickly, display all parent elements. | |
// This should help us calcualate the width of the list item's within the drop down. | |
// | |
hiddenFixObj.adjust( $customList ); | |
// | |
// Grab the largest list item width. | |
// | |
maxWidth = ( $listItems.outerWidth() > maxWidth ) ? $listItems.outerWidth() : maxWidth; | |
// | |
// Okay, now reset the parent elements. | |
// This will hide them again. | |
// | |
hiddenFixObj.reset(); | |
// | |
// Finally, hide the drop down. | |
// | |
$customSelect.removeClass( 'open' ); | |
// | |
// Set the custom list width. | |
// | |
$customSelect.width( maxWidth + 18); | |
// | |
// Set the custom list element (<ul />) width. | |
// | |
$customList.width( maxWidth + 16 ); | |
} // endif | |
} | |
$('form.custom input:radio[data-customforms!=disabled]').each(appendCustomMarkup); | |
$('form.custom input:checkbox[data-customforms!=disabled]').each(appendCustomMarkup); | |
$('form.custom select[data-customforms!=disabled]').each(appendCustomSelect); | |
}; | |
var refreshCustomSelect = function($select) { | |
var maxWidth = 0, | |
$customSelect = $select.next(); | |
$options = $select.find('option'); | |
$customSelect.find('ul').html(''); | |
$options.each(function () { | |
$li = $('<li>' + $(this).html() + '</li>'); | |
$customSelect.find('ul').append($li); | |
}); | |
// re-populate | |
$options.each(function (index) { | |
if (this.selected) { | |
$customSelect.find('li').eq(index).addClass('selected'); | |
$customSelect.find('.current').html($(this).html()); | |
} | |
}); | |
// fix width | |
$customSelect.removeAttr('style') | |
.find('ul').removeAttr('style'); | |
$customSelect.find('li').each(function () { | |
$customSelect.addClass('open'); | |
if ($(this).outerWidth() > maxWidth) { | |
maxWidth = $(this).outerWidth(); | |
} | |
$customSelect.removeClass('open'); | |
}); | |
$customSelect.css('width', maxWidth + 18 + 'px'); | |
$customSelect.find('ul').css('width', maxWidth + 16 + 'px'); | |
}; | |
var toggleCheckbox = function($element) { | |
var $input = $element.prev(), | |
input = $input[0]; | |
if (false === $input.is(':disabled')) { | |
input.checked = ((input.checked) ? false : true); | |
//Make sure that toggling a checkbox affects markup | |
if(input.checked){ | |
//Make sure the checked attribute is there | |
$input.attr('checked', 'checked'); | |
}else{ | |
//Delete the checked from the markup | |
$input.removeAttr('checked'); | |
} | |
$element.toggleClass('checked'); | |
$input.trigger('change'); | |
} | |
}; | |
var toggleRadio = function($element) { | |
var $input = $element.prev(), | |
input = $input[0]; | |
if (false === $input.is(':disabled')) { | |
$('input:radio[name="' + $input.attr('name') + '"]').next().not($element).removeClass('checked'); | |
$element.toggleClass('checked'); | |
input.checked = $element.hasClass('checked'); | |
$input.trigger('change'); | |
} | |
}; | |
$(document).on('click', 'form.custom span.custom.checkbox', function (event) { | |
event.preventDefault(); | |
event.stopPropagation(); | |
toggleCheckbox($(this)); | |
}); | |
$(document).on('click', 'form.custom span.custom.radio', function (event) { | |
event.preventDefault(); | |
event.stopPropagation(); | |
toggleRadio($(this)); | |
}); | |
$(document).on('change', 'form.custom select[data-customforms!=disabled]', function (event) { | |
refreshCustomSelect($(this)); | |
}); | |
$(document).on('click', 'form.custom label', function (event) { | |
var $associatedElement = $('#' + $(this).attr('for')), | |
$customCheckbox, | |
$customRadio; | |
if ($associatedElement.length !== 0) { | |
if ($associatedElement.attr('type') === 'checkbox') { | |
event.preventDefault(); | |
$customCheckbox = $(this).find('span.custom.checkbox'); | |
toggleCheckbox($customCheckbox); | |
} else if ($associatedElement.attr('type') === 'radio') { | |
event.preventDefault(); | |
$customRadio = $(this).find('span.custom.radio'); | |
toggleRadio($customRadio); | |
} | |
} | |
}); | |
$(document).on('click', 'form.custom div.custom.dropdown a.current, form.custom div.custom.dropdown a.selector', function (event) { | |
var $this = $(this), | |
$dropdown = $this.closest('div.custom.dropdown'), | |
$select = $dropdown.prev(); | |
event.preventDefault(); | |
$('div.dropdown').removeClass('open'); | |
if (false === $select.is(':disabled')) { | |
$dropdown.toggleClass('open'); | |
if ($dropdown.hasClass('open')) { | |
$(document).bind('click.customdropdown', function (event) { | |
$dropdown.removeClass('open'); | |
$(document).unbind('.customdropdown'); | |
}); | |
} else { | |
$(document).unbind('.customdropdown'); | |
} | |
return false; | |
} | |
}); | |
$(document).on('click', 'form.custom div.custom.dropdown li', function (event) { | |
var $this = $(this), | |
$customDropdown = $this.closest('div.custom.dropdown'), | |
$select = $customDropdown.prev(), | |
selectedIndex = 0; | |
event.preventDefault(); | |
event.stopPropagation(); | |
$('div.dropdown').removeClass('open'); | |
$this | |
.closest('ul') | |
.find('li') | |
.removeClass('selected'); | |
$this.addClass('selected'); | |
$customDropdown | |
.removeClass('open') | |
.find('a.current') | |
.html($this.html()); | |
$this.closest('ul').find('li').each(function (index) { | |
if ($this[0] == this) { | |
selectedIndex = index; | |
} | |
}); | |
$select[0].selectedIndex = selectedIndex; | |
$select.trigger('change'); | |
}); | |
$.fn.foundationCustomForms = $.foundation.customForms.appendCustomMarkup; | |
})( jQuery ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment