controlgroup.js (8564B)
1 /*! 2 * jQuery UI Controlgroup 1.12.1 3 * http://jqueryui.com 4 * 5 * Copyright jQuery Foundation and other contributors 6 * Released under the MIT license. 7 * http://jquery.org/license 8 */ 9 10 //>>label: Controlgroup 11 //>>group: Widgets 12 //>>description: Visually groups form control widgets 13 //>>docs: http://api.jqueryui.com/controlgroup/ 14 //>>demos: http://jqueryui.com/controlgroup/ 15 //>>css.structure: ../../themes/base/core.css 16 //>>css.structure: ../../themes/base/controlgroup.css 17 //>>css.theme: ../../themes/base/theme.css 18 19 ( function( factory ) { 20 if ( typeof define === "function" && define.amd ) { 21 22 // AMD. Register as an anonymous module. 23 define( [ 24 "jquery", 25 "./core" 26 ], factory ); 27 } else { 28 29 // Browser globals 30 factory( jQuery ); 31 } 32 }( function( $ ) { 33 var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g; 34 35 return $.widget( "ui.controlgroup", { 36 version: "1.12.1", 37 defaultElement: "<div>", 38 options: { 39 direction: "horizontal", 40 disabled: null, 41 onlyVisible: true, 42 items: { 43 "button": "input[type=button], input[type=submit], input[type=reset], button, a", 44 "controlgroupLabel": ".ui-controlgroup-label", 45 "checkboxradio": "input[type='checkbox'], input[type='radio']", 46 "selectmenu": "select", 47 "spinner": ".ui-spinner-input" 48 } 49 }, 50 51 _create: function() { 52 this._enhance(); 53 }, 54 55 // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation 56 _enhance: function() { 57 this.element.attr( "role", "toolbar" ); 58 this.refresh(); 59 }, 60 61 _destroy: function() { 62 this._callChildMethod( "destroy" ); 63 this.childWidgets.removeData( "ui-controlgroup-data" ); 64 this.element.removeAttr( "role" ); 65 if ( this.options.items.controlgroupLabel ) { 66 this.element 67 .find( this.options.items.controlgroupLabel ) 68 .find( ".ui-controlgroup-label-contents" ) 69 .contents().unwrap(); 70 } 71 }, 72 73 _initWidgets: function() { 74 var that = this, 75 childWidgets = []; 76 77 // First we iterate over each of the items options 78 $.each( this.options.items, function( widget, selector ) { 79 var labels; 80 var options = {}; 81 82 // Make sure the widget has a selector set 83 if ( !selector ) { 84 return; 85 } 86 87 if ( widget === "controlgroupLabel" ) { 88 labels = that.element.find( selector ); 89 labels.each( function() { 90 var element = $( this ); 91 92 if ( element.children( ".ui-controlgroup-label-contents" ).length ) { 93 return; 94 } 95 element.contents() 96 .wrapAll( "<span class='ui-controlgroup-label-contents'></span>" ); 97 } ); 98 that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" ); 99 childWidgets = childWidgets.concat( labels.get() ); 100 return; 101 } 102 103 // Make sure the widget actually exists 104 if ( !$.fn[ widget ] ) { 105 return; 106 } 107 108 // We assume everything is in the middle to start because we can't determine 109 // first / last elements until all enhancments are done. 110 if ( that[ "_" + widget + "Options" ] ) { 111 options = that[ "_" + widget + "Options" ]( "middle" ); 112 } else { 113 options = { classes: {} }; 114 } 115 116 // Find instances of this widget inside controlgroup and init them 117 that.element 118 .find( selector ) 119 .each( function() { 120 var element = $( this ); 121 var instance = element[ widget ]( "instance" ); 122 123 // We need to clone the default options for this type of widget to avoid 124 // polluting the variable options which has a wider scope than a single widget. 125 var instanceOptions = $.widget.extend( {}, options ); 126 127 // If the button is the child of a spinner ignore it 128 // TODO: Find a more generic solution 129 if ( widget === "button" && element.parent( ".ui-spinner" ).length ) { 130 return; 131 } 132 133 // Create the widget if it doesn't exist 134 if ( !instance ) { 135 instance = element[ widget ]()[ widget ]( "instance" ); 136 } 137 if ( instance ) { 138 instanceOptions.classes = 139 that._resolveClassesValues( instanceOptions.classes, instance ); 140 } 141 element[ widget ]( instanceOptions ); 142 143 // Store an instance of the controlgroup to be able to reference 144 // from the outermost element for changing options and refresh 145 var widgetElement = element[ widget ]( "widget" ); 146 $.data( widgetElement[ 0 ], "ui-controlgroup-data", 147 instance ? instance : element[ widget ]( "instance" ) ); 148 149 childWidgets.push( widgetElement[ 0 ] ); 150 } ); 151 } ); 152 153 this.childWidgets = $( $.unique( childWidgets ) ); 154 this._addClass( this.childWidgets, "ui-controlgroup-item" ); 155 }, 156 157 _callChildMethod: function( method ) { 158 this.childWidgets.each( function() { 159 var element = $( this ), 160 data = element.data( "ui-controlgroup-data" ); 161 if ( data && data[ method ] ) { 162 data[ method ](); 163 } 164 } ); 165 }, 166 167 _updateCornerClass: function( element, position ) { 168 var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all"; 169 var add = this._buildSimpleOptions( position, "label" ).classes.label; 170 171 this._removeClass( element, null, remove ); 172 this._addClass( element, null, add ); 173 }, 174 175 _buildSimpleOptions: function( position, key ) { 176 var direction = this.options.direction === "vertical"; 177 var result = { 178 classes: {} 179 }; 180 result.classes[ key ] = { 181 "middle": "", 182 "first": "ui-corner-" + ( direction ? "top" : "left" ), 183 "last": "ui-corner-" + ( direction ? "bottom" : "right" ), 184 "only": "ui-corner-all" 185 }[ position ]; 186 187 return result; 188 }, 189 190 _spinnerOptions: function( position ) { 191 var options = this._buildSimpleOptions( position, "ui-spinner" ); 192 193 options.classes[ "ui-spinner-up" ] = ""; 194 options.classes[ "ui-spinner-down" ] = ""; 195 196 return options; 197 }, 198 199 _buttonOptions: function( position ) { 200 return this._buildSimpleOptions( position, "ui-button" ); 201 }, 202 203 _checkboxradioOptions: function( position ) { 204 return this._buildSimpleOptions( position, "ui-checkboxradio-label" ); 205 }, 206 207 _selectmenuOptions: function( position ) { 208 var direction = this.options.direction === "vertical"; 209 return { 210 width: direction ? "auto" : false, 211 classes: { 212 middle: { 213 "ui-selectmenu-button-open": "", 214 "ui-selectmenu-button-closed": "" 215 }, 216 first: { 217 "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ), 218 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" ) 219 }, 220 last: { 221 "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr", 222 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" ) 223 }, 224 only: { 225 "ui-selectmenu-button-open": "ui-corner-top", 226 "ui-selectmenu-button-closed": "ui-corner-all" 227 } 228 229 }[ position ] 230 }; 231 }, 232 233 _resolveClassesValues: function( classes, instance ) { 234 var result = {}; 235 $.each( classes, function( key ) { 236 var current = instance.options.classes[ key ] || ""; 237 current = $.trim( current.replace( controlgroupCornerRegex, "" ) ); 238 result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " ); 239 } ); 240 return result; 241 }, 242 243 _setOption: function( key, value ) { 244 if ( key === "direction" ) { 245 this._removeClass( "ui-controlgroup-" + this.options.direction ); 246 } 247 248 this._super( key, value ); 249 if ( key === "disabled" ) { 250 this._callChildMethod( value ? "disable" : "enable" ); 251 return; 252 } 253 254 this.refresh(); 255 }, 256 257 refresh: function() { 258 var children, 259 that = this; 260 261 this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction ); 262 263 if ( this.options.direction === "horizontal" ) { 264 this._addClass( null, "ui-helper-clearfix" ); 265 } 266 this._initWidgets(); 267 268 children = this.childWidgets; 269 270 // We filter here because we need to track all childWidgets not just the visible ones 271 if ( this.options.onlyVisible ) { 272 children = children.filter( ":visible" ); 273 } 274 275 if ( children.length ) { 276 277 // We do this last because we need to make sure all enhancment is done 278 // before determining first and last 279 $.each( [ "first", "last" ], function( index, value ) { 280 var instance = children[ value ]().data( "ui-controlgroup-data" ); 281 282 if ( instance && that[ "_" + instance.widgetName + "Options" ] ) { 283 var options = that[ "_" + instance.widgetName + "Options" ]( 284 children.length === 1 ? "only" : value 285 ); 286 options.classes = that._resolveClassesValues( options.classes, instance ); 287 instance.element[ instance.widgetName ]( options ); 288 } else { 289 that._updateCornerClass( children[ value ](), value ); 290 } 291 } ); 292 293 // Finally call the refresh method on each of the child widgets. 294 this._callChildMethod( "refresh" ); 295 } 296 } 297 } ); 298 } ) );