Add `.disabled` class to Date/Picker cells before or after the legal date range
authorTim Düsterhus <duesterhus@woltlab.com>
Tue, 25 Apr 2023 10:45:19 +0000 (12:45 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Tue, 25 Apr 2023 10:45:19 +0000 (12:45 +0200)
And then reduce the opacity to make it more clear that these are unselectable.
Valid dates in a different month will still not be clickable, but their opacity
will not be reduced to not be misleading.

see https://www.woltlab.com/community/thread/294117-datepicker-ausw%C3%A4hlbare-daten-eindeutiger-darstellen/

ts/WoltLabSuite/Core/Date/Picker.ts
wcfsetup/install/files/js/WoltLabSuite/Core/Date/Picker.js
wcfsetup/install/files/style/ui/datePicker.scss

index f711a9a25c02e522f718e4003fdb2129d2cd260c..1c833e154517b8d6d053c2c4f4ec8c1ad0d1eadb 100644 (file)
@@ -470,7 +470,6 @@ function renderGrid(day?: number, month?: number, year?: number): void {
     // show the last row
     DomUtil.show(_dateCells[35].parentNode as HTMLElement);
 
-    let selectable: boolean;
     const comparableMinDate = new Date(_minDate.getFullYear(), _minDate.getMonth(), _minDate.getDate());
     for (let i = 0; i < 42; i++) {
       if (i === 35 && date.getMonth() !== month) {
@@ -483,17 +482,27 @@ function renderGrid(day?: number, month?: number, year?: number): void {
       const cell = _dateCells[i];
 
       cell.textContent = date.getDate().toString();
-      selectable = date.getMonth() === month;
-      if (selectable) {
-        if (date < comparableMinDate) {
-          selectable = false;
-        } else if (date > _maxDate) {
-          selectable = false;
-        }
+      const sameMonth = date.getMonth() === month;
+      if (sameMonth) {
+        cell.classList.remove("otherMonth");
+      } else {
+        cell.classList.add("otherMonth");
+      }
+
+      let selectable = true;
+      if (date < comparableMinDate) {
+        selectable = false;
+      } else if (date > _maxDate) {
+        selectable = false;
       }
 
-      cell.classList[selectable ? "remove" : "add"]("otherMonth");
       if (selectable) {
+        cell.classList.remove("disabled");
+      } else {
+        cell.classList.add("disabled");
+      }
+
+      if (sameMonth && selectable) {
         cell.href = "#";
         cell.setAttribute("role", "button");
         cell.tabIndex = 0;
@@ -547,7 +556,16 @@ function renderGrid(day?: number, month?: number, year?: number): void {
     for (let i = 0; i < 35; i++) {
       const cell = _dateCells[i];
 
-      cell.classList[!cell.classList.contains("otherMonth") && +cell.textContent! === day ? "add" : "remove"]("active");
+      let active = +cell.textContent! === day;
+      if (cell.classList.contains("otherMonth") || cell.classList.contains("disabled")) {
+        active = false;
+      }
+
+      if (active) {
+        cell.classList.add("active");
+      } else {
+        cell.classList.remove("active");
+      }
     }
 
     _dateGrid.dataset.day = day.toString();
@@ -605,7 +623,7 @@ function click(event: MouseEvent): void {
   event.preventDefault();
 
   const target = event.currentTarget as HTMLAnchorElement;
-  if (target.classList.contains("otherMonth")) {
+  if (target.classList.contains("otherMonth") || target.classList.contains("disabled")) {
     return;
   }
 
index 61ba5e0d07b01b284d455f8b78168d7ae8633009..abb83b19748bc01966b9651e6c1c082062ac9276 100644 (file)
@@ -393,7 +393,6 @@ define(["require", "exports", "tslib", "../Core", "./Util", "../Dom/Change/Liste
             }
             // show the last row
             Util_1.default.show(_dateCells[35].parentNode);
-            let selectable;
             const comparableMinDate = new Date(_minDate.getFullYear(), _minDate.getMonth(), _minDate.getDate());
             for (let i = 0; i < 42; i++) {
                 if (i === 35 && date.getMonth() !== month) {
@@ -403,17 +402,27 @@ define(["require", "exports", "tslib", "../Core", "./Util", "../Dom/Change/Liste
                 }
                 const cell = _dateCells[i];
                 cell.textContent = date.getDate().toString();
-                selectable = date.getMonth() === month;
-                if (selectable) {
-                    if (date < comparableMinDate) {
-                        selectable = false;
-                    }
-                    else if (date > _maxDate) {
-                        selectable = false;
-                    }
+                const sameMonth = date.getMonth() === month;
+                if (sameMonth) {
+                    cell.classList.remove("otherMonth");
+                }
+                else {
+                    cell.classList.add("otherMonth");
+                }
+                let selectable = true;
+                if (date < comparableMinDate) {
+                    selectable = false;
+                }
+                else if (date > _maxDate) {
+                    selectable = false;
                 }
-                cell.classList[selectable ? "remove" : "add"]("otherMonth");
                 if (selectable) {
+                    cell.classList.remove("disabled");
+                }
+                else {
+                    cell.classList.add("disabled");
+                }
+                if (sameMonth && selectable) {
                     cell.href = "#";
                     cell.setAttribute("role", "button");
                     cell.tabIndex = 0;
@@ -454,7 +463,16 @@ define(["require", "exports", "tslib", "../Core", "./Util", "../Dom/Change/Liste
         if (day) {
             for (let i = 0; i < 35; i++) {
                 const cell = _dateCells[i];
-                cell.classList[!cell.classList.contains("otherMonth") && +cell.textContent === day ? "add" : "remove"]("active");
+                let active = +cell.textContent === day;
+                if (cell.classList.contains("otherMonth") || cell.classList.contains("disabled")) {
+                    active = false;
+                }
+                if (active) {
+                    cell.classList.add("active");
+                }
+                else {
+                    cell.classList.remove("active");
+                }
             }
             _dateGrid.dataset.day = day.toString();
         }
@@ -497,7 +515,7 @@ define(["require", "exports", "tslib", "../Core", "./Util", "../Dom/Change/Liste
     function click(event) {
         event.preventDefault();
         const target = event.currentTarget;
-        if (target.classList.contains("otherMonth")) {
+        if (target.classList.contains("otherMonth") || target.classList.contains("disabled")) {
             return;
         }
         _input.dataset.empty = "false";
index 24651cac1427b6143b6e7c6d0c7b03646b00217c..28dca0f94b8fbe0039cb093376070f12ca8f9aea 100644 (file)
                        }
 
                        &.active,
-                       &:not(.otherMonth):hover {
+                       &:not(.otherMonth):hover,
+                       &:not(.disabled):hover {
                                background-color: var(--wcfDropdownBackgroundActive);
                                color: var(--wcfDropdownLinkActive);
                        }
 
-                       &.otherMonth {
+                       &.otherMonth,
+                       &.disabled {
                                color: var(--wcfContentDimmedText);
                                cursor: default;
                        }
+
+                       &.disabled {
+                               opacity: 0.45;
+                       }
                }
 
                > span {