Prevent form loss when navigating away

aethelwulffe wrote on Friday, December 18, 2015:

Trying to properly prevent folks from navigating away from their encounter form without hitting the save or cancel button.
The following should probably be written into the form-saving js library, but I have the extra bit here for viewing. I am posting as a screenshot because html inside code blocks on this forum seem to be getting parsed (and all text gets parsed as js).

The idea is to give folks an alert before they go to check out something elsewhere and replace the frame they were working in…thereby the promoter of Private Hysteria and Major Confusion, causing me to go to General Quarters with Corporal Punishment.
So: The above code still fires when you click the save or cancel buttons. I have made a few attempts to write exceptions into the method to make it not fire in those cases…to poor results.
In all the tawdry history of OpenEMR, certainly someone has taken note of similar issues and said; “I shall construct a tiny snippet of code to solve this problem, thereby saving us thousands of dollars in lost hours and goodwill annually.” If this is so, or if someone has a quality approach for doing so that they can otherwise share or help me with, this ineffective javascript noob would greatly appreciate it.
-Art

mdsupport wrote on Saturday, December 19, 2015:

You should define form.beforeunload to return false followed by unbind to let submits (both save and cancel) bypass beforeunload check.

An intrusive alternative would be to assign a class (e.g. amDirty) to critical input elements in a form, use jQuery to add event listener for monitoring the changes and then use the single isDirty state to decide the action. Of course, if you check and then uncheck a checkbox, the form will still be treated as dirty!

var _isDirty = false;
$(".amDirty").change(function(){
_isDirty = true;
});

If you want all elements in a form to be monitored, then use jQuery form’s child selector to attach change monitor - no html change necessary.

aethelwulffe wrote on Saturday, December 19, 2015:

Ah, yes…I have come across the is_Dirty alternative. I have simply failed to implement it properly at this point.
Thank you, I guess I am on the right track.
So…just out of curiosity, has ANYONE else ever run into an issue where behavior of the type above was a desired feature?

medfetch wrote on Friday, January 01, 2016:

Hi Art,

I use this on the Eye Form also, at least the autosave feature (will look up Dirty alternative). In fact, I discarded the save button altogether on this form.

There is a problem with autosaving the whole form at once repetitively - you cannot chart on more than one machine. We move patients from clinic area to clinic area throughout the exam so this is a real problem for ophthalmology. Please bear with me but this is key: to ensure data integrity, if the form is left open on machine #1 and you go to use another machine #2, the original machine #1 will not have updates entered from machine #2. When the form is closed on #1, its curent data state is saved to the DB ignoring those entered on #2. The entries made on machine #2 are erased from the database simply by closing the form on machine #1 “later” than #2. Sometimes we move patients to a third or fourth station for testing! Imagine my surprise when all my charting went poof, and disappeared?

Perhaps this is handled by the Dirty alternative thing (so I will look that up) but to this end I added a feature to ensure the current browser window has ownership. On start-up/opening the encounter form, if some other machine has the form opened, you are asked if you want to take control. Say Yes and any other browsers or machine looking at the same form (encounter/form_id etc) are in read-only mode, can’t save their changes. Choose to go Read-Only ie. preview the next patient’s chart and progress with technicians, and you will see the changes being made by the owner updated every 10 seconds, close enough to real time to be moderately useful.

Ray

medfetch wrote on Friday, January 01, 2016:

Here is a video of this in action on two browsers, one Firefox, one Chrome, simulating two separate machines. I apologize for the audio. I am over 50 so maybe I have an excuse?

aethelwulffe wrote on Saturday, January 02, 2016:

Quick question: Even if you have the same user (clinician) logged into all the machines (browsers looking at openemr and that form) you could modifiy the USER_AGENT of the browser open at each machine to a unique identifyer, then have your form check to see which machine you are at…thereby setting each piece of the input UI to editable or read-only.
Personally, I have had to table this bit as what I have works for (1) of the several problem areas we have, and there are many other projects screaming for attention. Thank you for your input and for helping keep this alive in my mind though.
http://www.howtogeek.com/113439/how-to-change-your-browsers-user-agent-without-installing-any-extensions/

medfetch wrote on Saturday, January 02, 2016:

Exactly, just add a variable to the form or use a session variable if you like. It is not a user-specific variable or a browser-specific variable but a session-specific variable, controlled server side.

I used a very simple browser-independent solution to temporarily lock an individual form by adding an ownership field (LOCKEDBY) to each form’s table in the DB. I see this process just like all the others - as a “square-dance” between the php view.php, javascript and save.php files: looks chaotic but you get the right partner in the end.

At the start, when the form is opened anywhere (view.php):

If there is no LOCKEDBY value in the DB, one is randonly generated mt_rand() in view.php and stored in the DB via javascript/ajax through save.php. To this user, the form is unlocked/not disabled and the user edits away as if nothing happened. They have ownership. The menu bar within the form displays “ACTIVE CHART”.

If there is a value for LOCKEDBY in the DB, a new random value variable $take_ownership is generated by view.php for this session. The form is locked - ie. all fields are disabled in the GUI for the user. A javascript pop-up asks if the user wishes to take ownership:
If they click yes, they own it. $take_ownership is stored as LOCKEDBY in the DB via ajax through save.php. The menu bar displays “ACTIVE CHART”. Each subsequent background/ajax “save” submits this new LOCKEDBY value, along with all the other fields. If the submitted LOCKEDBY value matches the one in the DB, the save is processed. When they unload/close this instance of the form, the LOCKEDBY value is set to NULL via an unlock ajax request sent to save.php.
If they click cancel, ie. do not take ownership, they are in read-only mode. The menu bar displays “READ-ONLY”. All fields are disabled, saves are impossible and the form they are viewing is updated every ten seconds via ajax, should any changes be made “elsewhere”, in another browser instance.

This save issue became important since even "open this frame in a new window" was creating two instances of the form that could destructively overwrite each other.  This solved my problem at least and I hope it will help others who may encounter the same.