adding all weblabels from weblabels.fsf.org
[weblabels.fsf.org.git] / www.fsf.org / 20131028 / files / static.fsf.org / plone2012 / formUnload.js
CommitLineData
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
12if (!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