2011-01-10 6 views
26

Wyświetlane jest okno dialogowe, gdy ktoś próbuje odejść od określonej strony bez zapisywania ich pracy. Używam zdarzenia onbeforeunload języka Javascript, działa świetnie.Sposób sprawdzania, czy użytkownik kliknął przycisk Anuluj w oknie dialogowym Javascript onbeforeunload?

Teraz chcę uruchomić trochę kodu JavaScript, gdy użytkownik kliknie "Anuluj" w oknie dialogowym, które się pojawi (mówiąc, że nie chce odejść od strony).

Czy to możliwe? Używam również jQuery, więc czy jest możliwe zdarzenie takie jak beforeunloadcancel, do którego mogę się podłączyć?

UPDATE: Chodzi o to, aby rzeczywiście uratować i kierują użytkowników do innej strony, jeśli wybrali anulować

+0

Nie sądzę, że to możliwe ... ale mam nadzieję, że się mylę. – keithjgrant

+0

Jestem bardzo ciekawa, w jaki sposób blokujesz nawigację za pomocą niestandardowego okna dialogowego. Czy możesz podać kod? – jAndy

+0

@jAndy, szukaj zdarzenia onbeforeunload w JavaScript, robi to dokładnie. –

Odpowiedz

44

Można to zrobić tak:

$(function() { 
    $(window).bind('beforeunload', function() { 
     setTimeout(function() { 
      setTimeout(function() { 
       $(document.body).css('background-color', 'red'); 
      }, 1000); 
     },1); 
     return 'are you sure'; 
    }); 
}); 

Kod ciągu pierwszego setTimeout metody ma opóźnienie 1ms. Jest to po prostu dodanie funkcji do UI queue. Ponieważ setTimeout działa asynchronicznie, interpreter JavaScript będzie kontynuowany przez bezpośrednie wywołanie instrukcji return, co z kolei spowoduje uruchomienie przeglądarki modal dialog. Spowoduje to zablokowanie UI queue, a kod z pierwszego setTimeout nie zostanie wykonany, dopóki modal nie zostanie zamknięty. Jeśli użytkownik naciśnie przycisk anuluj, wywoła inny setTimeout, który zostanie uruchomiony w ciągu około jednej sekundy. Jeśli użytkownik potwierdził ok, użytkownik przekieruje, a drugi setTimeout nigdy nie zostanie uruchomiony.

przykład: http://www.jsfiddle.net/NdyGJ/2/

+0

Poszedłem do łącza, ale nic się nie stało, gdy zamknąłem okno. Korzystanie z Chrome ... –

+0

Bardzo ładne, więc działa, ale nie do końca dla moich potrzeb. Nie rozumiem potrzeby zagnieżdżonego setTimeout, usunięcie zewnętrznego setTimeout wydaje się mieć ten sam efekt. Problem polega jednak na tym, że opóźniona funkcja może zostać wywołana podczas próby "kontynuowania" i wyjścia na żądaną stronę. Opóźnij go zbyt długo, a kliknięcie anuluj nie wydaje się działać, a opóźnienie jest zbyt krótkie i ryzykujesz przekierowanie na niewłaściwą stronę. –

+0

W chrome można ustawić opóźnienie 0ms i to działa. W IE musisz mieć dłuższą przerwę lub przestraszysz. –

1

niemożliwe. Może ktoś udowodni, że jestem zły ... Jaki kod chcesz uruchomić? Czy chcesz automatycznie zapisać po kliknięciu Anuluj? Brzmi to wbrew intuicji. Jeśli nie dokonałeś już autozapisu, myślę, że nie ma sensu autozapisywanie po naciśnięciu "Anuluj". Być może możesz podświetlić przycisk zapisywania w module obsługi onbeforeunload, aby użytkownik zobaczył, co powinien zrobić przed nawigacją.

+0

Chodzi o to, aby w rzeczywistości zapisać i przekierować je na inną stronę internetową, jeśli wybrano opcję Anuluj. –

2

Nie sądziłem, że to możliwe, ale tylko próbował ten pomysł i działa (choć niektórzy co hack i nie może działać tak samo we wszystkich przeglądarkach):

window.onbeforeunload = function() { 
    $('body').mousemove(checkunload); 
    return "Sure thing"; 
}; 

function checkunload() { 
    $('body').unbind("mousemove"); 
    //ADD CODE TO RUN IF CANCEL WAS CLICKED 
} 
+1

jeśli przesuniesz mysz po kliknięciu przycisku OK, aby opuścić witrynę, mimo wszystko zostanie uruchomiony kod anulowania ... –

+0

Domyślam się, że można dodać limit czasu przed powiązaniem zdarzenia mousemove, co może go naprawić, ale to sprawia, że ​​jest jeszcze więcej hack. –

+1

Zniknięcie istniejącego okna trwa dłużej niż 1 sekundę, a jeśli poruszysz myszką, będzie to wyglądało jak anulowanie. Posiadanie timera ma tę samą wadę, co odpowiedź jAndy'ego, która nie działa dobrze dla mnie. –

4

wiem, że to pytanie jest już stary, ale w przypadku gdy ktoś jest nadal występują problemy z tym, znalazłem rozwiązanie, które wydaje się działać dla mnie,

Zasadniczo zdarzenie unload jest zwolniony po beforeunload e kratka wentylacyjna. Możemy to wykorzystać, aby anulować timeout utworzony w przypadku beforeunload, modyfikując JANDY za odpowiedź:

$(function() { 
    var beforeUnloadTimeout = 0 ; 
    $(window).bind('beforeunload', function() { 
     console.log('beforeunload'); 
     beforeUnloadTimeout = setTimeout(function() { 
      console.log('settimeout function'); 
      $(document.body).css('background-color', 'red'); 
     },500); 
     return 'are you sure'; 
    }); 
    $(window).bind('unload', function() { 
     console.log('unload'); 
     if(typeof beforeUnloadTimeout !=='undefined' && beforeUnloadTimeout != 0) 
      clearTimeout(beforeUnloadTimeout); 
    }); 
}); 

EDIT:jsfiddle here

+0

Czy to była twoja praca? Ponieważ w moim przypadku otrzymuję 'unload' jak po wykonaniu funkcji timera ... (testowałem w Firefox 35) –

+0

Tak, to działa dla mnie, spróbuj zwiększyć czas dla funkcji timeout. –

+0

Przetestowałem trochę więcej i odkryłem, że jeśli postawię około 5 sekund (zamiast 0,5), to działa zgodnie z oczekiwaniami. Ale myślę, że to za dużo na wypadek, gdybyś anulował okno dialogowe ... Szkoda, że ​​nie otrzymujemy lepszej informacji zwrotnej na ten temat. –

-5
window.onbeforeunload = function() { 
    if (confirm('Do you want to navigate away from this page?')) { 
     alert('Saving work...(OK clicked)') 
    } else { 
     alert('Saving work...(canceled clicked)') 
     return false 
    } 
} 

z tego kodu również, jeśli użytkownik kliknie przycisk 'Anuluj' w IE8 pojawi się domyślne okno dialogowe nawigacji.

+3

Nie możesz użyć 'confirm()' w funkcji dołączonej do 'onbeforeunload'. –

+0

@jyoti: Wygląda na to, że chciałeś wypowiedzieć się na temat [czyjejś odpowiedzi] (http://stackoverflow.com/a/4670938/177710v). Aby to zrobić, kliknij link "dodaj komentarz" poniżej konkretnej odpowiedzi. Usuń tę odpowiedź z wątku, ponieważ jest to duplikat błędnej odpowiedzi, która niedługo zostanie cofnięta. – Oliver