Posts Tagged javascript
Czym Ajax jest, a czym nie?

ajax
Wpadłem ostatnio na dość ciekawą kwestię – błędne pojęcie na temat ajaxa skutkuje czasem błędną (bardziej skomplikowaną niż trzeba) implementacją jakiejś funkcjonalności.
Problem jest następujący: użytkownik wpisuje kod. My sprawdzamy go na serwerze i jeśli jest prawidłowy, to zwracamy pewne powiązane z nim właściwości (np. wysokość rabatu) i pewien komunikat, który musi być wyświetlony na stronie (np. w przypadku błędnego kodu “kod promocyjny jest niepoprawny”. Dodatkowe wymaganie jest takie: wysokość rabatu ma się pojawić koło ceny całkowitej, cena ma się zmniejszyć o ten rabat, a komunikat ma się pojawić nad przyciskiem “Zamów”, które jest w fizycznie w innym miejscu niż cena. Dobrze by było, gdyby w wypadku nieprawidłowego kodu przycisk zamów był nieaktywny.
Jeśli o Ajaxie myślisz tylko jak o sposobie na podmienianie fragmentów strony bez przeładowania to możesz skończyć z takim dziwadłem:
Wysyłasz trzy ajaxy – jeden update’uje jakiś element z rabatem, drugi pole z wiadomością, a trzeci (o zgrozo) przesyła kod html przycisku (raz disabled, raz enabled). No i jeszcze parsujesz, tniesz i sklejasz zwrócony rabat, żeby odjąć go od ceny.
Teraz zacznij myśleć o Ajaxie, który jest sposobem na komunikację z serwerem bez potrzeby przeładowania strony (przeładowanie strony to też komunikacja z serwerem – my pytamy, on odpowiada, o coś prosimy, serwer coś robi). Do tego po otrzymaniu odpowiedzi z serwera możemy z nią zrobić co chcemy – nie musi się automatycznie i bezmyślnie ładować do diva #ajaxResponseToParse
I w końcu, jeśli jeszcze nie wiesz, dowiedz się co to znaczy JSON.
Jeśli dodasz te trzy składniki to możesz skończyć z takim rozwiązaniem:
$.getJSON("http://example.com/check_code/XXX", function(data){
$("#discount-ammount") = data.discount;
$("#price").html(data.new_price); // *
$("#message").html(data.message);
$("#submit").get(0).disabled = data.submit_disabled;
});
(*) myślę, że dobrze takie rzeczy liczyć w jednym miejscu po stronie serwera.
Albo jednym słowem – wyjdź poza wygodne schematyczne myślenie i rozejrzyj się wokół. Możliwe, że wbijasz wkręt obcasem siedząc na młotku i gwoździe mając w kieszeni.
Krótka wskazówka – outline obiektowego Javascript w Eclipse
Jeśli używasz Eclipse, piszesz kod Javascript i piszesz go obiektowo może Cię to zainteresować.

Pewnie dobrze wiesz, że jest wiele sposobów na pisanie obiektowego Javascriptu, możesz o różnicach poczytać wszędzie. Jednak moim pragnieniem było, aby eclipse był w stanie pokazać mi outline aktualnie edytowanego pliku js. Po kilku próbach stwierdzam, że działa następujący sposób:
var Klasa = function(){
this.x = 1; //definicja pól
}
//definicja metod
Klasa.prototype.setX = function(parametr){
this.x = parametr;
}
Jak zrobić callback w javascript – minitutorial.
Jedną z największych magicznych mocy wszystkich frameworków i pluginów javascript jest możliwość rozszerzenia ich działania poprzez tak zwane callbacks. Pokażę Wam jak wykonać własny obiekt javascript, który będzie potrafił je obsłużyć.
Po pierwsze potrzebujesz zdefiniować swoją klasę:
function myClass(params){
}
Prościzna
Spróbujmy teraz obsłużyć callback beforeInit, który odpali się “najsampierw” przy tworzeniu obiektu:
function myClass(params){
if(params.beforeInit){
console.log("beforeInit");
params.beforeInit();
}
console.log("Init complete")
}
console.log("=============");
var a = new myClass(
{
beforeInit: function(){console.log("My message!");}
}
);
Włącz firebuga i sprawdź działanie
============= beforeInit My message! Init complete
Oczywiście Twoja klasa może zechcieć coś zrobić oprócz stworzenia siebie samej
Callbacki mogą zachowywać się różnie w zależności od stanu obiektu. Do klasy dodałem metodę doSth i callback beforeRun (który wykonuje się przed wykonaniem metody doSth)
Wypróbuj następujący kod:
function myClass(params){
if(params.beforeInit){
console.log("#beforeInit");
params.beforeInit();
}
this.doSth = function() {
if(params.beforeRun){
params.beforeRun(this.state);
}
console.log("#doSth");
}
if(params.state) {
this.state = params.state;
}else{
this.state = false;
}
console.log("Init complete")
}
console.log("=============");
var a = new myClass(
{
state: 1,
beforeRun: function(state){
if(state != false) {
console.log("Extended! state = " + state);
}else {
//do nothing
}
}
}
);
a.doSth();
console.log("=============");
var b = new myClass(
{
beforeRun: function(state){
if(state != false) {
console.log("Extended! state = " + state);
}else {
//do nothing
}
}
}
);
b.doSth();
wynik:
============= Init complete Extended! state = 1 #doSth ============= Init complete #doSth
Możesz też uzależnić wykonanie metody doSth w zależności od warunków wewnętrznych (parametr state) lub zewnętrznych:
function myClass(params){
if(params.beforeInit){
console.log("#beforeInit");
params.beforeInit();
}
this.doSth = function() {
if(params.beforeRun){
if(!params.beforeRun(this.state)){
return;
}
}
console.log("#doSth");
}
if(params.state) {
this.state = params.state;
}else{
this.state = false;
}
console.log("Init complete")
}
console.log("=============");
var a = new myClass(
{
state: 1,
beforeRun: function(state){
if(state != false) {
console.log("Extended! state = " + state);
}else {
return false
}
}
}
);
a.doSth();
console.log("=============");
var b = new myClass(
{
beforeRun: function(state){
if(state != false) {
console.log("Extended! state = " + state);
}else {
return false
}
}
}
);
b.doSth();
console.log("=============");
var c = new myClass(
{
beforeRun: function(state){
if( (new Date().getTime())%2 ) {
console.log("Extended! state = " + state);
}else {
return false
}
}
}
);
c.doSth();
Wynik (zależy od aktualnego czasu, więc może okazać się konieczne uruchomienie go kilka razy, zanim otrzymasz identyczny):
============= Init complete Extended! state = 1 ============= Init complete ============= Init complete Extended! state = false
W przypadku obiektu c metoda run odpali się tylko, jeśli aktualny timestamp jest podzielny przez 2
To tyle. Mam nadzieję, że pozwoli Wam to wymyślać ciekawsze i bardziej użyteczne fragmenty kodu javascript, nawet tego używanego prywatnie.
Sprytnie zaprojektowana klasa ze sprytnymi callbackami jest bardzo przyjemna – możliwe jest modyfikowanie jej zachowania bez modyfikacji klasy bazowej. To samo podejście znacie pewnie z Behaviors cake’a.