• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Wyłączyć window.onload przy odświeżeniu DIVa. JS.

0 głosów
138 wizyt
pytanie zadane 25 stycznia 2021 w JavaScript przez Mlorism Użytkownik (580 p.)

Cześć,

Mam na stronie formularz z customowymi sliderami. Gdy go resetuję (by odpalić funkcję, która je na nowo "koloruje") musiałem na nowo wczytać DIV.

 function resetSliders() {
            $("#magic").load(window.location.href + "#magic");
        }

Akurat tu się odwołuję do 1 slidera (bo jak odwołuję do drugiego, lub samego DIVa to nie działa) i to odświeża oba slidery w danym DIV

Niestety to odpala metodę window.onload, którą chciałem tylko użyć przy pierwszym otworzeniu strony. Dlaczego to problem? Bo gdy na stronie klinie się odpowiedni button, to podmienia widoczność 2 DIVów między sobą, a w window.onload mam podpiętą funkcję, która ustawia na "dzień dobry" widoczność konkretnego z nich. 

Czy da się po odpaleniu funkcji  $("#magic").load(window.location.href + "#magic") zrobić tak, by nie odpalało window.onload (ale odpalało ją przy otworzeniu strony po raz 1)? Próbuję wczytać tylko tego jednego DIV z 2 sliderami, a nie chcę odpalać window.onload dla całej strony.

Kod z githuba z całym html, a poniżej jest też js: 

https://github.com/Mlorism/LastTemple/blob/master/LastTemple/Pages/Manage/Armour.cshtml

ps. To projekt w ASP.NET, ale problem jest natury javascriptu.

1 odpowiedź

+1 głos
odpowiedź 25 stycznia 2021 przez ScriptyChris Mędrzec (183,720 p.)
wybrane 25 stycznia 2021 przez Mlorism
 
Najlepsza

W dokumentacji metody load z jQuery nie ma wzmianki o triggerowaniu jakiegokolwiek eventu lub wywołaniu event handlera window.onload. Również w kodzie źródłowym nie widać, by cokolwiek tam wzbudzało jakiś event - ewentualnie, w przekazanym callbacku można samodzielnie wykonać taką akcję (ale w Twoim kodzie tego nie widać). Jesteś pewien, że wywołanie funkcji resetSliders wywołuje metodę window.onload - po czym to stwierdzasz? Przyczyną mogło by być przypisanie nowej wartości do window.location.href, ale Twój kod nie nadpisuje tego property, a jedynie je odczytuje.

Patrząc w kod, w oczy rzuca się użycie location.reload po kliku w przycisk usuwający jakiś przedmiot za pośrednictwem API, co faktycznie przeładuje stronę i tym samym triggeruje eventy takie jak DOMContentLoaded i Load. Pytanie - dlaczego przeładowujesz stronę w takim przypadku, zamiast zaktualizować odpowiednie dane (w tym UI) na stronie na podstawie informacji, które ten endpoint może zwrócić? Trochę mało sensu ma korzystanie z Ajaxa przy jednoczesnym odświeżaniu strony, bo Ajax powstał właśnie po to, aby uniknąć przeładowania strony przy komunikacji z serwerem.

W jakim celu nadpisujesz window.onload wartością undefined? funkcja loadSettings jawnie nic nie zwraca, więc niejawnie zwraca undefined.


Jeśli chcesz odtworzyć stan UI po resecie formularza (a sam reset tego nie robi), to może sklonuj sobie ten fragment DOMu w jego pierwotnym stanie i wstaw go zamiast tego zmodyfikowanego już po resecie?

komentarz 25 stycznia 2021 przez Mlorism Użytkownik (580 p.)

Jesteś pewien, że wywołanie funkcji resetSliders wywołuje metodę window.onload - po czym to stwierdzasz? 

Jak wrzucę dla testu do metody loadSettings() linijkę "alert(komunikat)" to po kliknięciu Reset jest to wywoływane. 

Patrząc w kod, w oczy rzuca się użycie location.reload po kliku w przycisk usuwający jakiś przedmiot za pośrednictwem API, co faktycznie przeładuje stronę i tym samym triggeruje eventy takie jak DOMContentLoaded i Load.

To jest w widoku domyślnym, gdzie tabela, która jest widoczna ma przy każdym itemie przycisk i jak się odświeży strona po usunięciu, to jest wygenerowana tabela od nowa bez usuniętego itemu. To nic mi nie psuje. Jednak rozumiem Ciebie, że lepiej by to inaczej napisać. Chodzi Ci o to by tabelę w JE połączyć z array obiektów i  jakoś usunąć z niej, a zamiast przeładowania strony? Dzięki temu unikniemy obciążania serwera, bo wszystko się wykona po stronie UI?

W jakim celu nadpisujesz window.onload wartością undefined?

