| 1 | /*global chainHandler, getData */ |
|---|
| 2 | 'use strict'; |
|---|
| 3 | |
|---|
| 4 | function confirmClose() { |
|---|
| 5 | if (arguments.length > 0) { |
|---|
| 6 | for (let i = 0; i < arguments.length; i++) { |
|---|
| 7 | this.forms_id.push(arguments[i]); |
|---|
| 8 | } |
|---|
| 9 | } |
|---|
| 10 | } |
|---|
| 11 | |
|---|
| 12 | confirmClose.prototype = { |
|---|
| 13 | prompt: 'You have unsaved changes.', |
|---|
| 14 | forms_id: [], |
|---|
| 15 | forms: [], |
|---|
| 16 | formSubmit: false, |
|---|
| 17 | |
|---|
| 18 | getCurrentForms: function() { |
|---|
| 19 | // Store current form's element's values |
|---|
| 20 | |
|---|
| 21 | const formsInPage = this.getForms(); |
|---|
| 22 | const This = this; |
|---|
| 23 | this.forms = []; |
|---|
| 24 | for (let i = 0; i < formsInPage.length; i++) { |
|---|
| 25 | const f = formsInPage[i]; |
|---|
| 26 | let tmpForm = []; |
|---|
| 27 | for (let j = 0; j < f.elements.length; j++) { |
|---|
| 28 | const e = this.getFormElementValue(f[j]); |
|---|
| 29 | if (e != undefined) { |
|---|
| 30 | tmpForm.push(e); |
|---|
| 31 | } |
|---|
| 32 | } |
|---|
| 33 | this.forms.push(tmpForm); |
|---|
| 34 | |
|---|
| 35 | chainHandler(f, 'onsubmit', function() { |
|---|
| 36 | This.formSubmit = true; |
|---|
| 37 | }); |
|---|
| 38 | } |
|---|
| 39 | }, |
|---|
| 40 | |
|---|
| 41 | compareForms: function() { |
|---|
| 42 | // Compare current form's element's values to their original values |
|---|
| 43 | // Return false if any difference, else true |
|---|
| 44 | |
|---|
| 45 | if (this.forms.length == 0) { |
|---|
| 46 | return true; |
|---|
| 47 | } |
|---|
| 48 | |
|---|
| 49 | const formsInPage = this.getForms(); |
|---|
| 50 | for (let i = 0; i < formsInPage.length; i++) { |
|---|
| 51 | const f = formsInPage[i]; |
|---|
| 52 | var tmpForm = []; |
|---|
| 53 | for (let j = 0; j < f.elements.length; j++) { |
|---|
| 54 | const e = this.getFormElementValue(f[j]); |
|---|
| 55 | if (e != undefined) { |
|---|
| 56 | tmpForm.push(e); |
|---|
| 57 | } |
|---|
| 58 | } |
|---|
| 59 | for (let j = 0; j < this.forms[i].length; j++) { |
|---|
| 60 | if (this.forms[i][j] != tmpForm[j]) { |
|---|
| 61 | return false; |
|---|
| 62 | } |
|---|
| 63 | } |
|---|
| 64 | } |
|---|
| 65 | |
|---|
| 66 | return true; |
|---|
| 67 | }, |
|---|
| 68 | |
|---|
| 69 | getForms: function() { |
|---|
| 70 | // Get current list of forms as HTMLCollection(s) |
|---|
| 71 | |
|---|
| 72 | if (!document.getElementsByTagName || !document.getElementById) { |
|---|
| 73 | return []; |
|---|
| 74 | } |
|---|
| 75 | |
|---|
| 76 | if (this.forms_id.length > 0) { |
|---|
| 77 | let res = []; |
|---|
| 78 | for (let i = 0; i < this.forms_id.length; i++) { |
|---|
| 79 | const f = document.getElementById(this.forms_id[i]); |
|---|
| 80 | if (f != undefined) { |
|---|
| 81 | res.push(f); |
|---|
| 82 | } |
|---|
| 83 | } |
|---|
| 84 | return res; |
|---|
| 85 | } else { |
|---|
| 86 | return document.getElementsByTagName('form'); |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | return []; |
|---|
| 90 | }, |
|---|
| 91 | |
|---|
| 92 | getFormElementValue: function(e) { |
|---|
| 93 | // Return current value of an form element |
|---|
| 94 | |
|---|
| 95 | if (e == undefined) { |
|---|
| 96 | // Unknown object |
|---|
| 97 | return undefined; |
|---|
| 98 | } |
|---|
| 99 | if (e.type != undefined && e.type == 'button') { |
|---|
| 100 | // Ignore button element |
|---|
| 101 | return undefined; |
|---|
| 102 | } |
|---|
| 103 | if (e.classList.contains('meta-helper') || e.classList.contains('checkbox-helper')) { |
|---|
| 104 | // Ignore some application helper element |
|---|
| 105 | return undefined; |
|---|
| 106 | } |
|---|
| 107 | if (e.type != undefined && e.type == 'radio') { |
|---|
| 108 | // Return actual radio button value if selected, else null |
|---|
| 109 | return this.getFormRadioValue(e); |
|---|
| 110 | } else if (e.type != undefined && e.type == 'checkbox') { |
|---|
| 111 | // Return actual checkbox button value if checked, else null |
|---|
| 112 | return this.getFormCheckValue(e); |
|---|
| 113 | } else if (e.type != undefined && e.type == 'password') { |
|---|
| 114 | // Ignore password element |
|---|
| 115 | return null; |
|---|
| 116 | } else if (e.value != undefined) { |
|---|
| 117 | // Return element value if not undefined |
|---|
| 118 | return e.value; |
|---|
| 119 | } else { |
|---|
| 120 | // Every other case, return null |
|---|
| 121 | return null; |
|---|
| 122 | } |
|---|
| 123 | }, |
|---|
| 124 | |
|---|
| 125 | getFormCheckValue: function(e) { |
|---|
| 126 | if (e.checked) { |
|---|
| 127 | return e.value; |
|---|
| 128 | } |
|---|
| 129 | return null; |
|---|
| 130 | }, |
|---|
| 131 | |
|---|
| 132 | getFormRadioValue: function(e) { |
|---|
| 133 | for (let i = 0; i < e.length; i++) { |
|---|
| 134 | if (e[i].checked) { |
|---|
| 135 | return e[i].value; |
|---|
| 136 | } else { |
|---|
| 137 | return null; |
|---|
| 138 | } |
|---|
| 139 | } |
|---|
| 140 | return null; |
|---|
| 141 | } |
|---|
| 142 | }; |
|---|
| 143 | |
|---|
| 144 | let confirmClosePage = new confirmClose(); |
|---|
| 145 | |
|---|
| 146 | chainHandler(window, 'onload', function() { |
|---|
| 147 | confirmClosePage.getCurrentForms(); |
|---|
| 148 | }); |
|---|
| 149 | |
|---|
| 150 | chainHandler(window, 'onbeforeunload', function(event_) { |
|---|
| 151 | if (event_ == undefined && window.event) { |
|---|
| 152 | event_ = window.event; |
|---|
| 153 | } |
|---|
| 154 | |
|---|
| 155 | if (!confirmClosePage.formSubmit && !confirmClosePage.compareForms()) { |
|---|
| 156 | event_.returnValue = confirmClosePage.prompt; |
|---|
| 157 | return confirmClosePage.prompt; |
|---|
| 158 | } |
|---|
| 159 | return false; |
|---|
| 160 | }); |
|---|
| 161 | |
|---|
| 162 | const confirm_close = getData('confirm_close'); |
|---|
| 163 | confirmClose.prototype.prompt = confirm_close.prompt; |
|---|
| 164 | confirmClosePage = new confirmClose(...confirm_close.forms); |
|---|