Pokazywanie postów oznaczonych etykietą JavaScript. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą JavaScript. Pokaż wszystkie posty

niedziela, maja 15, 2016

ToDo od Trello jako "oddzielna aplikacja"

Byłem na GeeCON 2016.
Było całkiem miło, ale zdarzały się nudniejsze wykłady...

Na jednym z nich, poświęconym Self-Healing Systems zakodziłem sobie małe "narzędzie".

Wygląda tak:


Środek to Trello, ale "obudowa" jest moja ;-)

To prosta Aplikacja Chrome.

Jak powstała?

Najpierw trzeba było stworzyć manifest, czyli plik manifest.json.


{
"name": "Trello display",
"description": "Trello display",
"version": "0.1",
"manifest_version": 2,
"app": {
"background": {
"scripts": ["background.js"]
}
},
"permissions": [
"https://trello.com/","webview","storage"
]
}

W tym pliku opisujemy naszą aplikację.
Najważniejsze to to co widać w "app" i "permissions".
"manifest_version" jest konieczne ;-)
Co do reszty nie mam zdania.

W "app" opisujemy skrypty, które będą służyły do uruchomienia naszej aplikacji.
"background" w "app" wskazuje skrypt, który będzie uruchamiany wraz z naszą aplikacją.

Tu warto poczytać o samych aplikacjach i rozszerzeniach dla Chrome.

Nasz background.js wygląda tak:


chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('wrapper.html', {
'bounds': {
'width': 1200,
'height': 480
}
});
});

Każemy tutaj Chrome by w reakcji na uruchomienie aplikacji (w listenerze dla zdarzenia onLaunch) Chrome otwarło okienko z plikiem wrapper.html o rozmiarach 1200 na 480 pikseli.

wrapper.html to UI naszej "aplikacji".



<html>
<body>
<webview id="webview" style="width: 100%; height: 100%;" src="data:text/html, <html><h1>Loading...</h1></html>" partition="persist:przemelekTrelloApp"></webview>
<script src="wrapper.js">
</script≶
</body>
</html>

Tu najważniejsze to tag "webview".
Osadza on na stronie nową przeglądarkę (z własnymi ciasteczkami, które będą teoretycznie trzymane w oddzielnym "magazynie" w naszym Chrome, który tutaj zowie się "persist:przemelekTrelloApp"), która jest odizolowana od skryptu. Dzięki temu nawet jeśli autor strony zablokował jej umieszczanie w ramce to możliwe jest osadzenie takiej strony w naszej.... z tym, że nie mamy takich możliwości jak z ramką.
To by było prawie wszystko, ale tutaj zamiast załadowania Trello mielibyśmy tylko napis Loading... ;-)
Można by było tam po prostu wstawić https://trello.com, ale przy każdym uruchomieniu aplikacji lądowalibyśmy na stronie logowania... Po co?

Żeby pamiętać ostatni adres na którym byliśmy mamy skrypt w wrapper.js

chrome.storage.local.get(function(items) {
var url = items["url"];
if (!url) url="https://trello.com";
console.log(url);
webview.src=url;
console.log("toster");
console.log(webview.src);
});
webview.addEventListener('loadcommit', function(event) {
var url = event.url;
chrome.storage.local.set({url:url});
});

Rejestrujemy się na zdarzenie "loadcommit", które występuje zawsze po tym jak zawartość strony (bez obrazków i innych podobnych) została załadowana, czyli wtedy gdy adres strony jest już znany. Pobieramy url ze zdarzenia i wrzucamy je do lokalnego storage'a (coś podobnego do localStorage, z tym że apki Chrome nie mają prawa dostępu do localStorage).
Dodatkowo w momencie uruchamiania skryptu próbujemy odczytać to co jest zapisane w lokalnym storage'u. Jeśli jest tam coś pod właściwością url to wstawiamy to jako src do webview i już wszystko działa :-)

I to by było na tyle ;-)

Źródła są na GitHub'ie.

Jakby to kogoś interesowało i chciałby użyć to można pobrać, po zapisaniu na dysku idziemy do strony z Rozszerzeniami (menu hamburger w prawym górnym rogu Chrome -> Więcej narzędzi (aka More Tools) -> Rozszerzenia (Extensions) i przeciągamy pobrany plik do rozszerzeń. Chrome powinien go zainstalować)


Podobne postybeta
Robimy widget do Windows 7 :-)
Jak "okradłem" Google Readera ;-)
Chrome2ChromeV2 na GitHub :-)
"Kodowanie" na Chrome OS ;-)
Trudniej jest lepiej.... czyli AccountManager w Androidzie...

sobota, września 27, 2014

Najkrótsza droga do przyszłości - Polymer ;-)

Sieć Web urodziła się tak między 1989 a 1991 rokiem, kiedy to Tim Berners-Lee opublikował "HTML Tags".
Dwa lata później Internet Engineering Task Force opublikowało draft pierwszej wersji specyfikacji HTMLa, a NCSA zbudowało pierwszą popularną przeglądarkę internetową wspierającą HTMLa.

HTML był wielki.
Był prosty i elegancji. Świetnie nadawał się do tego do czego go zaprojektowano czyli do dzielenia się dokumentami i linkowania między nimi. To drugie znalazło nawet swoje miejsce w nazwie, bo HTML to nic innego jak HyperText Markup Language, czyli język znaczników do tworzenia hypertekstu. A ten hypertekst to właśnie możliwość wskazywania na inne dokumenty.

Mniej więcej w tym samym czasie czyli w 1993 roku pojawiły się pierwsze sytuacje gdzie dokumenty przestały wystarczać.
Pojawiła się specyfikacja CGI, która pozwalała na uczynienie stron "dynamicznymi", chociaż bardziej po prostu zmiennymi.
Chwilę później powstał PHP.

W 1995 do Netscape Navigatora dohackowano język skryptowy, podobno zajęło to tydzień czy dwa.
Język nazywał się przez chwilę Mocha, następnie LiveScript by w końcu zostać JavaScriptem.

Na początku służył do różnych mało istotnych rzeczy, pokazywania czasu od ostatniej zmiany strony, animowania elementów (wtedy gadał z pradziadem DOMa).

Ale w 1999 w Microsoftcie powstał XMLHttpRequest, wtedy się jeszcze inaczej nazywał, ale pojawił się pierwszy w miarę wygodny sposób "gadania" z JavaScriptu z serwerem.
Były też inne sposoby, ale XMLHttpRequest był najprostszy.

Zaczęły się czasy AJAXu... chociaż nikt tego nie zauważył do kwietnia 2004 roku gdy pojawił się GMAIL ;-)

W 2000 roku DOM na tyle dorósł, że pojawił się DOM Level 2.

No i od wtedy niewiele się zmieniło.

