Welcome Guest, Not a member yet? Register   Sign In
Smarter forms in regards to ENTER key
#1
Lightbulb 

It'd be lovely if a "smarter forms" handling in regards to the ENTER key could be added, with or without the form builder, and purely optional (of course).

By "smarter forms" I mean that ENTER in an input field quite frequently should not submit the form, but either stay in the current field, or move to the next (visible) field (or radio/checkbox) as it does with the TAB key.

(This obviously can't be done in a TEXTAREA field)

-joho
Reply
#2

Check this out:
https://stackoverflow.com/questions/8951...ting-enter
Reply
#3

(This post was last modified: 09-20-2023, 02:45 AM by joho.)

(09-20-2023, 02:09 AM)JustJohnQ Wrote: Check this out:
https://stackoverflow.com/questions/8951...ting-enter

Thanks. It's an interesting thread, but very jQuery oriented. I try to use as much "pure JS" as possible. My main point was that I think this would be something quite a lot of people would want, and it'd be nice to have it as part of CI. I did roll my own code for this eventually. It looks something like this:

Code:
<!-- Start me up -->
<script {csp-script-nonce}>
  (() => {
        'use strict';

        var cancelButton_id = null;
        var visibleFieldCount = 0;
        var visibleFields = null;
        var theForm = null;
        var formInputs = null;
        var ourInputs = [];

        function focusNext() {
            let currentField = document.activeElement;
            let currentInputIndex = ourInputs.indexOf(currentField);
            currentInputIndex++;
            if (currentInputIndex >= ourInputs.length) {
                currentInputIndex = 0;
            }
            let input = ourInputs[currentInputIndex];
            input.focus();
        }
        function documentKeyDown(e) {
            if (e.defaultPrevented) {
                return;// already handled
            }
            if (e.key == "Enter") {
                if (e.metakey || e.ctrlKey) {
                    if (e.target.form == theForm) {
                        e.preventDefault();
                        HTMLFormElement.prototype.submit.call(theForm);
                        return;
                    }
                }
                if (e.target.nodeName && e.target.nodeName.toLowerCase() != 'textarea') {
                    e.preventDefault();
                    focusNext();
                }
            }
        }
        function documentEditSetup() {
            let initialField = document.getElementById('the-field-you-want-to-focus-auto');
            if (initialField) {
                initialField.focus();
            }
            theForm = document.getElementById('the-id-of-the-form');
            formInputs = Array.from(theForm.elements);
            formInputs.forEach((fi) => {
                let fiType = fi.type.toLowerCase();
                if ( ! fi.hidden && fiType != 'hidden' && fiType != 'submit' ) {
                    visibleFieldCount++;
                    ourInputs.push(fi);
                }
            });
            cancelButton_id = document.getElementById('cancel-button');
            window.addEventListener('keydown', documentKeyDown);
            window.addEventListener('keyup', (e) => {
                if (e.defaultPrevented) {
                    return;// already handled
                }
                if (e.key == 'Escape') {
                    e.preventDefault();
                    alert("Cancel");
                }
            },
            true
            );
        }
        if (document.readyState === 'complete' ||
                (document.readyState !== 'loading' && !document.documentElement.doScroll)) {
            documentEditSetup();
        } else {
            document.addEventListener('DOMContentLoaded', documentEditSetup);
        }
    })();
</script>

I guess this would work as some sort of generic handler. You'd obviously need to add code for the 'Esc' key do emulate your 'Cancel' button.

-joho
Reply
#4

what about this version
Code:
(() => {
  'use strict';

  let cancelButtonId = null;
  let theForm = null;
  const ourInputs = [];

  const focusNext = () => {
    const currentField = document.activeElement;
    let currentInputIndex = ourInputs.indexOf(currentField);
    currentInputIndex = (currentInputIndex + 1) % ourInputs.length;
    const input = ourInputs[currentInputIndex];
    input.focus();
  };

  const documentKeyDown = (e) => {
    if (e.defaultPrevented) {
      return;
    }
    if (e.key === 'Enter') {
      if (e.metaKey || e.ctrlKey) {
        if (e.target.form === theForm) {
          e.preventDefault();
          theForm.submit();
        }
      } else if (e.target.nodeName && e.target.nodeName.toLowerCase() !== 'textarea') {
        e.preventDefault();
        focusNext();
      }
    }
  };

  const documentKeyUp = (e) => {
    if (e.defaultPrevented) {
      return;
    }
    if (e.key === 'Escape') {
      e.preventDefault();
      alert('Cancel');
    }
  };

  const documentEditSetup = () => {
    const initialField = document.getElementById('the-field-you-want-to-focus-auto');
    if (initialField) {
      initialField.focus();
    }
    theForm = document.getElementById('the-id-of-the-form');
    const formInputs = Array.from(theForm.elements);
   
    for (const fi of formInputs) {
      const fiType = fi.type.toLowerCase();
      if (!fi.hidden && fiType !== 'hidden' && fiType !== 'submit') {
        ourInputs.push(fi);
      }
    }
   
    cancelButtonId = document.getElementById('cancel-button');
    window.addEventListener('keydown', documentKeyDown);
    window.addEventListener('keyup', documentKeyUp, true);
  };

  if (document.readyState === 'complete' || (document.readyState !== 'loading' && !document.documentElement.doScroll)) {
    documentEditSetup();
  } else {
    document.addEventListener('DOMContentLoaded', documentEditSetup);
  }
})();
Learning Codeigniter 
Reply
#5

Sure, whatever floats your boat :-) I was merely trying to explain what I meant.

-joho
Reply




Theme © iAndrew 2016 - Forum software by © MyBB