1

I want to create a link (in form of a Bootstrap button) that works only on the second click; on the first click it is supposed to change its appearance a bit. For this I use .addClass(newClass), .removeClass(oldClass), and then attr("href", newUrl).

(Edit) To clarify: In the beginning, the link (anchor) has "#" as its href target, and an onlick handler. That handler, when executed on the first click, will remove itself from the anchor, and instead set the desired target URL in the hrefattribute. That is supposed to cause the link to only redirect to its target URL on the second click.)

This almost works, but only if I omit the attr() setting. When it is there, the class reverts to the old class of the link as soon as the script exits. When I step through it in the debugger, the link briefly changes its appearance as expected, but changes back when the event handler exits.

This is the HTML code:

<a id="twoclick-vjffkrzw" onclick="enabletwoclickbutton('twoclick-vjffkrzw', 
'http://localhost/something.php?cmd=admin&amp;func=userdetail&amp;pk=53&amp;action=removerole&amp;rolepk=1')"
class="btn btn-xs btn-warning" href="#">Remove this</a>

The script:

function enabletwoclickbutton(btn_id, url) {
    var whichbtn = '#' + btn_id;
    var btn = $(whichbtn);
    if (btn.hasClass("btn-warning")) {
        btn.off("click");
        btn.attr("href", url);
        btn.removeClass('btn-warning');
        btn.addClass('btn-danger');

    } else {
        console.log("Hey, this shouldnt happen.");
    }

}

I'm not very experienced in JS and jQuery, so it's quite possible that this is a stupid mistake on my side, but I just can't see it.

fbitterlich
  • 882
  • 7
  • 24

5 Answers5

2

First add return false; after the onclick function call to stop the default redirect. Then in your function you can set the onclick to null so that it isn't called a second time.

function enabletwoclickbutton(btn_id, url) {
  var whichbtn = '#' + btn_id;
  var btn = $(whichbtn);
  if (btn.hasClass("btn-warning")) {
    btn.off("click");
    btn.attr("href", url);
    btn.removeClass('btn-warning');
    btn.addClass('btn-danger');
    btn.attr('onclick', null);
  } else {
    console.log("Hey, this shouldnt happen.");
  }

}
.btn-warning {
  color: orange;
}
.btn-danger {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a id="twoclick-vjffkrzw" onclick="enabletwoclickbutton('twoclick-vjffkrzw', 
'http://localhost/something.php?cmd=admin&amp;func=userdetail&amp;pk=53&amp;action=removerole&amp;rolepk=1');return false;" class="btn btn-xs btn-warning" href="#">Remove this</a>
depperm
  • 10,606
  • 4
  • 43
  • 67
2

Use e.preventDefault() to avoid the default behavior of anchor.

Your way (however I recommend you to go with one below for readability and easy to modify later.)

html

<a id="twoclick-vjffkrzw" onclick="enabletwoclickbutton(event,'twoclick-vjffkrzw', 'http://localhost/something.php?cmd=admin&amp;func=userdetail&amp;pk=53&amp;action=removerole&amp;rolepk=1')" class="btn btn-xs btn-warning" href="#">Remove this</a>

js

 function enabletwoclickbutton(e,btn_id, url) {
    var whichbtn = '#' + btn_id;
    var btn = $(whichbtn);
    if (btn.hasClass("btn-warning")) {
        e.preventDefault();
        //btn.off("click");
        btn.attr("href", url);
        btn.removeClass('btn-warning')
           .addClass('btn-danger');

    } else {
        console.log("Hey, this shouldnt happen.");
    }

}

Recommended

Do not mix your javascript and html which is very hard to read as you can see in your code. You can write the entire code in javascript only

eg.

