Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [js] Dynamiczne drukowanie zawartości textarea w div
Forum PHP.pl > Forum > Po stronie przeglądarki > JavaScript
rozny
Witam,

zastanawiam się w jaki sposób rozwiązać zagadnienie. Chcę w czasie rzeczywistym drukować zawartość textarea w divie - coś na zasadzie podglądu wprowadzonych zmian w czasie rzeczywistym. Za js zabrałem się tak na prawdę dopiero kilka dni temu, dlatego zmuszony jestem poradzić się kogoś bardziej doświadczonego.

W jaki sposób za pomocą js mogę ingerować w zawartość elementu div? W jaki sposób w czasie rzeczywistym pobierać zawartość textarea? Na razie kombinuję z parametrem onChange wywołującym funkcję czytającą zawartość textarea, niestety nie jest to dobre rozwiązanie, gdyż zmiana następuje dopiero po dezaktywacji pola textarea.

Zależy mi bardziej na wskazówkach jak ugryźć temat niż na gotowcu. Będę wdzięczny za pomoc.

Pozdrawiam
kamil4u
Skoro chcesz wskazówki to proszę bardzo smile.gif Poczytaj o DOM i wszystkim co z nim związane. Generalnie to by Ci wystarczyło, ale ,że jest tego naprawdę sporo to napiszę Ci trochę więcej. Po pierwsze DOM musi być załadowany, najprościej użyć tutaj zdarzenia onload. Następnie trzeba się dobrać do div-a. Tu właśnie z pomocą przychodzi nam DOM i metoda szukania po id( bo po tym atrybucie najprościej ). Osiągniemy to za pomocą document.getElementById . Skoro mamy element teraz chcemy zmienić jego zawartość. Tu potrzebujesz .innerHTML . Dzięki temu możesz zmieniać wartość div-a. Teraz bawimy się dalej, czyli pobieramy referencję do elementu textarea( też najłatwiej po id ). Jego zawartość pobieramy za pomocą .value . Brakuje Ci teraz znaku '=' i kolejnego zdarzenia onchange. Przypisujemy zatem zdarzenie elementowi textarea. Robisz to za pomocą JS, a nie atrybutu HTML. Warto też żebyś zapoznał się ze słówkiem this, które wiele ułatwia.

Pseudokod:
Kod
Gdy_pobrany_DOM -> {
pobierz_element_textarea.przypisz_zdarzenie _onchange -> {
   pobierz_element_DIV.zmień_jego_zawartość = this.zawartość_textarea //tu this wskazuje na textarea właśnie
}
}
rozny
Dobra - popełniłem taki kod:

  1. function print_content() {
  2. var content=document.newsletter.tresc.value;
  3. document.getElementById('podglad').innerHTML = content;
  4. }


I działa. Funkcję w tej chwili wywołuję zdarzeniem HTML onChange, bo niebardzo wiem jak użyć właściwości _onChange js. Spróbowałem w ten sposób:

  1. function print_content() {
  2. var content=document.newsletter.tresc.value;
  3. document.getElementById('tresc').value _onchange -> {
  4. document.getElementById('podglad').innerHTML = content;
  5. }
  6.  
  7. }


Ale nie działa. Jakaś podpowiedź? wink.gif
Niktoś
Tak patrze i nie mogę zrozumieć ,co chcesz tą liniką osiągnąć:
Cytat
document.getElementById('tresc').value _onchange ->
rozny
Stwierdziłem, że może da się w ten sposób wywołać polecenie. Próbowałem to na chłopski rozum rozwiązać, ale jak widać jest to bzdura wink.gif

Jak już mówiłem js zająłem się dosłownie kilka dni temu i nie wszystko jest jeszcze dla mnie jasne i oczywiste. Pierwszy kod działa, ale nie w czasie rzeczywistym, a dopiero po opuszczeniu textarea (zdarzenie onChange w tagu <textarea>). Poczytam, może się doczytam jak użyć tego _onchange, jak sugerował kamil4u.

I jeszcze pytanie - bo to w praniu wyszło. W jaki sposób mogę przeparsować zawartość textarea. Bo w tej chwili owszem div się wypełnia treścią, ale np. bez enterów, a mam tam też bbcode, który chciałbym sobie przeparsować. Podejrzewam, że to już zahacza o AJAX?
Niktoś
Podejrzewam ,że kamil4u podał Tobie wskazówki,jak to zrobić ,a ty próbowałeś to w prosty sposób skopiować.
kamil4u
O AJAX na pewno nie zahacza.

