-1

I searched a lot for a solution to this certainly-not-unique problem, but I have not found anything that will work in my context of an HTML page.

I have an input text that contains some kind of source-code that generates something, and I can show a preview of that something on the same HTML page (by updating the background image, for example). Note that the source could be a LaTeX file, an email, a Java program, a ray-trace code, etc. The "action" to generate the preview has a certain cost to it, so I don't want to generate this preview at each modification to the source. But I'd like the preview to auto-update (the action to fire) without the user having to explicitly request it.

Another way to phrase the problem is to keep a source and sink synchronized with a certain reasonable frequency.

Here's my solution that's too greedy (updates at every change):

$('#source-text').keyup(function(){
    updatePreview(); // update on a change
  });

I tried throttling this by using a timestamp:

$('#source-text').keyup(function(){
    if (nextTime "before" Now) { // pseudocode
       updatePreview(); // update on a change
    } else {
       nextTime = Now + some delay // pseudocode
    }
  });

It's better, but it can miss the last updates once a user stops typing in the source-text field.

I thought of a "polling loop" for updates that runs at some reasonable interval and looks for changes or a flag meaning an update is needed. But I wasn't sure if that's a good model for an HTML page (or even how to do it in javascript).

zoran404
  • 1,342
  • 1
  • 19
  • 32
Fuhrmanator
  • 9,639
  • 6
  • 52
  • 97

2 Answers2

1

Use setTimeout, but store the reference so you can prevent it from executing if further editing has occurred. Basically, only update the preview once 5 seconds past the last keystroke has passed (at least in the below example).

// maintain out of the scope of the event
var to;

$('#source-text').on('keyup',function(){
  // if it exists, clear it and prevent it from occuring
  if (to) clearTimeout(to);

  // reassign it a new timeout that will expire (assuming user doesn't
  // type before it's timed out)
  to = setTimeout(function(){
    updatePreview();
  }, 5e3 /* 5 seconds or whatever */);
});

References:

And not to self-bump, but here's another [related] answer: How to trigger an event in input text after I stop typing/writing?

Community
  • 1
  • 1
Brad Christie
  • 98,427
  • 16
  • 148
  • 198
  • I thought your answer worked, but it doesn't update until I stop typing. I want updates to occur while typing, but at a frequency less than every keystroke. See http://jsfiddle.net/p4u2mhb9/2/ – Fuhrmanator Aug 19 '14 at 22:43
  • @Fuhrmanator: How about every 5 seconds while [still] typing? http://jsfiddle.net/p4u2mhb9/4/ – Brad Christie Aug 20 '14 at 12:27
0

I tweaked @bradchristie's answer, which wasn't quite the behavior I wanted (only one update occurs after the user stops typing - I want them to occur during typing, but at a throttled rate).

Here's the solution (demo at http://jsfiddle.net/p4u2mhb9/3/):

// maintain out of the scope of the event
var to;
var updateCount = 0;
var timerInProgress = false;

$('#source-text').on('keyup', function () {
    // reassign a new timeout that will expire
    if (!timerInProgress) {
        timerInProgress = true;
        to = setTimeout(function () {
            timerInProgress = false;
            updatePreview();
        }, 1e3 /* 1 second */ );
    }
});
Community
  • 1
  • 1
Fuhrmanator
  • 9,639
  • 6
  • 52
  • 97