Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Ładowanie bibliotek TinyMCE na żądanie
Forum PHP.pl > Forum > Po stronie przeglądarki > JavaScript
WebCM
Mam problem z dynamicznym tworzeniem edytorów TinyMCE w Google Chrome. Wyświetlą się tylko przy pierwszym wyświetleniu strony, a potem już nie (nie ma błędów w konsoli!) albo na odwrót.

Edytory mogą ładować się na 2 sposoby:
1. Na żądanie - podczas ładowania strony (wywołane w <body>)
2. Na żądanie - po załadowaniu strony (np. po kliknięciu przycisku)

Proces ładowania edytorów:
1. W sekcji <head> dołączam tradycyjnie plik ładujący loader.js
  1. <script type="text/javascript" src="loader.js"></script>

2. Plik loader.js wygląda tak:
[JAVASCRIPT] pobierz, plaintext
  1. function Editor(O)
  2. {
  3. var that = this;
  4.  
  5. //Jeśli nie załadowano tinyMCE, zrób to teraz
  6. if(!Editor.got)
  7. {
  8. include('tiny_mce.js');
  9. Editor.got = true;
  10. }
  11.  
  12. //Funkcja, która dodaje nowy edytor
  13. var init = function()
  14. {
  15. that.o = tinymce.add(new tinymce.Editor(O.id, {
  16.  
  17. //ustawienia wycięte, ale nie mają na to wpływu
  18.  
  19. }));
  20. that.o.render();
  21. };
  22.  
  23. //Jeżeli dokument jest już załadowany
  24. if(Editor.DOM) setTimeout(init,500);
  25.  
  26. //A jeśli nie jest jeszcze załadowany - PATRZ TUTAJ:
  27. else addEvent('load', function() { setTimeout(init,500); Editor.DOM = true })
  28. }
  29.  
  30. Editor.got = Editor.DOM = false;
[JAVASCRIPT] pobierz, plaintext

3. Natomiast instancje obiektu Editor są tworzone w sekcji <body> za formularzem:
  1. <script type="text/javascript">
  2. e = new Editor(formularz.nazwapola);

Bawiłem się w Firebugu do Firefoksa. Jeżeli strona jest już załadowana, dynamiczne wczytanie głównej biblioteki i dodanie nowego edytora nie działa. Czyżby wina TinyMCE? Przykład:
[JAVASCRIPT] pobierz, plaintext
  1. include('tiny_mce.js', function() {
  2. tinyMCE.init({mode:'none'});
  3. var test = new tinymce.Editor('txt', {theme:'advanced'});
  4. tinymce.add(test);
  5. test.render();
  6. });
[JAVASCRIPT] pobierz, plaintext


Funkcja addEvent (chyba) działa prawidłowo, ale gdyby ktoś miał wątpliwości:
[JAVASCRIPT] pobierz, plaintext
  1. function addEvent(type, f, o, capture)
  2. {
  3. if(window.addEventListener)
  4. {
  5. (o||window).addEventListener(type, f, capture||false)
  6. }
  7. else if(window.attachEvent)
  8. {
  9. (o||window).attachEvent('on'+type, f)
  10. }
  11. else if(!o['on'+type])
  12. {
  13. (o||window)[type] = f
  14. }
  15. }
[JAVASCRIPT] pobierz, plaintext

Jedynym wyjściem jest ładowanie głównej biblioteki podczas ładowania strony (przed zdarzeniem window.onload)?

Jak załadować bibliotekę TinyMCE na żądanie, a następnie wyświetlić edytor tak, aby działał w każdej przeglądarce?

Jak sprawdzić, czy wszystkie pliki TinyMCE są załadowane, czyli - czy można już odpalić edytor?
erix
Cytat
1. W sekcji <head> dołączam tradycyjnie plik ładujący loader.js

Co to jest? Pierwszy raz na oczy widzę.
WebCM
Cytat
Co to jest? Pierwszy raz na oczy widzę.
To plik na potrzeby skryptu CMS, aby zachować kompatybilność ze standardowym edytorem. Zamieściłem jego zawartość w punkcie nr 2. Jest po to, aby nie modyfikować oryginalnego tiny_mce.js.

Zaproponujcie lepsze rozwiązanie od tego, które przedstawiłem, jeżeli niewiele da się wykombinować tongue.gif
thek
Zerkni google pod kątem "tinymce dynamic load" ) Zarzucę jednym z wielu wskazywanych wyników smile.gif
http://blog.mirthlab.com/2008/11/13/dynami...nces-to-a-page/
WebCM
To stary sposób wstawiania i usuwania edytorów. Nowe wersje TinyMCE mają do tego celu API. Szukałem w Google innych sposobów, ale nie ma nic ciekawego. Pobawiłem się w Firebugu i wynika, że...

