tags:

views:

1175

answers:

8

A pattern that's started to show up a lot in one of the web apps I'm working are links that used to just be a regular a-tag link now need a popup box asking "are you sure?" before the link will go. (If the user hits cancel, nothing happens.)

We've got a solution that works, but somehow we're a web app shop without a Javascript expert, so I'm left with this crawling feeling like there's a better way to get the job done.

So, JS experts, what's the most standards-compliant, cross-browser way to get this done?

(For the record, this is already a site that requires JS, so no need to have a "non-JS" version. But, it does need to work in any and all reasonably modern browsers.)

(Also, for bonus points it would be nice if people with JS turned off didn't have the links work, rather than bypassing the confirm box.)

+3  A: 

Here's how we've been doing it:

<a href="#" onClick="goThere(); return false;">Go to new page</a>`

function goThere() 
{ 
   if( confirm("Are you sure?") ) 
    { 
       window.location.href="newPage.aspx"; 
    } 
}

(EDIT: Code reformatted to avoid horizontal scroll)

Electrons_Ahoy
Nothing wrong with this. Don't get caught up in the complexity of JavaScript's complete feature set if you don't have to.
dacracot
+2  A: 
<a href="http://..." onclick="return confirm('are you sure?')">text</a>
Diodeus
If JS is turned off, that should go directly to the link, without the confirm. The desire was for the link to be disabled if JS was disabled.
James Curran
The use of an onclick attribute is discouraged.
keparo
By whom? For what reason?
AnthonyWJones
A: 

A class-binding version (no need for inline onclick attributes): link this external < script> after all confirmable controls:

// dangerous - warnings on potentially harmful actions
// usage: add class="dangerous" to <a>, <input> or <button>
// Optionally add custom confirmation message to title attribute

function dangerous_bind() {
    var lists= [
        document.getElementsByTagName('input'),
        document.getElementsByTagName('button'),
        document.getElementsByTagName('a')
    ];
    for (var listi= lists.length; listi-->0;) { var els= lists[listi];
        for (var eli= els.length; eli-->0;) { var el= els[eli];
            if (array_contains(el.className.split(' '), 'dangerous'))
                el.onclick= dangerous_click;
        }
    }
}

function array_contains(a, x) {
    for (var i= a.length; i-->0;)
        if (a[i]==x) return true;
    return false;
}

function dangerous_click() {
    return confirm(this.title || 'Are you sure?');
}

dangerous_bind();

This is a slightly long-winded due to the binding working on submits/buttons as well. Generally though it makes sense to have ‘dangerous’ options you will want to confirm on buttons rather than links. GET requests as fired by links shouldn't really have any active effect.

bobince
+1  A: 

In jquery it is something like:

$("a").click(function() {if(confirm('yadda yadda')) event.stopPropagation();});

If I understand what jgreep mentioned, if you only want the confirm to appear on a few links, you would bind the click handler only to links with the right class. You could do this only for anchors or for any html element that has the class.

$(".conf").click(function() {if(confirm('yadda yadda')) event.stopPropagation();});
Josh
If you don't want to affect the entire document, you could show the selection of a class.
jgreep
A: 
var links = document.getElementsByTagName('A');

for (var i = 0; i < links.length; i++)
{ 
    links[i].onclick = function ()
    {       
       return Confirm("Are you sure?");
    }
}

This applies the message to all links, however its a little harder to make the links not work without javascript automatically (actually its impossible).

FlySwat
+3  A: 

Unobtrusive Javascript

The best practice is to add event handler methods to the links.

The confirm() function produces the dialog box you described, and returns true or false depending on the user's choice.

Event handler methods on links have a special behavior, which is that they kill the link action if they return false.

var link = document.getElementById('confirmToFollow');

link.onclick = function () {
    return confirm("Are you sure?");
};

If you want the link to require javascript, the HTML must be edited. Remove the href:

<a href="#" id="confirmToFollow"...

You can explicitly set the link destination in the event handler:

var link = document.getElementById('confirmToFollow');

link.onclick = function () {
    if( confirm("Are you sure?") ) {
        window.location = "http://www.stackoverflow.com/";
    }
    return false;
};

If you want the same method called on multiple links, you can acquire a nodeList of the links you want, and apply the method to each as you loop through the nodeList:

var allLinks = document.getElementsByTagName('a');
for (var i=0; i < allLinks.length; i++) {
    allLinks[i].onclick = function () {
        return confirm("Are you sure?");
    };
}

There are further permutations of the same idea here, such as using a classname to determine which links will listen for the method, and to pass a unique location into each based on some other criteria. They are six of one, half dozen of another.

Alternative Approaches (not encouraged practices):

One discouraged practice is to attach a method via an onclick attribute:

<a href="mypage.html" onclick="...

Another discouraged practice is to set the href attribute to a function call:

<a href="javascript: confirmLink() ...

Note that these discouraged practices are all working solutions.

keparo
Please explain why <a href="mypage.html" onclick="... is discouraged. Such statements need reasons attached.
AnthonyWJones
+2  A: 

If you are using jQuery you would do:

jQuery(document).ready(
    jQuery("a").click(){
        //you'd place here your extra logic
        document.location.href = this.href;
    }
);
voyager
A: 

Take a look at What’s the best way to open new browser window. You can do something similar, but throw up the confirmation prior to opening a new window.

Kon