Skip to content

Commit 67b2b99

Browse files
FORMS-21023: Close Date-Picker on touch-event in mobile/tablet devices (#1662)
* FORMS-21023: close datepicker on touch event in mobile/tablet devices * Added event listener for touch event outside the calendar widget * FORMS-21023: cypress tests for datepicker in mobile/tablet layout
1 parent ef3ed0e commit 67b2b99

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/clientlibs/site/js/datepickerwidget.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ if (typeof window.DatePickerWidget === 'undefined') {
2727
#dp = null;
2828
#curInstance = null;
2929
#calendarIcon = null;
30+
#documentTouchListener = null;
3031
static #visible = false;
3132
static #clickedWindow;
3233

@@ -550,6 +551,17 @@ if (typeof window.DatePickerWidget === 'undefined') {
550551
this.#focusedOnLi = false;
551552
DatePickerWidget.#visible = true;
552553
this.#position();
554+
555+
// Add document touch listener for mobile to close datepicker when tapping outside
556+
if (this.#touchSupported && !this.#documentTouchListener) {
557+
this.#documentTouchListener = (evt) => {
558+
if (DatePickerWidget.#visible && this.#curInstance) {
559+
this.#checkWindowClicked(evt);
560+
}
561+
};
562+
document.addEventListener("touchstart", this.#documentTouchListener, false);
563+
}
564+
553565
if (this.#options.showCalendarIcon) {
554566
this.#curInstance.$field.setAttribute('readonly', true); // when the datepicker is active, deactivate the field
555567
}
@@ -924,6 +936,11 @@ if (typeof window.DatePickerWidget === 'undefined') {
924936
document.removeEventListener("keydown", self.#hotKeysCallBack);
925937
this.#keysEnabled = false;
926938
}
939+
// Remove document touch listener if it exists
940+
if (this.#documentTouchListener) {
941+
document.removeEventListener("touchstart", this.#documentTouchListener);
942+
this.#documentTouchListener = null;
943+
}
927944
// Issue LC-7049:
928945
// datepickerTarget should be added when activate the field and should be removed
929946
// after the fields gets deactivated. Otherwise clicking on any other datefield

ui.tests/test-module/specs/datepicker/datepicker.runtime.cy.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,4 +383,72 @@ describe("Form Runtime with Date Picker", () => {
383383
cy.get('.datetimepicker').should('be.visible');
384384
});
385385
})
386+
387+
// Mobile Touch Functionality Tests
388+
describe("Mobile Touch Functionality", () => {
389+
beforeEach(() => {
390+
// Set mobile viewport for touch testing
391+
cy.viewport('iphone-x')
392+
});
393+
394+
it("should open datepicker on mobile touch", () => {
395+
const [datePicker4, datePicker4FieldView] = Object.entries(formContainer._fields)[4]
396+
397+
// Touch the datepicker field
398+
cy.get(`#${datePicker4}`).find(".cmp-adaptiveform-datepicker__calendar-icon").click().then(() => {
399+
cy.get('.datetimepicker').should('be.visible')
400+
cy.get('.dp-monthview').should('be.visible')
401+
})
402+
});
403+
404+
it("should close datepicker when tapping outside on mobile", () => {
405+
const [datePicker4, datePicker4FieldView] = Object.entries(formContainer._fields)[4]
406+
407+
// Open the datepicker
408+
cy.get(`#${datePicker4}`).find(".cmp-adaptiveform-datepicker__calendar-icon").click().then(() => {
409+
cy.get('.datetimepicker').should('be.visible')
410+
})
411+
412+
// Tap outside the datepicker (on the body)
413+
cy.get('body').click(0, 0).then(() => {
414+
cy.get('.datetimepicker').should('not.be.visible')
415+
})
416+
});
417+
418+
it("should not close datepicker when tapping inside the calendar", () => {
419+
const [datePicker4, datePicker4FieldView] = Object.entries(formContainer._fields)[4]
420+
421+
// Open the datepicker
422+
cy.get(`#${datePicker4}`).find(".cmp-adaptiveform-datepicker__calendar-icon").click().then(() => {
423+
cy.get('.datetimepicker').should('be.visible')
424+
})
425+
426+
// Tap inside the calendar (on a day)
427+
cy.get('.dp-monthview li').not('.header').first().click({force: true}).then(() => {
428+
cy.get('.datetimepicker').should('be.visible')
429+
})
430+
});
431+
432+
it("should work correctly with multiple datepicker fields on the same page", () => {
433+
// Test with multiple datepicker fields
434+
const [datePicker4, datePicker4FieldView] = Object.entries(formContainer._fields)[4]
435+
const [datePicker6, datePicker6FieldView] = Object.entries(formContainer._fields)[6]
436+
const datepickerIds = [datePicker4, datePicker6]
437+
438+
datepickerIds.forEach((id, index) => {
439+
// Open datepicker
440+
cy.get(`#${id}`).find(".cmp-adaptiveform-datepicker__calendar-icon").click().then(() => {
441+
cy.get('.datetimepicker').should('be.visible')
442+
})
443+
444+
// Tap outside to close
445+
cy.get('body').click(0, 0).then(() => {
446+
cy.get('.datetimepicker').should('not.be.visible')
447+
})
448+
449+
// Small delay between tests
450+
cy.wait(100)
451+
})
452+
});
453+
});
386454
})

0 commit comments

Comments
 (0)