Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Ładowanie bibliotek TinyMCE na żądanie, dynamiczne tworzenie edytorów - problem w Chrome
WebCM
post
Post #1





Grupa: Zarejestrowani
Postów: 375
Pomógł: 20
Dołączył: 28.07.2006

Ostrzeżenie: (0%)
-----


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?

Ten post edytował WebCM 11.12.2010, 16:55:04
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
WebCM
post
Post #2





Grupa: Zarejestrowani
Postów: 375
Pomógł: 20
Dołączył: 28.07.2006

Ostrzeżenie: (0%)
-----


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) (IMG:style_emoticons/default/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 (IMG:style_emoticons/default/cool.gif)

Ten post edytował WebCM 23.12.2010, 12:50:51
Go to the top of the page
+Quote Post

Posty w temacie


Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 3.10.2025 - 06:21