diff --git a/resources/js/components/common/Notifications.vue b/resources/js/components/common/Notifications.vue
index 6f12a13..b7cbbdf 100644
--- a/resources/js/components/common/Notifications.vue
+++ b/resources/js/components/common/Notifications.vue
@@ -98,7 +98,7 @@
@@ -45,6 +46,16 @@ export default {
next()
},
+ beforeRouteLeave (to, from, next) {
+ if (this.isDirty()) {
+ return this.alertConfirm('Changes you made may not be saved. Are you sure want to leave?', () => {
+ window.onbeforeunload = null
+ next()
+ }, () => {})
+ }
+ next()
+ },
+
middleware: 'auth',
data() {
@@ -54,7 +65,8 @@ export default {
loading: false,
error: '',
editorMaxHeight: 500,
- showInitialFormModal: false
+ showInitialFormModal: false,
+ formInitialHash: null
}
},
@@ -90,7 +102,14 @@ export default {
},
mounted() {
+ window.onbeforeunload = () => {
+ if (this.isDirty()) {
+ return false
+ }
+ }
+
this.initForm()
+ this.formInitialHash = this.hashString(JSON.stringify(this.form.data()))
if (this.$route.query.template !== undefined && this.$route.query.template) {
const template = this.$store.getters['open/templates/getBySlug'](this.$route.query.template)
if (template && template.structure) {
@@ -127,6 +146,23 @@ export default {
},
formGenerated(form) {
this.form = new Form({...this.form.data(), ...form})
+ },
+ isDirty () {
+ return !this.loading && this.formInitialHash && this.formInitialHash !== this.hashString(JSON.stringify(this.form.data()))
+ },
+ hashString (str, seed = 0) {
+ let h1 = 0xdeadbeef ^ seed
+ let h2 = 0x41c6ce57 ^ seed
+ for (let i = 0, ch; i < str.length; i++) {
+ ch = str.charCodeAt(i)
+ h1 = Math.imul(h1 ^ ch, 2654435761)
+ h2 = Math.imul(h2 ^ ch, 1597334677)
+ }
+
+ h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909)
+ h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909)
+
+ return 4294967296 * (2097151 & h2) + (h1 >>> 0)
}
}
}
diff --git a/resources/js/pages/forms/edit.vue b/resources/js/pages/forms/edit.vue
index 0a2f541..ddfa392 100644
--- a/resources/js/pages/forms/edit.vue
+++ b/resources/js/pages/forms/edit.vue
@@ -6,6 +6,7 @@
}"
:isEdit="true"
@mounted="onResize"
+ @on-save="formInitialHash=null"
/>
{{ error }}
@@ -42,6 +43,17 @@ export default {
store.commit('open/working_form/set', null) // Reset old working form
next()
},
+
+ beforeRouteLeave (to, from, next) {
+ if (this.isDirty()) {
+ return this.alertConfirm('Changes you made may not be saved. Are you sure want to leave?', () => {
+ window.onbeforeunload = null
+ next()
+ }, () => {})
+ }
+ next()
+ },
+
middleware: 'auth',
mixins: [SeoMeta],
@@ -49,7 +61,8 @@ export default {
return {
loading: false,
error: null,
- editorMaxHeight: 500
+ editorMaxHeight: 500,
+ formInitialHash: null
}
},
@@ -91,11 +104,18 @@ export default {
},
mounted () {
+ window.onbeforeunload = () => {
+ if (this.isDirty()) {
+ return false
+ }
+ }
+
this.closeAlert()
if (!this.form) {
loadForms()
} else {
this.updatedForm = new Form(this.form)
+ this.formInitialHash = this.hashString(JSON.stringify(this.updatedForm.data()))
}
},
@@ -107,6 +127,21 @@ export default {
if (this.$refs.editor) {
this.editorMaxHeight = Math.max(500, window.innerHeight - this.$refs.editor.$el.offsetTop)
}
+ },
+ isDirty () {
+ return !this.loading && this.formInitialHash && this.formInitialHash !== this.hashString(JSON.stringify(this.updatedForm.data()))
+ },
+ hashString (str, seed = 0) {
+ let h1 = 0xdeadbeef ^ seed
+ let h2 = 0x41c6ce57 ^ seed
+ for (let i = 0, ch; i < str.length; i++) {
+ ch = str.charCodeAt(i)
+ h1 = Math.imul(h1 ^ ch, 2654435761)
+ h2 = Math.imul(h2 ^ ch, 1597334677)
+ }
+ h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909)
+ h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909)
+ return 4294967296 * (2097151 & h2) + (h1 >>> 0)
}
}
}