Calendar: Use classes option for non performance critical rendering

This commit is contained in:
Felix Nagel 2016-04-16 16:49:40 +02:00
parent e02ef66389
commit bd7a6f1468
2 changed files with 135 additions and 109 deletions

View File

@ -7,7 +7,13 @@ define( [
common.testWidget( "calendar", { common.testWidget( "calendar", {
defaults: { defaults: {
buttons: [], buttons: [],
classes: {}, classes: {
"ui-calendar": "ui-corner-all",
"ui-calendar-header-first": "ui-corner-left",
"ui-calendar-header-last": "ui-corner-right",
"ui-calendar-prev": "ui-corner-all",
"ui-calendar-next": "ui-corner-all"
},
disabled: false, disabled: false,
dateFormat: { date: "short" }, dateFormat: { date: "short" },
eachDay: $.noop, eachDay: $.noop,

View File

@ -45,6 +45,13 @@ return $.widget( "ui.calendar", {
version: "@VERSION", version: "@VERSION",
options: { options: {
buttons: [], buttons: [],
classes: {
"ui-calendar": "ui-corner-all",
"ui-calendar-header-first": "ui-corner-left",
"ui-calendar-header-last": "ui-corner-right",
"ui-calendar-prev": "ui-corner-all",
"ui-calendar-next": "ui-corner-all"
},
dateFormat: { date: "short" }, dateFormat: { date: "short" },
eachDay: $.noop, eachDay: $.noop,
labels: { labels: {
@ -119,7 +126,7 @@ return $.widget( "ui.calendar", {
}, },
_hover: function( event ) { _hover: function( event ) {
$( event.currentTarget ).toggleClass( "ui-state-hover" ); this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
}, },
_handleKeydown: function( event ) { _handleKeydown: function( event ) {
@ -193,14 +200,15 @@ return $.widget( "ui.calendar", {
}, },
_updateDayElement: function( state ) { _updateDayElement: function( state ) {
var id = this._getDayId( this.date ); var id = this._getDayId( this.date ),
button = this._getDateElement( id ).children( "button" );
this.grid this.grid.attr( "aria-activedescendant", id );
.attr( "aria-activedescendant", id )
.find( "button." + state )
.removeClass( state );
return this._getDateElement( id ).children( "button" ).addClass( state ); this._removeClass( this.grid.find( "button." + state ), null, state );
this._addClass( button, null, state );
return button;
}, },
_getDateElement: function( id ) { _getDateElement: function( id ) {
@ -232,37 +240,40 @@ return $.widget( "ui.calendar", {
}, },
_createCalendar: function() { _createCalendar: function() {
var classes = "ui-calendar ui-widget ui-widget-content ui-helper-clearfix ui-corner-all", this.element
pickerHtml = this._buildHeaderButtons(); .attr( "role", "region" )
.append( this._buildHeaderButtons() );
if ( this.options.numberOfMonths === 1 ) { if ( this.options.numberOfMonths === 1 ) {
pickerHtml += this._buildHeader() + this._buildGrid(); this._buildSinglePicker();
this.element.attr( "aria-labelledby", this.gridId + "-title" );
} else { } else {
pickerHtml += this._buildMultiplePicker(); this._buildMultiplePicker();
classes += " ui-calendar-multi";
} }
this.element this._addClass( this.element, "ui-calendar", "ui-widget ui-widget-content ui-helper-clearfix" );
.addClass( classes )
.attr( "role", "region" )
.html( pickerHtml );
this.prevButton = this.element.find( ".ui-calendar-prev" );
this.nextButton = this.element.find( ".ui-calendar-next" );
this._refreshHeaderButtons(); this._refreshHeaderButtons();
this._createButtonPane(); this._createButtonPane();
this.grid = this.element.find( ".ui-calendar-calendar" ); this.grid = this.element.find( ".ui-calendar-calendar" );
}, },
_buildSinglePicker: function() {
var header = this._buildHeader();
this._addClass( header, "ui-calendar-header-first ui-calendar-header-last" );
this.element
.attr( "aria-labelledby", this.gridId + "-title" )
.append( header )
.append( this._buildGrid() );
},
_buildMultiplePicker: function() { _buildMultiplePicker: function() {
var headerClass, var element, header,
html = "", rowBreak = $( "<div>" ),
currentDate = this.viewDate, currentDate = this.viewDate,
months = this.viewDate.months( this.options.numberOfMonths - 1 ), months = this.viewDate.months( this.options.numberOfMonths - 1 ),
labelledby = [], labelledBy = [],
i = 0; i = 0;
for ( ; i < months.length; i++ ) { for ( ; i < months.length; i++ ) {
@ -270,108 +281,120 @@ return $.widget( "ui.calendar", {
// TODO: Shouldn't we pass date as a parameter to build* fns instead of setting this.date? // TODO: Shouldn't we pass date as a parameter to build* fns instead of setting this.date?
this.viewDate = months[ i ]; this.viewDate = months[ i ];
this.gridId = this.id + "-" + i; this.gridId = this.id + "-" + i;
labelledBy.push( this.gridId + "-title" );
labelledby.push( this.gridId + "-title" ); element = $( "<div>" );
headerClass = "ui-calendar-header ui-widget-header ui-helper-clearfix"; this._addClass( element, "ui-calendar-group" );
if ( months[ i ].first ) {
headerClass += " ui-corner-left";
} else if ( months[ i ].last ) {
headerClass += " ui-corner-right";
}
html += "<div class='ui-calendar-group'>"; header = this._buildHeader();
html += "<div class='" + headerClass + "'>" + this._addClass( header, "ui-calendar-header-" +
this._buildTitlebar() + "</div>"; ( ( months[ i ].first ) ? "first" : ( months[ i ].last ) ? "last" : "middle" )
html += this._buildGrid() + "</div>"; );
element.appendTo( this.element )
.append( header )
.append( this._buildGrid() );
} }
html += "<div class='ui-calendar-row-break'></div>"; this._addClass( this.element, "ui-calendar-multi" )
._addClass( rowBreak, "ui-calendar-row-break" );
this.element.attr( "aria-labelledby", labelledby.join( " " ) ); this.element
.attr( "aria-labelledby", labelledBy.join( " " ) )
.append( rowBreak );
this.viewDate = currentDate; this.viewDate = currentDate;
return html;
},
_buildHeader: function() {
return "<div class='ui-calendar-header ui-widget-header ui-helper-clearfix ui-corner-all'>" +
this._buildTitlebar() +
"</div>";
}, },
_buildHeaderButtons: function() { _buildHeaderButtons: function() {
return "<div class='ui-calendar-header-buttons'>" + var buttons = $( "<div>" );
this._buildPreviousLink() +
this._buildNextLink() + this.prevButton = $( "<button>", {
"</div>"; html: "<span class='ui-icon ui-icon-circle-triangle-w'></span>"
} );
this.nextButton = $( "<button>", {
html: "<span class='ui-icon ui-icon-circle-triangle-e'></span>"
} );
this._addClass( buttons, "ui-calendar-header-buttons" )
._addClass( this.prevButton, "ui-calendar-prev" )
._addClass( this.nextButton, "ui-calendar-next" );
return buttons
.append( this.prevButton )
.append( this.nextButton );
}, },
_buildPreviousLink: function() { _buildHeader: function() {
return "<button class='ui-calendar-prev ui-corner-all'>" + var header = $( "<div>" ),
"<span class='ui-icon ui-icon-circle-triangle-w'></span>" + title = $( "<div>", { role: "header", id: this.gridId + "-title" } ),
"</button>"; notice = $( "<span>" ).text( ", " + this._getTranslation( "datePickerRole" ) );
},
_buildNextLink: function() { this._addClass( header, "ui-calendar-header", "ui-widget-header ui-helper-clearfix" )
return "<button class='ui-calendar-next ui-corner-all'>" + ._addClass( notice, null, "ui-helper-hidden-accessible" );
"<span class='ui-icon ui-icon-circle-triangle-e'></span>" +
"</button>";
},
_buildTitlebar: function() { return header.append(
return "<div role='header' id='" + this.gridId + "-title'>" + title
"<div id='" + this.gridId + "-month-label' role='alert' class='ui-calendar-title'>" + .append( this._buildTitle() )
this._buildTitle() + .append( notice )
"</div>" + );
"<span class='ui-helper-hidden-accessible'>, " +
this._getTranslation( "datePickerRole" ) +
"</span>" +
"</div>";
}, },
_buildTitle: function() { _buildTitle: function() {
return "<span class='ui-calendar-month'>" + var title = $( "<div>", { role: "alert", id: this.gridId + "-month-label" } ),
this.viewDate.monthName() + month = $( "<span>" ).text( this.viewDate.monthName() ),
"</span> " + year = $( "<span>" ).text( this.viewDate.year() );
"<span class='ui-calendar-year'>" +
this.viewDate.year() + this._addClass( title, "ui-calendar-title" )
"</span>"; ._addClass( month, "ui-calendar-month" )
._addClass( year, "ui-calendar-year" );
return title
.append( month )
.append( " " )
.append( year );
}, },
_buildGrid: function() { _buildGrid: function() {
return "<table class='ui-calendar-calendar' role='grid' aria-readonly='true' " + var table = $( "<table>", {
"aria-labelledby='" + this.gridId + "-month-label' tabindex='0' " + role: "grid",
"aria-activedescendant='" + this._getDayId( this.date ) + "'>" + tabindex: 0,
this._buildGridHeading() + "aria-readonly": true,
this._buildGridBody() + "aria-labelledby": this.gridId + "-month-label",
"</table>"; "aria-activedescendant": this._getDayId( this.date )
} );
this._addClass( table, "ui-calendar-calendar" );
return table
.append( this._buildGridHeading() )
.append( this._buildGridBody() );
}, },
_buildGridHeading: function() { _buildGridHeading: function() {
var cells = "", var head = $( "<thead role='presentation'>" ),
week = $( "<th>" ),
row = $( "<tr role='row'>" ),
i = 0, i = 0,
weekDayLength = this.viewDate.weekdays().length, weekDayLength = this.viewDate.weekdays().length,
weekdays = this.viewDate.weekdays(); weekdays = this.viewDate.weekdays();
if ( this.options.showWeek ) { if ( this.options.showWeek ) {
cells += "<th class='ui-calendar-week-col'>" + this._getTranslation( "weekHeader" ) + "</th>"; this._addClass( week, "ui-calendar-week-col" );
} row.append( week.text( this._getTranslation( "weekHeader" ) ) );
for ( ; i < weekDayLength; i++ ) {
cells += this._buildGridHeaderCell( weekdays[ i ] );
} }
return "<thead role='presentation'>" + for ( ; i < weekDayLength; i++ ) {
"<tr role='row'>" + cells + "</tr>" + row.append( this._buildGridHeaderCell( weekdays[ i ] ) );
"</thead>"; }
return head.append( row );
}, },
_buildGridHeaderCell: function( day ) { _buildGridHeaderCell: function( day ) {
return "<th role='columnheader' abbr='" + day.fullname + "' aria-label='" + day.fullname + "'>" + return $( "<th role='columnheader' abbr='" + day.fullname + "' aria-label='" + day.fullname + "'>" +
"<span title='" + day.fullname + "'>" + "<span title='" + day.fullname + "'>" + day.shortname + "</span>" +
day.shortname + "</th>" );
"</span>" +
"</th>";
}, },
_buildGridBody: function() { _buildGridBody: function() {
@ -468,12 +491,11 @@ return $.widget( "ui.calendar", {
}, },
_createButtonPane: function() { _createButtonPane: function() {
this.buttonPane = $( "<div>" ) this.buttonPane = $( "<div>" );
.addClass( "ui-calendar-buttonpane ui-widget-content ui-helper-clearfix" ); this.buttonSet = $( "<div>" ).appendTo( this.buttonPane );
this.buttonSet = $( "<div>" ) this._addClass( this.buttonPane, "ui-calendar-buttonpane", "ui-widget-content ui-helper-clearfix" )
.addClass( "ui-calendar-buttonset" ) ._addClass( this.buttonSet, "ui-calendar-buttonset" );
.appendTo( this.buttonPane );
this._createButtons(); this._createButtons();
}, },
@ -486,7 +508,7 @@ return $.widget( "ui.calendar", {
this.buttonSet.empty(); this.buttonSet.empty();
if ( $.isEmptyObject( buttons ) || ( $.isArray( buttons ) && !buttons.length ) ) { if ( $.isEmptyObject( buttons ) || ( $.isArray( buttons ) && !buttons.length ) ) {
this.element.removeClass( "ui-calendar-buttons" ); this._removeClass( this.element, "ui-calendar-buttons" );
return; return;
} }
@ -519,7 +541,8 @@ return $.widget( "ui.calendar", {
click.apply( that.buttonClickContext, arguments ); click.apply( that.buttonClickContext, arguments );
} ); } );
} ); } );
this.element.addClass( "ui-calendar-buttons" );
this._addClass( this.element, "ui-calendar-buttons" );
this.buttonPane.appendTo( this.element ); this.buttonPane.appendTo( this.element );
}, },
@ -532,15 +555,15 @@ return $.widget( "ui.calendar", {
// Determine which day grid cell to focus after refresh // Determine which day grid cell to focus after refresh
// TODO: Prevent disabled cells from being focused // TODO: Prevent disabled cells from being focused
if ( this.options.numberOfMonths === 1 ) { if ( this.options.numberOfMonths === 1 ) {
this.element.find( ".ui-calendar-title" ).html( this._buildTitle() ); this.element.find( ".ui-calendar-title" ).replaceWith( this._buildTitle() );
this.element.find( ".ui-calendar-calendar" ).replaceWith( this._buildGrid() ); this.element.find( ".ui-calendar-calendar" ).replaceWith( this._buildGrid() );
} else { } else {
this._refreshMultiplePicker(); this._refreshMultiplePicker();
} }
this.grid = this.element.find( ".ui-calendar-calendar" ); this.grid = this.element.find( ".ui-calendar-calendar" );
this._setActiveDescendant();
this._setActiveDescendant();
this._refreshHeaderButtons(); this._refreshHeaderButtons();
this._createButtons(); this._createButtons();
}, },
@ -577,17 +600,16 @@ return $.widget( "ui.calendar", {
}, },
_disableElement: function( element, state ) { _disableElement: function( element, state ) {
element element.attr( "aria-disabled", state );
.attr( "aria-disabled", state ) this._toggleClass( element, null, "ui-state-disabled", state );
.toggleClass( "ui-state-disabled", state );
}, },
_refreshMultiplePicker: function() { _refreshMultiplePicker: function() {
var i = 0; var i = 0;
for ( ; i < this.options.numberOfMonths; i++ ) { for ( ; i < this.options.numberOfMonths; i++ ) {
this.element.find( ".ui-calendar-title" ).eq( i ).html( this._buildTitle() ); this.element.find( ".ui-calendar-title" ).eq( i ).replaceWith( this._buildTitle() );
this.element.find( ".ui-calendar-calendar" ).eq( i ).html( this._buildGrid() ); this.element.find( ".ui-calendar-calendar" ).eq( i ).replaceWith( this._buildGrid() );
this.viewDate.adjust( "M", 1 ); this.viewDate.adjust( "M", 1 );
} }
this.viewDate.adjust( "M", -this.options.numberOfMonths ); this.viewDate.adjust( "M", -this.options.numberOfMonths );
@ -642,8 +664,6 @@ return $.widget( "ui.calendar", {
_destroy: function() { _destroy: function() {
this.element this.element
.off( ".calendar" )
.removeClass( "ui-calendar ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-calendar-multi" )
.removeAttr( "role aria-labelledby" ) .removeAttr( "role aria-labelledby" )
.removeUniqueId() .removeUniqueId()
.empty(); .empty();