Skip to content

Button: Fix backcompat when called on collection of mixed elements #1808

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions tests/unit/button/deprecated.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@
<button id="button1">Button</button>
<a href="#" id="anchor-button">Anchor Button</a>

<div class="mixed">
<a href="#" id="mixed-anchor">Anchor</a>
<button id="mixed-button" disabled>Button</button>
<input type="button" value="Button" id="mixed-input">
<input type="checkbox" id="mixed-check" name="check"><label for="mixed-check">Check</label>
<input type="radio" id="mixed-radio" name="radio"><label for="mixed-radio">Radio</label>
</div>

</div>
</body>
</html>
18 changes: 18 additions & 0 deletions tests/unit/button/deprecated.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,22 @@ QUnit.test( "icon / icons options properly proxied", function( assert ) {
"Icons secondary option sets iconPosition option to end on init" );
} );

QUnit.test( "Calling button on a collection of mixed types works correctly", function( assert ) {
assert.expect( 5 );

var group = $( ".mixed" ).children();

group.button();

$.each( {
anchor: "button",
button: "button",
check: "checkboxradio",
input: "button",
radio: "checkboxradio"
}, function( type, widget ) {
assert.ok( $( "#mixed-" + type )[ widget ]( "instance" ), type + " is a " + widget );
} );
} );

} );
87 changes: 73 additions & 14 deletions ui/widgets/button.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,22 +342,81 @@ if ( $.uiBackCompat !== false ) {
} );

$.fn.button = ( function( orig ) {
return function() {
if ( !this.length || ( this.length && this[ 0 ].tagName !== "INPUT" ) ||
( this.length && this[ 0 ].tagName === "INPUT" && (
this.attr( "type" ) !== "checkbox" && this.attr( "type" ) !== "radio"
) ) ) {
return orig.apply( this, arguments );
}
if ( !$.ui.checkboxradio ) {
$.error( "Checkboxradio widget missing" );
}
if ( arguments.length === 0 ) {
return this.checkboxradio( {
"icon": false
return function( options ) {
var isMethodCall = typeof options === "string";
var args = Array.prototype.slice.call( arguments, 1 );
var returnValue = this;

if ( isMethodCall ) {

// If this is an empty collection, we need to have the instance method
// return undefined instead of the jQuery instance
if ( !this.length && options === "instance" ) {
returnValue = undefined;
} else {
this.each( function() {
var methodValue;
var type = $( this ).attr( "type" );
var name = type !== "checkbox" && type !== "radio" ?
"button" :
"checkboxradio";
var instance = $.data( this, "ui-" + name );

if ( options === "instance" ) {
returnValue = instance;
return false;
}

if ( !instance ) {
return $.error( "cannot call methods on button" +
" prior to initialization; " +
"attempted to call method '" + options + "'" );
}

if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
return $.error( "no such method '" + options + "' for button" +
" widget instance" );
}

methodValue = instance[ options ].apply( instance, args );

if ( methodValue !== instance && methodValue !== undefined ) {
returnValue = methodValue && methodValue.jquery ?
returnValue.pushStack( methodValue.get() ) :
methodValue;
return false;
}
} );
}
} else {

// Allow multiple hashes to be passed on init
if ( args.length ) {
options = $.widget.extend.apply( null, [ options ].concat( args ) );
}

this.each( function() {
var type = $( this ).attr( "type" );
var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
var instance = $.data( this, "ui-" + name );

if ( instance ) {
instance.option( options || {} );
if ( instance._init ) {
instance._init();
}
} else {
if ( name === "button" ) {
orig.call( $( this ), options );
return;
}

$( this ).checkboxradio( $.extend( { icon: false }, options ) );
}
} );
}
return this.checkboxradio.apply( this, arguments );

return returnValue;
};
} )( $.fn.button );

Expand Down