Dynamiczne ładowanie skryptu

0

Proszę o pomoc w takim problemie:
Ze strony główne (index.html), z danej pozycji jej menu, ładuję kod strony do odpowiedniego div'a za pomocą takiej konstrukcji:

<a href="javascript:void(0)" onClick="openInContent('content', 'about/about.html')">About</a>

Ładowana strona uruchamia się w <div id="content"> ale jako jedynie kod html. Niezależnie od tego czy skrypt jest osadzony zewnętrznie

<script src="../js/about.js"></script>

czy jest wewnątrz strony:

<script>
    document.querySelector('#aboutt').innerHTML = "about text";
</script>

gdzie w about.html jest:

<input id="aboutt" type="text" placeholder="tu ma być tekst z about">

Dziewe(?) jest to, że po kliknięciu w odpowiednią pozycje menu i władowaniu html'a strony about.html adres jest:

http://127.0.0.1:5500/index.html#

Ścieżki do js i css są poprawne i css sie ładuje. Dodam, że jeśli uruchomię about.html "samodzielnie" skrypt działa poprawnie.
Co robię nie tak?

1

A jest jakiś powód czemu chcesz wczytać dynamicznie tą stronę about/about.html i jej skrypt?

Czemu nie możesz wczytać wszystkiego od razu?

0

Ta strona jest ładowana z danej pozycji menu. Pozycja About wczytuje about.html, pozycja Strona 1 wczytuje strona1.html itd. Menu samo w sobie jest dynamiczne i chowa się po wybraniu danej pozycji. Ponad to te podstrony (Strona 1, Strona 2...) maja skrypty liczące więc muszą je wczytać. To menu jest w jednym div'ie, a podstrony ładują się do innego. Jeśli właduję taką stronę do div'a z menu, to oczywiście tego menu nie ma.

1

@Jadalbert: Mógłbyś pokazać cały ten projekt? Bo tu jest więcej rzeczy które trzeba wziąć pod uwagę.

0

Od nowa kod bo sobie wcześniej coś nacisnąłem niechcący, więc post powyżej nie ma sensu.

Cały to nieco chyba za dużo kodu, ale sądzę, że najistotniejsze są te fragmenty:

<div id="aside" class="sidenav">
    <a href="javascript:void(0)" class="closebtn" onclick="closeNav()">&times;</a>
    <a href="javascript:void(0)" onClick="openInContent('content', 'about/about.html')">About</a>
    <a href="javascript:void(0)" onClick="openInContent('content', 'strona1.html')">Strona 1</a>
    <a href="javascript:void(0)" onClick="openInContent('content', 'strona2.html')">Strona 2</a>
    <button class="dropdown-btn">Strona 3
        <i class='fa fa-caret-down'></i>
    </button>
    <div class="dropdown-container">
        <a href="javascript:void(0)" onclick="openInContent('content', 'Podstrona31.html')">Podstrona 31</a>
        <a href="javascript:void(0)" onclick="openInContent('content', 'Podstrona32.html')">Podstrona 32</a>
    </div>
    <a href="javascript:void(0)" onClick="openInContent('content', 'strona2.html')">Strona 4</a>
</div>
 <div id="main" class="main">
    <div id="content">
        To jest content
    </div>
</div>
<script>
[...]
function openInContent(id, filename) {
    let xhttp;
    let element = document.getElementById(id);
    let file = filename;
    if (file) {
        xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (this.readyState == 4) {
                if (this.status == 200) {element.innerHTML = this.responseText;}
                if (this.status == 404) {element.innerHTML = "<h1>404! Page not found.</h1>";}
            }
        }
        xhttp.open("GET", file, true);
        xhttp.send();
        return;
    }   
}
[...]
</script>

about.html

<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="/css/style.css">
    </head>
    <body>
        <h1>To jest about.</h1>
        Ze skryptu: <input id="aboutt" type="text" placeholder="tu ma być tekst z about">
        <script src="../js/about.js"></script>
    </body>
</html>  

about.js

document.querySelector('#aboutt').value = "about text";

Myślę, że to są te fragmenty, które do tej dyskusji wystarczą i są odpowiedzialne za omawiany problem.

1
Jadalbert napisał(a):

Cały to nieco chyba za dużo kodu, ale sądzę, że najistotniejsze są te fragmenty:
index.html

Chodzi o to, żebym mógł zrozumieć jak dokładnie Twoja aplikacja działa.

Bo jak czytam Twój post, to nie widzę powodu czemu wczytywanie tych plików miałoby być dynamiczne. Mogłyby przecież być wczytane statycznie, za jednym razem i wtedy żadnego problemu by nie było.

0

Eeeee... Przepraszam coś chyba nie umiem obsługiwać tego forum w sensie umieszczanie kodu. Chwilę - douczę się może.

0

