1

This is how I currently save my form every 2 minutes. I want to increase that to save more often or even better if it saves every 2 minutes as well as soon after the user has finished making any changes.

My form mainly contains - Radio, Textarea form elements but it would be nice if it tracks all elements, if not most.

Any ideas on how do I do that?

<script>
    window.setInterval(saveForm, (1000*60*2));  // 1000 millisecons = 1 sec

function saveForm()
{
    var actionurl = document.getElementById("myform").action;
    var postdata = $('#myform').serializeArray();
    $.ajax({
      method: "POST",
      url: actionurl,
      data: postdata
     }).done(function( msg ) {});

}
</script>

HTML

<form action="/myform/complete/15" id="myform" method="post" accept-charset="utf-8">
    <div class="view-wrap"> 

        <div class="view-item">
            <div class="row">
                <div class="col-md-3">
                    <span style="font-size: 14px;">1. This is first statement for a new assesment.</span>
                </div>
                <div class="col-md-9">
                    <div class="row">
                        <div class="col-md-3">
                            <div class="answers_opts_div">
                            <ul class="list-unstyled" id="answerslist_856">
                                <li>
                                    <input  type="radio" id="answer_radio_856_1" name="answers[856]" value="5" />
                                    <label for="answer_radio_856_1" style="color:#449D44">Strongly Agree</label>
                                </li>
                                <li>
                                    <input  type="radio" id="answer_radio_856_2" name="answers[856]" value="4" />
                                    <label for="answer_radio_856_2" style="">Agree</label>
                                </li>
                                <li>
                                    <input  type="radio" id="answer_radio_856_3" name="answers[856]" value="3" />
                                    <label for="answer_radio_856_3" style="">Undecided</label>
                                </li>
                            </ul>
                        </div>
                    </div>
                    <div class="col-md-9">
                        <textarea name="answer_comments[856]" rows="5" data-answerslist="answerslist_856" class="form-control answercomments" placeholder="comment required" style="border-width:4px;"></textarea>
                    </div>
                </div>
            </div>
        </div>

        <div class="view-item">
            <div class="row">
                <div class="col-md-3">
                    <span style="font-size: 14px;">1. This is the second statement for a new assesment.</span>
                </div>
                <div class="col-md-9">
                    <div class="row">
                        <div class="col-md-3">
                            <div class="answers_opts_div">
                            <ul class="list-unstyled" id="answerslist_857">
                                <li>
                                    <input  type="radio" id="answer_radio_857_1" name="answers[857]" value="5" />
                                    <label for="answer_radio_857_1" style="color:#449D44">Strongly Agree</label>
                                </li>
                                <li>
                                    <input  type="radio" id="answer_radio_857_2" name="answers[857]" value="4" />
                                    <label for="answer_radio_857_2" style="">Agree</label>
                                </li>
                                <li>
                                    <input  type="radio" id="answer_radio_857_3" name="answers[857]" value="3" />
                                    <label for="answer_radio_857_3" style="">Undecided</label>
                                </li>
                            </ul>
                        </div>
                    </div>
                    <div class="col-md-9">
                        <textarea name="answer_comments[857]" rows="5" data-answerslist="answerslist_857" class="form-control answercomments" placeholder="comment required" style="border-width:4px;"></textarea>
                    </div>
                </div>
            </div>
        </div>

    </div>
</form>
NoNice
  • 391
  • 1
  • 2
  • 14

2 Answers2

1

As suggested by other comments, your best option is to listen to the input and change event fired by any input elements in the form. Simply bind this event listener to saveForm and you should be good to go:

// Save form every 2 minutes
window.setInterval(saveForm, 1000 * 60 * 2);

// Listen to input or change events to save form
// Might want to throttle your callback here
$('#myform :input').on('change input', saveForm);

function saveForm() {
  // The rest of your logic
}

The reason why both input and change events are both listened to is because of browser compatibility: Internet Explorer does not support firing of oninput event on checkbox and radio buttons.