Pojawiały się nowe specyfikacje HTMLa, przez chwilę chciano go już nawet porzucić i zastąpić bardziej informatycznym XHTMLem (co się nie udało), wrócono znów do HTMLa w postaci HTML5.

Ale to były standardy, a rzeczywistość poszła przez dobudowywanie frameworków.
Ponieważ podstawowy framework jakim był DOM był implementowany różnie w różnych przeglądarkach zaczęły pojawiać się abstrakcje ukrywające DOM, pojawiło się jQuery, później AngularJS i inne.

W 2006 roku Google stworzyło GWT i miejmy nadzieję, że ktoś im to kiedyś wybaczy ;-)

Ale to wszystko było tylko próbami łatania tego co pojawiło się między 1991 a 2000 rokiem.

Przez to współczesne aplikacje wyglądają tak:


Są niczym innym jak zbiorowiskami DIVów (zwanymi ładnie po angielsku DIV Soup), w których istnieje jakaś hierarchia, ale nawet autorzy takich stron nie potrafią czytać kodu który interpretuje przeglądarka.

HTML/JavaScript stają się swoistym assemblerem, którego nikt zbyt dobrze nie rozumie i wszyscy dotykają się z nim przez różne fasady, które ukrywają pod sobą to co tam się dziej....

Nie jest to fajne.

Dlatego parę lat temu pojawiła się idea Web Componentów.

Web Components składają się z 4 oddzielnych specyfikacji.

Pierwszą są Custom Elements, które są niczym innym jak daniem programistom możliwości używania i tworzenia nowych elementów HTMLa.

Dzięki temu chcąc zobaczyć mapę Google w naszym kodzie możemy mając "gdzieś" zdefiniowany nowy tag użyć go:

To pozwala już zrobić zresztą wiele frameworków, które nie używają web componetów, np. AngularJS.

Drugą rzeczą, która składa się na Web Components są HTML Imports.

Od dawna tworząc stronę można było w niej wskazywać oddzielne pliki w których były skrypty JavaScript albo arkusze stylów CSS:


Jednak nie dawało się tego zrobić z HTMLem....

Do tego trzeba było używać rozwiązań server side takich jak np. JSP:


Ale dzięki HTML Imports teraz już nie trzeba tak kombinować, można użyć po prostu importu na HTMLu:

Trzecim filarem są szablony, czyli Templates.

Dzięki nim można dodawać do HTMLa fragmenty, które nie będą renderowane, ani nawet interpretowane.
Jeśli w dokumencie wstawimy kod:


<img src="http://example.com/image.jpg">

To przeglądarka nie wykona requestu pod wskazany adres! 

Dzięki temu nie trzeba już będzie robić takich rzeczy jak w AngularJS, czyli np. dodawania dodatkowych atrybutów:


<img ng-src="{{link}}">

Których AngularJS używa by "oszukać" przeglądarkę i by ta nie próbowała ładować obrazka {{link}}.

Ostatnim filarem jest Shadow DOM.

Z zewnątrz wygląda niepozornie:


Jak widzimy, w podglądzie elementów na stronie "nasz" tag, my-map jest widoczny tak jak w źródle jako <my-map>. 
Gdyby przejść przez drzewo DOM to gdy doń dotrzemy nie zobaczymy wśród jego dzieci tagu <style>, <geo-location> i im podobnych.
Dopiero gdy spojrzymy na #shadow-root to dostrzeżemy zawartość naszego taga.
To co jest w #shadow-root jest ukryte przed światem zewnętrznym, samo też nie widzi świata zewnętrznego.
Pozwala to na dobrą enkapsulację komponentów.
Style w całym dokumencie nie robią krzywdy komponentom.

Te cztery rzeczy pozwalają na tworzenie Web Componentów.

Ale używanie Web Components jest dość nieprzyjemne gdy robi się to bezpośrednio.

Dodatkowo wszystkie te 4 specyfikacje na dzień dzisiejszy implementuje tylko Chrome i Opera (przez to, że używa Chromium), Firefox wspiera natywnie tylko Custom Elements i jego zespół pracuje nad HTML Imports.

Wiemy więc, że przyszłość będzie słodka, ale jeszcze nam do niej daleko...

I tutaj pojawia się Polymer ;-)

Czyli biblioteka (bo jak podkreślają frameworkiem jest ciągle DOM), która pozwala na okiełznanie tych 4 specyfikacji w sposób prosty i przyjemny, do tego dodając jeszcze kilak miłych rzeczy takich jak data binidng, layouty, zbiór podstawowych elementów i od niedawna także Paper Elements, czyli elementy UI które pozwalają na tworzenie aplikacji zgodnych z Material Design.

Użycie tagów w Polymerze jest proste.

Wystarczy:
1) tag znaleźć (stworzyć albo znaleźć w tym katalogu tagów, lub w tym)
2) zaimportować
3) użyć

Tworzenie jest także proste.

Zaczynamy od zaimportowania Polymera i powiedzenia jak nazywa się nasz tag:


1
2
3
4
5
6
7
8
<link rel="import" href="bower_components/polymer/polymer.html">
<polymer-element name="new-tag">
<template>
</template>
<script>
Polymer('new-tag', { });
</script>
</polymer-element>

Jak widać zaczynamy w pierwszej linii od zaimportowania Polymera (który w tym przypadku jest w katalogu bower_componets/polymer.
W linii 2 mówimy Polymerowi, że mamy nowy tag o nazwie "new-tag".
W linii 3 zaczyna się szablon, który kończy się w linii 4.
W liniach 5-7 mamy kawałek JavaScriptu który rejestruje nasz tag.
W końcu w linii 8 kończymy definicję naszego tagu.

Teraz wypada dodać kod do naszego tagu :-)


 1
2
3
4
5
6
7
8
9
10
11
12
13
14

<link rel="import" href="bower_components/polymer/polymer.html">
<polymer-element name="new-tag">
<template>
<style>
h1 {
color: red;
}
</style>
<h1><content></content></h1>
</template>
<script>
Polymer('new-tag', { });
</script>
</polymer-element>
W liniach 4-8 dodaliśmy styl, a w linii 9 kod naszego tagu.

Jego użycie:
<new-tag>Toster</new-tag>
Spowoduje pojawienie się na stronie:

W drzewie DOM wygląda to tak:

Co się tu dzieje?

Przeglądarka renderując tag <new-tag> wstawiła tekst w <h1> na czerwono.
Za <h1> jest odpowiedzialna linia 9, która mówi tyle by content tagu, czyli Toster wstawić w to miejsce, style w liniach 4-8 mówią zaś, że wszystko co jest w <h1> było czerwone.

