Tag Archives: javascipt

webmastering

Wygrzebane z GitHuba (5) : CoffeeConsole

W piątym odcinku Waszego ulubio­nego cyklu pojawi się projekt z tygo­dnio­wym stażem na GitHu­bie pod tytu­łem Coffe­eCon­sole. Jest to inte­rak­tywna konsola języka Coffe­eScript dla prze­glą­darki Chrome. Do tej pory trzeba było używać okienka „TRY COFFEESCRIPT” na stro­nie http://coffeescript.org (brak podświe­tla­nej składni) lub insta­lo­wać Node.jsnpm.

Dla niewta­jem­ni­czo­nych, CS jest tzw. „lukrem skła­dnio­wym” na Java­Script, tzn. wyni­kiem kompi­la­cji CS jest czysty JS (który z kolei jesz­cze można ście­śnić jakimś „zmniej­sza­czem” — mini­fie­rem). Skład­nia CS przy­po­mina najbar­dziej Pythona (bloki kodu rozdzie­lane na podsta­wie wcięć, array compre­hen­sions). Domie­szano również nieco Ruby­ego (znak „?” przy zmien­nych będący spraw­dze­niem czy zmienna istnieje i „@” dla pól obieku).

Po ścią­gnię­ciu i rozpa­ko­wa­niu pakietu wystar­czy prze­cią­gnąć plik coffeeconsole.crx na okno otwar­tego Chroma i rozpocz­nie się insta­la­cja dodatku. Otrzy­mamy 2 pola edycji — lewy dla źródło­wego CS i prawy dla wyni­ko­wego kodu JS.

Poni­żej zade­mon­struję dzia­ła­nie tego cuda:

###
Przykladowy kod naskrobany w 5 min., nie zwracajcie na niego uwagi.
 
W ten sposob w wynikowym JS powstanie komentarz np. dotyczacy licencji.
###
 
# wartosc od ktorej humor jest dobry
goodMoodThrottle = 51
 
# tworze literal obiektowy
peopleMood = 
    'Dawid'  : 100
    'Marta'  : 78
    'Adam'   : 53
    'Marian' : 45
 
# tworze funkcje o 2 parametrach
getMoodString = (name, goodMood) ->
    # zwracam uwage na konstrukcje if-then-else
    # is zamieniane na ===
    # oraz "#{zmienna} cos tam dalej"
    if goodMood is true then "#{name} ma dobry humor" else "#{name} ma zły humor jak cholera"
 
# konstrukcja for-of dla petli po literalach obiektowych
for name, moodLevel of peopleMood
    # kompilator sam domysli sie, ze chodzi nam o alert(getMoodString(name,(bool)))
    alert getMoodString name, goodMoodThrottle <= moodLevel <= 100

W okienku z prawej strony otrzy­mamy nastę­pu­jący wynik kompilacji:

/*
Przykladowy kod naskrobany w 5 min., nie zwracajcie na niego uwagi.
 
W ten sposob w wynikowym JS powstanie komentarz np. dotyczacy licencji.
*/
 
var getMoodString, goodMoodThrottle, moodLevel, name, peopleMood;
 
goodMoodThrottle = 51;
 
peopleMood = {
  'Dawid': 100,
  'Marta': 78,
  'Adam': 53,
  'Marian': 45
};
 
getMoodString = function(name, goodMood) {
  if (goodMood === true) {
    return "" + name + " ma dobry humor";
  } else {
    return "" + name + " ma zły humor jak cholera";
  }
};
 
for (name in peopleMood) {
  moodLevel = peopleMood[name];
  alert(getMoodString(name, (goodMoodThrottle <= moodLevel && moodLevel <= 100)));
}

Patrząc na liczbę linii kodu mamy spory zysk w stosunku do wyni­ko­wego kodu JS. Przy okazji nie zajmu­jemy się zbęd­nymi śred­ni­kami i nawiasami.

Jeśli jesz­cze Was nie prze­ko­na­łem do użycia to propo­nuję zoba­czyć tworze­nie klas:

class Human
    constructor: (@name) ->
 
    whatIsYourName: ->
        "Mam na imie #{@name}"
 
people = []
 
people.push new Human 'Andrzej'
people.push new Human 'Marian'
people.push new Human 'Lucjan'
 
alert human.whatIsYourName() for human in people

Wynik w JS:

var Human, human, people, _i, _len;
 
Human = (function() {
 
  Human.name = 'Human';
 
  function Human(name) {
    this.name = name;
  }
 
  Human.prototype.whatIsYourName = function() {
    return "Mam na imie " + this.name;
  };
 
  return Human;
 
})();
 
people = [];
 
people.push(new Human('Andrzej'));
 
people.push(new Human('Marian'));
 
people.push(new Human('Lucjan'));
 
for (_i = 0, _len = people.length; _i < _len; _i++) {
  human = people[_i];
  alert(human.whatIsYourName());
}

Dla bardziej zain­te­re­so­wa­nych tema­tem Coffe­eScriptu pole­cam książkę The Little Book on Coffee Script dostępną online.

Inne

Własne funkcje w Google Spreadsheets

