2011-08-24 12 views
5

Używam backbone.js (0.5.3) z JQueryMobile (1.0 beta 2). Wiem, że istnieją konflikty routingu Korzystając z tych bibliotek razem, i chciałbym wiedzieć, czy istnieje rozwiązanie, aby z nich korzystać:Trasowanie Backbone.js i jQueryMobile bez hackowania lub innego routera

Mój problem jest bardzo podobny do opisanego w tym poście: jquery-mobile backbone.js routing

Kiedy zgłoszę żądanie, kod kręgosłupa render odpowiedniego widoku szkieletu zostanie wywołany przed całkowitym załadowaniem nowej strony jQuery. Próbuję uczynić mój html wygenerowany kod w elemencie $(".ui-page-active") DOM kierować stronę, która jest generowana przez jQueryMobile (lub stronę, która jest „włączony”):

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

Ale atrybut el jest pusty, gdy Metoda renderowania jest wywoływana, ponieważ komórka jquery nie wyrenderowała jeszcze domeny ...

Dzięki za pomoc!

Aktualizacja

Addy Osmani wydaje się, że odpowiedź na moje pytanie :) ale to będzie dla kolejnej części jego (wielkiej) Samouczek: http://msdn.microsoft.com/en-us/scriptjunkie/hh377172.aspx

Odpowiedz

10

Ok rozwiązaniem jest wyłączenie funkcji ładowania jQuery Mobile ajax i ręczne wywołanie metody $.mobile.changePage.

strona HTML:

<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> 

Wtedy gdy nowa trasa jest wyzwalany, najpierw zbudować mój nowy „jQuery stronę płótna” w szkielecie View konstruktora, dołączyć go do dokumentu HTML body i ustawić mój el Wyświetl element do tego nowego div:

Szkielet.Zobacz

$("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") 

A w metodzie render:

// 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"); 

działa jak czar i bez zbędnych sztuczek :)


Oto mój pełny widok Backbone jeśli to może pomóc każdy:

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") 
+0

na którym wydarzeniu uruchamiasz swoją aplikację? $ ('document'). ready() lub $ (document) .bind ('pageinit')? Próbowałem postępować zgodnie z Twoimi sugestiami, ale napotkasz błędy routera szkieletowego. – fbuchinger

+1

Uwaga: $ (document) .bind ("mobileinit" ... wywołanie musi być wykonane po załadowaniu jquery i PRZED załadowaniem jquery mobile – pws5068

1

To może być trochę Długi, ponieważ nie mam sposobu, aby go przetestować, ale spróbuj rozszerzyć historię Szkieletów i spraw, by wysłuchał zdarzenia tworzenia, zanim uruchomi kod. Więc ..

MyHistory = Backbone.History.extend({ 
    loadUrl : function(fragmentOverride) { 
     var fragment = this.fragment = this.getFragment(fragmentOverride); 
     var matched = _.any(this.handlers, function(handler) { 
     if (handler.route.test(fragment)) { 
      //This is the only change from core code.. 
      //We're just wrapping it into a callback. 
      $('.ui-page-active').one('pagecreate', function() { 
       handler.callback(fragment); 
      }); 
      return true; 
     } 
     }); 
     return matched; 
    } 
}); 
MyHistory.start(); 

To może zrobić, a przynajmniej dostać się na właściwą ścieżkę, mam nadzieję.

+0

prostu próbowałem tego, ale 'handler.callback (fragment) 'nigdy nie jest wywoływane ... wydaje się, że zdarzenie' pagecreate' nie jest wywoływane, dopóki Backbone nie wykonał wywołania zwrotnego (odpowiednia funkcja w routerze). W tym przypadku jQuery czeka na kręgosłup, kręgosłup czeka na jQuery, a jego impas ... – Tricote

1

z jQuery 1.2.0, wyłącz Ajax i linkBinding

$(document).bind("mobileinit", function(){ 
    $.mobile.ajaxEnabled = false; 
    $.mobile.hashListeningEnabled = false; 
    $.mobile.linkBindingEnabled = false; 
    $.mobile.pushStateEnabled = false; 
    }); 

po, który z normalnych tras kręgosłup, można połączyć ID z

<a href="#id" onclick="window.app_router.navigate('new', true)">Report</a> 
+0

Tak! Używam tylko jQuery mobile, aby uzyskać poprawne wsparcie nagłówka/stopki. wyciąć jednorożca, który łamał moją witrynę. – Jake