Nie jesteśmy oczywiście skazani na wstawianie naszego tekstu tylko w jedno miejsce, możemy użyć <content select="..."> by wybrać to co ma się pojawić.
Gdy użycie tagu będzie wyglądać tak:
<new-tag>
<span>Toster</span>
Urządzenie do tostowania
</new-tag>
A sam tag tak:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
<polymer-element name="new-tag">
<template>
<style>
h1 {
color: red;
}
</style>
<h1><content select="span"></content></h1>
<h3><content></content></h3>
</template>
<script>
Polymer('new-tag', { });
</script>
</polymer-element>
To efektem będzie:

Dzieje się tak ponieważ wszystko co było w <span> zostało złapane przez <content select="span">, reszta zaś trafiła do <content>.
Jeżeli jednak chcielibyśmy by nasz tag był w stanie przyjmować parametry nic nie stoi na przeszkodzie, niech nasz <new-tag> zacznie udawać okrągły obrazek:


Jego użycie wygląda tak:

 <new-tag src="tn_Buffy.jpg"></new-tag>
A sam tag tak:
<polymer-element name="new-tag" attributes="src">
<template>
<style>
img {
border-radius:50px;
}
</style>
<img src="{{src}}">
</template>
<script>
Polymer('new-tag', { });
</script>
</polymer-element>
Tutaj widzimy, że nasz <new-tag> ma atrybut src, który jest ustawiany i jego zawartość jest używana w {{src}}.
Te klamrowe nawiasy {{ }} wiążą się z kolejną  rzeczą, którą daje nam Polymer, czyli z data bindngime i event bindingiem.
Jeśli mowa o eventach to ich użycie jest bardzo proste.
Niech nasz tag teraz udaje licznik:



Co zapewni nam taki kod:


 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<polymer-element name="new-tag">
<template>
<style>
h1 { color: red; }
</style>
<h1>{{counter}}</h1>
<button on-click="{{increment}}">Increment</button>
</template>
<script>
Polymer('new-tag', {
created: function() {
this.counter = 0;
},
increment: function() {
this.counter++;
}
});
</script>
</polymer-element>
Jak widzimy do tagu <button> (w linii 7) przypięliśmy metodę increment, która dokonuje (w linii 15) inkrementacji zmiennej counter.
Data binding to coś co sprawia, że Polymer nabiera kolorów.
Wyobraźmy sobie taki oto kod:
<time-source time="{{time}}"></time-source>
<digital-clock time="{{time}}"></digital-clock>
Gdzie tag <time-source> "emituje" coś do {{time}}, a <digital-clock> to "konsumuje".
Oczywiście ta emisja i konsumpcja to coś umownego, oba tagi mogą robić obie te rzeczy.

Jeśli nasz tag chce reagować na zmianę atrybutu to musimy dodać doń metodę nazwaParametruChanged, czyli dla time to będzie timeChanged:

      timeChanged: function() { }

Tu zapraszam na mojego GitHuba by obejrzeć to dokładniej.
Kolejną rzeczą, którą dodaje Polymer są layouty....

To jest akurat rzecz, której nie do końca należy jeszcze używać bo się zmieniają.

Ale istota jest taka, że Polymer dodaje zbiór atrybutów które można stosować przy wszystkich wizualnych elementach tak, że są odpowiednio ustawiane na ekranie.
Tu odsyłam do strony Polymera, bo lepiej to tłumaczą.
Do tego wszystkiego Polymer dostarcza zbioru podstawowych elementów.
Są to tak elementy graficzne jak np. <core-icon>, który dostarcza ikonki (może to być nasz obrazek lub jedna z dostarczonych ikon), jak i elementy nie graficzne, takie jak np. <core-localstorage> czy <core-ajax>.

Przykładem takiego niewizualnego tagu jest tag, którym się tu już kiedyś dzieliłem czyli tag <geo-location>:
<polymer-element name="geo-location" attributes="lat lon auto">
<template>
<style>
:host {
display: none;
}
</style>
</template>
<script>
Polymer('geo-location', {
lat: 0.0,
lon: 0.0,
created: function() {
if (this.hasAttribute("auto")) {
this.getLocation();
}
},
getLocation: function() {
var t = this;
function updatePosition(position) {
var lat = position.coords.latitude;
var lon = position.coords.longitude;
t.lat = lat;
t.lon = lon;
}
navigator.geolocation.getCurrentPosition(updatePosition);
}

});
</script>
</polymer-element>
Tag ten ma trzy atrybuty, z czego w lat i lon znajduje się geolokalizacja komputera, a auto służy do włączenia taga. Dodatkowo tag ma metodę getLocation(), którą na nim można zawołać tak jak to się robi w JavaScript'cie.
Czyli najpierw mamy:

<geo-location auto id="loc" lat="{{lat}}" lon="{{lon}}"></geo-location>

A później w skrypcie:
this.$.loc.getLocation();
Jak widać używamy tutaj "czystego" JavaScript'u.

Do tego wszystkiego Polymer dostarcza teraz zestaw elementów UI zgodnych z Material Design.

Polymer dostarcza także warstwę pośrednią, która sprawia, że wszystkie te smakołyki działają na wszystkich wiodących przeglądarkach (zwykle 2 wersje w tył).
Na Chrome i Operze są wspierane natywnie, na innych dopóki nie będą wspierane natywnie są wspierane przez wypełniacze.

Było to dość długie, ale chyba warto ;-)

A ja sobie przygotowałem chociaż jakąś wizję mojej prezentacji (bo poprzednia wersja mi się nie podobała ;-)) o Polymerze.




Podobne postybeta
Data binding w Polymerze jest oszukany ;-)
Polymeryzacja AngularJS ;-)
ToDo od Trello jako "oddzielna aplikacja"
Robimy widget do Windows 7 :-)
Jak "okradłem" Google Readera ;-)

piątek, października 07, 2011

Odkryłem node.js :-)

Chyba znalazłem w końcu swój język do prototypowania i pisania małych aplikacji "serwerowych".
Może nawet nie język, a serwer ;-)

Mowa o node.js, dla którego językiem jest JavaScript i to wykonywany przy pomocy maszyny wirtualnej V8, tej samej, która mieszka w Chrome.

Nie jest to może totalne spełnienie moich marzeń, ale i tak mu bliżej niż kontrkandydatom :-)

Podobne postybeta
Dart wolny.... w sensie nieprędki
Reset
"Prosty" kod
Jak z metody size() w List w Java'ie dostać ujemną liczbę? ;-)
Wernyhora mode.... któryś tam.. co to jest Occam? ;-)

środa, września 07, 2011

Life - iteracja 2 ;-)

Coś sobie musiałem napisać bo inaczej bym zgłupiał ;-)
No to mamy wersję "Life" dla Canvas w JavaScript.



