5a920362 |
1 | |
2 | /* - formUnload.js - */ |
3 | /* |
4 | Provides "Your form has not been saved..." warning and query for forms matching |
5 | $('form.enableUnloadProtection'). |
6 | |
7 | Dependent on unlockOnFormUnload.js |
8 | */ |
9 | |
10 | /*global window:false, plone:false */ |
11 | |
12 | if (!window.beforeunload) {(function($) { |
13 | var BeforeUnloadHandler, |
14 | Class, |
15 | form, |
16 | c; |
17 | |
18 | BeforeUnloadHandler = function() { |
19 | var self = this, |
20 | message; |
21 | |
22 | this.message = window.form_modified_message || |
23 | "Discard changes? If you click OK, any changes you have made will be lost."; |
24 | |
25 | this.forms = []; |
26 | this.chkId = []; |
27 | this.chkType = new this.CheckType(); |
28 | this.handlers = [this.isAnyFormChanged]; |
29 | this.submitting = false; |
30 | |
31 | this.execute = function(event) { |
32 | // NOTE: this handler is not jQuery-wrapped! |
33 | // First clean out dead references to make sure we only work on |
34 | // forms that are actually in the dom. This is needed in |
35 | // combination with KSS and/or other dynamic replacements. |
36 | var domforms = $('form'); |
37 | self.forms = $.grep(self.forms, function(form) { |
38 | return domforms.index(form) > -1; |
39 | }); |
40 | |
41 | // Now do the protection work |
42 | if (self.submitting) {return;} |
43 | |
44 | $.each(self.handlers, function(i, fn) { |
45 | message = message || fn.apply(self); |
46 | }); |
47 | if (message===true) {message = self.message;} |
48 | if (message===false) {message = undefined;} |
49 | if (event && message) {event.returnValue = message;} |
50 | return message; |
51 | }; |
52 | this.execute.tool = this; |
53 | }; |
54 | Class = BeforeUnloadHandler.prototype; |
55 | |
56 | // form checking code |
57 | Class.isAnyFormChanged = function() { |
58 | var i; |
59 | for (i=0; i < this.forms.length; i+=1) { |
60 | form = this.forms[i]; |
61 | if (this.isElementChanged(form)) { |
62 | return true; |
63 | } |
64 | } |
65 | return false; |
66 | }; |
67 | Class.addHandler = function(fn) { |
68 | this.handlers.push(fn); |
69 | }; |
70 | Class.onsubmit = function() { |
71 | var tool = window.onbeforeunload && window.onbeforeunload.tool; |
72 | tool.submitting = true; |
73 | // Also set this on the unlocking tool! |
74 | // This way the tool knows we are in submitting, |
75 | // and can prevent unlocking. |
76 | plone.UnlockHandler.submitting = true; |
77 | }; |
78 | Class.addForm = function(form) { |
79 | if ($.inArray(form, this.forms) > -1) {return;} |
80 | this.forms.push(form); |
81 | $(form).submit(this.onsubmit); |
82 | // store hidden input's defaultValue to work around a moz bug |
83 | $(form).find('input:hidden').each(function() { |
84 | var value = this.defaultValue; |
85 | if (value!==undefined && value!==null) { |
86 | $(this).attr('originalValue', value.replace(/\r\n?/g,'\n')); |
87 | } |
88 | }); |
89 | }; |
90 | Class.addForms = function() { |
91 | var self = this; |
92 | $.each(arguments, function() { |
93 | if (this.tagName.toLowerCase() === 'form') { |
94 | self.addForm(this); |
95 | } else { |
96 | self.addForms.apply(self, $(this).find('form').get()); |
97 | } |
98 | }); |
99 | }; |
100 | Class.removeForms = function() { |
101 | var self = this; |
102 | $.each(arguments, function() { |
103 | if (this.tagName.toLowerCase() === 'form') { |
104 | var formElement = this; |
105 | self.forms = $.grep(self.forms, function(form) { |
106 | return form !== formElement; |
107 | }); |
108 | $(formElement).unbind('submit', self.onsubmit); |
109 | } else { |
110 | self.removeForms.apply(self, $(this).find('form').get()); |
111 | } |
112 | }); |
113 | }; |
114 | |
115 | Class.CheckType = function() {}; |
116 | c = Class.CheckType.prototype; |
117 | c.checkbox = c.radio = function(ele) { |
118 | return ele.checked !== ele.defaultChecked; |
119 | }; |
120 | c.file = c.password = c.textarea = c.text = function(ele) { |
121 | return ele.value !== ele.defaultValue; |
122 | }; |
123 | // hidden: cannot tell on Mozilla without special treatment |
124 | c.hidden = function(ele) { |
125 | var orig = $(ele).attr('originalValue'); |
126 | if (orig===undefined||orig===null) {return false;} |
127 | return $(ele).val().replace(/\r\n?/g, '\n') !== orig; |
128 | }; |
129 | |
130 | c['select-one'] = function(ele) { |
131 | var i, opt; |
132 | |
133 | for (i = 0; i < ele.length; i+=1) { |
134 | opt = ele[i]; |
135 | if (opt.selected !== opt.defaultSelected) { |
136 | if (i===0 && opt.selected) { |
137 | continue; /* maybe no default */ |
138 | } |
139 | return true; |
140 | } |
141 | } |
142 | return false; |
143 | }; |
144 | |
145 | c['select-multiple'] = function(ele) { |
146 | var i, opt; |
147 | |
148 | for (i = 0; i < ele.length; i+=1) { |
149 | opt = ele[i]; |
150 | if ( opt.selected !== opt.defaultSelected) { |
151 | return true; |
152 | } |
153 | } |
154 | return false; |
155 | }; |
156 | |
157 | Class.chk_form = function(form) { |
158 | // Find all form elements that are a) not marked as not-protected |
159 | // or b) not a descendant of a non-protected element. |
160 | var elems = $(form).find('> :input:not(.noUnloadProtection),' + |
161 | ':not(.noUnloadProtection) :input:not(.noUnloadProtection)'), |
162 | i; |
163 | for (i = 0; i < elems.length; i+=1) { |
164 | if (this.isElementChanged(elems.get(i))) { |
165 | return true; |
166 | } |
167 | } |
168 | return false; |
169 | }; |
170 | |
171 | Class.isElementChanged = function(ele) { |
172 | var method = ele.id && this.chkId[ele.id]; |
173 | if (!method && ele.type && ele.name) { |
174 | method = this.chkType[ele.type]; |
175 | } |
176 | if (!method && ele.tagName) { |
177 | method = this['chk_'+ele.tagName.toLowerCase()]; |
178 | } |
179 | |
180 | return method? method.call(this, ele) : false; |
181 | }; |
182 | |
183 | // Can't use jQuery handlers here as kupu and kss rely on direct access. |
184 | window.onbeforeunload = new BeforeUnloadHandler().execute; |
185 | |
186 | $(function() { |
187 | var tool = window.onbeforeunload && window.onbeforeunload.tool; |
188 | if (tool && $('#region-content,#content').length) { |
189 | tool.addForms.apply(tool, $('form.enableUnloadProtection').get()); |
190 | } |
191 | }); |
192 | }(jQuery));} |
193 | |