WhatSock / apex

Apex 4X: The Comprehensive ARIA Development Suite
MIT License
29 stars 9 forks source link

presetDate not work with range disabled date #51

Closed impetoyt closed 9 months ago

impetoyt commented 9 months ago

I upload the code here: https://easyupload.io/ogl4ic

1) open the calendar and choose a date from the range (take note that is the year 2023) 2) open the browser console and write: $A("departure_picker").presetDate($A("departure_picker"), new Date("2020-12-09"), new Date("2020-11-11"), new Date("2020-12-12")); 3) open again the calendar. Everything is set fine except for the years selection dropdown that is completly empty and doesn't show the current year which is 2020 4) try to write again in the console this $A("departure_picker").presetDate($A("departure_picker"), new Date("2023-12-09"), new Date("2023-11-11"), new Date("2023-12-12")); basically you are again choose the year 2023. Open the calendar and you will see that the years selection dropdown is working again and it also show the year which is 2023.

accdc commented 9 months ago

Hi, can you reproduce this on the page at: https://whatsock.com/Templates/Datepickers/With%20Absolute%20Disabled%20Date%20Ranges/index.htm

I am getting the expected results using the same directions.

  1. Open the calendar and choose a date.
  2. Run the following code in the console prompt in Chrome.
$A("UniqueCalendarId").presetDate($A("UniqueCalendarId"), new Date("2020-12-09"), new Date("2020-11-11"), new Date("2020-12-12"));

When the datepicker is next opened, it uses the new date within the preset, and the year and month dropdowns do reflect the new change as well.

impetoyt commented 9 months ago

I found the problem, the difference between my code and yours is that I use these other two properties in the calendar configuration:

        yearSelectMin: (new Date("2023-04-05")).getFullYear()
        yearSelectMax: (new Date("2023-05-25")).getFullYear()

So when I use the presetDate method which change minDate and maxDate it appear the issue just for the years selection since for the month dosn't exist that two properties. So in another word: $A("departure_picker").presetDate($A("departure_picker"), new Date("2020-12-09"), new Date("2020-11-11"), new Date("2020-12-12"));

The presetDate change correctly the minDate and maxDate but since the yearSelectMin or yearSelectMax is still set on the year 2023 the dropdown selection is empty. I think that the presetDate when called should override the yearSelectMin and yearSelectMax.

I noticed also another thinks if you use in the configuration minDate and maxDate but you don't use yearSelectMin and yearSelectMax it appear the issue above. For the moment one workaround it is just to put yearSelectMin and yearSelectMax with wide range.

accdc commented 9 months ago

Hi, I've been looking into this and the issue with your code is not actually the javascript, it is whatever changes you have made to your datepicker.css file.

When I copy datepicker.css from the 4X repo and paste that into your example code folder, instantly the functionality starts working as expected.

I noticed this because when you run the datepicker from your sample code, it is not possible to tab between the various controls via Tab or Shift+Tab, and the hidden select elements are not being hidden properly which is breaking the functionality. This isn't a JS issue but a CSS issue within your sample code.

impetoyt commented 9 months ago

In my Datapicker.css I use display: none!important (span tag) and display: in-line!important (select tag) in order to show always the select field for the years and for the months in order to allow the users to avoid two clicks to open the relative dropdowns. You said that you build the calendar in this way as accesible compromise so that the user have to click two times the months or the years in order to show the dropdown. Unfortunally it is really bad for the UX and that is the reason why I did that workaround. When the calendar is rendered the html code is: image The tag select shouldn't already be native accessible? Why do you need to use also the span tag like a button in order to active the tag select?

Anyway we can easily reproduce the issue in your test code (I think is js problem not css): https://whatsock.com/Templates/Datepickers/With%20Absolute%20Disabled%20Date%20Ranges/index.htm

1) choose a date from the calendar; 2) in the browser console: $A("UniqueCalendarId").presetDate($A("UniqueCalendarId"), new Date("1800-12-09"), new Date("1799-12-09"), new Date("1802-12-09")); 3) open the calendar again: you can't click on the previous year <td class="nav prev btn year disabled"... since it is disabled (so you can't reach the year 1799, you have to use the previous month), you can click on the years selection but the dropdown is empty, so you can't choose between 1799-1800-1801-1802.

I notice that this happens because in your test page you have the follow configuration for the calendar: yearSelectMin: 1900, yearSelectMax: 2030, So when you change the minDate and maxDate with presetDate and you put a years range that it isn't inside the range of yearSelectMin and yearSelectMax the issue appear. In other words the range new range 1799-1802 is different from 1900-2030 and for some reason will not update the dropdown year selection. As I said one quick workaround is to use a wide range for yearSelectMin and yearSelectMax.

accdc commented 9 months ago

I understand that if you have a datepicker that is preconfigured for a specific year date range, then you change it so that the new range is outside of that range then the select will not show any options.

This will happen if you hack a datepicker, but I don't understand why this would ever happen in practice for anyone actually using a datepicker to select a date. Why would you want to do this on a webpage?

To fix this within your datepicker, simply set the following:

yearSelectMin: 1,
yearSelectMax: 9999,

This will work with any reasonable min max date range.

Regarding your CSS, if you choose to force the select to be visible and the button to be hidden, it will break accessibility for all non-sighted screen reader users.

impetoyt commented 9 months ago

I don't think it's a kind of hack because I encounter this issue when I initialize three different calendar. When you choose a date from the first two calendar then the value of minDate and yearSelectMin of the third calendar is set with the date choosed from the first calendar and the value of maxDate and yearSelectMax of the third calendar is set with the date choosed from the second calendar. This is the exact example where when you change again the date of the first two calendar the third one needs to be update with the new minDate and maxDate using the presetDate method and so the user could encounter that issue on years dropdown. Anyway we both said that the solution is to put an independent range like: yearSelectMin: 1, yearSelectMax: 9999,

Regarding the css, it wasn't my intention to break the accessibility which is the most important things to me (I'll restore my css file). I tried to modify the css since many users was not comfortable to click two times in order to choose the month or the years.

accdc commented 9 months ago

Hi, as a quick note, I believe I found a way of rendering the select so that it doesn't cause any issues for accessibility. I have most of it done, but will have it ready next week. I'll reach out when it's ready.

accdc commented 9 months ago

I've updated the Datepicker module to version 5.1 which now includes the ability to render just the year/month select element instead of a button. https://whatsock.com/Templates/Datepickers/Basic/index.htm

This requires setting the following property in your config file:

// Force the month/year select dropdown to render instead of a button.
forceSelect: true,
accdc commented 9 months ago

I also just pushed an update to Datepicker 5.2 that will auto-adjust the yearSelectMin and yearSelectMax values whenever it detects that the minDate or maxDate properties have been changed or are out of sync.

impetoyt commented 9 months ago

It works, thanks a lot also for your patience.