views:

631

answers:

3

I have

<span class="cssButton"><a href="javascript:void(0);" class="buttonBlue" onclick="swfu.startUpload();"> <img src="http://uber-upload.com/img/icons/up_16.png" alt=""/> Uber-Upload! </a></span>

And i want to make it so that if you press that button, it also sets a variable that makes it so that if you try to leave the page, it will pop up one of those "Are you sure you want to leave this page" alerts to prevent people from accidently leaving while there is an upload going on.

Dont worry about unsetting the variable after the upload finishes, i'll add that, i just need one of you smart coders to make me a framework.

Thanks!

A: 

Relying on onbeforeunload is sketchy at best. Because spammers have abused the behavior in the same way you're suggesting the ability for people to do this has been basically removed.

You can now only respond to onbeforeunload if the close event was fired from activating a button or such.

Orion Adrian
so theres no way to make the button set $uploading=truethen put something like window.onbeforeunload = confirmExit; function confirmExit() {if ($uploading=true){ return "If you leave while uploading, your files will be lost. Are you sure you want to exit this page?"; }}Just something like that
jiexi
Seems to work well enough for GMail, SO, ...
T.J. Crowder
Your last statement is untrue; AFAIK (and I've tested this across IE6,7, and FF 2 and 3) onbeforeunload is fired any time you leave the page by any means.
George Stocker
@Gortok, Admittedly I haven't tested this recently, but my understanding is that the zone has a lot to do with what is and isn't allowed. If you code something on computer, you're going to be in the Intranet zone and there are laxer permissions in that zone.
Orion Adrian
+1  A: 
function warnUser()
{
   if(dataIsDirty)
   {
      return "You have made changes. They will be lost if you continue.";
   }
   else
   {
      // Reset the flag to its default value.
      dataIsDirty = false;
   }
}

function isDirty()
{
   dataIsDirty = true;
}

function isClean()
{
    dataIsDirty = false;
}

Then you use it just like on the onbeforeunload event.

window.onbeforeunload = warnUser;
dataIsDirty = false; //Or true, depending on if you want it to show up even if they dont' make changes)

Then to use it, just use the 'isClean' function to anything you don't want to trigger it(Save, for instance), or you can attach 'isDirty' to any event you want to trigger it before they leave (say, editing a form field).

George Stocker
Um, why are you setting dataIsDirty false when it's already false?
T.J. Crowder
for the most part this will work. Thanks
jiexi
On the initial loading of the page, you don't want that flag to be set if they leave the page. You only want it to be set if they change something. So by default, it should be false. When they change something, it's set to true, and when they click 'save', it's reset to false. That's why.
George Stocker
Your logic, translated into pseudocode, is **if (flag is true) { do something } else { set flag false; }**. That logic is flawed, you're setting the flag false when the flag is already false.
T.J. Crowder
I should clarify: That's just a detail, on the whole the answer is fine, although it only allows for a single upload.
T.J. Crowder
+1  A: 

Add this declaration to the page:

var upcount = 0;

Change your onclick to:

onclick="++upcount; swfu.startUpload();"

If the swfu gives you some kind of event when it's done uploading, put this on it:

--upcount;

And add this handler:

window.onbeforeunload = function() {
    if (upcount > 0) {
        return "The upload is still in progress, leaving the page will cancel it.";
    }
}

Where browsers respect the onbeforeunload, that'll work. And most of them do, most of the time. Where they don't, well, you tried. Note that by using a counter, you're allowing for multiple uploads.

You might consider attachEvent (IE) or addEventListener (standard) (or a library like Prototype or jQuery that evens out the differences for you) for attaching your events rather than using attributes. Using attributes (aka DOM0 handlers) is fairly old-fashioned and a bit limiting (only one handler per event per element). But it does still work.

T.J. Crowder
thanks, cleaner than other guys code.
jiexi
Cheers. I don't know about *cleaner*, the other was clean enough, but this does handle the one additional case (multiples).
T.J. Crowder