开发者

jquery: select next input even though in different fieldset

开发者 https://www.devze.com 2023-01-29 09:48 出处:网络
I have the following html page: <form action=\"editProfile\" id=\"userInformation\"> <fieldset id=\"birthdate\">

I have the following html page:

<form action="editProfile" id="userInformation">
<fieldset id="birthdate">
<label><input type="text" id="day" maxlength="2"/>/<input type="text" id="month" maxlength="2"/>/<input type="text" id="year开发者_Python百科" maxlength="2"/>
</fieldset>
<fieldset>
<label>Name</label><input type="text" id="name"/>
</fieldset>
</div>

Now I'd like to always jump to the next inputfield. I've tried:

$("#birthdate input[type=text]").keyup(function(e){
    if($(this).val().length == $(this).attr('maxlength')){
        $(this).next(":input").focus();
    }   
});

But that seems to stay within the fieldset. And nextall doesn't seem to work or I'm using it wrong.

edit: My solution so far:

        if($(this).val().length == $(this).attr('maxlength')){
            if($(this).parent().children().last().attr('id') == $(this).attr("id")){
                $(this).parent().next().find(':input').focus();
            }else{
                $(this).next("input").focus();
            }
        }


Here is a solution using a custom method (working example: http://jsfiddle.net/jamiec/uQdSS/)

(function($) {
   $.fn.nextOrParentNext = function(sel){
       var $next = $(this).next(sel);
       if($next.length)
       {
               return $next;
       }
       else
       {
           var $nextParent = $(this).parent().next().find(sel);
           if($nextParent.length)
           {
               return ($nextParent);
           }
       }                  
   };
})(jQuery);

$("#birthdate input:text").keydown(function(e){
    if($(this).val().length == $(this).attr('maxlength')){
        $(this).nextOrParentNext(":input").focus();
    }
});

basically, the custom plugin wraps the if/else logic of it being the last item in a fieldset.


Try this:

$("#birthdate input[type=text]").keyup(function(e){
    if($(this).val().length == $(this).attr('maxlength')){
      var $next = $(this).next(":input");
      if ($next.length == 0) // there are no next fields! try another fieldset
        $next = $(this).closest("fieldset").next("fieldset").find(":input:first");
      $next.focus();
    }
});


I know I also added it in my main post but this is easier to recieve comments. It seems like there are a lot of sollutions.

My own solution for now:

if($(this).val().length == $(this).attr('maxlength')){
            if($(this).parent().children().last().attr('id') == $(this).attr("id")){
                $(this).parent().next().find(':input').focus();
            }else{
                $(this).next("input").focus();
            }
        }

I tried to keep it pretty straightfoward yet flexible I think I could probabily simplify the second if a bit.


This is one solution. Probably not the best solution but it seems to work using the age old modulus operator to cycle the inputs:

(function() {
    var inputs = $("#userInformation input[type=text]"),
        i = 0,
        length = inputs.length;

    inputs.keyup(function(e) {
        if ($(this).val().length == $(this).attr('maxlength')) {
            i = ++i % length;
            inputs[i].focus();
        }
    });

}());

Example: http://jsfiddle.net/jonathon/DysJe/

I've also made a change to the selector for the inputs. Rather than just picking the birthdate fieldset, I pick up all the inputs on the form. Stick these in an array and cycle through focusing on them. I've put everything in it's own closure to keep the variables I created hidden away from everything else.

When it reaches the last input, it will just stop (if maxlength is not set) or it will cycle the focus at the beginning again. If you don't want it to cycle, just remove the modulus operator.

It does have a drawback though : if the user doesn't focus on the first element then it will ignore this and just go on to focus the second, third, etc.


I did a little bit more on this and removed the need for the other variable. This one doesn't work out the next one on the fly, it's set at the very start. Each input has its event set to focus the next item in the inputs list rather than to the next element i. It won't cycle through like the one above but it will move correctly so if the user tabs to the second one it'll progress to the third, etc.

(function() {
    var inputs = $("#userInformation input");

    inputs.each(function(i, item) {
        $(item).keyup(function() {
            if ($(this).val().length == $(this).attr('maxlength') && inputs[i + 1]) {
                inputs[i + 1].focus();
            }
        });
    });
}());

http://jsfiddle.net/jonathon/TQzKS/

You may want to set the tabIndexes for your input elements too. I'm not 100% on the order that jQuery returns items in - I think it might be based on the DOM structure. If there's anything unusual in your ordering then you could use the tabIndex value of the element to sort the inputs list before running the .each part.

Oh yes, and in both of these examples I set the keyup event so that it moves as soon as I've finished typing.


I used something like this recently, which works well:

function goToInput(distance) {
    var $input = $(this),
        $inputs = getInputs(),
        currentIndex = $inputs.index($input),
        newIndex = ($inputs.length + currentIndex + distance) % $inputs.length;

    if (currentIndex > -1) {
        $input.blur();
        $inputs.eq(newIndex).focusin().focus();
    }
}

function getInputs() {
    return $('#userInformation :input:visible:enabled');
}

function goToNextInput() {
    goToInput.apply(this, [1]);
}

function goToPreviousInput() {
    goToInput.apply(this, [-1]);
}

and then

getInputs().keyup(goToNextInput);
0

精彩评论

暂无评论...
验证码 换一张
取 消