Żeby zobaczyć jak to działa należy przycisnąć Run!
Najlepiej i najszybciej działa na Chrome.
Liczę, że w podobnych postach pojawi się taki, w którym wytłumaczone jest o co chodzi w grze o życie (grze życie?), czyli Life Conway'a.


Podobne postybeta
Yes or No? czyli tworzenie UI to nie jest prosta sprawa.
Chrome, Firefox, IE9 preview i cieniowanie Gouraud'em w JavaScript
Duże obrazki w Bloggeroidzie
Tym razem chcę bezszwowej TV ;-)
Żuraw Darwina, żuraw ewolucji, żuraw Dennett'a

czwartek, sierpnia 18, 2011

Sudoku solver - dalsza walka ;-)

Wydaje mi się, że dotarłem już do ściany z algorytmem ;-) A jedyne miejsce na przyspieszenie to optymalizacje.

Sudoku potwór które potrzebowało w tym co nazwałem rozwiązaniem doskonałym 38 tysięcy prób, teraz działa w 1500-1600 ;-)
Ówczesne blisko 8 sekund, zmieniło się w zwykle mniej niż 180 ms.

Potwór wygląda tak:



.........
.....3.85
..1.2....
...5.7...
..4...1..
.9.......
5......73
..2.1....
....4...9


Sama rozwiązywarka podobnie do tego jak wyglądała wcześniej ;-)



Algorytm działa prawie tak samo jak działał wcześniej z tą drobną różnicą, że poprawiłem 2 błędy z poprzedniej wersji, teraz jeżeli istnieje kilka równolicznych zestawów kandydatów to wybierany jest ten, który ma najmniejszą sumę liczby jeszcze niewykorzystanych liczb....... inaczej mówiąc ;-) Jeśli dla pola A są kandydaci 3 i 5, a dla pola B kandydaci 2 i 7 to wybierane przy uwzględnieniu, że np. 3 i 5 są wykorzystane już 8 razy na planszy, a 2 i 7 dopiero 3 razy to po zsumowaniu dla A będziemy mieli (9-8)*2, a dla B (9-3)*2, czyli A jest lepsze.
Następnie sortuję jeszcze liczby "kandydackie" dla pola tak by najpierw próbować te które których użyto już najwięcej razy.
Wcześniej jakby się zastanowić robiłem to jakby na odwrót ;-)
Dodatkowego przyśpieszenia wszystko dostało przez zmianę formatu przechowywania danych. Wcześniej miałem tablicę łańcuchów w postaci pole:wartość, teraz mam tablicę w której parzyste elementy to numer pola, a nieparzyste wartość. Dzięki temu unikam masy wołań split(":").
Dałoby się jeszcze to trochę przyśpieszyć, ale już jakoś nie czuję bluesa do tego ;-)

Cała zabawa jest zaś odpowiedzią na rozwiązywarkę WildWezyra :-)
Moja wykonuje mniej kroków, ale wykonuje się ciut wolniej, choć wydaje mi się, że wystarczyłoby kilka zmian w obróbce danych [może ich spróbuję ;-)]

Podobne postybeta
Sudoku - przyśpieszamy, ale jeszcze nie za bardzo ;-)
10 milionów pięter...
Sudoku - rozwiązanie doskonałe ;p
Sudoku - wstyd mi ;-)
Olśnienia :-)

niedziela, lipca 31, 2011

Robimy widget do Windows 7 :-)

Tytułem wstępu ;-)
W pracy ważne są dla mnie godziny w Los Angeles i Dallas, jakiś czas temu wrzuciłem sobie jako element aktywnego pulpitu Windows XP kawałek kodu w HTML i JavaScript, który pokazywał mi aktualną godzinę w Krakowie, Los Angeles i Dallas.
Jednak w tym tygodniu dostałem Windows 7 (dzięki BSODom na XP :-)), a że w Windows 7 (a może i w Vista) usunięto Active Desktop to mój hack już nie działał.

Postanowiłem więc zrobić sobie widget do tego :-)
Poszperałem trochę w sieci i już wiem jak zrobić widget :-)

Nie wygląda on jakoś szczególnie ładnie, tutaj na tle mojej tapety w prywatnym laptopie:


KRK to Kraków, LAX to Los Angeles, a DFW to Dallas (jakby to kogoś interesowało to są to nazwy portów lotniczych w tych miastach).

Jak robimy widget do Windows 7? :-) Prosto :-)

Najpierw tworzymy katalog, np. Timer.Gadget, w nim zaś tworzymy plik gadget.xml o mniej więcej tej treści:
<?xml version="1.0" encoding="utf-8" ?>
<gadget>
  <name>Timer Gadget</name>
  <namespace>pl.przemelek</namespace>
  <version>1.0.0.10</version>
  <author name="Przemelek">
    <info url="przemelek.blogspot.com" />
  </author>
  <description>Timer gadget.</description>
  <hosts>
    <host name="sidebar">
      <base type="HTML" apiVersion="1.0.0" src="timezones.html" />
      <permissions>Full</permissions>
      <platform minPlatformVersion="1.0" />
    </host>
  </hosts>
</gadget>
Tutaj można znaleźć dokładny opis tego pliku i wszystkich elementów.

Dla nas ważne jest to, że wskazaliśmy, że w pliku timezones.html znajduje się kod naszego widgetu.

Jest to zwykły dokument HTML, w którym można używać JavaScript. Jedyna istotna sprawa to to, że trzeba w tym pliku podać rozmiary co robimy definiując parametry dla body, np. tak:

<style type="text/css">
body{
margin:0;
width:220px;
height:120px;
}
</style>

Dzięki temu nasz widget będzie miał szerokość 220 pikseli i wysokość 120.
Niestety taki widget będzie miał białe tło, a wolelibyśmy przezroczyste.
Do tego używamy sztuczki, po pierwsze potrzebujemy "przezroczystego" obrazka, czyli pliku PNG nagranego z przezroczystością w kanale alfa (cokolwiek to znaczy, można do tego użyć IrfanView ;-)).
Jeśli ten przezroczysty plik nagramy jako background.png to wskazujemy Windowsowi, że ma go użyć jako tła w taki sposób:

<body>
<g:background id="imgBackground" src="background.png">
[......]
</g:background>
</body>

Kropki oznaczają kod strony i skryptu.

No i prawie wszystko mamy ;-)

Teraz testowanie.
Nasz katalog trzeba skopiować do c:\Program Files\Windows Sidebar\Gadgets, do tego trzeba mieć uprawnienia administratora, później już tylko prawy mysz na puplicie i wybieramy Gadżety, a później z okienka nasz :-)
W celu wprowadzenia zmian kopiujemy pliki do tego samego katalogu, w celu zapewnienia sobie tego, że Windows wszystko zupdatuje dobrze zmienić numer wersji w gadget.xml.

