From 1a34401b745c2cacbc10511eb8a90f251ea7411f Mon Sep 17 00:00:00 2001 From: Timon Foerster Date: Wed, 18 May 2022 02:11:27 +0200 Subject: [PATCH 1/3] #144 confirm if unsaved form changes --- lib/Coocook/Controller/Dish.pm | 2 ++ lib/Coocook/Controller/Recipe.pm | 1 + root/static/js/unsavedChanges.js | 21 ++++++++++++++++ root/templates/dish/edit.tt | 42 ++++++++++++++++---------------- root/templates/recipe/edit.tt | 2 +- 5 files changed, 46 insertions(+), 22 deletions(-) create mode 100644 root/static/js/unsavedChanges.js diff --git a/lib/Coocook/Controller/Dish.pm b/lib/Coocook/Controller/Dish.pm index ff83711d..6e3fdbed 100644 --- a/lib/Coocook/Controller/Dish.pm +++ b/lib/Coocook/Controller/Dish.pm @@ -81,6 +81,8 @@ sub edit : GET HEAD Chained('base') PathPart('') Args(0) RequiresCapability('vie for my $ingredient ( @{ $c->stash->{ingredients} } ) { $ingredient->{reposition_url} = $c->project_uri( '/dish/reposition', $ingredient->{id} ); } + + push @{ $c->stash->{js} }, '/js/unsavedChanges.js'; } sub delete : POST Chained('base') PathPart('delete') Args(0) RequiresCapability('edit_project') { diff --git a/lib/Coocook/Controller/Recipe.pm b/lib/Coocook/Controller/Recipe.pm index 77d223bf..98d3b564 100644 --- a/lib/Coocook/Controller/Recipe.pm +++ b/lib/Coocook/Controller/Recipe.pm @@ -107,6 +107,7 @@ sub edit : GET HEAD Chained('base') PathPart('') Args(0) RequiresCapability('vie and $c->stash( import_url => $c->uri_for_action( '/browse/recipe/import', [ $recipe->id, $recipe->url_name ] ) ); + push @{ $c->stash->{js} }, '/js/unsavedChanges.js'; } sub new_recipe : GET HEAD Chained('submenu') PathPart('recipes/new') diff --git a/root/static/js/unsavedChanges.js b/root/static/js/unsavedChanges.js new file mode 100644 index 00000000..15c0e31c --- /dev/null +++ b/root/static/js/unsavedChanges.js @@ -0,0 +1,21 @@ +const forms = document.getElementsByClassName('confirmIfUnsavedChanges'); +let hasUnsavedChanges = false; + +for(const form of forms) { + const inputs = Array.prototype.slice.apply(form.getElementsByTagName('input')); + const textareas = Array.prototype.slice.apply(form.getElementsByTagName('textarea')); + const selects = Array.prototype.slice.apply(form.getElementsByTagName('select')); + const elements = inputs.concat(textareas).concat(selects); + console.log(elements) + for(const elem of elements) { + elem.addEventListener('input', () => {if(!hasUnsavedChanges) hasUnsavedChanges = true}); + } + form.addEventListener('submit', () => {if(hasUnsavedChanges) hasUnsavedChanges = false}); +} + +window.addEventListener('beforeunload', (e) => { + if (hasUnsavedChanges) { + (e || window.event).returnValue = ''; + return ''; + } +}) \ No newline at end of file diff --git a/root/templates/dish/edit.tt b/root/templates/dish/edit.tt index ea8ed3de..e12132b4 100644 --- a/root/templates/dish/edit.tt +++ b/root/templates/dish/edit.tt @@ -10,33 +10,33 @@ -
-

Name:

-

Comment:

-

Servings: Changing here doesn’t recalculate values!

-

Tags:

-

- -

+ +

Name:

+

Comment:

+

Servings: Changing here doesn’t recalculate values!

+

Tags:

+

+ +

-

Preparation

- +

Preparation

+ -

Description

- +

Description

+ -

+

-

Ingredients

+

Ingredients