A nie. Teraz jest dobrze. Przedtem miałem jakieś dziwne formatowanie. Teraz wydaje się, że kod jest czytelny.
Dodam jeszcze, że odpalenie tej strony about.html z menu na index.html powoduje wyświetlenie tekstu z wartości placeholder, a nie ze skryptu about.js

0
Jadalbert napisał(a):

A nie. Teraz jest dobrze. Przedtem miałem jakieś dziwne formatowanie. Teraz wydaje się, że kod jest czytelny.

Sformatowałem kod za Ciebie.

Umieszczaj kod w znaczniki ```html oraz ```. Możesz też zaznaczyć całość kodu i użyć skrótu Ctrl+Alt+C.

Jadalbert napisał(a):

Dodam jeszcze, że odpalenie tej strony about.html z menu na index.html powoduje wyświetlenie tekstu z wartości placeholder, a nie ze skryptu about.js

Wrzuć kod całej aplikacji najlepiej w .zip albo .rar, lub umieść ją na gitubie.

1

Jeśli cała strona jest dość mała, to mógłbyś tak zrobić, że załadować wszystko naraz, tylko fragmenty byłyby ukryte za pomocą właściwości display: none w CSS

<div id="about" style="display:none">
o mnie
</div>

wtedy mógłbyś coś takiego zrobić:

document.getElementById('about').display = 'block'; // wyświetlanie
//...
document.getElementById('about').display = 'none'; // ukrywanie

Albo też można to zrobić w CSS za pomocą tricku: https://css-tricks.com/the-checkbox-hack/

Natomiast jeśli strona faktycznie byłaby duża, to wtedy można by rozważać ładowanie tego dynamicznie.

<a href="javascript:void(0)" onClick="openInContent('content', 'about/about.html')">About</a>

Czemu nie lubisz użytkownika? Jeśli chcesz to ładować dynamicznie, to pozwól użytkownikowi na otwarcie linku na różne sposoby. Użytkownik niekoniecznie będzie klikał lewym przyciskiem, żeby otworzyć link, ja często otwieram środkowym przyciskiem, żeby się w nowej karcie otworzyło. Więc lepiej byłoby, żeby wyglądało to tak:

<a href="about/about.html" onClick="openInContent('content', 'about/about.html')">About</a>

przy czym zapewne będziesz musiał dać wtedy return false czy wywołać metodę preventDefault() na obiekcie zdarzenia, żeby zablokować domyślną akcję, jakby użytkownik faktycznie kliknął lewym przyciskiem.

