1

I have this script below which is used in a survey. The problem I have is, onbeforeunload() works when I don't call a function inside it. If I make any function call(save_survey() or fetch_demographics()) inside it, the browser or the tab closes without any prompt.

  <script type="text/javascript">

  $(document).ready(function() {

  $('#select_message').hide();    
  startTime = new Date().getTime();
  });

  loc = 0;
  block_size = {{ block_size }};
  sid = {{ sid }};
  survey  = {{ survey|tojson }}; 
  survey_choices = '';
  startTime = 0;
  demographics_content = {};

 function save_survey(sf)
  {       
      var timeSpentMilliseconds = new Date().getTime() - startTime;
      var t = timeSpentMilliseconds / 1000 / 60;
      var surveydat = '';
          if(sf==1)
          { //Success
              surveydat = 'sid='+sid+'&dem='+JSON.stringify(demographics_content)+'&loc='+loc+'&t='+t+'&survey_choice='+JSON.stringify(survey_choices);
          }
          if(sf==0)
          { //Fail
              surveydat = 'sid='+sid+'&dem='+json_encode(demographics_content)+'&loc='+loc+'&t='+t+'&survey_choice='+json_encode(survey_choices);
          }
          //Survey Save Call
          $.ajax({
          type: 'POST',
          url: '/save_surveyresponse/'+sf,
          data: surveydat,
          beforeSend:function(){
              // this is where we append a loading image
              $('#survey_holder').html('<div class="loading"><img src="/static/img/loading.gif" alt="Loading..." /></div>');
            },
          success:function(data){
              // successful request; do something with the data
              $('#ajax-panel').empty();
              $('#survey_holder').html('Success');
              alert("Dev Alert: All surveys are over! Saving data now...");
              window.location.replace('http://localhost:5000/surveys/thankyou');
            },
          error:function(){
              // failed request; give feedback to user
              $('#survey_holder').html('<p class="error"><strong>Oops!</strong> Try that again in a few moments.</p>');
            }
          });


  }

  function verify_captcha()
  {
     // alert($('#g-recaptcha-response').html());
  }

  function block_by_block()
  {
      var div_content ='<table border="0" cellspacing="10" class="table-condensed"><tr>';
      var ii=0;
      var block = survey[loc];
      var temp_array = block.split("::");
      if(loc>=1)
      {
          var radio_val = $('input[name=block_child'+(loc-1)+']:checked', '#listform').val();
          //console.log(radio_val);
          if(radio_val!=undefined)
              survey_choices += radio_val +'\t';
          else
              {
                  alert("Please select one of the choices");
                  loc--;
                  return false;
              }

      }
      for(ii=0;ii<block_size;ii++)
      {
          //Chop the strings and change the div content
          div_content+="<td>" + temp_array[ii]+"</td>";
          div_content+="<td>" + ' <label class="btn btn-default"><input type="radio"  id = "block_child'+loc+'" name="block_child'+loc+'" value="'+temp_array[ii]+'"></label></td>';
          div_content+="</tr><tr>";
      }

      div_content+='<tr><td><input type="button" class="btn" value="Next" onClick="survey_handle()"></td><td>';
      div_content+='<input type="button" class="btn" value="Quit" onClick="quit_survey()"></td></tr>';
      div_content+="</table></br>";
      $("#survey_holder").html(div_content);

      //return Success;
  }

  function updateProgress()
  {

          var progress = (loc/survey.length)*100;
          $('.progress-bar').css('width', progress+'%').attr('aria-valuenow', progress);
          $("#active-bar").html(Math.ceil(progress));
 }


  function survey_handle()
  {

      if(loc==0)
      {
          verify_captcha();
          $("#message").hide();
          //Save the participant data and start showing survey
          fetch_demographics(); 
          block_by_block();
          updateProgress();
          $('#select_message').show();    
      }
      else if(loc<survey.length)
      {
        block_by_block();
        updateProgress();
      }

      else if(loc == survey.length)
      {
          //Save your data and show final page
          $('#select_message').hide();    
          survey_choices += $('input[name=block_child'+(loc-1)+']:checked', '#listform').val()+'\t';
          //alert(survey_choices);
          //Great way to call AJAX
          save_survey(1);
      }
      loc++;
      return false;
  }
  </script>
  <script type="text/javascript">
      window.onbeforeunload = function() {
      var timeSpentMilliseconds = new Date().getTime() - startTime;
      var t = timeSpentMilliseconds / 1000 / 60;
      //fetch_demographics();
      save_survey(0);
      return "You have spent "+Math.ceil(t)+ " minute/s on the survey!"; 
      //!!delete last inserted element if not quit

  }
  </script>

