button.js (9975B)
1 /*! 2 * jQuery UI Button 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: Button 11 //>>group: Widgets 12 //>>description: Enhances a form with themeable buttons. 13 //>>docs: http://api.jqueryui.com/button/ 14 //>>demos: http://jqueryui.com/button/ 15 //>>css.structure: ../../themes/base/core.css 16 //>>css.structure: ../../themes/base/button.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 26 // These are only for backcompat 27 // TODO: Remove after 1.12 28 "./controlgroup", 29 "./checkboxradio", 30 31 "./core" 32 ], factory ); 33 } else { 34 35 // Browser globals 36 factory( jQuery ); 37 } 38 }( function( $ ) { 39 40 $.widget( "ui.button", { 41 version: "1.12.1", 42 defaultElement: "<button>", 43 options: { 44 classes: { 45 "ui-button": "ui-corner-all" 46 }, 47 disabled: null, 48 icon: null, 49 iconPosition: "beginning", 50 label: null, 51 showLabel: true 52 }, 53 54 _getCreateOptions: function() { 55 var disabled, 56 57 // This is to support cases like in jQuery Mobile where the base widget does have 58 // an implementation of _getCreateOptions 59 options = this._super() || {}; 60 61 this.isInput = this.element.is( "input" ); 62 63 disabled = this.element[ 0 ].disabled; 64 if ( disabled != null ) { 65 options.disabled = disabled; 66 } 67 68 this.originalLabel = this.isInput ? this.element.val() : this.element.html(); 69 if ( this.originalLabel ) { 70 options.label = this.originalLabel; 71 } 72 73 return options; 74 }, 75 76 _create: function() { 77 if ( !this.option.showLabel & !this.options.icon ) { 78 this.options.showLabel = true; 79 } 80 81 // We have to check the option again here even though we did in _getCreateOptions, 82 // because null may have been passed on init which would override what was set in 83 // _getCreateOptions 84 if ( this.options.disabled == null ) { 85 this.options.disabled = this.element[ 0 ].disabled || false; 86 } 87 88 this.hasTitle = !!this.element.attr( "title" ); 89 90 // Check to see if the label needs to be set or if its already correct 91 if ( this.options.label && this.options.label !== this.originalLabel ) { 92 if ( this.isInput ) { 93 this.element.val( this.options.label ); 94 } else { 95 this.element.html( this.options.label ); 96 } 97 } 98 this._addClass( "ui-button", "ui-widget" ); 99 this._setOption( "disabled", this.options.disabled ); 100 this._enhance(); 101 102 if ( this.element.is( "a" ) ) { 103 this._on( { 104 "keyup": function( event ) { 105 if ( event.keyCode === $.ui.keyCode.SPACE ) { 106 event.preventDefault(); 107 108 // Support: PhantomJS <= 1.9, IE 8 Only 109 // If a native click is available use it so we actually cause navigation 110 // otherwise just trigger a click event 111 if ( this.element[ 0 ].click ) { 112 this.element[ 0 ].click(); 113 } else { 114 this.element.trigger( "click" ); 115 } 116 } 117 } 118 } ); 119 } 120 }, 121 122 _enhance: function() { 123 if ( !this.element.is( "button" ) ) { 124 this.element.attr( "role", "button" ); 125 } 126 127 if ( this.options.icon ) { 128 this._updateIcon( "icon", this.options.icon ); 129 this._updateTooltip(); 130 } 131 }, 132 133 _updateTooltip: function() { 134 this.title = this.element.attr( "title" ); 135 136 if ( !this.options.showLabel && !this.title ) { 137 this.element.attr( "title", this.options.label ); 138 } 139 }, 140 141 _updateIcon: function( option, value ) { 142 var icon = option !== "iconPosition", 143 position = icon ? this.options.iconPosition : value, 144 displayBlock = position === "top" || position === "bottom"; 145 146 // Create icon 147 if ( !this.icon ) { 148 this.icon = $( "<span>" ); 149 150 this._addClass( this.icon, "ui-button-icon", "ui-icon" ); 151 152 if ( !this.options.showLabel ) { 153 this._addClass( "ui-button-icon-only" ); 154 } 155 } else if ( icon ) { 156 157 // If we are updating the icon remove the old icon class 158 this._removeClass( this.icon, null, this.options.icon ); 159 } 160 161 // If we are updating the icon add the new icon class 162 if ( icon ) { 163 this._addClass( this.icon, null, value ); 164 } 165 166 this._attachIcon( position ); 167 168 // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove 169 // the iconSpace if there is one. 170 if ( displayBlock ) { 171 this._addClass( this.icon, null, "ui-widget-icon-block" ); 172 if ( this.iconSpace ) { 173 this.iconSpace.remove(); 174 } 175 } else { 176 177 // Position is beginning or end so remove the ui-widget-icon-block class and add the 178 // space if it does not exist 179 if ( !this.iconSpace ) { 180 this.iconSpace = $( "<span> </span>" ); 181 this._addClass( this.iconSpace, "ui-button-icon-space" ); 182 } 183 this._removeClass( this.icon, null, "ui-wiget-icon-block" ); 184 this._attachIconSpace( position ); 185 } 186 }, 187 188 _destroy: function() { 189 this.element.removeAttr( "role" ); 190 191 if ( this.icon ) { 192 this.icon.remove(); 193 } 194 if ( this.iconSpace ) { 195 this.iconSpace.remove(); 196 } 197 if ( !this.hasTitle ) { 198 this.element.removeAttr( "title" ); 199 } 200 }, 201 202 _attachIconSpace: function( iconPosition ) { 203 this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace ); 204 }, 205 206 _attachIcon: function( iconPosition ) { 207 this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon ); 208 }, 209 210 _setOptions: function( options ) { 211 var newShowLabel = options.showLabel === undefined ? 212 this.options.showLabel : 213 options.showLabel, 214 newIcon = options.icon === undefined ? this.options.icon : options.icon; 215 216 if ( !newShowLabel && !newIcon ) { 217 options.showLabel = true; 218 } 219 this._super( options ); 220 }, 221 222 _setOption: function( key, value ) { 223 if ( key === "icon" ) { 224 if ( value ) { 225 this._updateIcon( key, value ); 226 } else if ( this.icon ) { 227 this.icon.remove(); 228 if ( this.iconSpace ) { 229 this.iconSpace.remove(); 230 } 231 } 232 } 233 234 if ( key === "iconPosition" ) { 235 this._updateIcon( key, value ); 236 } 237 238 // Make sure we can't end up with a button that has neither text nor icon 239 if ( key === "showLabel" ) { 240 this._toggleClass( "ui-button-icon-only", null, !value ); 241 this._updateTooltip(); 242 } 243 244 if ( key === "label" ) { 245 if ( this.isInput ) { 246 this.element.val( value ); 247 } else { 248 249 // If there is an icon, append it, else nothing then append the value 250 // this avoids removal of the icon when setting label text 251 this.element.html( value ); 252 if ( this.icon ) { 253 this._attachIcon( this.options.iconPosition ); 254 this._attachIconSpace( this.options.iconPosition ); 255 } 256 } 257 } 258 259 this._super( key, value ); 260 261 if ( key === "disabled" ) { 262 this._toggleClass( null, "ui-state-disabled", value ); 263 this.element[ 0 ].disabled = value; 264 if ( value ) { 265 this.element.blur(); 266 } 267 } 268 }, 269 270 refresh: function() { 271 272 // Make sure to only check disabled if its an element that supports this otherwise 273 // check for the disabled class to determine state 274 var isDisabled = this.element.is( "input, button" ) ? 275 this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" ); 276 277 if ( isDisabled !== this.options.disabled ) { 278 this._setOptions( { disabled: isDisabled } ); 279 } 280 281 this._updateTooltip(); 282 } 283 } ); 284 285 // DEPRECATED 286 if ( $.uiBackCompat !== false ) { 287 288 // Text and Icons options 289 $.widget( "ui.button", $.ui.button, { 290 options: { 291 text: true, 292 icons: { 293 primary: null, 294 secondary: null 295 } 296 }, 297 298 _create: function() { 299 if ( this.options.showLabel && !this.options.text ) { 300 this.options.showLabel = this.options.text; 301 } 302 if ( !this.options.showLabel && this.options.text ) { 303 this.options.text = this.options.showLabel; 304 } 305 if ( !this.options.icon && ( this.options.icons.primary || 306 this.options.icons.secondary ) ) { 307 if ( this.options.icons.primary ) { 308 this.options.icon = this.options.icons.primary; 309 } else { 310 this.options.icon = this.options.icons.secondary; 311 this.options.iconPosition = "end"; 312 } 313 } else if ( this.options.icon ) { 314 this.options.icons.primary = this.options.icon; 315 } 316 this._super(); 317 }, 318 319 _setOption: function( key, value ) { 320 if ( key === "text" ) { 321 this._super( "showLabel", value ); 322 return; 323 } 324 if ( key === "showLabel" ) { 325 this.options.text = value; 326 } 327 if ( key === "icon" ) { 328 this.options.icons.primary = value; 329 } 330 if ( key === "icons" ) { 331 if ( value.primary ) { 332 this._super( "icon", value.primary ); 333 this._super( "iconPosition", "beginning" ); 334 } else if ( value.secondary ) { 335 this._super( "icon", value.secondary ); 336 this._super( "iconPosition", "end" ); 337 } 338 } 339 this._superApply( arguments ); 340 } 341 } ); 342 343 $.fn.button = ( function( orig ) { 344 return function() { 345 if ( !this.length || ( this.length && this[ 0 ].tagName !== "INPUT" ) || 346 ( this.length && this[ 0 ].tagName === "INPUT" && ( 347 this.attr( "type" ) !== "checkbox" && this.attr( "type" ) !== "radio" 348 ) ) ) { 349 return orig.apply( this, arguments ); 350 } 351 if ( !$.ui.checkboxradio ) { 352 $.error( "Checkboxradio widget missing" ); 353 } 354 if ( arguments.length === 0 ) { 355 return this.checkboxradio( { 356 "icon": false 357 } ); 358 } 359 return this.checkboxradio.apply( this, arguments ); 360 }; 361 } )( $.fn.button ); 362 363 $.fn.buttonset = function() { 364 if ( !$.ui.controlgroup ) { 365 $.error( "Controlgroup widget missing" ); 366 } 367 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) { 368 return this.controlgroup.apply( this, 369 [ arguments[ 0 ], "items.button", arguments[ 2 ] ] ); 370 } 371 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) { 372 return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] ); 373 } 374 if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) { 375 arguments[ 0 ].items = { 376 button: arguments[ 0 ].items 377 }; 378 } 379 return this.controlgroup.apply( this, arguments ); 380 }; 381 } 382 383 return $.ui.button; 384 385 } ) );