In this article I will demonstrate a simple but effective way to determine if something has changed on your webpage. I will use the MD5 hashing library available in dojo and compares the hash at the start of the process and at the end – if it has changed – something has changed.
Acknowledgements
I have to acknowledge Alex Skinner and Jason Lavoie who first showed me this method many years ago on a .NET project and Troy Reimer who was the Über smart genius to take the idea and apply it so eloquently to XPages using dojo cryptographic libraries. Thanks guys 🙂
Introduction
It has been an age old issue with web form development – how do I know if the user has changed anything?
We could track the start and end value of every field – doable but laborious. Also comes to a stumbling block with you have user interactions which are not field based – like dragging and dropping an employee from one manager box to another.
We could use the XSP._isDirty() function which is provided for us in XPages but that does not apply in all situations and this example will work with any webpage (assuming dojo is loaded)
MD5 Hash
Partially because of my lack of understanding but entirely because of its lack of relevance to this solution I am not going to go into how MD5 hashing works but to suffice to say: – an MD5 hash is an iterative encryption algorithm which can reduce a string of any length down to a fixed length (in our case 16 characters).
Dojo Cryptography libraries
Dojo provides various cryptographic algorithms and you can find out more about them here
http://dojotoolkit.org/reference-guide/1.6/dojox/encoding/crypto.html
In our case we are going to use the MD5 library and we add it to our XPage in the following manner:
dojo.require("dojox.encoding.digests.MD5");
What needs to be checked?
Well it just so happens (if you hadn’t noticed) that HTML is basically a long text string. So what we are going to do is to put a panel around the form fields we are trying to test again.
<xp:panel styleClass="myPanel"> web form stuff here </xp:panel>
And then once the page is loaded we are going to create the MD5 Hash of the HTML within that panel like this.
var oDocHash = oDocHash= dojox.encoding.digests.MD5(dojo.query('.myPanel')[0].innerHTML); console.log(oDocHash)
We can then either stick the hash in a cookie – or in a field on the form – or in this case in a windows variable.
(Before the JavaScript purists start to have a go – I know, I know don’t use the windows object to store variables – tough – I said 4 lines of code, didn’t I) 😉
So then the overall code to create the hash looks like this:
dojo.require("dojox.encoding.digests.MD5"); window.docHash = dojox.encoding.digests.MD5(dojo.query('.myPanel')[0].innerHTML);
The checking
When you are ready – or the user is not ready to check if anything has changed all we have to do is re-hash and then compare the variables, like this
hasChanged = (window.docHash != dojox.encoding.digests.MD5(dojo.query('.myPanel')[0].innerHTML))? "This form has changed" : "" if (hasChanged){alert(hasChanged)}
The overall Code sample
//Load the necessary dojo Crypto Library dojo.require("dojox.encoding.digests.MD5"); //Get a hash of the innerHTML of the element with the .myPanel class //Run this when the page is loaded window.docHash = dojox.encoding.digests.MD5(dojo.query('.myPanel')[0].innerHTML); console.log("Stored hash: "+window.docHash) //determine if a change has been made //run this when the page is ready to be saved or navigated away from hasChanged = (window.docHash != dojox.encoding.digests.MD5(dojo.query('.myPanel')[0].innerHTML))? "This form has changed" : "" console.log("New hash: "+dojox.encoding.digests.MD5(dojo.query('.myPanel')[0].innerHTML)) //panic panic if (hasChanged){alert(hasChanged)}
The demonstration
As you can see from the video below we are starting out with a simple XPage – not in Edit mode – I have also added some console logs to the code so that you can see what is going on. I use firebug to alter the HTML – and the hashes do not match. For the icing on the cake though if I put the HTML back to be exactly what it was before we started then the hashes match.
Conclusion
And there you have it – it is simple to implement and you don’t need to understand how the cryptography works to use it. Generally better than way I find because trying to understand cryptography usually causes headaches and nose bleeds.