qodesmith / datepicker

Get a date with JavaScript! A datepicker with no dependencies.
344 stars 101 forks source link

How to show calendar only when an icon is clicked? #71

Closed airblade closed 4 years ago

airblade commented 4 years ago

Hello!

I have been reading through the code and I must say it is a breath of fresh air compared to some other datepickers :)

Anyway, I have an <input type=text> for a date and a little calendar icon next to it. I can't quite figure out how to show the calendar when the icon is clicked (but not when the user simply focuses/types in the input field).

(Currently I have a click handler on the icon which calls datepicker() with the input field DOM element, and then show() on the returned picker instance. At that point nothing happens and I have to click into the input field to get the calendar.)

Any pointers would be much appreciated!

airblade commented 4 years ago

I figured it out: call datepicker() with the icon element, rather than the input field, and use onShow and onSelect to read/write the date from/to the input field.

qodesmith commented 4 years ago

@airblade I started writing a second option, which is to put a click event handler on the icon and use the datepicker instance's show and hide methods to trigger the calendar, but this lead me to discover a bug! While I'm glad you found a working solution to your problem, I'm going to reopen this issue to fix the bug. Once fixed, I'll post some example code to trigger the calendar as mentioned above. Thanks for your patience!

qodesmith commented 4 years ago

Ok, turns out there wasn't a bug, rather, I hadn't considered the flow of events in the browser. If you implement a click event on some element to toggle the calendar with the show and hide methods, it will work but the event bubbles and is then captured by datepicker's oneHandler event listener which will hide the calendar if it sees a click event anywhere outside the calendar. That means that any custom click event functions like this need to use stopPropagation! I'll update the documentation to be explicit about this, but your second option could look something like this:

// Keep the picker attached to the input element.
const picker = datepicker(inputElement, options)

// Toggle the calendar when the icon is clicked.
icon.addEventListener('click', e => {
  // Prevent Datepicker's event handler from hiding the calendar.
  e.stopPropagation()

  // Toggle the calendar.
  const isHidden = picker.calendarContainer.classList.contains('qs-hidden')
  picker[isHidden ? 'show' : 'hide']()
})

With the above, you can avoid having to provide custom onShow and onSelect callbacks.

airblade commented 4 years ago

Ah, that makes sense. And I think this section option is simpler than my current approach.

Thank you!