title: Implementing organic list browsing using arrow keys and intelligent lazy loading
body: <p><strong>Simple Scenario</strong></p>
  
  <p>I have a list, i implemented browsing with the arrow keys (up, down) and on each change of the current list item, a database object gets loaded via AJAX.</p>
  
  <p>Sweet.</p>
  
  <p><strong>The Problem</strong></p>
  
  <p>When a user browses through the list very fast, i don't want every request to go off. But the original request should go off instantly, of course.</p>
  
  <p>My idea was to set a timeout using a variable as delay, and after the initial load of an item, increase that variable.</p>
  
  <p>That works, but when the user stops browsing for a short moment, but then continues, i still don't want every request to go off.</p>
  
  <p>So i figured, the delay variable must be reasonably increased with every browsing event, until a threshold is reached.</p>
  
  <p>This organic approach would successfully minimize the amount of unnecessary loading of items.</p>
  
  <p><strong>My Solution</strong></p>
  
  <p>I came far. This piece of code (explanations below) will do the job, with one <strong>major culprit</strong>: </p>
  
  <p>After the first time browsing is done and then stopped, the delay will automatically stay at a (2nd step) minimum value of 150ms.</p>
  
  <p>Of course i tried to fix this, but as you will see, this is an interesting yet probably fairly common logical problem – and i think my overall approach is wrong. </p>
  
  <p>But i don't see how. Brain does not compute. Computer says no.</p>
  
  <p><strong>Code</strong></p>
  
  <p>You can either sift through my given example or <a href="https://jsfiddle.net/tonnqo0h/1/" rel="noreferrer">go here for a fully functional simulator in jsFiddle</a>.</p>
  
  <p>If you choose the jsFiddle: </p>
  
  <p>Click the button, the item load appears immediately. Now wait a bit, click the button again, the initial load will be delayed. If you continuously press the button quickly, the item load will appear only when you're finished with your click-spree.</p>
  
  <p><strong>Code Sample</strong></p>
  
  <p>We're inside an object literal, just so you know.</p>
  
  <pre><code>_clickTimer: false,                     // holds what setTimeout() returns
  _timerInc: 0,                           // the your timer delay are belong to us
  
  /**
   * Function is triggered whenever the user hits an arrow key
   * itemRef is the passed list item object (table row, in this case)
   */
  
  triggerItemClick: function(itemRef){
  
      var that=this;
      var itemId=$(itemRef).data('id');   // Get the item id
  
      if(this._clickTimer){               // If a timeout is waiting
  
          clearTimeout(this._clickTimer); // we clear it
          this._itemClickTimer=false;     // and reset the variable to false
  
          /**
           * Note that we only arrive here after the first call
           * because this._clickTimer will be false on first run
           */
  
          if(this._timerInc == 0){        // If our timer is zero
              this._timerInc = 150;       // we set it to 150
          } else {                        // otherwise
              if(this._timerInc &lt;= 350)   // we check if it is lower than 350 (this is our threshold)
                  this._timerInc += 15;   // and if so, we increase in steps of 15
          }
  
      } 
  
      /**
       * Regardless of any timing issues, we always want the list
       * to respond to browsing (even if we're not loading an item.
       */
  
      this.toggleListItem(itemId);
  
      /**
       * Here we now set the timeout and assign it to this._clickTimer
       */
  
      this._clickTimer=setTimeout(function(){
  
          // we now perform the actual loading of the item
          that.selectItem(itemId);
  
          // and we reset our delay to zero
          that._timerInc=0;
  
      }, this._timerInc); // we use the delay for setTimeout()
  
  }
  </code></pre>
  
  <p><strong>Explanation</strong></p>
  
  <p>On first call: <code>_clickTimer</code> is <code>false</code>, <code>_timerInc</code> is <code>0</code>, so the first call will lead to a delay of <code>0</code> for <code>setTimeout()</code> and <code>_clickTimer</code> will be set. The item will be instantly loaded.</p>
  
  <p>Second call - given that our timeout is still waiting to be triggered, the <code>_clickTimer</code> gets cleared, the delay set to <code>150</code> if <code>0</code> or increased by <code>15</code> if lower than <code>350</code> (threshold).</p>
  
  <p>This works great if you keep browsing. The timer increases, the load only gets fired once you stop browsing for a good moment.</p>
  
  <p><strong>But</strong> after you stopped, the next time you continue, <code>_clickTimer</code> will <strong>not be false</strong> (because <code>setTimeout()</code> assigns a counter to it), so in turn <code>_timerInc</code> will be set to <code>150</code> right away. So the first browse will lead to a delay of 150ms before anything gets loaded.</p>
  
  <p>Call me crazy or fastidious, but the goal is to not have this delay.</p>
  
  <p>Of course you'll say: simple, set <code>_clickTimer</code> to false at the end of the <code>setTimeout()</code> closure, so it gets reset once browsing is done and an item gets loaded. Great, but this results in the delay never going above 0ms. Think it through, you'll see.</p>
  
  <p>I hope this was explained properly and that someone's brain is more capable of finding a solution to this than mine.</p>