Posts Tagged javascript

Czym Ajax jest, a czym nie?

ajax

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.

, ,

No Comments

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;
}

, ,

No Comments

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.

No Comments