-[% INCLUDE 'includes/forms/ingredients_editor.tt' %] + [% INCLUDE 'includes/forms/ingredients_editor.tt' %] - +
[% INCLUDE 'includes/forms/ingredients_add.tt' %] diff --git a/root/templates/recipe/edit.tt b/root/templates/recipe/edit.tt index b99d1a46..d728a767 100644 --- a/root/templates/recipe/edit.tt +++ b/root/templates/recipe/edit.tt @@ -13,7 +13,7 @@ [% END %] -
+
From 935199121446cc431c840f39185050f2610326c9 Mon Sep 17 00:00:00 2001 From: Timon Foerster Date: Tue, 31 May 2022 12:16:18 +0200 Subject: [PATCH 2/3] (#144) bugfix and some changes --- root/static/js/unsavedChanges.js | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/root/static/js/unsavedChanges.js b/root/static/js/unsavedChanges.js index 15c0e31c..4b528db1 100644 --- a/root/static/js/unsavedChanges.js +++ b/root/static/js/unsavedChanges.js @@ -1,21 +1,22 @@ +"use strict"; + const forms = document.getElementsByClassName('confirmIfUnsavedChanges'); let hasUnsavedChanges = false; -for(const form of forms) { - const inputs = Array.prototype.slice.apply(form.getElementsByTagName('input')); - const textareas = Array.prototype.slice.apply(form.getElementsByTagName('textarea')); - const selects = Array.prototype.slice.apply(form.getElementsByTagName('select')); - const elements = inputs.concat(textareas).concat(selects); - console.log(elements) - for(const elem of elements) { - elem.addEventListener('input', () => {if(!hasUnsavedChanges) hasUnsavedChanges = true}); +for( const form of forms ) { + const inputs = Array.prototype.slice.apply(form.getElementsByTagName('input')); + const textareas = Array.prototype.slice.apply(form.getElementsByTagName('textarea')); + const selects = Array.prototype.slice.apply(form.getElementsByTagName('select')); + const elements = inputs.concat(textareas).concat(selects); + + for( const elem of elements ) { + elem.addEventListener('input', () => { if( !hasUnsavedChanges ) hasUnsavedChanges = true }); } - form.addEventListener('submit', () => {if(hasUnsavedChanges) hasUnsavedChanges = false}); + + form.addEventListener('submit', () => { if( hasUnsavedChanges ) hasUnsavedChanges = false }); } +// See documentation about 'beforeunload' event on https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event window.addEventListener('beforeunload', (e) => { - if (hasUnsavedChanges) { - (e || window.event).returnValue = ''; - return ''; - } -}) \ No newline at end of file + if( hasUnsavedChanges ) e.preventDefault(); // +}); From 7eb56ceba1f3f4b8b6c05243839dfb4f0f544284 Mon Sep 17 00:00:00 2001 From: Timon Foerster Date: Tue, 31 May 2022 12:28:36 +0200 Subject: [PATCH 3/3] (#144) add unsavedChanges.js to script.js --- lib/Coocook/Controller/Dish.pm | 2 -- lib/Coocook/Controller/Recipe.pm | 2 -- root/static/js/script.js | 23 +++++++++++++++++++++++ root/static/js/unsavedChanges.js | 22 ---------------------- 4 files changed, 23 insertions(+), 26 deletions(-) delete mode 100644 root/static/js/unsavedChanges.js diff --git a/lib/Coocook/Controller/Dish.pm b/lib/Coocook/Controller/Dish.pm index 6e3fdbed..ff83711d 100644 --- a/lib/Coocook/Controller/Dish.pm +++ b/lib/Coocook/Controller/Dish.pm @@ -81,8 +81,6 @@ sub edit : GET HEAD Chained('base') PathPart('') Args(0) RequiresCapability('vie for my $ingredient ( @{ $c->stash->{ingredients} } ) { $ingredient->{reposition_url} = $c->project_uri( '/dish/reposition', $ingredient->{id} ); } - - push @{ $c->stash->{js} }, '/js/unsavedChanges.js'; } sub delete : POST Chained('base') PathPart('delete') Args(0) RequiresCapability('edit_project') { diff --git a/lib/Coocook/Controller/Recipe.pm b/lib/Coocook/Controller/Recipe.pm index 98d3b564..21045905 100644 --- a/lib/Coocook/Controller/Recipe.pm +++ b/lib/Coocook/Controller/Recipe.pm @@ -106,8 +106,6 @@ sub edit : GET HEAD Chained('base') PathPart('') Args(0) RequiresCapability('vie $c->user and $c->stash( import_url => $c->uri_for_action( '/browse/recipe/import', [ $recipe->id, $recipe->url_name ] ) ); - - push @{ $c->stash->{js} }, '/js/unsavedChanges.js'; } sub new_recipe : GET HEAD Chained('submenu') PathPart('recipes/new') diff --git a/root/static/js/script.js b/root/static/js/script.js index 8910b1a2..70e03a52 100644 --- a/root/static/js/script.js +++ b/root/static/js/script.js @@ -1,3 +1,5 @@ +"use strict"; + $(function() { // reduce options of