Jak już nasz widget jest taki jak chcieliśmy i chcielibyśmy go komuś pokazać, lub zacząć go publikować to trzeba go spakować :-)
W tym celu po prostu zawartość naszego katalogu (czyli wszystkie pliki które są potrzebne widgetowi) pakujemy ZIPem do pliku z rozszerzeniem .gadget, w moim przypadku to Timer.Gadget.
I voilà! Widget gotowy :-)

Instalacja jest prosta, wystarczy zaklikać taki plik i Windows spyta nas czy chcemy go zainstalować.
Tutaj uwaga, to jest niepodpisany widget więc Windows będzie narzekać, że twórca jest niezweryfikowany, ale to nam raczej nie przeszkadza ;-)

Jak ktoś chce to zapraszam do pobierania :-)
Kilka uwag, gadget jest głupi i nie podaje tak naprawdę w 100% pewnego czasu w LAX i DFW, po prostu odejmuje zawsze taką samą liczbę od godziny lokalnej, to spowoduje, że przy zmianie strefy czasowej zmieni się też czas wyświetlany dla LAX i DFW ;-), dodatkowo nawet gdy będziemy ciągle w naszej strefie czasowej to widget będzie pokazywał bzdury w momencie zmiany czasu z letniego na zimowy, dodatkowo to następuje w różnym czasie u nas i u nich. Ale to detale, które nie są teraz ważne, jeśli nadal będę używał tego widgetu to po prostu sobie to zmienię gdy przyjdzie czas ;-)



Podobne postybeta
ToDo od Trello jako "oddzielna aplikacja"
Z NMEA do KML (chyba najbardziej kryptyczny tytuł postu jak stworzyłem ;-))
Programowanie jako sztuka oszukiwania ;-)
We Frankfurcie...
Jak "okradłem" Google Readera ;-)

poniedziałek, marca 14, 2011

Sudoku solver - film ;-)

W trakcie zabaw z pisaniem mojego Sudoku Solvera dodałem sobie do niego opcję debuga, dzięki której mogłem zobaczyć jak solver zabiera się do rozwiązania Sudoku ;-)
Dzięki temu mogłem np. stwierdzić, że mój pomysł z głupim połączeniem DFS i BFS się nie sprawdza ;-)

Np. dobre rozwiązanie Sudoku wygląda w taki sposób:



Widać, że dość szybko wypełniane są pola i linie w których istnieje mała ilość możliwych "wypełnień", po czym algorytm stara się wypełnić kolejne pola. Widać też cofanie się ze złych rozwiązań ;-)
Widać też to, że to co normalnie na moim laptopie zajmuje około 100 ms w trybie w którym pokazywane są wszystkie stany pośrednie zajmuje ponad 11 sekund ;-)


Podobne postybeta
Sudoku - rozwiązanie doskonałe ;p
Sudoku - wstyd mi ;-)
Przyśpieszanie backtrackingu
Sudoku - atak pierwszy ;-)
Mroczne Materie - polecam, gorąco polecam :-)

niedziela, marca 13, 2011

Sudoku - rozwiązanie doskonałe ;p

WildWezyr na Google Buzz zażyczył sobie bym dostarczył godnego przeciwnika dla jego Sudoku Solvera ;-)

Oto i on - Sudoku Solver 2011 XXX.YYY.ZŹĆ [buńczuczna nazwa to ważny element marketingu ;-)].



[tutaj link dla osób, które czytają to np. w Google Buzz :-)]

Pozbył się on dziedzictwa poprzednich rozwiązań i nie generuje już za każdym razem listy wszystkich możliwych kandydatów [OK, w rzeczywistości nadal to robi bo inaczej się raczej nie da, w końcu trzeba mieć jakieś sensowne kryterium wyboru pola, które się będzie rozpatrywać ;-)]. Dzięki temu odpadło mu sortowanie [i znów jeśli zagłębić się w szczegóły to fakt sortowania nie ma, ale w poprzedniej wersji było ono tylko dlatego, że format przechowywania informacji o polach był taki, że sortowanie było jedynym w miarę szybkim sposobem wyciągnięcia informacji o polu, które jest najbardziej "ograniczone"].

Ta wersja dorobiła się też guziczka Clear, a kopiowanie z formatu przechowującego Sudoku zostało zmienione tak by nie obracało planszy o 90 stopni :-)

Te drobne zmiany spowodowały, że trudne Sudoku są rozwiązywane w 200-300 krokach, a nie w 4000-5000 ;-)


Podobne postybeta
Sudoku - atak pierwszy ;-)
Sudoku - wstyd mi ;-)
Sudoku solver - film ;-)
Sudoku - przyśpieszamy, ale jeszcze nie za bardzo ;-)
Święta wojna...

czwartek, marca 10, 2011

Sudoku - wstyd mi ;-)

[Updata: mam już lepsze rozwiązanie, które radzi sobie jak mi się wydaje ze wszystkimi Sudoku i to w bardzo krótkim czasie :-)]

Już wiem czemu moje poprzednie rozwiązania były takie sobie...

Za sprytny chciałem być ;-)

Przy każdym kroku generowałem listę wszystkich możliwych w danym momencie "zajętości" pól i dla każdego z takich kandydatów robiłem kolejny krok...... to oznaczało, że przytłaczająca większość "kroków" była powtarzana po wielokroć.

A wystarczy nie kombinować i w każdym kroku zajmować się tylko 1 polem... I wtedy wszystko działa :-)



Ta wersja wzbogaciła się o "moduł" importu, dzięki niemu można do rozwiązywarki wrzucać różne przygotowane wcześniej przykłady. Pomysł jest od WildWezyra z jego Sudoku Solvera, z tym, że u mnie działa na odwrót :-)

Nie jest to jeszcze demon prędkości, ale to tylko dlatego, że korzystam nadal z kodu, który generuje listę kandydatów dla wszystkich pól i dopiero na końcu po posortowaniu ich wg. tego, które jest najbardziej "unikatowe" odrzucam z rozważań wszystkich kandydatów, którzy nie dotyczą tego pola, które jest najbardziej unikatowe.

Kolejny raz mam lekcję, że nie należy kombinować ;-)


Podobne postybeta
Sudoku - atak pierwszy wersja 2 ;-)
Sudoku - przyśpieszamy, ale jeszcze nie za bardzo ;-)
Sudoku - rozwiązanie doskonałe ;p
Sudoku - atak pierwszy ;-)
Sudoku solver - dalsza walka ;-)

poniedziałek, marca 07, 2011

Sudoku - atak pierwszy wersja 2 ;-)

[Updata: mam już lepsze rozwiązanie, które radzi sobie jak mi się wydaje ze wszystkimi Sudoku i to w bardzo krótkim czasie :-)]

