2015-02-18 17 views
12

Chciałbym zacząć od stwierdzenia, że ​​jestem nowy w jQuery i podejrzewam, że robię coś głupiego, więc mam nadzieję, że będzie to bardzo proste dla kogoś.jQuery. When(). Done() nie działa

Próbuję dodać przesuwne podmenu mobilne do mojej witryny. Chcę uzyskać efekt akordowy, dzięki któremu po kliknięciu jednego łącza nadrzędnego otworzy się podrzędne menu podrzędne i zamkną się wszystkie inne podmenu. Problem polega na synchronizacji czasu - podmenu podrzędne otwiera się, a następnie zamyka ponownie przez zresetowanie wszystkich podmenu. Zakładam, że odpowiedzią jest używanie odroczeń, ale wszystko, co wypróbowałem, zawiodło. To jest kod (obecnie nie działa):

function ResetMenu(){ 
    jQuery(".mobile-menu").find(".sub-menu").slideUp(100); 
    jQuery(".mobile-menu").find(".menu-item-has-child").removeClass("open"); 
}; 

function OpenSubmenu(){ 
    jQuery(this).next("ul").slideDown(100); 
    jQuery(this).parent().addClass("open"); 
}; 

jQuery("li.menu-item-has-children > a").click(function(){ 

    if(jQuery(this).parent().hasClass("open")){ 
     jQuery(".mobile-menu").find(".sub-menu").slideUp(100); 
     jQuery(this).parent().removeClass("open"); 
    } else { 
     jQuery.when(ResetMenu()).done(OpenSubmenu()); 
    } 
    return false; 
}); 

Każda pomoc zostanie bardzo doceniona. Dziękuję Ci!

Ronel

+1

'ResetMenu' potrzeby powrotu obietnicę dla tej pracy .. –

Odpowiedz

22

Jest to częsty błąd w jaki sposób korzystać z jQuery.when().

wymaga obietnic jako argumentów. Nie ma magicznej mocy, aby wiedzieć, kiedy funkcje, które przekazujesz, są w jakiś sposób zrobione. Te funkcje MUSZĄ zwracać obietnice, które zostaną rozwiązane lub odrzucone, gdy podstawowy kod zostanie wykonany, a następnie możesz przekazać te obietnice do jQuery.when().

Twoja funkcja ResetMenu() nie zwraca niczego, więc Twój jQuery.when() nie czeka na nic. Natychmiast uruchamia procedurę obsługi .then() (która wygląda tak, jak tego nie chcesz).

Tak więc, w tej linii:

jQuery.when(ResetMenu()).done(OpenSubmenu()); 

ResetMenu() musi powrócić obietnicę dla jQuery.when() wiedzieć kiedy to jest zrobione.

Można naprawić ResetMenu() pracować w ten sposób robiąc to:

function ResetMenu(){ 
    return jQuery(".mobile-menu").find(".sub-menu").slideUp(100).promise().then(function() { 
     // remove this class when the animation has completed 
     jQuery(".mobile-menu").find(".menu-item-has-child").removeClass("open"); 
    }); 
}; 

A potem dalej, trzeba zmienić sposób przekazać funkcję .done() to oba czyni to tylko odniesienie funkcyjny mogą być wykonywane później i wiąże odpowiednie this wartość do niego:

jQuery.when(ResetMenu()).done(OpenSubmenu.bind(this)); 

pamiętać, że .bind(this) zakłada, że ​​this jest odpowiednia wartość. Możesz przekazać dowolną wartość, która jest tam poprawną wartością i która stanie się wartościąwewnątrz OpenSubmenu(), gdy zostanie wykonana.

+3

dobrej jednym z' 'then' zwrotnego ... (.done OpenSubmenu()); 'powinno być' .done (OpenSubmenu); ' –

+0

@ArunPJohny - good catc h. Naprawiony. – jfriend00

+0

Dziękuję bardzo, że rozwiązuje. Kiedy część. Niestety .done part nadal nie działa - zdałem sobie sprawę, że funkcja OpenSubmenu potrzebuje parametru, w szczególności jQuery (this) musi zostać przekazana z funkcji zdarzenia click. Jednak gdy próbowałem używać .done (function() {OpenSubmenu (jQuery (this));}); wszystko znowu się nie udaje. Podejrzewam, że dzieje się tak dlatego, że przekazuję funkcję zamiast odwołania do funkcji, jak na twój ostatni komentarz, ale nie widzę, jak inaczej można to zrobić. Czy możesz dodać to do swojej odpowiedzi? – Ronelz

3

Po przejechaniu non obietnica obiekt do $.when() wywołania zwrotne przekazywane do done() jest wywoływana natychmiast, w przypadku gdy ResetMenu nie jest coś się OpenSubmenu powrocie nazywa się natychmiast, tam jest inny problem również - nie powinno się powoływać OpenSubmenu bezpośrednio (dodając ()), trzeba przekazać referencję do funkcji done()

function ResetMenu() { 
    jQuery(".mobile-menu").find(".menu-item-has-child").removeClass("open"); 
    return jQuery(".mobile-menu").find(".sub-menu").slideUp(100).promise(); 

}; 

function OpenSubmenu() { 
    jQuery(this).next("ul").slideDown(100); 
    jQuery(this).parent().addClass("open"); 
}; 

jQuery("li.menu-item-has-children > a").click(function() { 

    if (jQuery(this).parent().hasClass("open")) { 
     jQuery(".mobile-menu").find(".sub-menu").slideUp(100); 
     jQuery(this).parent().removeClass("open"); 
    } else { 
     jQuery.when(ResetMenu()).done(OpenSubmenu); 
    } 
    return false; 
});