Używając window.onload chcę w ten sposób dokonać 2 rzeczy na raz: 
a) ukryć DIV ze formularzem 
b) nakazać narysowanie background dla sliderów (które inaczej pozostaje "statyczne" jak mówi css, w mojej wersji kolor od początku do tego uchwytu się zmienia gradientowo dzięki metodzie setSlider())
c) to co ma zwracać by nie było undefined? Czy mogę osiągnąć to z a) i b) bez skorzystania z window.onload?

 sklonuj sobie ten fragment DOMu w jego pierwotnym stanie

Tylko chcę by stan nie był pierwotny, ale po zastosowaniu metody setSlider()

Bez i z setSlider():

Gdy wrzucę zamiast 

$("#magic").load(window.location.href + "#magic");

2 linijki, które powinny działać:

setSlider("physical");
setSlider("magic");

To niestety nie działa i efekt po resecie formularza wygląda tak:

komentarz 25 stycznia 2021 przez ScriptyChris Mędrzec (183,720 p.)

Jak wrzucę dla testu do metody loadSettings() linijkę "alert(komunikat)" to po kliknięciu Reset jest to wywoływane.  

Patrząc po samym kodzie, nie wiem dlaczego tak się dzieje - musiałbym go debugować. Ale nie widzę tutaj związku, bo praktycznie na początku skryptu przypisujesz do window.onload wartość undefined, więc po całkowitym załadowaniu strony żaden callback nie powinien być wołany, również przy resecie formularza.

Chodzi Ci o to by tabelę w JE połączyć z array obiektów i  jakoś usunąć z niej, a zamiast przeładowania strony? Dzięki temu unikniemy obciążania serwera, bo wszystko się wykona po stronie UI?

Co to jest "JE"?

Mam na myśli, że jeśli usunięcie przedmiotu jest realizowane przez wysłanie Ajax'a na serwer, to możesz wykorzystać fakt, że komunikację z serwerem robisz bez przeładowania strony i po prostu dany element (w tym przypadku chyba wiersz tabeli) usunąć korzystając z DOM API. Co do obciążenia serwera: dokładną odpowiedź na to pytanie uzyskasz, gdy zrobisz pomiary; ale na pewno różnicą na korzyść samego Ajax'a będzie liczba wysłanych requestów: jeden (wysłanie komendy DELETE, która zwróci jakiś wynik) i dalsze procesowanie na froncie w porównaniu do wysłania co najmniej dwóch requestów (znowu DELETE oraz przy ładowaniu strony ponownie będzie wysłany co najmniej jeden request po stronę HTML - reszta w zależności od ustawień cache'u apki).

Używając window.onload chcę w ten sposób dokonać 2 rzeczy na raz:

Ale ten window.onload w obecnej formie nie ma sensu. Teraz jest po prostu niemal na starcie skryptu wołana funkcja loadSettings, która m.in. ustawia slajdery i zwraca undefined do window.onload. Zastąpienie kodu window.onload = loadSettings(); samym loadSettings() nie powinno zrobić różnicy. Innymi słowy, w mojej ocenie ten window.onload w obecnej formie jest tam zbędny i tylko zaciemnia kod.

c) to co ma zwracać by nie było undefined?

Jeśli chcesz podpiąć callback do window.onload, to (zachowując analogię do Twojego obecnego podejścia) funkcja loadSettings (której wynik wywołania przypisujesz do window.onload) powinna zwracać jakąś funkcję (użycie handlera wymaga przypisania funkcji) i to dopiero ona będzie wywołana przy całkowitym załadowaniu strony.

Czy mogę osiągnąć to z a) i b) bez skorzystania z window.onload?

Jeśli a) i b) są wykonane przez wywołanie funkcji loadSettings, to tak - window.onload w obecnej formie jest zbędne (o czym wspomniałem wyżej).

Tylko chcę by stan nie był pierwotny, ale po zastosowaniu metody setSlider()

Zatem sklonuj sobie w wybranym momencie. Chodzi o to, że jeśli potrzebujesz przywrócić stan któregoś elementu w DOM (i jego potomków), to nie musisz odświeżać strony ani pobierać tego elementu Ajax'em. Możesz ten element sklonować w takiej formie, w jakiej jest w danym momencie i później wstawić na stronę (opcjonalnie zastępując nim inny element), gdy masz taką potrzebę. Alternatywnie, co pewnie będzie wymagać większej ilości kodu, możesz przywrócić stan tego elementu i jego potomków ręcznie - modyfikując jego treść, atrybuty i klasy pojedynczo w wybranym momencie. Wstawienie wcześniej sklonowanego elementu jest wygodniejsze. Analogicznie można to porównać z przywracaniem stanu jakiegoś obiektu lub tablicy w JavaScript "na piechotę" (pojedynczych propertisów/elementów) vs wykonanie deep copy przy pomocy kombinacji JSON.parse + JSON.stringify (nie dotyczy obiektów o cyrkularnych referencjach) lub rekrurencyjnego kopiowania propertisów przy pomocy Object.assign lub destrukturyzacji.