Lekko zmodyfikowana wersja, która wydaje się poprawiać pewne błędy poprzedniej (np. to, że tamta wcale nie sortowała elementów tak jak myślałem, że sortowała ;-)).



Czym się różni od poprzedniej wersji?

Po pierwsze dobrze sortuje rozwiązania, czyli najpierw przygląda się najbardziej "unikatowym" polom, a jeśli jakieś pola są podobnie "unikatowe" to najpierw uderza w te pola, które są zajęte przez bardziej popularne liczby (np. jeśli mamy już 8 dziewiątek na planszy to raczej taki kandydat jest bardziej sensowny do rozpatrzenia jako pierwszy).
Po drugie gdy już stworzona jest lista kandydatów, ale jeszcze przed sortowaniem, sprawdzane jest czy liczba kandydatów wystarczyłaby do zapełnienia planszy do pełna, jeśli nie to rozwiązanie jest porzucane.

Nadal jest to dość naiwny algorytm, ale wydaje się działać lepiej.


Podobne postybeta
Sudoku - wstyd mi ;-)
Sudoku - przyśpieszamy, ale jeszcze nie za bardzo ;-)
Sudoku - atak pierwszy ;-)
Sudoku - rozwiązanie doskonałe ;p
Sudoku solver - dalsza walka ;-)

niedziela, marca 06, 2011

Sudoku - atak pierwszy ;-)

[Updata: mam już lepsze rozwiązanie, które radzi sobie jak mi się wydaje ze wszystkimi Sudoku i to w bardzo krótkim czasie :-)]

Zaatakowałem sobie Sudoku ;-)
Czyli napisałem coś co powinno być zdolne do rozwiązywania Sudoku... i jest, ale w rozsądnym czasie rozwiązuje tylko te prostsze ;-)

Przykładowe Sudoku wrzuciłem do środka, dzięki czemu można zobaczyć działanie mojej "rozwiązywarki" ;-)



Jak to działa?

Prosto i naiwnie. Atak odbywa się przy pomocy backtrackingu (czyli tak samo jak atakowałem problem 8 królowych :-)).
Pozycje do rozważenia dobierane są w taki sposób, że najpierw skanujemy jakie liczby zostały użyte w poszczególnych liniach (poziomych i pionowych), oraz "sekcjach" (czyli kwadratach 3x3). Następnie iterujemy po liczbach od 1 do 9 i dla każdej z tych liczb iterujemy po możliwych pozycjach sprawdzając czy w danym momencie takowa pozycja może zostać zajęta przez daną liczbę, jeśli może to zapamiętujemy sobie daną liczbę na danej pozycji jako kandydata. Następnie sortujemy kandydatów tak by najpierw rozpatrywać tych, którzy są "najbardziej unikatowi" ;-) Idealnie takim kandydatem będzie 1 liczba, która może być na danej pozycji.

Przy bardziej skomplikowanych Sudoku dobrze to odpalać pod Chrome lub Firefoksem (4.0), i nie chodzi o wydajność JavaScriptu, a bardziej o to, że ta wersja co przeszukanie 1000 rozwiązań wyświetla alert ;-) a w Chrome i Firefoksie można po prostu zaznaczyć przy drugim alercie, że nie chcemy go już widzieć.... (przy okazji wydaje się, że obie przeglądarki dodają tą opcję tylko gdy alerty pojawiają się w odstępie góra 1 sekundy ;-)).

Teraz trzeba by się za to zabrać od poważniejszej strony i spróbować wymyślić lepszy algorytm :-)


Podobne postybeta
Sudoku - przyśpieszamy, ale jeszcze nie za bardzo ;-)
Sudoku - rozwiązanie doskonałe ;p
Sudoku - wstyd mi ;-)
Przyśpieszanie backtrackingu
Sudoku - atak pierwszy wersja 2 ;-)

wtorek, lutego 01, 2011

Jak &quot;okradłem&quot; Google Readera ;-)

Dziś dostałem przez maila pytanie czy można w jakiś sposób pobrać zawartość "kanału" w Google Readerze bo niestety blog, który dostarczał tego kanału wziął i zaginął, nie ma więc dostępu do RSSa.

Pewnie są inne sposoby, ale ja mam swój ;-)

W Chrome otwieramy Narzędzia dla Programisty lub Konsolę JavaScript, przełączamy się na tabkę Network, odświeżamy interesujący nas kanał w Google Readerze.


Wybieramy te większe z pobranych plików, tutaj to był 4 z kolei.
Po zajrzeniu do niego okazuje się, że to stary dobry JSON :-) a nie jakiś ohydny XML! (chociaż parser XMLa w Java'ie łatwiej napisać jak mamy pomoc w postaci bibliotek do SAX ;-))
No to teraz trzeba pozyskać tylko jego bebechy.
Ja najpierw użyłem Fiddler2, czyli serwera proxy, który pozwala na podglądanie co lata między siecią, a przeglądarką. Niestety narzędzia z Chrome się nie nadają bo nie można zaznaczyć łatwo całej zawartości pobranego pliku i jej skopiować...
Można jednak skopiować adres tego pliku i go po prostu otworzyć w przeglądarce ;-)

Wycinamy zawartość pliku i zapisujemy sobie do pliku o nazwie np. toster.js.
Teraz w tym pliku na samym jego początku, w tej samej linii gdzie jest pierwszy znak "{" dodajemy:
var a = {.....

[OK, bez tych kropek, samo var a = przed pierwszym {]

Na samym zaś końcu pliku dodajemy od nowej linii:
var zaw = "<html><head><META HTTP-EQUIV=\"Content-type\" CONTENT=\"text/html; charset=windows-1250\"></head><body>";
for (var idx=0; idx<a.items.length; idx++) {
var z = "<H1>"+a.items[idx].title+"</H1><br />";
z+="<h3>"+new Date(a.items[idx].published*1000)+"</h3>";
z+=a.items[idx].summary.content
zaw+=z+"<hr />"
}
zaw+="</body></html>"
var fso = new ActiveXObject("Scripting.FileSystemObject")
var MyFile = fso.CreateTextFile("resultKradziejowy.html", true)
MyFile.writeLine(zaw)
MyFile.close()


Nagrywamy na dysku i uruchamiamy to (w Windows z WSH, ale z tego co zauważyłem to praktycznie każdy Windows to już ma ;-)).
Po chwili w tym samym katalogu gdzie nasz plik JS zobaczymy plik HTML o nazwie resultKradziejowy.html :-)

Tada!

