Skip to content

Commit abc9e7c

Browse files
arschmitzscottgonzalez
authored andcommitted
Button: Fix backcompat when called on collection of mixed elements
Fixes #15109 Closes jquerygh-1808
1 parent c866e45 commit abc9e7c

File tree

3 files changed

+99
-14
lines changed

3 files changed

+99
-14
lines changed

tests/unit/button/deprecated.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@
5656
<button id="button1">Button</button>
5757
<a href="#" id="anchor-button">Anchor Button</a>
5858

59+
<div class="mixed">
60+
<a href="#" id="mixed-anchor">Anchor</a>
61+
<button id="mixed-button" disabled>Button</button>
62+
<input type="button" value="Button" id="mixed-input">
63+
<input type="checkbox" id="mixed-check" name="check"><label for="mixed-check">Check</label>
64+
<input type="radio" id="mixed-radio" name="radio"><label for="mixed-radio">Radio</label>
65+
</div>
66+
5967
</div>
6068
</body>
6169
</html>

tests/unit/button/deprecated.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,22 @@ QUnit.test( "icon / icons options properly proxied", function( assert ) {
194194
"Icons secondary option sets iconPosition option to end on init" );
195195
} );
196196

197+
QUnit.test( "Calling button on a collection of mixed types works correctly", function( assert ) {
198+
assert.expect( 5 );
199+
200+
var group = $( ".mixed" ).children();
201+
202+
group.button();
203+
204+
$.each( {
205+
anchor: "button",
206+
button: "button",
207+
check: "checkboxradio",
208+
input: "button",
209+
radio: "checkboxradio"
210+
}, function( type, widget ) {
211+
assert.ok( $( "#mixed-" + type )[ widget ]( "instance" ), type + " is a " + widget );
212+
} );
213+
} );
214+
197215
} );

ui/widgets/button.js

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -342,22 +342,81 @@ if ( $.uiBackCompat !== false ) {
342342
} );
343343

344344
$.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
345+
return function( options ) {
346+
var isMethodCall = typeof options === "string";
347+
var args = Array.prototype.slice.call( arguments, 1 );
348+
var returnValue = this;
349+
350+
if ( isMethodCall ) {
351+
352+
// If this is an empty collection, we need to have the instance method
353+
// return undefined instead of the jQuery instance
354+
if ( !this.length && options === "instance" ) {
355+
returnValue = undefined;
356+
} else {
357+
this.each( function() {
358+
var methodValue;
359+
var type = $( this ).attr( "type" );
360+
var name = type !== "checkbox" && type !== "radio" ?
361+
"button" :
362+
"checkboxradio";
363+
var instance = $.data( this, "ui-" + name );
364+
365+
if ( options === "instance" ) {
366+
returnValue = instance;
367+
return false;
368+
}
369+
370+
if ( !instance ) {
371+
return $.error( "cannot call methods on button" +
372+
" prior to initialization; " +
373+
"attempted to call method '" + options + "'" );
374+
}
375+
376+
if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
377+
return $.error( "no such method '" + options + "' for button" +
378+
" widget instance" );
379+
}
380+
381+
methodValue = instance[ options ].apply( instance, args );
382+
383+
if ( methodValue !== instance && methodValue !== undefined ) {
384+
returnValue = methodValue && methodValue.jquery ?
385+
returnValue.pushStack( methodValue.get() ) :
386+
methodValue;
387+
return false;
388+
}
389+
} );
390+
}
391+
} else {
392+
393+
// Allow multiple hashes to be passed on init
394+
if ( args.length ) {
395+
options = $.widget.extend.apply( null, [ options ].concat( args ) );
396+
}
397+
398+
this.each( function() {
399+
var type = $( this ).attr( "type" );
400+
var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
401+
var instance = $.data( this, "ui-" + name );
402+
403+
if ( instance ) {
404+
instance.option( options || {} );
405+
if ( instance._init ) {
406+
instance._init();
407+
}
408+
} else {
409+
if ( name === "button" ) {
410+
orig.call( $( this ), options );
411+
return;
412+
}
413+
414+
$( this ).checkboxradio( $.extend( { icon: false }, options ) );
415+
}
358416
} );
359417
}
360-
return this.checkboxradio.apply( this, arguments );
418+
419+
return returnValue;
361420
};
362421
} )( $.fn.button );
363422

0 commit comments

Comments
 (0)