Jak sam mówiłeś nie chciałeś gotowca, więc dałem Ci wskazówki i pseudokod, który nic nie ma wspólnego z takim jakim ma być. Poczytaj w takim razie o zdarzeniach. Polecam: http://webhelp.pl/artykuly/obsluga-zdarzen-w-przegladarkach/ - choć to jest trochę wyższy poziom niż potrzebujesz smile.gif

Najprościej( choć lepiej używać metody takiej jak w artykule ) piszesz:
Kod
referencja_do_elementu.onchange = function(){
//tu kod dla zdarzenia onchange
}


To samo z każdym innym zdarzeniem. Schemat: referencja.on{nazwa zdarzenia} = function(){ ..... }
Dla onload napiszesz window.onload bo tyczy się to całej strony. Musisz dobrać odpowiednie własności. Poczytaj, popatrz na inne kody i powinno Ci się udać. Co do reszty problemów to najpierw uporaj się z tym, a później będziemy walczyć dalej smile.gif
rozny
Czytam i kombinuję, ale coś nie idzie...

  1. function print_content() {
  2.  
  3. var content = document.newsletter.tresc.value;
  4.  
  5. document.getElementById('podglad').innerHTML = content;
  6.  
  7. }
  8.  
  9. var zdarzenie = document.getElementById('tresc');
  10. zdarzenie.onchange = print_content;


Sugerując się kodem zawartym w artykule, który mi podałeś urodziłem coś takiego. Nie działa wink.gif Stwierdziłem, że logicznym byłoby nasłuchiwać na zdarzenie, bo skąd skrypt ma wiedzieć, że coś się zmieniło skoro nie chcę tego wywoływać za pomocą html onchange. Dopisałem więc

  1. document.addEventListener(onchange, print_content, false);


Ale i tak nic mi to nie dało.

Wydaje mi się, że w jakiś sposób powinienem przekazać do skryptu zawartość przez this.value, ale z drugiej strony przecież robię to za pomoca tej linijki:

  1. var content = document.newsletter.tresc.value;


Bez przykładu chyba trudno mi będzie połapać się co robię nie tak.

Nie za bardzo rozumiem też w jaki sposób miałbym użyć zdarzenia document.onload, o którym wspominałeś w swoim pierwszym poście. Na chwilę obecną rozumiem tyle, że potrzebne by mi to było do sprawdzenia, czy dokument w ogóle został załadowany. Czyli sparowanie z ifami i jeśli załadowany, to wykonaj kod, a jeśli nie to nic nie rób. Tylko, po co mi to? wink.gif
kamil4u
Jest to po to, że teraz odwołujesz się do elementu, którego nie ma smile.gif Nie ma go bo nie jest zładowany. Dlatego zawsze trzeba poczekać na załadowanie się elementu i dopiero wtedy go wyszukać. Po to jest zdarzenie onLoad( do załadowania DOM-u istnieje też inne zdarzenie(lepsze), ale na razie je zostawmy ).
Kod
onload = function(){
//tu masz załadowany DOM
};


Jak Ci się uda to poprawię Twój kod, żeby był lepszy. Ale najpierw właśnie spróbuj zrobić, żeby działało. Aha! Zawsze patrz co pokazuje konsola błędów JS. Jako przyszyły programista JS to narzędzie jest Ci bardzo potrzebne.

Do dzieła smile.gif !
rozny
onload stosujemy na <body> tak? Teraz to rozumuję tak, że powinienem dać:

  1. <body onload="print_content();">


W ten sposób "coś" się dzieje. Tzn div, który domyślnie ma zawartość "aaaaaa" drukuje się "pusty", bo element textarea nie posiada żadnej wartości. Ale dodanie jakiejkolwiek treści w textarea nie zmienia już zawartości diva.

Kod wygląda tak:

  1. function print_content() {
  2.  
  3. var content = document.newsletter.tresc.value;
  4.  
  5. document.getElementById('podglad').innerHTML = content;
  6.  
  7. var zdarzenie = document.getElementById('tresc');
  8.  
  9. zdarzenie.onchange = print_content;
  10.  
  11. this.addEventListener(onload, print_content, false);
  12.  
  13. }


Dwie ostatnie linijki teoretycznie powinny dać ten sam wynik?
I co mnie zastanawia, to to że wewnątrz funkcji print_content() odwołuję się do funkcji... print_content(), co zdaje mi się być kompletną bzdurą wink.gif