Właśnie mamy plik z całym archwium jakiegoś bloga :-) [choć zastanawiam się czy rzeczywiście całym ;-) ... po chwili testowania, nie całym, ale wystarczy wtedy w parametrze n adresu wpisać jakąś dużą liczbę, dla mojego bloga to 2000 (bo wpisów jest koło 1300-1400), choć dla mojego bloga trzeba trochę zmodyfikować ten kod u góry, z symmary.content na content.content, no i coś się narazie wywala na zapisywaniu do pliku ;-) ale jak mi się wydaje jest to spowodowane tym, że mam w treści bloga jakiś znak, którego nie można zapisać do pliku wg. WSH, ale to się da zmienić jakby co ;-)].

Jakby kogo interesowało to tutaj jest wynik mojej niecnej działalności.


Podobne postybeta
ToDo od Trello jako "oddzielna aplikacja"
AppInventor - pierwsze wrażenia i pierwsze programy :-)
Mogłoby być łatwiej ;-)
Robimy widget do Windows 7 :-)
Najkrótsza droga do przyszłości - Polymer ;-)

środa, grudnia 22, 2010

ChromoPaskudztwo ;-) - czyli, pisanie aplikacji dla Chrome to pikuś :-)

Tak się dziś przez chwilę bawiłem i okazuje się, że tworzenie aplikacji dla Chrome, takiej instalowanej na komputerze nie jest takie trudne :-)

Wziąłem na warsztat moją starą zabawkę, która miała mi niby pomagać w pilnowaniu rzeczy do zrobienia. Ten coś był aplikacją HTA, używającą specyficznych dla IE obiektów do dostępu do lokalnych plików.
Postanowiłem przenieść to do Chrome i okazało się, że wszystko zajęło może 30 minut ;-)

Taką "pakowalną" aplikację tworzy się podobnie do rozszerzenia, z tym, że aplikacja ma w manifeście deklarację tego gdzie znajduje się "strona główna" aplikacji i nie ma akcji [czyli stron ;-)] dla przeglądarki [czyli stronki, która pojawia się po sklikaniu ikonki w zasobniku obok menu] i strony [czyli tego co pokazuje się po sklikaniu ikonki w pasku adresu, np. gwiazdki, której przyciśnięcie pozwala na dodanie strony do zakładek].

Fajne jest to, że aplikacja może "łazić" po sieci, nie trzeba kodu za to odpowiedzialnego wyrzucać do tła [trudno tak to tłumaczyć ;-) chodzi o stronę nazywaną w dokumentacji Background page, co bardziej niż tło oznacza tutaj zaplecze].

Lokalne pliki zastąpiłem przy pomocy localStorage, co wymagało tylko lekkich zmian w kodzie.
Aplikacja ma też możliwość używania lokalnie SQLa, ale tutaj nie próbowałem i nie wiem czy warto, z racji tego, że to się może jeszcze zmieniać [W3C czy jak im tam, wstrzymało prace nad tym bo wszystkie implementacje bazowały na SQLLite].

Wg. mnie w przypadku tych pakowanych apliakcji istotne jest to by one działały off-line, a sieci używały raczej do synchronizacji niż do "świadczenia usług".

Aplikacja może być kartą i panelem, różnica jest taka, że karta otwiera się normalnie w przeglądarce, a panel poza nią.



Tutaj ta moja "aplikacyjka" jako panel.

Jak rozumiem w Chrome OS panele trzymane są przy dole ekranu i układane obok siebie, pod Windows są po prostu otwierane. Mamy jedynie kontrolę nad ich rozmiarem.
Na moim Windows 7 panele zawsze otwierają się tak, że ich górny lewy róg jest w górnym lewym rogu ekranu głównego :-)

Ogólnie stwierdzam, że ma to potencjał :-)
Teraz trzeba go tylko zacząć wykorzystywać ;-)

Jakby ktoś ciekawy jak to to wygląda [w środku też], to tutaj jest "instalka". Co do kodu to powstał lata temu i się do niego nie przyznaje ;-) [widzę, że był pisany jeszcze w czasach gdy nie używałem tylko angielskich nazw dla elementów w kodzie].


Podobne postybeta
Nexus 4 - pierwsze wrażenia
YouWave
Czy się stoi czy się siedzi.... kamerka w laptopie jako detektor tego czy biurko jest w trybie stand czy sit ;-)
ToDo od Trello jako "oddzielna aplikacja"
Bloggeroid - polityka małych kroczków ;-)

środa, grudnia 15, 2010

Chrome2Chrome - kto chce potestować? ;-)

OK, Chrome2Chrome dotarł do etapu w którym można go już zacząć publicznie testować :-)

Jednym z wyznaczników tego jest to, że nie ma już w środku namiarów na moje konto :-)
Nie przegina też już z generowaniem transferu. Wg. teorii dzienne zapotrzebowanie na "pinganie" Google Docs to teraz nie ponad 100 MB, a jakieś 170 KB :-) ale to tylko teoria, w praktyce trzeba pewnie liczyć na 1 transmisje 512 bajtów bo tyle ma chyba pakiet TCP/IP [choć to leci w tunelu HTTPS, to może być ciut inaczej] co daje koło 17 MB.

Jak ktoś chce spróbować Chrome2Chrome, czyli wtyczki do Chrome, która pozwala na przesłanie strony z jednej przeglądarki do drugiej to zapraszam do pobierania.

Po uruchomieniu w pasku rozszerzeń pojawi się nowa, niezbyt piękna ikonka ;-)


To ta w środku.

Gdy ją klikniemy powinno pokazać się coś takiego:



Klikamy na Edit credentials i naszym oczom ukaże się:



Wpisujemy namiary na nasze konto Google [ważne by działało z Google Docs], oraz to jak chcemy by nazywał się ten komputer [tak naprawdę to ta przeglądarka].
Klikamy na Save computer name.
Klikamy gdzieś obok i teraz po chwili możemy spróbować znów kliknąć i spróbować rozwinąć listę obok "Send to". Tam powinna się pojawić nazwa naszego komputera. Jeśli się nie pojawiła, znów klikamy na Edit credentials i klikamy Save computer name.
Za drugim razem zwykle już działa.
To samo powtarzamy na innych komputerach [sugeruję wybrać inną nazwę dla tych maszyn ;-)]

Teraz wysyłanie strony wygląda w taki sposób, że gdy chcemy ją przesłać to po prostu klikamy ikonkę i wybieramy komputer gdzie ma ta strona zostać przesłana z listy, jak to widać tutaj:



I już po chwili powinna się ta strona na drugim komputerze otwierać :-)

Jeśli zajrzycie do Google Docs to zobaczycie kilka nowych plików. Po pierwsze plik markerFile, w którym będzie jakaś liczba, to jest plik, który służy do "synchronizacji" rozszerzeń. Coby nie pobierać za każdym razem całej listy plików w folderze Chrome2Chrome, rozszerzenie pobiera tylko ten plik i sprawdza czy jego zawartość się zmieniła, jeśli się zmieni pobiera całą zawartość foldera.
Dalej powinny się pojawić pliki postaci __nazwaKomputera__, które służą do budowania listy komputerów :-)
Samo przekazywanie strony polega zaś na tworzeniu plików _nazwaKomputera_id, które to pliki są kasowane przez komputer dla którego są przeznaczone.

