best way of making a link clickable only once until it finishes executing function

I have a paging system on my app that allows the user to click a link, an ajax call is made to get data, and that data is displayed. I'd like to make it so that the user can only click the link once, then somehow "disable" the link, execute my ajax call, then re-enable the link. I thought I could use bind() / unbind(), but am having trouble getting it to work. This is what I have:

    $('#btnNext').click(function (e) {
        if (currentPage == totalPages)
            e.preventDefault()
        else {
            $('#btnNext').unbind();
            move('next');
            $('#btnNext').bind("click", handler('next'));
        }
    });

    var handler = function ( direction ) {
        $('#dvResults').hide();
        move( direction );
        $('#dvResults').fadeIn(600);
    }

function move( direction ) {
....
}

Open in new window


for whatever reason, it pages twice (if i'm on page 1, it goes to 2, then 3), then i lose all functionality from the link.

Is this the best way to do this, or is there another way to do it?
LVL 34
Big MontySenior Web Developer / CEO of ExchangeTree.org Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ryan ChongCommented:
what kind of "links" do you have here? is it hyperlinks or buttons, or other elements?

see if this worked for you?

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>testing</title>
  <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script>
    var currentPage = 1;
    var totalPages = 3;

    $(document).ready(function () {
        $('#btnNext').click(function (e) {
            $('#btnPrev').prop("disabled", true);
            $('#btnNext').prop("disabled", true);
            if (currentPage == totalPages)
                e.preventDefault();
            else {
                move('next');
            }
        });

        $('#btnPrev').click(function (e) {
            $('#btnPrev').prop("disabled", true);
            $('#btnNext').prop("disabled", true);
            if (currentPage == 1)
                e.preventDefault();
            else {
                move('prev');
            }
        });

        function move(direction) {
            if (direction == "prev") {
                currentPage--;
                
                $('#dvResults').hide();
                $('#dvWait').fadeIn(100);

                setTimeout(function () {
                    $('#dvWait').hide();
                    $('#dvResults').fadeIn(600);
                    writePage();
                }, 2000);
                
            } else if (direction == "next") {
                currentPage++;
                
                $('#dvResults').hide();
                $('#dvWait').fadeIn(100);
                
                setTimeout(function () {
                    $('#dvWait').hide();
                    $('#dvResults').fadeIn(600);
                    writePage();
                }, 2000);
                
            }
            
        }

        $('#dvResults').hide();
        $('#dvWait').hide();
        writePage();
    });
    
    function writePage() {
        //Disable previous button if it's first page
        $('#btnPrev').prop("disabled", (currentPage == 1));
        //Disable next button if it's last page
        $('#btnNext').prop("disabled", (currentPage == totalPages));
        $('#dvInfo').text("Current Page: " + currentPage);
    }

</script>
</head>
<body>
<form method="post" action="processing.asp">
<div id="dvInfo">Current Page</div>
<button type="button" id="btnPrev">Previous</button>
<button type="button" id="btnNext">Next</button>

<div id="dvWait" style="margin:0 auto;">Please wait.. <img id="loader" style="height:30px; width:30px" src="http://www.mytreedb.com/uploads/mytreedb/loader/ajax_loader_gray_512.gif"></div>
<br />
<div id="dvResults">This is the result</div>

</form>
</body>
</html>

Open in new window


try to customize this sample by replacing the setTimeout function with AJAX callback function.
0
Leonidas DosasCommented:
When you clicked at an anchor the script below set at href the "#" value (or altrenative you can set "javascript:void(0)" value) and when the ajax calls done then you reset the href that it had it before:
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Bootstrap Example</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>   

</head>
<body>
<a href="https://www.experts-exchange.com/" id="myLink">Mylink</a>
        
<script>
var flag=false;
$('#myLink').on('click',function(ev){
  if(flag===false){
  var link=$(this).attr('href');
  $(this).attr('href','#');
  //make the ajax call here...
  //and at .done..
    ev.preventDefault();
    ev.stopPropagation();
   $(this).attr('href',link);
   flag=true;
   }
});
</script>
  

</body>
</html>

Open in new window

0
Julian HansenCommented:
I would not use a global variable for this but rather a property on the link itself

Consider the sample below. This uses a property on the DOM element to indicate whether it is active or not. Note we could also use the disabled class as a check - I have provided both methods as an example
CSS
.link.disabled {
  color: rgba(0,0,0,.5);
  border: 1px solid #999;
}

Open in new window

HTML
<b>Page: </b>
<a href="#" class="link">1</a>
<a href="#" class="link">2</a>
<a href="#" class="link">3</a>
<a href="#" class="link">4</a>
<a href="#" class="link">5</a>
<ul id="result" class="list-group"></ul>

Open in new window


jQuery
<script>
$(function() {
  $('.link').click(function(e) {
    var el = $(this);
    e.preventDefault();
    // You can also check for el.hasClass('disabled')
    if (!(el[0].disabled || false)) {
      el.addClass('disabled');
      el[0].disabled = true;
      $.ajax({
        url:'slow.php'
      }).done(function(resp) {
        el.removeClass('disabled');
        el[0].disabled = false;
      });
    }
    else {
      $('#result').append($('<li>', {class: 'list-group-item'}).html('Link: ' + el.text() + ' is still disabled'));
    }
  })
});
</script>

Open in new window


Working sample here
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Big MontySenior Web Developer / CEO of ExchangeTree.org Author Commented:
thank you, with a few modifications I was able to get this to work.
0
Julian HansenCommented:
You are welcome.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
JavaScript

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.