Michael Winter wrote:
As an event property assignment:
window.onbefore unload = function() {
return 'This is the prompt text.';
};
The documentation uses the proprietary event.returnVal ue property
instead of a return statement, but the result is the same.
Not quite. The return statement won't have the desired effect on IE, and
event.returnVal ue won't have any effect on Mozilla. To write code which
works on both you have to use both.
window.onbefore unload = function(event) {
var msg = 'This is the prompt text.';
if (!event) event = window.event;
if (event) event.returnVal ue = msg;
return msg;
};
Also note that if you use Mozilla's addEventHandler method to add handler
function, Mozilla will ignore the return value totally (so the function
gets called, but nothing you can do will make it pop up the warning box).
Here's a longer example (but still self-contained) which implements a
warning box whenever you try to navigate away from a page with a modified
form.
The original is at
http://codespeak.net/svn/kupu/trunk/...eforeunload.js,
documentation at
http://codespeak.net/svn/kupu/trunk/...FOREUNLOAD.txt, license at
http://codespeak.net/svn/kupu/trunk/...oc/LICENSE.txt. Add a call to
window.onbefore unload.tool.add Forms() to enable checking.
/* BeforeUnload form processing */
if (!window.before unload) (function() {
var BeforeUnloadHan dler = function() {
var self = this;
this.message = "Your form has not been saved. All changes you have
made will be lost";
if (window._) {
this.message = _("Your form has not been saved. All changes you
have made will be lost");
};
this.forms = [];
this.chkId = [];
this.chkType = new this.CheckType( );
this.handlers = [this.isAnyFormC hanged];
this.submitting = false;
this.execute = function(event) {
if (self.submittin g) return;
if (!event) event = window.event;
for (var i = 0; i < self.handlers.l ength; i++) {
var fn = self.handlers[i];
var message = message || fn.apply(self);
}
if (message===true ) message = self.message;
if (message===fals e) message = undefined;
if (event) event.returnVal ue = message;
return message;
}
this.execute.to ol = this;
}
var Class = BeforeUnloadHan dler.prototype;
// form checking code
Class.isAnyForm Changed = function() {
for (var i=0; i < this.forms.leng th; i++) {
var form = this.forms[i];
if (this.isElement Changed(form)) {
return true;
}
}
return false;
}
Class.addHandle r = function(fn) {
this.handlers.p ush(fn);
}
Class.onsubmit = function() {
var tool = window.onbefore unload && window.onbefore unload.tool;
tool.submitting = true;
}
Class.addForm = function(form) {
for (var i = 0; i < this.forms.leng th; i++) {
if (this.forms[i]==form) return;
}
this.forms.push (form);
form.onsubmit = this.onsubmit;
var elements = form.getElement sByTagName('inp ut');
for (var j = 0; j < elements.length ; j++) {
var ele = elements[j];
if (ele.type=='hid den') {
ele.setAttribut e('originalValu e', ele.defaultValu e);
}
}
}
Class.addForms = function() {
for (var i = 0; i < arguments.lengt h; i++) {
var element = arguments[i];
if (!element) continue;
if (element.tagNam e=='FORM') {
this.addForm(el ement);
}
else {
var forms = element.getElem entsByTagName(' form');
for (var j = 0; j < forms.length; j++) {
this.addForm(fo rms[j]);
}
}
}
}
Class.removeFor ms = function() {
for (var i = 0; i < arguments.lengt h; i++) {
var element = arguments[i];
if (!element) continue;
if (element.tagNam e=='FORM') {
for (var j = 0; j < arguments.lengt h; j++) {
if (this.forms[j] == element) {
this.forms.spli ce(j--, 1);
element.onsubmi t=null;
}
}
} else {
var forms = element.getElem entsByTagName(' form');
for (var j = 0; j < forms.length; j++) {
this.removeForm s(forms[j]);
}
}
}
}
Class.CheckType = function() {};
var c = Class.CheckType .prototype;
c.checkbox = c.radio = function(ele) {
return ele.checked != ele.defaultChec ked;
}
c.password = c.textarea = c.text = function(ele) {
return ele.value != ele.defaultValu e;
}
// hidden: cannot tell on Mozilla without special treatment
c.hidden = function(ele) {
var orig = ele.getAttribut e("originalValu e");
return orig && (ele.value != orig);
}
c['select-one'] = function(ele) {
for (var i=0 ; i < ele.length; i++) {
var opt = ele.options[i];
if ( opt.selected != opt.defaultSele cted) {
if (i===0 && opt.selected) continue; /* maybe no default */
return true;
}
}
return false;
}
c['select-multiple'] = function(ele) {
for (var i=0 ; i < ele.length; i++) {
var opt = ele.options[i];
if ( opt.selected != opt.defaultSele cted) {
return true;
}
}
return false;
}
Class.chk_form = function(form) {
var elements = form.elements;
for (var i=0; i < elements.length ; i++ ) {
var element = elements[i];
if (this.isElement Changed(element )) {
return true;
}
}
return false;
}
Class.isElement Changed = function(ele) {
var method = ele.id && this.chkId[ele.id];
if (!method && ele.type && ele.name)
method = this.chkType[ele.type];
if (!method && ele.tagName)
method = this['chk_'+ele.tagN ame.toLowerCase ()];
return method? method.apply(th is, [ele]) : false;
};
window.onbefore unload = new BeforeUnloadHan dler().execute;
})();