Perfection or Vanity

Project: Terminated

Blog nie jest już dalej prowadzony ani aktualizowany. Mimo tego, wpisy i komentarze są dalej dostępne. Możesz przeczytać pożegnalny wpis albo przejść do archiwum.

Evil Greasemonkey

Jakiś czas temu pragnąc napisać kolejny skrypt użytkownika (uwielbiam modyfikować strony via UserCSS / UserJS) otworzyłem about:config, aby sprawdzić wartość jednej zmiennej.

Jakież było moje zdziwienie, gdy po kilkunastu sekundach Firefox oznajmił mi, że skrypt na tej stronie może nie odpowiadać. Wybrałem jednak kontynuowanie pracy i wreszcie po kolejnym oczekiwaniu pojawił się spis. Byłem ciekaw o co chodzi i sprawdziłem w profilu plik prefs.js przechowujący wpisy z about:config. Rozmiar przekraczał 15MB!

Okazało się, że wszystkie większe skrypty zapisywały w preferencjach dane pod postacią zmiennych. Rekordzistami okazały się skrypty parsujące XML-e z Last.fm.

Zapisywanie i odczytywanie zmiennych w Greasemonkey jest proste jak drut - służą do tego funkcje GM_getValue i GM_setValue. Wygląda na to, że z powodu tej prostoty są nadużywane. Podany wyżej przykład dobrze ilustruje czemu nie należy traktować pliku preferencji jako własnej bazy danych.

Alternatywa - globalStorage

Czego można używać w zamian? Wprowadzonej w Firefoksie 2 metody na przechowywanie danych globalStorage – zaczerpniętego ze szkicu HTML5 1.

GlobalStorage definiuje przestrzeń dla każdej domeny, w której możemy zapisywać dowolne dane - będą one zachowane do momentu skasowania, a dostęp do nich ma każdy skrypt działający w obrębie tej domeny.

  1. var glStorage = globalStorage.namedItem(document.domain);

Taki kod stworzy nam obiekt, do którego możemy wkładać i wyjmować dane. W przypadku skryptów użytkownika, często działających symultanicznie na jednej stronie zaleca się dodawanie specyficznych prefiksów. Przykładowo:

  1. var namespace = 'my.script.globalstorage.test' + '.';
  2. var glStorage = globalStorage.namedItem(namespace + document.domain);

Specjalnie zaznaczyłem obecność ostatniej kropki, ponieważ jej usunięcie zaskutkuje błędem 2. Do zapisania danych służy setItem(), do odczytania getItem(), a usunięcia removeItem().

  1. glStorage.setItem('linki-nowe-okno', 'tak'); //klucz, wartość
  2. glStorage.getItem('linki-nowe-okno', 'nie'); //klucz, wartość domyślna
  3. glStorage.removeItem('linki-nowe-okno'); //klucz

Klucz to inaczej adres pod który się udajemy w tym dużym zbiorze danych, aby wykonać operacje na jednej z nich.

UserJS = Greasemonkey?

Mam już sposób na wygodne zapisywanie danych, ale zastanowiłem się czy to wszystko czego potrzebuję. Co będzie, gdy ktoś uruchomi mój skrypt na Firefoksie 1.5? Albo na Operze? Potrzeba większej elastyczności. Postanowiłem więc napisać uniwersalne funkcje korzystające progresywnie z trzech sposobów zapisu danych.

  1. globalStorage
  2. GM_getValue, GM_setValue
  3. document.cookie

Zadeklarowany wcześniej namespace nam się przyda także do 2 i 3 punktu (nazwy na pewno nie będą się powtarzać). Nie będę wnikał w strukturę całego skryptu, zwłaszcza że jest dość przejrzysty – obejrzyjcie go sami:

Pobierz: globalstorage.user.js

Kod tworzy 3 funkcje - setValue(), getValue() i remValue() do wykorzystania w jakimkolwiek UserJS.

Zobaczyć, że działa (prosty zapis i odczytanie wartości) możecie na stronie testowej.

Dyskusyjne może być użycie funkcji Gmk dla Fx 1.5 i niższych - ale dodałem ten kod, bo zależy w sumie co przechowujemy i jak dużo tych danych jest. Gdyby okazało się, że potrzebujemy dla skryptu prawie bazy danych, to polecam zrezygnować z wspierania poprzednich wersji Firefoksa. No i tym bardziej ciasteczek. A Opera mogłaby udostępnić jakiś inny mechanizm zapisu danych (choćby userData MS).

