Niezamierzony efekt a la Adblock na stronie Citi Handlowy Grzegorz Wójcik

Konsola JS w Google Chrome
Konsola JS w Google Chrome

Ostatnimi czasy coraz częściej przeglądam WWW za pomocą Chrome, ba – można powiedzieć nawet, że produkt Google stał się moją podstawową przeglądarką. Lubię proste i szybkie aplikacje, hołdujące idei KISS (ang. Keep It Simple, Stupid) a Chrome z pewnością się do nich zalicza.

Właśnie używając Google Chrome natrafiłem ostatnio na frapujący problem na stronie głównej banku Citi Handlowy, dostępnej pod adresem www.online.citibank.pl. Otóż, w przeglądarkach opartych o silnik WebKit (czyli również w Safari) na rzeczonej stronie nie zobaczymy ani jednej reklamy (sic!). Przypomina to trochę efekt działania popularnego Adblocka i wygląda w ten sposób:

Rendering strony banku - WebKit versus pozostałe silniki

Reklam jak wiadomo nikt za bardzo nie lubi, więc ich brak można z pewnością przeżyć (chociaż nie jestem pewien, czy takie same zdanie ma również dział marketingu w Citi) – ale niepokoi również niedziałająca sekcja Aktualności (czerwona strzałka), która dla klientów ma jednak dosyć istotne znaczenie.

W trosce o user-experience wszystkich klientów banku Citi będących użytkownikami Maców (oni też mają prawo do równouprawnienia), postanowiłem charytatywnie zdiagnozować źródło powyższego problemu. Charytatywnie – bo jak wiadomo mamy kryzys finansowy i różne komórki w bankach przechodzą teraz ciężkie chwile (czytaj: restrukturyzacje) :)

Diagnoza problemu – czyli pamiętaj o konsoli błędów

W IE6 błędy JavaScript sygnalizowane są przez ikonkę, która pojawia się na dole w pasku statusu i która widoczna jest jak byk dla każdego użytkownika tej przeglądarki. W nowszych przeglądarkach (Chrome, Safari) błędy JS nie są już sygnalizowane w tak oczywisty sposób. Co nie znaczy, że nie istnieją. Trzeba się tylko do nich dokopać.

W Google Chrome konsolę JS odpalamy wciskając kombinację klawiszy Ctrl+Shift+J lub wybieramy odpowiednią pozycję z menu (Opcje strony > Dla programistów > Konsola JavaScript). Trochę trudniej jest w Safari. W menu Edycja > Preferencje na karcie Zaawansowane zaznaczamy ptaszek przy opcji Pokaż menu Programowanie w pasku menu a następnie w zmaterializowanym menu Programowanie wybieramy pozycję Pokaż konsolę błędów.

Uzbrojeni w tą tajemną wiedzę, zobaczmy co wysypuje się na stronie banku:

Raport konsoli błędów JS w Safari/Chrome

Komunikaty nie pozostawiają wątpliwości – znamy już przyczynę niedziałającej sekcji Aktualności. Pod lupę weźmy skrypt aktualnosci.js i okolicę problematycznego wiersza nr 35:

  1. if(window.ActiveXObject) {
  2. xml=new ActiveXObject("Microsoft.XMLDOM");
  3. } else if(document.implementation.createDocument) {
  4. xml=document.implementation.createDocument("", "", null);
  5. } else { }
  6.  
  7. xml.async=false;
  8. xml.load("/retail/files/citiblue/aktualnosci.xml"); //na ten wiersz narzeka WebKit
  9. items = xml.getElementsByTagName('item');

Z powyższego fragmentu kodu łatwo wywnioskować jak działa sekcja Aktualności – za pomocą JS pobierany jest plik XML (aktualnosci.xml) i na jego podstawie budowana jest tablica newsów do wyświetlenia (items). Co ciekawe – ten plik XML ma format RSS (a RSS to przecież XML), więc ukłony w stronę twórców za pomysłowe wykorzystanie RSSa jako źródła danych dla skryptu. To co może jednak dziwić to sposób pobrania tego XMLa, wykorzystujący stosunkowo mało popularny obiekt Microsoft.XMLDOM. Obiekt ten przypomina dobrze znany AJAXowy Microsoft.XmlHttp, z tym że pozwala dokonywać prostych i trochę bardziej zaawansowanych operacji na fragmentach XML – i co ciekawe – również udostępnia metodę load, za pomocą której możemy wczytać do niego łańcuch XML z pliku na serwerze. W przypadku IE obiekt jest tworzony w linii nr 2, w reszcie przeglądarek (Firefox, Opera, Safari, Chrome) obiekt tworzy linia nr 4 (metoda ta opisywana jest w paru miejscach w Sieci jako zamiennik tej z IE). I tutaj zaczyna się problem. Twórca skryptu błędnie założył, że obiekt xml stworzony w IE i reszcie przeglądarek udostępnia taką samą funkcjonalność i takie same metody. Niestety – nie jest tak do końca. Otóż, o ile w Firefoxie i Operze na utworzonym obiekcie możemy wywołać metodę load (linia 8) i zadziała ona zgodnie z oczekiwaniami tak jak w IE, to jednak nie będzie to miało miejsca w przypadku przeglądarki bazującej na WebKicie.

