diff options
author | Felix Nagel <info@felixnagel.com> | 2014-06-20 00:13:20 +0200 |
---|---|---|
committer | Scott González <scott.gonzalez@gmail.com> | 2015-01-29 18:01:29 -0500 |
commit | 9461f6680b5b3b05cdb2dffe3b6d3b004f2666b7 (patch) | |
tree | 04c5c0b0a0d8a926bd08d7dcc8219b6fe86a171c | |
parent | 5df6d39d13e707eee9f5147abd424dfd47eff367 (diff) | |
download | jquery-ui-9461f6680b5b3b05cdb2dffe3b6d3b004f2666b7.tar.gz jquery-ui-9461f6680b5b3b05cdb2dffe3b6d3b004f2666b7.zip |
Calendar: Add buttons option
-rw-r--r-- | demos/calendar/buttonbar.html | 8 | ||||
-rw-r--r-- | tests/unit/calendar/calendar_common.js | 1 | ||||
-rw-r--r-- | tests/unit/calendar/calendar_core.js | 26 | ||||
-rw-r--r-- | tests/unit/calendar/calendar_options.js | 105 | ||||
-rw-r--r-- | tests/unit/calendar/calendar_test_helpers.js | 4 | ||||
-rw-r--r-- | tests/unit/datepicker/datepicker_common.js | 1 | ||||
-rw-r--r-- | tests/unit/datepicker/datepicker_core.js | 2 | ||||
-rw-r--r-- | tests/unit/datepicker/datepicker_options.js | 18 | ||||
-rw-r--r-- | ui/calendar.js | 73 | ||||
-rw-r--r-- | ui/datepicker.js | 4 |
10 files changed, 219 insertions, 23 deletions
diff --git a/demos/calendar/buttonbar.html b/demos/calendar/buttonbar.html index 498fe1041..7ed390b25 100644 --- a/demos/calendar/buttonbar.html +++ b/demos/calendar/buttonbar.html @@ -17,7 +17,11 @@ <script> $(function() { $( "#calendar" ).calendar({ - showButtonPanel: true + buttons: { + "Today": function() { + $( this ).calendar( "valueAsDate", new Date() ); + } + } }); }); </script> @@ -27,7 +31,7 @@ <div id="calendar"></div> <div class="demo-description"> -<p>Display a button for selecting Today's date and a Done button for closing the calendar with the boolean <code>showButtonPanel</code> option. Each button is enabled by default when the bar is displayed, but can be turned off with additional options. Button text is customizable.</p> +<p>Display a button for selecting Today's date with the <code>buttons</code> option.</p> </div> </body> </html> diff --git a/tests/unit/calendar/calendar_common.js b/tests/unit/calendar/calendar_common.js index 49f8b5f05..a669fdfc2 100644 --- a/tests/unit/calendar/calendar_common.js +++ b/tests/unit/calendar/calendar_common.js @@ -1,5 +1,6 @@ TestHelpers.commonWidgetTests( "calendar", { defaults: { + buttons: [], dateFormat: { date: "short" }, disabled: false, eachDay: $.noop, diff --git a/tests/unit/calendar/calendar_core.js b/tests/unit/calendar/calendar_core.js index 0a33363c9..8e3984383 100644 --- a/tests/unit/calendar/calendar_core.js +++ b/tests/unit/calendar/calendar_core.js @@ -5,7 +5,7 @@ module( "calendar: core" ); TestHelpers.testJshint( "calendar" ); test( "base structure", function() { - expect( 22 ); + expect( 26 ); var header, title, table, thead, week, child, buttonpane, element = $( "#calendar" ).calendar(), @@ -14,7 +14,7 @@ test( "base structure", function() { function step1() { ok( !dp.is( ".ui-calendar-rtl" ), "Structure - not right-to-left" ); ok( !dp.is( ".ui-calendar-multi" ), "Structure - not multi-month" ); - equal( dp.children().length, 3, "Structure - child count (header, calendar)" ); + equal( dp.children().length, 2, "Structure - child count (header, calendar)" ); header = dp.children( ":first" ); ok( header.is( "div.ui-calendar-header" ), "Structure - header division" ); @@ -42,17 +42,33 @@ test( "base structure", function() { ok( week.is( "tr" ), "Structure - month table week row" ); equal( week.children().length, 7, "Structure - week child count" ); - element.calendar( "destroy" ); - step2(); } function step2() { + element.calendar( "option", "buttons", { + "test": function() {}, + "test button": function() {} + }); + + equal( dp.children().length, 3, "Structure buttons - child count (header, calendar, buttonpane)" ); + + buttonpane = dp.children( ".ui-calendar-buttonpane" ); + equal( buttonpane.children( "div.ui-calendar-buttonset" ).length, 1, "Structure buttons - buttonset" ); + equal( buttonpane.find( "button.ui-button:first" ).text(), "test", "Structure buttons - buttonset" ); + equal( buttonpane.find( "button.ui-button:eq(1)" ).text(), "test button", "Structure buttons - buttonset" ); + + element.calendar( "destroy" ); + step3(); + } + + function step3() { + // Multi-month 2 element = $( "#calendar" ).calendar( { numberOfMonths: 2 } ); dp = element.calendar( "widget" ); ok( dp.is( ".ui-calendar-multi" ), "Structure multi [2] - multi-month" ); - equal( dp.children().length, 4, "Structure multi [2] - child count" ); + equal( dp.children().length, 3, "Structure multi [2] - child count" ); child = dp.children( ":eq(2)" ); ok( child.is( "div.ui-calendar-row-break" ), "Structure multi [2] - row break" ); diff --git a/tests/unit/calendar/calendar_options.js b/tests/unit/calendar/calendar_options.js index 6be4f8733..e5a09d3d8 100644 --- a/tests/unit/calendar/calendar_options.js +++ b/tests/unit/calendar/calendar_options.js @@ -2,6 +2,111 @@ module( "calendar: options" ); +test("buttons", function() { + expect( 21 ); + + var button, i, newButtons, + buttons = { + "Ok": function( event ) { + ok(true, "button click fires callback" ); + equal( this, element[ 0 ], "context of callback" ); + equal( event.target, button[ 0 ], "event target" ); + }, + "Cancel": function( event ) { + ok( true, "button click fires callback" ); + equal( this, element[ 0 ], "context of callback" ); + equal( event.target, button[ 1 ], "event target" ); + } + }, + element = $( "#calendar" ).calendar({ buttons: buttons }); + + button = element.calendar( "widget" ).find( ".ui-calendar-buttonpane button" ); + equal( button.length, 2, "number of buttons" ); + + i = 0; + $.each( buttons, function( key ) { + equal( button.eq( i ).text(), key, "text of button " + ( i + 1 ) ); + i++; + }); + + ok( button.parent().hasClass( "ui-calendar-buttonset" ), "buttons in container" ); + ok( + element.calendar( "widget" ).hasClass( "ui-calendar-buttons" ), + "calendar wrapper adds class about having buttons" + ); + + button.trigger( "click" ); + + newButtons = { + "Close": function( event ) { + ok( true, "button click fires callback" ); + equal( this, element[ 0 ], "context of callback" ); + equal( event.target, button[ 0 ], "event target" ); + } + }; + + deepEqual( + element.calendar( "option", "buttons" ), + buttons, + ".calendar('option', 'buttons') getter" + ); + element.calendar( "option", "buttons", newButtons ); + deepEqual( + element.calendar( "option", "buttons" ), + newButtons, + ".calendar('option', 'buttons', ...) setter" + ); + + button = element.calendar( "widget" ).find( ".ui-calendar-buttonpane button" ); + equal( button.length, 1, "number of buttons after setter" ); + button.trigger( "click" ); + + i = 0; + $.each( newButtons, function( key ) { + equal( button.eq( i ).text(), key, "text of button " + ( i + 1 ) ); + i += 1; + }); + + element.calendar( "option", "buttons", null ); + button = element.calendar( "widget" ).find( ".ui-calendar-buttonpane button" ); + equal( button.length, 0, "all buttons have been removed" ); + equal( element.find( ".ui-calendar-buttonset" ).length, 0, "buttonset has been removed" ); + equal( element.hasClass( "ui-calendar-buttons" ), false, "calendar element removes class about having buttons" ); + + element.remove(); +}); + +test( "buttons - advanced", function() { + expect( 7 ); + + var buttons, + element = $( "#calendar" ).calendar({ + buttons: [{ + text: "a button", + "class": "additional-class", + id: "my-button-id", + click: function() { + equal( this, element[ 0 ], "correct context" ); + }, + icons: { + primary: "ui-icon-cancel" + }, + showText: false + }] + }); + + buttons = element.calendar( "widget" ).find( ".ui-calendar-buttonpane button" ); + equal( buttons.length, 1, "correct number of buttons" ); + 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 ); + buttons.click(); + + element.remove(); +}); + test( "dateFormat", function() { expect( 2 ); var element = $( "#calendar" ).calendar({ diff --git a/tests/unit/calendar/calendar_test_helpers.js b/tests/unit/calendar/calendar_test_helpers.js index 94f3644c3..c5dfbd4a2 100644 --- a/tests/unit/calendar/calendar_test_helpers.js +++ b/tests/unit/calendar/calendar_test_helpers.js @@ -15,7 +15,9 @@ TestHelpers.calendar = { equal( d1.toString(), d2.toString(), message ); }, focusGrid: function( element ) { - element.find( "table:tabbable" ).simulate( "focus" ); + element.find( ":tabbable" ).last().simulate( "focus" ); + $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.TAB } ); + $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.TAB } ); return $( ":focus" ); } diff --git a/tests/unit/datepicker/datepicker_common.js b/tests/unit/datepicker/datepicker_common.js index 1544db58e..25c6d4298 100644 --- a/tests/unit/datepicker/datepicker_common.js +++ b/tests/unit/datepicker/datepicker_common.js @@ -1,6 +1,7 @@ TestHelpers.commonWidgetTests( "datepicker", { defaults: { appendTo: null, + buttons: [], dateFormat: { date: "short" }, disabled: false, eachDay: $.noop, diff --git a/tests/unit/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js index f0d93c781..ffb7ab6c4 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -29,7 +29,7 @@ asyncTest( "base structure", function() { setTimeout(function() { ok( widget.is( ":visible" ), "Datepicker visible" ); - equal( widget.children().length, 3, "Child count" ); + equal( widget.children().length, 2, "Child count" ); ok( widget.is( ".ui-calendar" ), "Class ui-calendar" ); ok( widget.is( ".ui-datepicker" ), "Class ui-datepicker" ); ok( widget.is( ".ui-front" ), "Class ui-front" ); diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index 16546424d..01b1b6556 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -40,6 +40,22 @@ test( "appendTo", function() { input.datepicker( "destroy" ); }); +test("buttons", function() { + expect( 3 ); + + var button, + buttons = { + "Ok": function() {}, + "Cancel": function() {} + }, + element = $( "#datepicker" ).datepicker({ buttons: buttons }); + + button = element.datepicker( "widget" ).find( ".ui-calendar-buttonpane button" ); + equal( button.length, 2, "number of buttons" ); + ok( button.parent().hasClass( "ui-calendar-buttonset" ), "buttons in container"); + ok( element.datepicker( "widget" ).hasClass( "ui-calendar-buttons" ), "calendar wrapper adds class about having buttons" ); +}); + test( "dateFormat", function() { expect( 2 ); var input = $( "#datepicker" ).val( "1/1/14" ).datepicker(), @@ -149,7 +165,7 @@ test( "showWeek", function() { input.datepicker( "option", "showWeek", true ); equal( container.find( "thead th" ).length, 8, "supports changing option after init" ); }); - + test( "min / max", function() { expect( 14 ); diff --git a/ui/calendar.js b/ui/calendar.js index 0d96d4030..370f70123 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -13,6 +13,7 @@ // AMD. Register as an anonymous module. // TODO Add globalize and $.date + // TODO: Keep button even if its optional? define([ "jquery", "./core", @@ -29,6 +30,7 @@ return $.widget( "ui.calendar", { version: "@VERSION", options: { + buttons: [], dateFormat: { date: "short" }, eachDay: $.noop, max: null, @@ -44,6 +46,7 @@ return $.widget( "ui.calendar", { _create: function() { this.id = this.element.uniqueId().attr( "id" ); this.labels = Globalize.translate( "datepicker" ); + this.buttonClickContext = this.element[ 0 ]; this.date = $.date( this.options.value, this.options.dateFormat ).select(); this.date.eachDay = this.options.eachDay; @@ -59,10 +62,6 @@ return $.widget( "ui.calendar", { this.date.adjust( "M", this.options.numberOfMonths ); this.refresh(); }, - "click .ui-calendar-current": function( event ) { - event.preventDefault(); - this._select( event, new Date().getTime() ); - }, "mousedown .ui-calendar-calendar a": function( event ) { event.preventDefault(); @@ -144,7 +143,7 @@ return $.widget( "ui.calendar", { pickerHtml = ""; if ( this.options.numberOfMonths === 1 ) { - pickerHtml = this._buildHeader() + this._buildGrid() + this._buildButtons(); + pickerHtml = this._buildHeader() + this._buildGrid(); } else { pickerHtml = this._buildMultiplePicker(); classes += " ui-calendar-multi"; @@ -158,6 +157,8 @@ return $.widget( "ui.calendar", { }) .html( pickerHtml ); + this._createButtonPane(); + this.grid = this.element.find( ".ui-calendar-calendar" ); }, @@ -190,7 +191,7 @@ return $.widget( "ui.calendar", { html += this._buildTitlebar() + "</div>" + this._buildGrid() + "</div>"; } - html += "<div class='ui-calendar-row-break'></div>" + this._buildButtons(); + html += "<div class='ui-calendar-row-break'></div>"; this.date = currentDate; @@ -363,12 +364,55 @@ return $.widget( "ui.calendar", { return content; }, - _buildButtons: function() { - return "<div class='ui-calendar-buttonpane ui-widget-content'>" + - "<button class='ui-calendar-current'>" + - this._getTranslation( "currentText" ) + - "</button>" + - "</div>"; + _createButtonPane: function() { + this.buttonPane = $( "<div>" ) + .addClass( "ui-calendar-buttonpane ui-widget-content ui-helper-clearfix" ); + + this.buttonSet = $( "<div>" ) + .addClass( "ui-calendar-buttonset" ) + .appendTo( this.buttonPane ); + + this._createButtons(); + }, + + _createButtons: function() { + var that = this, + buttons = this.options.buttons; + + this.buttonPane.remove(); + this.buttonSet.empty(); + + if ( $.isEmptyObject( buttons ) || ( $.isArray( buttons ) && !buttons.length ) ) { + this.element.removeClass( "ui-calendar-buttons" ); + return; + } + + $.each( buttons, function( name, props ) { + var click, buttonOptions; + props = $.isFunction( props ) ? + { click: props, text: name } : + props; + + // Default to a non-submitting button + props = $.extend( { type: "button" }, props ); + + // Change the context for the click callback to be the main element + click = props.click; + props.click = function() { + click.apply( that.buttonClickContext, arguments ); + }; + buttonOptions = { + icons: props.icons, + text: props.showText + }; + delete props.icons; + delete props.showText; + $( "<button></button>", props ) + .button( buttonOptions ) + .appendTo( that.buttonSet ); + }); + this.element.addClass( "ui-calendar-buttons" ); + this.buttonPane.appendTo( this.element ); }, // Refreshing the entire calendar during interaction confuses screen readers, specifically @@ -389,6 +433,7 @@ return $.widget( "ui.calendar", { .children().html( this.labels.prevText ); $( ".ui-calendar-next", this.element ).attr( "title", this.labels.nextText ) .children().html( this.labels.nextText ); + this._createButtons(); } else { this._refreshMultiplePicker(); } @@ -496,6 +541,10 @@ return $.widget( "ui.calendar", { this._super( key, value ); + if ( key === "buttons" ) { + this._createButtons(); + } + if ( key === "eachDay" ) { this.date.eachDay = value; this.refresh(); diff --git a/ui/datepicker.js b/ui/datepicker.js index 1adb08bd4..c7df60adc 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -32,7 +32,7 @@ }(function( $ ) { var widget, - calendarOptions = [ "dateFormat", "eachDay", "max", "min", "numberOfMonths", "showWeek" ]; + calendarOptions = [ "buttons", "dateFormat", "eachDay", "max", "min", "numberOfMonths", "showWeek" ]; widget = $.widget( "ui.datepicker", { version: "@VERSION", @@ -97,6 +97,8 @@ widget = $.widget( "ui.datepicker", { }) ) .calendar( "instance" ); + this.calendarInstance.buttonClickContext = that.element[ 0 ]; + this._setHiddenPicker(); this.element.attr({ |