The drawback is that this causes saveForm to be fired extremely often, so an improved version will be to throttle the callback triggered by the input/change event, so that it does not fire excessively. This can be done by using the jQuery debounce/throttle plugin:

// Listen to input or blur events to save form
// Only fire once every 250ms
$('#myform :input').on('change input', $.debounce(saveForm, 1000));

The code above debounces the change and input events, so that the form data is only sent every second. To determine if debounce or throttle suits you better, check out this very cool visualization: http://demo.nimius.net/debounce_throttle/

Terry
  • 63,248
  • 15
  • 96
  • 118
  • Yes firing excessively is my main concern as I was going to decrease the timer to say every 30 seconds or so but I thought that's not a good idea. – NoNice May 02 '18 at 13:40
  • @NoNice If that's the case, always use a debounce/throttle function that helps you reduce the calls you make to the server. The plugin I suggested is very widely used, and will definitely help you a lot :) – Terry May 02 '18 at 13:40
  • Thank you - I am just going to give it a test. Re milliseconds ... 1000 milliseconds = 1 second ... 60 seconds = 1minute ... so every 2 minutes??? – NoNice May 02 '18 at 13:43
  • @NoNice Whoops, your interval calculations are actually correct :) I've updated my answer – Terry May 02 '18 at 13:43
  • That plugin is almost 8 years old. I am using Jquery 1.10.1 - Do you still recommend this plugin or any alternative? I did try searching on Google but I seem to find loadash or other solutions? – NoNice May 02 '18 at 16:03
0

There would be a lot of ways to do what you are trying to achive. What I think a good solution would be, is to add the eventlistener that will be trigger on the form when the user interacts with it.

With this you can use setTiemout and clearTiemout.

Usuing keyup for the text area and click for the rest of the form, this will set a timeout of one second to the save function. If the user triggers an other event before the function runs, the timeOut will be clear and reset.

Hope this helps :)

function saveForm()
{
  console.log('Save');
    var actionurl = document.getElementById("myform").action;
    var postdata = $('#myform').serializeArray();
    $.ajax({
      method: "POST",
      url: actionurl,
      data: postdata
     }).done(function( msg ) {});
     clearTimeout(inter);
}
var inter = setTimeout(saveForm, (1000)); 
var form = document.getElementById('myform');
form.addEventListener('click',function(){  
  clearTimeout(inter);
  inter = setTimeout(saveForm, (1000));
});
form.addEventListener('keyup',function(){  
  clearTimeout(inter);
  inter = setTimeout(saveForm, (1000));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="/myform/complete/15" id="myform" method="post" accept-charset="utf-8">
    <div class="view-wrap"> 

        <div class="view-item">
            <div class="row">
                <div class="col-md-3">
                    <span style="font-size: 14px;">1. This is first statement for a new assesment.</span>
                </div>
                <div class="col-md-9">
                    <div class="row">
                        <div class="col-md-3">
                            <div class="answers_opts_div">
                            <ul class="list-unstyled" id="answerslist_856">
                                <li>
                                    <input  type="radio" id="answer_radio_856_1" name="answers[856]" value="5" />
                                    <label for="answer_radio_856_1" style="color:#449D44">Strongly Agree</label>
                                </li>
                                <li>
                                    <input  type="radio" id="answer_radio_856_2" name="answers[856]" value="4" />
                                    <label for="answer_radio_856_2" style="">Agree</label>
                                </li>
                                <li>
                                    <input  type="radio" id="answer_radio_856_3" name="answers[856]" value="3" />
                                    <label for="answer_radio_856_3" style="">Undecided</label>
                                </li>
                            </ul>
                        </div>
                    </div>
                    <div class="col-md-9">
                        <textarea name="answer_comments[856]" rows="5" data-answerslist="answerslist_856" class="form-control answercomments" placeholder="comment required" style="border-width:4px;"></textarea>
                    </div>
                </div>
            </div>
        </div>

        <div class="view-item">
Gerardo BLANCO
  • 5,590
  • 1
  • 16
  • 35