Chętnie poznam opinie :-) Mogą być krytyczne, choć wolę pozytywne :-)


Podobne postybeta
Browser2Browser, czyli prześlij stronę z przeglądarki do przeglądarki ;-)
Wpisy z Bloggera jako eventy w Google Calendar, odsłona 3 - Aplikacja ;-)
Gadające Gadu-Gadu
Coca-Cola Zero i pomidory = najbardziej "odchudzająca dieta" na świecie ;-)
Żarówki kolekcjonerskie ;-)

niedziela, grudnia 12, 2010

Chrome2Chrome - pożeracz transferu ;-)

No i mam małego zgryza z Chrome2Chrome.
Każdy request z prośba o listę plików w folderze Chrome2Chrome to w przypadku braku komputerów, które są dostępne 1.77 KB, w przypadku 1 komputera to już 4.31 KB, dla 2 to 6.85 KB. Czyli każdy komputer dodatkowo to 2.54 KB więcej transferu.
Niby nic, ale w momencie gdy odpytujemy co 5 sekund to już zaczyna być dużo.
W ciągu doby to jakieś 17280 requestów [będzie tego trochę mniej bo u mnie cały request to jakieś 300 ms, do tego dochodzą sytuacje gdy coś zostanie pobrane, ale to co spowoduje spadek ilości requestów spowoduje wzrost ilości danych].
A to jest 115 MB danych... dużo, szczególnie jeśli by to biegało na połączeniu gdzie jest mały limit danych.

Powinno być tego mniej bo Chrome2Chrome prosi Google Docs by wysyłało listę elementów w folderze Chrome2Chrome tylko wtedy gdy się zmieniła, niestety Google Docs wysyła zawsze ;-)

Pomysł jest więc inny, zrezygnować z podejścia z pobieraniem listy elementów w folderze, za to zacząć używać pojedynczych plików. Wtedy co powiedzmy minutę albo co 10 minut Chrome2Chrome sprawdzałby listę komputerów, a później by co 5 sekund pobierał plik dla danego komputera. To by wtedy nie było parę KB, a góra 256 bajtów.
To by były 4.3 MB na 1 komputer, czyli w miarę znośna ilość danych :-)

Btw. dlatego nigdy nie lubiłem XMLa, strasznie duży jest. JSON przy nim to maleństwo, do tego dużo bardziej czytelne.

Podobne postybeta
Chrome2Chrome - kto chce potestować? ;-)
Koronawirus - jak na mnie wpływa
Chrome2Chrome w Chrome Web Store
Chrome2Chrome 0.7.2 - OAuth w akcji ;-)
A tak o liczbach ;-)

Chrome OS, Chrome2Chrome i w ogóle Chrome ;-)

Faza Chrome/Chrome OS nadal u mnie trwa ;-)

Dotarło np. do mnie, że komputer z Chrome OS to będzie idealna maszyna dla mojej mamy :-), która boi się, że "coś popsuje", a w Chrome OS to się po prostu nie może zdarzyć.

Jedyną przeszkodą jest brak możliwości uruchomienia na Chrome OS bazy książek, którą sobie kiedyś napisałem (w Turbo Pascalu z użyciem TurboVision), a która to baza jest używana przez moją mamę do trzymania katalogu książek.
Ale zaczęło mi się w głowie roić, że skoro chciałbym mieć też listę książek na telefonie to można by było połączyć obie rzeczy i napisać prostą aplikację dla Chrome, która pokazywałaby bazę książek, przechowywałaby ją zaś albo lokalnie (przy pomocy localStorage) albo w Google Docs, i w przypadku trzymania w Google Docs mogłaby pobierać też te dane na telefon i byłoby jak znalazł w księgarni.

Jeszcze Skype brakuje dla Chrome OS... ale przecież zawsze można zacząć używać Google Talka/Google Voice.

Bawiłem się też dziś w tworzenie Chrome2Chrome i oto efekty:



Ikonki jeszcze nie mam i używam nadal ikonki z Buzz Troll Removera ;-) Samo UI też nie jest piękne, ale główna funkcjonalność czyli możliwość przesyłania stron między różnymi komputerami już działa :-)

Akurat na tym filmie złośliwie trwa to aż 10 sekund [i nie widać momentu gdy zamykam na EEE PC dialog wyrzucony przez system, który mówi o tym, że coś padło ;-)], ale zwykle jest to o wiele szybsze.

Wszystko działa w taki sposób, że każda z przeglądarek z Chrome2Chrome co 2.5 sekundy pobiera listę dokumentów w folderze Chrome2Chrome w Google Docs [jak trzeba to tworzy ten folder], jeżeli znajdzie jakikolwiek plik o nazwie zaczynającej się od _, a następnie nazwy komputera i znów _ to pobiera ten plik, otwiera stronę której adres jest w tym pliku i kasuje go z Google Docs.
Wysyłanie strony to po prostu stworzenie pliku tekstowego z nazwą _nazwaKomputera_jakieśID [które to jakieśID jest tylko po to by być bo nie musi być nawet unikatowe], w którym to pliku zapisany jest adres strony do otwarcia].

Sam kod do operowania na Google Docs to jakieś 280 linii kodu w JavaScript i to napisanego z wieloma powtórzeniami.

Np. upload wygląda tak:
    function upload(auth,folder,name,body) {
var req = new Object();
req.method="POST";
req.url="https://docs.google.com/feeds/default/private/full";
if (folder!=null) {
var elems = folder.split("%");
req.url+="/folder%"+elems[1]+"/contents";
}
req.body=body;
var headers = new Array();
headers.push({"name":"Content-Type","value":"text/plain"});
headers.push({"name":"Authorization","value":("GoogleLogin auth="+auth)});
headers.push({"name":"Slug","value":name});
headers.push({"name":"GData-Version","value":"3.0"});
req.headers=headers;
var retXML = fetch(req.url, req.method, req.headers, req.body, null,false,true);
return retXML;
}


Czyli już mam kod do operowania Google Docs z rozszerzenia ;-)
Jedynie update mi nie działa, ale możliwe, że to przez to iż zdecydowałem się na używanie wersji 3.0 API, i chyba trzeba będzie zrobić downgrade do wersji 2.0.


Podobne postybeta
Wysyłamy pliki do Google Docs przy pomocy Go :-)
Toperz ;-) czyli OCR + Android odsłona 2 albo któraś tam
Żenienie Todoist z Obsidian przy pomocy Pythona ;-)
Wredne Google Docs
Zmienne Go ;-)