Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Dynamiczne wczytywanie plików JS
Forum PHP.pl > Forum > Po stronie przeglądarki > JavaScript
WebCM
Tworzę grę logiczno-przygodową tylko w XHTML, CSS i JavaScript. Po uruchomieniu gry wyświetli się ekran główny z wyborem poziomu i opcjami (wygląd, język, muzyka OGG). Ewentualnie informacja o potrzebie aktualizacji przeglądarki.

1) Na początku trzeba załadować główny plik językowy i pobrać menu.

Przejdźmy do procesu ładowania poziomu.

2) Kod XHTML - tutaj raczej AJAX i wstawienie kodu do odpowiedniego obiektu <div>
3) Kod JS - informacje o pokojach, przedmiotach, funkcje, zmienne - dla ładowanego poziomu...
4) Plik językowy dla ładowanego poziomu.

Do końca nie zdecydowałem, czy będzie podział na poziomy, czy nie. W każdym razie 1) i 3) trzeba załadować dynamicznie.

Sposób 1. DOM
Tutaj wystarczy stworzyć za pomocą DOM obiekt <script> i dopiąć atrybut SRC. Problemy mogą być w IE, ale zawsze można sprawdzić, czy istnieją obiekty, które trzeba pobrać.

JSON + eval
Pliki pobieramy za pomocą AJAX, a potem zawartość wsadzamy do eval(). Panuje opinia, że eval() spowalnia skrypt.

Którym sposobem najlepiej ładować skrypty JS do tych celów? Ważne, by nie pojawiły się problemy nawet na IE 6.
kamil4u
Cytat
Panuje opinia, że eval() spowalnia skrypt.

Eval spowalnia skrypt, gdyż (z tego co pamiętam) uruchamia na nowo praser JS.