komentarz 25 stycznia 2021 przez Mlorism Użytkownik (580 p.)
edycja 26 stycznia 2021 przez Mlorism

Co to jest "JE"?

Wybacz, to literówka chodziło o oczywiście o JS (JavaScript). Dzięki za podpowiedź z node.remove(), wykorzystam.

Zastąpienie kodu window.onload = loadSettings(); samym loadSettings() nie powinno zrobić różnicy. Innymi słowy, w mojej ocenie ten window.onload w obecnej formie jest tam zbędny i tylko zaciemnia kod.

Rozumiem, że zaciemnia. Jako początkujący w JS, nie wiem jak do tego podejść. Jak mam odpalić więc loadSettings() by ustawił mi na początku slidery, skoro nie przez przypisanie do window.onload? Jaki taki kod/pseudokod powinien wyglądać?

Nad klonowaniem poćwiczę, to coś ciekawego i nowego dla mnie.

Udało mi się rozwiązać problem z przeliczaniem kolorów dla sliderów przy resecie. Błędnie myślałem, że przy metodzie onreset kod, który piszę wykona się po tym co kryje się pod metodą resetującą. Okazuje się że by uzyskać taki efekt muszę dać lekkie opóźnienie.

Więc zamiast: 

function resetSliders() {
           $("#magic").load(window.location.href + "#magic");
       }

Jest i działa lepiej (nie generuje dodatkowych problemów):

 function resetSliders() {
            setTimeout(function () {
                setSlider("physical");
                setSlider("magic");
            }, 100);            
        }

 

komentarz 26 stycznia 2021 przez ScriptyChris Mędrzec (183,720 p.)

Rozumiem, że zaciemnia. Jako początkujący w JS, nie wiem jak do tego podejść. Jak mam odpalić więc loadSettings() by ustawił mi na początku slidery, skoro nie przez przypisanie do window.onload? Jaki taki kod/pseudokod powinien wyglądać?

Napisałem w poprzednim komentarzu:

Zastąpienie kodu window.onload = loadSettings(); samym loadSettings() nie powinno zrobić różnicy. 

Więc po prostu 

// zamiast 
window.onload = loadSettings();

// zapisz
loadSettings();

Okazuje się że by uzyskać taki efekt muszę dać lekkie opóźnienie.

Ojoj, użycie setTimeout bez biznesowego lub UI'owego uzasadnienia - lecz gdy chcesz wymusić wykonanie kodu po czasie ze względu na event loop - to workaround. Czy ten kod ma związek z czekaniem na odpowiedź Ajaxa lub próbujesz wymusić odświeżenie czegoś w DOM? Czemu akurat 100ms? Jeśli próbujesz wymusić odświeżenie DOM, to do tego służy requestAnimationFrame, jeśli czekasz na Ajax, to wykonaj ten kod w callbacku przekazanym w parametrze, jeśli czekasz na zakończenie animacji, to podepnij się na animationend event.

Jest i działa lepiej (nie generuje dodatkowych problemów):

Jakie problemy rozwiązuje użycie setTimeout? 

komentarz 26 stycznia 2021 przez Mlorism Użytkownik (580 p.)

Jakie problemy rozwiązuje użycie setTimeout? 

Przez to, że miałem problem z wywołaniem funkcji dla sliderów (zanim się wyświetlą) spowodowało, że odświeżałem kawałek strony. To spowodowało z kolei problemy z ciągle odpalaną metodą window.onload, co psuło z kolei, który DIV jest widoczny po zresetowaniu formularza. setTimeout w metodzie odpalanej na onreset pozwoliło zmienić jak wyglądają slidery po resecie bez odświeżania strony, a nie przed. Teraz zastąpiłem to zgodnie z sugestią przez requestAnimationFrame i wszystko też działa.

Dzięki za rady, wprowadziłem te rozwiązania do mojego projektu. :)

 

 

komentarz 26 stycznia 2021 przez ScriptyChris Mędrzec (183,720 p.)

To spowodowało z kolei problemy z ciągle odpalaną metodą window.onload

Nadal nie rozumiem jak ten handler mógł się uruchamiać, skoro nic do niego nie było przypisane, ale niech będzie. :P

Podobne pytania

0 głosów
1 odpowiedź 234 wizyt
pytanie zadane 27 stycznia 2019 w JavaScript przez Próbny Nowicjusz (200 p.)
0 głosów
2 odpowiedzi 155 wizyt
+1 głos
0 odpowiedzi 363 wizyt

89,132 zapytań

137,737 odpowiedzi

307,744 komentarzy

59,181 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...