6 Replies Latest reply on Apr 26, 2013 1:53 PM by Jorge Rimblas

    Arrow Keys in Tabular Forms

      I have a user who wants very much to be able to move about a tabular form using arrow keys, as if he were in Excel.

      I don't see how this can be done. Can it? If so, how?

      I am working in APEX 4.0.
        • 1. Re: Arrow Keys in Tabular Forms
          Jorge Rimblas
          "Unfortunately" it is possible. :)
          Well... left and right navigation would probably need to be with the TAB key, as it currently works.
          But up and down could be done with the arrows.

          Here's basically what you would do.
          1. listen for keypresses events.
          - I would do some consol.log or alert messages to find out what the up and down arrow values are.
          2. You can set the focus to the correct cell after you get the key press. You find out which cell you're in ie. f04_0002 and you if you press down you need to go to f04_0003. A javascript split can separate the f04 from the row 0002, then you increments it and build the new destination.
          3. A $("#f04_0003").focus() will take you to the new cell.

          Hope this gets you started.
          • 2. Re: Arrow Keys in Tabular Forms
            Jorge Rimblas
            Ok, I just couldn't leave it alone.
            Here's a rough solution. It needs code to pad correctly with zeroes for all number of rows because right now it's just set to pad for up to 99 rows which will not work for most cases, but not all.

            Create an Adv Dynamic Action:
            Name: Move with Arrow Keys
            Event: Key Down
            Selector Type: jQuery
            jQuery Selector: input[id^=f]

            The selector will apply to all input fields whose ID starts with f. This may need to be fine tuned or limited to only the input fields on the tabular form.

            The True Action is of type Execute JavaScript Code
            And here is the code:
            var col = this.triggeringElement.id.split("_")[0];
            var row = this.triggeringElement.id.split("_")[1];
            var k = this.browserEvent.keyCode;
            var new_row, moveFocus = false;
            // Key Down
            if (k===40) {
            //  console.log('Go Down from ' + this.triggeringElement.id);
              new_row = Number(row) + 1;
              moveFocus = true;
            // Key Up
            if (k===38) {
              // console.log('Go Up from ' + this.triggeringElement.id);
              new_row = Number(row) - 1;
              moveFocus = true;
            // Move the focus
            if (moveFocus) {
              if (new_row < 10) {
                $("#" + col + "_000" + new_row).focus();
              else {
                $("#" + col + "_00" + new_row).focus();
            Change the Event Scope to "Live" so that you don't get a bunch of key listeners all over your page. That will make it so that there's only one.

            This is basically the concept I outlined above.

            What do you think?

            PS. Don't forget that the consol.log messages will choke IE. Talking about IE... I didn't test it there. :)

            Edited by: jrimblas on Apr 26, 2013 8:53 AM made some adjustments to the code
            • 3. Re: Arrow Keys in Tabular Forms
              Here's my solution.

              Rather than use the Id's, when going up and down, just get the name attribute, get previous or next row, the find the field with the same name.

              Give tabular form a static ID of #arrow-tabular (or whatever you like).
              Event: Key Down
              jQuery Selector: #arrow-tabular input

              True Action:Execute JS code
              var baseSelector = '#arrow-tabular input[type!="hidden"]';
                  if (event.preventDefault) {
                  } else {
                      event.returnValue = false;
                  switch (event.keyCode) {
                      case 37:
                          var prevElIndex = $(baseSelector).index(this.triggeringElement)-1;
                          $(baseSelector + ':eq(' + prevElIndex + ')').focus();
                      case 38:
                          var name = this.triggeringElement.name;
                          var row = $x_UpTill(this.triggeringElement,'TR');
                          var prevRow = $(row).prev();
                          $('input[name="' + name + '"]', prevRow).focus();
                      case 39:
                          var nextElIndex = $(baseSelector).index(this.triggeringElement)+1;
                          $(baseSelector + ':eq(' + nextElIndex + ')').focus();
                      case 40:
                          var name = this.triggeringElement.name;
                          var row = $x_UpTill(this.triggeringElement,'TR');
                          var nextRow = $(row).next();
                          $('input[name="' + name + '"]', nextRow).focus();
              I don't like the idea of arrow keys alone moving input fields, so I have implemented to only do so when pressed in combination with the ctrl key.

              Demo: http://apex.oracle.com/pls/apex/f?p=45448:29:
              • 4. Re: Arrow Keys in Tabular Forms
                Trent, I'm holding down the control key in your demo, but the demo does not work. Am I doing something wrong or is there a js problem?
                • 5. Re: Arrow Keys in Tabular Forms
                  Probably, you are using IE? Apparently it doesn't have the function event.preventDefault().


                  Try again.

                  Updated the code.
                  • 6. Re: Arrow Keys in Tabular Forms
                    Jorge Rimblas
                    So Doug, two excellent solutions and no feedback?
                    I do like Trent's approach of using the Ctrl Key, but I would only use it for the left and right movement. If you don't add the ctrl key, then you can't move left and right within the field characters.
                    However, for the up and down, simple up and down arrows (with no ctrl keys) would work great.

                    I did setup a sample:

                    Use demo/demo to log in.