aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Nagel <info@felixnagel.com>2014-06-20 00:13:20 +0200
committerScott González <scott.gonzalez@gmail.com>2015-01-29 18:01:29 -0500
commit9461f6680b5b3b05cdb2dffe3b6d3b004f2666b7 (patch)
tree04c5c0b0a0d8a926bd08d7dcc8219b6fe86a171c
parent5df6d39d13e707eee9f5147abd424dfd47eff367 (diff)
downloadjquery-ui-9461f6680b5b3b05cdb2dffe3b6d3b004f2666b7.tar.gz
jquery-ui-9461f6680b5b3b05cdb2dffe3b6d3b004f2666b7.zip
Calendar: Add buttons option
-rw-r--r--demos/calendar/buttonbar.html8
-rw-r--r--tests/unit/calendar/calendar_common.js1
-rw-r--r--tests/unit/calendar/calendar_core.js26
-rw-r--r--tests/unit/calendar/calendar_options.js105
-rw-r--r--tests/unit/calendar/calendar_test_helpers.js4
-rw-r--r--tests/unit/datepicker/datepicker_common.js1
-rw-r--r--tests/unit/datepicker/datepicker_core.js2
-rw-r--r--tests/unit/datepicker/datepicker_options.js18
-rw-r--r--ui/calendar.js73
-rw-r--r--ui/datepicker.js4
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({