Search code examples
jquery-mobilebackbone.jsasynchronousheaderfooter

Backbone and jQuery Mobile : same header on all pages


I'm in charge of the development of a web application.

I did a lot of research and I finally decided to develop this webapp with Backbone and jQuery Mobile. As you certainly know, there are some routing conflicts between jQuery Mobile and BackBone. I decided to use Backbone routing so I disabled jQM routing thanks to this tutorial : http://coenraets.org/blog/2012/03/using-backbone-js-with-jquery-mobile/.

I started to build a sample application (without jQM) with only 3 views and a router. It works perfectly. You can run this application here. I voluntary put jQuery Mobile HTML tags for the next part.

Now, I would like to do the same thing with jQuery Mobile : keep the same header for all templates. The previous tutorial really helped me but I'm still confused about the DOM system of jQM.

What I've tried is here :

index.html (pastebin.com/PcHDaZ2P)

<head>
    <title></title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="css/jquery.mobile-1.0.1.min.css"/>

    <!-- The Templates -->
    <script type="text/template" id="home">
            <p>This is Home page.</p>
            <ul data-role="listview"  data-inset="true">
                <li><a href="#page1">Page 1</a></li>
                <li><a href="#page2">Page 2</a></li>
            </ul>
    </script>

    <script type="text/template" id="page1">
            <p>This is Page 1.</p>
            <ul data-role="listview" data-inset="true">
                <li><a href="#">Home</a></li>
                <li><a href="#page2">Page 2</a></li>
            </ul>
    </script>

    <script type="text/template" id="page2">
            <p>This is Page 2.</p>
            <ul data-role="listview" data-inset="true">
                <li><a href="#">Home</a></li>
                <li><a href="#page1">Page 1</a></li>
            </ul>
    </script>

    <!-- The Scripts -->
    <script src="lib/jquery-1.7.1.min.js"></script>
    <script src="js/jqm-config.js"></script>
    <script src="lib/jquery.mobile-1.0.1.min.js"></script>
    <script src="lib/underscore-min.js"></script>
    <script src="lib/backbone-min.js"></script>
    <script src="js/main.js"></script>
</head>

<body>
    <!-- The fixed header -->
    <div data-role="header">
            <a href="#" data-icon="home">Home</a>
            <h1>Header</h1>
    </div>

    <!-- THE CONTENT FOR THE TEMPLATES -->
    <div data-role="content" id="app-content">
    </div>
</body>

main.js (pastebin.com/2GXurpby)

window.HomeView = Backbone.View.extend({

    template:_.template($('#home').html()),

    render:function (eventName) {
        $(this.el).html(this.template());
        return this;
    }
});

window.Page1View = Backbone.View.extend({

    template:_.template($('#page1').html()),

    render:function (eventName) {
        $(this.el).html(this.template());
        return this;
    }
});

window.Page2View = Backbone.View.extend({

    template:_.template($('#page2').html()),

    render:function (eventName) {
        $(this.el).html(this.template());
        return this;
    }
});

var AppRouter = Backbone.Router.extend({

    routes:{
        "":"home",
        "page1":"page1",
        "page2":"page2"
    },

    initialize:function () {
        // Handle back button throughout the application
        $('.back').live('click', function(event) {
            window.history.back();
            return false;
        });
        this.firstPage = true;
    },

    home:function () {
        console.log('#home');
        this.changePage(new HomeView());
    },

    page1:function () {
        console.log('#page1');
        this.changePage(new Page1View());
    },

    page2:function () {
        console.log('#page2');
        this.changePage(new Page2View());
    },

    changePage:function (page) {
        console.log($(page.el));
        $(page.el).attr('data-role', 'page');
        page.render();
        $('#app-content').append($(page.el));
        var transition = $.mobile.defaultPageTransition;
        // We don't want to slide the first page
        if (this.firstPage) {
            transition = 'none';
            this.firstPage = false;
        }
        $.mobile.changePage($(page.el), {changeHash:false, transition: transition});
    }

});

$(document).ready(function () {
    console.log('document ready');
    app = new AppRouter();
    Backbone.history.start();
});

But it doesn't work.

So, can you help me to realize this system : have the same header for all templates and just a variable content in the app-content div with jQuery Mobile ?


Solution

  • Okay, I've finally found the solution by using trigger event.

    I just want same header and footer on each page (or template) by using Backbone and jQuery Mobile. This is in fact pretty simple but I was on the wrong way when I researched.

    The following is 2 simples applications ; the only difference is here :

    The normal app (working jsFiddle : http://jsfiddle.net/QLu4P/)

    app.Views.Main = Backbone.View.extend({
    initialize : function(params)
    {
        // ...
    },
    
    render : function()
    {
        // ...
        $(this.el).html(renderedContent);
        // ...
    }
    

    });

    The app using jQuery Mobile (working jsFiddle : http://jsfiddle.net/q5TX7/)

    app.Views.Main = Backbone.View.extend({
    initialize : function(params)
    {
        // ...
    },
    
    render : function()
    {
        // ...
        $(this.el).html(renderedContent).trigger('create');
        // ...
    }
    

    });

    I've just added .trigger('create') on $(this.el).html(renderedContent) ! I've purposely put jQuery Mobile tags on the 2 apps in order to highlight that this is almost the same code.

    Hope it gonna be useful.