window event that you want to listen for is
beforeunload. You might bind to the event like so:
$(window).bind 'beforeunload', -> 'Are you sure you want to close this window?'
Return a string from the function. This string will be displayed in a browser-native confirm-style dialogue.
beforeunload in Ember
Now, if your app is controlled by Ember, you’re likely going to want it to handle bindings such as this from within Ember. There are several places you might want to put this code. Your decision will depend on the needs of your app. You can put it in a route or controller. The scope of that route or controller should match the scope for which you want the
beforeunload event to be caught. In other words, if you want
beforeunload to be caught for the entire app, put the listener in
ApplicationController). Or if you wanted a more limited scope, put the listener in a more specific route.
For instance, if you wanted to save a blog post when the user closes a tab, you might implement something like this:
App.BlogEditController = Ember.ObjectController.extend saveBeforeClose: (-> $(window).bind 'beforeunload', => @get('model').save() 'Are you sure you want to leave unsaved work?' ).on 'init'
In practice, the UX for this kind of feature can be tricky. If someone closes a tab, odds are they meant to and don’t want to be bothered with a confirm dialogue asking them to reiterate their decision. On the other hand, maybe the didn’t realize the implications of closing out the app, such as in the case of unsaved work, and they become very grateful for the reminder to stay and save something.
In the case of the last example, it would be cool if we could detect the window closing, save the work automatically, and let the user close the tab as they indicated without interruption. For asynchronous actions such as network requests, this is problematic. The request will not finish before the browser has trashed the whole window. In cases such as this, you will need to synchronize your requests to block before finishing execution of the
beforeunload event callback.
So, does this work for you? How might you make it better?