title: Given a set of top/bottom pixel ranges, how do I find which one has been scrolled into?
body: <h2>The Problem</h2>
  
  <p>As the page is scrolled from top to bottom, the user will pass through these ranges. Suppose they are values in an alphabetical address book: as they scroll from top to bottom, they will pass from A to Z. There are tabs on the side labeled with the names of sections in the document, labeled 'Aa-An', 'Am-As', etc.</p>
  
  <p>What I want is, as the user scrolls from top to bottom, the scroll handler determines which of these sections is currently scrolled into and highlights the tab correlated with the current section.</p>
  
  <p>In Javascript, on the document's scroll event, I need to determine whether the document's vertical scroll falls between one of a set of values. The values look like this:</p>
  
  <pre><code>var indices = {
    'Aa-An': [{id: 92, name: 'Aardvark'}, {id: 13, name: 'Affable'}, ...],
    'Am-As': [{id: 28, name: 'Amber'}, ...],
    ...
  }
  
  var heights = {
    'item_92': {top: 170, bottom: 380},
    'item_28': {top: 380, bottom: 600},
    ...
  }
  </code></pre>
  
  <p>The keys in <code>heights</code> are the <code>id</code> attributes of the first element in each array in <code>indices</code>. <code>top</code> is the location on the page of the first element in that list, and <code>bottom</code> is the location on the page of the bottom edge of the last element in that list.</p>
  
  <h2>The Current Solution</h2>
  
  <p>My scroll handler is:</p>
  
  <pre><code>var scroll = get_vertical_scroll();
  
  for(var key in heights) {
    var top = heights[key].top;
    var bottom = heights[key].bottom;
  
    if(scroll &gt;= top &amp;&amp; scroll &lt; bottom) {
      select('.index_tab').removeClass('selected');
      get('index_'+key).addClass('selected');
      return;
    }
  }
  </code></pre>
  
  <p>At most, there will only be 12 keys in <code>heights</code> to iterate through, so this is an effective linear solution. But, the scroll event is already pretty slow and if there's a smart way to make this O(1) -- even in only some cases -- that would go a long way given that this happens on each scroll of the document.</p>