source: Dev/trunk/src/client/qed-client/app/Router.js @ 515

Last change on this file since 515 was 515, checked in by hendrikvanantwerpen, 11 years ago

Also prevent page close when content is dirty.

File size: 4.6 KB
Line 
1define([
2    "./Content",
3    "./Path",
4    "dojo/_base/declare",
5    "dojo/_base/event",
6    "dojo/_base/lang",
7    "dojo/hash",
8    "dojo/on",
9    "dojo/topic",
10    "require"
11], function(Content, Path, declare, event, lang, hash, on, topic, require) {
12
13    var Router = declare(null,{
14        _started: false,
15        _routes: null,
16        _previousHash: null,
17        _beforePreviousHash: null,
18
19        constructor: function() {
20            this._routes = [];
21        },
22        startup: function() {
23            if ( this._started ) { return; }
24            Content.startup();
25            this._started = true;
26            if ( hash() === "" ) {
27                hash(Path.getDefault());
28            }
29            this._handleHashChange(hash());
30            window.onbeforeunload = function(evt) {
31                var msg = Content.isDirty() ?
32                        "Unsaved changes, leave anyway?" :
33                        null;
34                evt.returnValue = msg;
35                return msg;
36            };
37                        topic.subscribe("/dojo/hashchange",
38                            lang.hitch(this,'_handleHashChange'));
39        },
40        register: function(route) {
41            if ( this._started ) {
42                console.warn('Registering routes after startup() is called is discouraged.');
43            }
44            var callback = this._normalizeCallback(route);
45            if ( callback ) {
46                if ( route.path ) {
47                    route.callback = callback;
48                    route.path = new Path(route.path);
49                    this._routes.push(route);
50                } else {
51                    this._defaultCallback = callback;
52                }
53            } else {
54                console.warn("Route "+(route.path||"default")+" has no action.");
55            }
56        },
57        _normalizeCallback: function(route) {
58            var self = this;
59            var callback = null;
60            if ( route.callback ) {
61                callback = function(params){
62                    Content.set(route.callback(params));
63                };
64            } else if ( route.redirect ) {
65                callback = function(params){
66                    self.go(route.redirect);
67                };
68            } else if ( route.constructor ) {
69                callback = function(params){
70                    Content.set( new route.constructor(params) );
71                };
72            }
73            return callback;
74        },
75        _handleHashChange: function(newHash) {
76            if ( this._previousHash === newHash ) {
77                return false;
78            }
79            if ( Content.isDirty() ) {
80                if ( !confirm("Unsaved changes, leave anyway?") ) {
81                    var probablyBack = this._beforePreviousHash === newHash;
82                    // if we think we go backwards, we re-add the history
83                    // entry, otherwise we reset the current one,
84                    // resulting in minor annoyance of double back
85                    // behaviour.
86                    hash(this._previousHash,!probablyBack);
87                    return false;
88                } else {
89                    Content.markClean();
90                }
91            }
92            this._beforePreviousHash = this._previousHash;
93            this._previousHash = newHash;
94            for (var i = this._routes.length-1; i >= 0; i--) {
95                var route = this._routes[i];
96                var params = null;
97                if ((params = route.path.match(newHash)) !== null) {
98                    try {
99                        route.callback(params);
100                    } catch(err) {
101                        console.error("Page change failed with",err,err.stack,err.toString());
102                    }
103                    return true;
104                }
105            }
106            try {
107                this._defaultCallback();
108            } catch(err) {
109                console.error("Default page failed.",err);
110            }
111            return true;
112        },
113        go: function(path,args,replace) {
114            if ( !this._started ) { return; }
115            var newHash = Path.format(path,args);
116            if ( replace === true ) {
117                this._beforePreviousHash = this._previousHash;
118                this._previousHash = newHash;
119            }
120            hash(newHash,replace);
121        },
122        _defaultCallback: function() {
123            require("./Page",function(Page){
124                Content.set(new Page({
125                    templateString: "<div>Requested page not found. Go <a href=\"#"+Path.getDefault()+"\">home</a>.</div>"
126                }));
127            });
128        }
129    });
130
131    return new Router();
132});
Note: See TracBrowser for help on using the repository browser.