source: Dev/branches/rest-dojo-ui/client/rft/content.js @ 388

Last change on this file since 388 was 347, checked in by hendrikvanantwerpen, 13 years ago

[Client] Merged mockup into pages/ folder.
[Client] Make client more robust when pages have empty lines or multiple root nodes.

File size: 7.4 KB
RevLine 
[264]1/** rft/ui/content - Load page content
2 *
3 * The rft/ui/content module is responsible for loading content in the app.
4 * Content is loaded by calling:
5 *    content.goTo('pageId');
6 * The page is then loaded from pages/pageId.html. This should contain one top node.
7 * This top node gets a _Page widget instantiated on it. The template should not
8 * specify another widget on the topnode. A page controller can be specified by
9 * the data-rft-mixin attribute to a class inherited from _PageController.
10 * You can also specify methods in the template in script tags as:
11 *     <script type="rft/method" data-rft-method-name="onVisit|onLeave">
12 *        // code
13 *     </script>
14 * The two relevant events are onVisit and onLeave. After loading and starting
15 * the complete page onVisit is called. Use this to link widgets together and
16 * load any dynamic content not handled by widget logic already.
17 * The event onLeave is called before navigating to another page. If false is
18 * returned from this function, the navigation will be cancelled. You can use
[340]19 * this e.g. to ask confirmation if changed values are not saved.
[264]20 */
[292]21define(['dojo/_base/declare','dojo/_base/connect','dojo/_base/xhr','dojo/_base/json',
22    'dojo/_base/lang','dojo/_base/Deferred','dojo/hash','dojo/dom-attr','dojo/dom-construct',
[311]23    'dojo/io-query','dijit','./util','./ui/_Page'],
[292]24    function(declare,connect,xhr,json,lang,Deferred,hash,attr,domConstruct,uriQuery,dijit,util,_Page){
[257]25        return new (function() {
26            var self = this;
[292]27
[257]28            var HRI = declare(null,{
[260]29                constructor: function() {
[263]30                    this._path = this._fixPath('/');
[257]31                    this._args = {};
32                    if ( arguments.length == 1 ) {
33                        this.hash(arguments[0]);
34                    } else if ( arguments.length == 2 ) {
35                        this.path(arguments[0]);
36                        this.args(arguments[1]);
37                    }
38                },
39                path: function(path) {
40                    if ( path )
41                        this._path = this._fixPath(path);
42                    return this._path;
43                },
44                args: function(args) {
45                    if ( args && lang.isObject(args) )
46                        this._args = args;
47                    return this._args;
48                },
49                hash: function(hash) {
50                    if ( hash && lang.isString(hash) ) {
51                        var parts = hash.split('!');
52                        if ( parts[1] )
53                            this._path = this._fixPath(parts[1]);
54                        if ( parts[2] )
55                            this._args = uriQuery.queryToObject(parts[2]);
56                    }
57                    return '!'+this._path+'!'+uriQuery.objectToQuery(this._args);
58                },
59                _fixPath: function(path) {
60                    if ( !lang.isString(path) || util.isEmptyString(path) ) {
61                        path = "/";
62                    }
63                    if ( path[0] != '/' ) {
64                        path = '/'+path;
65                    }
66                    if ( path[path.length-1] == '/' ) {
67                        path = path + "index";
68                    }
69                    return path;
70                }
[256]71            });
72
[292]73            var currentHri = null;
74            var currentPage = null;
75           
[257]76            function _goTo(hri,replace) {
77                var contentPane = dijit.byId('content');
[263]78                var dfd = new Deferred();
79               
80                // if already there, return
[292]81                if ( currentHri && currentHri.hash() === hri.hash() ) {
[263]82                    dfd.resolve();
83                    return dfd.promise;
[257]84                }
[263]85               
86                // check if we can leave current page
87                if ( currentPage ) {
88                    if ( currentPage.onLeave() === false ) {
[264]89                        // restore hash if changed by hand or back button
[292]90                        hash(currentHri.hash());
[263]91                        dfd.reject();
92                        return dfd.promise;
93                    }
[274]94                    currentPage = null;
[263]95                }
96               
[347]97                function getFirstNode(html) {
98                    var nodeOrFragment = domConstruct.toDom(html);
99                    if (nodeOrFragment instanceof Element) {
100                        return nodeOrFragment;
101                    }
102                    if (nodeOrFragment instanceof DocumentFragment) {
103                        console.warn("Fragment found, will only use first Element");
104                        for (i in nodeOrFragment.childNodes) {
105                            var node = nodeOrFragment.childNodes[i];
106                            if (node instanceof Element) {
107                                return node;
108                            }
109                        }
110                    }
111                    return domConstruct.toDom('<div>No Element found in template.</div>');
112                }
113
[292]114                function mixinArgs(node) {
115                    var props = {};
116                    if ( attr.has(node,'data-dojo-props') ) {
117                        props = json.fromJson(attr.get(node,'data-dojo-props'));
118                    }
119                    lang.mixin(props,{pageArgs:hri.args()});
120                    var jsonStr = json.toJson(props);
121                    attr.set(node,'data-dojo-props',jsonStr.slice(1,jsonStr.length-1));
122                }
123               
[263]124                // update hash
[292]125                currentHri = hri;
126                hash(hri.hash(),replace);
[263]127               
128                // load html
[274]129                var pageUrl = 'rft/pages'+hri.path()+'.html';
[257]130                xhr.get({
[263]131                    url: pageUrl,
[260]132                    failOk: true
[257]133                })
[263]134               
135                // initialize page or create error message
[257]136                .then(function(html){
[347]137                    var rootNode = getFirstNode(html);
[292]138                    mixinArgs(rootNode);
139                    contentPane.set('content',rootNode);
[274]140                    currentPage = dijit.byNode(rootNode);
141                    if ( !currentPage ) {
142                        currentPage = new _Page({},rootNode);
143                    }
[263]144                    dfd.resolve();
[257]145                },function(){
[274]146                    contentPane.set('content',"<div>Page "+hri.path()+" not found.</div>");
[263]147                    dfd.reject();
[257]148                });
[263]149                return dfd.promise;
[256]150            }
151
[257]152            self.initial = function(path,args) {
[292]153                if ( currentHri ) {
[260]154                    var dfd = new Deferred();
[263]155                    dfd.resolve();
[260]156                    return dfd.promise;
[257]157                }
158                if ( hash() ) {
159                    var hri = new HRI(hash());
[260]160                    return _goTo(hri, true);
[257]161                } else {
[260]162                    return _goTo(new HRI(path,args));
[257]163                }
[311]164            };
[257]165
166            self.goTo = function(path,args) {
[260]167                return _goTo(new HRI(path,args));
[257]168            }
169
[292]170            self.getArgs = function() {
171                if ( currentHri ) {
172                    return currentHri.args();
173                } else {
174                    return {};
175                }
[311]176            };
[292]177
[257]178            connect.subscribe('/dojo/hashchange', function(){
179                _goTo(new HRI(hash()));
[256]180            });
[257]181
182        })();
183    });
Note: See TracBrowser for help on using the repository browser.