1/* 2 * jQuery Custom Forms Plugin 1.0 3 * www.ZURB.com 4 * Copyright 2010, ZURB 5 * Free to use under the MIT license. 6 * http://www.opensource.org/licenses/mit-license.php 7*/ 8 9(function( $ ){ 10 'use strict'; 11 /** 12 * Helper object used to quickly adjust all hidden parent element's, display and visibility properties. 13 * This is currently used for the custom drop downs. When the dropdowns are contained within a reveal modal 14 * we cannot accurately determine the list-item elements width property, since the modal's display property is set 15 * to 'none'. 16 * 17 * This object will help us work around that problem. 18 * 19 * NOTE: This could also be plugin. 20 * 21 * @function hiddenFix 22 */ 23 var hiddenFix = function() { 24 25 return { 26 /** 27 * Sets all hidden parent elements and self to visibile. 28 * 29 * @method adjust 30 * @param {jQuery Object} $child 31 */ 32 33 // We'll use this to temporarily store style properties. 34 tmp : [], 35 36 // We'll use this to set hidden parent elements. 37 hidden : null, 38 39 adjust : function( $child ) { 40 // Internal reference. 41 var _self = this; 42 43 // Set all hidden parent elements, including this element. 44 _self.hidden = $child.parents().andSelf().filter( ":hidden" ); 45 46 // Loop through all hidden elements. 47 _self.hidden.each( function() { 48 49 // Cache the element. 50 var $elem = $( this ); 51 52 // Store the style attribute. 53 // Undefined if element doesn't have a style attribute. 54 _self.tmp.push( $elem.attr( 'style' ) ); 55 56 // Set the element's display property to block, 57 // but ensure it's visibility is hidden. 58 $elem.css( { 'visibility' : 'hidden', 'display' : 'block' } ); 59 }); 60 61 }, // end adjust 62 63 /** 64 * Resets the elements previous state. 65 * 66 * @method reset 67 */ 68 reset : function() { 69 // Internal reference. 70 var _self = this; 71 // Loop through our hidden element collection. 72 _self.hidden.each( function( i ) { 73 // Cache this element. 74 var $elem = $( this ), 75 _tmp = _self.tmp[ i ]; // Get the stored 'style' value for this element. 76 77 // If the stored value is undefined. 78 if( _tmp === undefined ) 79 // Remove the style attribute. 80 $elem.removeAttr( 'style' ); 81 else 82 // Otherwise, reset the element style attribute. 83 $elem.attr( 'style', _tmp ); 84 85 }); 86 // Reset the tmp array. 87 _self.tmp = []; 88 // Reset the hidden elements variable. 89 _self.hidden = null; 90 91 } // end reset 92 93 }; // end return 94 95 }; 96 97 jQuery.foundation = jQuery.foundation || {}; 98 jQuery.foundation.customForms = jQuery.foundation.customForms || {}; 99 100 $.foundation.customForms.appendCustomMarkup = function ( options ) { 101 102 var defaults = { 103 disable_class: "no-custom" 104 }; 105 106 options = $.extend( defaults, options ); 107 108 function appendCustomMarkup(idx, sel) { 109 var $this = $(sel).hide(), 110 type = $this.attr('type'), 111 $span = $this.next('span.custom.' + type); 112 113 if ($span.length === 0) { 114 $span = $('<span class="custom ' + type + '"></span>').insertAfter($this); 115 } 116 117 $span.toggleClass('checked', $this.is(':checked')); 118 $span.toggleClass('disabled', $this.is(':disabled')); 119 } 120 121 function appendCustomSelect(idx, sel) { 122 var hiddenFixObj = hiddenFix(); 123 // 124 // jQueryify the <select> element and cache it. 125 // 126 var $this = $( sel ), 127 // 128 // Find the custom drop down element. 129 // 130 $customSelect = $this.next( 'div.custom.dropdown' ), 131 // 132 // Find the custom select element within the custom drop down. 133 // 134 $customList = $customSelect.find( 'ul' ), 135 // 136 // Find the custom a.current element. 137 // 138 $selectCurrent = $customSelect.find( ".current" ), 139 // 140 // Find the custom a.selector element (the drop-down icon). 141 // 142 $selector = $customSelect.find( ".selector" ), 143 // 144 // Get the <options> from the <select> element. 145 // 146 $options = $this.find( 'option' ), 147 // 148 // Filter down the selected options 149 // 150 $selectedOption = $options.filter( ':selected' ), 151 // 152 // Initial max width. 153 // 154 maxWidth = 0, 155 // 156 // We'll use this variable to create the <li> elements for our custom select. 157 // 158 liHtml = '', 159 // 160 // We'll use this to cache the created <li> elements within our custom select. 161 // 162 $listItems 163 ; 164 var $currentSelect = false; 165 // 166 // Should we not create a custom list? 167 //
168 if ( $this.hasClass( options.disable_class ) ) return; 169 170 // 171 // Did we not create a custom select element yet? 172 // 173 if ( $customSelect.length === 0 ) { 174 // 175 // Let's create our custom select element! 176 // 177 178 // 179 // Determine what select size to use. 180 // 181 var customSelectSize = $this.hasClass( 'small' ) ? 'small' : 182 $this.hasClass( 'medium' ) ? 'medium' : 183 $this.hasClass( 'large' ) ? 'large' : 184 $this.hasClass( 'expand' ) ? 'expand' : '' 185 ; 186 // 187 // Build our custom list. 188 // 189 $customSelect = $('<div class="' + ['custom', 'dropdown', customSelectSize ].join( ' ' ) + '"><a href="#" class="selector"></a><ul /></div>'); 190 // 191 // Grab the selector element 192 // 193 $selector = $customSelect.find( ".selector" ); 194 // 195 // Grab the unordered list element from the custom list. 196 // 197 $customList = $customSelect.find( "ul" ); 198 // 199 // Build our <li> elements. 200 // 201 liHtml = $options.map( function() { return "<li>" + $( this ).html() + "</li>"; } ).get().join( '' ); 202 // 203 // Append our <li> elements to the custom list (<ul>). 204 // 205 $customList.append( liHtml ); 206 // 207 // Insert the the currently selected list item before all other elements. 208 // Then, find the element and assign it to $currentSelect. 209 // 210 211 $currentSelect = $customSelect.prepend( '<a href="#" class="current">' + $selectedOption.html() + '</a>' ).find( ".current" ); 212 // 213 // Add the custom select element after the <select> element. 214 // 215 $this.after( $customSelect ) 216 // 217 //then hide the <select> element. 218 // 219 .hide(); 220 221 } else { 222 // 223 // Create our list item <li> elements. 224 // 225 liHtml = $options.map( function() { return "<li>" + $( this ).html() + "</li>"; } ).get().join( '' ); 226 // 227 // Refresh the ul with options from the select in case the supplied markup doesn't match. 228 // Clear what's currently in the <ul> element. 229 // 230 $customList.html( '' ) 231 // 232 // Populate the list item <li> elements. 233 // 234 .append( liHtml ); 235 236 } // endif $customSelect.length === 0 237 238 // 239 // Determine whether or not the custom select element should be disabled. 240 // 241 $customSelect.toggleClass( 'disabled', $this.is( ':disabled' ) ); 242 // 243 // Cache our List item elements. 244 // 245 $listItems = $customList.find( 'li' ); 246 247 // 248 // Determine which elements to select in our custom list. 249 // 250 $options.each( function ( index ) { 251 252 if ( this.selected ) { 253 // 254 // Add the selected class to the current li element 255 // 256 $listItems.eq( index ).addClass( 'selected' ); 257 // 258 // Update the current element with the option value. 259 // 260 if ($currentSelect) { 261 $currentSelect.html( $( this ).html() ); 262 } 263 264 } 265 266 }); 267 268 // 269 // Update the custom <ul> list width property. 270 // 271 $customList.css( 'width', 'auto' ); 272 // 273 // Set the custom select width property. 274 // 275 $customSelect.css( 'width', 'auto' ); 276 277 // 278 // If we're not specifying a predetermined form size. 279 // 280 if ( !$customSelect.is( '.small, .medium, .large, .expand' ) ) { 281 282 // ------------------------------------------------------------------------------------ 283 // This is a work-around for when elements are contained within hidden parents. 284 // For example, when custom-form elements are inside of a hidden reveal modal. 285 // 286 // We need to display the current custom list element as well as hidden parent elements 287 // in order to properly calculate the list item element's width property. 288 // ------------------------------------------------------------------------------------- 289 290 // 291 // Show the drop down. 292 // This should ensure that the list item's width values are properly calculated. 293 // 294 $customSelect.addClass( 'open' ); 295 // 296 // Quickly, display all parent elements. 297 // This should help us calcualate the width of the list item's within the drop down. 298 // 299 hiddenFixObj.adjust( $customList ); 300 // 301 // Grab the largest list item width. 302 // 303 maxWidth = ( $listItems.outerWidth() > maxWidth ) ? $listItems.outerWidth() : maxWidth; 304 // 305 // Okay, now reset the parent elements. 306 // This will hide them again. 307 // 308 hiddenFixObj.reset(); 309 // 310 // Finally, hide the drop down. 311 // 312 $customSelect.removeClass( 'open' ); 313 // 314 // Set the custom list width. 315 // 316 $customSelect.width( maxWidth + 18); 317 // 318 // Set the custom list element (<ul />) width. 319 // 320 $customList.width( maxWidth + 16 ); 321 322 } // endif 323 324 } 325 326 $('form.custom input:radio[data-customforms!=disabled]').each(appendCustomMarkup); 327 $('form.custom input:checkbox[data-customforms!=disabled]').each(appendCustomMarkup); 328 $('form.custom select[data-customforms!=disabled]').each(appendCustomSelect); 329 }; 330 331 var refreshCustomSelect = function($select) { 332 var maxWidth = 0, 333 $customSelect = $select.next(); 334 $options = $select.find('option'); 335 $customSelect.find('ul').html(''); 336 337 $options.each(function () { 338 $li = $('<li>' + $(this).html() + '</li>'); 339 $customSelect.find('ul').append($li); 340 });
341 342 // re-populate 343 $options.each(function (index) { 344 if (this.selected) { 345 $customSelect.find('li').eq(index).addClass('selected'); 346 $customSelect.find('.current').html($(this).html()); 347 } 348 }); 349 350 // fix width 351 $customSelect.removeAttr('style') 352 .find('ul').removeAttr('style'); 353 $customSelect.find('li').each(function () { 354 $customSelect.addClass('open'); 355 if ($(this).outerWidth() > maxWidth) { 356 maxWidth = $(this).outerWidth(); 357 } 358 $customSelect.removeClass('open'); 359 }); 360 $customSelect.css('width', maxWidth + 18 + 'px'); 361 $customSelect.find('ul').css('width', maxWidth + 16 + 'px'); 362 363 }; 364 365 var toggleCheckbox = function($element) { 366 var $input = $element.prev(), 367 input = $input[0]; 368 369 if (false === $input.is(':disabled')) { 370 input.checked = ((input.checked) ? false : true); 371 $element.toggleClass('checked'); 372 373 $input.trigger('change'); 374 } 375 }; 376 377 var toggleRadio = function($element) { 378 var $input = $element.prev(), 379 $form = $input.closest('form.custom'), 380 input = $input[0]; 381 382 if (false === $input.is(':disabled')) { 383 $form.find('input:radio[name="' + $input.attr('name') + '"]').next().not($element).removeClass('checked'); 384 if ( !$element.hasClass('checked') ) { 385 $element.toggleClass('checked'); 386 } 387 input.checked = $element.hasClass('checked'); 388 389 $input.trigger('change'); 390 } 391 }; 392 393 $(document).on('click', 'form.custom span.custom.checkbox', function (event) { 394 event.preventDefault(); 395 event.stopPropagation(); 396 397 toggleCheckbox($(this)); 398 }); 399 400 $(document).on('click', 'form.custom span.custom.radio', function (event) { 401 event.preventDefault(); 402 event.stopPropagation(); 403 404 toggleRadio($(this)); 405 }); 406 407 $(document).on('change', 'form.custom select[data-customforms!=disabled]', function (event) { 408 refreshCustomSelect($(this)); 409 }); 410 411 $(document).on('click', 'form.custom label', function (event) { 412 var $associatedElement = $('#' + $(this).attr('for') + '[data-customforms!=disabled]'), 413 $customCheckbox, 414 $customRadio; 415 if ($associatedElement.length !== 0) { 416 if ($associatedElement.attr('type') === 'checkbox') { 417 event.preventDefault(); 418 $customCheckbox = $(this).find('span.custom.checkbox'); 419 //the checkbox might be outside after the label 420 if ($customCheckbox.length == 0) { 421 $customCheckbox = $(this).next('span.custom.checkbox'); 422 } 423 //the checkbox might be outside before the label 424 if ($customCheckbox.length == 0) { 425 $customCheckbox = $(this).prev('span.custom.checkbox'); 426 } 427 toggleCheckbox($customCheckbox); 428 } else if ($associatedElement.attr('type') === 'radio') { 429 event.preventDefault(); 430 $customRadio = $(this).find('span.custom.radio'); 431 //the radio might be outside after the label 432 if ($customRadio.length == 0) { 433 $customRadio = $(this).next('span.custom.radio'); 434 } 435 //the radio might be outside before the label 436 if ($customRadio.length == 0) { 437 $customRadio = $(this).prev('span.custom.radio'); 438 } 439 toggleRadio($customRadio); 440 } 441 } 442 }); 443 444 $(document).on('click', 'form.custom div.custom.dropdown a.current, form.custom div.custom.dropdown a.selector', function (event) { 445 var $this = $(this), 446 $dropdown = $this.closest('div.custom.dropdown'), 447 $select = $dropdown.prev(); 448 449 event.preventDefault(); 450 $('div.dropdown').removeClass('open'); 451 452 if (false === $select.is(':disabled')) { 453 $dropdown.toggleClass('open'); 454 455 if ($dropdown.hasClass('open')) { 456 $(document).bind('click.customdropdown', function (event) { 457 $dropdown.removeClass('open'); 458 $(document).unbind('.customdropdown'); 459 }); 460 } else { 461 $(document).unbind('.customdropdown'); 462 } 463 return false; 464 } 465 }); 466 467 $(document).on('click', 'form.custom div.custom.dropdown li', function (event) { 468 var $this = $(this), 469 $customDropdown = $this.closest('div.custom.dropdown'), 470 $select = $customDropdown.prev(), 471 selectedIndex = 0; 472 473 event.preventDefault(); 474 event.stopPropagation(); 475 $('div.dropdown').removeClass('open'); 476 477 $this 478 .closest('ul') 479 .find('li') 480 .removeClass('selected'); 481 $this.addClass('selected'); 482 483 $customDropdown 484 .removeClass('open') 485 .find('a.current') 486 .html($this.html()); 487 488 $this.closest('ul').find('li').each(function (index) { 489 if ($this[0] == this) { 490 selectedIndex = index; 491 } 492 493 });
494 $select[0].selectedIndex = selectedIndex; 495 496 $select.trigger('change'); 497 }); 498 499 500 $.fn.foundationCustomForms = $.foundation.customForms.appendCustomMarkup; 501 502})( jQuery );
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.