arrowFields

A recent project had a requirement to move between the form fields with arrows.
Since I was just given the specs, I couldn’t tell the client about the existence of Tab and Shift+Tab like any good pretentious developer would.

So I wrote a little directive that does that, and then I saw it was nice enough to keep and even publish since it does slightly improve form navigation.

The HTML markup is simple – just add the directive as an attribute to any form field:


    

The directive is simple – bind keyup:


element.bind("keyup", function(e) {

check if it’s an arrow

var keyCode = e.keyCode;
switch (keyCode) {
case (39): // Right
// do something
break;
case (37): // Left
// do something
break;
}

then move the focus to the next input.


var inputs = $(':input');
var nextInput = (inputs.index(this) == inputs.length-1) ? inputs.get(0) : inputs.get(inputs.index(this) + 1);
nextInput.focus();

Only little problem was that when doing so – the user couldn’t use the arrows inside the field – which breaks the normal expected behavior of a UI element and that is a BIG UX no no.
So I added a check for the caret position, and the arrows will jump to the next field – if it’s a Back arrow at the start of the field, or Next arrow at the end of the input’s content.


// caret position
var cert = element[0].selectionStart;
// field's content length - used to find right edge of content
var conLength = element[0].value.length;

// and in the Right arrow action - check if it's the rightmost position:
if (cert>=conLength) {
// do something
}

and the full directive looks like that:


angular.module('yourApp').directive('formArrows', function () {
    return {
        restrict: 'A',
        link: function (scope, element) {
            element.bind("keyup", function(e) {
                // get key code / 39 - Right, 37 - Left, 38 - Up, 40 - Down
                var keyCode = e.keyCode;
                // list page objects to iterate - in this case - :input. Use other selector for similar behavior with different objects
                // use $(':input:enabled') - to rotate just between enabled fields, but just if you have disabled fields
                var inputs = $(':input');
                // caret position
                var cert = element[0].selectionStart;
                // field's content length - used to find right edge of content
                var conLength = element[0].value.length;

                // now just
                    switch (keyCode) {
                        case (39): // Right
                            // if caret position is at the rightmost of the input value
                            if (cert>=conLength) {
                                // get the next element
                                var nextInput = (inputs.index(this) == inputs.length-1) ? inputs.get(0) : inputs.get(inputs.index(this) + 1);
                                if (nextInput) {
                                    //focus on the next element
                                    nextInput.focus();
                                    //move caret to the start of the element
                                    nextInput.selectionStart = 0;
                                }
                            }
                            break;
                        case (37):  // Left
                            // if caret position is at the beginning of the input
                            if (cert==0)
                            {
                            // get the previous element
                            var prevInput = inputs.get(inputs.index(this) - 1);
                            if (prevInput) {
                                // focus on the previous element
                                prevInput.focus();
                                }
                            }
                    break;
                    }
            });
        }
    }
});

sample

[codepen_embed height=”204″ theme_id=”0″ slug_hash=”lFvLc” default_tab=”result”]See the Pen form-arrows – directive by ziv pugatch (@zivpug) on CodePen.[/codepen_embed]

Leave a Reply

Your email address will not be published. Required fields are marked *