Proponuję Sposób 1, choć najlepiej gdybyś przetestował dwa i sprawdził co jest szybsze, mniej zawodne smile.gif
seth-kk
google uzywa document.write();
#luq
Taka mała uwaga.
Nigdy nie łącz JSON`a z evalem (kwestia bezpieczeństwa), używaj do tego JSON.parse.
WebCM
Teraz dowiedziałem się, że nowe przeglądarki mają natywną obsługę obiektu JSON. Skłaniam się właśnie do tego formatu ze względu na większą elastyczność. Oczywiście funkcje też można dołączać jako własności? winksmiley.jpg Dla starszych przeglądarek pozostanie eval(). Nie dołączam zewnętrznych bibliotek.

@seth-kk: document.write odpada. Skrypty 3) i 4) będą ładowane dopiero po wykonaniu akcji.

Wtedy w pliku level2.js mogę pominąć nazwy zmiennych - przynajmniej tak mi się zdaje:
Kod
{
    computer:
    {
        on: 1,
        disk: 0
    }
}

Być może jestem w błędzie i to wcale nie jest dobre rozwiązanie.
erix
Cytat
Oczywiście funkcje też można dołączać jako własności? Dla starszych przeglądarek pozostanie eval(). Nie dołączam zewnętrznych bibliotek.

JSONP. Właściwie, to wszystkie przeglądarki umożliwiają przetwarzanie danych przez JSON, nawet IE6. biggrin.gif
WebCM
Natywny parser w Firefoksie 3.5 JSON.parse() ogranicza mnie. Nie można wplątać funkcji:
Kod
{
    dosomething: function(z, c, b) { alert(c) }
}

Raczej nie napiszę logiki etapu tylko za pomocą zmiennych (czyt. własności obiektu), choć jest to możliwe. Musiałbym rozbudować silnik gry, aby obsłużyć wszystkie możliwe zdarzenia, np. użycie przedmiotów na określonych rzeczach, zmianę stanu urządzeń, tekst w zależności od tego, czy płyta / dyskietka jest włożona, czy prąd włączony... Czy jest sens aż tak kombinować? Raczej NIE.

Mam zamiar udostępnić grę do pobrania, więc pewnie pojawią się mirrory w sieci. Gdybym nawet użył JSON.parse(), wciąż pojawia się zagrożenie, że ktoś zmodyfikuje inną partię skryptu, aby wyciągnąć cookies lub przeprowadzić CSRF.

Poszukam jeszcze benchmarków i zdecyduję, co wykorzystać. AJAX i tak będzie potrzebny, by pobrać XHTML.
zegarek84
na upartego nie musisz używać AJAX'a do pobrania JSON winksmiley.jpg:
Howto Dynamically Insert Javascript And CSS - wystarczy podpiąć zdarzenie onload i odpalić odpowiednią funkcję na JSON...

wcześniej gdy pisali by nie używać eval to właśnie mieli na myśli o tych załączanych funkcjach jako metody winksmiley.jpg
Cytat(WebCM @ 21.08.2009, 19:48:42 ) *
Poszukam jeszcze benchmarków i zdecyduję, co wykorzystać. AJAX i tak będzie potrzebny, by pobrać XHTML.

no i tu znowu na upartego mając odpowiednią strukturę JSON mógłbyś na jego podstawie budować xhtml'a więc i ajax też nie jest przymusem ;p
WebCM
Znam metodę z DOM. Eksperymentowałem. IE 8 niestety ma niepełną obsługę. Podzielę się wynikami:

Kod
function include(file, loaded)
{
    var js = document.createElement('script');
    js.type = 'text/javascript';
    js.src = file;

    //Wywołaj funkcję, gdy plik zostanie załadowany
    if(loaded)
    {
        js.onreadystatechange = function()
        {
            if(js.readyState == 'complete') loaded()
        };
        js.onload = loaded;
    }
    document.getElementsByTagName('head')[0].appendChild(js);
}

Funkcja dołącza dynamicznie skrypt JavaScript i opcjonalnie wywołuje po załadowaniu funkcję przekazaną do loaded.

Jak przeglądarki radzą sobie z tym? Testowałem w: IE 8, Chrome 2.0.172.33, Opera 9.61, FX 3.5, Safari 4.30.19.1

onload: Opera 9, Chrome 2, FX 3.5, Safari 4.30
onreadystatechange: IE 8, Opera 9.6

Internet Explorer
Studium przypadku - zazwyczaj wartość readyState kończy się na 'loaded'. Czasami 'complete'.

Opera
Własność readyState przyjmuje wartości 'interactive' i 'loaded'. Potem przenosi się do onload. Gdy dopuszczę wartość 'loaded' dla readyState, Opera wywoła funkcję przekazaną jako parametr kilka razy.

Chrome 2, Firefox 3.5, Safari 4.30
Obsługują tylko własność onload, więc nie ma problemu z wywołaniem funkcji w odpowiednim momencie. Na blogach można przeczytać, że w Safari kod w ogóle nie działa. Musieli to poprawić.

Można ewentualnie wykryć w onreadystatechange, czy obiekty są już dostępne.

Potrzebuję więcej argumentów przemawiających za DOM lub za eval() lub za AJAX + <script>.innerHTML.
erix
Cytat
Obsługują tylko własność onload, więc nie ma problemu z wywołaniem funkcji w odpowiednim momencie. Na blogach można przeczytać, że w Safari kod w ogóle nie działa. Musieli to poprawić.

Przejrzyj źródła jQuery, bo chyba tam było jakieś obejście.

Cytat
lub za AJAX + <script>.innerHTML.

Możesz wczytać przecież skrypt z zewnętrznego źródła, albo tak, jak robi JSONP:
[JAVASCRIPT] pobierz, plaintext
  1. var a = {....}
  2. processData();
[JAVASCRIPT] pobierz, plaintext

Wtedy nie będziesz potrzebował żadnych zdarzeń, gdyż dane będą już wczytane. ;]
zegarek84
jeśli w JSON i tak zamierzasz przesyłać funkcje w metodach to równie dobrze mógłbyś w DOM przesłać też ale na końcu skryptu funkcję inicjującą tą co jest już w window - mam na myśli tą co ma przejrzeć obiekt...

czyli np. coś w ten deseń:

temp={}; //tymczasowy kontener json
inicjuj(); //wszystko widać co i jak - wywołanie funkcji która ma się dobrać do obiektu temp

//edit
@erix mnie ubiegł...
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.