Yes, so first of all apologies for the slightly wordy and not particularly "on point" title for this post - I can't quite how to name it, hence the above...
I wanted a quick a dirty solution for this scenario that works in SharePoint Online, which means JavaScript. I'm not claiming that what I'm about to show you is the best possible way to manage this, but it works and the customer was really happy that I was able to throw a solution together for them so quickly.
This may be too wide a catchment for your liking/requirements, if it is there are other events you can hook into, or you could filter the events you aren't interested in the function itself (I highly doubt that this could ever be considered good practice, especially if there's an event you could hook up to instead that already misses out the scenarios you don't need).
The problem
Anyway, what this post is about is how to give users creating and editing publishing pages in SharePoint a better experience when leaving a page that is in edit mode. This arose from a customer complaining that if they accidentally (or even purposely) click on the back button, or hit F5 or even click on a link somewhere whilst editing a page they get whisked away without a shadow of a warning meaning that there will be a high chance of losing any unsaved work.I wanted a quick a dirty solution for this scenario that works in SharePoint Online, which means JavaScript. I'm not claiming that what I'm about to show you is the best possible way to manage this, but it works and the customer was really happy that I was able to throw a solution together for them so quickly.
The solution
Standard javascript gives you the window.beforeunload event to hook up to and assign a function that fires each time that event is triggered. window.beforeunload has quite a wide catchment of possible triggers, namely (docco courtesy of MSDN):
- Close the current window.
- Navigate to another location by entering a new address or selecting a Favorite.
- Click an anchor that refers to another document.
- Invoke the anchor.click method.
- Invoke the document.write method.
- Invoke the document.close method.
- Invoke the window.close method.
- Invoke the window.navigate or NavigateAndFind method.
- Invoke the location.replace method.
- Invoke the location.reload method.
- Specify a new value for the location.href property.
- Submit a form to the address specified in the ACTION attribute via the INPUT type=submit control, or invoke the form.submit method.
- Invoke the window.open method, providing the possible value _self for the window name.
- Invoke the document.open method.
- Click the Back, Forward, Refresh, or Home button.
Within a SharePoint publishing page (the context I'm writing this for), you can check many things using JavaScript, including whether a page is in edit mode. SP.Ribbon.PageState.Handlers.isInEditMode() evaluates as true/false depending on, you guessed it, whether or not the page is in edit mode. Crazy times.
However, you must be careful to test the use of functions like this, as SharePoint commonly restricts the loading of unnecessary JavaScript functions to minimise the JavaScript payload. The whole SP.Ribbon function set only gets loaded when the ribbon is being displayed (what a shock) and so I've thrown in a check to see whether or not the ribbon JS is loaded prior to trying to do anything with it.
On top of this, there are some elements of the ribbon that a user can click that actively preserve or save any changes that might have been made on the page whilst it was in edit mode, namely Save, Check-in and Publish - it would be odd to throw a warning to the user about leaving the page in a context where they've just asked to save or publish it, so I've filtered that out based on the object passed through the onbeforeunload event.
Anyway, that's probably enough chatter, here's the final commented code. I placed this into the PlaceHolderAdditionalPageHead content placeholder of the page layout for article publishing pages that my customer's users work with:
And there you have it. The onbeforeunload event handles the display of the message box to the user including the two options they are given, it'll look like this (in Chrome):<script type="text/javascript">//<![CDATA[//hook into onbeforeunloadwindow.onbeforeunload = function (e) {//make sure that SP.Ribbon functions are loadedif(SP.Ribbon){//check if were in edit modeif(SP.Ribbon.PageState.Handlers.isInEditMode()){var e = e || window.event;//check to make sure we ignore save, checkin and publishif(e.srcElement.activeElement.id != "Ribbon.EditingTools.CPEditTab.EditAndCheckout.SaveEdit-SelectedItem"&& e.srcElement.activeElement.id != "Ribbon.EditingTools.CPEditTab.EditAndCheckout.Checkout-SelectedItem"&& e.srcElement.activeElement.id != "Ribbon.PublishTab.Publishing.Publish-SelectedItem"){//configure this message how you likevar msg = "Do you really want to leave this page? You will lose any unsaved changes if you do!"// For IE and Firefoxif (e) {e.returnValue = msg;}// For Safari / chromereturn msg;}}}};//]]></script>
If they click the "Stay on this Page" button, then the event is cancelled and the browser window state remains unchanged. If they hit "Leave this Page" then, well, I'll let you work that one out...
Caveat
One scenario where this could prove annoying (unless you're going to add some more 'ignore this type of event' clauses into your script) is where users will be adding a lot of web parts to pages as they cause a page refresh, which triggers the script as things currently stand. I'm not in that scenario at the moment so have ignored it. Doubtless it is the first bit of feedback I'll get once it's rolled out and I'll have to make it better. For what it's worth, inserting images, embedding video and things like that do not trigger the script, which is nice.
- rob
No comments:
Post a Comment