Tylko, że po tym, co tu wrzuciłeś, to mam wrażenie, że robisz coś kompletnie od czapy i że ta strona powinna być przepisana na jedną z poniższych:

  • klasyczna strona HTML z normalnymi linkami do podstron, bez jakiegoś ładowania dynamicznego
  • prosta stronka z pewnymi interaktywnymi elementami dopisanymi w JS albo za pomocą HTML/CSS. Stronka ta nie musiałaby niczego ładować, po prostu by były wyświetlane albo chowane pewne załadowane już elementy. Mógłbyś też skorzystać z kotwic do nawigacji (np. jak na tym przykładzie: https://jsfiddle.net/en5yLq3k/)
  • SPA(Single Page Application) - czyli strona, która działa jak aplikacja, gdzie JS steruje całym GUI. Tylko wtedy:
    • warto użyć jakiejś biblioteki typu React czy Vue
    • zwykle się pobiera suche dane w formacie JSON z serwera i już widok robi po stronie przeglądarki tworząc tzw. "komponenty", w których umieszczasz szablon danego elementu strony
    • pytanie, czy takie podejście ci w ogóle potrzebne? Z jednej strony wydaje się, że i tak robisz już swoją partyzancką wersję SPA, więc użycie Reacta miałoby więcej sensu. Z drugiej strony... no nie wiem, to zależy, co dokładnie robisz. Czy to ma być prosta stronka, do której chcesz dodać trochę interaktywności, czy może faktycznie rozbudowana aplikacja?
1
LukeJL napisał(a):

Jeśli cała strona jest dość mała, to mógłbyś tak zrobić, że załadować wszystko naraz, tylko fragmenty byłyby ukryte za pomocą właściwości display: none w CSS

Niby tak ale to już mocno wbrew sztuce.
Kolega ewidentnie chciałby zrobić "SPA" a nieodłącznym elementem SPA jest zarządzanie historią przeglądarki. Bez tego strasznie "śmierdzi" amatorszczyzną.
Zatem do wyboru ma zrobić to wykorzystując:

  1. kotwice
  2. wykorzystać funkcje: history.pushState, history.replaceState ( t.j. https://developer.mozilla.org/en-US/docs/Web/API/History/pushState, https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState )
<div id="about" style="display:none">
o mnie
</div>

wtedy mógłbyś coś takiego zrobić:

document.getElementById('about').display = 'block'; // wyświetlanie
//...
document.getElementById('about').display = 'none'; // ukrywanie

j.w. od biedy można tak zrobić ale to jednak bardzo biedne rozwiązanie, mało elastyczne i niewygodne dla użytkownika.

Albo też można to zrobić w CSS za pomocą tricku: https://css-tricks.com/the-checkbox-hack/

To już lepiej zrobić linkach i pseudoklasie :target w tym przypadku podczas klikania przynajmniej będzie historia i zadziała guzik "wstecz":
https://developer.mozilla.org/en-US/docs/Web/CSS/:target
https://yari-demos.prod.mdn.mozit.cloud/en-US/docs/Web/CSS/:target/_sample_.a_table_of_contents.html#p1

Czemu nie lubisz użytkownika? Jeśli chcesz to ładować dynamicznie, to pozwól użytkownikowi na otwarcie linku na różne sposoby.

Tak najlepiej. Szczególnie biorąc pod uwagę, że elementy, które mają display:none nie muszą być indeksowane przez wyszukiwarki a nawet mogą być traktowane jako "niechciane".
Dla dobrego efektu SEO i tak obsługa linków musiałaby istnieć.

Tylko, że po tym, co tu wrzuciłeś, to mam wrażenie, że robisz coś kompletnie od czapy i że ta strona powinna być przepisana na jedną z poniższych:

To już inna bajka :-)

Podsumowując, jeśli kolega nie czuje się na siłach to najlepiej żeby zrobił zwykłe statyczne strony HTML bez kombinowania.

1
katakrowa napisał(a):
LukeJL napisał(a):

Jeśli cała strona jest dość mała, to mógłbyś tak zrobić, że załadować wszystko naraz, tylko fragmenty byłyby ukryte za pomocą właściwości display: none w CSS

Niby tak ale to już mocno wbrew sztuce.
Kolega ewidentnie chciałby zrobić "SPA" a nieodłącznym elementem SPA jest zarządzanie historią przeglądarki. Bez tego strasznie "śmierdzi" amatorszczyzną.

Tylko jeśli URL jest częścią aplikacji. Może być SPA które nie używa URL do nawigacji i jakoś działają.

0

Przesyłam kody. Mam nadzieję, że tak można jak zrobiłem. Korzystam z Visual Studio Code.

PressureCalc.7z

0
Riddle napisał(a):
katakrowa napisał(a):
LukeJL napisał(a):

Jeśli cała strona jest dość mała, to mógłbyś tak zrobić, że załadować wszystko naraz, tylko fragmenty byłyby ukryte za pomocą właściwości display: none w CSS

Niby tak ale to już mocno wbrew sztuce.
Kolega ewidentnie chciałby zrobić "SPA" a nieodłącznym elementem SPA jest zarządzanie historią przeglądarki. Bez tego strasznie "śmierdzi" amatorszczyzną.

Tylko jeśli URL jest częścią aplikacji. Może być SPA które nie używa URL do nawigacji i jakoś działają.

To zależy jaki jest cel "strony" jeśli jest to aplikacja narzędziowa to nie ma to znaczenia ale jeśli jest to strona informacyjna, którą chcemy pozycjonować to to "jakoś" nie znaczy dobrze / poprawnie / zgodnie ze sztuką.
Żeby nawigacja bez URL działała masz tylko 2 możliwości, o których napisałem i robisz to na linkach z pseudoklasami :target lub :active albo obsługujesz historię przeglądarki wykorzystującdo tego funkcje:
https://developer.mozilla.org/en-US/docs/Web/API/History/pushState
https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState

0
Jadalbert napisał(a):

Przesyłam kody. Mam nadzieję, że tak można jak zrobiłem. Korzystam z Visual Studio Code.

Dzięki za podesłanie kodu.

No to analizując tą aplikację, rozumiem co chcesz zrobić, wydaje mi się że najlepszym wyjściami dla Ciebie, będzie jedno z tych:

  • Zrób aplikacje webową z backendem (np w pythonie, php, rubym, javie, etc.) oraz z technologią do SSR (np djago view, php blade, jsp, etc.)
  • Zainteresuj się rozwiązaniami typu SSR - Server Side Rendering
  • Skorzystaj z frameworka do generowania kontetu, jakyll, docusaurus, etc.
  • Jeśli chcesz aplikację tylko w JavaScript, to odejdź od dynamicznego ładowania plików w taki sposób. Zainteresuj się programem "webpack", który pozwoli Ci zbudować w miarę sensowną aplikacje:
    • Wtedy możesz albo nadal pisać w JavaScript
    • Albo użyć jednego z frameworków: React, Angular, Vue.

Moim zdaniem najlepszym byłby dla Ciebie backend w pythonie.

0
Riddle napisał(a):
Jadalbert napisał(a):

Przesyłam kody. Mam nadzieję, że tak można jak zrobiłem. Korzystam z Visual Studio Code.

Dzięki za podesłanie kodu.

No to analizując tą aplikację, rozumiem co chcesz zrobić, wydaje mi się że najlepszym wyjściami dla Ciebie, będzie jedno z tych:

  • Zrób aplikacje webową z backendem (np w pythonie, php, rubym, javie, etc.) oraz z technologią do SSR (np djago view, php blade, jsp, etc.)
  • Skorzystaj z frameworka do generowania kontetu, jakyll, docusaurus, etc.
  • Jeśli chcesz aplikację tylko w JavaScript, to odejdź od dynamicznego ładowania plików w taki sposób. Zainteresuj się programem "webpack", który pozwoli Ci zbudować w miarę sensowną aplikacje:
    • Wtedy możesz albo nadal pisać w JavaScript
    • Albo użyć jednego z frameworków: React, Angular, Vue.

Moim zdaniem najlepszym byłby dla Ciebie backend w pythonie.

Ok. Dzięki za info. Spojrzę na te narzędzia, o których wspominasz i może rzeczywiście zajmę się tym pythonem. Niemniej, i zrozum mnie, proszę, dobrze, problem, który opisałem nadal nie jest rozwiązany. Byc może jest sensownie nierozwiązywalny lub zbyt dużo zachodu trzeba by go rozwiązać. Dziwne jednak jest to nieładowanie skryptu, który jest przecież na stronie (akurat w przesłanych kodach jest dołączany). Ale umieszczenie go na stronie i tak nic nie daje. Niby prosta rzecz i powinno działać, a nie chce.

0
Jadalbert napisał(a):

Ok. Dzięki za info. Spojrzę na te narzędzia, o których wspominasz i może rzeczywiście zajmę się tym pythonem. Niemniej, i zrozum mnie, proszę, dobrze, problem, który opisałem nadal nie jest rozwiązany. Byc może jest sensownie nierozwiązywalny lub zbyt dużo zachodu trzeba by go rozwiązać. Dziwne jednak jest to nieładowanie skryptu, który jest przecież na stronie (akurat w przesłanych kodach jest dołączany). Ale umieszczenie go na stronie i tak nic nie daje. Niby prosta rzecz i powinno działać, a nie chce.

Znasz takie podejście "divide and conquer" - "dziel i zwyciężaj"?

Polega na wzięciu jakiegoś skomplikowanego zagadnienia i rozbicia go na mniejsze kawałki. U Ciebie takim mniejszym kawałkiem byłoby próba wstawienia po prostu HTML'a i skryptu do elementu. Uruchom sobie taki kod i powiedz mi co widzisz:

<!DOCTYPE html>
<html>
<body>
<div id="content">
  
</div>

<script>
    let content = '<span>This is my content</span> <script>alert("This is my script");<' + '/script>';
    document.querySelector('#content').innerHTML = content;
</script>

</body>
</html>             

Czy widzisz pojawiający się alert()? :>

PS: Zapis <' + '/script> jest po to żeby </script> można było umieścić w HTML'u.

0
Riddle napisał(a):
Jadalbert napisał(a):

Ok. Dzięki za info. Spojrzę na te narzędzia, o których wspominasz i może rzeczywiście zajmę się tym pythonem. Niemniej, i zrozum mnie, proszę, dobrze, problem, który opisałem nadal nie jest rozwiązany. Byc może jest sensownie nierozwiązywalny lub zbyt dużo zachodu trzeba by go rozwiązać. Dziwne jednak jest to nieładowanie skryptu, który jest przecież na stronie (akurat w przesłanych kodach jest dołączany). Ale umieszczenie go na stronie i tak nic nie daje. Niby prosta rzecz i powinno działać, a nie chce.

Znasz takie podejście "divide and conquer" - "dziel i zwyciężaj"?

Polega na wzięciu jakiegoś skomplikowanego zagadnienia i rozbicia go na mniejsze kawałki. U Ciebie takim mniejszym kawałkiem byłoby próba wstawienia po prostu HTML'a i skryptu do elementu. Uruchom sobie taki kod i powiedz mi co widzisz:

<!DOCTYPE html>
<html>
<body>
<div id="content">
  
</div>

<script>
    let content = '<span>This is my content</span> <script>alert("This is my script");<' + '/script>';
    document.querySelector('#content').innerHTML = content;
</script>

</body>
</html>             

Czy widzisz pojawiający się alert()? :>

PS: Zapis <' + '/script> jest po to żeby </script> można było umieścić w HTML'u.

Dzięki. Obadam sprawę lecz dziś juz musze kończyć. Zdam sprawę jutro. Tobie i wszystkim dziękuję za pomoc.

1 użytkowników online, w tym zalogowanych: 0, gości: 1