Skip to content

Commit

Permalink
Merge pull request #520 from gselderslaghs/timepicker-accessibility
Browse files Browse the repository at this point in the history
Timepicker accessibility #476
  • Loading branch information
wuda-io authored Nov 13, 2024
2 parents b9c12ed + 2abdbe8 commit 196bd69
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 37 deletions.
41 changes: 33 additions & 8 deletions sass/components/_timepicker.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

/* Clock Digital Display */
.timepicker-digital-display {
width: 200px;
width: auto;
flex: 1 auto;
background-color: var(--md-sys-color-primary);;
padding: 10px;
Expand All @@ -27,15 +27,16 @@
.timepicker-text-container {
font-size: 4rem;
font-weight: bold;
text-align: center;
text-align: left;
color: var(--font-on-primary-color-medium);
font-weight: 400;
position: relative;
user-select: none;
padding: 1rem 1rem 1.5rem 1rem;

input[type=text]{
height: 4rem;
color: rgba(255, 255, 255, 0.6);
color: var(--md-sys-color-secondary);
border-bottom: 0px;
font-size: 4rem;
direction: ltr;
Expand All @@ -60,17 +61,26 @@ input[type=text].timepicker-input-minutes {
}

input[type=text].text-primary {
color: rgba(255, 255, 255, 1);
color: var(--md-sys-color-on-background);
}

.timepicker-display-am-pm {
font-size: 1.3rem;
position: absolute;
top: 1.2rem;
right: 1rem;
bottom: 1rem;
bottom: auto;
font-weight: 400;
}

.timepicker-modal .am-btn,
.timepicker-modal .pm-btn {
width: 3.6rem;
height: 2rem;
line-height: 2rem;
vertical-align: middle;
text-align: center;
}

/* Analog Clock Display */
.timepicker-analog-display {
Expand All @@ -85,9 +95,8 @@ input[type=text].text-primary {
height: 270px;
overflow: visible;
position: relative;
margin: auto;
margin-top: 25px;
margin-bottom: 5px;
margin: 30px 14px 14px;
padding: 10px;
user-select: none;
}

Expand Down Expand Up @@ -195,13 +204,29 @@ input[type=text].text-primary {

.timepicker-text-container {
top: 32%;
padding: 0;
text-align: center;
}

.timepicker-display-am-pm {
position: relative;
top: auto;
right: auto;
bottom: auto;
text-align: center;
margin-top: 1.2rem;
}

input[type=text].timepicker-input-minutes {
min-width: 5.3rem;
}

.timepicker-modal .am-btn,
.timepicker-modal .pm-btn {
width: auto;
height: auto;
line-height: inherit;
vertical-align: top;
text-align: inherit;
}
}
83 changes: 54 additions & 29 deletions src/timepicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,10 @@ export class Timepicker extends Component<TimepickerOptions> {
this.plate.addEventListener('mousedown', this._handleClockClickStart);
this.plate.addEventListener('touchstart', this._handleClockClickStart);
this.digitalClock.addEventListener('keyup', this._inputFromTextField);
this.inputHours.addEventListener('click', () => this.showView('hours'));
this.inputMinutes.addEventListener('click', () => this.showView('minutes'));
this.inputHours.addEventListener('focus', () => this.showView('hours'));
this.inputHours.addEventListener('focusout', () => this.formatHours());
this.inputMinutes.addEventListener('focus', () => this.showView('minutes'));
this.inputMinutes.addEventListener('focusout', () => this.formatMinutes());
}

_removeEventHandlers() {
Expand Down Expand Up @@ -359,9 +361,23 @@ export class Timepicker extends Component<TimepickerOptions> {

_setupModal() {
this.modal = Modal.init(this.modalEl, {
onOpenStart: this.options.onOpenStart,
onOpenStart: () => {
if (typeof this.options.onOpenStart === 'function') {
this.options.onOpenStart.call(this);
}
this.modalEl.querySelectorAll('.btn').forEach((e: HTMLButtonElement) => {
if (e.style.visibility !== 'hidden') e.tabIndex = 0;
});
},
onOpenEnd: this.options.onOpenEnd,
onCloseStart: this.options.onCloseStart,
onCloseStart: () => {
if (typeof this.options.onCloseStart === 'function') {
this.options.onCloseStart.call(this);
}
this.modalEl.querySelectorAll('.btn').forEach((e: HTMLButtonElement) => {
e.tabIndex = -1;
});
},
onCloseEnd: () => {
if (typeof this.options.onCloseEnd === 'function') {
this.options.onCloseEnd.call(this);
Expand Down Expand Up @@ -392,10 +408,10 @@ export class Timepicker extends Component<TimepickerOptions> {

private _createButton(text: string, visibility: string): HTMLButtonElement {
const button = document.createElement('button');
button.classList.add('btn-flat', 'waves-effect');
button.classList.add('btn', 'btn-flat', 'waves-effect', 'text');
button.style.visibility = visibility;
button.type = 'button';
button.tabIndex = this.options.twelveHour ? 3 : 1;
button.tabIndex = -1;
button.innerText = text;
return button;
}
Expand Down Expand Up @@ -566,7 +582,7 @@ export class Timepicker extends Component<TimepickerOptions> {
}
this.hours = +value[0] || 0;
this.minutes = +value[1] || 0;
this.inputHours.value = this.hours;
this.inputHours.value = Timepicker._addLeadingZero(this.hours);
this.inputMinutes.value = Timepicker._addLeadingZero(this.minutes);

this._updateAmPmView();
Expand Down Expand Up @@ -635,31 +651,26 @@ export class Timepicker extends Component<TimepickerOptions> {

_inputFromTextField = () => {
const isHours = this.currentView === 'hours';
if (isHours) {
if (isHours && this.inputHours.value !== '') {
const value = parseInt(this.inputHours.value);
if (value > 0 && value < 13) {
this.drawClockFromTimeInput(value, isHours);
this.showView('minutes', this.options.duration / 2);
if (value > 0 && value < (this.options.twelveHour ? 13 : 24)) {
this.hours = value;
this.inputMinutes.focus();
}
else {
const hour = new Date().getHours();
this.inputHours.value = (hour % 12).toString();
this.setHoursDefault();
}
this.drawClockFromTimeInput(this.hours, isHours);
}
else {
else if(!isHours && this.inputMinutes.value !== '') {
const value = parseInt(this.inputMinutes.value);
if (value >= 0 && value < 60) {
this.inputMinutes.value = Timepicker._addLeadingZero(value);
this.drawClockFromTimeInput(value, isHours);
this.minutes = value;
(<HTMLElement>this.modalEl.querySelector('.confirmation-btns :nth-child(2)')).focus();
}
else {
const minutes = new Date().getMinutes();
this.inputMinutes.value = Timepicker._addLeadingZero(minutes);
this.minutes = new Date().getMinutes();
this.inputMinutes.value = this.minutes;
}
this.drawClockFromTimeInput(this.minutes, isHours);
}
}

Expand All @@ -669,15 +680,10 @@ export class Timepicker extends Component<TimepickerOptions> {
let radius;
if (this.options.twelveHour) {
radius = this.options.outerRadius;
} else {
radius = isHours && value > 0 && value < 13 ? this.options.innerRadius : this.options.outerRadius;
}
let cx1 = Math.sin(radian) * (radius - this.options.tickRadius),
cy1 = -Math.cos(radian) * (radius - this.options.tickRadius),
cx2 = Math.sin(radian) * radius,
cy2 = -Math.cos(radian) * radius;
this.hand.setAttribute('x2', cx1.toString());
this.hand.setAttribute('y2', cy1.toString());
this.bg.setAttribute('cx', cx2.toString());
this.bg.setAttribute('cy', cy2.toString());
this.setClockAttributes(radian, radius);
}

setHand(x, y, roundBy5: boolean = false) {
Expand Down Expand Up @@ -742,13 +748,17 @@ export class Timepicker extends Component<TimepickerOptions> {

this[this.currentView] = value;
if (isHours) {
this.inputHours.value = value.toString();
this.inputHours.value = Timepicker._addLeadingZero(value);
}
else {
this.inputMinutes.value = Timepicker._addLeadingZero(value);
}

// Set clock hand and others' position
this.setClockAttributes(radian, radius);
}

setClockAttributes(radian: number, radius: number) {
let cx1 = Math.sin(radian) * (radius - this.options.tickRadius),
cy1 = -Math.cos(radian) * (radius - this.options.tickRadius),
cx2 = Math.sin(radian) * radius,
Expand All @@ -759,6 +769,21 @@ export class Timepicker extends Component<TimepickerOptions> {
this.bg.setAttribute('cy', cy2.toString());
}

formatHours() {
if (this.inputHours.value == '') this.setHoursDefault();
this.inputHours.value = Timepicker._addLeadingZero(Number(this.inputHours.value));
}

formatMinutes() {
if (this.inputMinutes.value == '') this.minutes = new Date().getMinutes();
this.inputMinutes.value = Timepicker._addLeadingZero(Number(this.inputMinutes.value));
}

setHoursDefault() {
this.hours = new Date().getHours();
this.inputHours.value = (this.hours % (this.options.twelveHour ? 12 : 24)).toString();
}

/**
* Open timepicker.
*/
Expand Down

0 comments on commit 196bd69

Please sign in to comment.