javascriptsweetalert2pikaday

Do not focus Swal input


I have a standard Swal with input.

Swal.fire({
  ...
  text: "legend",
  input: "text",
  customClass: { popup: "datepicker-container" },
  ...
  preConfirm: (inputValue) => {
    ...
  },
  willClose: () => {
    if (datepicker) datepicker.destroy();
  },
});

The datepicker-container class permit to enhance the input with a Pickaday datepicker.

I have as behavior:

  1. The display of the datepicker at the final place
  2. Animation of Swal popup
  3. At the end of the animation, the input is at the final place, and so the datepicker the element matches the input

So two choices, to solve this issue:

  1. Do not focus input value at rendering, and so display datepicker only on user input
  2. Focus input only at the end of the animation, and display datepicker only when input is on final place

For the solution 1. I have tried several focus option (focusConfirm, focusCancel), without result. I have tried to focus confirm button on didRender, but as the popup is repainted on the screen after this handler, there is no effect. The only effect is with:

  didOpen: () => {
    Swal.getConfirmButton().focus();
  },

But there is a blink with the datepicker. It is still displayed at swal initial rendering.

For the solution 2., I see no way to configure that. But it was the behavior in the origin project, it's why I put a question here, and not an issue of SweetAlert2 Github.


Solution

  • Finally, after workarounds proposed by project maintener (https://github.com/sweetalert2/sweetalert2/issues/2526), I handle the end of popup animation.

    Live demo of the solution: https://codepen.io/plouf142/pen/KKRYoVe

    /**
     * Depending on the browser, detect the supported event property name
     * for the End of CSS Animations.
     * From https://jonsuh.com/blog/detect-the-end-of-css-animations-and-transitions-with-javascript/
     *
     * @returns {String}, the name of the property name for the end of animations
     */
    function whichAnimationEvent() {
      var t,
        el = document.createElement("fakeelement");
    
      var animations = {
        animation: "animationend",
        OAnimation: "oAnimationEnd",
        MozAnimation: "animationend",
        WebkitAnimation: "webkitAnimationEnd"
      };
    
      for (t in animations) {
        if (el.style[t] !== undefined) {
          return animations[t];
        }
      }
    }
    
    // Event name fired on animation end (browser dependent)
    var animationEvent = whichAnimationEvent();
    
    /**
     * Handle end of show animation of the Swal popup.
     * This is the event when the popup is displayed at its final position
     */
    function onSwalShowPopupAnimationEnded() {
      this.removeEventListener(animationEvent, onSwalShowPopupAnimationEnded);
    
      // Show datepicker associated with Swal input
      let input = Swal.getInput();
      input && input.click();
    }
    
    var datepicker = null;
    
    Swal.fire({
      text: "Legend...",
      input: "text",
      didOpen: () => {
        let field = Swal.getInput();
    
        datepicker = new Pikaday({ field: field });
    
        // Wait end of animation
        animationEvent &&
          Swal.getPopup().addEventListener(
            animationEvent,
            onSwalShowPopupAnimationEnded
          );
      },
      willClose: () => {
        if (datepicker) datepicker.destroy();
      }
    });