Tak czy inaczej, uważam że preferencje przeglądarki nie powinny być zaśmiecane wpisami skryptów i twórcy Greasemonkey poszli na łatwiznę. Prośba, abyście Wy nie szli. :)

  • 1) wtedy Web Applications 1.0
  • 2) Odwołamy się do innej domeny (testexample.com), a to wyrzuci błąd bezpieczeństwa.

Informacje i hiperłącza

Blog o projektowaniu zgodnych ze standardami stron internetowych.

Praktyczne przykłady, sztuczki CSS, sposoby obchodzenia błędów przeglądarek, lekki i nieinwazyjny JavaScript, użyteczny design, dostępność i skrypty użytkownika.

RSS

Informacje o wpisie

Napisał riddle 23 maja 2007 o 05:07

Kategorie: Greasemonkey, JavaScript & DOM

Dodaj do:

Wpisy archiwalne

Archiwum miesięczne

Dzięki!

Dodaj bloga do Technorati Favorites Dodaj bloga do Del.icio.us Blog należy do sieci 10przykazań.com

  1. a dostęp do nich ma każdy skrypt działający w obrębie tej domeny

    Zaznaczę jeszcze tylko, że tego na razie nie jestem pewien, a jest zbyt późno żebym dociekał.

  2. (Komentarz zmodyfikowany 23.05.2007 o 16:50)

    //sorry za małego offtopa, ale 1400 osób Cię śledzi, nieźle. Gratki. ^^

  3. Tom Sieron 3 23 maja 2007, 14:50

    Alternatywnie możnaby użyc Flash local shared object (http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=tn_16194).

    AFAIR Dojo ma plugin do uzywania tego w miare prosto do przechowywania danych po stronie klienta. Kiedys na newsgrupie jQuery ktos wspominal ze chcialby napisac plugin do tego ale chyba nic z tego nie wyszlo w koncu, a szkoda. Nie masz moze wolne pol godzinki zeby cos takiego napisac? :)

  4. OK, ciekawe rozwiązanie to Storage, ale co zrobić w takiej sytuacji: jest sobie add-on stworzony kompilatorem skryptów Greasemonkey i przydałoby się ustawić domyślne wartości pewnych ustawień przy instalacji. Jeśli używa się preferencji przeglądarki, sprawa jest prosta: plik defaults.js w chrome://<nazwa>/defaults/preferences/ i wszystko gra. A jak osiągnąć taki efekt przy zastosowaniu Storage? Jakichś magicznych skryptów instalacyjnych by trzeba pewnie :-(

  5. @riddle: slyszales o Google Gears? http://code.google.com/apis/gears

    Poszukaj na necie…
    Na pewno znajdziesz wiele dem (demów? :> joke) ukazujacych potencjał GG…

  6. Czy słyszałem? Oczywiście. :]

  7. Wybacz… nie czytam „wszystkiego” ;)

    Odnosnie twojego wpisu – zerknij do dokumentacji API:
    http://code.google.com/apis/gears/api_database.html
    „(on/off)-line” to tylko kropla w morzu zastosowan tego cacka ___

  8. ciekawe rzeczy piszesz :)) pozdr

  9. Hey Dude,

    dansk is one of the languages that i dont spaek :)
    But i like to ask for MySQL storage of the Note Data.
    I got a MySQL server up an running and i play with some guys an Travian account dual. So we dont like to play with damed PLUS. As we have installed your Note Script we think about the storage of the date by the way to MySQL.
    I think its not a real problem to build it in, but im not able to do it. Is it posible that you like to show us how we can make it?

    Ok thanks for any help for this!

  10. Hi.

    It’s Polish actually. ;) The solution I presented in the post bases on UserJS, JavaScript – not SQL of any kind, I’m sorry.

Dodaj komentarz

Do formatowania komentarzy używaj Textile (HTML nie działa). Szczególnie jeśli wklejasz większe fragmenty kodu. W razie niepewności użyj podglądu komentarza.

Wypowiedzi obraźliwe, infantylne oraz nie na temat będą moderowane – pisząc postaraj się zwiększyć wartość dyskusji.

Komentarze nie służą do wysyłania wiadomości albo informowania o błędach, itd. Chcesz coś mi napisać – skontaktuj się.