NudeCanalTroll
NudeCanalTroll

Reputation: 2286

How can I focus an input that's sliding in from off the screen?

I have an element (#cols) that's 3x wider than the <body>. It has 3 columns, each of which is exactly as wide as <body>. Clicking a button slides the #cols element over by the width of one column and simultaneously focuses the <input> in the column that's sliding into view:

http://jsbin.com/puhurakewa/1/edit?html,css,js,output

The problem, as you can see from the demo, is that focusing the input causes weird behavior. I believe the browser says,

"Crap, the user focused an input that's off-screen. I need to show it!"

and then magically scrolls the input into view. This breaks the transition.

Is there a way to disable this behavior? It's extremely undesirable. I've noticed it in Chrome, Safari, and Firefox on my Mac.

EDIT: Thank you for the answers so far. I should have been more specific with my question. I'm aware that I can "work around" this issue by waiting for the animation to end, but what I'm curious about is how to work through this issue and focus the input immediately. It's a better experience, because users can begin typing before the transition is over.

Upvotes: 5

Views: 2489

Answers (3)

Shaun Lebron
Shaun Lebron

Reputation: 2541

magically scrolls the input into view

This is the key. Just change scrollLeft of the container to 0 after focusing. I had to put a wrapper around it though.

http://jsbin.com/danarucama/1/edit?html,css,js,output

Upvotes: 1

EaziLuizi
EaziLuizi

Reputation: 1615

Since you already using Jquery might as well leverage the animate method, then on the complete function you focus the input, for more info check out the docs

Heres the JS (this works perfectly, but spend some time neatening it up/refactoring if you wish):

$(document).ready(function () {
  $('button').on('click', function () {

  var colId = $('.showing').attr('id');

    if(colId == "col-1"){
      $('#cols').animate({
          right: '200px'
      }, 1000, "swing", function(){
          $("#col-2").find('input').focus();
          $('#col-1').removeClass('showing');  
          $('#col-2').addClass('showing');              
      });
    }
    else if(colId == "col-2"){
      $('#cols').animate({
          right: '400px'
      }, 1000, "swing", function(){
          $("#col-3").find('input').focus();
          $('#col-2').removeClass('showing');  
          $('#col-3').addClass('showing');                    
      });          
    }
    else if(colId == "col-3"){
      $('#cols').animate({
          right: '0px'
      }, 1000, "swing", function(){
          $("#col-1").find('input').focus();
          $('#col-3').removeClass('showing');  
          $('#col-1').addClass('showing');                    
      });          
    }
  });
});

Then change your CSS to position relative like so:

#cols {
  height: 100%;
  transition: transform 400ms;
  white-space: nowrap;
  width: 600px;
  position:relative;
}

HTML (just add 'showing' class to first col):

<body>
   <button>Shift Cols & Focus Input</button>
   <div id="cols" col-to-show="1" >
      <div class="col showing" id="col-1">
        <input type="text" value="1" />
      </div>
      <div class="col" id="col-2">
        <input type="text" value="2" />
      </div>
      <div class="col" id="col-3">
        <input type="text" value="3" />
      </div>
  </div>
</body>

Here's a fiddle

Upvotes: 1

anpsmn
anpsmn

Reputation: 7257

Add the focus event after transition ends

 $('#cols').on('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', function() {
      $input.focus();
  });

JSbin Demo

Upvotes: 1

Related Questions