Po załadowaniu głównej biblioteki tiny_mce.js wystarczy wywołać
[JAVASCRIPT] pobierz, plaintext
  1. include('tiny_mce.js', function() {
  2. var editor = new tinymce.Editor('id_pola', {opcje});
  3. editor.render(); //od tej chwili TinyMCE zacznie ładować pozostałe pliki
  4. tinyMCE.add(editor); //to nie jest konieczne?
  5. });
[JAVASCRIPT] pobierz, plaintext
Występował inny problem opisany tu: http://tinymce.moxiecode.com/punbb/viewtopic.php?pid=83564

Jak widać, 4 dni temu pojawiła się solucja, którą za chwilę przetestuję. W skrócie:
1. Nie ładuj biblioteki tiny_mce.js wielokrotnie!
2. Używaj opcji strict_loading_mode

Przestroga: tinyMCE jest skrótem do obiektu tinymce.EditorManager - to nie to samo co tinymce!

Problem w Chrome powraca. Edytory TinyMCE wyświetlą się tylko po odświeżeniu strony. W przeciwnym przypadku widać, że plik tiny_mce.js ładuje się i nic. Zbadałem przyczynę. Okazuje się, że zdarzenie HTMLScriptElement.onload nie zawsze występuje! Funkcja include() wygląda tak:
[JAVASCRIPT] pobierz, plaintext
  1. function include(file, loaded)
  2. {
  3. var js = document.createElement('script');
  4. js.type = 'text/javascript';
  5. js.src = file;
  6.  
  7. //Wywołaj funkcję, gdy plik zostanie załadowany
  8. if(loaded)
  9. {
  10. //IE, Opera
  11. if(js.readyState)
  12. {
  13. js.onreadystatechange = function()
  14. {
  15. if(js.readyState == 'complete' || js.readyState == 'loaded')
  16. {
  17. loaded(); js.onreadystatechange = null
  18. }
  19. }
  20. }
  21.  
  22. //Firefox, Chrome, Safari, Opera - TU JEST PROBLEM
  23. else js.onload = loaded;
  24. }
  25. document.getElementsByTagName('head')[0].appendChild(js)
  26. }
[JAVASCRIPT] pobierz, plaintext
Dla pewności zbadałem, że WebKit NIE ma własności readyState. Podejrzewam, że nie da się zrobić nic więcej. Sami przetestujcie na własnych skryptach, czy to błąd, czy funkcja (bug or feature) tongue.gif

Na pewno programiści zgłaszali błąd zarówno do Google i do Apple i nic.

AKTUALIZACJA

Moje pierwsze spostrzeżenia były błędne. Zdarzenie HTMLScriptElement.onload wywołuje się zawsze. To ewidentnie wina TinyMCE, tylko dlaczego w innych przeglądarkach problem nie występuje? Mimo wszystko wierzę, że window.onload w Chrome wywołuje się za wcześnie i stąd metoda tinyMCE.init() nie działa.

AKTUALIZACJA 2

Znalazłem przyczynę. Klasa tinymce.dom.EventUtils działa nieprawidłowo na silniku WebKit. Funkcja add:
Kod
if (n == 'init')
{
    if (t.domLoaded)
    {
        console.log('DOM loaded - callback will be called');
        cb();
    }
    else
    {
        console.log('DOM not ready - put callback onto stack');
        t.inits.push(cb);
    }
    return cb;
}
t.inits.push(cb); to ostatnia ważna operacja. Potem nic się nie dzieje. Wywołanie:
Kod
Event.add(document, 'init', function() {

Są tylko 2 miejsca, gdzie własność .domLoaded jest ustawiana na TRUE: _pageInit and _wait. Inny ważny kod:
Kod
else if (doc.addEventListener) {
    t._add(win, 'DOMContentLoaded', function() {
        t._pageInit(win);
    });
}
oraz
Kod
Event = tinymce.dom.Event = new tinymce.dom.EventUtils();

// Dispatch DOM content loaded event for IE and Safari
Event._wait(window);
Oba zdarzenia DOMContentLoaded i onload nie wykonują się, czyli musiały zostać wywołane wcześniej.

Jednak .domLoaded ma wartość TRUE - który fragment kodu go ustawia, jeżeli _pageInit() nie jest wywoływana?

Szukam rozwiązania. Może ktoś już wpadł i nie będę musiał spędzić kolejnego dnia na to cool.gif
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.