Skip to content
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
2 changes: 1 addition & 1 deletion demos/controlgroup/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ <h1>Controlgroup</h1>
<input type="checkbox" name="insurance" id="insurance-v">
<label for="vertical-spinner" class="ui-controlgroup-label"># of cars</label>
<input id="vertical-spinner" class="ui-spinner-input">
<button>Book Now!</button>
<button id="book">Book Now!</button>
</div>
</fieldset>
</div>
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/controlgroup/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ define( [
"ui/widgets/controlgroup",
"ui/widgets/checkboxradio",
"ui/widgets/selectmenu",
"ui/widgets/button"
"ui/widgets/button",
"ui/widgets/spinner"
], function( common ) {

common.testWidget( "controlgroup", {
Expand Down
22 changes: 22 additions & 0 deletions tests/unit/controlgroup/controlgroup.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,28 @@
<option>Slow</option>
</select>
</div>
<select id="select-sanatize">
<option>Fast</option>
<option>Medium</option>
<option>Slow</option>
</select>
<div class="controlgroup-pre">
<select id="select-pre">
<option>Fast</option>
<option>Medium</option>
<option>Slow</option>
</select>
<button>Button with icon on the bottom</button>
</div>
<div class="controlgroup-refresh">
<select id="select-refresh">
<option>Fast</option>
<option>Medium</option>
<option>Slow</option>
</select>
<label class="ui-controlgroup-label">Label</label>
<button>Button with icon on the bottom</button>
</div>
</div>
</body>
</html>
28 changes: 27 additions & 1 deletion tests/unit/controlgroup/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ define( [
"ui/widgets/controlgroup",
"ui/widgets/checkboxradio",
"ui/widgets/selectmenu",
"ui/widgets/button"
"ui/widgets/button",
"ui/widgets/spinner"
], function( QUnit, $ ) {

QUnit.module( "Controlgroup: Core" );
Expand Down Expand Up @@ -74,4 +75,29 @@ QUnit.test( "selectmenu: controlgroupLabel", function( assert ) {
assert.hasClasses( label.find( "span" ), "ui-controlgroup-label-contents" );
} );

var assertSanatized = function( assert, initClasses, expectedClasses, message ) {
var selectmenu = $( "#select-sanatize" ).selectmenu( {
classes: {
"ui-selectmenu-button-open": initClasses
}
} ).selectmenu( "instance" );
var classes = {
"ui-selectmenu-button-open": "ui-corner-top"
};
var result = $.ui.controlgroup.prototype._resolveClassesValues( classes, selectmenu );
assert.deepEqual( result, {
"ui-selectmenu-button-open": expectedClasses + " ui-corner-top"
}, message );
};

QUnit.test( "_resolveClassesValues", function( assert ) {
assert.expect( 6 );
assertSanatized( assert, "bar ui-corner-bottom", "bar", "Single corner class removed end" );
assertSanatized( assert, "ui-corner-bottom bar", "bar", "Single corner class removed beginning" );
assertSanatized( assert, "bar ui-corner-bottom ui-corner-left", "bar", "Multiple corner classes removed end" );
assertSanatized( assert, "ui-corner-bottom ui-corner-left bar", "bar", "Multiple corner classes removed beginning" );
assertSanatized( assert, "bar ui-corner-bottom ui-corner-left foo", "bar foo", "Multiple corner class removed middle" );
assertSanatized( assert, "bar", "bar", "No corner classes" );
} );

} );
51 changes: 44 additions & 7 deletions tests/unit/controlgroup/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ define( [
"ui/widgets/controlgroup",
"ui/widgets/checkboxradio",
"ui/widgets/selectmenu",
"ui/widgets/button"
"ui/widgets/button",
"ui/widgets/spinner"
], function( QUnit, $ ) {

QUnit.module( "Controlgroup: methods" );
Expand All @@ -13,6 +14,7 @@ QUnit.test( "destroy", function( assert ) {
assert.expect( 1 );
assert.domEqual( ".controlgroup", function() {
$( ".controlgroup" ).controlgroup().controlgroup( "destroy" );
$( "#spinner" ).addClass( "ui-spinner-input" );
} );
} );

Expand All @@ -21,7 +23,7 @@ QUnit.test( "disable", function( assert ) {
var element = $( ".controlgroup" ).controlgroup().controlgroup( "disable" );
assert.lacksClasses( element, "ui-state-disabled",
"The widget does not get the disabled class, because we disable each child widget" );
assert.strictEqual( element.find( ".ui-state-disabled" ).length, 6,
assert.strictEqual( element.find( ".ui-state-disabled" ).length, 9,
"Child widgets are disabled" );
} );

Expand All @@ -37,7 +39,8 @@ QUnit.test( "enable", function( assert ) {
var tests = {
"checkboxradio": "<input type='checkbox'>",
"selectmenu": "<select><option>foo</option></select>",
"button": "<button>button text</button>"
"button": "<button>button text</button>",
"spinner": "<input class='ui-spinner-input'>"
},
orientations = {
"horizontal": [
Expand All @@ -63,7 +66,7 @@ $.each( tests, function( widget, html ) {
QUnit.test( "refresh: " + widget + ": " + name, function( assert ) {
assert.expect( 41 );

var i, control, currentClasses,
var i, control, label, currentClasses,
controls = [],
element = $( "<div>" ).controlgroup( {
direction: name
Expand Down Expand Up @@ -109,11 +112,11 @@ $.each( tests, function( widget, html ) {

// Add a label for each element and then append the element to the control group
for ( i = 0; i < 4; i++ ) {
control = $( html ).attr( "id", "id" + i )
.add( $( "<label>label text</label>" ).clone().attr( "for", "id" + i ) );
control = $( html ).attr( "id", "id" + i );
label = $( "<label>label text</label>" ).attr( "for", "id" + i );

controls.push( control );
element.append( control );
element.append( control, label );
}

// Refresh the controlgroup now that its populated
Expand All @@ -136,6 +139,9 @@ $.each( tests, function( widget, html ) {
iterateHidden();

// Disable the first control
if ( widget === "spinner" ) {
controls[ 0 ].spinner( "disable" );
}
controls[ 0 ].prop( "disabled", true );

element.controlgroup( "refresh" );
Expand All @@ -148,4 +154,35 @@ $.each( tests, function( widget, html ) {
} );
} );

QUnit.test( "Child Classes Option: init", function( assert ) {
assert.expect( 1 );
var selectmenu = $( "#select-pre" ).selectmenu( {
classes: {
"ui-selectmenu-button-closed": "test-class"
}
} );
$( ".controlgroup-pre" ).controlgroup();
assert.hasClasses( selectmenu.selectmenu( "widget" ), "test-class" );
} );

QUnit.test( "Child Classes Option: refresh", function( assert ) {
assert.expect( 1 );
var controlgroup = $( ".controlgroup-refresh" ).controlgroup();
var selectmenu = $( "#select-refresh" ).selectmenu( {
classes: {
"ui-selectmenu-button-closed": "test-class"
}
} );
controlgroup.controlgroup( "refresh" );
assert.hasClasses( selectmenu.selectmenu( "widget" ), "test-class" );
} );

QUnit.test( "Controlgroup Label: refresh", function( assert ) {
assert.expect( 1 );
var controlgroup = $( ".controlgroup-refresh" ).controlgroup();
controlgroup.controlgroup( "refresh" );
assert.strictEqual( controlgroup.find( ".ui-controlgroup-label-contents" ).length, 1,
"Controlgroup label does not re-wrap on refresh" );
} );

} );
5 changes: 3 additions & 2 deletions tests/unit/controlgroup/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ define( [
"ui/widgets/controlgroup",
"ui/widgets/checkboxradio",
"ui/widgets/selectmenu",
"ui/widgets/button"
"ui/widgets/button",
"ui/widgets/spinner"
], function( QUnit, $ ) {

QUnit.module( "Controlgroup: options" );
Expand All @@ -13,7 +14,7 @@ QUnit.test( "disabled", function( assert ) {
assert.expect( 4 );
var element = $( ".controlgroup" ).controlgroup().controlgroup( "option", "disabled", true );
assert.lacksClasses( element, "ui-state-disabled" );
assert.equal( element.find( ".ui-state-disabled" ).length, 6, "Child widgets are disabled" );
assert.equal( element.find( ".ui-state-disabled" ).length, 9, "Child widgets are disabled" );

element.controlgroup( "option", "disabled", false );
assert.lacksClasses( element, "ui-state-disabled" );
Expand Down
45 changes: 35 additions & 10 deletions ui/widgets/controlgroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
factory( jQuery );
}
}( function( $ ) {
var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;

return $.widget( "ui.controlgroup", {
version: "@VERSION",
Expand Down Expand Up @@ -86,7 +87,12 @@ return $.widget( "ui.controlgroup", {
if ( widget === "controlgroupLabel" ) {
labels = that.element.find( selector );
labels.each( function() {
$( this ).contents()
var element = $( this );

if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
return;
}
element.contents()
.wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
} );
that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
Expand All @@ -107,15 +113,25 @@ return $.widget( "ui.controlgroup", {

// Find instances of this widget inside controlgroup and init them
that.element
.find( selector )[ widget ]( options )
.find( selector )
.each( function() {
var element = $( this );
var instance = element[ widget ]( "instance" );

// If the button is the child of a spinner ignore it
if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this should really be more generic. Something along the lines of if the found widget is inside any other widget which is also inside this controlgroup, then ignore it. The problem is the "which is also inside any other widget" part. I'm not sure there's anything we can do about this right now, but I really don't like that we're writing logic around specific widgets.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree I just was not sure how else to do this unless we force enhancment within a controlgroup to be more explicit ala JQM data-role

return;
}
if ( instance ) {
options.classes = that._resolveClassesValues( options.classes, instance );
}
element[ widget ]( options );

// Store an instance of the controlgroup to be able to reference
// from the outermost element for changing options and refresh
var widgetElement = element[ widget ]( "widget" );
$.data( widgetElement[ 0 ], "ui-controlgroup-data",
element[ widget ]( "instance" ) );
instance ? instance : element[ widget ]( "instance" ) );

childWidgets.push( widgetElement[ 0 ] );
} );
Expand Down Expand Up @@ -149,7 +165,7 @@ return $.widget( "ui.controlgroup", {
classes: {}
};
result.classes[ key ] = {
"middle": null,
"middle": "",
"first": "ui-corner-" + ( direction ? "top" : "left" ),
"last": "ui-corner-" + ( direction ? "bottom" : "right" )
}[ position ];
Expand Down Expand Up @@ -180,22 +196,31 @@ return $.widget( "ui.controlgroup", {
width: direction ? "auto" : false,
classes: {
middle: {
"ui-selectmenu-button-open": null,
"ui-selectmenu-button-closed": null
"ui-selectmenu-button-open": "",
"ui-selectmenu-button-closed": ""
},
first: {
"ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
},
last: {
"ui-selectmenu-button-open": direction ? null : "ui-corner-tr",
"ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
}

}[ position ]
};
},

_resolveClassesValues: function( classes, instance ) {
$.each( classes, function( key ) {
var current = instance.options.classes[ key ] || "";
current = current.replace( controlgroupCornerRegex, "" ).trim();
classes[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
} );
return classes;
},

_setOption: function( key, value ) {
if ( key === "direction" ) {
this._removeClass( "ui-controlgroup-" + this.options.direction );
Expand Down Expand Up @@ -236,9 +261,9 @@ return $.widget( "ui.controlgroup", {
var instance = children[ value ]().data( "ui-controlgroup-data" );

if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
instance.element[ instance.widgetName ](
that[ "_" + instance.widgetName + "Options" ]( value )
);
var options = that[ "_" + instance.widgetName + "Options" ]( value );
options.classes = that._resolveClassesValues( options.classes, instance );
instance.element[ instance.widgetName ]( options );
} else {
that._updateCornerClass( children[ value ](), value );
}
Expand Down