JavaScript
Børre Stenseth

JavaScript på en webside

Hva

Vi har slått fast at JavaScript kjører i en sandkasse, uten tilgang til annet enn den websiden det er koplet til. Det vi skal se litt på her er hvordan koplingen mellom scriptet og websiden er, og vi skal se litt på debugging av script.

Det vi hele tiden må huske er at JavaScript er et interpretert språk. Det vil si at språket ikke kompileres før det kjøres.

Plassering av JavaScriptet

Vi kan i prinsipp plassere JavaScript-kode hvor vi vil på en HTML-side. Koden skal pakkes inn i script-elementer, f.eks. slik:

<script type="text/javascript">
  function myfunction()
  {
    ...
  }
</script>

Normalt samler vi koden i head-elementet på en HTML-side. Fordelen er da at scriptet er på plass når resten av siden lastes og eventuelt forsøker å bruke det.

Det finnes imidlertid en del situasjoner der det er lettere å tenke omvendt, nemlig at hele eller deler av siden er lastet før vi introduserer javascript-komponenter.

Det er ofte en god ide å legge skriptet på en fil for seg og la nettleseren hente det når siden lastes:

<script type="text/javascript" src="mycode.js"> </script>

Det er to grunner til dette. Den ene grunnen er den åpenbare at vi kan vedlikeholde skriptet ett sted selv om det brukes på mange sider. Den andre grunnen er at vi sparer litt tid ved at skriptfila caches og altså ikke trenger å lastes hver gang sider lastes. Merk at script lastes og parses, interpreteres, i det øyeblikk DOM-parseren finner script-elementet, enten det ligger i selve dokumentet eller det hentes fra en fil.

Når vi av og til ønsker å plassere script-elementer andre steder enn i head-elementet er det fordi at vi vil at scriptet skal forholde seg til komponenter som allerede er lastet inn og parset som en del av DOM. Hvis vi f.eks. skriver følgende i head-elementet:

<script type="text/javascript">
    var antallParagrafer=null;
    function tellParagrafer(){
            antallParagrafer=document.getElementsByTagName('p').length;
            alert("antall paragrafer på denne siden er: "+antallParagrafer);
    }
</script>

så vil antallParagrafer bli initiert til null. Funksjonen tellParagrafer vil ikke bli kjørt før den eventuelt kalles. Det kan vi gjøre ved å sette inn følgende som siste element i body-elementet:

<script type="text/javascript">
tellParagrafer()
</script>
Et enkelt eksempel https://borres.hiof.no/wep/js/onpage/demo1.html

Vi kunne i dette tilfellet alternativt ha kalt funksjonen ved onload-begivenheten i body-elementet:

<body onload="tellParagrafer()">

Dersom vi inkluderer skriptet på selve siden er det av og til lurt å maskere javaskriptkoden slik at den ikke parses som en del at det HTML-dokumentet er plassert på. Dette kan vi gjøre slik:

<script type="text/javascript">
//<![CDATA[
function f()
{
  T='';
  for(ix=1; ix < 4; ix++)
    T+=ix;
  alert(T+' : kjør');
}
//]]>
</script>

Linjene:

//<[CDATA[
//]]>

Oppfattes som kommentarer i javaskriptkoden, mens CDATA hindrer webparseren i å parse innholdet. På denne måten unngår vi at tegn som < og > i skriptet blir tolket som en del av dokumentstrukturen.

Vi kan også inkludere script på websiden som skriver direkte til siden der det plasseres. Det vil si at scriptet når det interpreteres bidrar til DOM-treet. F.eks er linja nedenfor skrevet direkte fra et script:

script-elementet ser slik ut:

<script type="text/javascript">
	document.write('<p style="color:red">Hallo der</p>');
</script>

defer

Vi er ofte i den situasjonen at et javaskript er avhengig av elementer på websiden for å gjøre jobben. Det er mange måter å løse dette på. Vi kan inkludere skriptet med en script-tag etter at de nødvendige sidekomponenetene er lastet. Vi kan samle funksjonaliteten i en funksjon som kalles "nederst" på siden eller ved body-onload.

Vi har også muligheten for å merke en skript fil med defer. Det innebærer at scriptet ikke loades og parses før siden er lastet. F.eks. slik:

<script src="test2.js" type="text/javascript" defer="defer"> </script>

Jeg har skrevet defer="defer" fordi jeg av vedlikeholdsårsaker er glad i velformet (X)HTML. defer hadde vært nok.

Testing og debugging

Det har vært ganske grisete å teste javascript. Det har vært laget flere forsøk på å bygge strukturer som gjør det mulig å bruke en unit-testing strategi slik som vi kjenner fra en rekke andre språk, som Java, C#, Python. Problemet med dette for de fleste av oss er at feilene vi sliter med oftest er koplet til kodens forhold til omgivelsene, DOM-strukturen eller CSS. Det blir derfor vanskelig å etablere testomgivelser som er særlig nyttige. Dette stiller seg annerledes dersom vi skal utvikle tyngre javaskriptbiblioteker, der fokus er på selve kode.

Det de fleste av oss har gjort er å bruke alert for å vise verdier underveis i koden, eller å skrive til selve websiden. Det siste kan vi gjøre med document.write som vist overfor eller vi kan lage oss en enkel dump-funksjon som rapporterer status i et element på siden mens vi tester.

Heldigvis har dette blitt veldig mye bedre de siste årene. Alle de store nettleserne har utvklerverktøy som setter oss i stand til å inspisere staus på DOM og vi kan sette breakpoints i javaskriptkoden og inspisere variable.

Jeg bruker stort sett FireFox som utviklings- og testomgivelse, men du finner lignende løsninger i andre nettlesere. Det første jeg gjør er å sette opp
Tools : Web Developer : Browser Console.
Når det er gjort kan jeg skrive til konsollet fra javascriptkoden, se Console hos Mozilla [1] . Vi har mange mulige rapporteringsformer:

  • console.clear()
    Tømmer konsollet
  • console.log()
    console.log("hallo")
  • console.warn()
    console.warn("dette kan gå galt")
  • console.info()
    console.info("nå har vi kommet så langt")
  • console.error()
    console.error("dette skulle ikke hendt")
  • console.dir()
    console.dir(personer[i])

console API'et gir oss mange muligheter for å formatere rapporteringen ut over ren tekst som vist ovenfor. Merk spesielt dir() som rapporterer attributter og metoder i et objekt.

Dersom jeg ikke får tilstrekkelig kontroll og innsikt via konsollet, har jeg en rekke andre muligheter i Web Developers tools. Jeg kan inspisere dynamiske endringer i DOM-strukturen, i CSS og jeg kan sette breakpoints i koden og inspisere variable.

Referanser
  1. Console Mozilla Developers Network developer.mozilla.org/en-US/docs/Web/API/console 25-01-2014