开发者

HTML: When a browser scrolls to an input, how can one make it bring the entire input's parent into view?

开发者 https://www.devze.com 2023-01-19 22:37 出处:网络
I\'m not a web guy, so this might be something really simple I\'m missing, but: Consider the following page:

I'm not a web guy, so this might be something really simple I'm missing, but:

Consider the following page:

http://pastehtml.com/view/1bg9qno.html

Which is basically a list of <input>s, and each input has a helper <span> with text (that will change along with the input's value on keyUp).

So when the list is long enough (like in the above HTML page), if you tab thru the inputs, you will eventually get to the input on the bottom of the page, tab again, and the browser will scroll down to the next input.

In my case, the input has the helper text which is crucial to my app.

The problem is that when the user tabs down to the input that is not visible, the browser only brings that input into the view, and not his entire parent (<div class="item">) which contains the helper text. As a result, this helper text is not visible to the user while he enters stuff in the input.

How can one tell the browser to bring the entire parent into view when focusing the out-of-view input?

Is there any elegant solution?

BTW: This doesn't happen in Chrome, since Chrome always scrolls down a part-page, but it always happens in Firefox which always scrolls as little as possible to the input.

The HTML looks like this:

<body>
    <div class="item">
        <input type="text" value="text" />
        <b开发者_StackOverflow社区r />
        <span>helper text</span>
    </div>
    <hr />
    ...
    <hr />
    <div class="item">
        <input type="text" value="text" />
        <br />
        <span>helper text</span>
    </div>
</body>


<html>
  <head>
    <script>
      function scrollParentIntoView(elem){
        setTimeout(function(){
           var children  = elem.parentNode.children;
           var lastChild = children[children.length - 1];
           lastChild.scrollIntoView();
           elem.parentNode.scrollIntoView();
           //elem.ScrollIntoView();
         },1);
      }
    </script>
  </head>
  <body>
    ...
    <div>
      <input onfocus="scrollParentIntoView(this);" />
      ...
      <p>end</p>
    </div>
    ...
  </body>
</html>

I've tested on FF and Chrome and seems to do the job - you can see the input and 'end' when each '...' is replaced with a dozen
tags


Here is a solution using jQuery. It's based on the height of your item container.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
    $(document).ready(function() {
        $(".item input").focus(function() {
            var parent = $(this).parent();

            // Check if the bottom of the item container is below the viewport
            if ($(parent).position().top + $(parent).height() > $(window).scrollTop() + $(window).height())
            {
                // Adjust the scroll position according to the height of the item container
                $(window).scrollTop($(window).scrollTop() + $(parent).height());
            }
        });
    });
</script>

Edit

Here is a demo for you: http://pastehtml.com/view/1bnv1xb.html


This Javascript works in FF 3.6, IE 8, Safari 4, and Chrome 3.1. It doesn't require JQuery, doesn't need setTimeouts, and can be condensed to about 8 lines:

//Collect the elements 
var ALL = document.getElementsByTagName("INPUT");

for(x=0;x<ALL.length;x++) {
  //Add relative position style to allow offset math
  ALL.style.position = 'relative';

  ALL[x].onfocus = function() {
    //Find scroll offset distance
    var temp = this.offsetParent.offsetTop + 
               this.offsetParent.offsetHeight - 
               document.documentElement.clientHeight;

    //Detect webkit browser and apply scroll offset as appropriate
    window.devicePixelRatio ? 
      document.body.scrollTop = temp : 
      document.documentElement.scrollTop = temp;
  }
}


Of course, the obvious solution here is to put all the important content above the input element, but it's obvious that that won't do for whatever reason, so here's another solution:

Remember that tabindex can be used to allow any element to be focused. This means that we can simply drop a tabindex on the parent of the input elements to allow the entire parent to gain focus and scroll into view.

However, this also means that tab must be tapped twice to get the input element focused. You will also need to explicitly set tabindex on the input element to have them be the next in line to gain focus.

<ol id="input">
    <li tabindex="3">
        <input type="text" tabindex="5" />
        <p>Helper Text</p>
    </li>
    <li tabindex="7">
        <input type="text" tabindex="10" />
        <p>Helper Text</p>
    </li>
</ol>

You'll also want to give the parent elements a :focus style instead of the rather ugly dotted outline.

See: http://www.jsfiddle.net/F2fwy/2

0

精彩评论

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