I have checked whether those functions have any problem but they work fine when I call them from different part of the code. Later, I thought it might be because of unreachable function scope but its not the case. I have tried moving the onbeforeunload() at the end of script and the problem still persists. Wondering why this is happening, can anyone enlighten me?

St1id3r
  • 313
  • 5
  • 12
  • what do your browser debugger say ? – 3pic Jul 24 '15 at 07:49
  • possible duplicate of [window.onbeforeunload ajax request problem with Chrome](http://stackoverflow.com/questions/4945932/window-onbeforeunload-ajax-request-problem-with-chrome) – Adriano Repetti Jul 24 '15 at 07:50
  • @AdrianoRepetti I have just tried with "async: false" but its still the same. I am asking this because it worked well(calling save_survey() in onbeforeunload) before. After I made couple of edits in save_survey() function, it stopped working. – St1id3r Jul 24 '15 at 07:59
  • @Strukt There's no chance to see debugger for me as it closes along with the tab. I am using inspect element to capture the console. Please correct me if am doing it wrong way.. – St1id3r Jul 24 '15 at 08:00
  • @St1d3 Right. It seems the bug is in your function, is the function loaded when onbefore... is called ? have you try putting the function bloc code instead of the function "name" ? – 3pic Jul 24 '15 at 08:02
  • @St1id3r once your ajax succeeds, are you sure HTML elements are loaded ?... that s the matter of async. Async should be quite worse to some extents. Is it working if you replace `onbeforeunload`with `onload` (curious) ? – 3pic Jul 24 '15 at 08:04
  • If you set a breakpoint then tab won't be closed.Moreover in onbeforeunload also alert() isn't allowed (and DOM changes may be ignored as well). – Adriano Repetti Jul 24 '15 at 08:09
  • 1
    @Strukt I am using Flask and I don't see any request in the server console. – St1id3r Jul 24 '15 at 08:10
  • @St1id3r you see no request ? Here is the issue... is this relevant ? http://flask.pocoo.org/docs/0.10/patterns/jquery/ – 3pic Jul 24 '15 at 08:11
  • @AdrianoRepetti Thanks a lot! I identified where the problem was. There is no json_encode instead of JSON.stringify and hence it is crashing. That tip with debugger is invaluable. Also, its working fine even without async: false. – St1id3r Jul 24 '15 at 08:32
  • Be careful with AJAX in onbeforeunload, it doesn't work in every browser and they sometimes change its behavior from one version to the other (see Chrome). Keep it synchronous (of course only in onbeforeunload). – Adriano Repetti Jul 24 '15 at 08:50
  • @AdrianoRepetti If I use synchronous request, the application is having a Broken Pipe problem and nothing is replied back to the Javascript. The script crashes for a different reaspn now. Not sure why I am getting this error "error: [Errno 32] Broken pipe" in Flask Console when I am using synchronous request. – St1id3r Jul 24 '15 at 09:03
  • Did you also drop alert() and window.location.replace calls? It's not something you can do when user is closing tab or navigating away. – Adriano Repetti Jul 24 '15 at 09:10
  • Yea, after you said. I am checking all the code once and also my Python script. Will post once I find something. :) – St1id3r Jul 24 '15 at 09:16

1 Answers1

0

I identified where the problem was. I am using json_encode instead of JSON.stringify and hence it is crashing(which I found and changed already in sf=1 case). That tip with debugger is invaluable. Also, its working fine even without async: false.

Thank you again @AdrianoRepetti!

St1id3r
  • 313
  • 5
  • 12