34

I have a large form on my website that I want to be able to autosave to a database as the user is filling it out. Almost identical to how google drive works when typing a document.

I am trying not to have a function that runs every X seconds but rather a function that runs when the user has taken a break in typing. So, if the user has not typed in 1 hour but is still on the page, it doesn't keep pushing save requests.

This is all I have so far which is a basic javascript form submit.

$("#page1Form").submit(function(event){
  event.preventDefault();  
  $changesSaved.text("Saving...");
  var url = "/backend/forms/page1-POST.php";
        $.ajax({
         type: "POST",
         url: url,
         data: $("#page1Form").serialize(),
         success: function(data) { $changesSaved.text(data); }
        });
  return false;
  });
bryan
  • 8,879
  • 18
  • 83
  • 166

3 Answers3

64

Debounce the textarea change.

Demo: jsFiddle

Put your ajax call in the saveToDB() function. These event names('input propertychange change') will trigger on any form element change such as radio buttons, inputs, etc.

var timeoutId;
$('#the-textarea').on('input propertychange change', function() {
    console.log('Textarea Change');

    clearTimeout(timeoutId);
    timeoutId = setTimeout(function() {
        // Runs 1 second (1000 ms) after the last change    
        saveToDB();
    }, 1000);
});

function saveToDB()
{
    console.log('Saving to the db');    
}

Here is a full demo showing you how to debounce a full form and use ajax to send the data and then return the status (Saving, Saved, etc).

Demo full form and ajax: jsFiddle

paaacman
  • 3,012
  • 1
  • 20
  • 18
MLM
  • 3,660
  • 3
  • 41
  • 66
  • 1
    I agree with you about the timeout, but your going to need to bind this to the entire form, not just a textarea. – Blake Plumb Nov 11 '13 at 16:40
  • This is awesome MLM, works exactly how I expected. Thanks for the suggestions @BlakePlumb I will definitely modify that. – bryan Nov 11 '13 at 16:45
  • @bryan Updated my answer with a solution for full form. – MLM Nov 11 '13 at 16:47
  • @MLM any chance you could give me an example of how to use the debounce? – bryan Nov 11 '13 at 16:50
  • 1
    @bryan Updated Answer. Check out the ajax demo – MLM Nov 11 '13 at 16:59
  • Thanks @MLM! What about if I also needed the save function to start on a change in radio button/check box? – bryan Nov 11 '13 at 20:01
  • @bryan Both demo's for full form are updated to accomdate radio and check boxes. – MLM Nov 11 '13 at 20:36
  • 1
    @MLM thanks for the great solution... I tried it though, and it appears to not be sending the data in the textarea. It sends all the fields except the textarea. – Wes Jun 15 '16 at 20:05
7

I know that this question is old, but I would like to include a code that I like the most. I found it here: http://codetunnel.io/how-to-implement-autosave-in-your-web-app/

Here is the code:

var $status = $('#status'),
    $commentBox = $('#commentBox'),
    timeoutId;

$commentBox.keypress(function () {
    $status.attr('class', 'pending').text('changes pending');

    // If a timer was already started, clear it.
    if (timeoutId) clearTimeout(timeoutId);

    // Set timer that will save comment when it fires.
    timeoutId = setTimeout(function () {
        // Make ajax call to save data.
        $status.attr('class', 'saved').text('changes saved');
    }, 750);
});

It saves after the user stops writing for more than 750 milliseconds.

It also has a status letting the user know that the changes have been saved or not.

  • It doesn't work when the comment is selected+deleted or backspaced. – Mukesh Kumar Sep 15 '20 at 19:39
  • It works but I had to trigger the event based on both keypress and blur so that the last letter of the textarea is also saved : $commentBox.on('keyup blur', function () { .... } – Paul Noon May 29 '21 at 09:57
1

Try Sisyphus.js https://github.com/simsalabim/sisyphus. It persists the form data in the browser's local storage and is robust against tabs closing, browser crashes, etc...

spitz
  • 658
  • 1
  • 8
  • 19