set onbeforeunload only when dirty
https://developers.google.com/web/updates/2018/07/page-lifecycle-api#legacy-lifecycle-apis-to-avoid
This commit is contained in:
parent
fa4dfd680b
commit
5da1e0fb9b
36
edit/edit.js
36
edit/edit.js
|
@ -25,7 +25,8 @@ const CssToProperty = {'url': 'urls', 'url-prefix': 'urlPrefixes', 'domain': 'do
|
||||||
|
|
||||||
let editor;
|
let editor;
|
||||||
|
|
||||||
window.onbeforeunload = beforeUnload;
|
|
||||||
|
document.addEventListener('visibilitychange', beforeUnload);
|
||||||
chrome.runtime.onMessage.addListener(onRuntimeMessage);
|
chrome.runtime.onMessage.addListener(onRuntimeMessage);
|
||||||
|
|
||||||
preinit();
|
preinit();
|
||||||
|
@ -176,7 +177,8 @@ function onRuntimeMessage(request) {
|
||||||
break;
|
break;
|
||||||
case 'styleDeleted':
|
case 'styleDeleted':
|
||||||
if (styleId === request.id || editor && editor.getStyle().id === request.id) {
|
if (styleId === request.id || editor && editor.getStyle().id === request.id) {
|
||||||
window.onbeforeunload = () => {};
|
document.removeEventListener('visibilitychange', beforeUnload);
|
||||||
|
window.onbeforeunload = null;
|
||||||
closeCurrentTab();
|
closeCurrentTab();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -192,24 +194,27 @@ function onRuntimeMessage(request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked for 'visibilitychange' event by default.
|
||||||
|
* Invoked for 'beforeunload' event when the style is modified and unsaved.
|
||||||
|
* See https://developers.google.com/web/updates/2018/07/page-lifecycle-api#legacy-lifecycle-apis-to-avoid
|
||||||
|
* > Never add a beforeunload listener unconditionally or use it as an end-of-session signal.
|
||||||
|
* > Only add it when a user has unsaved work, and remove it as soon as that work has been saved.
|
||||||
|
*/
|
||||||
function beforeUnload() {
|
function beforeUnload() {
|
||||||
if (saveSizeOnClose) {
|
if (saveSizeOnClose) rememberWindowSize();
|
||||||
rememberWindowSize();
|
const activeElement = document.activeElement;
|
||||||
}
|
if (activeElement) {
|
||||||
document.activeElement.blur();
|
// blurring triggers 'change' or 'input' event if needed
|
||||||
if (isClean()) {
|
activeElement.blur();
|
||||||
return;
|
// refocus if unloading was canceled
|
||||||
|
setTimeout(() => activeElement.focus());
|
||||||
}
|
}
|
||||||
|
const isDirty = editor ? editor.isDirty() : !isCleanGlobal();
|
||||||
|
if (isDirty) {
|
||||||
updateLintReportIfEnabled(null, 0);
|
updateLintReportIfEnabled(null, 0);
|
||||||
// neither confirm() nor custom messages work in modern browsers but just in case
|
// neither confirm() nor custom messages work in modern browsers but just in case
|
||||||
return t('styleChangesNotSaved');
|
return t('styleChangesNotSaved');
|
||||||
|
|
||||||
function isClean() {
|
|
||||||
if (editor) {
|
|
||||||
return !editor.isDirty();
|
|
||||||
} else {
|
|
||||||
return isCleanGlobal();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,6 +411,7 @@ function updateTitle() {
|
||||||
const clean = isCleanGlobal();
|
const clean = isCleanGlobal();
|
||||||
const title = styleId === null ? t('addStyleTitle') : t('editStyleTitle', [name]);
|
const title = styleId === null ? t('addStyleTitle') : t('editStyleTitle', [name]);
|
||||||
document.title = clean ? title : DIRTY_TITLE.replace('$', title);
|
document.title = clean ? title : DIRTY_TITLE.replace('$', title);
|
||||||
|
window.onbeforeunload = clean ? null : beforeUnload;
|
||||||
$('#save-button').disabled = clean;
|
$('#save-button').disabled = clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ global CodeMirror dirtyReporter
|
||||||
global updateLintReportIfEnabled initLint linterConfig updateLinter
|
global updateLintReportIfEnabled initLint linterConfig updateLinter
|
||||||
global createAppliesToLineWidget messageBox
|
global createAppliesToLineWidget messageBox
|
||||||
global sectionsToMozFormat
|
global sectionsToMozFormat
|
||||||
|
global beforeUnload
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
@ -18,8 +19,10 @@ function createSourceEditor(style) {
|
||||||
|
|
||||||
const dirty = dirtyReporter();
|
const dirty = dirtyReporter();
|
||||||
dirty.onChange(() => {
|
dirty.onChange(() => {
|
||||||
document.body.classList.toggle('dirty', dirty.isDirty());
|
const isDirty = dirty.isDirty();
|
||||||
$('#save-button').disabled = !dirty.isDirty();
|
window.onbeforeunload = isDirty ? beforeUnload : null;
|
||||||
|
document.body.classList.toggle('dirty', isDirty);
|
||||||
|
$('#save-button').disabled = !isDirty;
|
||||||
updateTitle();
|
updateTitle();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -73,8 +73,7 @@ function initGlobalEvents() {
|
||||||
installed.addEventListener('mouseover', handleEvent.lazyAddEntryTitle);
|
installed.addEventListener('mouseover', handleEvent.lazyAddEntryTitle);
|
||||||
installed.addEventListener('mouseout', handleEvent.lazyAddEntryTitle);
|
installed.addEventListener('mouseout', handleEvent.lazyAddEntryTitle);
|
||||||
|
|
||||||
// remember scroll position on normal history navigation
|
document.addEventListener('visibilitychange', rememberScrollPosition);
|
||||||
window.onbeforeunload = rememberScrollPosition;
|
|
||||||
|
|
||||||
$$('[data-toggle-on-click]').forEach(el => {
|
$$('[data-toggle-on-click]').forEach(el => {
|
||||||
// dataset on SVG doesn't work in Chrome 49-??, works in 57+
|
// dataset on SVG doesn't work in Chrome 49-??, works in 57+
|
||||||
|
|
Loading…
Reference in New Issue
Block a user