$('#twoclick-vjffkrzw').click(function(e){
    var btn = $(this);
    if (btn.hasClass("btn-warning")) {
        e.preventDefault();
        //btn.off("click");
        btn.attr("href", 'http://localhost/something.php?cmd=admin&amp;func=userdetail&amp;pk=53&amp;action=removerole&amp;rolepk=1');
        btn.removeClass('btn-warning');
        btn.addClass('btn-danger');

    } else {
        console.log("Hey, this shouldnt happen.");
    }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a id="twoclick-vjffkrzw" class="btn btn-xs btn-warning" href="#">Remove this</a>
bipen
  • 36,319
  • 9
  • 49
  • 62
  • But on second click, the event would still be prevented – A. Wolff Aug 29 '16 at 14:48
  • Opps the OP edited the question. In that case move the `preventDefault()` inside the if condition... :) :).. updated already anyways Thanks @A.Wolff – bipen Aug 29 '16 at 14:53
  • 1
    @ᴀʀᴛᴜʀғɪʟɪᴘɪᴀᴋ yes make sense!! updated Thanks :)... removed the `.off`. Feel free and update it . – bipen Aug 29 '16 at 15:25
1

you have to check if it is the first time you click the button. to do this you can use a variable . check the code below

var clk=0;
function enabletwoclickbutton(btn_id, url) {
if(clk==0){
 clk++;
}else{
clk=0;
var whichbtn = '#' + btn_id;
    var btn = $(whichbtn);
    if (btn.hasClass("btn-warning")) {
        btn.off("click");
        btn.attr("href", url);
        btn.removeClass('btn-warning');
        btn.addClass('btn-danger');

    } else {
        console.log("Hey, this shouldnt happen.");
    }
}

check jsfiddle

Zenel Rrushi
  • 2,346
  • 1
  • 18
  • 34
  • 1
    Not necessary; that is done by the class-checking. On the second click, the link doesn't have the `btn-warning` class any more. – fbitterlich Aug 29 '16 at 15:09
1

I'd use data attribute to store url value (added my-btn class for clarity)

<a data-action="http://localhost/something.php?cmd=admin&amp;func=userdetail&amp;pk=53&amp;action=removerole&amp;rolepk=1" class="btn btn-xs btn-warning my-btn" href="#">Remove this</a>

Then set click function with jQuery instead of using onClick attribute (as it's not good practice):

$('.my-btn').click(function(event){
    // prevent default click action:
    event.preventDefault();
    if ($(this).hasClass("btn-warning")) {
        $(this).removeClass('btn-warning').addClass('btn-danger');
    }else{
        // go to url on a second click:
        location.href = $(this).data("action");
    }
});

EDIT (@A.Wolff comment)
BTW.: Checking the existence of btn-warning class is actually pointless. The click event won't be handled at the second click anyway...

$('.my-btn').click(function(event){
    event.preventDefault();
    $(this).removeClass('btn-warning').addClass('btn-danger')
           .off('click').attr('href', $(this).data("action"));
});
Community
  • 1
  • 1
Artur Filipiak
  • 9,027
  • 4
  • 30
  • 56
  • 1
    This won't handle all specific cases of anchor click behaviour, like holding the ctrl key to open it in new tab/window. This could or not matter – A. Wolff Aug 29 '16 at 14:48
0

With input from the various answers, I was able to find out what was happening.

Apparently the changed href will be executed only after the the event handler exits. Since in my configuration by chnce it redirected to the same page, the page was actually reloaded, that's why the button/link got its original appearance back and that tricked me into believing that the attr() setting didn't work right.

The key was to simply call event.preventDefault() before setting the new URL.

Some of you recommended (directly or indirectly) to generate the button click handler in JS directly. I don't think this would make the code better readable (the only thing that made the HTML unreadable is the long URL.) As the HTML is generated dynamically, this wouldn't be a practical solution anyway.

So, the finalized code looks like this:

function enabletwoclickbutton(e, btn_id, url) {
    var whichbtn = '#' + btn_id;
    var btn = $(whichbtn);
    if (btn.hasClass("btn-warning")) {
        e.preventDefault();
        btn.off("click");
        btn.attr("href", url);
        btn.removeClass('btn-warning');
        btn.addClass('btn-danger');
    } else {
        console.log("Hey, this shouldnt happen.");
    }

}

Now it works as exected.

fbitterlich
  • 882
  • 7
  • 24