From 74e4557ec35282c99a8b0323e0afb3be85b7693d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bartosz=20Dziewo=C5=84ski?= Date: Fri, 31 Jul 2015 00:36:19 +0200 Subject: [PATCH] mw.widgets.DateInputWidget: Allow not having a date selected * Allow empty value, that is, no date being selected. Display an appropriate label when that is the case. * Start with no date selected, rather than today's date. * When the field is empty and gets focus, set the date to today, on the assumption that this is likely what the user wants. Permit emptying the field, though. * Highlight today's date on the calendar. Bonus cleanup: * Update the UI from #setValue, immediately when needed. * Improve validation of incoming values. * Correct some documentation. * Correct some bad copy-paste in styles which caused disabled widget to not display correctly. Change-Id: I7a1f7ff20eb6fc21ea59ecfe48deb9305c8e29e8 --- languages/i18n/en.json | 1 + languages/i18n/qqq.json | 1 + resources/Resources.php | 1 + .../mw.widgets.CalendarWidget.less | 7 +- .../mw.widgets.DateInputWidget.js | 89 ++++++++++++++----- .../mw.widgets.DateInputWidget.less | 20 +++-- 6 files changed, 88 insertions(+), 31 deletions(-) diff --git a/languages/i18n/en.json b/languages/i18n/en.json index 508e25488c..f59df68075 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -3805,6 +3805,7 @@ "special-characters-title-endash": "en dash", "special-characters-title-emdash": "em dash", "special-characters-title-minus": "minus sign", + "mw-widgets-dateinput-no-date": "No date selected", "mw-widgets-titleinput-description-new-page": "page does not exist yet", "mw-widgets-titleinput-description-redirect": "redirect to $1" } diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index a0cfab2b89..53f58285f8 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -3976,6 +3976,7 @@ "special-characters-title-endash": "Title tooltip for the en dash character (–); See https://en.wikipedia.org/wiki/Dash", "special-characters-title-emdash": "Title tooltip for the em dash character (—); See https://en.wikipedia.org/wiki/Dash", "special-characters-title-minus": "Title tooltip for the minus sign character (−), not to be confused with a hyphen", + "mw-widgets-dateinput-no-date": "Label of a date input field when no date has been selected.", "mw-widgets-titleinput-description-new-page": "Description label for a new page in the title input widget.", "mw-widgets-titleinput-description-redirect": "Description label for a redirect in the title input widget." } diff --git a/resources/Resources.php b/resources/Resources.php index fb0971e49a..a0c0744d20 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -1809,6 +1809,7 @@ return array( 'oojs-ui', ), 'messages' => array( + 'mw-widgets-dateinput-no-date', 'mw-widgets-titleinput-description-new-page', 'mw-widgets-titleinput-description-redirect', ), diff --git a/resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.less b/resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.less index 276bc65e85..582a316d39 100644 --- a/resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.less +++ b/resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.less @@ -220,7 +220,9 @@ } .mw-widget-calendarWidget-day-today { - // Intentionally left blank. + border: 1px solid #3787fb; + border-radius: ((@calendarHeight / 7) / 2); + margin: -1px; } .mw-widget-calendarWidget-item-selected { @@ -247,6 +249,9 @@ &.mw-widget-calendarWidget-day, &.mw-widget-calendarWidget-day-heading { border-radius: ((@calendarHeight / 7) / 4); + // Hide the border from .mw-widget-calendarWidget-day-today + border: 0; + margin: 0; } &.mw-widget-calendarWidget-month { diff --git a/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.js b/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.js index 1820dda463..3888fc71c9 100644 --- a/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.js +++ b/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.js @@ -16,8 +16,8 @@ * @constructor * @param {Object} [config] Configuration options * @cfg {string} [precision='day'] Date precision to use, 'day' or 'month' - * @cfg {string|null} [date=null] Day or month date (depending on `precision`), in the - * format 'YYYY-MM-DD' or 'YYYY-MM'. When null, defaults to current date. + * @cfg {string} [value] Day or month date (depending on `precision`), in the format 'YYYY-MM-DD' + * or 'YYYY-MM'. If not given or empty string, no date is selected. * @cfg {string} [inputFormat] Date format string to use for the textual input field. Displayed * while the widget is active, and the user can type in a date in this format. Should be short * and easy to type. When not given, defaults to 'YYYY-MM-DD' or 'YYYY-MM', depending on @@ -75,6 +75,7 @@ .addClass( 'mw-widget-dateInputWidget' ) .append( this.handle.$element, this.textInput.$element, this.calendar.$element ); // Set handle label and hide stuff + this.updateUI(); this.deactivate(); }; @@ -118,7 +119,10 @@ value = this.textInput.getValue(); this.inTextInput++; this.textInput.isValid().done( function ( valid ) { - if ( valid ) { + if ( value === '' ) { + // No date selected + widget.setValue( '' ); + } else if ( valid ) { // Well-formed date value, parse and set it var mom = moment( value, widget.getInputFormat() ); // Use English locale to avoid number formatting @@ -141,22 +145,16 @@ * @inheritdoc */ mw.widgets.DateInputWidget.prototype.setValue = function ( value ) { - if ( value === undefined || value === null ) { - // Default to today - value = this.calendar.getDate(); - } - var oldValue = this.value; + if ( !moment( value, this.getInternalFormat() ).isValid() ) { + value = ''; + } + mw.widgets.DateInputWidget.parent.prototype.setValue.call( this, value ); if ( this.value !== oldValue ) { - if ( !this.inCalendar ) { - this.calendar.setDate( this.getValue() ); - } - if ( !this.inTextInput ) { - this.textInput.setValue( this.getMoment().format( this.getInputFormat() ) ); - } + this.updateUI(); } return this; @@ -179,15 +177,50 @@ }; /** - * Deactivate this input field for data entry. Opens the calendar and shows the text field. + * @inheritdoc + */ + mw.widgets.DateInputWidget.prototype.focus = function () { + this.activate(); + return this; + }; + + /** + * @inheritdoc + */ + mw.widgets.DateInputWidget.prototype.blur = function () { + this.deactivate(); + return this; + }; + + /** + * Update the contents of the label, text input and status of calendar to reflect selected value. * * @private */ - mw.widgets.DateInputWidget.prototype.deactivate = function () { - this.textInput.setValue( this.getMoment().format( this.getInputFormat() ) ); - this.calendar.setDate( this.getValue() ); - this.handle.setLabel( this.getMoment().format( this.getDisplayFormat() ) ); + mw.widgets.DateInputWidget.prototype.updateUI = function () { + if ( this.getValue() === '' ) { + this.textInput.setValue( '' ); + this.calendar.setDate( null ); + this.handle.setLabel( mw.msg( 'mw-widgets-dateinput-no-date' ) ); + this.$element.addClass( 'mw-widget-dateInputWidget-empty' ); + } else { + if ( !this.inTextInput ) { + this.textInput.setValue( this.getMoment().format( this.getInputFormat() ) ); + } + if ( !this.inCalendar ) { + this.calendar.setDate( this.getValue() ); + } + this.handle.setLabel( this.getMoment().format( this.getDisplayFormat() ) ); + this.$element.removeClass( 'mw-widget-dateInputWidget-empty' ); + } + }; + /** + * Deactivate this input field for data entry. Closes the calendar and hides the text field. + * + * @private + */ + mw.widgets.DateInputWidget.prototype.deactivate = function () { this.$element.removeClass( 'mw-widget-dateInputWidget-active' ); this.handle.toggle( true ); this.textInput.toggle( false ); @@ -195,12 +228,19 @@ }; /** - * Activate this input field for data entry. Closes the calendar and hides the text field. + * Activate this input field for data entry. Opens the calendar and shows the text field. * * @private */ mw.widgets.DateInputWidget.prototype.activate = function () { - this.setValue( this.getValue() ); + if ( this.getValue() === '' ) { + // Setting today's date is probably more helpful than leaving the widget empty? We could just + // display the placeholder and leave it there, but it's likely that at least the year will be + // the same as today's. + + // Use English locale to avoid number formatting + this.setValue( moment().locale( 'en' ).format( this.getInternalFormat() ) ); + } this.$element.addClass( 'mw-widget-dateInputWidget-active' ); this.handle.toggle( false ); @@ -339,9 +379,14 @@ /** * @private - * @param {string} date Date string, must be in 'YYYY-MM-DD' or 'YYYY-MM' format to be valid + * @param {string} date Date string, to be valid, must be empty (no date selected) or in + * 'YYYY-MM-DD' or 'YYYY-MM' format to be valid */ mw.widgets.DateInputWidget.prototype.validateDate = function ( date ) { + if ( date === '' ) { + return true; + } + // "Half-strict mode": for example, for the format 'YYYY-MM-DD', 2015-1-3 instead of 2015-01-03 // is okay, but 2015-01 isn't, and neither is 2015-01-foo. Use Moment's "fuzzy" mode and check // parsing flags for the details (stoled from implementation of #isValid). diff --git a/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.less b/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.less index 33e3406c33..f87869cbf9 100644 --- a/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.less +++ b/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.less @@ -39,7 +39,7 @@ .oo-ui-box-sizing(border-box); } - &.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle { + &.oo-ui-widget-disabled .mw-widget-dateInputWidget-handle { cursor: default; } @@ -59,10 +59,6 @@ border: 1px solid #ccc; border-radius: 0.1em; line-height: 1.275em; - - &:hover { - border-color: #347bff; - } } > .oo-ui-textInputWidget input { @@ -92,16 +88,24 @@ } } - &:hover .oo-ui-dropdownWidget-handle { - border-color: #aaa; + &.oo-ui-widget-enabled { + .mw-widget-dateInputWidget-handle:hover { + border-color: #347bff; + } } &.oo-ui-widget-disabled { - .oo-ui-dropdownWidget-handle { + .mw-widget-dateInputWidget-handle { color: #ccc; text-shadow: 0 1px 1px #fff; border-color: #ddd; background-color: #f3f3f3; } } + + &-empty { + .mw-widget-dateInputWidget-handle { + color: #ccc; + } + } } -- 2.20.1