Yacine's

JMVC + JQM improved dispatch

In my previous example, I used an eval to load a page controller from the jQuery.fn  name space. Here is a much better version of that code which has the added benefit of allowing access to the instance of my controller:

1
2
3
4
5
6
7
8
If ( typeof MyApp.Pages[pageName] === 'function') {
    // don't really need the element passed here per this example's controller, will check if needed.
    pageInstance  = new MyApp.Pages[pageName]($('body'));
    pageInstance.view.done( function ( htmlOutput ) {
        $('body').append(htmlOutput);
        $('#' + pageName).page();
        $.mobile.changePage( $('#' + pageName) );
    }

On the controller side, the init method becomes much simpler than I had originally written:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
 * @class MyApp.Pages.Frontpage
 */
$.Controller('MyApp.Pages.Frontpage',
    /** @Static */
    {
        defaults : {
            itemsPerPage : 20,
            currentPage : 1
        },
        pluginName: 'frontpage'
    },
    /** @Prototype */
    {
        /**
         * Downloads and renders a full page of blog posts
         */
        init : function() {
            this.view = $.View("my_app/pages/views/frontpage.ejs", {
                items: MyApp.Models.BlogPost.findAll({
                    start : (this.options.currentPage-1)
                            * this.options.itemsPerPage,
                    count : this.options.itemsPerPage
                })
            });
        }
    }
); // End of controller

My full bootstrap method now looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
function() {
    // intercept changePage events to inject our controllers as needed (dispatch)
    $(document).bind( "pagebeforechange", function( e, data ) {
        // we only handle url changes
        if ( typeof data.toPage === "string" ) {
            // We are being asked to load a page by URL
            var u = $.mobile.path.parseUrl( data.toPage ),
                re = /^\#([a-zA-Z]+)$/; // TODO $.route

            if (u.hash.search(re) !== -1 && $(u.hash).length == 0) {
                var pageName = re.exec(u.hash);
                pageName = pageName[1];
                if(pageName === 'splah') {
                    return false;
                }
                // ucwords - ignore as it will be replaced by using $.route
                controllerName = pageName.replace(/^([a-z])|\s+([a-z])/g, function (str) {
                    return str.toUpperCase();
                });
                if (typeof MyApp.Pages[controllerName] === 'function') {
                    var $instance = new MyApp.Pages[controllerName]($('body'));
                    $instance.view.done(function (htmlOutput){
                        // add the rendered output to the body (could also be done in the controllers instead)
                        $('body').append(htmlOutput);
                        $('#' + pageName).page(); // jQuery Mobile magic decoration
                        // passing an object skips the dispatch and just shows the page
                        $.mobile.changePage($('#' + pageName));
                    });
                    e.preventDefault();
                }
            }
        }
    });
    $('#splash').fadeIn(500);
    setTimeout(function () {
        $.mobile.changePage('#frontpage');
    }, 500);
});

I’ll flesh out the full updated integration when I get home, but i am now close to my ideal setup and my full app is working as expected from start to finish. Among my recent changes are the use of partials, routes, pagination, API service auth (with caveats) and of course testing and documentation.

Stay tuned!

Share

One ResponseLeave one →

  1. Johannes Neugschwentner

     /  February 19, 2012

    lovely! hope this and the previous posts get me started, haven’t looked for longer then 2 or 3 hours now, but this is the sweetest I found so far :)
    It also possibly gives me a hint as to my little prob with jqm-multipages —- http://stackoverflow.com/questions/9151351/jquerymobile-woes-1-0-1-not-working-properly-in-eclipse-adt-android-simula
    —-
    (I think the magic jqm command “page()” could do the trick)

    Reply

Leave a Reply

Additional comments powered by BackType