310 likes | 503 Views
Tworzenie Aplikacji Internetowych. 8. dr Wojciech M. Gańcza. Serwer i Klient. Serwer przetwarza zlecenia od wielu klientów. Klient pracuje na potrzeby pojedynczego użytkownika Moc obliczeniowa komputerów klientów jest porównywalna z mocą obliczeniową serwerów
E N D
Tworzenie Aplikacji Internetowych 8 dr Wojciech M. Gańcza
Serwer i Klient • Serwer przetwarza zlecenia od wielu klientów. • Klient pracuje na potrzeby pojedynczego użytkownika • Moc obliczeniowa komputerów klientów jest porównywalna z mocą obliczeniową serwerów • Większość mocy używana jest do obsługi do obsługi interfejsu graficznego
Serwer i Klient… • Szkoda by moc obliczeniowa klienta się marnowała • Można z niej skorzystać! • Na stronie można umieścić program który będzie wykonywany w czasie tworzenia strony <script> ... </script>
Programy sterowane zdarzeniami • Programy na serwerze przygotowują stronę w czasie pojedynczego uruchomienia programu • Programy po stronie klienta też mogą tak działać • Ale nie muszą… • Mogą też reagować na zdarzenia modyfikując dane w kontrolkach lub zawartość strony • Język: JavaScript
DOM • DOM – Document Object Model – to zbiór obiektów które pozwalają na dostęp do zawartości okna przeglądarki. • Niemal każdy element może być dostępny z poziomu kodu • W wielu wypadkach taki element musi mieć określony identyfikator <div id=”nazwa”>
JavaScript • Język JavaScript ma składnie bardzo podobna do C++; • Nie ma tu jednak ścisłej typizacji zmiennych – jak w PHP • Kod umieszczony na stronie może być wykonany w czasie ładowania dokumentu • Jeśli zadeklarujemy funkcje – to będą wykonane w momencie wywołania
Tabliczka mnożenia <script> document.write(”<table>”); for (var i=0; i<10; ++i) { document.write(”<tr>”); for (var j=0; j<10; ++j) { document.write(”<td>” + (i*j) + ”</td>”); } document.write(”</tr>”); } document.write(”</table>”); </script>
Zdarzenia • Z każdym elementem związane są określone zdarzenia. • Zdarzenia związane są z akcjami użytkownika albo ze zmiana stanu wyświetlanej strony • Funkcje obsługi zdarzeń można zdefiniować jako właściwości odpowiednich znaczników HTML albo właściwości obiektów DOM
Kalkulator… <html> <body> <form name="f1"> <input type="text"id="a"> x <input type="text"id="b"> <input type="button"value="="onclick="calc();"> <input type="text"id="s"disabled> ... </form> </body> </html>
Kalkulator… <script> function calc() { var a = document.getElementById("a").value; var b = document.getElementById("b").value; document.getElementById("s").value = a * b; } </script> • Można też inaczej – zamiast czekać na naciśnięcie przycisku – można reagować na zmianę zawartości komórki:
Kalkulator … <input type="text"id="a" onchange="calc();"> x <input type="text"id="b" onchange ="calc();"> = <input type="text"id="s"disabled> • Teraz iloczyn jest liczony po każdej zmianie zawartości kontrolki … • Czyli po zakończeniu jej edycji – gdy już ją opuścimy • Jak zrobić by obliczenia były wykonywane od razu?
Kalkulator… • Zdarzenie ‘onkeydown’ wołany jest zanim wartośc kontrolki się zmieni • Podobnie ‘onkeypress’ • Natomiast ‘onkeyup’ jest idealne do naszych zastosowań <input type="text"id="a" onkeyup="calc();"> x <input type="text"id="b" onkeyup="calc();"> = <input type="text"id="s"disabled>
Inny przykład • Kontrolka pozwalająca na wprowadzanie liczb (na przykład do kwot) wymaga sprawdzenia • Czy wprowadzane są tylko liczby • Czy jest tylko jeden separator dziesiętny (dopuszczamy zarówno kropkę jak i przecinek) • Po zakończeniu edycji – formatujemy liczbę zaokrąglając do dwu miejsc po przecinku
Kontrolka do kwot • Nie dopuszczenie do wprowadzenia innych znaków niż liczby i separator wymaga filtrowania zdarzeń • Jest to możliwe dzięki modyfikacji zdarzenia • Warto sprawdzić czy zdarzenie może być odwołane (-> w3c) • I w jaki sposób • Poprzez zwrócenie wartości false • Czy poprzez nadpisanie danych zdarzenia
Kontrolka do kwot… <input style="width: 64px; height: 22px; text-align: right" type="input" name="id"id="id" value="0,00" onchange="reformat(this);" onkeypress="checkCharacter(event, this);" onkeydown="checkCharacter(event, this)">
Połykanie znaków • Zauważmy, że musimy zareagować zarówno na zdarzenie onkydown jak i onkeypres • Definiując wywołanie zdarzenia – możemy przekazać parametry. • Zauważmy, że możemy przekazać this – zdarzenia zachowują się tu jak metody (choć w funkcji obsługi zdarzenia do this dostępu nie ma jeśli nie było przekazane • Można przekazać obiekt zdarzenia.
Sprawdzenie znaku function checkCharacter(event, obj) { x = obj.value; p = x.indexOf('.'); if (p == -1) p = x.indexOf(','); v = event.charCode; if (v == undefined) v = event.keyCode; if (v < 32) return true;
Sprawdzenie znaku … v = String.fromCharCode(v); if ((v > '9' || v < '0') && !(((v == ',') || (v == '.')) && (p<0))) { event.charCode = 0; event.keyCode = 0; return false; } return true; }
Przeformatowanie function reformat(x) { v = x.value; v = v.replace(',', '.'); a = Number(v); i = Math.floor(a); f = Math.round(100*(a - i)); if (f == 0) f = "00"; else if (f < 10) f = "0" + String(f); else f = String(f); v = String(i) + "," + f; x.value = v; }
Inne kontrolki • W podobny sposób możemy przygotować elementy edycyjne do wprowadzania identyfikatorów, kodów czy statusu kodowanego na pojedynczym znaku • Możemy także pokładać element edycyjny z kilku – na przykład dołączyć do pola tekstowego kilka przycisków służących do zmiany wartości
Kontrolki a źródło danych • Źródło danych dostarcza dane do wyświetlenia lub do dalszego przetwarzania • Jeśli potrzebujemy tabelki zawierającej elementy edycyjne – nic prostszego • Jest tylko niewielki problem – nazwy • Można je tworzyć z jakiegoś stałego tekstu oraz identyfikatora rekordu
Formater elementów edycyjnych class FormatEdit extends RecordsetFormater { var$name; var$idField; function FormatEdit(&$recordset, $fieldsList, $name, $idField) { $this->RecordsetFormater(&$recordset, $fieldsList); $this->name= $name; $this->idField = $idField; } function getId() { return $this->name . $this->currentRecord[$this->idField]; } }
Formater kwot class FormatMoneyEdit extends FormatEdit { function FormatMoneyEdit(&$recordset, $fieldsList, $name, $idField) { ... } function format($field) { $id = $this->getId(); ... return"<input style=\"width: 64px; height: 22px; text-align: right\" type=\"input\" name=\"" . $id . "\" id=\"" . $id . "\" value=\"" . $field . "\"" . "onchange=\"reformat(this);\ " onkeypress=\"checkCharacter(event, this)\ " onkeydown=\"checkCharacter(event, this)\"> "; } }
Formater kwot… • Warto jeszcze sformatować przychodzącą wartość pola: if ($field != "") { $integral = (int)($field); $fraction = round(100*($field – $integral)); $frac = ","; $field = (string)($integral); if ($fraction < 10) $field = $field . ',0' . $fraction; else $field = $field . ',' . $fraction; }
Inne elementy • Podobnie możemy przygotować formatery dla innych elementów edycyjnych • Dość przydatne mogą okazać się elementy typu checkbox • Jest z nimi jeden problem – nie zaznaczone – nie są przesyłane • Zastanówmy się jednak do czego mogą służyć w tabelce
Zaznaczenia • Element checkbox może służyć do zaznaczania pozycji do dalszych działań • Bardziej przydatna będzie kolekcja wybranych identyfikatorów niż pole binarne w źródle danych • Inne zastosowanie: włączanie lub przełączanie edytowalności innych elementów – ale po kolei…
Zaznaczenia • Warto przygotować sobie klasę na zaznaczone elementy class SelectedItems { var$items; var $name; function SelectedItems($name) { $this->name = $name; $cntrl = new Control($name, null); if ($cntrl->value == null) $this->items = array(); else if (is_array($cntrl->value)) $this->items = $cntrl->value; else $this->items = explode("|", $cntrl->value); }
Zaznaczenia… function is($id) { if (in_array($id, $this->items) == false) return false; else return true; } function render(&$output) { $output->out( "<input type=\"hidden\„ name=\"" . $this->name . "\" value=\"" . implode("|", $this->items) . "\">"); } }
Zaznaczenia… class FormatCheckbox extends RecordsetFormater { var$name; var$selected; function FormatCheckbox (&$recordset, $fieldsList, $name, $selected) { $this->RecordsetFormater(&$recordset, $fieldsList); $this->name = $name; $this->selected = $selected; } function format($field) { return"<input type=\"checkbox\" name=\"" . $this->name . "[]\" id=\"" . $this->name . $field . "\" value=\"" . $field . >"; } }
W następnym odcinku • Wracamy do aplikacji – budujemy listę książek • Pozwalamy na zaznaczanie • Edycja książek – różne sposoby edycji w zależności od potrzeb • Zbliżamy się do podstawowej funkcjonalności programu