From 891a7d9c082e4fcf93f8427de7dda8dcc26e76e2 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Fri, 19 Oct 2012 15:38:56 -0500 Subject: [PATCH 01/73] Widget: add the _classes method. Fixes #7053 --- tests/unit/widget/widget_core.js | 18 ++++++++++++++++++ ui/widget.js | 13 +++++++++++++ 2 files changed, 31 insertions(+) diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index feafca9428c..49abaff24d1 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -607,6 +607,24 @@ test( ".option() - deep option setter", function() { div.testWidget( "option", "foo.qux.newOpt", "newVal" ); }); +test( "_classes", function(){ + expect( 3 ); + $.widget( "ui.testWidget", { + options: { + classes: { + "test": "class1 class2", + "test2": "class3" + } + }, + _create: function() { + equal( this._classes( "test" ), "test class1 class2" ); + equal( this._classes( "test2" ), "test2 class3" ); + equal( this._classes( "test test2" ), "test2 class3 test class1 class2" ); + } + }); + $( "
" ).testWidget(); +}); + test( ".enable()", function() { expect( 2 ); $.widget( "ui.testWidget", { diff --git a/ui/widget.js b/ui/widget.js index 41425b1a9d3..b421a1ed96b 100644 --- a/ui/widget.js +++ b/ui/widget.js @@ -383,6 +383,19 @@ $.Widget.prototype = { return this; }, + _classes: function( key ) { + var out = [], + parts = key.split( " " ), + i = parts.length; + + while ( i-- ) { + out.push( parts[ i ] ); + out.push( this.options.classes[ parts[ i ] ] ); + } + + return out.join( " " ); + }, + enable: function() { return this._setOptions({ disabled: false }); }, From 6a6446ba1df14acea298c5495eeadea0c1586431 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Fri, 19 Oct 2012 15:39:37 -0500 Subject: [PATCH 02/73] Tabs: use the _classes method. Fixes #7053 --- tests/unit/tabs/tabs_common.js | 10 +++++++ tests/unit/tabs/tabs_core.js | 35 +++++++++++++++++++---- tests/unit/tabs/tabs_methods.js | 16 +++++++++++ tests/unit/tabs/tabs_options.js | 9 +++++- ui/tabs.js | 49 ++++++++++++++++++++------------- 5 files changed, 94 insertions(+), 25 deletions(-) diff --git a/tests/unit/tabs/tabs_common.js b/tests/unit/tabs/tabs_common.js index a589515f806..743403e0630 100644 --- a/tests/unit/tabs/tabs_common.js +++ b/tests/unit/tabs/tabs_common.js @@ -1,6 +1,16 @@ TestHelpers.commonWidgetTests( "tabs", { defaults: { active: null, + classes: { + "ui-tabs": "ui-corner-all", + "ui-tabs-collapsible": null, + "ui-tabs-active": null, + "ui-tabs-nav": "ui-corner-all", + "ui-tab": "ui-corner-top", + "ui-tabs-anchor": null, + "ui-tabs-panel": "ui-corner-bottom", + "ui-tabs-loading": null + }, collapsible: false, disabled: false, event: "click", diff --git a/tests/unit/tabs/tabs_core.js b/tests/unit/tabs/tabs_core.js index 2d18a6f1ab7..dadbf1b8287 100644 --- a/tests/unit/tabs/tabs_core.js +++ b/tests/unit/tabs/tabs_core.js @@ -5,11 +5,32 @@ var state = TestHelpers.tabs.state; module( "tabs: core" ); test( "markup structure", function() { - expect( 3 ); - var element = $( "#tabs1" ).tabs(); + expect( 15 ); + var element = $( "#tabs1" ).tabs(), + ul = element.find( "ul.ui-tabs-nav" ), + tabs = ul.find( "li" ), + active = tabs.eq( 0 ); + ok( element.hasClass( "ui-tabs" ), "main element is .ui-tabs" ); - ok( element.find( "ul" ).hasClass( "ui-tabs-nav" ), "list item is .ui-tabs-nav" ); - equal( element.find( ".ui-tabs-panel" ).length, 3, + ok( element.hasClass( "ui-widget" ), "main element is .ui-widget" ); + ok( element.hasClass( "ui-widget-content" ), "main element is .ui-widget-content" ); + ok( element.hasClass( "ui-corner-all" ), "main element is .ui-corner-all" ); + ok( !element.hasClass( "ui-tabs-collapsible" ), "main element is not .ui-tabs-collapsible" ); + + ok( ul.hasClass( "ui-tabs-nav" ), "list is .ui-tabs-nav" ); + ok( ul.hasClass( "ui-widget-header" ), "list is .ui-widget-header" ); + ok( ul.hasClass( "ui-corner-all" ), "list is .ui-corner-all" ); + + ok( tabs.hasClass( "ui-tab" ), "list item is .ui-tab" ); + ok( tabs.hasClass( "ui-corner-top" ), "list item is .ui-corner-top" ); + ok( tabs.hasClass( "ui-state-default" ), "list item is .ui-state-default" ); + + ok( element.find( "a" ).hasClass( "ui-tabs-anchor" ), "link item is .ui-tabs-anchor" ); + + ok( active.hasClass( "ui-tabs-active" ), "active item is .ui-tabs-active" ); + ok( active.hasClass( "ui-state-active" ), "active item is .ui-state-active" ); + + equal( element.find( ".ui-tabs-panel.ui-widget-content.ui-corner-bottom" ).length, 3, ".ui-tabs-panel elements exist, correct number" ); }); @@ -130,17 +151,21 @@ test( "accessibility", function() { }); asyncTest( "accessibility - ajax", function() { - expect( 4 ); + expect( 6 ); var element = $( "#tabs2" ).tabs(), + tab = element.find( ".ui-tabs-nav li" ).eq( 3 ), panel = $( "#custom-id" ); equal( panel.attr( "aria-live" ), "polite", "remote panel has aria-live" ); equal( panel.attr( "aria-busy" ), null, "does not have aria-busy on init" ); element.tabs( "option", "active", 3 ); equal( panel.attr( "aria-busy" ), "true", "panel has aria-busy during load" ); + ok( tab.hasClass( "ui-tabs-loading" ), "tab is .ui-tabs-loading during load" ); + element.one( "tabsload", function() { setTimeout(function() { equal( panel.attr( "aria-busy" ), null, "panel does not have aria-busy after load" ); + ok( !tab.hasClass( "ui-tabs-loading" ), "tab is not .ui-tabs-loading after load" ); start(); }, 1 ); }); diff --git a/tests/unit/tabs/tabs_methods.js b/tests/unit/tabs/tabs_methods.js index a3d663f272d..c08e9c049fe 100644 --- a/tests/unit/tabs/tabs_methods.js +++ b/tests/unit/tabs/tabs_methods.js @@ -15,6 +15,22 @@ test( "destroy", function() { }); }); +asyncTest( "destroy - ajax", function() { + expect( 1 ); + domEqual( "#tabs2", function( done ) { + var element = $( "#tabs2" ).tabs({ + load: function() { + setTimeout(function() { + element.tabs( "destroy" ); + done(); + start(); + }); + } + }); + element.tabs( "option", "active", 2 ); + }); +}); + test( "enable", function() { expect( 8 ); diff --git a/tests/unit/tabs/tabs_options.js b/tests/unit/tabs/tabs_options.js index a9632481e8f..8d35eba9357 100644 --- a/tests/unit/tabs/tabs_options.js +++ b/tests/unit/tabs/tabs_options.js @@ -123,12 +123,13 @@ test( "{ collapsible: false }", function() { }); test( "{ collapsible: true }", function() { - expect( 6 ); + expect( 9 ); var element = $( "#tabs1" ).tabs({ active: 1, collapsible: true }); + ok( element.hasClass( "ui-tabs-collapsible" ), "main element is .ui-tabs-collapsible" ); element.tabs( "option", "active", false ); equal( element.tabs( "option", "active" ), false ); @@ -141,6 +142,12 @@ test( "{ collapsible: true }", function() { element.find( ".ui-state-active .ui-tabs-anchor" ).click(); equal( element.tabs( "option", "active" ), false ); state( element, 0, 0, 0 ); + + element.tabs( "option", "collapsible", false ); + ok( !element.hasClass( "ui-tabs-collapsible" ), "main element is not .ui-tabs-collapsible" ); + + element.tabs( "option", "collapsible", true ); + ok( element.hasClass( "ui-tabs-collapsible" ), "main element is .ui-tabs-collapsible" ); }); test( "disabled", function() { diff --git a/ui/tabs.js b/ui/tabs.js index c0b24e74374..9cad6a94851 100644 --- a/ui/tabs.js +++ b/ui/tabs.js @@ -29,6 +29,16 @@ return $.widget( "ui.tabs", { delay: 300, options: { active: null, + classes: { + "ui-tabs": "ui-corner-all", + "ui-tabs-collapsible": null, + "ui-tabs-active": null, + "ui-tabs-nav": "ui-corner-all", + "ui-tab": "ui-corner-top", + "ui-tabs-anchor": null, + "ui-tabs-panel": "ui-corner-bottom", + "ui-tabs-loading": null + }, collapsible: false, event: "click", heightStyle: "content", @@ -70,8 +80,8 @@ return $.widget( "ui.tabs", { this.running = false; this.element - .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) - .toggleClass( "ui-tabs-collapsible", options.collapsible ); + .addClass( this._classes( "ui-tabs" ) + " ui-widget ui-widget-content" ) + .toggleClass( this._classes( "ui-tabs-collapsible" ), options.collapsible ); this._processTabs(); options.active = this._initialActive(); @@ -278,7 +288,7 @@ return $.widget( "ui.tabs", { this._super( key, value); if ( key === "collapsible" ) { - this.element.toggleClass( "ui-tabs-collapsible", value ); + this.element.toggleClass( this._classes( "ui-tabs-collapsible" ), value ); // Setting collapsible: false while collapsed; open first panel if ( !value && this.options.active === false ) { this._activate( 0 ); @@ -354,7 +364,7 @@ return $.widget( "ui.tabs", { this.tabs.eq( 0 ).attr( "tabIndex", 0 ); } else { this.active - .addClass( "ui-tabs-active ui-state-active" ) + .addClass( this._classes( "ui-tabs-active" ) + " ui-state-active" ) .attr({ "aria-selected": "true", "aria-expanded": "true", @@ -375,7 +385,7 @@ return $.widget( "ui.tabs", { prevPanels = this.panels; this.tablist = this._getList() - .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) + .addClass( this._classes( "ui-tabs-nav" ) + " ui-helper-reset ui-helper-clearfix ui-widget-header" ) .attr( "role", "tablist" ) // Prevent users from focusing disabled tabs via click @@ -398,7 +408,7 @@ return $.widget( "ui.tabs", { }); this.tabs = this.tablist.find( "> li:has(a[href])" ) - .addClass( "ui-state-default ui-corner-top" ) + .addClass( this._classes( "ui-tab" ) + " ui-state-default" ) .attr({ role: "tab", tabIndex: -1 @@ -407,7 +417,7 @@ return $.widget( "ui.tabs", { this.anchors = this.tabs.map(function() { return $( "a", this )[ 0 ]; }) - .addClass( "ui-tabs-anchor" ) + .addClass( that._classes( "ui-tabs-anchor" ) ) .attr({ role: "presentation", tabIndex: -1 @@ -454,7 +464,7 @@ return $.widget( "ui.tabs", { }); this.panels - .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .addClass( this._classes( "ui-tabs-panel" ) + " ui-widget-content" ) .attr( "role", "tabpanel" ); // Avoid memory leaks (#10056) @@ -473,7 +483,7 @@ return $.widget( "ui.tabs", { _createPanel: function( id ) { return $( "
" ) .attr( "id", id ) - .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .addClass( this._classes( "ui-tabs-panel" ) + " ui-widget-content" ) .data( "ui-tabs-destroy", true ); }, @@ -621,7 +631,7 @@ return $.widget( "ui.tabs", { } function show() { - eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); + eventData.newTab.closest( "li" ).addClass( that._classes( "ui-tabs-active" ) + " ui-state-active" ); if ( toShow.length && that.options.show ) { that._show( toShow, that.options.show, complete ); @@ -634,11 +644,11 @@ return $.widget( "ui.tabs", { // start out by hiding, then showing, then completing if ( toHide.length && this.options.hide ) { this._hide( toHide, this.options.hide, function() { - eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + eventData.oldTab.closest( "li" ).removeClass( that._classes( "ui-tabs-active" ) + " ui-state-active" ); show(); }); } else { - eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + eventData.oldTab.closest( "li" ).removeClass( this._classes( "ui-tabs-active" ) + " ui-state-active" ); toHide.hide(); show(); } @@ -704,18 +714,19 @@ return $.widget( "ui.tabs", { }, _destroy: function() { + var that = this; if ( this.xhr ) { this.xhr.abort(); } - this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); + this.element.removeClass( this._classes( "ui-tabs ui-tabs-collapsible" ) + " ui-widget ui-widget-content" ); this.tablist - .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) + .removeClass( this._classes( "ui-tabs-nav" ) + " ui-helper-reset ui-helper-clearfix ui-widget-header" ) .removeAttr( "role" ); this.anchors - .removeClass( "ui-tabs-anchor" ) + .removeClass( this._classes( "ui-tabs-anchor" ) ) .removeAttr( "role" ) .removeAttr( "tabIndex" ) .removeUniqueId(); @@ -727,8 +738,8 @@ return $.widget( "ui.tabs", { $( this ).remove(); } else { $( this ) - .removeClass( "ui-state-default ui-state-active ui-state-disabled " + - "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) + .removeClass( that._classes( "ui-tabs-active ui-tab ui-tabs-panel" ) + + " ui-helper-reset ui-helper-clearfix ui-widget-content ui-state-default ui-state-active ui-state-disabled" ) .removeAttr( "tabIndex" ) .removeAttr( "aria-live" ) .removeAttr( "aria-busy" ) @@ -826,7 +837,7 @@ return $.widget( "ui.tabs", { // jQuery <1.8 returns false if the request is canceled in beforeSend, // but as of 1.8, $.ajax() always returns a jqXHR object. if ( this.xhr && this.xhr.statusText !== "canceled" ) { - tab.addClass( "ui-tabs-loading" ); + tab.addClass( this._classes( "ui-tabs-loading" ) ); panel.attr( "aria-busy", "true" ); this.xhr @@ -846,7 +857,7 @@ return $.widget( "ui.tabs", { that.panels.stop( false, true ); } - tab.removeClass( "ui-tabs-loading" ); + tab.removeClass( that._classes( "ui-tabs-loading" ) ); panel.removeAttr( "aria-busy" ); if ( jqXHR === that.xhr ) { From 07f52c131c57992f381704a24ed6a36e0a9cbbb7 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Tue, 23 Apr 2013 14:03:13 -0500 Subject: [PATCH 03/73] Dialog: use the _classes method. Deprecate dialogClass. Fixes #7053 --- tests/unit/dialog/dialog_common.js | 14 +++- tests/unit/dialog/dialog_common_deprecated.js | 56 ++++++++++++++ tests/unit/dialog/dialog_core.js | 35 +++++++++ tests/unit/dialog/dialog_deprecated.html | 68 ++++++++++++++++ tests/unit/dialog/dialog_deprecated.js | 31 ++++++++ tests/unit/dialog/dialog_methods.js | 10 ++- tests/unit/dialog/dialog_options.js | 20 ----- ui/dialog.js | 77 +++++++++++++------ 8 files changed, 265 insertions(+), 46 deletions(-) create mode 100644 tests/unit/dialog/dialog_common_deprecated.js create mode 100644 tests/unit/dialog/dialog_deprecated.html create mode 100644 tests/unit/dialog/dialog_deprecated.js diff --git a/tests/unit/dialog/dialog_common.js b/tests/unit/dialog/dialog_common.js index fc10fabaab6..fa53f302d47 100644 --- a/tests/unit/dialog/dialog_common.js +++ b/tests/unit/dialog/dialog_common.js @@ -3,10 +3,22 @@ TestHelpers.commonWidgetTests( "dialog", { appendTo: "body", autoOpen: true, buttons: [], + classes: { + "ui-dialog": "ui-corner-all", + "ui-dialog-content": null, + "ui-dialog-titlebar": "ui-corner-all", + "ui-dialog-titlebar-close": null, + "ui-dialog-title": null, + "ui-dialog-buttons": null, + "ui-dialog-buttonpane": null, + "ui-dialog-buttonset": null, + "ui-dialog-dragging": null, + "ui-dialog-resizing": null, + "ui-widget-overlay": null + }, closeOnEscape: true, closeText: "Close", disabled: false, - dialogClass: "", draggable: true, height: "auto", hide: null, diff --git a/tests/unit/dialog/dialog_common_deprecated.js b/tests/unit/dialog/dialog_common_deprecated.js new file mode 100644 index 00000000000..66ec7260a78 --- /dev/null +++ b/tests/unit/dialog/dialog_common_deprecated.js @@ -0,0 +1,56 @@ +TestHelpers.commonWidgetTests( "dialog", { + defaults: { + appendTo: "body", + autoOpen: true, + buttons: [], + classes: { + "ui-dialog": "ui-corner-all", + "ui-dialog-content": null, + "ui-dialog-titlebar": "ui-corner-all", + "ui-dialog-titlebar-close": null, + "ui-dialog-title": null, + "ui-dialog-buttons": null, + "ui-dialog-buttonpane": null, + "ui-dialog-buttonset": null, + "ui-dialog-dragging": null, + "ui-dialog-resizing": null, + "ui-widget-overlay": null + }, + closeOnEscape: true, + closeText: "close", + dialogClass: "", + disabled: false, + draggable: true, + height: "auto", + hide: null, + maxHeight: null, + maxWidth: null, + minHeight: 150, + minWidth: 150, + modal: false, + position: { + my: "center", + at: "center", + of: window, + collision: "fit", + using: $.ui.dialog.prototype.options.position.using + }, + resizable: true, + show: null, + title: null, + width: 300, + + // callbacks + beforeClose: null, + close: null, + create: null, + drag: null, + dragStart: null, + dragStop: null, + focus: null, + open: null, + resize: null, + resizeStart: null, + resizeStop: null + } +}); diff --git a/tests/unit/dialog/dialog_core.js b/tests/unit/dialog/dialog_core.js index d72fef7b5bf..94e22aef743 100644 --- a/tests/unit/dialog/dialog_core.js +++ b/tests/unit/dialog/dialog_core.js @@ -7,6 +7,41 @@ // TODO add teardown callback to remove dialogs module("dialog: core"); +test( "markup structure", function() { + expect( 15 ); + var element = $("
").dialog({ + buttons: [{ + text: "Ok", + click: $.noop + }] + }), + widget = element.dialog( "widget" ), + titlebar = widget.find( ".ui-dialog-titlebar" ), + close = titlebar.find( "button" ), + buttonpane = widget.find( ".ui-dialog-buttonpane" ); + + ok( widget.hasClass( "ui-dialog" ), "widget is .ui-dialog" ); + ok( widget.hasClass( "ui-widget" ), "widget is .ui-widget" ); + ok( widget.hasClass( "ui-widget-content" ), "widget is .ui-widget-content" ); + ok( widget.hasClass( "ui-corner-all" ), "widget is .ui-corner-all" ); + ok( widget.hasClass( "ui-dialog-buttons" ), "widget is .ui-dialog-buttons" ); + + ok( titlebar.hasClass( "ui-dialog-titlebar" ), "titlebar is .ui-dialog-titlebar" ); + ok( titlebar.hasClass( "ui-corner-all" ), "titlebar is .ui-corner-all" ); + ok( titlebar.hasClass( "ui-widget-header" ), "titlebar is .ui-widget-header" ); + ok( titlebar.find( ".ui-dialog-title" ).length, "title is .ui-dialog-title" ); + + ok( close.hasClass( "ui-dialog-titlebar-close" ), "close button is .ui-dialog-titlebar-close" ); + + ok( element.hasClass( "ui-dialog-content" ), "element is .ui-dialog-content" ); + ok( element.hasClass( "ui-widget-content" ), "element is .ui-widget-content" ); + + ok( buttonpane.hasClass( "ui-dialog-buttonpane" ), "buttonpane is .ui-dialog-buttonpane" ); + ok( buttonpane.hasClass( "ui-widget-content" ), "buttonpane is .ui-widget-content" ); + ok( buttonpane.find( ".ui-dialog-buttonset" ).length, "buttonset is .ui-dialog-buttonset" ); + +}); + test("title id", function() { expect(1); diff --git a/tests/unit/dialog/dialog_deprecated.html b/tests/unit/dialog/dialog_deprecated.html new file mode 100644 index 00000000000..4a404c79e03 --- /dev/null +++ b/tests/unit/dialog/dialog_deprecated.html @@ -0,0 +1,68 @@ + + + + + jQuery UI Dialog Test Suite + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
...
+
+ Please share some personal information + + +
+
+

Some more (optional) information

+ +
+
+
+
+
+ + diff --git a/tests/unit/dialog/dialog_deprecated.js b/tests/unit/dialog/dialog_deprecated.js new file mode 100644 index 00000000000..5e0093e05dc --- /dev/null +++ b/tests/unit/dialog/dialog_deprecated.js @@ -0,0 +1,31 @@ +/* + * dialog_deprecated.js + */ +(function( $ ) { + +module( "dialog (deprecated): options" ); + +test( "dialogClass", function() { + expect( 6 ); + + var element = $( "
" ).dialog(), + widget = element.dialog( "widget" ); + equal( widget.is( ".foo" ), false, "dialogClass not specified. class not added" ); + element.remove(); + + element = $( "
" ).dialog({ dialogClass: "foo" }); + widget = element.dialog( "widget" ); + equal( widget.is( ".foo" ), true, "dialogClass in init. foo class added"); + element.dialog( "option", "dialogClass", "foobar" ); + equal( widget.is( ".foo" ), false, "dialogClass changed, previous one was removed" ); + equal( widget.is( ".foobar" ), true, "dialogClass changed, new one was added" ); + element.remove(); + + element = $( "
" ).dialog({ dialogClass: "foo bar" }); + widget = element.dialog( "widget" ); + equal( widget.is( ".foo" ), true, "dialogClass in init, two classes. foo class added" ); + equal( widget.is( ".bar" ), true, "dialogClass in init, two classes. bar class added" ); + element.remove(); +}); + +})( jQuery ); diff --git a/tests/unit/dialog/dialog_methods.js b/tests/unit/dialog/dialog_methods.js index c449ad0d413..1cdeebd0411 100644 --- a/tests/unit/dialog/dialog_methods.js +++ b/tests/unit/dialog/dialog_methods.js @@ -34,7 +34,7 @@ test("init", function() { }); test("destroy", function() { - expect( 17 ); + expect( 18 ); var element, element2; @@ -49,6 +49,14 @@ test("destroy", function() { equal( dialog.parent()[ 0 ], $( "#qunit-fixture" )[ 0 ] ); equal( dialog.index(), 2 ); }); + domEqual( "#dialog2", function() { + $( "#dialog2" ).dialog({ + buttons: [{ + text: "Ok", + click: $.noop + }] + }).dialog( "destroy" ); + }, "Buttons"); // Ensure dimensions are restored (#8119) $( "#dialog1" ).show().css({ diff --git a/tests/unit/dialog/dialog_options.js b/tests/unit/dialog/dialog_options.js index 3e5444c67e2..77ca09703a7 100644 --- a/tests/unit/dialog/dialog_options.js +++ b/tests/unit/dialog/dialog_options.js @@ -224,26 +224,6 @@ test("closeText", function() { element.remove(); }); -test("dialogClass", function() { - expect( 6 ); - - var element = $("
").dialog(); - equal(element.dialog("widget").is(".foo"), false, "dialogClass not specified. foo class added"); - element.remove(); - - element = $("
").dialog({ dialogClass: "foo" }); - equal(element.dialog("widget").is(".foo"), true, "dialogClass in init. foo class added"); - element.dialog( "option", "dialogClass", "foobar" ); - equal( element.dialog("widget").is(".foo"), false, "dialogClass changed, previous one was removed" ); - equal( element.dialog("widget").is(".foobar"), true, "dialogClass changed, new one was added" ); - element.remove(); - - element = $("
").dialog({ dialogClass: "foo bar" }); - equal(element.dialog("widget").is(".foo"), true, "dialogClass in init, two classes. foo class added"); - equal(element.dialog("widget").is(".bar"), true, "dialogClass in init, two classes. bar class added"); - element.remove(); -}); - test("draggable", function() { expect(4); diff --git a/ui/dialog.js b/ui/dialog.js index 5561a96cde3..dc95ca7d064 100644 --- a/ui/dialog.js +++ b/ui/dialog.js @@ -29,15 +29,27 @@ } }(function( $ ) { -return $.widget( "ui.dialog", { +$.widget( "ui.dialog", { version: "@VERSION", options: { appendTo: "body", autoOpen: true, buttons: [], + classes: { + "ui-dialog": "ui-corner-all", + "ui-dialog-content": null, + "ui-dialog-titlebar": "ui-corner-all", + "ui-dialog-titlebar-close": null, + "ui-dialog-title": null, + "ui-dialog-buttons": null, + "ui-dialog-buttonpane": null, + "ui-dialog-buttonset": null, + "ui-dialog-dragging": null, + "ui-dialog-resizing": null, + "ui-widget-overlay": null + }, closeOnEscape: true, closeText: "Close", - dialogClass: "", draggable: true, hide: null, height: "auto", @@ -114,7 +126,7 @@ return $.widget( "ui.dialog", { this.element .show() .removeAttr( "title" ) - .addClass( "ui-dialog-content ui-widget-content" ) + .addClass( this._classes( "ui-dialog-content" ) + " ui-widget-content" ) .appendTo( this.uiDialog ); this._createTitlebar(); @@ -154,7 +166,7 @@ return $.widget( "ui.dialog", { this.element .removeUniqueId() - .removeClass( "ui-dialog-content ui-widget-content" ) + .removeClass( this._classes( "ui-dialog-content" ) + " ui-widget-content" ) .css( this.originalCss ) // Without detaching first, the following becomes really slow .detach(); @@ -327,8 +339,7 @@ return $.widget( "ui.dialog", { _createWrapper: function() { this.uiDialog = $("
") - .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " + - this.options.dialogClass ) + .addClass( this._classes( "ui-dialog" ) + " ui-widget ui-widget-content ui-front " ) .hide() .attr({ // Setting tabIndex makes the div focusable @@ -387,7 +398,7 @@ return $.widget( "ui.dialog", { var uiDialogTitle; this.uiDialogTitlebar = $( "
" ) - .addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" ) + .addClass( this._classes( "ui-dialog-titlebar") + " ui-widget-header ui-helper-clearfix" ) .prependTo( this.uiDialog ); this._on( this.uiDialogTitlebar, { mousedown: function( event ) { @@ -412,7 +423,7 @@ return $.widget( "ui.dialog", { }, text: false }) - .addClass( "ui-dialog-titlebar-close" ) + .addClass( this._classes( "ui-dialog-titlebar-close" ) ) .appendTo( this.uiDialogTitlebar ); this._on( this.uiDialogTitlebarClose, { click: function( event ) { @@ -423,7 +434,7 @@ return $.widget( "ui.dialog", { uiDialogTitle = $( "" ) .uniqueId() - .addClass( "ui-dialog-title" ) + .addClass( this._classes( "ui-dialog-title" ) ) .prependTo( this.uiDialogTitlebar ); this._title( uiDialogTitle ); @@ -441,10 +452,10 @@ return $.widget( "ui.dialog", { _createButtonPane: function() { this.uiDialogButtonPane = $( "
" ) - .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ); + .addClass( this._classes( "ui-dialog-buttonpane" ) + " ui-widget-content ui-helper-clearfix"); this.uiButtonSet = $( "
" ) - .addClass( "ui-dialog-buttonset" ) + .addClass( this._classes( "ui-dialog-buttonset" ) ) .appendTo( this.uiDialogButtonPane ); this._createButtons(); @@ -459,7 +470,7 @@ return $.widget( "ui.dialog", { this.uiButtonSet.empty(); if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) { - this.uiDialog.removeClass( "ui-dialog-buttons" ); + this.uiDialog.removeClass( this._classes( "ui-dialog-buttons" ) ); return; } @@ -485,7 +496,7 @@ return $.widget( "ui.dialog", { .button( buttonOptions ) .appendTo( that.uiButtonSet ); }); - this.uiDialog.addClass( "ui-dialog-buttons" ); + this.uiDialog.addClass( this._classes( "ui-dialog-buttons" ) ); this.uiDialogButtonPane.appendTo( this.uiDialog ); }, @@ -505,7 +516,7 @@ return $.widget( "ui.dialog", { handle: ".ui-dialog-titlebar", containment: "document", start: function( event, ui ) { - $( this ).addClass( "ui-dialog-dragging" ); + $( this ).addClass( that._classes( "ui-dialog-dragging" ) ); that._blockFrames(); that._trigger( "dragStart", event, filteredUi( ui ) ); }, @@ -522,7 +533,7 @@ return $.widget( "ui.dialog", { "top" + (top >= 0 ? "+" : "") + top, of: that.window }; - $( this ).removeClass( "ui-dialog-dragging" ); + $( this ).removeClass( that._classes( "ui-dialog-dragging" ) ); that._unblockFrames(); that._trigger( "dragStop", event, filteredUi( ui ) ); } @@ -559,7 +570,7 @@ return $.widget( "ui.dialog", { minHeight: this._minHeight(), handles: resizeHandles, start: function( event, ui ) { - $( this ).addClass( "ui-dialog-resizing" ); + $( this ).addClass( that._classes( "ui-dialog-resizing" ) ); that._blockFrames(); that._trigger( "resizeStart", event, filteredUi( ui ) ); }, @@ -579,7 +590,6 @@ return $.widget( "ui.dialog", { "top" + (top >= 0 ? "+" : "") + top, of: that.window }; - $( this ).removeClass( "ui-dialog-resizing" ); that._unblockFrames(); that._trigger( "resizeStop", event, filteredUi( ui ) ); } @@ -667,12 +677,6 @@ return $.widget( "ui.dialog", { var isDraggable, isResizable, uiDialog = this.uiDialog; - if ( key === "dialogClass" ) { - uiDialog - .removeClass( this.options.dialogClass ) - .addClass( value ); - } - if ( key === "disabled" ) { return; } @@ -841,7 +845,7 @@ return $.widget( "ui.dialog", { } this.overlay = $( "
" ) - .addClass( "ui-widget-overlay ui-front" ) + .addClass( this._classes( "ui-widget-overlay" ) + " ui-front") .appendTo( this._appendTo() ); this._on( this.overlay, { mousedown: "_keepFocus" @@ -872,4 +876,29 @@ return $.widget( "ui.dialog", { } }); +// DEPRECATED +if ( $.uiBackCompat ) { + + // DialogClass option + $.widget( "ui.dialog", $.ui.dialog, { + options: { + dialogClass: "" + }, + _createWrapper: function() { + this._super(); + this.uiDialog.addClass( this.options.dialogClass ); + }, + _setOption: function( key, value ) { + if ( key === "dialogClass" ) { + this.uiDialog + .removeClass( this.options.dialogClass ) + .addClass( value ); + } + this._superApply( arguments ); + } + }); +} + +return $.ui.dialog; + })); From f8c5aea9a37c484d0057b2c0fbce9df12ff022d1 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Tue, 23 Apr 2013 15:10:29 -0500 Subject: [PATCH 04/73] Accordion: use the _classes method. Fixes #7053 --- tests/unit/accordion/accordion_common.js | 10 +++++ tests/unit/accordion/accordion_core.js | 22 +++++++--- tests/unit/accordion/accordion_methods.js | 8 +++- ui/accordion.js | 52 ++++++++++++++--------- 4 files changed, 64 insertions(+), 28 deletions(-) diff --git a/tests/unit/accordion/accordion_common.js b/tests/unit/accordion/accordion_common.js index ef24cf25ec5..858c2e88b4f 100644 --- a/tests/unit/accordion/accordion_common.js +++ b/tests/unit/accordion/accordion_common.js @@ -2,6 +2,16 @@ TestHelpers.commonWidgetTests( "accordion", { defaults: { active: 0, animate: {}, + classes: { + "ui-accordion": null, + "ui-accordion-header": "ui-corner-top", + "ui-accordion-header-active": null, + "ui-accordion-header-collapsed": "ui-corner-all", + "ui-accordion-content": "ui-corner-bottom", + "ui-accordion-content-active": null, + "ui-accordion-header-icon": null, + "ui-accordion-icons": null + }, collapsible: false, disabled: false, event: "click", diff --git a/tests/unit/accordion/accordion_core.js b/tests/unit/accordion/accordion_core.js index 8e0175aeb93..c61b6e26e3e 100644 --- a/tests/unit/accordion/accordion_core.js +++ b/tests/unit/accordion/accordion_core.js @@ -7,15 +7,25 @@ module( "accordion: core", setupTeardown() ); $.each( { div: "#list1", ul: "#navigation", dl: "#accordion-dl" }, function( type, selector ) { test( "markup structure: " + type, function() { - expect( 4 ); - var element = $( selector ).accordion(); + expect( 11 ); + var element = $( selector ).accordion(), + headers = element.find( ".ui-accordion-header" ), + panels = element.find( ".ui-accordion-content" ); + ok( element.hasClass( "ui-accordion" ), "main element is .ui-accordion" ); - equal( element.find( ".ui-accordion-header" ).length, 3, + ok( element.hasClass( "ui-widget" ), "main element is .ui-widget" ); + ok( headers.hasClass( "ui-corner-top" ), "header is .ui-corner-top" ); + ok( !headers.eq( 0 ).hasClass( "ui-corner-all" ), "open header is not .ui-corner-all" ); + ok( headers.eq( 1 ).hasClass( "ui-corner-all" ), "closed header is .ui-corner-all" ); + ok( headers.next().hasClass( "ui-accordion-content" ), "panel is .ui-accordion-content" ); + ok( headers.next().hasClass( "ui-widget-content" ), "panel is .ui-widget-content" ); + ok( headers.next().hasClass( "ui-corner-bottom" ), "panel is .ui-corner-bottom" ); + + equal( headers.length, 3, ".ui-accordion-header elements exist, correct number" ); - equal( element.find( ".ui-accordion-content" ).length, 3, + equal( panels.length, 3, ".ui-accordion-content elements exist, correct number" ); - deepEqual( element.find( ".ui-accordion-header" ).next().get(), - element.find( ".ui-accordion-content" ).get(), + deepEqual( headers.next().get(), panels.get(), "content panels come immediately after headers" ); }); }); diff --git a/tests/unit/accordion/accordion_methods.js b/tests/unit/accordion/accordion_methods.js index 1e809b310c2..643a20123cc 100644 --- a/tests/unit/accordion/accordion_methods.js +++ b/tests/unit/accordion/accordion_methods.js @@ -7,10 +7,16 @@ var equalHeight = TestHelpers.accordion.equalHeight, module( "accordion: methods", setupTeardown() ); test( "destroy", function() { - expect( 1 ); + expect( 2 ); domEqual( "#list1", function() { $( "#list1" ).accordion().accordion( "destroy" ); }); + // Animate + domEqual( "#list1", function() { + $( "#list1" ).accordion() + .accordion( "option", "active", 1 ) + .accordion( "destroy" ); + }); }); test( "enable/disable", function() { diff --git a/ui/accordion.js b/ui/accordion.js index 94643719731..2c5d9c5d6da 100644 --- a/ui/accordion.js +++ b/ui/accordion.js @@ -29,6 +29,16 @@ return $.widget( "ui.accordion", { options: { active: 0, animate: {}, + classes: { + "ui-accordion": null, + "ui-accordion-header": "ui-corner-top", + "ui-accordion-header-active": null, + "ui-accordion-header-collapsed": "ui-corner-all", + "ui-accordion-content": "ui-corner-bottom", + "ui-accordion-content-active": null, + "ui-accordion-header-icon": null, + "ui-accordion-icons": null + }, collapsible: false, event: "click", header: "> li > :first-child,> :not(li):even", @@ -62,7 +72,7 @@ return $.widget( "ui.accordion", { _create: function() { var options = this.options; this.prevShow = this.prevHide = $(); - this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ) + this.element.addClass( this._classes( "ui-accordion" ) + " ui-widget ui-helper-reset" ) // ARIA .attr( "role", "tablist" ); @@ -90,18 +100,18 @@ return $.widget( "ui.accordion", { var icons = this.options.icons; if ( icons ) { $( "" ) - .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) + .addClass( this._classes( "ui-accordion-header-icon" ) + " ui-icon " + icons.header ) .prependTo( this.headers ); this.active.children( ".ui-accordion-header-icon" ) .removeClass( icons.header ) .addClass( icons.activeHeader ); - this.headers.addClass( "ui-accordion-icons" ); + this.headers.addClass( this._classes( "ui-accordion-icons" ) ); } }, _destroyIcons: function() { this.headers - .removeClass( "ui-accordion-icons" ) + .removeClass( this._classes( "ui-accordion-icons" ) ) .children( ".ui-accordion-header-icon" ) .remove(); }, @@ -111,13 +121,13 @@ return $.widget( "ui.accordion", { // clean up main element this.element - .removeClass( "ui-accordion ui-widget ui-helper-reset" ) + .removeClass( this._classes( "ui-accordion" ) + " ui-widget ui-helper-reset" ) .removeAttr( "role" ); // clean up headers this.headers - .removeClass( "ui-accordion-header ui-accordion-header-active ui-state-default " + - "ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) + .removeClass( this._classes( "ui-accordion-header ui-accordion-header-active ui-accordion-header-collapsed" ) + + " ui-state-default ui-state-active ui-state-disabled" ) .removeAttr( "role" ) .removeAttr( "aria-expanded" ) .removeAttr( "aria-selected" ) @@ -129,8 +139,8 @@ return $.widget( "ui.accordion", { // clean up content panels contents = this.headers.next() - .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom " + - "ui-accordion-content ui-accordion-content-active ui-state-disabled" ) + .removeClass( this._classes( "ui-accordion-content ui-accordion-content-active" ) + + " ui-helper-reset ui-widget-content ui-state-disabled" ) .css( "display", "" ) .removeAttr( "role" ) .removeAttr( "aria-hidden" ) @@ -263,10 +273,10 @@ return $.widget( "ui.accordion", { prevPanels = this.panels; this.headers = this.element.find( this.options.header ) - .addClass( "ui-accordion-header ui-state-default ui-corner-all" ); + .addClass( this._classes( "ui-accordion-header ui-accordion-header-collapsed" ) + " ui-state-default" ); this.panels = this.headers.next() - .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) + .addClass( this._classes( "ui-accordion-content" ) + " ui-helper-reset ui-widget-content" ) .filter( ":not(.ui-accordion-content-active)" ) .hide(); @@ -284,10 +294,10 @@ return $.widget( "ui.accordion", { parent = this.element.parent(); this.active = this._findActive( options.active ) - .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) - .removeClass( "ui-corner-all" ); + .addClass( this._classes( "ui-accordion-header-active" ) + " ui-state-active" ) + .removeClass( this._classes( "ui-accordion-header-collapsed" ) ); this.active.next() - .addClass( "ui-accordion-content-active" ) + .addClass( this._classes( "ui-accordion-content-active" ) ) .show(); this.headers @@ -440,7 +450,7 @@ return $.widget( "ui.accordion", { // switch classes // corner classes on the previously active header stay after the animation - active.removeClass( "ui-accordion-header-active ui-state-active" ); + active.removeClass( this._classes( "ui-accordion-header-active" ) + " ui-state-active" ); if ( options.icons ) { active.children( ".ui-accordion-header-icon" ) .removeClass( options.icons.activeHeader ) @@ -449,8 +459,8 @@ return $.widget( "ui.accordion", { if ( !clickedIsActive ) { clicked - .removeClass( "ui-corner-all" ) - .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); + .removeClass( this._classes( "ui-accordion-header-collapsed" ) ) + .addClass( this._classes( "ui-accordion-header-active" ) + " ui-state-active" ); if ( options.icons ) { clicked.children( ".ui-accordion-header-icon" ) .removeClass( options.icons.header ) @@ -459,7 +469,7 @@ return $.widget( "ui.accordion", { clicked .next() - .addClass( "ui-accordion-content-active" ); + .addClass( this._classes( "ui-accordion-content-active" ) ); } }, @@ -568,10 +578,10 @@ return $.widget( "ui.accordion", { var toHide = data.oldPanel; toHide - .removeClass( "ui-accordion-content-active" ) + .removeClass( this._classes( "ui-accordion-content-active" ) ) .prev() - .removeClass( "ui-corner-top" ) - .addClass( "ui-corner-all" ); + .removeClass( this._classes( "ui-accordion-header-active" ) ) + .addClass( this._classes( "ui-accordion-header-collapsed" ) ); // Work around for rendering bug in IE (#5421) if ( toHide.length ) { From 544f9ff814bc5111fb2e5435cea7a01d34b99f09 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Wed, 24 Apr 2013 09:35:38 -0500 Subject: [PATCH 05/73] Autocomplete: use the _classes method. Fixes #7053 --- tests/unit/autocomplete/autocomplete_common.js | 5 +++++ tests/unit/autocomplete/autocomplete_core.js | 9 +++++++++ ui/autocomplete.js | 15 ++++++++++----- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/tests/unit/autocomplete/autocomplete_common.js b/tests/unit/autocomplete/autocomplete_common.js index 63b24d384b9..c1036388a64 100644 --- a/tests/unit/autocomplete/autocomplete_common.js +++ b/tests/unit/autocomplete/autocomplete_common.js @@ -2,6 +2,11 @@ TestHelpers.commonWidgetTests( "autocomplete", { defaults: { appendTo: null, autoFocus: false, + classes: { + "ui-autocomplete": null, + "ui-autocomplete-input": null, + "ui-autocomplete-loading": null + }, delay: 300, disabled: false, messages: { diff --git a/tests/unit/autocomplete/autocomplete_core.js b/tests/unit/autocomplete/autocomplete_core.js index fa3f9abb072..ffdc737acee 100644 --- a/tests/unit/autocomplete/autocomplete_core.js +++ b/tests/unit/autocomplete/autocomplete_core.js @@ -2,6 +2,15 @@ module( "autocomplete: core" ); +test( "markup structure", function() { + expect( 2 ); + var element = $( "#autocomplete" ).autocomplete(), + menu = element.autocomplete( "widget" ); + + ok( element.hasClass( "ui-autocomplete-input" ), "main element is .ui-autocomplete-input" ); + ok( menu.hasClass( "ui-autocomplete" ), "menu is .ui-autocomplete" ); +}); + test( "prevent form submit on enter when menu is active", function() { expect( 2 ); var event, diff --git a/ui/autocomplete.js b/ui/autocomplete.js index aa0e546334e..defd21f500e 100644 --- a/ui/autocomplete.js +++ b/ui/autocomplete.js @@ -32,6 +32,11 @@ $.widget( "ui.autocomplete", { options: { appendTo: null, autoFocus: false, + classes: { + "ui-autocomplete": null, + "ui-autocomplete-input": null, + "ui-autocomplete-loading": null + }, delay: 300, minLength: 1, position: { @@ -80,7 +85,7 @@ $.widget( "ui.autocomplete", { this.isNewMenu = true; this.element - .addClass( "ui-autocomplete-input" ) + .addClass( this._classes( "ui-autocomplete-input" ) ) .attr( "autocomplete", "off" ); this._on( this.element, { @@ -202,7 +207,7 @@ $.widget( "ui.autocomplete", { this._initSource(); this.menu = $( "
    " ) - .addClass( "ui-autocomplete ui-front" ) + .addClass( this._classes( "ui-autocomplete" ) + " ui-front" ) .appendTo( this._appendTo() ) .menu({ // disable ARIA support, the live region takes care of that @@ -323,7 +328,7 @@ $.widget( "ui.autocomplete", { _destroy: function() { clearTimeout( this.searching ); this.element - .removeClass( "ui-autocomplete-input" ) + .removeClass( this._classes( "ui-autocomplete-input" ) ) .removeAttr( "autocomplete" ); this.menu.element.remove(); this.liveRegion.remove(); @@ -428,7 +433,7 @@ $.widget( "ui.autocomplete", { _search: function( value ) { this.pending++; - this.element.addClass( "ui-autocomplete-loading" ); + this.element.addClass( this._classes( "ui-autocomplete-loading" ) ); this.cancelSearch = false; this.source( { term: value }, this._response() ); @@ -444,7 +449,7 @@ $.widget( "ui.autocomplete", { this.pending--; if ( !this.pending ) { - this.element.removeClass( "ui-autocomplete-loading" ); + this.element.removeClass( this._classes( "ui-autocomplete-loading" ) ); } }, this ); }, From 3c52f199418c1a4708d8c96cb649bac93484012a Mon Sep 17 00:00:00 2001 From: David Petersen Date: Wed, 24 Apr 2013 13:30:48 -0500 Subject: [PATCH 06/73] Slider: use the _classes method. Fixes #7053 --- tests/unit/slider/slider_common.js | 9 ++++++ tests/unit/slider/slider_core.js | 19 +++++++++++++ ui/slider.js | 44 ++++++++++++++++-------------- 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/tests/unit/slider/slider_common.js b/tests/unit/slider/slider_common.js index 6d7278de6a2..dda3f64d971 100644 --- a/tests/unit/slider/slider_common.js +++ b/tests/unit/slider/slider_common.js @@ -1,6 +1,15 @@ TestHelpers.commonWidgetTests( "slider", { defaults: { animate: false, + classes: { + "ui-slider": "ui-corner-all", + "ui-slider-handle": "ui-corner-all", + "ui-slider-range": "ui-corner-all", + "ui-slider-range-min": null, + "ui-slider-range-max": null, + "ui-slider-horizontal": null, + "ui-slider-vertical": null + }, cancel: "input,textarea,button,select,option", delay: 0, disabled: false, diff --git a/tests/unit/slider/slider_core.js b/tests/unit/slider/slider_core.js index 3649bded038..425c7bfc441 100644 --- a/tests/unit/slider/slider_core.js +++ b/tests/unit/slider/slider_core.js @@ -12,6 +12,25 @@ function handle() { // Slider Tests module( "slider: core" ); +test( "markup structure", function() { + expect( 9 ); + var element = $( "
    " ).slider({ range: true }), + handle = element.find( "span" ), + range = element.find( "div" ); + + ok( element.hasClass( "ui-slider" ), "main element is .ui-slider" ); + ok( element.hasClass( "ui-widget" ), "main element is .ui-widget" ); + ok( element.hasClass( "ui-widget-content" ), "main element is .ui-widget-content" ); + ok( element.hasClass( "ui-corner-all" ), "main element is .ui-corner-all" ); + + ok( handle.hasClass( "ui-slider-handle" ), "handle is .ui-slider-handle" ); + ok( handle.hasClass( "ui-corner-all" ), "handle is .ui-corner-all" ); + + ok( range.hasClass( "ui-slider-range" ), "range is .ui-slider-range" ); + ok( range.hasClass( "ui-widget-header" ), "range is .ui-widget-header" ); + ok( range.hasClass( "ui-corner-all" ), "range is .ui-corner-all" ); +}); + test( "keydown HOME on handle sets value to min", function() { expect( 2 ); element = $( "
    " ); diff --git a/ui/slider.js b/ui/slider.js index 6d97f3c6939..0469022d3c6 100644 --- a/ui/slider.js +++ b/ui/slider.js @@ -31,6 +31,15 @@ return $.widget( "ui.slider", $.ui.mouse, { options: { animate: false, + classes: { + "ui-slider": "ui-corner-all", + "ui-slider-handle": "ui-corner-all", + "ui-slider-range": "ui-corner-all", + "ui-slider-range-min": null, + "ui-slider-range-max": null, + "ui-slider-horizontal": null, + "ui-slider-vertical": null + }, distance: 0, max: 100, min: 0, @@ -61,11 +70,9 @@ return $.widget( "ui.slider", $.ui.mouse, { this._calculateNewMax(); this.element - .addClass( "ui-slider" + - " ui-slider-" + this.orientation + + .addClass( this._classes( "ui-slider ui-slider-" + this.orientation ) + " ui-widget" + - " ui-widget-content" + - " ui-corner-all"); + " ui-widget-content" ); this._refresh(); this._setOption( "disabled", this.options.disabled ); @@ -83,8 +90,9 @@ return $.widget( "ui.slider", $.ui.mouse, { _createHandles: function() { var i, handleCount, options = this.options, - existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), - handle = "", + existingHandles = this.element.find( ".ui-slider-handle" ) + .addClass( this._classes( "ui-slider-handle" ) + " ui-state-default" ), + handle = "", handles = []; handleCount = ( options.values && options.values.length ) || 1; @@ -123,15 +131,15 @@ return $.widget( "ui.slider", $.ui.mouse, { } if ( !this.range || !this.range.length ) { - this.range = $( "
    " ) + this.range = $( "
    " ) .appendTo( this.element ); - classes = "ui-slider-range" + + classes = this._classes( "ui-slider-range" ) + // note: this isn't the most fittingly semantic framework class for this element, // but worked best visually with a variety of themes - " ui-widget-header ui-corner-all"; + " ui-widget-header"; } else { - this.range.removeClass( "ui-slider-range-min ui-slider-range-max" ) + this.range.removeClass( this._classes( "ui-slider-range-min ui-slider-range-max" ) ) // Handle range switching from true to min/max .css({ "left": "", @@ -139,8 +147,8 @@ return $.widget( "ui.slider", $.ui.mouse, { }); } - this.range.addClass( classes + - ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) ); + this.range.addClass( classes + " " + + this._classes( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) ); } else { if ( this.range ) { this.range.remove(); @@ -163,12 +171,8 @@ return $.widget( "ui.slider", $.ui.mouse, { } this.element - .removeClass( "ui-slider" + - " ui-slider-horizontal" + - " ui-slider-vertical" + - " ui-widget" + - " ui-widget-content" + - " ui-corner-all" ); + .removeClass( this._classes( "ui-slider ui-slider-horizontal ui-slider-vertical" ) + + " ui-widget ui-widget-content" ); this._mouseDestroy(); }, @@ -452,8 +456,8 @@ return $.widget( "ui.slider", $.ui.mouse, { case "orientation": this._detectOrientation(); this.element - .removeClass( "ui-slider-horizontal ui-slider-vertical" ) - .addClass( "ui-slider-" + this.orientation ); + .removeClass( this._classes( "ui-slider-horizontal ui-slider-vertical" ) ) + .addClass( this._classes( "ui-slider-" + this.orientation ) ); this._refreshValue(); // Reset positioning from previous orientation From b1c0f22561895631224b07198d9f74dbc27b7f1a Mon Sep 17 00:00:00 2001 From: David Petersen Date: Wed, 24 Apr 2013 13:46:22 -0500 Subject: [PATCH 07/73] Spinner: use the _classes method. Fixes #7053 --- tests/unit/spinner/spinner_common.js | 7 +++++++ tests/unit/spinner/spinner_core.js | 21 +++++++++++++++++++++ ui/spinner.js | 17 ++++++++++++----- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/tests/unit/spinner/spinner_common.js b/tests/unit/spinner/spinner_common.js index b494e3ca34d..ae9fce58faf 100644 --- a/tests/unit/spinner/spinner_common.js +++ b/tests/unit/spinner/spinner_common.js @@ -1,5 +1,12 @@ TestHelpers.commonWidgetTests( "spinner", { defaults: { + classes: { + "ui-spinner-input": null, + "ui-spinner": "ui-corner-all", + "ui-spinner-button": null, + "ui-spinner-up": "ui-corner-tr", + "ui-spinner-down": "ui-corner-br" + }, culture: null, disabled: false, icons: { diff --git a/tests/unit/spinner/spinner_core.js b/tests/unit/spinner/spinner_core.js index 03088fecdca..076b3b8cfdd 100644 --- a/tests/unit/spinner/spinner_core.js +++ b/tests/unit/spinner/spinner_core.js @@ -4,6 +4,27 @@ var simulateKeyDownUp = TestHelpers.spinner.simulateKeyDownUp; module( "spinner: core" ); +test( "markup structure", function() { + expect( 9 ); + var element = $( "#spin" ).spinner(), + spinner = element.spinner( "widget" ), + up = spinner.find( ".ui-spinner-up" ), + down = spinner.find( ".ui-spinner-down" ); + + ok( element.hasClass( "ui-spinner-input" ), "input is .ui-spinner-input" ); + + ok( spinner.hasClass( "ui-spinner" ), "main element is .ui-spinner" ); + ok( spinner.hasClass( "ui-widget" ), "main element is .ui-widget" ); + ok( spinner.hasClass( "ui-widget-content" ), "main element is .ui-widget-content" ); + ok( spinner.hasClass( "ui-corner-all" ), "main element is .ui-corner-all" ); + + ok( up.hasClass( "ui-spinner-button" ), "up button is .ui-spinner-button" ); + ok( up.hasClass( "ui-corner-tr" ), "up button is .ui-corner-tr" ); + + ok( down.hasClass( "ui-spinner-button" ), "down button is .ui-spinner-button" ); + ok( down.hasClass( "ui-corner-br" ), "down button is .ui-corner-br" ); +}); + test( "keydown UP on input, increases value not greater than max", function() { expect( 5 ); var element = $( "#spin" ).val( 70 ).spinner({ diff --git a/ui/spinner.js b/ui/spinner.js index 263b29d3fbb..8d3d9421097 100644 --- a/ui/spinner.js +++ b/ui/spinner.js @@ -41,6 +41,13 @@ return $.widget( "ui.spinner", { defaultElement: "", widgetEventPrefix: "spin", options: { + classes: { + "ui-spinner-input": null, + "ui-spinner": "ui-corner-all", + "ui-spinner-button": null, + "ui-spinner-up": "ui-corner-tr", + "ui-spinner-down": "ui-corner-br" + }, culture: null, icons: { down: "ui-icon-triangle-1-s", @@ -203,7 +210,7 @@ return $.widget( "ui.spinner", { _draw: function() { var uiSpinner = this.uiSpinner = this.element - .addClass( "ui-spinner-input" ) + .addClass( this._classes( "ui-spinner-input" ) ) .attr( "autocomplete", "off" ) .wrap( this._uiSpinnerHtml() ) .parent() @@ -254,15 +261,15 @@ return $.widget( "ui.spinner", { }, _uiSpinnerHtml: function() { - return ""; + return ""; }, _buttonHtml: function() { return "" + - "" + + "" + "" + "" + - "" + + "" + "" + ""; }, @@ -461,7 +468,7 @@ return $.widget( "ui.spinner", { _destroy: function() { this.element - .removeClass( "ui-spinner-input" ) + .removeClass( this._classes( "ui-spinner-input" ) ) .prop( "disabled", false ) .removeAttr( "autocomplete" ) .removeAttr( "role" ) From 43ec02b1c11fbed1284a899d0c57446773085fb7 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Wed, 24 Apr 2013 14:03:07 -0500 Subject: [PATCH 08/73] Progressbar: use the _classes method. Fixes #7053 --- tests/unit/progressbar/progressbar_common.js | 7 +++++++ tests/unit/progressbar/progressbar_core.js | 14 +++++++++++-- ui/progressbar.js | 22 ++++++++++++++------ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/tests/unit/progressbar/progressbar_common.js b/tests/unit/progressbar/progressbar_common.js index 0768576f568..db0cdddc10d 100644 --- a/tests/unit/progressbar/progressbar_common.js +++ b/tests/unit/progressbar/progressbar_common.js @@ -1,5 +1,12 @@ TestHelpers.commonWidgetTests( "progressbar", { defaults: { + classes: { + "ui-progressbar": "ui-corner-all", + "ui-progressbar-value": "ui-corner-left", + "ui-progressbar-overlay": null, + "ui-progressbar-indeterminate": null, + "ui-progressbar-complete": "ui-corner-right" + }, disabled: false, max: 100, value: 0, diff --git a/tests/unit/progressbar/progressbar_core.js b/tests/unit/progressbar/progressbar_core.js index 8f4a138ce9c..138841eaa73 100644 --- a/tests/unit/progressbar/progressbar_core.js +++ b/tests/unit/progressbar/progressbar_core.js @@ -1,9 +1,19 @@ module( "progressbar: core" ); test( "markup structure", function() { - expect( 5 ); - var element = $( "#progressbar" ).progressbar(); + expect( 12 ); + var element = $( "#progressbar" ).progressbar(), + value = element.children().eq( 0 ); ok( element.hasClass( "ui-progressbar" ), "main element is .ui-progressbar" ); + ok( element.hasClass( "ui-widget" ), "main element is .ui-widget" ); + ok( element.hasClass( "ui-widget-content" ), "main element is .ui-widget-content" ); + ok( element.hasClass( "ui-corner-all" ), "main element is .ui-corner-all" ); + ok( !value.hasClass( "ui-progressbar-complete" ), "value is not .ui-progressbar-complete" ); + ok( !value.hasClass( "ui-corner-right" ), "value is not .ui-corner-right" ); + element.progressbar( "option", "value", 100 ); + ok( value.hasClass( "ui-progressbar-complete" ), "value is .ui-progressbar-complete" ); + ok( value.hasClass( "ui-corner-right" ), "value is .ui-corner-right" ); + ok( !element.hasClass( "ui-progressbar-indeterminate" ), "main element is not .ui-progressbar-indeterminate" ); equal( element.children().length, 1, "main element contains one child" ); diff --git a/ui/progressbar.js b/ui/progressbar.js index ac8144d7361..b6bd83763a1 100644 --- a/ui/progressbar.js +++ b/ui/progressbar.js @@ -27,6 +27,13 @@ return $.widget( "ui.progressbar", { version: "@VERSION", options: { + classes: { + "ui-progressbar": "ui-corner-all", + "ui-progressbar-value": "ui-corner-left", + "ui-progressbar-overlay": null, + "ui-progressbar-indeterminate": null, + "ui-progressbar-complete": "ui-corner-right" + }, max: 100, value: 0, @@ -41,7 +48,7 @@ return $.widget( "ui.progressbar", { this.oldValue = this.options.value = this._constrainedValue(); this.element - .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) + .addClass( this._classes( "ui-progressbar" ) + " ui-widget ui-widget-content" ) .attr({ // Only set static values, aria-valuenow and aria-valuemax are // set inside _refreshValue() @@ -49,7 +56,8 @@ return $.widget( "ui.progressbar", { "aria-valuemin": this.min }); - this.valueDiv = $( "
    " ) + this.valueDiv = $( "
    " ) + .addClass( this._classes( "ui-progressbar-value" ) + " ui-widget-header" ) .appendTo( this.element ); this._refreshValue(); @@ -57,7 +65,7 @@ return $.widget( "ui.progressbar", { _destroy: function() { this.element - .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) + .removeClass( this._classes( "ui-progressbar" ) + " ui-widget ui-widget-content" ) .removeAttr( "role" ) .removeAttr( "aria-valuemin" ) .removeAttr( "aria-valuemax" ) @@ -125,15 +133,17 @@ return $.widget( "ui.progressbar", { this.valueDiv .toggle( this.indeterminate || value > this.min ) - .toggleClass( "ui-corner-right", value === this.options.max ) + .toggleClass( this._classes( "ui-progressbar-complete" ), value === this.options.max ) .width( percentage.toFixed(0) + "%" ); - this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate ); + this.element.toggleClass( this._classes( "ui-progressbar-indeterminate" ), this.indeterminate ); if ( this.indeterminate ) { this.element.removeAttr( "aria-valuenow" ); if ( !this.overlayDiv ) { - this.overlayDiv = $( "
    " ).appendTo( this.valueDiv ); + this.overlayDiv = $( "
    " ) + .addClass( this._classes( "ui-progressbar-overlay" ) ) + .appendTo( this.valueDiv ); } } else { this.element.attr({ From 51d1d33fd1d7ad750f455134fbb8df64c3def968 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Thu, 25 Apr 2013 08:28:40 -0500 Subject: [PATCH 09/73] Menu: use the _classes method. Fixes #7053 --- tests/unit/menu/menu_common.js | 7 +++++++ tests/unit/menu/menu_core.js | 3 ++- ui/menu.js | 34 +++++++++++++++++++++------------- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/tests/unit/menu/menu_common.js b/tests/unit/menu/menu_common.js index ae0ab988785..b1c90b4a80b 100644 --- a/tests/unit/menu/menu_common.js +++ b/tests/unit/menu/menu_common.js @@ -1,5 +1,12 @@ TestHelpers.commonWidgetTests( "menu", { defaults: { + classes: { + "ui-menu": "ui-corner-all", + "ui-menu-icons": null, + "ui-menu-icon": null, + "ui-menu-item": null, + "ui-menu-divider": null + }, disabled: false, icons: { submenu: "ui-icon-caret-1-e" diff --git a/tests/unit/menu/menu_core.js b/tests/unit/menu/menu_core.js index f02f97fca50..55f9077a110 100644 --- a/tests/unit/menu/menu_core.js +++ b/tests/unit/menu/menu_core.js @@ -3,9 +3,10 @@ module( "menu: core" ); test( "markup structure", function() { - expect( 6 ); + expect( 7 ); var element = $( "#menu1" ).menu(); ok( element.hasClass( "ui-menu" ), "main element is .ui-menu" ); + ok( element.hasClass( "ui-corner-all" ), "main element is .ui-corner-all" ); element.children().each(function( index ) { ok( $( this ).hasClass( "ui-menu-item" ), "child " + index + " is .ui-menu-item" ); }); diff --git a/ui/menu.js b/ui/menu.js index 6d60e12a5bf..3c9d016648d 100644 --- a/ui/menu.js +++ b/ui/menu.js @@ -30,6 +30,13 @@ return $.widget( "ui.menu", { defaultElement: "
      ", delay: 300, options: { + classes: { + "ui-menu": "ui-corner-all", + "ui-menu-icons": null, + "ui-menu-icon": null, + "ui-menu-item": null, + "ui-menu-divider": null + }, icons: { submenu: "ui-icon-caret-1-e" }, @@ -55,8 +62,8 @@ return $.widget( "ui.menu", { this.mouseHandled = false; this.element .uniqueId() - .addClass( "ui-menu ui-widget ui-widget-content" ) - .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) + .addClass( this._classes( "ui-menu" ) + " ui-widget ui-widget-content" ) + .toggleClass( this._classes( "ui-menu-icons" ), !!this.element.find( ".ui-icon" ).length ) .attr({ role: this.options.role, tabIndex: 0 @@ -155,7 +162,7 @@ return $.widget( "ui.menu", { this.element .removeAttr( "aria-activedescendant" ) .find( ".ui-menu" ).addBack() - .removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" ) + .removeClass( this._classes( "ui-menu ui-menu-icons" ) + " ui-widget ui-widget-content ui-front" ) .removeAttr( "role" ) .removeAttr( "tabIndex" ) .removeAttr( "aria-labelledby" ) @@ -167,12 +174,12 @@ return $.widget( "ui.menu", { // Destroy menu items this.element.find( ".ui-menu-item" ) - .removeClass( "ui-menu-item" ) + .removeClass( this._classes( "ui-menu-item" ) ) .removeAttr( "role" ) .removeAttr( "aria-disabled" ) .children( ".ui-menu-item-wrapper" ) .removeUniqueId() - .removeClass( "ui-menu-item-wrapper ui-state-hover" ) + .removeClass( this._classes( "ui-menu-item-wrapper" ) + "ui-state-hover" ) .removeAttr( "tabIndex" ) .removeAttr( "role" ) .removeAttr( "aria-haspopup" ) @@ -184,7 +191,8 @@ return $.widget( "ui.menu", { }); // Destroy menu dividers - this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); + this.element.find( ".ui-menu-divider" ) + .removeClass( this._classes( "ui-menu-divider" ) + " ui-widget-content" ); }, _keydown: function( event ) { @@ -287,7 +295,7 @@ return $.widget( "ui.menu", { // Initialize nested menus submenus.filter( ":not(.ui-menu)" ) - .addClass( "ui-menu ui-widget ui-widget-content ui-front" ) + .addClass( this._classes( "ui-menu" ) + " ui-widget ui-widget-content ui-front" ) .hide() .attr({ role: this.options.role, @@ -297,9 +305,9 @@ return $.widget( "ui.menu", { .each(function() { var menu = $( this ), item = menu.prev(), - submenuCaret = $( "" ) - .addClass( "ui-menu-icon ui-icon " + icon ) - .data( "ui-menu-submenu-caret", true ); + submenuCarat = $( "" ) + .addClass( that._classes( "ui-menu-icon" ) + " ui-icon " + icon ) + .data( "ui-menu-submenu-carat", true ); item .attr( "aria-haspopup", "true" ) @@ -314,16 +322,16 @@ return $.widget( "ui.menu", { items.not( ".ui-menu-item" ).each(function() { var item = $( this ); if ( that._isDivider( item ) ) { - item.addClass( "ui-widget-content ui-menu-divider" ); + item.addClass( that._classes( "ui-menu-divider" ) + " ui-widget-content" ); } }); // Don't refresh list items that are already adapted items.not( ".ui-menu-item, .ui-menu-divider" ) - .addClass( "ui-menu-item" ) + .addClass( this._classes( "ui-menu-item" ) ) .children() .not( ".ui-menu" ) - .addClass( "ui-menu-item-wrapper" ) + .addClass( this._classes( "ui-menu-item-wrapper" ) ) .uniqueId() .attr({ tabIndex: -1, From 0aa2e1fed758311d398774f3e5056e5e1b74216b Mon Sep 17 00:00:00 2001 From: David Petersen Date: Thu, 25 Apr 2013 09:50:51 -0500 Subject: [PATCH 10/73] Tooltip: use the _classes method. Fixes #7053 --- tests/unit/tooltip/tooltip.html | 3 + tests/unit/tooltip/tooltip_common.js | 5 +- .../unit/tooltip/tooltip_common_deprecated.js | 25 +++++++++ tests/unit/tooltip/tooltip_deprecated.html | 55 +++++++++++++++++++ tests/unit/tooltip/tooltip_deprecated.js | 16 ++++++ tests/unit/tooltip/tooltip_options.js | 8 --- ui/tooltip.js | 30 ++++++++-- 7 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 tests/unit/tooltip/tooltip_common_deprecated.js create mode 100644 tests/unit/tooltip/tooltip_deprecated.html create mode 100644 tests/unit/tooltip/tooltip_deprecated.js diff --git a/tests/unit/tooltip/tooltip.html b/tests/unit/tooltip/tooltip.html index 18bd88c2c98..41babc0a004 100644 --- a/tests/unit/tooltip/tooltip.html +++ b/tests/unit/tooltip/tooltip.html @@ -5,6 +5,9 @@ jQuery UI Tooltip Test Suite + diff --git a/tests/unit/tooltip/tooltip_common.js b/tests/unit/tooltip/tooltip_common.js index 2d6ea91eccd..01a4225820f 100644 --- a/tests/unit/tooltip/tooltip_common.js +++ b/tests/unit/tooltip/tooltip_common.js @@ -1,5 +1,9 @@ TestHelpers.commonWidgetTests( "tooltip", { defaults: { + classes: { + "ui-tooltip": "ui-corner-all", + "ui-tooltip-content": null + }, content: function() {}, disabled: false, hide: true, @@ -10,7 +14,6 @@ TestHelpers.commonWidgetTests( "tooltip", { collision: "flipfit flip" }, show: true, - tooltipClass: null, track: false, // callbacks diff --git a/tests/unit/tooltip/tooltip_common_deprecated.js b/tests/unit/tooltip/tooltip_common_deprecated.js new file mode 100644 index 00000000000..cad4a28f8b1 --- /dev/null +++ b/tests/unit/tooltip/tooltip_common_deprecated.js @@ -0,0 +1,25 @@ +TestHelpers.commonWidgetTests( "tooltip", { + defaults: { + classes: { + "ui-tooltip": "ui-corner-all", + "ui-tooltip-content": null + }, + content: function() {}, + disabled: false, + hide: true, + items: "[title]:not([disabled])", + position: { + my: "left top+15", + at: "left bottom", + collision: "flipfit flip" + }, + show: true, + tooltipClass: null, + track: false, + + // callbacks + close: null, + create: null, + open: null + } +}); diff --git a/tests/unit/tooltip/tooltip_deprecated.html b/tests/unit/tooltip/tooltip_deprecated.html new file mode 100644 index 00000000000..29a4b64284c --- /dev/null +++ b/tests/unit/tooltip/tooltip_deprecated.html @@ -0,0 +1,55 @@ + + + + + jQuery UI Tooltip Test Suite + + + + + + + + + + + + + + + + + + + + +
      +
      + +
      + anchor + + aria-describedby + span + baz +
      + +
      + +
      + +
      + + diff --git a/tests/unit/tooltip/tooltip_deprecated.js b/tests/unit/tooltip/tooltip_deprecated.js new file mode 100644 index 00000000000..abd24f2e61a --- /dev/null +++ b/tests/unit/tooltip/tooltip_deprecated.js @@ -0,0 +1,16 @@ +/* + * dialog_deprecated.js + */ +(function( $ ) { + +module( "tooltip: (deprecated) options" ); + +test( "tooltipClass", function() { + expect( 1 ); + var element = $( "#tooltipped1" ).tooltip({ + tooltipClass: "custom" + }).tooltip( "open" ); + ok( $( "#" + element.data( "ui-tooltip-id" ) ).hasClass( "custom" ) ); +}); + +}( jQuery ) ); diff --git a/tests/unit/tooltip/tooltip_options.js b/tests/unit/tooltip/tooltip_options.js index 17f0a423775..4b9d64830a7 100644 --- a/tests/unit/tooltip/tooltip_options.js +++ b/tests/unit/tooltip/tooltip_options.js @@ -120,14 +120,6 @@ test( "items", function() { element.tooltip( "destroy" ); }); -test( "tooltipClass", function() { - expect( 1 ); - var element = $( "#tooltipped1" ).tooltip({ - tooltipClass: "custom" - }).tooltip( "open" ); - ok( $( "#" + element.data( "ui-tooltip-id" ) ).hasClass( "custom" ) ); -}); - test( "track + show delay", function() { expect( 2 ); var event, diff --git a/ui/tooltip.js b/ui/tooltip.js index 180c9f8e24c..347c0bb8a17 100644 --- a/ui/tooltip.js +++ b/ui/tooltip.js @@ -25,9 +25,13 @@ } }(function( $ ) { -return $.widget( "ui.tooltip", { +$.widget( "ui.tooltip", { version: "@VERSION", options: { + classes: { + "ui-tooltip": "ui-corner-all", + "ui-tooltip-content": null + }, content: function() { // support: IE<9, Opera in jQuery <1.7 // .text() can't accept undefined, so coerce to a string @@ -44,7 +48,6 @@ return $.widget( "ui.tooltip", { collision: "flipfit flip" }, show: true, - tooltipClass: null, track: false, // callbacks @@ -404,12 +407,11 @@ return $.widget( "ui.tooltip", { _tooltip: function( element ) { var tooltip = $( "
      " ) .attr( "role", "tooltip" ) - .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " + - ( this.options.tooltipClass || "" ) ), + .addClass( this._classes( "ui-tooltip" ) + " ui-widget ui-widget-content " ), id = tooltip.uniqueId().attr( "id" ); $( "
      " ) - .addClass( "ui-tooltip-content" ) + .addClass( this._classes( "ui-tooltip-content" ) ) .appendTo( tooltip ); tooltip.appendTo( this.document[0].body ); @@ -458,4 +460,22 @@ return $.widget( "ui.tooltip", { } }); +// DEPRECATED +if ( $.uiBackCompat ) { + + // TooltipClass option + $.widget( "ui.tooltip", $.ui.tooltip, { + options: { + tooltipClass: null + }, + _tooltip: function() { + var tooltip = this._superApply( arguments ); + tooltip.tooltip.addClass( this.options.tooltipClass || "" ); + return tooltip; + } + }); +} + +return $.ui.tooltip; + })); From 9562d7a852f3d9d8927e4dbe34ebb85c6f3860b9 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sat, 23 Aug 2014 17:41:03 -0500 Subject: [PATCH 11/73] Selectmenu: use the _classes method. Fixes #7053 --- tests/unit/selectmenu/selectmenu_common.js | 9 ++++++ tests/unit/selectmenu/selectmenu_core.js | 18 ++++++++++++ ui/selectmenu.js | 32 ++++++++++++++-------- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/tests/unit/selectmenu/selectmenu_common.js b/tests/unit/selectmenu/selectmenu_common.js index 10073fe97be..da7388eab69 100644 --- a/tests/unit/selectmenu/selectmenu_common.js +++ b/tests/unit/selectmenu/selectmenu_common.js @@ -1,6 +1,15 @@ TestHelpers.commonWidgetTests( "selectmenu", { defaults: { appendTo: null, + classes: { + "ui-selectmenu-button": "", + "ui-selectmenu-button-open": "ui-corner-top", + "ui-selectmenu-button-closed": "ui-corner-all", + "ui-selectmenu-text": null, + "ui-selectmenu-menu": null, + "ui-selectmenu-optgroup": null, + "ui-selectmenu-open": null + }, disabled: null, icons: { button: "ui-icon-triangle-1-s" diff --git a/tests/unit/selectmenu/selectmenu_core.js b/tests/unit/selectmenu/selectmenu_core.js index b4efb80f2fb..b3d0790e2bc 100644 --- a/tests/unit/selectmenu/selectmenu_core.js +++ b/tests/unit/selectmenu/selectmenu_core.js @@ -2,6 +2,24 @@ module( "selectmenu: core" ); +test( "markup structure", function() { + var element = $( "#files" ).selectmenu(), + button = element.selectmenu( "widget" ), + menu = element.selectmenu( "menuWidget" ), + menuWrap = menu.parent(); + + expect( 7 ); + + ok( button.hasClass( "ui-selectmenu-button" ), "button is .ui-selectmenu-button" ); + ok( button.hasClass( "ui-selectmenu-button-closed" ), "button is .ui-selectmenu-button-closed" ); + ok( !button.hasClass( "ui-selectmenu-button-open" ), "button is not .ui-selectmenu-button-open" ); + ok( button.hasClass( "ui-widget" ), "button is .ui-widget" ); + ok( button.hasClass( "ui-state-default" ), "button is .ui-state-default" ); + + ok( menuWrap.hasClass( "ui-selectmenu-menu" ), "menu is .ui-selectmenu-menu" ); + ok( !menuWrap.hasClass( "ui-selectmenu-menu-open" ), "menu is not .ui-selectmenu-menu-open" ); +}); + asyncTest( "accessibility", function() { var wrappers, button, menu, element = $( "#speed" ).attr( "title", "A demo title" ); diff --git a/ui/selectmenu.js b/ui/selectmenu.js index 0859a2c2c1c..d504b27a9fd 100644 --- a/ui/selectmenu.js +++ b/ui/selectmenu.js @@ -31,6 +31,15 @@ return $.widget( "ui.selectmenu", { defaultElement: " - + An anchor +
      +

      CSS Buttons

      + + + -An anchor +An anchor

      Examples of the markup that can be used for buttons: A button element, an input of type submit and an anchor.

      diff --git a/demos/button/icons.html b/demos/button/icons.html index 76cb1147876..ac7611b98b5 100644 --- a/demos/button/icons.html +++ b/demos/button/icons.html @@ -11,39 +11,58 @@ - - - - - -

      Some buttons with various combinations of text and icons.

      +
      +
      +

      Widget

      + Button with icon only + + + +
      +
      +

      CSS

      + + + + + +
      diff --git a/tests/unit/button/button.html b/tests/unit/button/button.html index abda5c987f0..762eaa1dd68 100644 --- a/tests/unit/button/button.html +++ b/tests/unit/button/button.html @@ -33,7 +33,7 @@
      -
      +
      diff --git a/tests/unit/button/button_common.js b/tests/unit/button/button_common.js index ef22d30114f..c59d4ee909d 100644 --- a/tests/unit/button/button_common.js +++ b/tests/unit/button/button_common.js @@ -1,14 +1,12 @@ TestHelpers.commonWidgetTests( "button", { defaults: { disabled: null, - icons: { - primary: null, - secondary: null - }, + showLabel: true, label: null, - text: true, + icon: null, + iconPosition: "beginning", - // callbacks + // Callbacks create: null } }); diff --git a/tests/unit/button/button_core.js b/tests/unit/button/button_core.js index f647cdc26b1..ed7424281b2 100644 --- a/tests/unit/button/button_core.js +++ b/tests/unit/button/button_core.js @@ -5,69 +5,9 @@ (function($) { -module("button: core"); +module( "Button: core" ); -test("checkbox", function() { - expect( 4 ); - var input = $("#check"), - label = $("label[for=check]"); - ok( input.is(":visible") ); - ok( label.is(":not(.ui-button)") ); - input.button(); - ok( input.is(".ui-helper-hidden-accessible") ); - ok( label.is(".ui-button") ); -}); - -test("radios", function() { - expect( 4 ); - var inputs = $("#radio0 input"), - labels = $("#radio0 label"); - ok( inputs.is(":visible") ); - ok( labels.is(":not(.ui-button)") ); - inputs.button(); - ok( inputs.is(".ui-helper-hidden-accessible") ); - ok( labels.is(".ui-button") ); -}); - -function assert(noForm, form1, form2) { - ok( $("#radio0 .ui-button" + noForm).is(".ui-state-active") ); - ok( $("#radio1 .ui-button" + form1).is(".ui-state-active") ); - ok( $("#radio2 .ui-button" + form2).is(".ui-state-active") ); -} - -test("radio groups", function() { - expect( 12 ); - $("input[type=radio]").button(); - assert(":eq(0)", ":eq(1)", ":eq(2)"); - - // click outside of forms - $("#radio0 .ui-button:eq(1)").click(); - assert(":eq(1)", ":eq(1)", ":eq(2)"); - - // click in first form - $("#radio1 .ui-button:eq(0)").click(); - assert(":eq(1)", ":eq(0)", ":eq(2)"); - - // click in second form - $("#radio2 .ui-button:eq(0)").click(); - assert(":eq(1)", ":eq(0)", ":eq(0)"); -}); - -test( "radio groups - ignore elements with same name", function() { - expect( 1 ); - var form = $( "form:first" ), - radios = form.find( "[type=radio]" ).button(), - checkbox = $( "", { - type: "checkbox", - name: radios.attr( "name" ) - }); - - form.append( checkbox ); - radios.button( "refresh" ); - ok( true, "no exception from accessing button instance of checkbox" ); -}); - -test("input type submit, don't create child elements", function() { +test( "Input type submit, don't create child elements", function() { expect( 2 ); var input = $("#submit"); deepEqual( input.children().length, 0 ); @@ -75,150 +15,15 @@ test("input type submit, don't create child elements", function() { deepEqual( input.children().length, 0 ); }); -test("buttonset", function() { - expect( 6 ); - var set = $("#radio1").buttonset(); - ok( set.is(".ui-buttonset") ); - deepEqual( set.children(".ui-button").length, 3 ); - deepEqual( set.children("input[type=radio].ui-helper-hidden-accessible").length, 3 ); - ok( set.children("label:eq(0)").is(".ui-button.ui-corner-left:not(.ui-corner-all)") ); - ok( set.children("label:eq(1)").is(".ui-button:not(.ui-corner-all)") ); - ok( set.children("label:eq(2)").is(".ui-button.ui-corner-right:not(.ui-corner-all)") ); -}); - -test("buttonset (rtl)", function() { - expect( 6 ); - var set, - parent = $("#radio1").parent(); - // Set to rtl - parent.attr("dir", "rtl"); - - set = $("#radio1").buttonset(); - ok( set.is(".ui-buttonset") ); - deepEqual( set.children(".ui-button").length, 3 ); - deepEqual( set.children("input[type=radio].ui-helper-hidden-accessible").length, 3 ); - ok( set.children("label:eq(0)").is(".ui-button.ui-corner-right:not(.ui-corner-all)") ); - ok( set.children("label:eq(1)").is(".ui-button:not(.ui-corner-all)") ); - ok( set.children("label:eq(2)").is(".ui-button.ui-corner-left:not(.ui-corner-all)") ); -}); - -// TODO: simulated click events don't behave like real click events in IE -// remove this when simulate properly simulates this -// see http://yuilibrary.com/projects/yui2/ticket/2528826 fore more info -if ( !$.ui.ie || ( document.documentMode && document.documentMode > 8 ) ) { - asyncTest( "ensure checked and aria after single click on checkbox label button, see #5518", function() { - expect( 3 ); - - $("#check2").button().change( function() { - var lbl = $( this ).button("widget"); - ok( this.checked, "checked ok" ); - ok( lbl.attr("aria-pressed") === "true", "aria ok" ); - ok( lbl.hasClass("ui-state-active"), "ui-state-active ok" ); - }); - - // support: Opera - // Opera doesn't trigger a change event when this is done synchronously. - // This seems to be a side effect of another test, but until that can be - // tracked down, this delay will have to do. - setTimeout(function() { - $("#check2").button("widget").simulate("click"); - start(); - }, 1 ); - }); -} - -test( "#7092 - button creation that requires a matching label does not find label in all cases", function() { - expect( 5 ); - var group = $( "" ); - group.find( "input[type=checkbox]" ).button(); - ok( group.find( "label" ).is( ".ui-button" ) ); - - group = $( "" ); - group.filter( "input[type=checkbox]" ).button(); - ok( group.filter( "label" ).is( ".ui-button" ) ); - - group = $( "" ); - group.find( "input[type=checkbox]" ).button(); - ok( group.filter( "label" ).is( ".ui-button" ) ); - - group = $( "" ); - group.find( "input[type=checkbox]" ).button(); - ok( group.find( "label" ).is( ".ui-button" ) ); - - group = $( "" ); - group.filter( "input[type=checkbox]" ).button(); - ok( group.find( "label" ).is( ".ui-button" ) ); -}); - -test( "#5946 - buttonset should ignore buttons that are not :visible", function() { - expect( 2 ); - $( "#radio01" ).next().addBack().hide(); - var set = $( "#radio0" ).buttonset({ items: "input[type=radio]:visible" }); - ok( set.find( "label:eq(0)" ).is( ":not(.ui-button):not(.ui-corner-left)" ) ); - ok( set.find( "label:eq(1)" ).is( ".ui-button.ui-corner-left" ) ); -}); - -test( "#6262 - buttonset not applying ui-corner to invisible elements", function() { - expect( 3 ); - $( "#radio0" ).hide(); - var set = $( "#radio0" ).buttonset(); - ok( set.find( "label:eq(0)" ).is( ".ui-button.ui-corner-left" ) ); - ok( set.find( "label:eq(1)" ).is( ".ui-button" ) ); - ok( set.find( "label:eq(2)" ).is( ".ui-button.ui-corner-right" ) ); -}); - -asyncTest( "Resetting a button's form should refresh the visual state of the button widget to match.", function() { - expect( 2 ); - var form = $( "
      " + - "" + - "" + - "
      " ), - button = form.find( "button" ).button(), - checkbox = form.find( "input[type=checkbox]" ).button(); - - checkbox.prop( "checked", false ).button( "refresh" ); - ok( !checkbox.button( "widget" ).hasClass( "ui-state-active" ) ); - - form.get( 0 ).reset(); - - // #9213: If a button has been removed, refresh should not be called on it when - // its corresponding form is reset. - button.remove(); - - setTimeout(function() { - ok( checkbox.button( "widget" ).hasClass( "ui-state-active" )); - start(); - }, 1 ); -}); - -asyncTest( "#6711 Checkbox/Radiobutton do not Show Focused State when using Keyboard Navigation", function() { - expect( 2 ); - var check = $( "#check" ).button(), - label = $( "label[for='check']" ); - ok( !label.is( ".ui-state-focus" ) ); - check.focus(); - setTimeout(function() { - ok( label.is( ".ui-state-focus" ) ); - start(); - }); -}); - -test( "#7534 - Button label selector works for ids with \":\"", function() { - expect( 1 ); - var group = $( "" ); - group.find( "input" ).button(); - ok( group.find( "label" ).is( ".ui-button" ), "Found an id with a :" ); -}); - -asyncTest( "#9169 - Disabled button maintains ui-state-focus", function() { +asyncTest( "Disabled button maintains ui-state-focus", function() { expect( 2 ); var element = $( "#button1" ).button(); - element[ 0 ].focus(); + element.simulate( "focus" ); setTimeout(function() { - ok( element.hasClass( "ui-state-focus" ), "button has ui-state-focus" ); + ok( element.is( ":focus" ), "Button is focused" ); element.button( "disable" ); - ok( !element.hasClass( "ui-state-focus" ), - "button does not have ui-state-focus when disabled" ); + ok( !element.is( ":focus" ), + "Button has had focus removed" ); start(); }); }); diff --git a/tests/unit/button/button_events.js b/tests/unit/button/button_events.js index 2fd03832562..d24aa866660 100644 --- a/tests/unit/button/button_events.js +++ b/tests/unit/button/button_events.js @@ -3,24 +3,16 @@ */ (function($) { -module("button: events"); +module( "Button: events" ); -test("buttonset works with single-quote named elements (#7505)", function() { - expect( 1 ); - $("#radio3").buttonset(); - $("#radio33").click( function(){ - ok( true, "button clicks work with single-quote named elements" ); - }).click(); -}); - -asyncTest( "when button loses focus, ensure active state is removed (#8559)", function() { +asyncTest( "When button loses focus, ensure active state is removed", function() { expect( 1 ); var element = $( "#button" ).button(); element.one( "keypress", function() { element.one( "blur", function() { - ok( !element.is(".ui-state-active"), "button loses active state appropriately" ); + ok( !element.is( ".ui-state-active" ), "button loses active state appropriately" ); start(); }).blur(); }); diff --git a/tests/unit/button/button_methods.js b/tests/unit/button/button_methods.js index 1c781c87e22..4dc1dc525e6 100644 --- a/tests/unit/button/button_methods.js +++ b/tests/unit/button/button_methods.js @@ -4,9 +4,9 @@ (function($) { -module("button: methods"); +module( "Button: methods" ); -test("destroy", function() { +test( "destroy", function() { expect( 1 ); domEqual( "#button", function() { $( "#button" ).button().button( "destroy" ); @@ -49,26 +49,4 @@ test( "refresh: Ensure disabled state is preserved correctly.", function() { ok( !element.button( "option", "disabled" ), "Changing a radio button's disabled property should update the state after refresh."); }); -// #8975 -test( "refresh: buttonset should turn added elements into button widgets", function() { - expect( 2 ); - var radioButtonset = $( "#radio0" ).buttonset(), - checkboxButtonset = $( "#checkbox0" ).buttonset(); - - radioButtonset.append( - "" + - "" - ); - checkboxButtonset.append( - "" + - "" - ); - - radioButtonset.buttonset( "refresh" ); - checkboxButtonset.buttonset( "refresh" ); - - equal( radioButtonset.find( ":ui-button" ).length, 4, "radio" ); - equal( checkboxButtonset.find( ":ui-button" ).length, 4, "checkbox" ); -}); - -})(jQuery); +})(jQuery); \ No newline at end of file diff --git a/tests/unit/button/button_options.js b/tests/unit/button/button_options.js index 834a64dcf2a..36cb574ab7d 100644 --- a/tests/unit/button/button_options.js +++ b/tests/unit/button/button_options.js @@ -25,135 +25,84 @@ test( "disabled, explicit value", function() { deepEqual( element.prop( "disabled" ), true, "element is not disabled" ); }); -test("disabled, null", function() { +test( "disabled, null", function() { expect( 4 ); - $("#radio01").button({ disabled: null }); - deepEqual(false, $("#radio01").button("option", "disabled"), + $( "#radio01" ).button({ disabled: null }); + strictEqual( $("#radio01").button("option", "disabled"), false, "disabled option set to false"); - deepEqual(false, $("#radio01").prop("disabled"), "element is disabled"); + strictEqual( $("#radio01").prop("disabled"), false, "element is disabled"); - $("#radio02").prop("disabled", true).button({ disabled: null }); - deepEqual(true, $("#radio02").button("option", "disabled"), - "disabled option set to true"); - deepEqual(true, $("#radio02").prop("disabled"), "element is not disabled"); + $( "#radio02" ).prop( "disabled", true ).button({ disabled: null }); + deepEqual( true, $( "#radio02" ).button( "option", "disabled" ), + "disabled option set to true" ); + deepEqual( true, $( "#radio02" ).prop( "disabled" ), "element is not disabled" ); }); -test( "disabled, ui-state-active is removed unless checkbox or radio", function() { - expect( 12 ); - var elements = [ - $( "" ), - $( "" ), - $( "" ), - $( "
      " ), - $( "" ), - $( "" ) - ]; - - $.each( elements, function() { - var element = $( this ).first().button(), - buttonElement = element.button( "widget" ), - elementType = element.prop( "nodeName" ).toLowerCase(); - - if ( element.is( "input" ) ) { - elementType += ":" + element.attr( "type" ); - } - - element.trigger( "mousedown" ); - ok( buttonElement.hasClass( "ui-state-active" ), - "[" + elementType + "] has ui-state-active class after mousedown." ); - - element.button( "disable" ); - if ( element.is( "[type=checkbox], [type=radio]" ) ) { - ok( buttonElement.hasClass( "ui-state-active" ), - "Disabled [" + elementType + "] has ui-state-active class." ); - } else { - ok( !buttonElement.hasClass( "ui-state-active" ), - "Disabled [" + elementType + "] does not have ui-state-active class." ); - } - }); -}); - -test("text false without icon", function() { +test( "showLabel false without icon", function() { expect( 1 ); - $("#button").button({ - text: false + $( "#button" ).button({ + showLabel: false }); - ok( $("#button").is(".ui-button-text-only:not(.ui-button-icon-only)") ); + strictEqual( $( "#button" ).attr( "class" ), "ui-button ui-widget ui-corner-all" ); - $("#button").button("destroy"); + $( "#button" ).button( "destroy" ); }); -test("text false with icon", function() { +test("showLabel false with icon", function() { expect( 1 ); $("#button").button({ - text: false, - icons: { - primary: "iconclass" - } + showLabel: false, + icon: "iconclass" }); - ok( $("#button").is(".ui-button-icon-only:not(.ui-button-text):has(span.ui-icon.iconclass)") ); + strictEqual( $( "#button" ).attr( "class" ), "ui-button ui-widget ui-corner-all ui-icon-beginning ui-button-icon-only" ); - $("#button").button("destroy"); + $( "#button" ).button( "destroy" ); }); -test("label, default", function() { +test( "label, default", function() { expect( 2 ); - $("#button").button(); - deepEqual( $("#button").text(), "Label" ); - deepEqual( $( "#button").button( "option", "label" ), "Label" ); + $( "#button" ).button(); + deepEqual( $( "#button" ).text(), "Label" ); + deepEqual( $( "#button" ).button( "option", "label" ), "Label" ); - $("#button").button("destroy"); + $( "#button" ).button( "destroy" ); }); -test("label", function() { +test( "label", function() { expect( 2 ); - $("#button").button({ + $( "#button" ).button({ label: "xxx" }); - deepEqual( $("#button").text(), "xxx" ); - deepEqual( $("#button").button( "option", "label" ), "xxx" ); + deepEqual( $( "#button" ).text(), "xxx" ); + deepEqual( $( "#button" ).button( "option", "label" ), "xxx" ); - $("#button").button("destroy"); + $( "#button" ).button( "destroy" ); }); -test("label default with input type submit", function() { +test( "label default with input type submit", function() { expect( 2 ); - deepEqual( $("#submit").button().val(), "Label" ); - deepEqual( $("#submit").button( "option", "label" ), "Label" ); + deepEqual( $( "#submit" ).button().val(), "Label" ); + deepEqual( $( "#submit" ).button( "option", "label" ), "Label" ); }); -test("label with input type submit", function() { +test( "label with input type submit", function() { expect( 2 ); - var label = $("#submit").button({ + var label = $( "#submit" ).button({ label: "xxx" }).val(); deepEqual( label, "xxx" ); - deepEqual( $("#submit").button( "option", "label" ), "xxx" ); + deepEqual( $( "#submit" ).button( "option", "label" ), "xxx" ); }); -test("icons", function() { +test( "icons", function() { expect( 1 ); $("#button").button({ - text: false, - icons: { - primary: "iconclass", - secondary: "iconclass2" - } + showLabel: false, + icon: "iconclass" }); - ok( $("#button").is(":has(span.ui-icon.ui-button-icon-primary.iconclass):has(span.ui-icon.ui-button-icon-secondary.iconclass2)") ); + strictEqual( $( "#button" ).find( "span.ui-icon.iconclass" ).length, 1 ); - $("#button").button("destroy"); -}); - -test( "#5295 - button does not remove hoverstate if disabled" , function() { - expect( 1 ); - var btn = $("#button").button(); - btn.hover( function() { - btn.button( "disable" ); - }); - btn.trigger( "mouseenter" ); - btn.trigger( "mouseleave" ); - ok( !btn.is( ".ui-state-hover") ); + $( "#button" ).button( "destroy" ); }); })(jQuery); diff --git a/tests/visual/button/button.html b/tests/visual/button/button.html index 3ac055b91b0..36666f743c3 100644 --- a/tests/visual/button/button.html +++ b/tests/visual/button/button.html @@ -14,18 +14,14 @@ $( this ).children() .eq( 0 ) .button({ - text: false, - icons: { - primary: "ui-icon-help" - } + showLabel: false, + icon: "ui-icon-help" }) .end() .eq( 1 ) .button({ - icons: { - primary: "ui-icon-help" - }, - disabled: true + icon: "ui-icon-help", + disabled: false }) .end() .eq( 2 ) @@ -66,24 +62,6 @@
      -
      - - - - - - -
      - -
      - - - - - - -
      -
      anchor anchor diff --git a/themes/base/button.css b/themes/base/button.css index 43ff15cfe43..060ecaff795 100644 --- a/themes/base/button.css +++ b/themes/base/button.css @@ -9,9 +9,9 @@ * http://api.jqueryui.com/button/#theming */ .ui-button { + padding: .4em 1em; display: inline-block; position: relative; - padding: 0; line-height: normal; margin-right: .1em; cursor: pointer; @@ -19,6 +19,7 @@ text-align: center; overflow: visible; /* removes extra width in IE */ } + .ui-button, .ui-button:link, .ui-button:visited, @@ -28,83 +29,110 @@ } /* to make room for the icon, a width needs to be set here */ .ui-button-icon-only { - width: 2.2em; + padding: 0; + height: 2.1em; + text-indent: -9999px; + white-space: nowrap; +} +.ui-icon { + position: absolute; + display: block; } /* button elements seem to need a little more width */ button.ui-button-icon-only { width: 2.4em; } -.ui-button-icons-only { - width: 3.4em; -} -button.ui-button-icons-only { - width: 3.7em; -} -/* button text element */ -.ui-button .ui-button-text { - display: block; - line-height: normal; -} -.ui-button-text-only .ui-button-text { +/* no icon support for input elements, provide padding by default */ +input.ui-button.ui-icon-end, +input.ui-button.ui-icon-beginning, +input.ui-button.ui-icon-top, +input.ui-button.ui-icon-bottom{ padding: .4em 1em; } -.ui-button-icon-only .ui-button-text, -.ui-button-icons-only .ui-button-text { - padding: .4em; - text-indent: -9999999px; +input.ui-button.ui-button-icon-only { + text-indent: 0; } -.ui-button-text-icon-primary .ui-button-text, -.ui-button-text-icons .ui-button-text { - padding: .4em 1em .4em 2.1em; + +/* button icon element(s) */ +.ui-button.ui-icon-end .ui-icon { + left: auto; + right: .5em; } -.ui-button-text-icon-secondary .ui-button-text, -.ui-button-text-icons .ui-button-text { - padding: .4em 2.1em .4em 1em; + +.ui-button.ui-icon-top .ui-icon, +.ui-button.ui-icon-bottom .ui-icon { + left: 50%; + margin-left: -11px; } -.ui-button-text-icons .ui-button-text { - padding-left: 2.1em; - padding-right: 2.1em; + +.ui-button.ui-icon-top .ui-icon { + top: .6em; } -/* no icon support for input elements, provide padding by default */ -input.ui-button { - padding: .4em 1em; + +.ui-button.ui-icon-bottom .ui-icon { + top: auto; + bottom: .05em; } -/* button icon element(s) */ -.ui-button-icon-only .ui-icon, -.ui-button-text-icon-primary .ui-icon, -.ui-button-text-icon-secondary .ui-icon, -.ui-button-text-icons .ui-icon, -.ui-button-icons-only .ui-icon { +.ui-button-icon-only .ui-icon { + left: 50%; + margin-left: -8px; +} + +.ui-button .ui-icon { position: absolute; + display: block; top: 50%; margin-top: -8px; } -.ui-button-icon-only .ui-icon { - left: 50%; - margin-left: -8px; + +.ui-button.ui-icon-beginning { + padding-left: 2.4em; } -.ui-button-text-icon-primary .ui-button-icon-primary, -.ui-button-text-icons .ui-button-icon-primary, -.ui-button-icons-only .ui-button-icon-primary { - left: .5em; + +.ui-button.ui-icon-end { + padding: .4em 2.1em .4em 1em; } -.ui-button-text-icon-secondary .ui-button-icon-secondary, -.ui-button-text-icons .ui-button-icon-secondary, -.ui-button-icons-only .ui-button-icon-secondary { - right: .5em; + +.ui-button.ui-icon-top { + padding: 1.1em 1em .4em 1em; +} + +.ui-button.ui-icon-bottom { + padding: .4em 1em 1.1em 1em; +} + +.ui-button.ui-icon-notext .ui-icon { + padding: 0; + width: 2.1em; + height: 2.1em; + text-indent: -9999px; + white-space: nowrap; + } +input.ui-button.ui-icon-notext .ui-icon { + width: auto; + height: auto; + text-indent: 0; + white-space: normal; + padding: .4em 1em; +} /* button sets */ .ui-buttonset { margin-right: 7px; } -.ui-buttonset .ui-button { - margin-left: 0; - margin-right: -.3em; + +.ui-button.ui-icon-top { + padding: 1.1em 1em .4em 1em; +} + +.ui-button.ui-icon-bottom { + padding: .4em 1em 1.1em 1em; } +>>>>>>> 06cac52... Button: fix css errors /* workarounds */ /* reset extra padding in Firefox, see h5bp.com/l */ input.ui-button::-moz-focus-inner, diff --git a/themes/base/core.css b/themes/base/core.css index b1831c8f8bf..23923550844 100644 --- a/themes/base/core.css +++ b/themes/base/core.css @@ -68,7 +68,6 @@ /* Icons ----------------------------------*/ -/* states and images */ .ui-icon { display: block; text-indent: -99999px; @@ -76,6 +75,35 @@ background-repeat: no-repeat; } +.ui-icon { + left: .5em; + top: .2em; +} + +.ui-icon-end .ui-icon { + left: auto; + right: .5em; +} + +.ui-icon-top .ui-icon, +.ui-icon-bottom .ui-icon { + left: 50%; + margin-left: -11px; +} + +.ui-icon-top .ui-icon { + top: .6em; +} + +.ui-icon-bottom .ui-icon { + top: auto; + bottom: .05em; +} + +.ui-icon-notext .ui-icon { + left: 50%; + margin-left: -8px; +} /* Misc visuals ----------------------------------*/ diff --git a/themes/base/theme.css b/themes/base/theme.css index 2aa74110243..42e88b35475 100644 --- a/themes/base/theme.css +++ b/themes/base/theme.css @@ -50,7 +50,10 @@ ----------------------------------*/ .ui-state-default, .ui-widget-content .ui-state-default, -.ui-widget-header .ui-state-default { +.ui-widget-header .ui-state-default, +.ui-button, +html .ui-button.ui-state-disabled:hover, +html .ui-button.ui-state-disabled:active { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url("images/ui-bg_glass_75_e6e6e6_1x400.png")/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; @@ -58,7 +61,11 @@ } .ui-state-default a, .ui-state-default a:link, -.ui-state-default a:visited { +.ui-state-default a:visited, +a.ui-button, +a:link.ui-button, +a:visited.ui-button, +.ui-button { color: #555555/*{fcDefault}*/; text-decoration: none; } @@ -67,7 +74,9 @@ .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, -.ui-widget-header .ui-state-focus { +.ui-widget-header .ui-state-focus, +.ui-button:hover, +.ui-button:focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url("images/ui-bg_glass_75_dadada_1x400.png")/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; @@ -80,13 +89,17 @@ .ui-state-focus a, .ui-state-focus a:hover, .ui-state-focus a:link, -.ui-state-focus a:visited { +.ui-state-focus a:visited, +a.ui-button:hover, +a.ui-button:focus { color: #212121/*{fcHover}*/; text-decoration: none; } .ui-state-active, .ui-widget-content .ui-state-active, -.ui-widget-header .ui-state-active { +.ui-widget-header .ui-state-active, +a.ui-button:active, +.ui-button:active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url("images/ui-bg_glass_65_ffffff_1x400.png")/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; @@ -168,15 +181,19 @@ .ui-widget-header .ui-icon { background-image: url("images/ui-icons_222222_256x240.png")/*{iconsHeader}*/; } -.ui-state-default .ui-icon { - background-image: url("images/ui-icons_888888_256x240.png")/*{iconsDefault}*/; +.ui-state-default .ui-icon, +.ui-button .ui-icon { + background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; } .ui-state-hover .ui-icon, -.ui-state-focus .ui-icon { - background-image: url("images/ui-icons_454545_256x240.png")/*{iconsHover}*/; -} -.ui-state-active .ui-icon { - background-image: url("images/ui-icons_454545_256x240.png")/*{iconsActive}*/; +.ui-state-focus .ui-icon, +.ui-button:hover .ui-icon, +.ui-button:focus .ui-icon { + background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; +} +.ui-state-active .ui-icon, +.ui-button:active .ui-icon { + background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; } .ui-state-highlight .ui-icon { background-image: url("images/ui-icons_2e83ff_256x240.png")/*{iconsHighlight}*/; diff --git a/ui/button.js b/ui/button.js index 5d502ad51ea..c8b925e5bd0 100644 --- a/ui/button.js +++ b/ui/button.js @@ -24,31 +24,14 @@ } }(function( $ ) { -var lastActive, - baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", - typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only", +var baseClasses = "ui-button ui-widget ui-corner-all", + typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons" + + " ui-button-text-only ui-icon-beginning ui-icon-end ui-icon-top ui-icon-bottom", formResetHandler = function() { var form = $( this ); setTimeout(function() { - form.find( ":ui-button" ).button( "refresh" ); - }, 1 ); - }, - radioGroup = function( radio ) { - var name = radio.name, - form = radio.form, - radios = $( [] ); - if ( name ) { - name = name.replace( /'/g, "\\'" ); - if ( form ) { - radios = $( form ).find( "[name='" + name + "'][type=radio]" ); - } else { - radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument ) - .filter(function() { - return !this.form; - }); - } - } - return radios; + form.find( ".ui-button" ).filter( ":ui-button" ).button( "refresh" ); + }); }; $.widget( "ui.button", { @@ -56,354 +39,161 @@ $.widget( "ui.button", { defaultElement: " - -
      -
        -
      • Open...
      • -
      • Save
      • -
      • Delete
      • -
      -
      - -
      -

      An example of a split button built with two buttons: A plain button with just text, one with only a primary icon -and no text. Both are grouped together in a set.

      -
      - - diff --git a/demos/button/toolbar.html b/demos/button/toolbar.html deleted file mode 100644 index e2eac055c82..00000000000 --- a/demos/button/toolbar.html +++ /dev/null @@ -1,114 +0,0 @@ - - - - - jQuery UI Button - Toolbar - - - - - - - - - - - -
      - - - - - - - - - - - - - - -
      - -
      -

      - A mediaplayer toolbar. Take a look at the underlying markup: A few button elements, - an input of type checkbox for the Shuffle button, and three inputs of type radio for the Repeat options. -

      -
      - - From d443a88de15101ae2190a8e6ca474832e5fc0711 Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Tue, 2 Sep 2014 20:57:22 -0400 Subject: [PATCH 52/73] Button: Adding classes option --- tests/unit/button/button_common.js | 5 +++++ tests/unit/button/button_options.js | 7 ++++--- themes/base/button.css | 30 ----------------------------- ui/button.js | 17 ++++++++++------ 4 files changed, 20 insertions(+), 39 deletions(-) diff --git a/tests/unit/button/button_common.js b/tests/unit/button/button_common.js index c59d4ee909d..4be5db881b3 100644 --- a/tests/unit/button/button_common.js +++ b/tests/unit/button/button_common.js @@ -5,6 +5,11 @@ TestHelpers.commonWidgetTests( "button", { label: null, icon: null, iconPosition: "beginning", + classes: { + "ui-button": "ui-corner-all", + "ui-button-icon-only": "", + "ui-button-icon": "" + }, // Callbacks create: null diff --git a/tests/unit/button/button_options.js b/tests/unit/button/button_options.js index 36cb574ab7d..cf4697a0bee 100644 --- a/tests/unit/button/button_options.js +++ b/tests/unit/button/button_options.js @@ -43,7 +43,8 @@ test( "showLabel false without icon", function() { $( "#button" ).button({ showLabel: false }); - strictEqual( $( "#button" ).attr( "class" ), "ui-button ui-widget ui-corner-all" ); + strictEqual( $( "#button" ).is( ":ui-button.ui-corner-all.ui-widget" ), true, + "Button has correct classes" ); $( "#button" ).button( "destroy" ); }); @@ -54,8 +55,8 @@ test("showLabel false with icon", function() { showLabel: false, icon: "iconclass" }); - strictEqual( $( "#button" ).attr( "class" ), "ui-button ui-widget ui-corner-all ui-icon-beginning ui-button-icon-only" ); - + strictEqual( $( "#button" ).is( ".ui-button.ui-corner-all.ui-widget.ui-button-icon-only" ), + true, "Button has correct classes" ); $( "#button" ).button( "destroy" ); }); diff --git a/themes/base/button.css b/themes/base/button.css index 060ecaff795..8a25e5dba9e 100644 --- a/themes/base/button.css +++ b/themes/base/button.css @@ -103,36 +103,6 @@ input.ui-button.ui-button-icon-only { padding: .4em 1em 1.1em 1em; } -.ui-button.ui-icon-notext .ui-icon { - padding: 0; - width: 2.1em; - height: 2.1em; - text-indent: -9999px; - white-space: nowrap; - -} - -input.ui-button.ui-icon-notext .ui-icon { - width: auto; - height: auto; - text-indent: 0; - white-space: normal; - padding: .4em 1em; -} -/* button sets */ -.ui-buttonset { - margin-right: 7px; -} - -.ui-button.ui-icon-top { - padding: 1.1em 1em .4em 1em; -} - -.ui-button.ui-icon-bottom { - padding: .4em 1em 1.1em 1em; -} - ->>>>>>> 06cac52... Button: fix css errors /* workarounds */ /* reset extra padding in Firefox, see h5bp.com/l */ input.ui-button::-moz-focus-inner, diff --git a/ui/button.js b/ui/button.js index 6518d9c4653..271268f8b72 100644 --- a/ui/button.js +++ b/ui/button.js @@ -42,7 +42,12 @@ $.widget( "ui.button", { showLabel: true, label: null, icon: null, - iconPosition: "beginning" + iconPosition: "beginning", + classes: { + "ui-button": "ui-corner-all", + "ui-button-icon-only": "", + "ui-button-icon": "" + } }, _getCreateOptions: function() { @@ -118,11 +123,11 @@ $.widget( "ui.button", { _updateIcon: function( icon ) { if ( !this.icon ) { - this.icon = $( "" ).addClass( "ui-icon" ); + this.icon = $( "" ).addClass( this._classes( "ui-button-icon" ) + " ui-icon" ); this.element.addClass( "ui-icon-" + this.options.iconPosition ); if ( !this.options.showLabel ){ - this.element.addClass( "ui-button-icon-only" ); + this.element.addClass( this._classes( "ui-button-icon-only" ) ); } } else { this.icon.removeClass( this.options.icon ); @@ -134,7 +139,7 @@ $.widget( "ui.button", { _destroy: function() { this.element - .removeClass( baseClasses + " ui-state-active " + typeClasses ) + .removeClass( this._classes( "ui-button ui-button-icon-only" ) + " " + baseClasses + " ui-state-active " + typeClasses ) .removeAttr( "role" ); if ( this.icon ) { @@ -151,14 +156,14 @@ $.widget( "ui.button", { this._updateIcon( value ); } else { this.icon.remove(); - this.element.removeClass( "ui-icon-" + this.options.iconPosition ); + this.element.removeClass( this._classes( "ui-button-icon" ) + " ui-icon-" + this.options.iconPosition ); } } // Make sure we cant end up with a button that has no text nor icon if ( key === "showLabel" ) { if ( ( !value && !this.options.icon ) || value ) { - this.element.toggleClass( "ui-button-icon-only", !value ) + this.element.toggleClass( this._classes( "ui-button-icon-only" ), !value ) .toggleClass( this.options.iconPosition, !!value ); this._updateTooltip(); } else { From 122c57874a61acd4519e389f062787343208f35a Mon Sep 17 00:00:00 2001 From: Jasper de Groot Date: Thu, 4 Sep 2014 13:14:16 +0200 Subject: [PATCH 53/73] Button: Fixed the height of icon-only buttons in controlgroups --- themes/base/button.css | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/themes/base/button.css b/themes/base/button.css index 8a25e5dba9e..d33965f9539 100644 --- a/themes/base/button.css +++ b/themes/base/button.css @@ -27,21 +27,19 @@ .ui-button:active { text-decoration: none; } + /* to make room for the icon, a width needs to be set here */ .ui-button-icon-only { - padding: 0; - height: 2.1em; + width: 2.2em; + box-sizing: border-box; text-indent: -9999px; white-space: nowrap; } + .ui-icon { position: absolute; display: block; } -/* button elements seem to need a little more width */ -button.ui-button-icon-only { - width: 2.4em; -} /* no icon support for input elements, provide padding by default */ input.ui-button.ui-icon-end, From 8645e0458ffea6cecf0a2b83b65a4323e17a4759 Mon Sep 17 00:00:00 2001 From: Jasper de Groot Date: Mon, 8 Sep 2014 10:20:11 +0200 Subject: [PATCH 54/73] Button: Added user-select none --- themes/base/button.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/themes/base/button.css b/themes/base/button.css index d33965f9539..64ef85f44c7 100644 --- a/themes/base/button.css +++ b/themes/base/button.css @@ -18,6 +18,10 @@ vertical-align: middle; text-align: center; overflow: visible; /* removes extra width in IE */ + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } .ui-button, From 3d650076ca86dd8210610f7b6ce91f5ca02804fb Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Mon, 22 Sep 2014 23:32:20 -0400 Subject: [PATCH 55/73] Button: Fixup from PR Review --- demos/button/default.html | 11 +++++----- demos/button/icons.html | 8 ++++---- ui/button.js | 42 +++++++++++++++++++++++++++++---------- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/demos/button/default.html b/demos/button/default.html index 928a3b4a7b1..f4fdd672284 100644 --- a/demos/button/default.html +++ b/demos/button/default.html @@ -11,11 +11,10 @@ @@ -37,6 +36,8 @@

      CSS Buttons

      Examples of the markup that can be used for buttons: A button element, an input of type submit and an anchor.

      +

      Buttons can be styled via the button widget for by adding the classes yourself to avoid the javascript overhead if you dont need any of the methods provided by the button widget

      p> +

      Here you can see examples of both buttons styled with css only and done using the button widget

      diff --git a/demos/button/icons.html b/demos/button/icons.html index ac7611b98b5..3982ab7fc48 100644 --- a/demos/button/icons.html +++ b/demos/button/icons.html @@ -30,12 +30,9 @@ -
      -

      Some buttons with various combinations of text and icons.

      -

      Widget

      - Button with icon only + Button with icon only @@ -63,6 +60,9 @@

      CSS

      Button with icon on top +
      +
      +

      Some buttons with various combinations of text and icons.

      diff --git a/ui/button.js b/ui/button.js index 271268f8b72..13652fe943c 100644 --- a/ui/button.js +++ b/ui/button.js @@ -24,8 +24,7 @@ } }(function( $ ) { -var baseClasses = "ui-button ui-widget ui-corner-all", - typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons" + +var typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons" + " ui-button-text-only ui-icon-beginning ui-icon-end ui-icon-top ui-icon-bottom", formResetHandler = function() { var form = $( this ); @@ -81,6 +80,7 @@ $.widget( "ui.button", { this.options.disabled = this.element.prop( "disabled" ) || false; } + this.hasTitle = this.element.attr( "title" ); this._enhance(); if ( this.element.is( "a" ) ) { @@ -97,7 +97,9 @@ $.widget( "ui.button", { _enhance: function() { this._setOption( "disabled", this.options.disabled ); - this.element.addClass( baseClasses ).attr( "role", "button" ); + this.element + .addClass( this._classes( "ui-button" ) + " ui-widget" ) + .attr( "role", "button" ); // Check to see if the label needs to be set or if its already correct if ( this.options.label && this.options.label !== this.originalLabel ) { @@ -114,9 +116,8 @@ $.widget( "ui.button", { _updateTooltip: function() { this.title = this.element.attr( "title" ); - this.noTitle = !this.title; - if ( !this.options.showLabel && !this.noTitle ){ + if ( !this.options.showLabel && !this.title ) { this.element.attr( "title", this.options.label ); } }, @@ -124,10 +125,11 @@ $.widget( "ui.button", { _updateIcon: function( icon ) { if ( !this.icon ) { this.icon = $( "" ).addClass( this._classes( "ui-button-icon" ) + " ui-icon" ); - this.element.addClass( "ui-icon-" + this.options.iconPosition ); - if ( !this.options.showLabel ){ + if ( !this.options.showLabel ) { this.element.addClass( this._classes( "ui-button-icon-only" ) ); + } else { + this.element.addClass( "ui-icon-" + this.options.iconPosition ); } } else { this.icon.removeClass( this.options.icon ); @@ -139,7 +141,8 @@ $.widget( "ui.button", { _destroy: function() { this.element - .removeClass( this._classes( "ui-button ui-button-icon-only" ) + " " + baseClasses + " ui-state-active " + typeClasses ) + .removeClass( this._classes( "ui-button ui-button-icon-only" ) + " ui-widget" + + " ui-state-active " + typeClasses ) .removeAttr( "role" ); if ( this.icon ) { @@ -150,17 +153,35 @@ $.widget( "ui.button", { } }, + _elementsFromClassKey: function( classKey ) { + switch ( classKey ) { + case "ui-button-icon-only": + if ( this.options.showLabel ) { + return $(); + } + break; + case "ui-button-icon": + if ( this.icon ) { + return this.icon; + } + return $(); + default: + return this._superApply( arguments ); + } + }, + _setOption: function( key, value ) { if ( key === "icon" ) { if ( value !== null ) { this._updateIcon( value ); } else { this.icon.remove(); - this.element.removeClass( this._classes( "ui-button-icon" ) + " ui-icon-" + this.options.iconPosition ); + this.element.removeClass( this._classes( "ui-button-icon" ) + " ui-icon-" + + this.options.iconPosition ); } } - // Make sure we cant end up with a button that has no text nor icon + // Make sure we can't end up with a button that has no text nor icon if ( key === "showLabel" ) { if ( ( !value && !this.options.icon ) || value ) { this.element.toggleClass( this._classes( "ui-button-icon-only" ), !value ) @@ -177,6 +198,7 @@ $.widget( "ui.button", { if ( this.isInput ) { this.element.val( value ); } else { + // If there us an icon append it else nothing then append the value // this avoids removal of the icon when setting label text this.element.html( !!this.icon ? "" : this.icon ).append( value ); From 259f8aa4642d23311ac304da213b09c3b07c3c3e Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Wed, 22 Oct 2014 11:50:17 -0400 Subject: [PATCH 56/73] Button: backcompat for old button widget --- ui/button.js | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/ui/button.js b/ui/button.js index 13652fe943c..8fe2660fc58 100644 --- a/ui/button.js +++ b/ui/button.js @@ -223,9 +223,84 @@ $.widget( "ui.button", { this._updateTooltip(); } - }); +// DEPRECATED +if ( $.uiBackCompat ) { + + // Text and Icons options + $.widget( "ui.button", $.ui.button, { + options: { + text: true, + icons: { + primary: null, + secondary: null + } + }, + + _create: function() { + if ( this.options.showLabel && !this.options.text ) { + this.options.showLabel = this.options.text; + } + if ( !this.options.icon && ( this.options.icons.primary || + this.options.icons.secondary ) ) { + if ( this.options.icons.primary ) { + this.options.icon = this.options.icons.primary; + } else { + this.options.icon = this.options.icons.secondary; + this.options.iconPosition = "end"; + } + } + this._super(); + }, + + _setOption: function( key, value ) { + if ( key === "text" ) { + this._setOption( "showLabel", value ); + } + if ( key === "icons" ) { + this._setOption( "icon", value ); + if ( value.primary ) { + this._setOption( "icon", value ); + this._setOption( "iconPosition", "beginning" ); + } else if ( value.secondary ) { + this._setOption( "icon", value ); + this._setOption( "iconPosition", "end" ); + } + } + this._superApply( arguments ); + } + }); + $.fn.button = (function( orig ) { + return function() { + if ( this[ 0 ].tagName === "input" && ( this.attr( "type") === "checkbox" || + this.attr( "type" ) === "radio" ) ) { + if ( $.ui.checkboxradio ) { + if ( arguments.length === 0 ) { + return this.checkboxradio({ + "icon": false + }); + } else { + return this.checkboxradio.apply( arguments ); + } + } else { + $.error( "Checkboxradio widget missing" ); + } + } else { + return orig.apply( this, arguments ); + } + }; + })( $.fn.button ); + $.fn.buttonset = function( method, key, value ) { + if ( method === "option" && key === "items" ) { + value = { + "button": value + }; + } + this.controlgroup.call( method, key, value ); + }; +} + return $.ui.button; })); From 737e99aa5e0d4d115dc14625f9de52c8dad50696 Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Fri, 28 Mar 2014 10:48:18 -0400 Subject: [PATCH 57/73] Dialog: Updating dialog and tests for new button API --- tests/unit/dialog/dialog_common_deprecated.js | 2 +- tests/unit/dialog/dialog_deprecated.html | 2 +- tests/unit/dialog/dialog_options.js | 16 +++++++--------- ui/dialog.js | 16 ++++++++-------- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/tests/unit/dialog/dialog_common_deprecated.js b/tests/unit/dialog/dialog_common_deprecated.js index 8a21043ca4b..063318e6d26 100644 --- a/tests/unit/dialog/dialog_common_deprecated.js +++ b/tests/unit/dialog/dialog_common_deprecated.js @@ -17,7 +17,7 @@ TestHelpers.commonWidgetTests( "dialog", { "ui-widget-overlay": "" }, closeOnEscape: true, - closeText: "close", + closeText: "Close", dialogClass: "", disabled: false, draggable: true, diff --git a/tests/unit/dialog/dialog_deprecated.html b/tests/unit/dialog/dialog_deprecated.html index 8cf1f5cf614..75c69f4747a 100644 --- a/tests/unit/dialog/dialog_deprecated.html +++ b/tests/unit/dialog/dialog_deprecated.html @@ -29,7 +29,7 @@ }); - + diff --git a/tests/unit/dialog/dialog_options.js b/tests/unit/dialog/dialog_options.js index 77ca09703a7..008df4bd426 100644 --- a/tests/unit/dialog/dialog_options.js +++ b/tests/unit/dialog/dialog_options.js @@ -154,10 +154,8 @@ test("buttons - advanced", function() { click: function() { equal(this, element[0], "correct context"); }, - icons: { - primary: "ui-icon-cancel" - }, - showText: false + icon: "ui-icon-cancel", + showLabel: false } ] }); @@ -167,8 +165,8 @@ test("buttons - advanced", function() { equal(buttons.attr("id"), "my-button-id", "correct id"); equal(buttons.text(), "a button", "correct label"); ok(buttons.hasClass("additional-class"), "additional classes added"); - deepEqual( buttons.button("option", "icons"), { primary: "ui-icon-cancel", secondary: null } ); - equal( buttons.button( "option", "text" ), false ); + deepEqual( buttons.button("option", "icon"), "ui-icon-cancel" ); + equal( buttons.button( "option", "showLabel" ), false ); buttons.click(); element.remove(); @@ -209,17 +207,17 @@ test("closeText", function() { expect(3); var element = $("
      ").dialog(); - equal(element.dialog("widget").find(".ui-dialog-titlebar-close span").text(), "Close", + equal(element.dialog("widget").find(".ui-dialog-titlebar-close").text(), "Close", "default close text"); element.remove(); element = $("
      ").dialog({ closeText: "foo" }); - equal(element.dialog("widget").find(".ui-dialog-titlebar-close span").text(), "foo", + equal(element.dialog("widget").find(".ui-dialog-titlebar-close").text(), "foo", "closeText on init"); element.remove(); element = $("
      ").dialog().dialog("option", "closeText", "bar"); - equal(element.dialog("widget").find(".ui-dialog-titlebar-close span").text(), "bar", + equal(element.dialog("widget").find(".ui-dialog-titlebar-close").text(), "bar", "closeText via option method"); element.remove(); }); diff --git a/ui/dialog.js b/ui/dialog.js index f9f8e412477..7878ed83fd6 100644 --- a/ui/dialog.js +++ b/ui/dialog.js @@ -416,10 +416,8 @@ $.widget( "ui.dialog", { this.uiDialogTitlebarClose = $( "" ) .button({ label: this.options.closeText, - icons: { - primary: "ui-icon-closethick" - }, - text: false + icon: "ui-icon-closethick", + showLabel: false }) .addClass( this._classes( "ui-dialog-titlebar-close" ) ) .appendTo( this.uiDialogTitlebar ); @@ -485,11 +483,13 @@ $.widget( "ui.dialog", { click.apply( that.element[ 0 ], arguments ); }; buttonOptions = { - icons: props.icons, - text: props.showText + icon: props.icon, + showLabel: props.showLabel, + iconPosition: props.iconPosition }; - delete props.icons; - delete props.showText; + delete props.icon; + delete props.showLabel; + delete props.iconPosition; $( "", props ) .button( buttonOptions ) .appendTo( that.uiButtonSet ); From 33f195954c445c7c953b1fd2979c4af987bf1f3e Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Fri, 22 Aug 2014 16:40:09 -0400 Subject: [PATCH 58/73] Selectmenu: update to use button css This ensures consistency between different form elements --- tests/unit/selectmenu/selectmenu.html | 2 +- tests/unit/selectmenu/selectmenu_methods.js | 2 +- themes/base/selectmenu.css | 19 +------------------ ui/selectmenu.js | 5 ++--- 4 files changed, 5 insertions(+), 23 deletions(-) diff --git a/tests/unit/selectmenu/selectmenu.html b/tests/unit/selectmenu/selectmenu.html index 618eea3d00a..ff26c7be0bd 100644 --- a/tests/unit/selectmenu/selectmenu.html +++ b/tests/unit/selectmenu/selectmenu.html @@ -11,7 +11,7 @@ + + + + + + + +
      +

      Checkbox and radio button widgets

      +

      Checkbox

      + + + + +

      Radio Group

      + + + + + + +
      + +
      +

      Examples of the markup that can be used with checkboxs and radio buttons.

      +
      + + diff --git a/demos/checkboxradio/icon.html b/demos/checkboxradio/icon.html new file mode 100644 index 00000000000..28e266a1668 --- /dev/null +++ b/demos/checkboxradio/icon.html @@ -0,0 +1,45 @@ + + + + + jQuery UI Button - Icon functionality + + + + + + + + + +
      +

      Checkbox and radio button widgets

      +

      Checkbox

      + + + + +

      Radio Group

      + + + + + + +
      + +
      +

      Examples of the markup that can be used with checkboxs and radio buttons.

      +
      + + diff --git a/tests/unit/checkboxradio/checkboxradio.html b/tests/unit/checkboxradio/checkboxradio.html new file mode 100644 index 00000000000..e729e71fdc8 --- /dev/null +++ b/tests/unit/checkboxradio/checkboxradio.html @@ -0,0 +1,85 @@ + + + + + jQuery UI Checkboxradio Test Suite + + + + + + + + + + + + + + + + +
      +
      + +
      + + + +
      +
      +
      + + + +
      +
      +
      +
      + + + +
      +
      +
      +
      + + + +
      +
      + + + + + + + + + + + + + + + + + + + + + + + +
      + + diff --git a/tests/unit/checkboxradio/checkboxradio_common.js b/tests/unit/checkboxradio/checkboxradio_common.js new file mode 100644 index 00000000000..93c74613767 --- /dev/null +++ b/tests/unit/checkboxradio/checkboxradio_common.js @@ -0,0 +1,10 @@ +TestHelpers.commonWidgetTests( "checkboxradio", { + defaults: { + disabled: null, + label: null, + icon: false, + + // Callbacks + create: null + } +}); diff --git a/tests/unit/checkboxradio/checkboxradio_core.js b/tests/unit/checkboxradio/checkboxradio_core.js new file mode 100644 index 00000000000..ffbf5312459 --- /dev/null +++ b/tests/unit/checkboxradio/checkboxradio_core.js @@ -0,0 +1,140 @@ +/* + * checkboxradio_core.js + */ + + +(function($) { + +module("Checkboxradio: core"); +test("Checkbox", function() { + expect( 4 ); + var input = $("#check"), + label = $("label[for=check]"); + ok( input.is( ":visible" ) ); + ok( !label.hasClass(".ui-button)") ); + input.checkboxradio(); + strictEqual( input.attr( "class" ), "ui-helper-hidden-accessible ui-checkboxradio" ); + strictEqual( label.attr( "class" ), "ui-button ui-widget ui-corner-all ui-checkbox-label" ); +}); + +test("Radios", function() { + expect( 4 ); + var inputs = $("#radio0 input"), + labels = $("#radio0 label"); + ok( inputs.is(":visible") ); + ok( labels.is(":not(.ui-button)") ); + inputs.checkboxradio(); + ok( inputs.is(".ui-helper-hidden-accessible") ); + ok( labels.is(".ui-button") ); +}); + +function assert(noForm, form1, form2) { + ok( $("#radio0 .ui-button" + noForm).is(".ui-state-active") ); + ok( $("#radio1 .ui-button" + form1).is(".ui-state-active") ); + ok( $("#radio2 .ui-button" + form2).is(".ui-state-active") ); +} + +test("radio groups", function() { + expect( 12 ); + $("input[type=radio]").checkboxradio(); + assert(":eq(0)", ":eq(1)", ":eq(2)"); + + // click outside of forms + $("#radio0 .ui-button:eq(1)").simulate("click"); + assert(":eq(1)", ":eq(1)", ":eq(2)"); + + // click in first form + $("#radio1 .ui-button:eq(0)").simulate("click"); + assert(":eq(1)", ":eq(0)", ":eq(2)"); + + // click in second form + $("#radio2 .ui-button:eq(0)").simulate("click"); + assert(":eq(1)", ":eq(0)", ":eq(0)"); +}); + +asyncTest( "Checkbox/Radiobutton do not Show Focused State when using Keyboard Navigation", function() { + expect( 2 ); + var check = $( "#check" ).checkboxradio(), + label = $( "label[for='check']" ); + ok( !label.is( ".ui-state-focus" ) ); + check.focus(); + setTimeout(function() { + ok( label.is( ".ui-state-focus" ) ); + start(); + }); +}); + +// TODO: simulated click events don't behave like real click events in IE +// remove this when simulate properly simulates this +// see http://yuilibrary.com/projects/yui2/ticket/2528826 fore more info +if ( !$.ui.ie || ( document.documentMode && document.documentMode > 8 ) ) { + asyncTest( "Ensure checked after single click on checkbox label button", function() { + expect( 2 ); + + $( "#check2" ).checkboxradio().change( function() { + var label = $( this ).checkboxradio( "widget" ); + ok( this.checked, "checked ok" ); + + // The following test is commented out for now because with new markup we are trying to avoid aria + //ok( lbl.attr("aria-pressed") === "true", "aria ok" ); + ok( label.hasClass( "ui-state-active" ), "ui-state-active ok" ); + }); + + // Support: Opera + // Opera doesn't trigger a change event when this is done synchronously. + // This seems to be a side effect of another test, but until that can be + // tracked down, this delay will have to do. + setTimeout(function() { + $( "#check2" ).checkboxradio( "widget" ).simulate( "click" ); + start(); + }, 1 ); + }); +} +test( "Checkbox creation that requires a matching label does not find label in all cases", function() { + expect( 5 ); + var group = $( "" ); + group.find( "input[type=checkbox]" ).checkboxradio(); + ok( group.find( "label" ).is( ".ui-button" ) ); + + group = $( "" ); + group.filter( "input[type=checkbox]" ).checkboxradio(); + ok( group.filter( "label" ).is( ".ui-button" ) ); + + group = $( "" ); + group.find( "input[type=checkbox]" ).checkboxradio(); + ok( group.filter( "label" ).is( ".ui-button" ) ); + + group = $( "" ); + group.find( "input[type=checkbox]" ).checkboxradio(); + ok( group.find( "label" ).is( ".ui-button" ) ); + + group = $( "" ); + group.filter( "input[type=checkbox]" ).checkboxradio(); + ok( group.find( "label" ).is( ".ui-button" ) ); +}); + +asyncTest( "Resetting a button's form should refresh the visual state of the button widget to match.", function() { + expect( 2 ); + var form = $( "
      " + + "" + + "
      " ), + checkbox = form.find( "input[type=checkbox]" ).checkboxradio(); + + checkbox.prop( "checked", false ).checkboxradio( "refresh" ); + ok( !checkbox.checkboxradio( "widget" ).hasClass( "ui-state-active" ) ); + + form.get( 0 ).reset(); + + setTimeout(function() { + ok( checkbox.checkboxradio( "widget" ).hasClass( "ui-state-active" )); + start(); + }, 1 ); +}); +test( "Checkbox label selector works for ids with \":\"", function() { + expect( 1 ); + var group = $( "" ); + group.find( "input" ).checkboxradio(); + ok( group.find( "label" ).is( ".ui-button" ), "Found an id with a :" ); +}); + +})(jQuery); diff --git a/tests/unit/checkboxradio/checkboxradio_methods.js b/tests/unit/checkboxradio/checkboxradio_methods.js new file mode 100644 index 00000000000..bcec6d9f059 --- /dev/null +++ b/tests/unit/checkboxradio/checkboxradio_methods.js @@ -0,0 +1,131 @@ +/* + * checkboxradio_methods.js + */ + + +(function($) { + +module( "Checkboxradio: methods" ); + test( "Checkbox: refresh", function() { + var checkbox = $( "#checkbox-method-refresh" ), + widget; + expect( 2 ); + checkbox.checkboxradio({ + icon: true + }); + + widget = checkbox.checkboxradio( "widget" ); + delete $(".ui-icon" )[0]; + + checkbox.checkboxradio( "refresh" ); + strictEqual( widget.find( ".ui-icon" ).length, 1, "Icon is recreated on refresh" ); + checkbox.prop( "checked", true ); + checkbox.checkboxradio( "refresh" ); + strictEqual( widget.hasClass( "ui-checkbox-checked" ), true, + "State updated based on checked property" ); + }); + + test( "Checkbox: destroy", function(){ + var checkbox = $( "#checkbox-method-destroy" ), + checkboxClasses = checkbox.attr( "class" ), + label = $( "#checkbox-method-destroy-label" ), + labelClasses = label.attr( "class" ); + + expect( 2 ); + checkbox.checkboxradio(); + checkbox.checkboxradio( "destroy" ); + strictEqual( checkbox.attr( "class"), checkboxClasses, + "checkbox classes match original after destroy" ); + strictEqual( label.attr( "class"), labelClasses, + "label classes match original after destroy" ); + }); + + test( "Checkbox: disable / enable", function(){ + var checkbox = $( "#checkbox-method-disable" ); + + expect( 4 ); + checkbox.checkboxradio(); + checkbox.checkboxradio( "disable" ); + strictEqual( checkbox.checkboxradio( "widget" ).hasClass( "ui-state-disabled" ), true, + "label gets ui-state-disabled when disable is called" ); + strictEqual( checkbox.is( ":disabled" ), true, + "checkbox is disabled when disable is called" ); + checkbox.checkboxradio( "enable" ); + strictEqual( checkbox.checkboxradio( "widget" ).hasClass( "ui-state-disabled" ), false, + "label has ui-state-disabled removed when enable is called" ); + strictEqual( checkbox.is( ":disabled" ), false, + "checkbox has disabled prop removed when enable is called" ); + }); + test( "Checkbox: widget returns the label", function(){ + var checkbox = $( "#checkbox-method-refresh" ), + label = $( "#checkbox-method-refresh-label" ); + + expect( 1 ); + + checkbox.checkboxradio(); + strictEqual( checkbox.checkboxradio( "widget" ).attr( "id" ), label.attr( "id" ), + "widget method returns label" ); + }); + + test( "Radio: refresh", function() { + var radio = $( "#radio-method-refresh" ), + widget; + expect( 2 ); + radio.checkboxradio({ + icon: true + }); + + widget = radio.checkboxradio( "widget" ); + delete $(".ui-icon" )[0]; + + radio.checkboxradio( "refresh" ); + strictEqual( widget.find( ".ui-icon" ).length, 1, "Icon is recreated on refresh" ); + radio.prop( "checked", true ); + radio.checkboxradio( "refresh" ); + strictEqual( widget.hasClass( "ui-radio-checked" ), true, + "State updated based on checked property" ); + }); + + test( "Radio: destroy", function(){ + var radio = $( "#radio-method-destroy" ), + radioClasses = radio.attr( "class" ), + label = $( "#radio-method-destroy-label" ), + labelClasses = label.attr( "class" ); + + expect( 2 ); + radio.checkboxradio(); + radio.checkboxradio( "destroy" ); + strictEqual( radio.attr( "class"), radioClasses, + "radio classes match original after destroy" ); + strictEqual( label.attr( "class"), labelClasses, + "label classes match original after destroy" ); + }); + + test( "Radio: disable / enable", function(){ + var radio = $( "#checkbox-method-disable" ); + + expect( 4 ); + radio.checkboxradio(); + radio.checkboxradio( "disable" ); + strictEqual( radio.checkboxradio( "widget" ).hasClass( "ui-state-disabled" ), true, + "label gets ui-state-disabled when disable is called" ); + strictEqual( radio.is( ":disabled" ), true, + "radio is disabled when disable is called" ); + radio.checkboxradio( "enable" ); + strictEqual( radio.checkboxradio( "widget" ).hasClass( "ui-state-disabled" ), false, + "label has ui-state-disabled removed when enable is called" ); + strictEqual( radio.is( ":disabled" ), false, + "radio has disabled prop removed when enable is called" ); + }); + test( "Radio: widget returns the label", function(){ + var radio = $( "#radio-method-refresh" ), + label = $( "#radio-method-refresh-label" ); + + expect( 1 ); + + radio.checkboxradio(); + strictEqual( radio.checkboxradio( "widget" ).attr( "id" ), label.attr( "id" ), + "widget method returns label" ); + }); + +})(jQuery); diff --git a/tests/unit/checkboxradio/checkboxradio_options.js b/tests/unit/checkboxradio/checkboxradio_options.js new file mode 100644 index 00000000000..b372e267064 --- /dev/null +++ b/tests/unit/checkboxradio/checkboxradio_options.js @@ -0,0 +1,173 @@ +/* + * checkboxradio_methods.js + */ + + +(function($) { + +module( "Checkboxradio: checkbox: options" ); + test( "options: disabled", function() { + var checkbox = $( "#checkbox-option-disabled" ), + widget; + expect( 10 ); + checkbox.checkboxradio({ + disabled: true + }); + + widget = checkbox.checkboxradio( "widget" ); + + strictEqual( widget.hasClass( "ui-state-disabled" ), true, + "label gets ui-state-disabled when initial option set to true" ); + strictEqual( checkbox.is( ":disabled" ), true, + "checkbox is disabled when inital option is set to true" ); + + checkbox.checkboxradio( "option", "disabled", false ); + + strictEqual( widget.hasClass( "ui-state-disabled" ), false, + "label has ui-state-disabled removed when disabled set to false" ); + strictEqual( checkbox.is( ":disabled" ), false, + "checkbox has disabled prop removed when disabled set to false" ); + + checkbox.checkboxradio( "option", "disabled", true ); + + strictEqual( widget.hasClass( "ui-state-disabled" ), true, + "label gets ui-state-disabled when option set to true" ); + strictEqual( checkbox.is( ":disabled" ), true, + "checkbox is disabled when option is set to true" ); + + checkbox.checkboxradio( "destroy" ); + checkbox.prop( "disabled", true ); + checkbox.checkboxradio(); + + strictEqual( widget.hasClass( "ui-state-disabled" ), true, + "label gets ui-state-disabled when checkbox is disabled in dom on startup" ); + strictEqual( checkbox.is( ":disabled" ), true, + "checkbox is disabled when checkbox is disabled in dom on startup" ); + + checkbox.checkboxradio( "destroy" ); + checkbox.checkboxradio({ + disabled: null + }); + + strictEqual( widget.hasClass( "ui-state-disabled" ), true, + "passing null to disabled on startup checks the dom" ); + strictEqual( checkbox.is( ":disabled" ), true, + "passing null to disabled on startup checks the dom" ); + }); + test( "options: icon", function() { + var checkbox = $( "#checkbox-option-icon" ), + widget; + + expect( 9 ); + + checkbox.checkboxradio(); + + widget = checkbox.checkboxradio( "widget" ); + + strictEqual( widget.find( "span" ).length, 0, + "Label does not contain a span when created with icon:false" ); + + checkbox.checkboxradio( "destroy" ); + + checkbox.checkboxradio({ + icon: true + }); + + strictEqual( widget.find( "span" ).length, 1, + "Label contains a span when created with icon:true" ); + strictEqual( widget.find( "span" ).attr( "class" ), + "ui-icon ui-icon-background ui-corner-all ui-icon-blank", + "Icon span has proper classes when created not checked" ); + + checkbox.checkboxradio( "destroy" ).prop( "checked", true ); + + checkbox.checkboxradio({ + icon: true + }); + + strictEqual( widget.find( "span" ).attr( "class" ), + "ui-icon ui-icon-background ui-corner-all ui-icon-check", + "Icon span has proper classes when created checked" ); + + checkbox.checkboxradio( "option", "icon", false ); + + strictEqual( widget.find( "span" ).length, 0, + "Label does not contain a span when option set to icon:false and checked" ); + + checkbox.checkboxradio( "option", "icon", true ); + + strictEqual( widget.find( "span" ).attr( "class" ), + "ui-icon ui-icon-background ui-corner-all ui-icon-check", + "Icon span has proper classes when option set to true and :is( checked )" ); + + checkbox.prop( "checked", false ).checkboxradio( "refresh" ); + checkbox.checkboxradio( "option", "icon", false ); + + strictEqual( widget.find( "span" ).length, 0, + "Label does not contain a span when option set to icon:false and not checked" ); + + checkbox.checkboxradio( "option", "icon", true ); + + strictEqual( widget.find( "span" ).attr( "class" ), + "ui-icon ui-icon-background ui-corner-all ui-icon-blank", + "Icon span has proper classes when option set to true and not checked" ); + + checkbox.checkboxradio( "destroy" ); + + strictEqual( widget.find( "span" ).length, 0, + "Label does not contain a span after destroy when icon true" ); + + }); + test( "options: label", function() { + var checkbox = $( "#checkbox-option-label" ), + widget; + + expect( 10 ); + + checkbox.checkboxradio(); + + widget = checkbox.checkboxradio( "widget" ); + + strictEqual( checkbox.checkboxradio( "option", "label" ), + "checkbox label", "When no value passed on create text from dom is used for option" ); + strictEqual( widget.text(), + "checkbox label", "When no value passed on create text from dom is used in dom" ); + + checkbox.checkboxradio( "destroy" ); + + checkbox.checkboxradio({ + label: "foo" + }); + + strictEqual( checkbox.checkboxradio( "option", "label" ), + "foo", "When value is passed on create value is used for option" ); + strictEqual( widget.text(), + "foo", "When value is passed on create value is used in dom" ); + + checkbox.checkboxradio( "destroy" ); + checkbox.checkboxradio({ + label: null + }); + + strictEqual( checkbox.checkboxradio( "option", "label" ), + "foo", "When null is passed on create text from dom is used for option" ); + strictEqual( widget.text(), + "foo", "When null is passed on create text from dom is used in dom" ); + + checkbox.checkboxradio( "option", "label", "bar" ); + + strictEqual( checkbox.checkboxradio( "option", "label" ), + "bar", "When value is passed value is used for option" ); + strictEqual( widget.text(), + "bar", "When value is passed value is used in dom" ); + + checkbox.checkboxradio( "option", "label", null ); + + strictEqual( checkbox.checkboxradio( "option", "label" ), + "bar", "When null is passed text from dom is used for option" ); + strictEqual( widget.text(), + "bar", "When null is passed text from dom is used in dom" ); + + }); + +})(jQuery); diff --git a/tests/unit/controlgroup/controlgroup_core.js b/tests/unit/controlgroup/controlgroup_core.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/unit/index.html b/tests/unit/index.html index bd48590ec37..21a00d7e8be 100644 --- a/tests/unit/index.html +++ b/tests/unit/index.html @@ -40,6 +40,7 @@

      Widgets

    • Accordion
    • Autocomplete
    • Button
    • +
    • Checkboxradio
    • Datepicker
    • Dialog
    • Menu
    • diff --git a/tests/visual/checkboxradio/checkbox.html b/tests/visual/checkboxradio/checkbox.html new file mode 100644 index 00000000000..f3db979dda0 --- /dev/null +++ b/tests/visual/checkboxradio/checkbox.html @@ -0,0 +1,70 @@ + + + + + jQuery UI Button - Checkboxes + + + + + + + + + + + +
      + css for new checkbox widget +
      +
      + + + + + + + + +
      +
      + + + + + + + + +
      + + diff --git a/themes/base/base.css b/themes/base/base.css index 479c3279d9b..be4508284a2 100644 --- a/themes/base/base.css +++ b/themes/base/base.css @@ -13,6 +13,7 @@ @import url("accordion.css"); @import url("autocomplete.css"); @import url("button.css"); +@import url("checkboxradio.css"); @import url("datepicker.css"); @import url("dialog.css"); @import url("draggable.css"); diff --git a/themes/base/checkboxradio.css b/themes/base/checkboxradio.css new file mode 100644 index 00000000000..7e90394df5d --- /dev/null +++ b/themes/base/checkboxradio.css @@ -0,0 +1,40 @@ +/*! + * jQuery UI Checkboxradio @VERSION + * http://jqueryui.com + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/checkboxradio/#theming + */ + +.ui-checkbox { + display: none; +} +.ui-checkbox-label .ui-icon-background { + border-radius: .12em; + border: none; +} +.ui-radio-label .ui-icon.ui-icon-background { + width: 16px; + height: 16px; + border-radius: 1em; + overflow: visible; + border: none; + background-color: rgb( 0, 0, 0 ); + background-color: rgba( 0, 0, 0, .3 ); + opacity: .3; +} +.ui-radio-label.ui-radio-checked .ui-icon, +.ui-radio-label.ui-radio-checked:hover .ui-icon { + background-image: none; + background-color: #fff; + width: 8px; + height: 8px; + border-width: 4px; + border-style: solid; +} +.ui-checkboxradio-disabled { + pointer-events: none; +} diff --git a/themes/base/core.css b/themes/base/core.css index 23923550844..05186d086f5 100644 --- a/themes/base/core.css +++ b/themes/base/core.css @@ -77,7 +77,7 @@ .ui-icon { left: .5em; - top: .2em; + top: .3em; } .ui-icon-end .ui-icon { diff --git a/themes/base/theme.css b/themes/base/theme.css index 42e88b35475..a53577c203b 100644 --- a/themes/base/theme.css +++ b/themes/base/theme.css @@ -59,6 +59,9 @@ html .ui-button.ui-state-disabled:active { font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; } +.ui-state-active .ui-icon-background { + background-color: #e6e6e6/*{bgColorDefault}*/; +} .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited, @@ -99,12 +102,16 @@ a.ui-button:focus { .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active, a.ui-button:active, -.ui-button:active { +.ui-button:active, +.ui-button.ui-state-active:hover { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url("images/ui-bg_glass_65_ffffff_1x400.png")/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; } +.ui-icon-background { + background-color: #ffffff/*{bgColorActive}*/; +} .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { diff --git a/ui/checkboxradio.js b/ui/checkboxradio.js new file mode 100644 index 00000000000..684f8fbcca2 --- /dev/null +++ b/ui/checkboxradio.js @@ -0,0 +1,271 @@ +/*! + * jQuery UI Checkboxradio @VERSION + * http://jqueryui.com + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/checkboxradio/ + */ +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + + // AMD. Register as an anonymous module. + define([ + "jquery", + "./core", + "./widget" + ], factory ); + } else { + + // Browser globals + factory( jQuery ); + } +}(function( $ ) { + +var baseClasses = "ui-button ui-widget ui-corner-all", + typeClasses = " ui-icon ui-icon-background ui-state-focus ui-icon-check ui-icon-blank" + + " ui-radio-label ui-checkbox-label ui-state-active ui-icon-beginning ui-icon-end" + + " ui-icon-top ui-icon-bottom ui-radio-checked ui-checkbox-checked", + formResetHandler = function() { + var form = $( this ); + setTimeout(function() { + form.find( ".ui-checkboxradio" ).checkboxradio( "refresh" ); + }); + }, + radioGroup = function( radio ) { + var name = radio.name, + form = radio.form, + radios = $( [] ); + if ( name ) { + name = name.replace( /'/g, "\\'" ); + if ( form ) { + radios = $( form ).find( "[name='" + name + "']" ); + } else { + radios = $( "[name='" + name + "']", radio.ownerDocument ) + .filter(function() { + return !this.form; + }); + } + } + return radios; + }; + +$.widget( "ui.checkboxradio", { + version: "@VERSION", + defaultElement: "", + options: { + disabled: null, + label: null, + icon: false + }, + + _getCreateOptions: function() { + var options = {}; + + this._readLabel(); + + this.originalLabel = this.label.html(); + + this._readDisabled( options ); + + if ( this.originalLabel ) { + options.label = this.originalLabel; + } + + return options; + }, + + _readDisabled: function( options ) { + var isDisabled = this.element.prop( "disabled" ); + + if ( isDisabled !== undefined ) { + options.disabled = isDisabled; + } else { + options.disabled = false; + } + }, + + _create: function() { + var formElement = $( this.element[ 0 ].form ); + + // We don't use _on and _off here because we want all the checkboxes in the same form to use + // single handler which handles all the checkboxradio widgets in the form + formElement.off( "reset" + this.eventNamespace, formResetHandler ); + formElement.on( "reset" + this.eventNamespace, formResetHandler ); + + // If the option is a boolean its been set by either user or by + // _getCreateOptions so we need to make sure the prop matches + // If it is not a boolean the user set it explicitly to null so we need to check the dom + if ( typeof this.options.disabled === "boolean" ) { + this.element.prop( "disabled", this.options.disabled ); + } else { + this._readDisabled( this.options ); + } + + // If the option is true we call set options to add the disabled + // classes and ensure the element is not focused + if ( this.options.disabled === true ){ + this._setOption( "disabled", true ); + } + + this._readType(); + + this._enhance(); + + this._on({ + "change": "_toggleClasses", + "focus": function() { + this.label.addClass( "ui-state-focus" ); + }, + "blur": function() { + this.label.removeClass( "ui-state-focus" ); + } + }); + }, + + _readType: function() { + this.type = this.element[ 0 ].type; + if ( !/radio|checkbox/.test( this.type ) ) { + throw new Error( "Can't create checkboxradio widget for type " + this.type ); + } + }, + + _readLabel: function() { + var ancestor, labelSelector, + labels = this.element[ 0 ].labels; + + // Check control.labels first + if ( labels !== undefined && labels.length > 0 ) { + this.label = $( labels[ 0 ] ); + } else { + + // We don't search against the document in case the element + // is disconnected from the DOM + ancestor = this.element.parents().last(); + + // Look for the label based on the id + labelSelector = "label[for='" + this.element.attr( "id" ) + "']"; + this.label = ancestor.find( labelSelector ); + if ( !this.label.length ) { + + // The label was not found make sure ancestors exist if they do check their siblings + // if they dont check the elements siblings + ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); + + // Check if any of the new set of ancestors is the label + this.label = ancestor.filter( labelSelector ); + if ( !this.label.length ) { + + // Still not found look inside the ancestors for the label + this.label = ancestor.find( labelSelector ); + } + } + } + }, + + _enhance: function() { + var checked = this.element.is( ":checked" ); + + this._updateIcon( checked ); + this.element.addClass( "ui-helper-hidden-accessible ui-checkboxradio" ); + + this.label.addClass( baseClasses + " ui-" + this.type + "-label" ); + + if ( checked ) { + this.label.addClass( "ui-" + this.type + "-checked ui-state-active" ); + } + if ( this.options.label && this.options.label !== this.originalLabel ) { + this.label.html( this.icon ? this.icon : "" ).append( this.options.label ); + } else if ( this.originalLabel ) { + this.options.label = this.originalLabel; + } + }, + + widget: function() { + return this.label; + }, + + _toggleClasses: function() { + var checked = this.element.is( ":checked" ); + this.label.toggleClass( "ui-" + this.type + "-checked ui-state-active", checked ); + if ( this.options.icon && this.type === "checkbox" ) { + this.icon + .toggleClass( "ui-icon-check", checked ) + .toggleClass( "ui-icon-blank", !checked ); + } + if ( this.type === "radio" ) { + radioGroup( this.element[0] ) + .not( this.element ) + .map(function() { + return $( this ).checkboxradio( "widget" )[ 0 ]; + }) + .removeClass( "ui-state-active ui-radio-checked" ); + } + }, + + _destroy: function() { + this.label.removeClass( baseClasses + " " + typeClasses ); + if ( this.icon ) { + this.icon.remove(); + } + this.element.removeClass( "ui-checkboxradio ui-helper-hidden-accessible" ); + }, + + _setOption: function( key, value ) { + var original; + if ( key === "label" && value === null ) { + original = this.options[ key ]; + } + this._super( key, value ); + if ( key === "disabled" ) { + this.label.toggleClass( "ui-state-disabled", !!value ); + this.element.prop( "disabled", !!value ); + return; + } + if ( key === "label" && value === null ) { + this.options[ key ] = original; + } + this.refresh(); + }, + + _updateIcon: function( checked ) { + var toAdd = "ui-icon ui-icon-background ui-corner-all "; + + if ( this.options.icon ) { + this.label.addClass( "ui-icon-beginning" ); + if ( !this.icon ){ + this.icon = $( "" ); + } + + if ( this.type === "checkbox" ) { + toAdd += checked ? "ui-icon-check" : "ui-icon-blank"; + } + this.icon.addClass( toAdd ).appendTo( this.label ); + } else if ( this.icon !== undefined ) { + this.label.removeClass( "ui-icon-beginning" ); + this.icon.remove(); + delete this.icon; + } + }, + + refresh: function() { + var checked = this.element.is( ":checked" ), + isDisabled = this.element.is( ":disabled" ); + this._updateIcon( checked ); + this.label.toggleClass( "ui-state-active ui-" + this.type + "-checked", checked ); + if ( this.options.label !== null ) { + this.label.html( !!this.icon ? this.icon : "" ).append( this.options.label ); + } + + if ( isDisabled !== this.options.disabled ) { + this._setOptions({ "disabled": isDisabled }); + } + } + +}); + +return $.ui.checkboxradio; + +})); From cbd6e0363c880dc631f510808d44115ac6634b48 Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Wed, 23 Jul 2014 22:11:03 -0400 Subject: [PATCH 61/73] Checkboxradio: add visual focus outline to checkbox and radio buttons This adds a focus outline matching that roughly from chrome osx --- themes/base/theme.css | 3 +++ ui/checkboxradio.js | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/themes/base/theme.css b/themes/base/theme.css index a53577c203b..eebefd357c5 100644 --- a/themes/base/theme.css +++ b/themes/base/theme.css @@ -98,6 +98,9 @@ a.ui-button:focus { color: #212121/*{fcHover}*/; text-decoration: none; } +.ui-visual-focus { + box-shadow: 0 0 3px 1px rgb(94, 158, 214); +} .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active, diff --git a/ui/checkboxradio.js b/ui/checkboxradio.js index 684f8fbcca2..965ee2952b6 100644 --- a/ui/checkboxradio.js +++ b/ui/checkboxradio.js @@ -117,10 +117,10 @@ $.widget( "ui.checkboxradio", { this._on({ "change": "_toggleClasses", "focus": function() { - this.label.addClass( "ui-state-focus" ); + this.label.addClass( "ui-state-focus ui-visual-focus" ); }, "blur": function() { - this.label.removeClass( "ui-state-focus" ); + this.label.removeClass( "ui-state-focus ui-visual-focus" ); } }); }, From 80cb6e74f91711f20723240df52a011d5f921135 Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Wed, 23 Jul 2014 12:51:42 -0400 Subject: [PATCH 62/73] Checkboxradio: allow the parent of the input to be the label Conflicts: ui/checkboxradio.js --- tests/unit/checkboxradio/checkboxradio.html | 3 + .../unit/checkboxradio/checkboxradio_core.js | 8 ++- .../checkboxradio/checkboxradio_methods.js | 13 ++++- .../checkboxradio/checkboxradio_options.js | 12 ++-- tests/visual/checkboxradio/checkbox.html | 5 +- ui/checkboxradio.js | 57 +++++++++++++------ 6 files changed, 68 insertions(+), 30 deletions(-) diff --git a/tests/unit/checkboxradio/checkboxradio.html b/tests/unit/checkboxradio/checkboxradio.html index e729e71fdc8..e101da5c320 100644 --- a/tests/unit/checkboxradio/checkboxradio.html +++ b/tests/unit/checkboxradio/checkboxradio.html @@ -80,6 +80,9 @@ +
      diff --git a/tests/unit/checkboxradio/checkboxradio_core.js b/tests/unit/checkboxradio/checkboxradio_core.js index ffbf5312459..843fc3ff5f1 100644 --- a/tests/unit/checkboxradio/checkboxradio_core.js +++ b/tests/unit/checkboxradio/checkboxradio_core.js @@ -90,8 +90,8 @@ if ( !$.ui.ie || ( document.documentMode && document.documentMode > 8 ) ) { }, 1 ); }); } -test( "Checkbox creation that requires a matching label does not find label in all cases", function() { - expect( 5 ); +test( "Checkbox creation that requires a matching finds label in all cases", function() { + expect( 6 ); var group = $( "" ); group.find( "input[type=checkbox]" ).checkboxradio(); ok( group.find( "label" ).is( ".ui-button" ) ); @@ -111,6 +111,10 @@ test( "Checkbox creation that requires a matching label does not find label in a group = $( "" ); group.filter( "input[type=checkbox]" ).checkboxradio(); ok( group.find( "label" ).is( ".ui-button" ) ); + + group = $( "" ); + group.find( "input[type=checkbox]" ).checkboxradio(); + ok( group.find( "label" ).is( ".ui-button" ) ); }); asyncTest( "Resetting a button's form should refresh the visual state of the button widget to match.", function() { diff --git a/tests/unit/checkboxradio/checkboxradio_methods.js b/tests/unit/checkboxradio/checkboxradio_methods.js index bcec6d9f059..ee96f556a43 100644 --- a/tests/unit/checkboxradio/checkboxradio_methods.js +++ b/tests/unit/checkboxradio/checkboxradio_methods.js @@ -40,7 +40,7 @@ module( "Checkboxradio: methods" ); "label classes match original after destroy" ); }); - test( "Checkbox: disable / enable", function(){ + test( "Checkbox: disable / enable", function() { var checkbox = $( "#checkbox-method-disable" ); expect( 4 ); @@ -101,7 +101,7 @@ module( "Checkboxradio: methods" ); "label classes match original after destroy" ); }); - test( "Radio: disable / enable", function(){ + test( "Radio: disable / enable", function() { var radio = $( "#checkbox-method-disable" ); expect( 4 ); @@ -127,5 +127,14 @@ module( "Checkboxradio: methods" ); strictEqual( radio.checkboxradio( "widget" ).attr( "id" ), label.attr( "id" ), "widget method returns label" ); }); + test( "Input wrapped in a label preserved on refresh", function() { + var input = $( "#label-with-no-for" ).checkboxradio(), + element = input.checkboxradio( "widget" ); + + expect( 1 ); + + input.checkboxradio( "refresh" ); + strictEqual( input.parent().is( element ), true, "Input preserved" ); + }); })(jQuery); diff --git a/tests/unit/checkboxradio/checkboxradio_options.js b/tests/unit/checkboxradio/checkboxradio_options.js index b372e267064..49c28fb6502 100644 --- a/tests/unit/checkboxradio/checkboxradio_options.js +++ b/tests/unit/checkboxradio/checkboxradio_options.js @@ -1,4 +1,4 @@ -/* +-/* * checkboxradio_methods.js */ @@ -130,7 +130,7 @@ module( "Checkboxradio: checkbox: options" ); strictEqual( checkbox.checkboxradio( "option", "label" ), "checkbox label", "When no value passed on create text from dom is used for option" ); - strictEqual( widget.text(), + strictEqual( widget.contents().not( this.element ), "checkbox label", "When no value passed on create text from dom is used in dom" ); checkbox.checkboxradio( "destroy" ); @@ -141,7 +141,7 @@ module( "Checkboxradio: checkbox: options" ); strictEqual( checkbox.checkboxradio( "option", "label" ), "foo", "When value is passed on create value is used for option" ); - strictEqual( widget.text(), + strictEqual( widget.contents().not( this.element ), "foo", "When value is passed on create value is used in dom" ); checkbox.checkboxradio( "destroy" ); @@ -151,21 +151,21 @@ module( "Checkboxradio: checkbox: options" ); strictEqual( checkbox.checkboxradio( "option", "label" ), "foo", "When null is passed on create text from dom is used for option" ); - strictEqual( widget.text(), + strictEqual( widget.contents().not( this.element ), "foo", "When null is passed on create text from dom is used in dom" ); checkbox.checkboxradio( "option", "label", "bar" ); strictEqual( checkbox.checkboxradio( "option", "label" ), "bar", "When value is passed value is used for option" ); - strictEqual( widget.text(), + strictEqual( widget.contents().not( this.element ), "bar", "When value is passed value is used in dom" ); checkbox.checkboxradio( "option", "label", null ); strictEqual( checkbox.checkboxradio( "option", "label" ), "bar", "When null is passed text from dom is used for option" ); - strictEqual( widget.text(), + strictEqual( widget.contents().not( this.element ), "bar", "When null is passed text from dom is used in dom" ); }); diff --git a/tests/visual/checkboxradio/checkbox.html b/tests/visual/checkboxradio/checkbox.html index f3db979dda0..e1a3267cea2 100644 --- a/tests/visual/checkboxradio/checkbox.html +++ b/tests/visual/checkboxradio/checkbox.html @@ -61,9 +61,8 @@ - - - + + diff --git a/ui/checkboxradio.js b/ui/checkboxradio.js index 965ee2952b6..7f841010841 100644 --- a/ui/checkboxradio.js +++ b/ui/checkboxradio.js @@ -54,21 +54,38 @@ var baseClasses = "ui-button ui-widget ui-corner-all", $.widget( "ui.checkboxradio", { version: "@VERSION", - defaultElement: "", options: { disabled: null, label: null, - icon: false + icon: true, + classes: { + "ui-checkboxradio": null, + "ui-checkbox": null, + "ui-radio": null, + "ui-checkbox-label": "ui-corner-all", + "ui-radio-label": "ui-corner-all", + "ui-checkboxradio-icon": "ui-corner-all", + "ui-radio-checked": null, + "ui-checkbox-checked": null + } }, _getCreateOptions: function() { - var options = {}; + var disabled, + that = this, + options = {}; this._readLabel(); - this.originalLabel = this.label.html(); + this.originalLabel = ""; + this.label.contents().not( this.element ).each( function() { + that.originalLabel += ( this.nodeType === 3 ) ? $( this ).text() : this.outerHTML; + }); - this._readDisabled( options ); + disabled = this.element.prop( "disabled" ); + if ( disabled != null ) { + options.disabled = disabled; + } if ( this.originalLabel ) { options.label = this.originalLabel; @@ -95,13 +112,9 @@ $.widget( "ui.checkboxradio", { formElement.off( "reset" + this.eventNamespace, formResetHandler ); formElement.on( "reset" + this.eventNamespace, formResetHandler ); - // If the option is a boolean its been set by either user or by - // _getCreateOptions so we need to make sure the prop matches - // If it is not a boolean the user set it explicitly to null so we need to check the dom - if ( typeof this.options.disabled === "boolean" ) { - this.element.prop( "disabled", this.options.disabled ); - } else { - this._readDisabled( this.options ); + // If it is null the user set it explicitly to null so we need to check the dom + if ( this.options.disabled == null ) { + this.options.disabled = this.element.prop( "disabled" ) || false; } // If the option is true we call set options to add the disabled @@ -134,11 +147,16 @@ $.widget( "ui.checkboxradio", { _readLabel: function() { var ancestor, labelSelector, - labels = this.element[ 0 ].labels; + parent = this.element.closest( "label" ); + + this.parentLabel = false; // Check control.labels first - if ( labels !== undefined && labels.length > 0 ) { - this.label = $( labels[ 0 ] ); + if ( this.element[ 0 ].labels !== undefined && this.element[ 0 ].labels.length > 0 ){ + this.label = $( this.element[ 0 ].labels[ 0 ] ); + } else if ( parent.length > 0 ) { + this.label = parent; + this.parentLabel = true; } else { // We don't search against the document in case the element @@ -241,6 +259,8 @@ $.widget( "ui.checkboxradio", { if ( this.type === "checkbox" ) { toAdd += checked ? "ui-icon-check" : "ui-icon-blank"; + } else { + toAdd += "ui-icon-blank"; } this.icon.addClass( toAdd ).appendTo( this.label ); } else if ( this.icon !== undefined ) { @@ -254,9 +274,12 @@ $.widget( "ui.checkboxradio", { var checked = this.element.is( ":checked" ), isDisabled = this.element.is( ":disabled" ); this._updateIcon( checked ); - this.label.toggleClass( "ui-state-active ui-" + this.type + "-checked", checked ); + console.log( this.options.label ); + this.label.toggleClass( "ui-state-active " + this._classes( "ui-" + this.type + "-checked" ), checked ); if ( this.options.label !== null ) { - this.label.html( !!this.icon ? this.icon : "" ).append( this.options.label ); + this.label.contents().not( this.element.add( this.icon ) ).remove(); + this.label.append( this.options.label ); + } if ( isDisabled !== this.options.disabled ) { From 7ac96c8291e2f3ca4ba525eabf3c4bc643d46d46 Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Fri, 7 Nov 2014 23:33:51 -0500 Subject: [PATCH 63/73] Checkboxradio: Fixup demos --- demos/checkboxradio/default.html | 2 +- demos/checkboxradio/{icon.html => icons.html} | 2 +- demos/checkboxradio/index.html | 16 ++++++++++++++++ demos/index.html | 1 + tests/unit/checkboxradio/checkboxradio.html | 4 ++-- tests/visual/index.html | 5 +++++ ui/checkboxradio.js | 2 ++ 7 files changed, 28 insertions(+), 4 deletions(-) rename demos/checkboxradio/{icon.html => icons.html} (95%) create mode 100644 demos/checkboxradio/index.html diff --git a/demos/checkboxradio/default.html b/demos/checkboxradio/default.html index 4bc6c0005eb..e9e9383e016 100644 --- a/demos/checkboxradio/default.html +++ b/demos/checkboxradio/default.html @@ -23,7 +23,7 @@

      Checkbox

      Radio Group

      diff --git a/demos/checkboxradio/icon.html b/demos/checkboxradio/icons.html similarity index 95% rename from demos/checkboxradio/icon.html rename to demos/checkboxradio/icons.html index 28e266a1668..4f46bcc8a34 100644 --- a/demos/checkboxradio/icon.html +++ b/demos/checkboxradio/icons.html @@ -25,7 +25,7 @@

      Checkbox

      Radio Group

      diff --git a/demos/checkboxradio/index.html b/demos/checkboxradio/index.html new file mode 100644 index 00000000000..6d6f47fd586 --- /dev/null +++ b/demos/checkboxradio/index.html @@ -0,0 +1,16 @@ + + + + + + jQuery UI Checkboxradio Demos + + + + + + + diff --git a/demos/index.html b/demos/index.html index f37874a4481..4b4d04e06b5 100644 --- a/demos/index.html +++ b/demos/index.html @@ -11,6 +11,7 @@
    • accordion
    • autocomplete
    • button
    • +
    • checkboxradio
    • datepicker
    • dialog
    • draggable
    • diff --git a/tests/unit/checkboxradio/checkboxradio.html b/tests/unit/checkboxradio/checkboxradio.html index e101da5c320..2f651a2cff5 100644 --- a/tests/unit/checkboxradio/checkboxradio.html +++ b/tests/unit/checkboxradio/checkboxradio.html @@ -7,11 +7,11 @@ - + @@ -19,21 +19,28 @@

      Checkbox and radio button widgets

      Checkbox

      - - - - +
      + Filter by rating + + + + + + + + +

      Radio Group

      - - - - - - +
      + Filter by location: + + + + + +
      diff --git a/demos/checkboxradio/icons.html b/demos/checkboxradio/icons.html index 4f46bcc8a34..75a33ec6136 100644 --- a/demos/checkboxradio/icons.html +++ b/demos/checkboxradio/icons.html @@ -2,7 +2,7 @@ - jQuery UI Button - Icon functionality + jQuery UI Checkboxradio - Icon functionality @@ -22,20 +22,28 @@

      Checkbox and radio button widgets

      Checkbox

      - - -
      diff --git a/demos/checkboxradio/images/jquery-mobile.png b/demos/checkboxradio/images/jquery-mobile.png new file mode 100644 index 0000000000000000000000000000000000000000..fe2c36376d4dd8f1627d34e3982d4e924f138176 GIT binary patch literal 6296 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 literal 0 HcmV?d00001 diff --git a/demos/checkboxradio/images/qunit.png b/demos/checkboxradio/images/qunit.png new file mode 100644 index 0000000000000000000000000000000000000000..048bcfddbdd6f02e3ae9522098014c2510b39f38 GIT binary patch literal 6740 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 literal 0 HcmV?d00001 diff --git a/demos/checkboxradio/images/sizzle.png b/demos/checkboxradio/images/sizzle.png new file mode 100644 index 0000000000000000000000000000000000000000..6145cd8ec488a6ea924ecb9c4ef4fb4a41fac5ac GIT binary patch literal 8875 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 literal 0 HcmV?d00001 diff --git a/demos/checkboxradio/index.html b/demos/checkboxradio/index.html index 6d6f47fd586..ed0c37d4b7b 100644 --- a/demos/checkboxradio/index.html +++ b/demos/checkboxradio/index.html @@ -10,6 +10,8 @@ diff --git a/demos/checkboxradio/product-selector.html b/demos/checkboxradio/product-selector.html new file mode 100644 index 00000000000..0f894b7e3f5 --- /dev/null +++ b/demos/checkboxradio/product-selector.html @@ -0,0 +1,126 @@ + + + + + jQuery UI Checkboxradio - Product Selector + + + + + + + + + + + +
      +
      +

      1.) Select a brand

      +
      + + + + + + + + + + +
      +
      +
      +

      2.) Select a shape

      +
      + + + + + + + + +
      +
      +
      +

      3.) customize

      +
      + + + + + + + + +
      +
      +
      +
      + +
      +

      Examples of the markup that can be used with checkboxs and radio buttons.

      +
      + + diff --git a/demos/checkboxradio/radiogroup.html b/demos/checkboxradio/radiogroup.html new file mode 100644 index 00000000000..2489a334891 --- /dev/null +++ b/demos/checkboxradio/radiogroup.html @@ -0,0 +1,40 @@ + + + + + jQuery UI Checkboxradio - Radio Group + + + + + + + + + + +
      + +

      Radio Group

      +
      + Location: + + + + + +
      +
      + +
      +

      Example markup using a controlgroup to create a radio group

      +
      + + diff --git a/demos/controlgroup/default.html b/demos/controlgroup/default.html new file mode 100644 index 00000000000..9e4bcdd80ef --- /dev/null +++ b/demos/controlgroup/default.html @@ -0,0 +1,90 @@ + + + + + jQuery UI Controlgroup - Default Functionality + + + + + + + + + + + + + + + +
      +

      A Controlgroup featuring various form controls

      +
      +
      +

      Controlgroup

      +
      + Rental Car +
      + + + + + + + + +
      +
      +
      +
      + Rental Car +
      + + + + + + + + +
      +
      +>>>>>>> 423b976... Checkboxradio: Fixed demos and tests +
      + + + diff --git a/demos/controlgroup/index.html b/demos/controlgroup/index.html new file mode 100644 index 00000000000..58e2f7eda7a --- /dev/null +++ b/demos/controlgroup/index.html @@ -0,0 +1,17 @@ + + + + + + jQuery UI Checkboxradio Demos + + + + + + + diff --git a/demos/controlgroup/splitbutton.html b/demos/controlgroup/splitbutton.html new file mode 100644 index 00000000000..5d4c7b3ce55 --- /dev/null +++ b/demos/controlgroup/splitbutton.html @@ -0,0 +1,58 @@ + + + + + jQuery UI Controlgroup - Split Button + + + + + + + + + + + + + + + +
      +

      A Controlgroup creating a split button

      +
      +
      +

      Split button

      +
      + + +
      +
      +
      +

      A Controlgroup creating a split button

      +
      + + diff --git a/demos/controlgroup/toolbar.html b/demos/controlgroup/toolbar.html new file mode 100644 index 00000000000..f90fb304009 --- /dev/null +++ b/demos/controlgroup/toolbar.html @@ -0,0 +1,256 @@ + + + + + jQuery UI Controlgroup - Toolbar + + + + + + + + + + + + + + + +
      +

      A sample editor toolbar

      +

      Highlight text and edit it using the buttons and dropdowns in the toolbar

      +
      +
      + + + + + + + + + + + + +
      +

      +
      +The Rime of the Ancient Mariner (text of 1834)
      +BY SAMUEL TAYLOR COLERIDGE
      +Argument 
      +
      +How a Ship having passed the Line was driven by storms to the cold Country towards the South Pole;
      +and how from thence she made her course to the tropical Latitude of the Great Pacific Ocean; and 
      +of the strange things that befell; and in what manner the Ancyent Marinere came back to his own
      +Country.
      +
      +PART I
      +It is an ancient Mariner,
      +And he stoppeth one of three.
      +'By thy long grey beard and glittering eye,
      +Now wherefore stopp'st thou me?
      +
      +The Bridegroom's doors are opened wide,
      +And I am next of kin;
      +The guests are met, the feast is set:
      +May'st hear the merry din.'
      +
      +He holds him with his skinny hand,
      +'There was a ship,' quoth he.
      +'Hold off! unhand me, grey-beard loon!'
      +Eftsoons his hand dropt he.
      +
      +He holds him with his glittering eye—
      +The Wedding-Guest stood still,
      +And listens like a three years' child:
      +The Mariner hath his will.
      +
      +The Wedding-Guest sat on a stone:
      +He cannot choose but hear;
      +And thus spake on that ancient man,
      +The bright-eyed Mariner.
      +
      +'The ship was cheered, the harbour cleared,
      +Merrily did we drop
      +Below the kirk, below the hill,
      +Below the lighthouse top.
      +
      +The Sun came up upon the left,
      +Out of the sea came he!
      +And he shone bright, and on the right
      +Went down into the sea.
      +
      +Higher and higher every day,
      +Till over the mast at noon—'
      +The Wedding-Guest here beat his breast,
      +For he heard the loud bassoon.
      +
      +The bride hath paced into the hall,
      +Red as a rose is she;
      +Nodding their heads before her goes
      +The merry minstrelsy.
      +
      +The Wedding-Guest he beat his breast,
      +Yet he cannot choose but hear;
      +And thus spake on that ancient man,
      +The bright-eyed Mariner.
      +
      +And now the STORM-BLAST came, and he
      +Was tyrannous and strong:
      +He struck with his o'ertaking wings,
      +And chased us south along.
      +
      +With sloping masts and dipping prow,
      +As who pursued with yell and blow
      +Still treads the shadow of his foe,
      +And forward bends his head,
      +The ship drove fast, loud roared the blast,
      +And southward aye we fled.
      +
      +And now there came both mist and snow,
      +And it grew wondrous cold:
      +And ice, mast-high, came floating by,
      +As green as emerald.
      +
      +And through the drifts the snowy clifts
      +Did send a dismal sheen:
      +Nor shapes of men nor beasts we ken—
      +The ice was all between.
      +
      +The ice was here, the ice was there,
      +The ice was all around:
      +It cracked and growled, and roared and howled,
      +Like noises in a swound!
      +
      +At length did cross an Albatross,
      +Thorough the fog it came;
      +As if it had been a Christian soul,
      +We hailed it in God's name.
      +
      +It ate the food it ne'er had eat,
      +And round and round it flew.
      +The ice did split with a thunder-fit;
      +The helmsman steered us through!
      +
      +And a good south wind sprung up behind;
      +The Albatross did follow,
      +And every day, for food or play,
      +Came to the mariner's hollo!
      +
      +In mist or cloud, on mast or shroud,
      +It perched for vespers nine;
      +Whiles all the night, through fog-smoke white,
      +Glimmered the white Moon-shine.'
      +
      +'God save thee, ancient Mariner!
      +From the fiends, that plague thee thus!—
      +Why look'st thou so?'—With my cross-bow
      +I shot the ALBATROSS.
      +
      + + diff --git a/tests/unit/checkboxradio/checkboxradio_core.js b/tests/unit/checkboxradio/checkboxradio_core.js index 843fc3ff5f1..35f162a8c8c 100644 --- a/tests/unit/checkboxradio/checkboxradio_core.js +++ b/tests/unit/checkboxradio/checkboxradio_core.js @@ -14,7 +14,7 @@ test("Checkbox", function() { ok( !label.hasClass(".ui-button)") ); input.checkboxradio(); strictEqual( input.attr( "class" ), "ui-helper-hidden-accessible ui-checkboxradio" ); - strictEqual( label.attr( "class" ), "ui-button ui-widget ui-corner-all ui-checkbox-label" ); + strictEqual( label.attr( "class" ), "ui-button ui-widget ui-checkbox-label ui-corner-all" ); }); test("Radios", function() { @@ -87,7 +87,7 @@ if ( !$.ui.ie || ( document.documentMode && document.documentMode > 8 ) ) { setTimeout(function() { $( "#check2" ).checkboxradio( "widget" ).simulate( "click" ); start(); - }, 1 ); + }); }); } test( "Checkbox creation that requires a matching finds label in all cases", function() { @@ -141,4 +141,12 @@ test( "Checkbox label selector works for ids with \":\"", function() { ok( group.find( "label" ).is( ".ui-button" ), "Found an id with a :" ); }); +test( "Calling checkboxradio on an unsupported element throws an error", function() { + expect( 1 ); + throws( $( "
      " ).checkboxradio, "Error thrown" ); +}); +test( "Calling checkboxradio oan input with no label throws an error", function() { + expect( 1 ); + throws( $( "" ).checkboxradio, "Error thrown" ); +}); })(jQuery); diff --git a/tests/visual/checkboxradio/checkbox.html b/tests/visual/checkboxradio/checkbox.html index e1a3267cea2..6e85f8763c8 100644 --- a/tests/visual/checkboxradio/checkbox.html +++ b/tests/visual/checkboxradio/checkbox.html @@ -54,7 +54,7 @@ - +
      diff --git a/tests/visual/index.html b/tests/visual/index.html index 8477fa7d33b..5529c1dfda9 100644 --- a/tests/visual/index.html +++ b/tests/visual/index.html @@ -33,7 +33,7 @@

      Button

      Checkboxradio

      Dialog

      diff --git a/themes/base/checkboxradio.css b/themes/base/checkboxradio.css index 7e90394df5d..c522e2d22f3 100644 --- a/themes/base/checkboxradio.css +++ b/themes/base/checkboxradio.css @@ -22,7 +22,7 @@ border-radius: 1em; overflow: visible; border: none; - background-color: rgb( 0, 0, 0 ); + background-color: rgb( 192, 192, 192 ); background-color: rgba( 0, 0, 0, .3 ); opacity: .3; } diff --git a/ui/checkboxradio.js b/ui/checkboxradio.js index 3611ffcf3c3..d91f3dbd4d1 100644 --- a/ui/checkboxradio.js +++ b/ui/checkboxradio.js @@ -24,10 +24,9 @@ } }(function( $ ) { -var baseClasses = "ui-button ui-widget ui-corner-all", - typeClasses = " ui-icon ui-icon-background ui-state-focus ui-icon-check ui-icon-blank" + - " ui-radio-label ui-checkbox-label ui-state-active ui-icon-beginning ui-icon-end" + - " ui-icon-top ui-icon-bottom ui-radio-checked ui-checkbox-checked", +var baseClasses = "ui-button ui-widget", + typeClasses = "ui-state-focus ui-radio-label ui-checkbox-label ui-state-active " + + "ui-icon-beginning ui-icon-end ui-icon-top ui-icon-bottom ui-radio-checked ui-checkbox-checked", formResetHandler = function() { var form = $( this ); setTimeout(function() { @@ -98,35 +97,18 @@ $.widget( "ui.checkboxradio", { return options; }, - _readDisabled: function( options ) { - var isDisabled = this.element.prop( "disabled" ); - - if ( isDisabled !== undefined ) { - options.disabled = isDisabled; - } else { - options.disabled = false; - } - }, - _create: function() { var formElement = $( this.element[ 0 ].form ); // We don't use _on and _off here because we want all the checkboxes in the same form to use - // single handler which handles all the checkboxradio widgets in the form + // a single handler which handles all the checkboxradio widgets in the form formElement.off( "reset" + this.eventNamespace, formResetHandler ); formElement.on( "reset" + this.eventNamespace, formResetHandler ); - // If it is null the user set it explicitly to null so we need to check the dom if ( this.options.disabled == null ) { this.options.disabled = this.element.prop( "disabled" ) || false; } - // If the option is true we call set options to add the disabled - // classes and ensure the element is not focused - if ( this.options.disabled === true ){ - this._setOption( "disabled", true ); - } - this._readType(); this._enhance(); @@ -145,7 +127,7 @@ $.widget( "ui.checkboxradio", { _readType: function() { this.type = this.element[ 0 ].type; if ( !/radio|checkbox/.test( this.type ) ) { - throw new Error( "Can't create checkboxradio widget for type " + this.type ); + $.error( "Can't create checkboxradio widget for type " + this.type ); } }, @@ -156,7 +138,7 @@ $.widget( "ui.checkboxradio", { this.parentLabel = false; // Check control.labels first - if ( this.element[ 0 ].labels !== undefined && this.element[ 0 ].labels.length > 0 ){ + if ( this.element[ 0 ].labels !== undefined && this.element[ 0 ].labels.length > 0 ) { this.label = $( this.element[ 0 ].labels[ 0 ] ); } else if ( parent.length > 0 ) { this.label = parent; @@ -172,8 +154,8 @@ $.widget( "ui.checkboxradio", { this.label = ancestor.find( labelSelector ); if ( !this.label.length ) { - // The label was not found make sure ancestors exist if they do check their siblings - // if they dont check the elements siblings + // The label was not found, make sure ancestors exist. If they do check their + // siblings, if they dont check the elements siblings ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); // Check if any of the new set of ancestors is the label @@ -182,6 +164,9 @@ $.widget( "ui.checkboxradio", { // Still not found look inside the ancestors for the label this.label = ancestor.find( labelSelector ); + if ( this.label.length === 0 ) { + $.error( "No label found for checkboxradio widget" ); + } } } } @@ -190,6 +175,7 @@ $.widget( "ui.checkboxradio", { _enhance: function() { var checked = this.element.is( ":checked" ); + this._setOption( "disabled", this.options.disabled ); this._updateIcon( checked ); this.element.addClass( "ui-helper-hidden-accessible " + this._classes( "ui-checkboxradio" ) ); @@ -231,7 +217,8 @@ $.widget( "ui.checkboxradio", { }, _destroy: function() { - this.label.removeClass( baseClasses + " " + typeClasses ); + this.label.removeClass( this._classes( "ui-radio-label ui-checkbox-label" ) + " " + + baseClasses + " " + typeClasses ); if ( this.icon ) { this.icon.remove(); } @@ -262,7 +249,7 @@ $.widget( "ui.checkboxradio", { if ( this.options.icon ) { this.label.addClass( "ui-icon-beginning" ); - if ( !this.icon ){ + if ( !this.icon ) { this.icon = $( "" ); } From c70e383158236e1297b83ce41855e63090430ba6 Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Thu, 23 Oct 2014 13:29:52 -0400 Subject: [PATCH 67/73] Checkboxradio: change all classes to be prefixed with ui-checkboxradio And simplify css --- .../checkboxradio/checkboxradio_common.js | 13 ++--- .../unit/checkboxradio/checkboxradio_core.js | 3 +- .../checkboxradio/checkboxradio_methods.js | 4 +- .../checkboxradio/checkboxradio_options.js | 35 +++++++----- themes/base/checkboxradio.css | 11 ++-- ui/button.js | 4 +- ui/checkboxradio.js | 54 +++++++++++++------ 7 files changed, 75 insertions(+), 49 deletions(-) diff --git a/tests/unit/checkboxradio/checkboxradio_common.js b/tests/unit/checkboxradio/checkboxradio_common.js index 0d2a62a9caa..d46aca55436 100644 --- a/tests/unit/checkboxradio/checkboxradio_common.js +++ b/tests/unit/checkboxradio/checkboxradio_common.js @@ -3,16 +3,13 @@ TestHelpers.commonWidgetTests( "checkboxradio", { defaults: { disabled: null, label: null, - icon: false, + icon: true, classes: { - "ui-checkboxradio": null, - "ui-checkbox": null, - "ui-radio": null, - "ui-checkbox-label": "ui-corner-all", - "ui-radio-label": "ui-corner-all", + "ui-checkboxradio": "", + "ui-checkboxradio-label": "ui-corner-all", + "ui-checkboxradio-radio-label": "", "ui-checkboxradio-icon": "ui-corner-all", - "ui-radio-checked": null, - "ui-checkbox-checked": null + "ui-checkboxradio-checked": "" }, // Callbacks diff --git a/tests/unit/checkboxradio/checkboxradio_core.js b/tests/unit/checkboxradio/checkboxradio_core.js index 35f162a8c8c..ed7e1330be0 100644 --- a/tests/unit/checkboxradio/checkboxradio_core.js +++ b/tests/unit/checkboxradio/checkboxradio_core.js @@ -14,7 +14,8 @@ test("Checkbox", function() { ok( !label.hasClass(".ui-button)") ); input.checkboxradio(); strictEqual( input.attr( "class" ), "ui-helper-hidden-accessible ui-checkboxradio" ); - strictEqual( label.attr( "class" ), "ui-button ui-widget ui-checkbox-label ui-corner-all" ); + strictEqual( label.attr( "class" ), "ui-icon-beginning ui-button ui-widget" + + " ui-checkboxradio-label ui-corner-all" ); }); test("Radios", function() { diff --git a/tests/unit/checkboxradio/checkboxradio_methods.js b/tests/unit/checkboxradio/checkboxradio_methods.js index ee96f556a43..618f254b449 100644 --- a/tests/unit/checkboxradio/checkboxradio_methods.js +++ b/tests/unit/checkboxradio/checkboxradio_methods.js @@ -21,7 +21,7 @@ module( "Checkboxradio: methods" ); strictEqual( widget.find( ".ui-icon" ).length, 1, "Icon is recreated on refresh" ); checkbox.prop( "checked", true ); checkbox.checkboxradio( "refresh" ); - strictEqual( widget.hasClass( "ui-checkbox-checked" ), true, + strictEqual( widget.hasClass( "ui-checkboxradio-checked" ), true, "State updated based on checked property" ); }); @@ -82,7 +82,7 @@ module( "Checkboxradio: methods" ); strictEqual( widget.find( ".ui-icon" ).length, 1, "Icon is recreated on refresh" ); radio.prop( "checked", true ); radio.checkboxradio( "refresh" ); - strictEqual( widget.hasClass( "ui-radio-checked" ), true, + strictEqual( widget.hasClass( "ui-checkboxradio-checked" ), true, "State updated based on checked property" ); }); diff --git a/tests/unit/checkboxradio/checkboxradio_options.js b/tests/unit/checkboxradio/checkboxradio_options.js index d58a130268e..46fd9e904b0 100644 --- a/tests/unit/checkboxradio/checkboxradio_options.js +++ b/tests/unit/checkboxradio/checkboxradio_options.js @@ -60,7 +60,7 @@ module( "Checkboxradio: checkbox: options" ); expect( 9 ); - checkbox.checkboxradio(); + checkbox.checkboxradio({ icon: false }); widget = checkbox.checkboxradio( "widget" ); @@ -75,8 +75,8 @@ module( "Checkboxradio: checkbox: options" ); strictEqual( widget.find( "span" ).length, 1, "Label contains a span when created with icon:true" ); - strictEqual( widget.find( "span" ).attr( "class" ), - "ui-checkboxradio-icon ui-corner-all ui-icon ui-icon-background ui-icon-blank", + strictEqual( widget.find( "span" ).is( ".ui-checkboxradio-icon.ui-corner-all.ui-icon." + + "ui-icon-background.ui-icon-blank" ), true, "Icon span has proper classes when created not checked" ); checkbox.checkboxradio( "destroy" ).prop( "checked", true ); @@ -85,8 +85,8 @@ module( "Checkboxradio: checkbox: options" ); icon: true }); - strictEqual( widget.find( "span" ).attr( "class" ), - "ui-checkboxradio-icon ui-corner-all ui-icon ui-icon-background ui-icon-check", + strictEqual( widget.find( "span" ).is( ".ui-checkboxradio-icon.ui-corner-all.ui-icon." + + "ui-icon-background.ui-icon-check" ), true, "Icon span has proper classes when created checked" ); checkbox.checkboxradio( "option", "icon", false ); @@ -96,8 +96,8 @@ module( "Checkboxradio: checkbox: options" ); checkbox.checkboxradio( "option", "icon", true ); - strictEqual( widget.find( "span" ).attr( "class" ), - "ui-checkboxradio-icon ui-corner-all ui-icon ui-icon-background ui-icon-check", + strictEqual( widget.find( "span" ).is( ".ui-checkboxradio-icon.ui-corner-all.ui-icon." + + "ui-icon-background.ui-icon-check" ), true, "Icon span has proper classes when option set to true and :is( checked )" ); checkbox.prop( "checked", false ).checkboxradio( "refresh" ); @@ -108,8 +108,8 @@ module( "Checkboxradio: checkbox: options" ); checkbox.checkboxradio( "option", "icon", true ); - strictEqual( widget.find( "span" ).attr( "class" ), - "ui-checkboxradio-icon ui-corner-all ui-icon ui-icon-background ui-icon-blank", + strictEqual( widget.find( "span" ).is( ".ui-checkboxradio-icon.ui-corner-all.ui-icon." + + "ui-icon-background.ui-icon-blank" ), true, "Icon span has proper classes when option set to true and not checked" ); checkbox.checkboxradio( "destroy" ); @@ -118,6 +118,13 @@ module( "Checkboxradio: checkbox: options" ); "Label does not contain a span after destroy when icon true" ); }); + function getLabelText( label, element ) { + var text = ""; + label.contents().not( element ).each( function() { + text += ( this.nodeType === 3 ) ? $( this ).text() : ""; + }); + return text; + } test( "options: label", function() { var checkbox = $( "#checkbox-option-label" ), widget; @@ -130,7 +137,7 @@ module( "Checkboxradio: checkbox: options" ); strictEqual( checkbox.checkboxradio( "option", "label" ), "checkbox label", "When no value passed on create text from dom is used for option" ); - strictEqual( widget.contents().not( this.element ), + strictEqual( getLabelText( widget, checkbox ), "checkbox label", "When no value passed on create text from dom is used in dom" ); checkbox.checkboxradio( "destroy" ); @@ -141,7 +148,7 @@ module( "Checkboxradio: checkbox: options" ); strictEqual( checkbox.checkboxradio( "option", "label" ), "foo", "When value is passed on create value is used for option" ); - strictEqual( widget.contents().not( this.element ), + strictEqual( getLabelText( widget, checkbox ), "foo", "When value is passed on create value is used in dom" ); checkbox.checkboxradio( "destroy" ); @@ -151,21 +158,21 @@ module( "Checkboxradio: checkbox: options" ); strictEqual( checkbox.checkboxradio( "option", "label" ), "foo", "When null is passed on create text from dom is used for option" ); - strictEqual( widget.contents().not( this.element ), + strictEqual( getLabelText( widget, checkbox ), "foo", "When null is passed on create text from dom is used in dom" ); checkbox.checkboxradio( "option", "label", "bar" ); strictEqual( checkbox.checkboxradio( "option", "label" ), "bar", "When value is passed value is used for option" ); - strictEqual( widget.contents().not( this.element ), + strictEqual( getLabelText( widget, checkbox ), "bar", "When value is passed value is used in dom" ); checkbox.checkboxradio( "option", "label", null ); strictEqual( checkbox.checkboxradio( "option", "label" ), "bar", "When null is passed text from dom is used for option" ); - strictEqual( widget.contents().not( this.element ), + strictEqual( getLabelText( widget, checkbox ), "bar", "When null is passed text from dom is used in dom" ); }); diff --git a/themes/base/checkboxradio.css b/themes/base/checkboxradio.css index c522e2d22f3..52c17c0ffd8 100644 --- a/themes/base/checkboxradio.css +++ b/themes/base/checkboxradio.css @@ -9,14 +9,11 @@ * http://api.jqueryui.com/checkboxradio/#theming */ -.ui-checkbox { - display: none; -} -.ui-checkbox-label .ui-icon-background { +.ui-checkboxradio-label .ui-icon-background { border-radius: .12em; border: none; } -.ui-radio-label .ui-icon.ui-icon-background { +.ui-checkboxradio-radio-label .ui-icon-background { width: 16px; height: 16px; border-radius: 1em; @@ -26,8 +23,8 @@ background-color: rgba( 0, 0, 0, .3 ); opacity: .3; } -.ui-radio-label.ui-radio-checked .ui-icon, -.ui-radio-label.ui-radio-checked:hover .ui-icon { +.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon, +.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon { background-image: none; background-color: #fff; width: 8px; diff --git a/ui/button.js b/ui/button.js index 8fe2660fc58..6775a6cb432 100644 --- a/ui/button.js +++ b/ui/button.js @@ -51,7 +51,7 @@ $.widget( "ui.button", { _getCreateOptions: function() { var disabled, - options = {}; + options = this._super() || {}; this.isInput = this.element.is( "input" ); this.originalLabel = this.isInput ? this.element.val() : this.element.html(); @@ -226,7 +226,7 @@ $.widget( "ui.button", { }); // DEPRECATED -if ( $.uiBackCompat ) { +if ( $.uiBackCompat === false ) { // Text and Icons options $.widget( "ui.button", $.ui.button, { diff --git a/ui/checkboxradio.js b/ui/checkboxradio.js index d91f3dbd4d1..d7c68fac22a 100644 --- a/ui/checkboxradio.js +++ b/ui/checkboxradio.js @@ -26,7 +26,8 @@ var baseClasses = "ui-button ui-widget", typeClasses = "ui-state-focus ui-radio-label ui-checkbox-label ui-state-active " + - "ui-icon-beginning ui-icon-end ui-icon-top ui-icon-bottom ui-radio-checked ui-checkbox-checked", + "ui-icon-beginning ui-icon-end ui-icon-top ui-icon-bottom ui-checkboxradio-radio-checked " + + "ui-checkboxradio-checkbox-checked", formResetHandler = function() { var form = $( this ); setTimeout(function() { @@ -62,21 +63,18 @@ $.widget( "ui.checkboxradio", { icon: false, >>>>>>> db16c96... Checkboxradio: add classes option classes: { - "ui-checkboxradio": null, - "ui-checkbox": null, - "ui-radio": null, - "ui-checkbox-label": "ui-corner-all", - "ui-radio-label": "ui-corner-all", + "ui-checkboxradio": "", + "ui-checkboxradio-label": "ui-corner-all", + "ui-checkboxradio-radio-label": "", "ui-checkboxradio-icon": "ui-corner-all", - "ui-radio-checked": null, - "ui-checkbox-checked": null + "ui-checkboxradio-checked": "" } }, _getCreateOptions: function() { var disabled, that = this, - options = {}; + options = this._super() || {}; this._readLabel(); @@ -180,10 +178,14 @@ $.widget( "ui.checkboxradio", { this.element.addClass( "ui-helper-hidden-accessible " + this._classes( "ui-checkboxradio" ) ); - this.label.addClass( baseClasses + " " + this._classes( "ui-" + this.type + "-label" ) ); + this.label.addClass( baseClasses + " " + this._classes( "ui-checkboxradio-label" ) ); + + if ( this.type === "radio" ) { + this.label.addClass( "ui-checkboxradio-radio-label" ); + } if ( checked ) { - this.label.addClass( this._classes( "ui-" + this.type + "-checked" ) + + this.label.addClass( this._classes( "ui-checkboxradio-checked" ) + " ui-state-active" ); } if ( this.options.label && this.options.label !== this.originalLabel ) { @@ -199,7 +201,7 @@ $.widget( "ui.checkboxradio", { _toggleClasses: function() { var checked = this.element.is( ":checked" ); - this.label.toggleClass( this._classes( "ui-" + this.type + "-checked" ) + + this.label.toggleClass( this._classes( "ui-checkboxradio-checked" ) + " ui-state-active", checked ); if ( this.options.icon && this.type === "checkbox" ) { this.icon @@ -212,12 +214,12 @@ $.widget( "ui.checkboxradio", { .map(function() { return $( this ).checkboxradio( "widget" )[ 0 ]; }) - .removeClass( "ui-state-active " + this._classes( "ui-radio-checked" ) ); + .removeClass( "ui-state-active " + this._classes( "ui-checkboxradio-checked" ) ); } }, _destroy: function() { - this.label.removeClass( this._classes( "ui-radio-label ui-checkbox-label" ) + " " + + this.label.removeClass( this._classes( "ui-checkboxradio-radio-label ui-checkboxradio-label" ) + " " + baseClasses + " " + typeClasses ); if ( this.icon ) { this.icon.remove(); @@ -226,6 +228,28 @@ $.widget( "ui.checkboxradio", { " ui-helper-hidden-accessible" ); }, + _elementsFromClassKey: function( classKey ) { + var parts = classKey.split( "-" ), + checkedType = parts[ 2 ] === this.type || parts[ 2 ] === undefined, + checkedClass = parts[ 3 ] === "checked" || this.element.is( ":checked" ); + switch ( classKey ) { + case "ui-checkboxradio": + case "ui-checkboxradio-radio-label": + case "ui-checkboxradio-label": + case "ui-checkboxradio-checked": + if ( checkedType && checkedClass ) { + return this.label; + } + return $(); + case "ui-checkboxradio-icon": + if ( this.icon ) { + return this.icon; + } + return $(); + } + return this._superApply( arguments ); + }, + _setOption: function( key, value ) { var original; if ( key === "label" && value === null ) { @@ -270,7 +294,7 @@ $.widget( "ui.checkboxradio", { var checked = this.element.is( ":checked" ), isDisabled = this.element.is( ":disabled" ); this._updateIcon( checked ); - this.label.toggleClass( "ui-state-active " + this._classes( "ui-" + this.type + "-checked" ), checked ); + this.label.toggleClass( "ui-state-active " + this._classes( "ui-checkboxradio-checked" ), checked ); if ( this.options.label !== null ) { this.label.contents().not( this.element.add( this.icon ) ).remove(); this.label.append( this.options.label ); From 987a83fe3290d6712f714256d0a7b7c6388c6e80 Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Fri, 22 Aug 2014 23:39:35 -0400 Subject: [PATCH 68/73] Controlgroup: Inital commit of new widget This widget replaces the buttonset widget --- demos/button/icons.html | 1 + demos/controlgroup/default.html | 104 +++++++++++++ demos/controlgroup/index.html | 3 + demos/controlgroup/toolbar.html | 2 +- demos/index.html | 1 + demos/tooltip/video-player.html | 7 +- tests/unit/controlgroup/controlgroup.html | 61 ++++++++ .../unit/controlgroup/controlgroup_common.js | 15 ++ tests/unit/controlgroup/controlgroup_core.js | 89 +++++++++++ .../unit/controlgroup/controlgroup_methods.js | 130 ++++++++++++++++ .../unit/controlgroup/controlgroup_options.js | 92 +++++++++++ themes/base/base.css | 1 + themes/base/button.css | 18 +++ themes/base/controlgroup.css | 26 ++++ themes/base/core.css | 26 ---- ui/controlgroup.js | 143 ++++++++++++++++++ 16 files changed, 690 insertions(+), 29 deletions(-) create mode 100644 tests/unit/controlgroup/controlgroup.html create mode 100644 tests/unit/controlgroup/controlgroup_common.js create mode 100644 tests/unit/controlgroup/controlgroup_methods.js create mode 100644 tests/unit/controlgroup/controlgroup_options.js create mode 100644 themes/base/controlgroup.css create mode 100644 ui/controlgroup.js diff --git a/demos/button/icons.html b/demos/button/icons.html index 3982ab7fc48..089e669ff75 100644 --- a/demos/button/icons.html +++ b/demos/button/icons.html @@ -36,6 +36,7 @@

      Widget

      +

      CSS

      diff --git a/demos/controlgroup/default.html b/demos/controlgroup/default.html index 9e4bcdd80ef..37090024285 100644 --- a/demos/controlgroup/default.html +++ b/demos/controlgroup/default.html @@ -2,7 +2,11 @@ +<<<<<<< HEAD jQuery UI Controlgroup - Default Functionality +======= + jQuery UI Controlgroup - Default Funstionality +>>>>>>> 14168e2... Controlgroup: Inital commit of new widget @@ -29,13 +33,17 @@ .ui-controlgroup-vertical select { width: 100%; } +<<<<<<< HEAD .ui-controlgroup.ui-controlgroup-vertical > button.ui-button { text-align: center; } +======= +>>>>>>> 14168e2... Controlgroup: Inital commit of new widget
      +<<<<<<< HEAD

      A Controlgroup featuring various form controls

      @@ -86,5 +94,101 @@

      Controlgroup

      >>>>>>> 423b976... Checkboxradio: Fixed demos and tests
      +======= +

      Some buttons with various combinations of text and icons.

      +
      +
      +

      Widget

      +
      + + + + + + + +
      +
      +
      + + + + + + + +
      +
      +
      +

      CSS

      +
      + + + + + +
      +
      +
      + + + + + +
      +
      +>>>>>>> 14168e2... Controlgroup: Inital commit of new widget diff --git a/demos/controlgroup/index.html b/demos/controlgroup/index.html index 58e2f7eda7a..8fd3f752f89 100644 --- a/demos/controlgroup/index.html +++ b/demos/controlgroup/index.html @@ -9,7 +9,10 @@ diff --git a/demos/controlgroup/toolbar.html b/demos/controlgroup/toolbar.html index f90fb304009..ab02b83fb10 100644 --- a/demos/controlgroup/toolbar.html +++ b/demos/controlgroup/toolbar.html @@ -142,7 +142,7 @@
       The Rime of the Ancient Mariner (text of 1834)
       BY SAMUEL TAYLOR COLERIDGE
      -Argument 
      +Argument
       
       How a Ship having passed the Line was driven by storms to the cold Country towards the South Pole;
       and how from thence she made her course to the tropical Latitude of the Great Pacific Ocean; and 
      diff --git a/demos/index.html b/demos/index.html
      index 4b4d04e06b5..89375dde704 100644
      --- a/demos/index.html
      +++ b/demos/index.html
      @@ -12,6 +12,7 @@
       	
    • autocomplete
    • button
    • checkboxradio
    • +
    • controlgroup
    • datepicker
    • dialog
    • draggable
    • diff --git a/demos/tooltip/video-player.html b/demos/tooltip/video-player.html index 23747bb204f..986be0d25da 100644 --- a/demos/tooltip/video-player.html +++ b/demos/tooltip/video-player.html @@ -10,6 +10,7 @@ + @@ -78,8 +79,10 @@ notify( button ); }); }); - $( ".set" ).buttonset({ - items: "button" + $( ".set" ).controlgroup({ + items: { + "button" : "button" + } }); $( "button.menu" ) diff --git a/tests/unit/controlgroup/controlgroup.html b/tests/unit/controlgroup/controlgroup.html new file mode 100644 index 00000000000..5b97d5378ec --- /dev/null +++ b/tests/unit/controlgroup/controlgroup.html @@ -0,0 +1,61 @@ + + + + + jQuery UI Controlgroup Test Suite + + + + + + + + + + + + + + + + +
      +
      +
      + + + + + + + +
      +
      + + diff --git a/tests/unit/controlgroup/controlgroup_common.js b/tests/unit/controlgroup/controlgroup_common.js new file mode 100644 index 00000000000..53f722b7ce2 --- /dev/null +++ b/tests/unit/controlgroup/controlgroup_common.js @@ -0,0 +1,15 @@ +TestHelpers.commonWidgetTests( "controlgroup", { + defaults: { + disabled: null, + items: { + "button": "input[type=button], input[type=submit], input[type=reset], button, a", + "checkboxradio": "input[type='checkbox'], input[type='radio']", + "selectmenu": "select" + }, + direction: "horizontal", + excludeInvisible: true, + + // Callbacks + create: null + } +}); diff --git a/tests/unit/controlgroup/controlgroup_core.js b/tests/unit/controlgroup/controlgroup_core.js index e69de29bb2d..98c53170f67 100644 --- a/tests/unit/controlgroup/controlgroup_core.js +++ b/tests/unit/controlgroup/controlgroup_core.js @@ -0,0 +1,89 @@ +module( "Controlgroup: Core" ); + +function hasCornerClass( className, element ) { + if ( className ) { + return element.hasClass( className ); + } + + return element.attr( "class" ).match( /ui-corner/g ); +} + +test( "selectmenu: open/close corners", function() { + expect( 1 ); + var element = $( ".controlgroup" ).controlgroup(), + selects = element.find( "select" ), + selectButton = selects.eq( 0 ).selectmenu( "widget" ); + + expect( 12 ); + + selects.eq( 0 ).selectmenu( "open" ); + + strictEqual( selectButton.hasClass( "ui-corner-tl" ), true, + "Horizontal: First selectmenu gets ui-corner-tl when opened" ); + + selects.eq( 0 ).selectmenu( "close" ); + + strictEqual( selectButton.hasClass( "ui-corner-left" ), true, + "Horizontal: First selectmenu gets ui-corner-left when closed" ); + + selectButton = selects.eq( 1 ).selectmenu( "widget" ); + + selects.eq( 1 ).selectmenu( "open" ); + + strictEqual( !!hasCornerClass( false, selectButton ), false, + "Horizontal: Middle selectmenu does not get corner class when opened" ); + + selects.eq( 1 ).selectmenu( "close" ); + + strictEqual( !!hasCornerClass( false, selectButton ), false, + "Horizontal: Middle selectmenu does not get corner class when closed" ); + + selectButton = selects.eq( 2 ).selectmenu( "widget" ); + + selects.eq( 2 ).selectmenu( "open" ); + + strictEqual( selectButton.hasClass( "ui-corner-tr" ), true, + "Horizontal: Last selectmenu gets ui-corner-tr when opened" ); + + selects.eq( 2 ).selectmenu( "close" ); + + strictEqual( selectButton.hasClass( "ui-corner-right" ), true, + "Horizontal: Last selectmenu gets ui-corner-right when closed" ); + + element.controlgroup( "option", "direction", "vertical" ); + selectButton = selects.eq( 0 ).selectmenu( "widget" ); + + selects.eq( 0 ).selectmenu( "open" ); + + strictEqual( selectButton.hasClass( "ui-corner-top" ), true, + "vertical: First selectmenu gets ui-corner-top when opened" ); + + selects.eq( 0 ).selectmenu( "close" ); + + strictEqual( selectButton.hasClass( "ui-corner-top" ), true, + "vertical: First selectmenu gets ui-corner-top when closed" ); + + selectButton = selects.eq( 1 ).selectmenu( "widget" ); + + selects.eq( 1 ).selectmenu( "open" ); + + strictEqual( !!hasCornerClass( false, selectButton ), false, + "vertical: Middle selectmenu does not get corner class when opened" ); + + selects.eq( 1 ).selectmenu( "close" ); + + strictEqual( !!hasCornerClass( false, selectButton ), false, + "vertical: Middle selectmenu does not get corner class when closed" ); + + selectButton = selects.eq( 2 ).selectmenu( "widget" ); + + selects.eq( 2 ).selectmenu( "open" ); + + strictEqual( !!hasCornerClass( false, selectButton ), false, + "vertical: Last selectmenu does not get corner class when opened" ); + + selects.eq( 2 ).selectmenu( "close" ); + + strictEqual( selectButton.hasClass( "ui-corner-bottom" ), true, + "vertical: Last selectmenu gets ui-corner-bottom when closed" ); +}); \ No newline at end of file diff --git a/tests/unit/controlgroup/controlgroup_methods.js b/tests/unit/controlgroup/controlgroup_methods.js new file mode 100644 index 00000000000..90715055a6e --- /dev/null +++ b/tests/unit/controlgroup/controlgroup_methods.js @@ -0,0 +1,130 @@ +module( "Controlgroup: methods" ); + +test( "destroy", function() { + expect( 1 ); + domEqual( ".controlgroup", function() { + $( ".controlgroup" ).controlgroup().controlgroup( "destroy" ); + }); +}); +test( "disable", function() { + var tests = 1, + element = $( ".controlgroup" ).controlgroup().controlgroup( "disable" ); + strictEqual( element.hasClass( "ui-state-disabled" ), false, + "ui-state-disabled is not present on widget after disabling" ); + $.each( $.ui.controlgroup.prototype.options.items, function( widget, selector ){ + element.children( selector ).each(function(){ + expect( ++tests ); + strictEqual( $( this )[ widget ]( "widget" ).hasClass( "ui-state-disabled"), true, + "Child " + widget + " widgets are disabled" ); + }); + }); +}); + +test( "enable", function() { + var tests = 1, + element = $( ".controlgroup" ).controlgroup().controlgroup( "enable" ); + strictEqual( element.hasClass( "ui-state-disabled" ), false, + "ui-state-disabled is not present on widget after enabling" ); + $.each( $.ui.controlgroup.prototype.options.items, function( widget, selector ){ + element.children( selector ).each(function(){ + expect( ++tests ); + strictEqual( $( this )[ widget ]( "widget" ).hasClass( "ui-state-disabled"), false, + "Child " + widget + " widgets are not disabled" ); + }); + }); +}); + +function hasCornerClass( className, element ) { + if ( className ) { + return element.hasClass( className ); + } + + return element.attr( "class" ).match( /ui-corner/g ); +} +test( "refresh", function() { + var count = 0, + tests = { + "checkboxradio": "", + "selectmenu": "", + "button": " + + + + + Button with icon on the bottom + +
      +
      + + +
      + + + + Button with icon on the bottom + +
    diff --git a/tests/unit/controlgroup/controlgroup_common.js b/tests/unit/controlgroup/controlgroup_common.js index 53f722b7ce2..21acab744ac 100644 --- a/tests/unit/controlgroup/controlgroup_common.js +++ b/tests/unit/controlgroup/controlgroup_common.js @@ -8,6 +8,11 @@ TestHelpers.commonWidgetTests( "controlgroup", { }, direction: "horizontal", excludeInvisible: true, + classes: { + "ui-controlgroup": "", + "ui-controlgroup-horizontal": "", + "ui-controlgroup-vertical": "" + }, // Callbacks create: null diff --git a/tests/unit/controlgroup/controlgroup_options.js b/tests/unit/controlgroup/controlgroup_options.js index aa99352c555..4228a51639a 100644 --- a/tests/unit/controlgroup/controlgroup_options.js +++ b/tests/unit/controlgroup/controlgroup_options.js @@ -52,6 +52,39 @@ test( "items", function() { expect( 2 ); }); +test( "items: custom selector", function() { + var element = $( ".controlgroup-custom-selector" ).controlgroup({ + items: { + "button": ".button" + } + }); + strictEqual( element.children( ".ui-button" ).length, 5, + "Correct child widgets are called when custom selector used" ); + expect( 1 ); +}); + +$.widget( "ui.test", { + _create: function (){ + this.element.addClass( "ui-test ui-button" ); + }, + refresh: function() { + return; + } +}); +test( "items: custom widget", function() { + var element = $( ".controlgroup-custom-widget" ).controlgroup({ + items: { + "test": ".test" + } + }); + + strictEqual( element.children( ".ui-button" ).length, 7, + "Correct child widgets are called when custom selector used" ); + strictEqual( element.children( ".ui-test" ).length, 1, + "Custom widget called" ); + expect( 2 ); +}); + test( "excludeInvisible", function() { var element = $( ".controlgroup" ).controlgroup(), buttons = element.children( ".ui-button" ); diff --git a/themes/base/controlgroup.css b/themes/base/controlgroup.css index 0aff19d5edd..c708d60e0a2 100644 --- a/themes/base/controlgroup.css +++ b/themes/base/controlgroup.css @@ -11,14 +11,14 @@ .ui-controlgroup > .ui-button { - margin-left: -2px; - margin-right: -1px; + margin-left: -.14em; + margin-right: -.14em; } .ui-controlgroup.ui-controlgroup-vertical > .ui-button { display: block; width: 100%; - margin-top: -1px; - margin-bottom: -1px; + margin-top: 0; + margin-bottom: 0; text-align: left; } .ui-controlgroup-vertical label.ui-button { diff --git a/ui/controlgroup.js b/ui/controlgroup.js index c0a3ab1589c..2a5a0af275f 100644 --- a/ui/controlgroup.js +++ b/ui/controlgroup.js @@ -35,52 +35,19 @@ $.widget( "ui.controlgroup", { "selectmenu": "select" }, direction: "horizontal", - excludeInvisible: true + excludeInvisible: true, + classes: { + "ui-controlgroup": "", + "ui-controlgroup-horizontal": "", + "ui-controlgroup-vertical": "" + } }, _create: function() { this._enhance(); - this._on( this.element, { - "selectmenuopen": "_handleSelectmenuOpen", - "selectmenuclose": "_handleSelectmenuClose" - }); - }, - - _handleSelectmenuOpen: function( event ) { - var target = $( event.target ), - widget = target.selectmenu ( "widget" ), - vertical = this.options.direction === "vertical"; - if ( widget[ 0 ] !== this.first[ 0 ] || !vertical ) { - widget.removeClass( "ui-corner-top" ); - } - if ( vertical && widget[ 0 ] === this.last[ 0 ] ) { - widget.removeClass( "ui-corner-bottom" ); - } - if ( widget[ 0 ] === this.first[ 0 ] ) { - widget.removeClass( "ui-corner-left" ) - .addClass( "ui-corner-" + ( vertical ? "top" : "tl" ) ); - } - if ( widget[ 0 ] === this.last[ 0 ] ) { - widget.removeClass( "ui-corner-right" ) - .addClass( vertical ? "" : "ui-corner-tr" ); - } - }, - - _handleSelectmenuClose: function( event ) { - var target = $( event.target ), - widget = target.selectmenu ( "widget" ), - vertical = this.options.direction === "vertical"; - widget.removeClass( "ui-corner-all" ); - if ( widget[ 0 ] === this.first[ 0 ] ) { - widget.removeClass( "ui-corner-left" ) - .addClass( "ui-corner-" + ( vertical ? "top" : "left" ) ); - } - if ( widget[ 0 ] === this.last[ 0 ] ) { - widget.removeClass( "ui-corner-right" ) - .addClass( vertical ? "ui-corner-bottom" : "ui-corner-right" ); - } }, + // To support enhanced option in jQuery mobile we isolate dom manipulation here _enhance: function() { this.element.attr( "role", "toolbar" ); this.refresh(); @@ -89,20 +56,75 @@ $.widget( "ui.controlgroup", { _destroy: function() { this._callChildMethod( "destroy" ); this.element.removeAttr( "role" ); - this.element.removeClass( "ui-controlgroup ui-selectmenu-vertical ui-controlgroup-horizontal" ) - .children().removeClass( "ui-corner-all ui-corner-top" + + this.element.removeClass( + this._classes( "ui-controlgroup ui-controlgroup-vertical ui-controlgroup-horizontal" ) + ).children().removeClass( "ui-corner-all ui-corner-top" + " ui-corner-bottom ui-corner-left ui-corner-tl ui-corner-tr" ); }, _callChildMethod: function( method, filter ) { var that = this; $.each( this.options.items, function( widget, selector ) { + var options = {}; + switch ( widget ) { + case "button": + options.classes = { + "ui-button": null + }; + break; + case "checkboxradio": + options.classes = { + "ui-checkbox-label": null, + "ui-radio-label": null + }; + break; + case "selectmenu": + options.classes = { + "ui-selectmenu-button-open": null, + "ui-selectmenu-button-closed": null + }; + break; + } if ( $.fn[ widget ] && selector ) { - that.element.children( selector ).not( filter )[ widget ]( method ); + that.element.children( selector ).not( filter )[ widget ]( method ? + method : options ); } }); }, + _button_options: function() { + return { + classes: { + "ui-button": "" + } + }; + }, + + _checkboxradio_options: function() { + return { + classes: { + "ui-checkbox-label": "", + "ui-radio-label": "" + } + }; + }, + + _selectmenu_options: function() { + return { + classes: { + "ui-selectmenu-button-open": "", + "ui-selectmenu-button-closed": "" + } + }; + }, + + _elementsFromClassKey: function( classKey ) { + if ( this.options.direction !== classKey.split( "-" )[ 2 ] ) { + return $(); + } + return this._superApply( arguments ); + }, + _setOption: function( key, value ) { var original = this.options[ key ]; @@ -120,8 +142,11 @@ $.widget( "ui.controlgroup", { }, refresh: function() { - var vertical = ( this.options.direction === "vertical" ); - this.element.addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction ); + var firstClasses = {}, + lastClasses = {}, + vertical = ( this.options.direction === "vertical" ); + this.element.addClass( this._classes( "ui-controlgroup ui-controlgroup-" + + this.options.direction ) ); this._callChildMethod( undefined ); this.visible = this.element.children( ".ui-button" ).removeClass( function(index, css) { return ( css.match( /ui-corner-[a-z]*/g ) || [] ).join( " " ); @@ -131,7 +156,26 @@ $.widget( "ui.controlgroup", { .addClass( "ui-corner-" + ( vertical ? "top" : "left" ) ); this.last = this.visible.filter( ":last" ) .addClass( "ui-corner-" + ( vertical ? "bottom" : "right" ) ); - this.element.find( this.options.items.selectmenu ).selectmenu( "refresh" ); + if ( $.ui.selectmenu ) { + if ( this.first.is( ".ui-selectmenu-button" ) && !vertical ) { + firstClasses[ "ui-selectmenu-button-open" ] = "ui-corner-tl"; + firstClasses[ "ui-selectmenu-button-closed" ] = "ui-corner-left"; + $( "#" + this.first.attr( "id" ).replace( /-button/, "" ) ) + .selectmenu( "option", "classes", firstClasses ); + } + if ( this.last.is( ".ui-selectmenu-button" ) ) { + if ( vertical ) { + lastClasses[ "ui-selectmenu-button-open" ] = null; + lastClasses[ "ui-selectmenu-button-closed" ] = "ui-corner-bottom"; + } else { + lastClasses[ "ui-selectmenu-button-open" ] = "ui-corner-tr"; + lastClasses[ "ui-selectmenu-button-closed" ] = "ui-corner-right"; + } + $( "#" + this.last.attr( "id" ).replace( /-button/, "" ) ) + .selectmenu( "option", "classes", lastClasses ); + } + this.element.find( this.options.items.selectmenu ).selectmenu( "refresh" ); + } this._callChildMethod( "refresh" ); } From 3e1478a8abe2b1a0412e598ec4d63a04cbe4ca48 Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Wed, 22 Oct 2014 09:32:41 -0400 Subject: [PATCH 70/73] Controlgroup: Add extension points for special options and refresh Methods of new widgets added via the items option. --- ui/controlgroup.js | 61 +++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/ui/controlgroup.js b/ui/controlgroup.js index 2a5a0af275f..0a518f7f993 100644 --- a/ui/controlgroup.js +++ b/ui/controlgroup.js @@ -62,31 +62,15 @@ $.widget( "ui.controlgroup", { " ui-corner-bottom ui-corner-left ui-corner-tl ui-corner-tr" ); }, - _callChildMethod: function( method, filter ) { + _callChildMethod: function( method ) { var that = this; $.each( this.options.items, function( widget, selector ) { var options = {}; - switch ( widget ) { - case "button": - options.classes = { - "ui-button": null - }; - break; - case "checkboxradio": - options.classes = { - "ui-checkbox-label": null, - "ui-radio-label": null - }; - break; - case "selectmenu": - options.classes = { - "ui-selectmenu-button-open": null, - "ui-selectmenu-button-closed": null - }; - break; + if ( that[ "_" + widget + "_options" ] ) { + options = that[ "_" + widget + "_options" ](); } if ( $.fn[ widget ] && selector ) { - that.element.children( selector ).not( filter )[ widget ]( method ? + that.element.children( selector )[ widget ]( method ? method : options ); } }); @@ -130,8 +114,7 @@ $.widget( "ui.controlgroup", { this._super( key, value ); if ( key === "direction" ) { - this.element.removeClass( "ui-controlgroup-" + original ) - .addClass( "ui-controlgroup-" + value ); + this.element.removeClass( "ui-controlgroup-" + original ); } if ( key === "disabled" ) { this._callChildMethod( value ? "disable" : "enable" ); @@ -141,21 +124,11 @@ $.widget( "ui.controlgroup", { }, - refresh: function() { + _refresh_selectmenu: function() { var firstClasses = {}, lastClasses = {}, vertical = ( this.options.direction === "vertical" ); - this.element.addClass( this._classes( "ui-controlgroup ui-controlgroup-" + - this.options.direction ) ); - this._callChildMethod( undefined ); - this.visible = this.element.children( ".ui-button" ).removeClass( function(index, css) { - return ( css.match( /ui-corner-[a-z]*/g ) || [] ).join( " " ); - }).filter( this.options.excludeInvisible ? ":visible" : "*" ); - this.first = this.visible.filter( ":first" ) - .addClass( "ui-corner-" + ( vertical ? "top" : "left" ) ); - this.last = this.visible.filter( ":last" ) - .addClass( "ui-corner-" + ( vertical ? "bottom" : "right" ) ); if ( $.ui.selectmenu ) { if ( this.first.is( ".ui-selectmenu-button" ) && !vertical ) { firstClasses[ "ui-selectmenu-button-open" ] = "ui-corner-tl"; @@ -176,6 +149,28 @@ $.widget( "ui.controlgroup", { } this.element.find( this.options.items.selectmenu ).selectmenu( "refresh" ); } + }, + + refresh: function() { + var that = this, + vertical = ( this.options.direction === "vertical" ); + this.element.addClass( this._classes( "ui-controlgroup ui-controlgroup-" + + this.options.direction ) ); + this._callChildMethod( undefined ); + this.visible = this.element.children( ".ui-button" ).removeClass( function(index, css) { + return ( css.match( /ui-corner-[a-z]*/g ) || [] ).join( " " ); + }).filter( this.options.excludeInvisible ? ":visible" : "*" ); + + this.first = this.visible.eq( 0 ) + .addClass( "ui-corner-" + ( vertical ? "top" : "left" ) ); + this.last = this.visible.last() + .addClass( "ui-corner-" + ( vertical ? "bottom" : "right" ) ); + + $.each( this.options.items, function( widget ) { + if ( that[ "_refresh_" + widget ] ) { + that[ "_refresh_" + widget ](); + } + }); this._callChildMethod( "refresh" ); } From 5969ce65979a99c0294e3d75472efe276e5c9d29 Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Wed, 12 Nov 2014 12:14:38 -0500 Subject: [PATCH 71/73] Button: breakup deprecated tests --- demos/controlgroup/default.html | 105 ------------------ demos/controlgroup/index.html | 3 - tests/unit/button/button.html | 3 + tests/unit/button/button_common_deprecated.js | 22 ++++ tests/unit/button/button_core_deprecated.js | 12 ++ tests/unit/button/button_deprecated.html | 80 +++++++++++++ ui/button.js | 13 ++- ui/checkboxradio.js | 20 ++-- 8 files changed, 132 insertions(+), 126 deletions(-) create mode 100644 tests/unit/button/button_common_deprecated.js create mode 100644 tests/unit/button/button_core_deprecated.js create mode 100644 tests/unit/button/button_deprecated.html diff --git a/demos/controlgroup/default.html b/demos/controlgroup/default.html index 75c8c89fc4f..de865b1f476 100644 --- a/demos/controlgroup/default.html +++ b/demos/controlgroup/default.html @@ -2,11 +2,7 @@ -<<<<<<< HEAD jQuery UI Controlgroup - Default Functionality -======= - jQuery UI Controlgroup - Default Funstionality ->>>>>>> 14168e2... Controlgroup: Inital commit of new widget @@ -34,17 +30,13 @@ .ui-controlgroup-vertical select { width: 100%; } -<<<<<<< HEAD .ui-controlgroup.ui-controlgroup-vertical > button.ui-button { text-align: center; } -======= ->>>>>>> 14168e2... Controlgroup: Inital commit of new widget
    -<<<<<<< HEAD

    A Controlgroup featuring various form controls

    @@ -93,102 +85,5 @@

    Controlgroup

    - -======= -

    Some buttons with various combinations of text and icons.

    -
    -
    -

    Widget

    -
    - - - - - - - -
    -
    -
    - - - - - - - -
    -
    -
    -

    CSS

    -
    - - - - - -
    -
    -
    - - - - - -
    -
    ->>>>>>> 14168e2... Controlgroup: Inital commit of new widget diff --git a/demos/controlgroup/index.html b/demos/controlgroup/index.html index 8fd3f752f89..58e2f7eda7a 100644 --- a/demos/controlgroup/index.html +++ b/demos/controlgroup/index.html @@ -9,10 +9,7 @@ diff --git a/tests/unit/button/button.html b/tests/unit/button/button.html index 762eaa1dd68..d8a5df9c5b1 100644 --- a/tests/unit/button/button.html +++ b/tests/unit/button/button.html @@ -5,6 +5,9 @@ jQuery UI Button Test Suite + diff --git a/tests/unit/button/button_common_deprecated.js b/tests/unit/button/button_common_deprecated.js new file mode 100644 index 00000000000..cfcccb38d94 --- /dev/null +++ b/tests/unit/button/button_common_deprecated.js @@ -0,0 +1,22 @@ +TestHelpers.commonWidgetTests( "button", { + defaults: { + disabled: null, + showLabel: true, + label: null, + icon: null, + iconPosition: "beginning", + text: true, + icons: { + primary: null, + secondary: null + }, + classes: { + "ui-button": "ui-corner-all", + "ui-button-icon-only": "", + "ui-button-icon": "" + }, + + // Callbacks + create: null + } +}); diff --git a/tests/unit/button/button_core_deprecated.js b/tests/unit/button/button_core_deprecated.js new file mode 100644 index 00000000000..3db47a7ec85 --- /dev/null +++ b/tests/unit/button/button_core_deprecated.js @@ -0,0 +1,12 @@ +/* + * button_core.js + */ + + +(function($) { + +module( "Button: core deprecated" ); + + + +})(jQuery); diff --git a/tests/unit/button/button_deprecated.html b/tests/unit/button/button_deprecated.html new file mode 100644 index 00000000000..feb5bfd603b --- /dev/null +++ b/tests/unit/button/button_deprecated.html @@ -0,0 +1,80 @@ + + + + + jQuery UI Button Test Suite + + + + + + + + + + + + + + + + + + + +
    +
    + +
    + +
    + + + +
    +
    + + + +
    + +
    + + + +
    + +
    +
    + + + +
    +
    +
    +
    + + + +
    +
    + + + + +
    + + + +
    + + diff --git a/ui/button.js b/ui/button.js index 6775a6cb432..16e66105e09 100644 --- a/ui/button.js +++ b/ui/button.js @@ -56,7 +56,7 @@ $.widget( "ui.button", { this.isInput = this.element.is( "input" ); this.originalLabel = this.isInput ? this.element.val() : this.element.html(); - disabled = this.element.prop( "disabled" ); + disabled = this.element[ 0 ].disabled; if ( disabled != null ) { options.disabled = disabled; } @@ -77,7 +77,7 @@ $.widget( "ui.button", { formElement.on( "reset" + this.eventNamespace, formResetHandler ); if ( this.options.disabled == null ) { - this.options.disabled = this.element.prop( "disabled" ) || false; + this.options.disabled = this.element[ 0 ].disabled || false; } this.hasTitle = this.element.attr( "title" ); @@ -206,7 +206,8 @@ $.widget( "ui.button", { } this._super( key, value ); if ( key === "disabled" ) { - this.element.toggleClass( "ui-state-disabled", value ).prop( "disabled", value ).blur(); + this.element.toggleClass( "ui-state-disabled", value )[ 0 ].disabled = value; + this.element.blur(); } }, @@ -215,7 +216,7 @@ $.widget( "ui.button", { // Make sure to only check disabled if its an element that supports this otherwise // check for the disabled class to determine state var isDisabled = this.element.is( "input, button" ) ? - this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" ); + this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" ); if ( isDisabled !== this.options.disabled ) { this._setOptions({ "disabled": isDisabled }); @@ -226,7 +227,7 @@ $.widget( "ui.button", { }); // DEPRECATED -if ( $.uiBackCompat === false ) { +if ( $.uiBackCompat !== false ) { // Text and Icons options $.widget( "ui.button", $.ui.button, { @@ -273,7 +274,7 @@ if ( $.uiBackCompat === false ) { }); $.fn.button = (function( orig ) { return function() { - if ( this[ 0 ].tagName === "input" && ( this.attr( "type") === "checkbox" || + if ( this.tagName === "input" && ( this.attr( "type") === "checkbox" || this.attr( "type" ) === "radio" ) ) { if ( $.ui.checkboxradio ) { if ( arguments.length === 0 ) { diff --git a/ui/checkboxradio.js b/ui/checkboxradio.js index d7c68fac22a..16c1365afc7 100644 --- a/ui/checkboxradio.js +++ b/ui/checkboxradio.js @@ -57,11 +57,7 @@ $.widget( "ui.checkboxradio", { options: { disabled: null, label: null, -<<<<<<< HEAD icon: true, -======= - icon: false, ->>>>>>> db16c96... Checkboxradio: add classes option classes: { "ui-checkboxradio": "", "ui-checkboxradio-label": "ui-corner-all", @@ -83,7 +79,7 @@ $.widget( "ui.checkboxradio", { that.originalLabel += ( this.nodeType === 3 ) ? $( this ).text() : this.outerHTML; }); - disabled = this.element.prop( "disabled" ); + disabled = this.element[ 0 ].disabled; if ( disabled != null ) { options.disabled = disabled; } @@ -104,7 +100,7 @@ $.widget( "ui.checkboxradio", { formElement.on( "reset" + this.eventNamespace, formResetHandler ); if ( this.options.disabled == null ) { - this.options.disabled = this.element.prop( "disabled" ) || false; + this.options.disabled = this.element[ 0 ].disabled || false; } this._readType(); @@ -171,7 +167,7 @@ $.widget( "ui.checkboxradio", { }, _enhance: function() { - var checked = this.element.is( ":checked" ); + var checked = this.element[ 0 ].checked; this._setOption( "disabled", this.options.disabled ); this._updateIcon( checked ); @@ -200,7 +196,7 @@ $.widget( "ui.checkboxradio", { }, _toggleClasses: function() { - var checked = this.element.is( ":checked" ); + var checked = this.element[ 0 ].checked; this.label.toggleClass( this._classes( "ui-checkboxradio-checked" ) + " ui-state-active", checked ); if ( this.options.icon && this.type === "checkbox" ) { @@ -231,7 +227,7 @@ $.widget( "ui.checkboxradio", { _elementsFromClassKey: function( classKey ) { var parts = classKey.split( "-" ), checkedType = parts[ 2 ] === this.type || parts[ 2 ] === undefined, - checkedClass = parts[ 3 ] === "checked" || this.element.is( ":checked" ); + checkedClass = parts[ 3 ] === "checked" || this.element[ 0 ].checked; switch ( classKey ) { case "ui-checkboxradio": case "ui-checkboxradio-radio-label": @@ -258,7 +254,7 @@ $.widget( "ui.checkboxradio", { this._super( key, value ); if ( key === "disabled" ) { this.label.toggleClass( "ui-state-disabled", !!value ); - this.element.prop( "disabled", !!value ); + this.element[ 0 ].disabled = !!value; return; } if ( key === "label" && value === null ) { @@ -291,8 +287,8 @@ $.widget( "ui.checkboxradio", { }, refresh: function() { - var checked = this.element.is( ":checked" ), - isDisabled = this.element.is( ":disabled" ); + var checked = this.element[ 0 ].checked, + isDisabled = this.element[ 0 ].disabled; this._updateIcon( checked ); this.label.toggleClass( "ui-state-active " + this._classes( "ui-checkboxradio-checked" ), checked ); if ( this.options.label !== null ) { From 2d04b3e2bf86d495deff88c8deea2913e9561286 Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Wed, 3 Dec 2014 11:55:18 -0500 Subject: [PATCH 72/73] Button: Add backcompat tests and fix backcompat issues --- tests/unit/button/button_core_deprecated.js | 18 +++ tests/unit/button/button_deprecated.html | 13 +- tests/unit/button/button_methods.js | 16 +- .../unit/button/button_methods_deprecated.js | 37 +++++ tests/unit/button/button_options.js | 17 +-- .../unit/button/button_options_deprecated.js | 141 ++++++++++++++++++ ui/button.js | 45 ++++-- 7 files changed, 244 insertions(+), 43 deletions(-) create mode 100644 tests/unit/button/button_methods_deprecated.js create mode 100644 tests/unit/button/button_options_deprecated.js diff --git a/tests/unit/button/button_core_deprecated.js b/tests/unit/button/button_core_deprecated.js index 3db47a7ec85..bdba0cf1d81 100644 --- a/tests/unit/button/button_core_deprecated.js +++ b/tests/unit/button/button_core_deprecated.js @@ -7,6 +7,24 @@ module( "Button: core deprecated" ); +test( "Calling button on a checkbox input calls checkboxradio widget", function(){ + var checkbox = $( "#checkbox01" ); + expect( 2 ); + checkbox.button(); + equal( checkbox.is( ":ui-checkboxradio" ), true, + "Calling button on a checkbox creats checkboxradio instance" ); + equal( checkbox.checkboxradio( "option", "icon" ), false, + "Calling button on a checkbox sets the checkboxradio icon option to false" ); +}); +test( "Calling buttonset calls controlgroup", function(){ + var controlgroup = $( ".buttonset" ); + + expect( 1 ); + controlgroup.buttonset(); + + equal( controlgroup.is( ":ui-controlgroup" ), true, + "Calling buttonset creats controlgroup instance" ); +}); })(jQuery); diff --git a/tests/unit/button/button_deprecated.html b/tests/unit/button/button_deprecated.html index feb5bfd603b..02c05fcc9ca 100644 --- a/tests/unit/button/button_deprecated.html +++ b/tests/unit/button/button_deprecated.html @@ -15,18 +15,21 @@ js: [ "ui/core.js", "ui/widget.js", - "ui/button.js" + "ui/button.js", + "ui/checkboxradio.js", + "ui/controlgroup.js" ] }); - - - + + + + @@ -34,7 +37,7 @@
    -
    +
    diff --git a/tests/unit/button/button_methods.js b/tests/unit/button/button_methods.js index 4dc1dc525e6..8e2a8b8a05d 100644 --- a/tests/unit/button/button_methods.js +++ b/tests/unit/button/button_methods.js @@ -14,7 +14,7 @@ test( "destroy", function() { }); test( "refresh: Ensure disabled state is preserved correctly.", function() { - expect( 8 ); + expect( 4 ); var element = $( "" ); element.button({ disabled: true }).button( "refresh" ); @@ -28,25 +28,11 @@ test( "refresh: Ensure disabled state is preserved correctly.", function() { element.button( { disabled: true} ).button( "refresh" ); ok( element.button( "option", "disabled" ), "" ); element.button( { disabled: true} ).prop( "disabled", false ).button( "refresh" ); ok( !element.button( "option", "disabled" ), "Changing a