tophf 2018-08-02 20:54:40 +03:00
parent fa4dfd680b
commit 5da1e0fb9b
3 changed files with 30 additions and 22 deletions

View File

@ -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) {
// blurring triggers 'change' or 'input' event if needed
activeElement.blur();
// refocus if unloading was canceled
setTimeout(() => activeElement.focus());
} }
document.activeElement.blur(); const isDirty = editor ? editor.isDirty() : !isCleanGlobal();
if (isClean()) { if (isDirty) {
return; updateLintReportIfEnabled(null, 0);
} // neither confirm() nor custom messages work in modern browsers but just in case
updateLintReportIfEnabled(null, 0); return t('styleChangesNotSaved');
// neither confirm() nor custom messages work in modern browsers but just in case
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;
} }

View File

@ -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();
}); });

View File

@ -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+