Подія перехоплення сторінки перехоплення


117

Під час редагування сторінки в моїй системі користувач може вирішити перейти на інший веб-сайт, і таким чином може втратити всі зміни, які вони не зберегли.

Я хотів би перехопити будь-яку спробу перейти на іншу сторінку та підказати користувачеві бути впевненим, що вони хочуть, щоб це сталося, оскільки вони могли потенційно втратити свою поточну роботу.

Gmail робить це дуже подібним чином. Наприклад, складіть нову електронну пошту, почніть вводити текст тіла та введіть нове місце в адресному рядку (скажімо, twitter.com чи щось). Тут буде запропоновано запитати "Ви впевнені?"

Ідеї, як це повторити? Я націлений на IE8, але хотів би бути сумісним і з FF & Chrome.


Відповіді:


154

Схожий на відповідь Ghommey, але це також підтримує старі версії IE та Firefox.

window.onbeforeunload = function (e) {
  var message = "Your confirmation message goes here.",
  e = e || window.event;
  // For IE and Firefox
  if (e) {
    e.returnValue = message;
  }

  // For Safari
  return message;
};

1
Чи можете ви пояснити перший рядок (var message = ...)? Я не знаю, що робить ця кома та другий вираз.
mtmurdock

7
@mtmurdock Це просто синтаксис Javascript для оголошення кількох змінних. var foo, bar;те саме, щоvar foo; var bar;
T Nguyen

4
@mtmurdock, Другий вислів " var e = e || window.event;" означає встановити e, що дорівнює параметру e (якщо це truthy) або window.event, якщо не truthy. Це не буде правдою, якщо параметр e недійсний.
T Nguyen

3
@Blieque addEventListener не підтримується в IE8. Не редагуйте відповіді людей, навіть не читаючи запитання.
Елі Сірий

2
Більше не працює в Chrome (застаріло): developers.google.com/web/updates/2016/04/…
Micha Schwab

25

Дивіться цю статтю. Шукаєте, що ви шукаєте - це передзавантаження

зразок коду:

  <script language="JavaScript">
  window.onbeforeunload = confirmExit;
  function confirmExit()
  {
    return "You have attempted to leave this page.  If you have made any changes to the fields without clicking the Save button, your changes will be lost.  Are you sure you want to exit this page?";
  }
</script>

2
Чи є спосіб визначити, що користувач обрав опцію "Залишити цю сторінку", а не "Залишати на цій сторінці"?
Шилпа Соні

@ShilpaSoni незабаром ви отримаєте наступну подію розвантаження, developer.mozilla.org/en-US/docs/Web/API/Window/unload_event, але я не думаю, що існує синхронний спосіб.
науковець

6

Замість дратівливого спливаючого вікна підтвердження було б непогано затримати, залишивши лише трохи (питання мілісекунд) для успішного управління розміщенням збережених даних на сервері, що мені вдалося для мого сайту, використовуючи написання фіктивного тексту на консоль так:

window.onbeforeunload=function(e){
  // only take action (iterate) if my SCHEDULED_REQUEST object contains data        
  for (var key in SCHEDULED_REQUEST){   
    postRequest(SCHEDULED_REQUEST); // post and empty SCHEDULED_REQUEST object
    for (var i=0;i<1000;i++){
      // do something unnoticable but time consuming like writing a lot to console
      console.log('buying some time to finish saving data'); 
    };
    break;
  };
}; // no return string --> user will leave as normal but data is send to server

Редагувати: Дивіться також Synchronous_AJAX і як це зробити з jquery


Мені подобається ця альтернатива спливаючому меню. Дякую за пропозицію, Ремі.
Кріс Баланс

2
це не має абсолютно ніякого сенсу -1. javascript не має нитки, що ви робите, це робити postRequest, а потім призупиняти обчислення сайту, не дозволяючи нікому нічого робити (включаючи ваш postRequest, який тим часом був уже надісланий перед паузою обчислення).
fmsf

І саме тому він працює: справді пост-запит був надісланий перед паузою для обчислень, але це невелике блокування сторінки перед її фактичним залишенням забезпечує достатньо часу, щоб клієнт браузера (не JavaScript) дійсно закінчив надсилати цей запит належним чином . Я помітив, що коли я лише надсилаю запит (без блокування) і залишаю сторінку відразу після, запит не завжди надсилається.
Ремі

6
Я б не використовував це у виробництві. console.log не є перехресним браузером; кожен postRequest страждає від затримки попередніх (що також означає, що сторінка буде висіти там протягом тривалості вашого циклу * заплановані запити); запити не запускаються паралельно; Ви не гарантовано дійсно надсилаєте свої запити. Якби я був змушений зіткнутися з цією проблемою, я б пішов із синхронним запитом ajax, якщо є лише один запит. За допомогою декількох запитів я використовував би запити async ajax та цикл, який перевіряє результати (успіх чи помилку) від зворотних зворотів запитів.
framp

Я не знав, що console.log не є крос-браузером, а синхронний запит Ajax дійсно повинен бути кращим рішенням (для одного запиту). Згаданий SCHEDULED_REQUESTоб’єкт, який накопичує будь-яку невідкладну інформацію, яку слід надсилати на сервер, як буфер даних, ефективно приєднуючи кілька запитів до одного (звичайно, URL цих запитів однаковий). Використання запиту на синхронний Ajax перед завантаженням повинно вирішити проблему крос-браузера, як ви вже говорили. Дякуємо за ваш цінний коментар!
Ремі

0

У мене є користувачі, які не заповнили всі необхідні дані.

<cfset unloadCheck=0>//a ColdFusion precheck in my page generation to see if unload check is needed
var erMsg="";
$(document).ready(function(){
<cfif q.myData eq "">
    <cfset unloadCheck=1>
    $("#myInput").change(function(){
        verify(); //function elsewhere that checks all fields and populates erMsg with error messages for any fail(s)
        if(erMsg=="") window.onbeforeunload = null; //all OK so let them pass
        else window.onbeforeunload = confirmExit(); //borrowed from Jantimon above;
    });
});
<cfif unloadCheck><!--- if any are outstanding, set the error message and the unload alert --->
    verify();
    window.onbeforeunload = confirmExit;
    function confirmExit() {return "Data is incomplete for this Case:"+erMsg;}
</cfif>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.