Powyższą sytuację możemy dokładnie prześledzić na tej przykładowej stronie.

Jak widać, błąd jest na tyle paskudny, że zatrzymuje wykonywanie następujących po nim instrukcji. Tłumaczy to fakt braku flashowych reklam, które umieszczane są również za pomocą JavaScript (ten sposób pozwala obejść słynny problem patentowy Eolas w IE).

Rozwiązanie

Jest bardzo proste. Należy porzucić pomysł z wykorzystaniem problematycznego obiektu Microsoft.XMLDOM i oprzeć się na starym dobrym Microsoft.XmlHttp (vel XMLHttpRequest). Przecież w udostępnianej przez XHR właściwości responseXML mamy również fragment XML, który możemy parsować (np. za pomocą getElementsByTagName). Jako, że na rzeczonej stronie bankowej mamy dostęp do jQuery, nie musimy się nawet bawić we własne wrappery na XHR i możemy po prostu zrobić coś takiego:

  1. $.ajax({
  2. type: "GET",
  3. url: "aktualnosci.xml",
  4. success: function(xml){
  5. items = xml.getElementsByTagName('item');
  6. }
  7. });

I oto działające rozwiązanie.

Konkluzja

Przede wszystkim kłania się testowanie wyglądu i działania strony pod popularnymi przeglądarkami. Nie jest ich przecież tak dużo (wystarczy IE, Firefox, Safari/Chrome, Opera). Warto też, przed wykorzystaniem jakiegoś kawałka kodu znalezionego w Internecie, zastanowić się nad jego interakcją z pozostałymi skryptami/elementami strony. W przypadku dużych stron głównych, na których z natury rzeczy „dużo się dzieje” o takie wpadki nietrudno.

Grzegorz Wójcik

Grzegorz Wójcik jest założycielem internetowego magazynu kminek.pl. Pasjonat i twórca lekkich, dostępnych i użytecznych stron internetowych budowanych w oparciu o standardy sieciowe i najlepsze praktyki. Prywatnie wielki miłośnik ambitnego kina sci-fi oraz grunge-rocka z lat 90.

Zobacz wszystkie artykuły tego autora (15)

  1. SpeX 1

    I wysłałeś informację o błędzie do Citi?

  2. tomek 2

    a mi sie wydaje ze to reklamowka citi-banku ;-)

  3. Greg 4

    Niezły artykuł. Wydaje mi się, że programiści Citi nie mają zbyt wielkiego doświadczenia z JScript. Bardziej poprawne podejście z pracą na wielu przeglądarkach to zamienić:

    1. xml.load("/retail/files/citiblue/aktualnosci.xml"); //na ten wiersz narzeka WebKit

    na

    1. if(xml.load) {
    2. xml.load("/retail/files/citiblue/aktualnosci.xml"); //na ten wiersz narzeka WebKit
    3. }else{
    4. /*obsłużyć błąd, np. prośbę o wysłanie komunikatu o błędzie w miejscu gdzie powinnny znaleźć się aktualności */
    5. }
  4. Aznar 5

    Ciekawe kto się zajmuje strona citi? może po prostu nikt z ich klientów nie używa chrome :P albo nikomu nie przeszkadza brak reklam :) Trzeba zgłosić i tyle :)

Dodaj komentarz * pola obowiązkowe

 
 

Dozwolone tagi HTML: <strong> <em> <a href="" title=""> <code> <pre lang=""> <blockquote cite="">

Komentarze są moderowane. Mile widziane wpisy wnoszące nowe, ciekawe informacje do omawianego tematu
lub sygnalizujące ewentualne błędy merytoryczne. Wszelkie przejawy spamu lub nieetycznego zachowania bedą
karane blokadą adresu IP/domeny.