0

I am trying to disable a button to prevent multiple click in a synchronous ajax call. My code is as follows.

<!DOCTYPE html>
<html>
 <head>
  <meta charset="UTF-8"> 
  <link type="text/css" rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:300,400,500,700"> <!-- optional font -->
  <script  src="https://code.jquery.com/jquery-3.2.1.min.js"  integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="  crossorigin="anonymous"></script>
     <script type="text/javascript">
        $(document).ready(function(){
         var test = false;
            $(document).on('click', '#test', function(e){
             console.log(test);
             if (test) {
              return;
             }
             test = true;
                ajax_call();
  
            });

            function ajax_call() {
             $.ajax({
                    contentType: 'application/json;charset=utf-8',
                    type: 'POST',
                    url: 'https://validdomain',
                    dataType: 'json',
                    xhrFields: {
                      withCredentials: true
                    },
                    crossDomain: true,
                    data: JSON.stringify({'test' : 'test'}),
                    success: function(data, textStatus, jqXHR) {
                        console.log(data);test =false;
                        copypaste();
                        test = false;
                    },
                    error: function(jqXHR, textStatus, errorThrown) { 
                        console.log(textStatus);
                        
                        test = false;
                    },
                    async: false,
                });
            }

            function copypaste() {
             var tempInput = document.createElement("textarea");
                tempInput.setAttribute('id', 'copyid');
                tempInput.style = "position: absolute; left: -1000px; top: -1000px";
                tempInput.value = 'Text Copied';
                console.log(tempInput);
                document.body.appendChild(tempInput);
                tempInput.select();
                var result = document.execCommand('copy');
                document.body.removeChild(tempInput);
                if (result) {
                    alert('copied');
                }
                else {
                 alert('not copied');
                }

                return result;
            }

        });
    </script>
 </head>
 <body>
  <input type="submit" id="test"/>
 </body>
</html>

But my button is not disabled on the second click(I am getting alert twice.). If I make the ajax request as an asynchronous call then button is disabled. Is there any way that I can disable my button during a synchronous call?

Thanks in advance!

savithraj
  • 180
  • 1
  • 12
  • 1
    Never ever use `async: false`. It is a terrible practice and is deprecated by browser vendors. Look at the warnings in your browser console – charlietfl Jul 12 '17 at 18:04
  • 1
    Also if you use synchronous ajax you wouldn't have to disable the button – Musa Jul 12 '17 at 18:10
  • I know that it is a terrible option. But I used that because document.execCommand doesn't work if it is triggered from ajax callback functions. So I have to use async:false so that I will move my copypaste() function outside ajax. – savithraj Jul 12 '17 at 18:16
  • @Musa what do you mean by 'Wouldn't have to disable the button?'. If I don't disable it then if any user clicks the button twice then web service will be called twice which is bad. – savithraj Jul 12 '17 at 18:17
  • Because synchronous ajax locks up the UI. – Musa Jul 12 '17 at 18:40
  • Possible duplicate of [How to disable a submit button when AJAX request is in progress and enable it after receiving success AJAX response?](https://stackoverflow.com/questions/24989475/how-to-disable-a-submit-button-when-ajax-request-is-in-progress-and-enable-it-af) – Puroto Jul 12 '17 at 18:42

3 Answers3

0

I added the necessary statement but you could put it to another place for example inside the ajax callback function. Also I changed async: false

<!DOCTYPE html>
<html>
 <head>
  <meta charset="UTF-8"> 
  <link type="text/css" rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:300,400,500,700"> <!-- optional font -->
  <script  src="https://code.jquery.com/jquery-3.2.1.min.js"  integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="  crossorigin="anonymous"></script>
     <script type="text/javascript">
        $(document).ready(function(){
         var test = false;
            $(document).on('click', '#test', function(e){
             console.log(test);
             if (test) {
              return;
             }
             test = true;
                ajax_call();
                //Try adding this statement you can add wherever you want
                $(document).off('click', '#test');
  
            });

            function ajax_call() {
             $.ajax({
                    contentType: 'application/json;charset=utf-8',
                    type: 'POST',
                    url: 'https://validdomain',
                    dataType: 'json',
                    xhrFields: {
                      withCredentials: true
                    },
                    crossDomain: true,
                    data: JSON.stringify({'test' : 'test'}),
                    success: function(data, textStatus, jqXHR) {
                        console.log(data);test =false;
                        copypaste();
                        test = false;
                    },
                    error: function(jqXHR, textStatus, errorThrown) { 
                        console.log(textStatus);
                        
                        test = false;
                    },
                    async: true,
                });
            }

            function copypaste() {
             var tempInput = document.createElement("textarea");
                tempInput.setAttribute('id', 'copyid');
                tempInput.style = "position: absolute; left: -1000px; top: -1000px";
                tempInput.value = 'Text Copied';
                console.log(tempInput);
                document.body.appendChild(tempInput);
                tempInput.select();
                var result = document.execCommand('copy');
                document.body.removeChild(tempInput);
                if (result) {
                    alert('copied');
                }
                else {
                 alert('not copied');
                }

                return result;
            }

        });
    </script>
 </head>
 <body>
  <input type="submit" id="test"/>
 </body>
</html>
Ziya ERKOC
  • 839
  • 7
  • 18
  • As I mentioned in my problem, this works perfectly fine if I use asynchronous call. But document.execCommand doesn't work if it is triggered from ajax (success/error) callback functions. So I have to use async:false so that I will move my copypaste() function outside ajax . – savithraj Jul 12 '17 at 18:22
  • Would you look at that post https://stackoverflow.com/questions/30712590/how-to-programmatically-copy-asynchronous-dependent-content-to-the-clipboard-fol – Ziya ERKOC Jul 12 '17 at 18:29
  • Yes, but I didn't like that approach as user has to wait till the timeout time to get the response. Another disadvantage is if the service takes more time than our timeout then the logic will go wrong. – savithraj Jul 12 '17 at 18:44
  • But user is not offened when he/she waits for couple of seconds do not worry about it. You could basically add loading screen – Ziya ERKOC Jul 12 '17 at 18:51
0

Why not simply disable the button and re-enable it instead of declaring a global variable like $("#test").attr('disabled','disabled') ? Variable scopes can get tricky in javascript.

Merih Taze
  • 41
  • 3
0

You happen to be looking for something simple like this?

PS: You have to enter the details for the ajax call yourself.

html

<button id="button">Button</button>

jQuery/js

$("#button").click(function(){
   console.log("clicked");
   // deactivate button
   $("#button").attr("disabled", true);
   ajaxCall();

});

function ajaxCall(){
    $.ajax({
    //...ajax call here,
    complete: function(){
      // reactivate button after you receive any reply from ajax
      $("#button").attr("disabled", false);
    }
    })
}
Rob Monhemius
  • 4,822
  • 2
  • 17
  • 49