Od czasów powsta­nia Google Docs (a szcze­gól­nie Spre­ad­she­ets) zasta­na­wia­łem się czy da się zrobić w tym coś konkret­nego. Mam tu na myśli własne funk­cje, jakieś wykresy, a nie tylko „wylicz mi sumę z pól A1:A5”. Doku­men­ta­cja prawie tylko po angiel­sku, do tego jesz­cze często mało obszerne infor­ma­cje na temat np. tytu­ło­wych custom func­tions.

Jako iż wynaj­muję miesz­ka­nie, co miesiąc muszę poświę­cać 10 min. aby wyli­czyć właści­cie­lowi należną mu kwotę za media. To o 9 min. za dużo! A pomy­lić się po drodze jesz­cze można… Ułatwi­łem sobie tworząc arkusz, który wymaga tylko wpisa­nia liczby z licznika.

Stwo­rzymy sobie arkusz kalku­la­cyjny w Google Spre­ad­she­ets (jeżeli oczy­wi­ście komuś nie prze­szka­dza, że Google oprócz tego co ma w mailach i czego szuka, będzie również wiedziało ile zużywa ciepłej wody itd.)

Udostęp­ni­łem wszyst­kim „arkusz badaw­czy” do wglądu. Może­cie oglą­dać, ale nie może­cie nic zmie­niać (zaraz bym tam czytał o powięk­sza­niu peni­sów). Natu­ral­nie powpi­sy­wa­łem losowe warto­ści, to się nie sugerować :-)

Własne funk­cje w G. Docs możemy sobie pisać w Java­scrip­cie. Tools -> Scripts -> Script Editor. W moim przy­padku zrobi­łem funk­cję wyli­cza­jącą miesięczną opłatę za konkretne medium. Wyglada tak:

function liczMedium(stalaOplata, cenaJednostkowa, staryStan, nowyStan) {
  if (staryStan == '' || nowyStan == '') return 'czekam na dane...';
  else if (typeof staryStan != 'number' || typeof nowyStan != 'number') return 'stany licznika musza byc liczba!';
  if (cenaJednostkowa == '') return 'Nie podano ceny jednostkowej!';
  stalaOplata = (stalaOplata == '')?0:stalaOplata; // nie kazde medium ma opate przesylowa
  stalaOplata = parseFloat(stalaOplata); // rzutuj do floata
  cenaJednostkowa = parseFloat(cenaJednostkowa); // rzutuj do floata
  var roznica = parseFloat(nowyStan - staryStan); // roznice tez do floata
  if (roznica < 0) return 'Błąd - nowy stan licznika nie może być mniejszy od starego';
  return stalaOplata + (cenaJednostkowa * roznica); // dla kazdego medium takie samo dzialanie
}

Te dziwne machloje z rzuto­wa­niem do floatów ceny jednost­ko­wej są przez to, że Google uparło się, że wszystko licz­bowe w komórce skon­wer­tuje do postaci z dwoma miej­scami po prze­cinku. Wiemy, że np. cena za KWh prądu to zazwy­czaj coś takiego jak 0,3567545487566575676 zł i trzeba użyć pola tekstowego :-)

Oczy­wi­ście nieład­nie by było gdyby funk­cja nie dosta­jąc żadnej warto­ści wyrzu­cała szpetny error. Dlatego jeżeli nic nie jest wpisane, wyświe­tla w komórce czekam na dane… Dodat­kowo pod sam koniec przy wyli­cza­niu różnicy robimy proste spraw­dze­nie czy ktoś nie „mach­nął się” odczy­tu­jąc z licz­nika mniej­szą wartość od poprzed­niej. Zapewne od razu zapy­ta­cie: a co jak mi wymie­nili licz­nik? Na mój gust trzeba by wpisać jedno­ra­zowo jakiś offset przy przej­ściu ze starego licz­nika na nowy, np.: =liczMedium(E6;F6;G5;475+G6).

Zuży­cie roczne wyli­czam poprzez =(MAX(G3:G14)-MIN(G3:G14), czyli szukam maksy­mal­nej i mini­mal­nej liczby i odej­muję. Jeżeli zmie­nili nam licz­nik to znowu będziemy mieli zafał­szo­wane dane. Należy wydzie­lić zakres starego licz­nika i nowego np. tak: =(MAX(G3:G5)-MIN(G3:G5))+(MAX(G6:G14)-MIN(G6:G14)).

Na koniec zapewne zapy­ta­cie jak zrobić taki do niczego nam niepo­trzebny baje­rancki wykres? Ano żeby go zrobić, potrze­bu­jemy zgru­po­wać poroz­rzu­cane dane w jednej tabelce. Najle­piej zrobić to w osob­nym arku­szu (u mnie Sheet2) linku­ją­cym do komó­rek z pierw­szego arku­sza. Aby odwo­łać się wpisu­jemy =Sheet1!A1. Wykres z kolei linkuje do zakresu z drugiego arku­sza =Sheet2!A1:E13

Jak coś jest niezro­zu­miałe to pytać. Wpis dedy­kuję wszyst­kim „wynaj­mo­wa­czom” nieuto­pio­nym w doży­wot­nim kredy­cie hipo­tecz­nym, peace!