skip to Main Content

On document ready, this function performNext calls fine:

$(document).ready(function() {
  performNext();
});

performNext function hides a current fieldset and shows a next one, my question here is an extension of another question with minimal reproducible example I asked here

But it doesn’t get called on keydown:

$(document).on("keydown", (e) => {
  if (e.key === "F1") {
    e.preventDefault();
    performNext();
    console.log("F1");
  };
});

performNext function:

function performNext() {
    console.log("performNext started");

    var current_fs, next_fs; //fieldsets
    var opacity;
    var current = 1;
    var steps = $("fieldset").length;

    $(".next").click(function() {

        $current_fs = $(this).closest("fieldset");
        $next_fs = $current_fs.next();

        //show the next fieldset
        $next_fs.show();
        //hide the current fieldset with style
        $current_fs.animate({
            opacity: 0
        }, {
            step: function(now) {
                // for making fielset appear animation
                opacity = 1 - now;

                $current_fs.css({
                    'display': 'none',
                    'position': 'relative'
                });
                $next_fs.css({
                    'opacity': opacity
                });
            },
            duration: 500
        });
    });

    $("#msform").on("submit", function(e) {
        e.preventDefault()
    })
    
    console.log("performNext ended");

}

Tried this answer but not working.

console.log("performNext started"); 
console.log("performNext ended"); 
console.log("F1");

Are all logged in console, so mapping the F-key works. What am I missing?

2

Answers


  1. Your logic is not good. You’re creating click and submit handlers inside a function chat can be potentially called multiple times. The events will add up on top of existing ones. Therefore $(".next").click(function() { and $("#msform").on("submit", function(e) { should not be part of the performNext function. Also your 13 lines of $current_fs.animate({ can be achieved in only a couple of CSS lines using the CSS transition property. Rather, use an index to navigate your fieldsets and store the desired index in your button’s data-* attribute:

    const $msForm = $("#msform");
    const $fieldset = $msForm.find("fieldset");
    const stepsTotal = $fieldset.length; // i.e: 4
    let stepCurrent = 0; // Start at step index 0
    
    // Instead of "performNext()", use a more flexible goToStep() 
    // function that accepts a step index:
    function goToStep(index) {
      const $step = $fieldset.eq(index);
      $fieldset.not($step).removeClass("is-active");
      $step.addClass("is-active");
    }
    
    // Got to step index (stored in button's data-* attribute)
    $("[data-gotostep]").on("click", function() {
      stepCurrent = Number($(this).data("gotostep"));
      goToStep(stepCurrent);
    });
    
    // Go to next step
    $(document).on("keydown", (evt) => {
      if (evt.originalEvent.key === "F1") {
        evt.preventDefault();
        stepCurrent += 1;
        stepCurrent = Math.min(stepCurrent, stepsTotal - 1); 
        goToStep(stepCurrent);
      };
    });
    
    // Init:
    goToStep(0); // Show first step
    
    // Other stuff...
    $msForm.on("submit", function(evt) {
      evt.preventDefault()
    });
    #msform fieldset {
      position: absolute;
      width: 100%;
      visibility: hidden;
      opacity: 0;
      transition: 0.5s; /* instead of jQuery .animate() */
    }
    
    #msform fieldset.is-active {
      position: relative;
      visibility: visible;
      opacity: 1;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
    
    <form id="msform">
      <fieldset>
        <label>1/3 Your name:<br><input name="name" type="text"></label><br>
        <button type="button" data-gotostep="1">Next</button>
      </fieldset>
      <fieldset>
        <button type="button" data-gotostep="0">Back</button><br>
        <label>2/3 Your surname<br><input name="surname" type="text"></label><br>
        <button type="button" data-gotostep="2">Next</button>
      </fieldset>
      <fieldset>
        <button type="button" data-gotostep="1">Back</button><br>
        <label>3/3 Your age<br><input name="age" type="number"></label><br>
        <button type="button" data-gotostep="3">Next</button>
      </fieldset>
      <fieldset>
        <button type="submit" data-gotostep="0">Start all over</button><br>
        <label>You're all set!</label><br>
        <button type="submit">Finish</button>
      </fieldset>
    </form>
    Login or Signup to reply.
  2. If you want to press F1 and focus on the next <fieldset>, you could try the following procedure:

    $(document).ready(function() {
      performNext();
    });
    
    $(document).on('keydown', (e) => {
      if (e.key === 'F1') {
        e.preventDefault();
        performNext();
      };
    });
    
    function performNext() {
      var $focusedInput = $(':focus'), $currFieldset, $nextFieldset;
      if ($focusedInput.length === 0) {
        $nextFieldset = $('form > fieldset').first();
      } else {
        $currFieldset = $focusedInput.closest('fieldset');
        $nextFieldset = $currFieldset.next('fieldset');
        // Wrap around
        if ($nextFieldset.length === 0) {
          var $form = $currFieldset.closest('form');
          $nextFieldset = $form.find('fieldset:first-child'); 
        }
      }
      $nextFieldset.show();
      $nextFieldset.find('input').first().focus();
      // hide the current fieldset with style
      if ($currFieldset != null) {
        $currFieldset.animate({ opacity: 0 }, {
          step: function(now) {
            // for making fielset appear animation
            var opacity = 1 - now;
            $currFieldset.css({ display: 'none', position: 'relative' });
            $nextFieldset.css({ opacity: opacity });
          },
          duration: 500
        });
      }
    }
    fieldset {
      display: none;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <form action="#">
      <fieldset id="name-fs">
        <legend>What is your name? (Step 1/2)</legend>
        <label for="given-name-txt">Given name:</label>
        <input type="text" id="given-name-txt" name="given-name" placeholder="Jane" />
        <label for="surname-txt">Surname</label>
        <input type="text" id="surname-txt" name="surname" placeholder="Doe" />
      </fieldset>
      <fieldset id="agree-fs">
        <legend>Do you agree?  (Step 2/2)</legend>
        <input type="checkbox" id="agree-cbx-yes" name="agree" value="true" />
        <label for="agree-cbx-yes">I agree</label>
        <input type="checkbox" id="agree-cbx-no" name="agree" value="false" />
        <label for="agree-cbx-no">No</label>
      </fieldset>
    </form>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search