button.js ➔ ... ➔ $.widget(ꞌui.buttonꞌ)._setOption   F
last analyzed

Complexity

Conditions 12
Paths 240

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
nc 240
nop 2
dl 0
loc 47
rs 3.9752
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like button.js ➔ ... ➔ $.widget(ꞌui.buttonꞌ)._setOption often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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