Is this the most efficient way to do this function?
For the sake of efficiency, what you have may be close. As others have pointed out, the selector for the fields to reset the value of formmodified
could be combined. For example, the single selector offered in the answer by Roland Illig:
$("input[name='ModifyRecord'], input[name='DeleteRecord'], input[name='DeleteChecked']").click(function() {
formmodified = false;
});
This could be simplified using an arrow function (a feature of ecmascript-6 - note the browser support of those).
$("input[name='ModifyRecord'], input[name='DeleteRecord'], input[name='DeleteChecked']")
.click(_ => formmodified = false);
Another approach is to use event delegation by adding a click handler to an element containing those inputs - e.g. the document, form, etc. Then check the target
property of the event
argument to see if it:
- has a value in the
tagName
attribute of input, and
- has a value in the
name
attribute matching one of the three inputs targeted (i.e. 'ModifyRecord', 'DeleteRecord', 'DeleteChecked')
For #1, we can access the tagName
property. For #2, we can create an array - e.g. var resetNames = ['ModifyRecord', 'DeleteRecord', 'DeleteChecked'];
and if the name
attribute is in that array:
$(document).click(function(clickEvent) {
var targ = clickEvent.target;
if (targ.tagName.toLowerCase() == 'input' && resetNames.includes(targ.name)) {
formmodified = 0;
}
}
Like ced mentioned, adding a class attribute to the inputs to target could simplify the logic. Then the logic to check if the name of the input is in the array could be replaced by a simple call to targ.hasClass()
.
Or can it be simplified much more to run smoother?
I am not sure about smoother, but I do know that the MDN documentation for onbeforeunload states:
You can and should handle this event through window.addEventListener()
and the beforeunload
event. More documentation is available there.1
For a single page application, there may not be a need to have more than one function called during the beforeunload
event, but as applications grow larger, there may be a need to have multiple. That approach (with window.addEventListener('beforeunload', function() {...})
supports multiple callback functions to be run.
Also note that the documentation for beforeunload states:
If a string is assigned to the returnValue
Event property, a dialog appears asking the user for confirmation to leave the page... WebKit-based browsers don't follow the spec for the dialog box. An almost cross-browser working example would be close to the following:
window.addEventListener("beforeunload", function (e) {
var confirmationMessage = "\o/";
e.returnValue = confirmationMessage; // Gecko, Trident, Chrome 34+
return confirmationMessage; // Gecko, WebKit, Chrome <34
});
2
So for both cases, set the returnValue
property on the event argument (i.e. e
in the example above) and then return that value.
And in agreement with Roland, add var
(I would say let
but maybe you are supporting browsers that don't fully support that and other ecmascript-6 features like IE 10 and earlier) before initializing formmodified
to limit the scope to that of the DOM-loaded callback.
Additionally, the format for .ready()
can be simplified to "the recommended syntax"3:
$(function() { ... })
$(function() { //DOM ready callback
var formmodified = 0;
var resetNames = ['ModifyRecord', 'DeleteRecord', 'DeleteChecked'];
$('form *').change(function() {
formmodified = 1;
console.log('set formmodified to 1');
});
window.addEventListener('beforeunload', confirmExit);
function confirmExit(e) {
if (formmodified === 1) {
var confirmationMessage = "Are you sure you want to leave this page? This will abandon any progress on changes to document preferences";
e.returnValue = confirmationMessage
return e.returnValue;
}
}
$(document).click(function(clickEvent) {
var targ = clickEvent.target;
if (targ.tagName.toLowerCase() == 'input' && resetNames.includes(targ.name)) {
formmodified = 0;
console.log('set formmodified to 0');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<form>
Some text
<input type="Number" name="numberField" />
<input name="CreateRecord" type="button" value="Create record" />
<input name="ModifyRecord" type="button" value="Modify record" />
<input name="DeleteRecord" type="button" value="Delete record" />
<input name="DeleteChecked" type="button" value="Delete checked" />
</form>
1https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload#Notes
2https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload
3http://api.jquery.com/ready/