Jeżeli chodzi o konsolę błędów, to nie zwraca żadnego błędu...
kamil4u
Nie nie nie smile.gif Nie dawaj żadnego onload w body. W ogóle zapomnij o atrybutach onload. onclick, onchange itd. . Używaj kodu JS tylko w plikach JS. Dałem Ci poprzednim razem gotowca. Ponieważ już jesteś naprawdę blisko to tu w pełni poprawny kod:
[JAVASCRIPT] pobierz, plaintext
  1. <textarea id="textarea"></textarea> <br> <hr> <br>
  2. <div id="div"></div>
  3.  
  4. <script>
  5. onload = function(){
  6. document.getElementById('textarea').onchange = function(){ //wstaw sobie tu inne zdarzenia np. onkeydown
  7. document.getElementById('div').innerHTML = this.value;
  8. }
  9. }
  10. </script>
[JAVASCRIPT] pobierz, plaintext


Napisz dokładnie czego nie rozumiesz i co Ci wyjaśnić bardziej. I poczytaj więcej o DOM, zdarzeniach itd. bo widać, że jeszcze tego nie rozumiesz smile.gif
Np. o addEventListener całkowicie nie zrozumiałeś, dlatego na początek proponuję korzystać z przypisywania zdarzeń w taki sposób jak w powyższym kodzie, żebyś jeden sposób załapał porządnie.
rozny
Dzięki, ale jednak nie o to mi chodzi. To co mi podałeś, napisałem już wcześniej i mój kod działał na zdarzenie onchange. Twój kod działa dokładnie tak samo - piszę w textarea i nic się nie zmienia, dopiero kiedy wyjdę z edycji textarea zawartość diva się zmienia. A ja chcę, żeby zawartość diva zmieniała się w trakcie pisania w textarea, czyli w textarea piszę "a" i dokładnie w tym samym momencie "a" pojawia się w divie...
Niktoś
  1. <textarea id="textarea"></textarea> <br> <hr> <br>
  2. <div id="div"></div>
  3.  
  4. onload = function(){
  5. document.getElementById('textarea').onkeydown = function(){ //wstaw sobie tu inne zdarzenia np. onkeydown
  6. document.getElementById('div').innerHTML = this.value;
  7. }
  8. }

Kolega Ci,napisał praktycznie gotowca,trzeba było tylko zmienić event ,z boku Tobie to zakomentował.W czym masz jeszcze problem?
Może poczytaj o eventach w js.
rozny
Faktycznie, gapa ze mnie i przegapiłem to wstydnis.gif Już wszystko śmiga jak należy, dzięki za pomoc yahoo.gif

Teraz muszę to przetrawić pod kątem parsowania treści... Jakieś wskazówki?

Cytat(kamil4u @ 2.03.2012, 00:28:33 ) *
O AJAX na pewno nie zahacza.
[...]
Poczytaj, popatrz na inne kody i powinno Ci się udać. Co do reszty problemów to najpierw uporaj się z tym, a później będziemy walczyć dalej smile.gif


Walczę teraz z kwestią przeparsowania tego wszystkiego przez skrypt PHP, jednak nie widzę innej opcji niż AJAX i XMLHttpRequest. Znowu jak czytam o tym, to niebardzo widzę jakby to miało działać, jeżeli wynik w divie drukujemy "po znaku". Any ideas?
Niktoś
Odpowiedzią może być:
http://www.doman.art.pl/kursjs/kurs/regular.html
rozny
Oczywiście, można wszystko przepuścić przez wyrażenia regularne, z tym że w tym celu musiałbym napisać kolejny kod, a dokładnie to samo mam już naklepane w PHP. Zastanawiam się teraz nad sensownością pisania dwa razy tego samego, tylko po to by wyświetlic poprawnie bbcode w podglądzie zdarzenia. Jak sądzicie? Z punktu widzenia szybkości zapewne to rozwiązanie będzie bardziej wydajne niż XmlHttpRequest i zabawa z "ajaxem"... Z drugiej zaś strony, zawsze bym się nauczył czegoś nowego wink.gif
Orzeszekk
Cytat(rozny @ 5.03.2012, 11:39:53 ) *
Oczywiście, można wszystko przepuścić przez wyrażenia regularne, z tym że w tym celu musiałbym napisać kolejny kod, a dokładnie to samo mam już naklepane w PHP. Zastanawiam się teraz nad sensownością pisania dwa razy tego samego, tylko po to by wyświetlic poprawnie bbcode w podglądzie zdarzenia. Jak sądzicie? Z punktu widzenia szybkości zapewne to rozwiązanie będzie bardziej wydajne niż XmlHttpRequest i zabawa z "ajaxem"... Z drugiej zaś strony, zawsze bym się nauczył czegoś nowego wink.gif


biblioteka Jquery ma bardzo wygodny ajax, ktory dziala pod kazda przegladarka i wyglada mniej wiecej tak:

