5. Programmering av webbsidor
Aarne Ranta
Datorintroduktion 2009, D och DV, Chalmers & GU
%!target:html
%!postproc(html): #NEW
%!postproc(html): #HR
#NEW
==HTML==
HTML = HyperText Markup Language - språket som används för att skriva webbsidor.
"Markup": **taggar** som strukturerar texten.
En **webbläsare** (t.ex. Firefox) är ett program som **tolkar** HTML
och visar texten genom att göra de saker som taggarna anger.
(Jfr. GHCi: det är ett program som tolkar Haskell)
#NEW
==Exempel på HTML-dokument==
[En enkel text test0.html]
[Text med allt möjligt test1.html]
[Fahrenheit-Celsius-tabell test2.html]
[Text med länkar till Google test3.html]
[Text med länkar till en ordbok test4.html]
[Ett fotoalbum test5.html]
#NEW
==Ett HTML-dokument==
Den grundläggande strukturen i ett HTML-dokument finns i följande mall:
```
Head-titeln: texten överst i ramen
Body: texten i textfältet.
Huvudtitel
Paragraf, bestående av text och annat, t.ex.
länkar till webbsidor,
text i fetstil,
text i kursiv,
text i maskinskrift,
text i röd font,
bilder, som är länkar till bildfiler och kan skalas till önskad storlek
(i nästa paragraf):
Lite mindre titel
Och så en tabell:
```
Klicka [här mall.html] för att se dokumentet i din webbläsare.
#NEW
==Ett annat HTML-dokument==
```
Pictures
```
Klicka [här test5.html] för att se dokumentet i din webbläsare.
Vill någon skriva sånt här?
Nej! Vi ska skriva ett Haskell-program som skriver HTML-filen.
Detta är ett exempel på **generativ programmering**: man skriver program som
genererar program.
#NEW
==HTML-element och taggar==
En **tagg** är text mellan ``<`` och ``>``. Vi börjar med en funktion
som producerar en tagg
```
tag :: String -> String
tag t = "<" ++ t ++ ">"
```
och motsvarande sluttagg:
```
endTag :: String -> String
endTag t = tag ("/" ++ t)
```
De flesta HTML-elementen skapas genom att omsluta mindre element med en tagg
och dess sluttagg:
```
tagged :: String -> HTML -> HTML
tagged t h = tag t ++ h ++ endTag t
```
Till exempel fetstil:
```
bold :: HTML -> HTML
bold h = tagged "b" h
```
Själva typen HTML? Vi nöjer oss med den enklaste möjliga,
```
type HTML = String
```
Alla dessa definitioner finns i biblioteket som har skapats för
den här föreläsningen och uppgifterna: [``MkHTML`` MkHTML.hs]:
#NEW
==Ett litet HTML-bibliotek==
Alla dessa finns i [``MkHTML`` MkHTML.hs]:
```
para :: HTML -> HTML
para h = tagged "p" h
header :: Int -> HTML -> HTML
header i h = tagged ("h" ++ show i) h
bold :: HTML -> HTML
bold h = tagged "b" h
italic :: HTML -> HTML
italic h = tagged "i" h
typewriter :: HTML -> HTML
typewriter h = tagged "tt" h
string :: String -> HTML
string s = s
list :: [HTML] -> HTML
list hs = unlines hs
```
#NEW
==Attribut==
En tagg kan innehålla **attribut**, som ger extra information.
Exempel 1: en **länk** har URL:en (= Uniform Resource Locator, "webbadressen")
som attribut:
```
Haskell Home
```
Exempel 2: en **bild** har både bild-URL:en och valfria
storleksattribut:
```
```
**Obs**: URL-attributet kan vara en fil på samma dator, som i bildexemplet.
**Obs**: sluttaggen har inga attribut.
#NEW
==Generering av attribut==
Vi kan generalisera den tagg-skapande funktionen:
```
attrTag :: String -> [(String,String)] -> String
attrTag t attrs =
tag (t ++ " " ++ unwords [a ++"=" ++ "\"" ++ v ++ "\"" | (a,v) <- attrs])
```
Nu kan vi skriva
```
attrTagged :: String -> [(String,String)] -> HTML -> HTML
attrTagged t attrs h = attrTag t attrs ++ h ++ endTag t
```
Och sedan:
```
link :: String -> HTML -> HTML
link url txt = attrTagged "a" [("href",url)] txt
image :: String -> Int -> HTML
image url size = attrTag "img" [("src",url),("width", show size)]
```
Alla dessa finns i [``MkHTML`` MkHTML.hs].
#NEW
==Fullständiga HTML-dokument==
Dokumentet ska (oftast) ha formen
```
Titeln
Innehållet
```
Vi skapar detta med
```
html :: String -> HTML -> HTML
html hd bod = tagged "html" (headTitle (string hd) ++++ body bod)
headTitle :: String -> HTML
headTitle s = tagged "head" (tagged "title" s)
body :: HTML -> HTML
body h = tagged "body" h
```
Alla dessa finns i [``MkHTML`` MkHTML.hs].
#NEW
==Ett fullständigt exempel i Haskell==
HTML-koden:
```
Hello
Hello World
```
Haskell-koden
```
html "Hello" (string "Hello World")
```
[Resultatet i webbläsaren test0.html]
I Haskell blir det mindre att skriva.
Och det blir inga syntaxfel t.ex. saknande sluttaggar.
#NEW
==Ett annat exempel==
HTML-koden:
```
Head-titeln: texten överst i ramen
Body: texten i textfältet.
Huvudtitel
Paragraf, bestaende av text och annat, t.ex.
lankar till webbsidor,
text i fetstil,
text i kursiv,
text i maskinskrift,
text i röd font,
bilder, som ar lankar till bildfiler och kan skalas till onskad storlek
(i nästa paragraf):
Lite mindre titel
```
Haskell-koden:
```
html
"Head-titeln: texten overst i ramen"
(list [
string "Body: texten i textfaltet.",
header 1 "Huvudtiteln",
para (list [
string "Paragraf, bestaende av text och annat, t.ex.",
link "http://www.haskell.org" "lankar till webbsidor",
bold "text i fetstil",
italic "text i kursiv",
typewriter "text i maskinskrift",
colored "red" "text i rod font",
string "bilder, som ar lankar till bildfiler och kan skalas",
string "till onskad storlek (i nasta paragraf):"
]),
para (image "didno.jpg" 512),
header 2 "Lite mindre titel"
])
```
[Dokumentet i webbläsaren test1.html].
Vi vinner knappast något med Haskell här...
#NEW
==Tabeller==
En enkel tabell ser ut så här:
|| A1 | A2 | A3 ||
| B1 | B2 | B3 ||
HTML-koden ser ut så här:
```
```
Vi vill kunna skapa tabellen med Haskell-koden
```
table [["A1","A2","A3"],["B1","B2","B3"]]
```
#NEW
==Generering av tabeller==
En tabell kan ses som en //lista av listor//.
Den yttre listan är raderna (````), de inre är cellerna (````).
Vi kan så klart använda listkomprehension:
```
table :: [[HTML]] -> HTML
table rows =
attrTagged "table" [("border","yes")]
(list [tagged "tr" (list [tagged "td" cell | cell <- row]) | row <- rows])
```
Funktionen finns även i [``MkHTML`` MkHTML.hs]
#NEW
==Generering av större tabeller==
Vi kan generera innehållet i tabellen med listkomprehension:
```
html
"Fahrenheit to Celcius"
(table [[show f, show (5*(f - 32)/9)] | f <- [0,20 .. 300]])
```
Resultatet finns [här test2.html].
#NEW
==Fotoalbumet==
Vårt [fotoalbum test5.html] är en tabell där
- varje cell visar en miniatyrbild ("thumbnail")
- miniatyrbilden är en länk till samma bild i full storlek
Om ``pics`` är listan av bildernas URL:er, kan vi generera albumet med
```
html
"Pictures"
(table (grid 5 [link pic (image pic 128) | pic <- pics]))
```
Funktionen ``grid`` (finns i [``MkHTML`` MkHTML.hs]) styckar upp en lista
till dellistor av önskad längd:
```
grid :: Int -> [a] -> [[a]]
grid i [] = []
grid i xs = take i xs : grid i (drop i xs)
```
**Obs**: ``grid`` är en **rekursiv** funktion, dvs. den anropar sig själv.
Detta begrepp hör till nästa Haskell-kurs!
#NEW
==Hur man skapar fillistan==
Vi har använt Unix-kommandot ``ls``:
```
ls pictures/*.jpg > pics
```
som gav oss alla filer i katalogen [``pictures`` pictures/]
med namnsuffixen ``jpg``.
Dessa skrevs till filen ``pics``, som sedan lästes av en IO-funktion
så här:
```
mk_test5 :: IO ()
mk_test5 = do
s <- readFile "pics"
let pics = lines s
let doc = html
"Pictures"
(table (grid 5 [link pic (image pic 128) | pic <- pics]))
writeFile "test5.html" doc
```
Vi går inte genom detaljerna på den här kursen - men den här koden
kan tillämpas till vilken som helst katalog med JPG-filer.
#NEW
==Generering av Google-sökningar==
Om man går till [Google www.google.se] och slår in ett sökord, t.ex.
"haskell", öppnas en webbsida som har URL
```
http://www.google.se/search?&q=haskell
```
Från detta kan vi gissa en funktion
```
googled :: String -> HTML
googled s = link ("http://www.google.se/search?&q=" ++ s) s
```
För att länka varje ord i en text till en Google-sökning används
```
googledText :: String -> HTML
googledText s = unwords [googled w | w <- words s]
```
Som exempel på detta, skapar Haskell-koden
```
html
"Google bakom lankarna"
(googledText "Varje ord som klickas skickas till Google")
```
[det här dokumentet test3.html].
#NEW
==Dynamiska HTML-sidor==
Vi har visat hur man skapar **statiska sidor**: de skapas en gång, läggs ut
på nätet, och ändras inte automatiskt.
**Dynamiska sidor**: ett program skriver nya sidor t.ex. som svar till
besökarnas frågor.
Google är ett typexempel.
Haskell är ett möjligt språk även för dynamisk webbprogrammering, se
[här http://www.haskell.org/haskellwiki/Practical_web_programming_in_Haskell].
Ett exempel med Haskell,
[GF http://www.cs.chalmers.se/Cs/Research/Language-technology/GF/]
och
[Google Web Toolkit http://code.google.com/webtoolkit/]:
[flerspråkiga kylskåpsmagneter http://tournesol.cs.chalmers.se:41296/fridge/].
#NEW
==Andra sätt att skapa HTML==
De här föreläsningarna har skapats med
[txt2tags http://txt2tags.sourceforge.net/].
Källan till den här föreläsningen ser ut [så här dator-05.txt].
Fördelar:
- lättare att skriva än HTML
- kan genereras till andra format, t.ex. LaTeX (och därmed PDF)
Nackdelar:
- blir inte lika snyggt som handskrivet HTML kan bli
#NEW
==Uppgifter==
**Redovisning**. Visa de resulterande HTML-sidorna i en webbläsare.
1. Skapa en HTML-fil som innehåller ditt namn och foto (om du har
ett digitalt; annars någon annan trevlig bild). och valfritt annat
material. Gör detta manuellt i HTML eller med en Haskell-funktion
genom att använda [``MkHTML.hs`` MkHTML.hs].
2. Undersök hur man skapar söklänkar till [Wikipedia http://en.wikipedia.org/]
och generera sedan en HTML-sida som innehåller en tabell med
namnen på de 27 EU-länderna, med 3 länder på en rad.
Varje land ska vara länkat till Wikipedia-artikeln om landet.
Börja med att söka upp listan av EU-länderna på nätet.
(Vi rekommenderar engelsk Wikipedia sör att slippa problemen
med //äåö//.)
3. Skapa ett eget fotoalbum genom att återanvända funktionen ``mk_test5.html``
i [``MkHTML.hs`` MkHTML.hs]. Albumet ska innehålla minst 15 bilder.
**Tips**: om du inte har egna digitala bilder, kan du
hitta sådana med [Googles bildsökning http://images.google.se].
4. Modifiera ordstatistikfunktionen i [``Freq.hs`` Freq.hs]
([föreläsning 4 dator-04.html])
så att den skriver ut de 100 vanligaste orden med antalet förekomster till
en tabell i en HTML-fil. I redovisningen, visa resultatet för
[Röda rummet redRoom.txt].
#NEW
==Sammanfattning och referens==
Vi hade inget nytt Haskell-material, utan bara en del HTML, som
kan sammanfattas i [malldokumentet mall.html] med källkoden
```
Head: texten överst i ramen
Body: texten i textfältet.
Huvudtitel
Paragraf, bestående av text och annat, t.ex.
länkar till webbsidor,
text i fetstil,
text i kursiv,
text i maskinskrift,
text i röd font,
bilder, som är länkar till bildfiler och kan skalas till önskad storlek
(i nästa paragraf):
Lite mindre titel
Och så en tabell:
```
|