2012-01-30 13 views
9

Tak więc używam Jquery mobile z wielkim sukcesem, z wyjątkiem jednego problemu. Teraz za każdym razem, gdy użytkownik przegląda dynamiczną stronę z treścią, niezależnie od zawartości, zawsze jest przycisk u dołu, który po kliknięciu wysyła treść pod wskazany adres; działa świetnie. Po pierwszym załadowaniu strony kliknięcie powoduje jednorazowe uruchomienie zdarzenia. Podczas drugiej wizyty odpalono ją dwa razy, trzeci 3 razy itd. Dostajesz punkt. Przeszukałem sieć i zaimplementowałem każdą poprawkę, na jaką mogłem natknąć się, np. Używając "strony" zamiast "pageinit", wiążąc, rozłączając, usuwając div, wyłączając buforowanie w DOM, ale nic nie działa. Jedynym sukcesem, jaki udało mi się uzyskać, jest użycie kliknięcia .one(), ale po ponownym kliknięciu musi zostać uruchomiony. Oto struktura. Muszę .js pliki, które ładują się z tym każdy, aby rozpocząćJquery mobile .click wypalanie wiele razy na nowej stronie wizyta

$("#page").live("pageinit", function() { 

Teraz miałem z funkcji e-mail i inne rzeczy w jednym pliku, ale to sprawia, że ​​łatwiej jest je rozdzielić i słyszałem to nie ma znaczenia. Teraz tutaj jest funkcja o nazwie e-mail w pageinit

$('.eb').live('click', function() { 
     var id = $('.eb').attr('id'); 
     var to = $('#recipient').val(); 
     var message = $('#email').html(); 

     var atpos = to.indexOf("@"); 
     var dotpos = to.lastIndexOf("."); 
     if (atpos < 1 || dotpos < atpos + 2 || dotpos + 2 >= to.length) { 
      alert('Please enter a valid email address!'); 
      return false; 
     } 

     if(to.length == 0) { 
      alert('Please enter a valid email address!'); 
      return false; 
     } 

     $.mobile.showPageLoadingMsg(); 

     $.post('./services/service.email.php', { id: id, to: to, message: message}, function(data) { 
      if(data.success == true) { 
       $.mobile.hidePageLoadingMsg(); 
       alert('Your recipe has been sent!'); 
       $('#recipient').val(''); 
       return true; 
      } 

      if(data.success == false) { 
       if(data.fail == 1) { 
        alert('An error has occured sending your recipe. Try again soon!'); 
        return false; 
       } 

       if(data.fail == 2) { 
        alert('Please enter a valid email address!'); 
       } 
      } 
     }, 'json'); 
      return false; 
    }); 

wszystko działa bez zarzutu z wyjątkiem bieżących wypalania .click na każdej nowej stronie. Czy ktoś może mnie poprowadzić we właściwym kierunku?

Odpowiedz

2

I rozwiązać ten problem poprzez realizację był z samego div, #page. Ta strona została załadowana dynamiczną zawartością, ale identyfikator nigdy nie był taki, więc gdzieś w kolejce był gdzieś zbuforowany i był uruchamiany przyrostowo przy każdej nowej wizycie. Właśnie dodałem kod PHP, aby utworzyć unikalny identyfikator div na każdym załadowaniu strony.

<?php $id = uniqid() ?> 
<div id="<?php echo $id; ?>">CONTENT</div> 

Rozwiązało to problem i uruchamia się tylko raz, niezależnie od tego, jak strony mogą się przeładować.

+4

Ten proces pozostawia za sobą wszystkie rodzaje powiązań zdarzeń, które nie są konieczne (im dalej użytkownicy zobaczą, tym wolniej będzie działać, ponieważ właśnie ładujesz coraz więcej delegowanych procedur obsługi zdarzeń, które muszą być sprawdzane za każdym razem, gdy zdarzenie bąbelkuje DOM). Twój problem polegał na regularnej pułapce pracy z dynamiczną treścią, a Ty byłeś zbyt liberalny ze swoimi powiązaniami z wydarzeniami. Prawdziwą poprawką jest zaprzestanie używania delegowanych procedur obsługi zdarzeń tam, gdzie nie są one konieczne. Cieszę się, że coś wymyśliłeś, ale to nie jest dobra odpowiedź. – Jasper

13

Od wersji jQuery 1.7 metoda .live() jest przestarzała. Użyj .on(), aby dołączyć programy do obsługi zdarzeń.

Jeśli używasz wersji 1.7+, spróbuj odłączyć zdarzenie kliknięcia najpierw za pomocą .off().

$('.eb').off('click').on('click', function() { 
// ... 
}); 

jeśli trzeba użyć .live() można rozpiąć zdarzenia z .die()

$('.eb').die('click').live('click', function() { 
// ... 
}); 

lub lepszego wykorzystania .delegate() i .undelegate() un elementu nadrzędnego:

$(document).undelegate('.eb', 'click').delegate('.eb', 'click', function() { 
// ... 
}); 
+0

jQuery Mobile nadal jest dostarczane z jQuery Core 1.6.4, który nie ma '.on()', ale '.delegate()' jest nadal preferowany w stosunku do '.live()'. – Jasper

+0

Edytowałem swoją odpowiedź i dodałem przykład dla '.delegate()' – Ingemar

+1

OK, kilka problemów. ** 1) ** '$ ('. Eb'). On (" kliknięcie "to nie to samo, co użycie' .live() ',' $ (document) .on ("kliknięcie", ".eb" , function() {...}) 'jest takie samo jak' .live() '. Sposób w jaki używasz' .on() 'jest taki sam jak' .bind() '. ** 2) * * Również w jQuery Mobile zazwyczaj delegujesz zdarzenia z elementu 'document', ponieważ jest to element ** only ** gwarantowany w DOM w dowolnym momencie. – Jasper

10

Wystarczy przesunąć imprezę click kod obsługi poza kodem obsługi zdarzenia pageinit w następujący sposób:

$(document).delegate("#page", "pageinit", function() { 


}); 
$(document).delegate('.eb', 'click', function() { 
     var id = $('.eb').attr('id'); 
     var to = $('#recipient').val(); 
     var message = $('#email').html(); 

     var atpos = to.indexOf("@"); 
     var dotpos = to.lastIndexOf("."); 
     if (atpos < 1 || dotpos < atpos + 2 || dotpos + 2 >= to.length) { 
      alert('Please enter a valid email address!'); 
      return false; 
     } 

     if(to.length == 0) { 
      alert('Please enter a valid email address!'); 
      return false; 
     } 

     $.mobile.showPageLoadingMsg(); 

     $.post('./services/service.email.php', { id: id, to: to, message: message}, function(data) { 
      if(data.success == true) { 
       $.mobile.hidePageLoadingMsg(); 
       alert('Your recipe has been sent!'); 
       $('#recipient').val(''); 
       return true; 
      } 

      if(data.success == false) { 
       if(data.fail == 1) { 
        alert('An error has occured sending your recipe. Try again soon!'); 
        return false; 
       } 

       if(data.fail == 2) { 
        alert('Please enter a valid email address!'); 
       } 
      } 
     }, 'json'); 
      return false; 
    }); 

Podczas korzystania delegacji zdarzeń nie chcą wiązać się wewnątrz innej obsługi zdarzeń, ponieważ za każdym razem, obsługi zdarzeń pożary będziesz ponownego wiązania (i kiedy przekazać obsługi zdarzeń są delegowane do życia DOM).

Można również użyć .bind() zamiast .live() (to moja preferowana metoda):

$(document).delegate("#page", "pageinit", function() { 
    $('.eb').bind('click', ...); 
}); 

Można zauważyć, że obie moje przykłady zmienić out .live() dla .delegate() jak to działa nieco szybciej, nawet gdy delegowanie od element document. .delegate() s prawdziwą siłą jest to, że można wybrać element główny zamiast wiązać się z elementu document: http://api.jquery.com/delegate

+0

Próbowałem zarówno rozwiązania, jak i Ingemar, a oba zapobiegały fantastycznym pożarom. Problem polega na tym, że zachowanie jest tak sporadyczne, że nie rozumiem. Klikam w niego, jeśli wystrzeli, znowu go nie kliknę, kliknij 3 razy, gdy się odpali, kliknij raz, gdy wystrzeli ..... Cóż, to dziwne zachowanie. – Naterade

+0

Powyższy kod nie wyzwoli żadnych wielokrotnych pożarów i jeśli zostanie umieszczony w zasięgu globalnym, powinien być dostępny dla każdego zdarzenia "kliknięcia" uruchamianego w elementach '.eb'. Jeśli nadal masz problemy, być może wysłałeś moją poprawkę w niewłaściwym zakresie lub wystąpił błąd w innym miejscu kodu. Aby sprawdzić błędy, otwórz konsolę delevoper (prawie zawsze "F + 12"). – Jasper

+0

Uratowałeś mi godziny! Dziękuję Ci! – Michal

0

Jeśli podejrzewasz, że formularz (na przykład wyskakujący formularz) tworzy wiele stron po przesłaniu, spróbuj dodać dane-ajax = "false" do elementu formularza każdego formularza. To rozwiązało mój problem.

Powiązane problemy