Skip to content

Commit

Permalink
Button: Fix backcompat when called on collection of mixed elements
Browse files Browse the repository at this point in the history
Fixes #15109
Closes gh-1808
  • Loading branch information
arschmitz authored and scottgonzalez committed May 2, 2017
1 parent c866e45 commit abc9e7c
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 14 deletions.
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

0 comments on commit abc9e7c

Please sign in to comment.