Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone.js and jQueryMobile routing without hack or other router

I am using backbone.js (0.5.3) with JQueryMobile (1.0 beta 2). I know there are routing conflicts when using those libraries together, and I would like to know if there is a solution to use them :

  • without hacking into the jquery mobile source code like described in Ben Nolan's pots : http://bennolan.com/2010/11/23/backbone-and-jquery-mobile.html
  • and without using another router like jquerymobile-router (unless there is no other option...)

My problem is quite similar to the one described in this post : jquery-mobile backbone.js routing

When when i make a request, the backbone render code of the corresponding backbone view gets triggered before the new jquery page is fully loaded. I'm trying to render my html generated code in the $(".ui-page-active") DOM element to target the page that is generated by jQueryMobile (or the page that is "activated") :

MyView = Backbone.View.extend({
  el: $(".ui-page-active")
  render: function(){
    console.log(el)
  }
});

But the el attribute is empty when the render method is called, because jquery mobile has not yet rendered the dom...

Thanks for any help !

Update

Addy Osmani seems to have the answer to my question :) but it will be for the next part of his (great) tutorial : http://msdn.microsoft.com/en-us/scriptjunkie/hh377172.aspx

like image 424
Tricote Avatar asked Aug 24 '11 08:08

Tricote


1 Answers

Ok the solution is to disable jQuery Mobile ajax loading feature and call the $.mobile.changePage method manually.

HTML page :

    <script type="text/javascript" charset="utf-8" src="js/mobile/jquery.js"></script>
    <script type="text/javascript">
      $(document).bind("mobileinit", function(){
        $.mobile.ajaxEnabled = false;
        $.mobile.hashListeningEnabled = false;
      });
    </script>
    <script type="text/javascript" charset="utf-8" src="js/mobile/jquery-mobile.js"></script>

Then whenever a new route is triggered, I first build my new "jQuery page canvas" in the Backbone View constructor, append it to the HTML document body and set my el view element to this new div :

Backbone.View

    $("body").prepend("""
      <div id="my-id" data-role="page" class="cloudy-background-mobile">
        <div class="cloudy-header" data-role="header" data-position="fixed"></div>
        <div class="cloudy-content" data-role="content"></div>
      </div>
    """)
    this.el = $("#logs-view")

And in the render method :

// Build the content using undescore.js templating system
this.el.find('.cloudy-content').html(this.template({logs : this.collection}));
this.find('.cloudy-header').html(this.template_header({logbook: this.logbook}));

// Change the page using jquery mobile and reapply jquery styles
$.mobile.changePage(this.el, "slide", false, false);
this.trigger( "pagecreate" );

Works like a charm and without any unnecessary hacks :)


Here is my full Backbone View if it can help anyone :

class LogsView extends Backbone.View
  constructor: (options) ->
    super
    $("body").prepend("""
      <div id="logs-view" data-role="page" class="cloudy-background-mobile">
        <div class="cloudy-header" data-role="header" data-position="fixed"></div>
        <div class="cloudy-content" data-role="content"></div>
      </div>
    """)
    @el = $("#logs-view")
    @logbook = options.logbook
    @collection.bind 'reset', @render

    @template = _.template('''
      <ul data-role="listview" data-theme="c" data-inset="true">
        <% logs.each(function(log){ %>
          <li>
            <a href="#logs-<%= log.cid %>"><%= log.getLabel() %></a>
          </li>
        <% }); %>
      </ul>
    ''')

    @template_header = _.template('''
      <h1>Carnets <%= logbook.get('name') %></h1>
      <a href="#logbook-<%= logbook.cid %>-logs-new" data-icon="plus" class="ui-btn-right">&nbsp;</a>
    ''')

  render: =>
    # Build the content using undescore.js templating system
    @el.find('.cloudy-content').html(@template({logs : @collection}))
    @el.find('.cloudy-header').html(@template_header({logbook: @logbook}))

    # Change the page using jquery mobile and reapply jquery styles
    $.mobile.changePage(@el, "slide", false, false)
    @el.trigger( "pagecreate" )
like image 195
Tricote Avatar answered Nov 02 '22 04:11

Tricote