$('div#ID_DIVA_KTORY_CHCESZ_ZAPELNIC").load("http://adres", { parametr_post_1: wartosc_parametru_post_1, parametr_post_2: wartosc_parametru_Post_2}, function () { /* funkcja wykonywana po zakonczeniu ładowania (callback) */ } );

zrob sobie tak jak ci wygodnie, a jak twoj portal bedzie odwiedzalo +200 userów jednoczesnie to przepiszesz sobie na najbardziej wydajną wersję.

mi jakby sie nie chcialo pisac wyrazen regularnych 2 raz po stronie klienta to bym zrobil tak. Ustawilbym sobie w onchange edytora tekstowego event handler ktory liczy do 5 sekund i jesli inny klawisz nie zostanie w tym czasie nacisnięty, wysyła ajaxowe żądanie do serwera przesylajac mu jako parametr zawartosc pola tekstowego. Serwer przetwarza to, i odpowiada sparsowanym bbcode przeznaczonym do wyswietlenia w divie. wszystko to mozesz zrobic za pomoca funkcji $(obiekt).load. po stronie serwera wydziel sobie parsowanie kodu bbcode do oddzielnej funkcji ktora przyjmuje za parmetr tekst z bbcode a zwraca np html, umiesc to w oddzielnym pliku php, i ten plik wywołuj przez jquery i voila.

w momencie jak wysyłasz żądanie po 5 sekundach, mozesz do tej funkcji robiącej zapytanie ajaxowe dorzucic rowniez funkcje ktora w divie ustawi jakiegos kręcącego się dookoła gifa zeby bylo widac ze się ładuje i juz, i bedzie fajnie wyglądało.
rozny
Poradziłem sobie ze wszystkimi zagadnieniami. Wyszło mi coś takiego:

  1. onload = function () {
  2.  
  3. document.getElementById('tresc').onkeyup = function () {
  4.  
  5. var tablicaBBC = new Array(
  6.  
  7. new RegExp ('\\[b\\](.*?)\\[\\/b\\]', 'gi'),
  8. new RegExp ('\\[u\\](.*?)\\[\\/u\\]', 'gi'),
  9. new RegExp ('\\[i\\](.*?)\\[\\/i\\]', 'gi'),
  10. new RegExp ('\\[center\\](.*?)\\[\\/center\\]', 'gi'),
  11. new RegExp ('\\[url\\](.*?)\\[\\/url\\]', 'gi'),
  12. new RegExp ('\\[img\\](.*?)\\[\\/img\\]', 'gi'),
  13. new RegExp ('\\[cytat\\](.*?)\\[\\/cytat\\]', 'gi'),
  14. new RegExp ('\\[cytat=(.*?)\\](.*?)\\[\\/cytat\\]', 'gi'),
  15. new RegExp ('\\[YT\\](.*?)\\[\\/YT\\]', 'gi'),
  16. new RegExp ('\\[size=(.*?)\\](.*?)\\[\\/size\\]', 'gi'),
  17. new RegExp ('\\[color=(.*?)\\](.*?)\\[\\/color\\]', 'gi'),
  18. new RegExp ('\n', 'gi')
  19. );
  20.  
  21. var records = tablicaBBC.length;
  22.  
  23. var tablicaHTML = new Array(
  24.  
  25. '<span style="font-weight: bold;">$1</span>',
  26. '<span style="text-decoration: underline;">$1</span>',
  27. '<span style="font-style: italic;">$1</span>',
  28. '<p style="text-align: center;">$1</p>',
  29. '<a href="http://$1">$1</a>',
  30. '<img src="$1" border="0" />',
  31. '<fieldset class="quote">$1</fieldset>',
  32. '<fieldset class="quote"><legend>$1:</legend>$2</fieldset>',
  33. '<iframe width="560" height="315" src="http://www.youtube.com/embed/$1" frameborder="0" allowfullscreen></iframe>',
  34. '<span style="font-size: $1em;">$2</span>',
  35. '<span style="color: $1;">$2</span>',
  36. '<br />'
  37.  
  38. );
  39.  
  40. function parse_bbcode(input) {
  41.  
  42. for (var i = 0; i < records; i++) {
  43.  
  44. input = input.replace(tablicaBBC[i], tablicaHTML[i]);
  45.  
  46. }
  47.  
  48. document.getElementById('podglad').innerHTML = input;
  49.  
  50. }
  51. parse_bbcode(this.value);
  52.  
  53. }
  54. }


Pewnie nie jest to jakoś nadzwyczajnie eleganckie, ale działa smile.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.