Archive for the ‘Utveckling’ Category

Prompt i terminalen som visar git- och svn-status

tisdag, januari 29th, 2013

Här kommer ett tips om du arbetar med Git eller SVN ifrån terminalen. Det går att modifiera prompten så att den visar statusen för aktuell arbetskopia.

Normalt ser prompten ut ungefär så här, beroende på distribution (jag kör Linux Mint för tillfället).

Min prompt

När jag hoppar in i en katalog som är utcheckad från SVN ser det ut så här.

Nu syns information om aktuell branch och revision, i detta fall är branchen branches/RB-1.8 och revisionen 837. Att det visas i grönt betyder att det inte finns några modifieringar. Om jag ändrar i en fil kommer prompten att bli röd.

Modifierad arbetskopia

Arbetar du med Git syns liknande information i prompten. På bilden nedan syns hur jag går in i en katalog som är klonad från Git, skapar en ny branch med git flow och redigerar en fil. Prompten byter även här färg till rött när det finns modifierade filer och när jag committar mina ändringar ändrar färgen till grön igen. Jag slutför min feature (branch) och promten ändras igen så att aktuell branch (develop) visas.

Git prompt

För att få den här funktionaliteten läggar man till kodsnutten nedan i filen .bashrc som finns i din hemkatalog, finns den inte går det bra att skapa den. För att scriptet ska fungera måste filen /etc/bash_completion.d/git finnas, den kommer vanligen med i installationen av git, åtminstone om du installerar med apt-get install git.

Här kommer då koden.

# Custom PS1 prompt to show git and svn repos, branches and their status
Color_Off="\[\033[0m\]"       # Text Reset
Green="\[\033[0;32m\]"        # Green
BGreen="\[\033[1;32m\]"       # Green
BYellow="\[\033[1;33m\]"      # Yellow
IRed="\[\033[0;91m\]"         # Red
PathShort="\w"

export SVN_SHOWDIRTYSTATE=1
export PS1='$(git branch &>/dev/null;\
if [ $? -eq 0 ]; then \
  # In Git repo
  echo "$(echo `git status` | grep "nothing to commit" > /dev/null 2>&1; \
  if [ "$?" -eq "0" ]; then \
    # Clean repository - nothing to commit
    echo "'$Green'"$(__git_ps1 " (%s)"); \
  else \
    # Changes to working tree
    echo "'$IRed'"$(__git_ps1 " {%s}"); \
  fi) '$BYellow$PathShort$Color_Off'\$ "; \
elif [[ -d ".svn" ]] ; then \
  # In SVN repo 
  r=`__svn_rev` ;\
  b=`__svn_branch` ;\
  out=`svn status | grep -c ".*"` ; \
  if [ $out -eq 0 ] ; then \
    echo "'$Green'[$b:$r] '$BYellow$PathShort$Color_Off'\$ "; \
  else \
    echo "'$IRed'[$b:$r] '$BYellow$PathShort$Color_Off'\$ "; \
  fi; 
else \
  @2 - Prompt when not in GIT repo
  echo " '$BGreen'\u@\h '$BYellow$PathShort$Color_Off'\$ "; \
fi)'

# Outputs the current trunk, branch, or tag
__svn_branch() {
    local url=
    if [[ -d .svn ]]; then
        url=`svn info | awk '/URL:/ {print $2}'`
        root=`svn info|awk '/Repository Root/ {print $3}'`
        if [[ $url =~ trunk ]]; then
            echo trunk
        elif [[ $url =~ /branches/ ]]; then
            echo ${url##$root/}
        elif [[ $url =~ /tags/ ]]; then
            echo ${url##$root/}
        fi
    fi
}

# Outputs the current revision
__svn_rev() {
    local r=$(svn info | awk '/Revision:/ {print $2}')
    if [ ! -z $SVN_SHOWDIRTYSTATE ]; then
        local svnst flag
        svnst=$(svn status | grep '^\s*[?ACDMR?!]')
        [ -z "$svnst" ] && flag=*
        r=$r$flag
    fi
    echo $r
}

Rock on!

Tömma cache och generera autoloads i eZ Publish ifrån Netbeans

måndag, januari 14th, 2013

För att slippa hoppa ut i terminalen och köra scripten när man uppdaterat från svn, kan man göra följande.

Skapa en fil, exempelvis run.php i roten på ez-installationen. Kom ihåg att lägga till den i svn ignore! Filen ska se ut så här:


<?php
/*
 * Rensa cache och generera autoloads
 *
 */
system("/usr/bin/php bin/php/ezpgenerateautoloads.php");
system("/usr/bin/php bin/php/ezcache.php --clear-all --purge");
?>

1. Öppna projektet i Netbeans.
2. Klicka på File-menyn och välj Project Properties.
3. Klicka på Run Configuration i vänster-menyn.

Gör följande inställningar:
Run As: Script (run in command line)
Index File: run.php (Alltså filen du skapade tidigare)
Working Directory: /var/www/hmpr (Alltså ez root)

Se bilden hur det ska se ut.

Netbeans inställningar

Klicka Ok.
Nu kan man köra detta genom att antingen välja Run-menyn och sedan Run Project, eller genom att trycka F6!

Använd error-loggen!

måndag, mars 5th, 2012

error_logOfta när jag ska hjälpa någon av våra utvecklare med ett problem är min första fråga: Vad står det i loggen? Apache och php har väl utvecklade loggfunktioner och man kan med hjälp av dom få en ganska bra fingervisning om vad som orsakar problemet.  Exempelvis kan det stå:

[Fri Mar 02 17:38:08 2012] [error] [client 127.0.0.1] PHP Parse error:  syntax error,
unexpected ';' in /var/www/smhifb/application/controllers/start.php on line 64</pre>

Just det här felet beror förmodligen på att det saknas en slutparantes eller klammer på rad 64 i filen start.php (Nu var det här bara ett exempel, eftersom rena syntaxfel så klart hittas av din IDE, som jag utgår ifrån att  du använder.)

När jag utvecklar har jag alltid ett terminalfönster öppet som visar loggarna i realtid så att jag snabbt ska kunna se om det händer något som inte borde hända, när man surfar in i applikationen.  Även om man inte märker några fel när man surfar så händer det ändå att det dyker upp fel i loggen. Oftast är detta då varningar eller notiser, vilka inte är fatala för körningen av koden. Det är väldigt vanligt att man ändrar i php.ini så att notiser och till och med varningar inte visas i loggen, koden fungerar ju ändå. Gör inte det! Se till att varningar och notiser loggas och fixa till felen! Den enda anledningen till att folk slår av notiser och varningar är att dom antingen är lata eller programmerar dåligt.  Det är lika vanligt att de som har varningar och notiser aktiverat inte bryr sig om att rätta till dessa fel, eftersom det fungerar ändå. Var inte en lat programmerare! Konsekvensen blir att koden inte blir så optimerad som den kunnat vara, dessutom kan små fel bli betydligt större längre fram.

Ett litet tips, använd programmet multitail. Multitail är ett program som körs i konsollen och kan visa flera loggar samtidigt i realtid. Vanligen när man vill se en logg i realtid använder man sig av kommandot tail med växeln -f, exempelvis:

tail -f /var/log/httpd/error_log

Med multitail kör man istället

multitail /var/log/httpd/error_log /var/log/httpd/access_log

Detta medför att terminalfönstret delas på två och visar en logg i varje del. Det är otroligt smidigt att se error-loggen i den ena delen och access-loggen i den andra. Det allra bästa med multitail är att det har syntax highlighting, det skriver alltså ut olika saker i olika färger, vilket gör det enklare  att se i loggen. multitail
Så, en kort sammanfattning.

  • Använd error-loggen
  • Se till att varningar och notiser visas
  • Fixa felen, även varningar och notiser
  • Visa loggen i realtid i ett eget terninalfönster
  • Använd multitail

Kod ska vara kul  och är det också med rätt förutsättningar, en av dessa förutsättningar är att veta vad som är fel och framför allt veta att det är fel.

wget i OS X Lion

fredag, januari 27th, 2012

wget för osxKommandot wget, som bland annat kan användas för hämta filer och sidor via http och ftp, finns tyvärr inte i Osx Lion. Det här är något som irriterat mig ett tag, men som jag av olika anledningar inte tagit tag i än. Så idag när jag satt och skrev lite nya alias för diverse kommandon (jag gör så för exempelvis de ssh-anslutningar jag ofta använder, det går fortare att bara skriva goserver1 istället för att skriva ssh -p 2211 daniel@server1.domain.com), så kom jag på att curl faktiskt finns i Lion. Varför helt enkelt inte göra ett alias för wget till curl? Så här gör man.

I min hemkatalog finns en fil som heter .bash_profile, i den lägger jag till följande rad:

alias wget='curl -O'

Sedan sparar jag filen och stänger alla eventuella terminal-fönster och öppnar ett nytt. Nu kan jag använda mig av kommandot wget för att hämta hem filer:

wget http://server1.domain.com/path/large_file.zip

Det här blir så klart inte exakt detsamma som att ha wget installerat på riktigt, eftersom wget kan göra så mycket mer än att bara hämta en fil, men i 99% av fallen är det just bara det jag använder det till. Ska jag göra något mer avancerat snickrar jag hellre ihop ett skript, antingen i bash eller i PHP.

OSX – som Linux fast snyggare!

Manuell databasfråga i eZ Publish, för ökad prestanda

tisdag, januari 24th, 2012

eZ Publish är ett mycket kompetent system för innehållshantering, men ibland kan man behöva gå förbi alla praktiska funktioner som finns. Bland annat kan det vara aktuellt att göra detta när man vill lista en stor mängd data i tabellform, till exempel en medlemslista. Vi hade ett projekt där kunden ville att ungefär 900 medlemmar skulle visas samtidigt i en lista, samt på en Googlekarta, vilket gjorde att det inte blev riktigt optimalt att använda de befintliga funktionerna i eZ Publish, det gick helt enkelt för långsamt. För att lösa problemet byggde jag en modul med en custom fetch som tog hand om det hela istället för de inbyggda fetch-funktionerna. Hur man bygger en egen modul finns väl dokumenterat och det är inget jag tänker beskriva nu, däremot fanns det väldigt lite information (i princip obefintlig) om hur man hämtar ut information direkt ur databasen. Genom att studera databasen och med hjälp av lite reverse enginering kom jag fram till följande.

Om man utgår från tabellen ezcontentobject_tree som representerar nodträdet så kan man köra en sql-fråga för att få fram alla barn till en viss nod.

SELECT et.contentobject_id id
FROM   ezcontentobject_tree et
WHERE  et.parent_node_id = 2

Satsen ovan ger följande resultat.

+------+
| id   |
+------+
|   58 |
|   59 |
|   76 |
|  122 |
+------+

Alltså, en lista på de objekt-id’n som finns direkt under noden med id 2.

Information om varje objekt lagras i tabellen ezcontentobject_attribute, därför gör man en JOIN för att få ut även denna information. Satsen blir då så här.

SELECT et.contentobject_id id,
       en.data_text        namn
FROM   ezcontentobject_tree et
       LEFT JOIN ezcontentobject_attribute en
         ON et.contentobject_id = en.contentobject_id
            AND et.contentobject_version = en.version
            AND en.contentclassattribute_id = 361
WHERE  et.parent_node_id = 97
       AND et.contentobject_is_published = 1
       AND et.is_hidden = 0
       AND et.is_invisible = 0

Här hämtas alltså information från tabellen ezcontentobject_attribute med contentclassattribut_id lika med 361, vilket är objektets namn i detta fall. Detta id hittar man i administrationsgränssnittet under Setup->Classes och sedan den klass objektet är en instans av. Se bilden nedan.

Jag har i satsen ovan lagt  till tre villkor i slutet som ser till att man bara får träffar på noder som är publicerade och synliga på sajten.

Resultatet blir.

+------+-----------------------------+
| id   | namn                        |
+------+-----------------------------+
|  398 | COOP OBS! LILLESTRØM        |
|  399 | COOP OBS! LØREN             |
|  400 | COOP OBS! MARIERO           |
|  401 | COOP OBS! MORENEN           |
|  402 | COOP OBS! NORD AVD. HARSTAD |
+------+-----------------------------+

För varje attribut man vill hämta ut måste man alltså göra en extra JOIN enligt ovan.

Om man vill hämta attribut av typen ezurl måste man göra två extra JOINs eftersom själva urlen sparas i tabellen ezurl och korskopplas i tabellen ezurl_object_link. Det man måste lägga till är alltså.

LEFT JOIN ezcontentobject_attribute eu
  ON et.contentobject_id = eu.contentobject_id
     AND et.contentobject_version = eu.version
     AND eu.contentclassattribute_id = 367
LEFT JOIN ezurl_object_link eol
  ON eu.id = eol.contentobject_attribute_id
     AND eu.version = eol.contentobject_attribute_version
LEFT JOIN ezurl eurl
  ON eol.url_id = eurl.id

Den kompletta sql-frågan blev så här.


SELECT et.contentobject_id id,
       en.data_text        name,
       etel.data_text      tele,
       efa.data_text       fax,
       pnr.data_text       postnr,
       por.data_text       postort,
       em.data_text        email,
       eurl.url            url
FROM   ezcontentobject_tree et
       LEFT JOIN ezcontentobject_attribute en
         ON et.contentobject_id = en.contentobject_id
            AND et.contentobject_version = en.version
            AND en.contentclassattribute_id = 361
       LEFT JOIN ezcontentobject_attribute etel
         ON et.contentobject_id = etel.contentobject_id
            AND et.contentobject_version = etel.version
            AND etel.contentclassattribute_id = 362
       LEFT JOIN ezcontentobject_attribute efa
         ON et.contentobject_id = efa.contentobject_id
            AND et.contentobject_version = efa.version
            AND efa.contentclassattribute_id = 363
       LEFT JOIN ezcontentobject_attribute pnr
         ON et.contentobject_id = pnr.contentobject_id
            AND et.contentobject_version = pnr.version
            AND pnr.contentclassattribute_id = 364
       LEFT JOIN ezcontentobject_attribute por
         ON et.contentobject_id = por.contentobject_id
            AND et.contentobject_version = por.version
            AND por.contentclassattribute_id = 365
       LEFT JOIN ezcontentobject_attribute em
         ON et.contentobject_id = em.contentobject_id
            AND et.contentobject_version = em.version
            AND em.contentclassattribute_id = 366
       LEFT JOIN ezcontentobject_attribute eu
         ON et.contentobject_id = eu.contentobject_id
            AND et.contentobject_version = eu.version
            AND eu.contentclassattribute_id = 367
       LEFT JOIN ezurl_object_link eol
         ON eu.id = eol.contentobject_attribute_id
            AND eu.version = eol.contentobject_attribute_version
       LEFT JOIN ezurl eurl
         ON eol.url_id = eurl.id
WHERE  et.parent_node_id = 97
       AND et.contentobject_is_published = 1
       AND et.is_hidden = 0
       AND et.is_invisible = 0

Resultatet av frågan blir.

+------+-----------------------------+-------------+-------------+--------+------------+------------------------------+------+
| id   | name                        | tele        | fax         | postnr | postort    | email                        | url  |
+------+-----------------------------+-------------+-------------+--------+------------+------------------------------+------+
|  398 | COOP OBS! LILLESTRØM        | 63 80 55 00 | 63 81 38 30 | 2000   | LILLESTRØM | xxxxx.xxxxx@obs.coop.no      | NULL |
|  399 | COOP OBS! LØREN             | 22 65 50 65 | 22 64 57 17 | 0513   | OSLO       | xxx.xxx.xxx.xxx@obs.coop.no  | NULL |
|  400 | COOP OBS! MARIERO           | 51 82 50 50 | 51 82 50 51 | 4095   | STAVANGER  | xxxx.xxxxxxx@obs.coop.no     | NULL |
|  401 | COOP OBS! MORENEN           | 69 84 65 00 | 69 84 65 51 | 1859   | SLITU      | xxxxxx.xxxxxxx@obs.coop.no   | NULL |
|  402 | COOP OBS! NORD AVD. HARSTAD | 77 02 89 00 | 77 02 89 01 | 9406   | HARSTAD    | xxxxxx.xxxxxx.x@nord.coop.no | NULL |
+------+-----------------------------+-------------+-------------+--------+------------+------------------------------+------+

Den här datan använde vi sedan för att bygga en lista över medlemmarna. Vi valde dessutom att generera html-koden direkt i modulen eftersom vi fortfarande inte var helt nöjda med prestandan när vi använde de befintliga template-funktionerna.

Resultatet kan du se här: http://elektronikkbransjen.no/Medlem/Medlemsoversikt

All utdata från sql-satserna ovan är förkortade, den vekliga utdatan var mer än 900 rader.
Epost-adresserna i utdatan ovan är modifierade på grund av sekretess.

Dynamisk VirtualHost i Apache

tisdag, maj 17th, 2011

Utvecklar du sajter och lägger varje gång till en ny Virtual Host i Apaches konfigurationsfil så har jag ett tips, VirtualDocumentRoot! Om du har en utvecklingsdomän som heter domain.com skapar du ett wildcard i DNS’en ( *.domain.com ) som pekar mot din utevecklingsmaskin. I Apache’s konfiguration gör du sedan så här:


<VirtualHost *:80>
ServerAlias *.domain.com
UseCanonicalName Off
VirtualDocumentRoot /var/www/dev/%1
ErrorLog logs/dev-errorlog
CustomLog logs/dev-access.log combined
</VirtualHost>

Den här metoden kräver att modulen mod_vhost_alias är laddad i Apache.

Nu kan du skapa en katalog i /var/www/dev för varje nytt projekt och du kan automatiskt surfa till det genom att använda katalogens namn som subdomän. Alltså, /var/www/dev/projekt1 kan kommas åt via http://projekt1.domain.com.

Hur smidigt som helst 🙂

Versionshantering med Subversion

måndag, mars 14th, 2011

När man utvecklar så är det så klart själva kodandet man har i fokus, inget konstigt med det, men när man bygger större sajter eller webb-applikationer där man är fler än en utvecklare måste man börja tänka på andra saker.  Man måste bland annat på något vis dela upp arbetet så att flera personer inte gör samma sak, man måste även se till att två personer inte redigerar samma fil samtidigt för att sedan skriva över varandras ändringar. En lösning på dessa problem är att använda sig av ett versionshanteringssystem, exempelvis Subversion.

Subversion, förkortat svn, är enkelt uttryckt en databas som innehåller all kod man utvecklar. När jag ska börja utveckla en viss funktion på en sajt ser jag till att hämta hem den senaste versionen av koden från databasen, eller med  korrekta termer, jag checkar ut koden. Jag har nu all kod på min egen dator och utvecklar min funktion och när jag är klar så skickar jag tillbaka koden till databasen, jag gör en commit (eller commitar som vi säger på svengelska). När jag gör det så kontrollerar svn att det inte finns en nyare version av de filer jag editerat, om det finns det så ber servern mig att uppdatera mina filer först. När jag uppdaterar så försöker svn att slå ihop mina utvecklade funktioner med den befintliga koden, och efter det kan jag commita igen. Det fina med det hela är att det är bara filer som är ändrade som överförs, jag behöver alltså inte ladda hem eller ladda upp all kod igen. Om svn inte kan slå ihop mina förändringar med den befintliga koden så får jag lösa det själv genom att jag får se filen i de olika versionerna sida vid sida och kan på så vis bestämma hur slutresultatet ska se ut. Det där beror så klart lite på vilken editor man använder, men de flesta avancerade utvecklingsverktygen har stöd för svn och då fungerar det som jag sa ovan.

En av de absoluta fördelarna med att använda Subversion är att alla versioner av filerna sparas. Man kan alltså när som helst gå tillbaka till vilken version som helst av filen. Säg att jag märker att en viss funktion har slutat fungera, då kan jag enkelt backa till en tidigare version, där jag vet att det fungerade. Ungefär som en flerstegs undo 🙂

Med hjälp av Subversion kan alltså flera utvecklare arbeta samtidigt på samma kod utan att behöva bry sig om att de andra gör det samtidigt.

En annan väldigt praktisk funktion är något som kallas för taggning. När vi tycker att vi har utvecklat klart och det är dags att publicera det vi gjort kan vi ”tagga” koden. Detta innebär att om jag exempelvis taggar aktuell kod i databasen med v1.0 (första versionen av applikationen) och sedan fortsätter att utveckla, så kommer databasen ändå ihåg exakt hur all kod såg ut vid taggningen. Man kan säga att det skapas en kopia av koden exakt vid ögonblicket för taggningen även om det inte sker i verkligheten. Jag kan nu alltså när jag vill hämta hem version 1.0 av applikationen, även om vi fortsatt utvecklingen och kommit till version 1.5. På det här viset kan vi även buggfixa på version 1.4 samtidigt som utveckling sker på 1.5, vilket underlättar otroligt mycket om version 1.5 innehåller mycket ny funktionalitet.

För dig som använder Mac har tidningen Macworld har skrivit en artikel som går igenom grunderna i Subversion på just Mac.

 

Bättre url_title() i Codeigniter

onsdag, januari 5th, 2011

Codeigniter är bra på många vis när man ska bygga php-applikationer, dessvärre finns det en del funktioner som inte är helt optimerade för det svenska språket, exempelvis url_title(). url_title() är en funktion som finns i en helper som heter URL Helper och gör om en textsträng till en URL-vänlig sträng så här:

$title = "What's wrong with CSS?";
$url_title = url_title($title);
echo $url_title;

Detta skulle eka ut Whats-wrong-with-CSS, alltså utan mellanslag och apostrofer. Problematiken kommer när man vill göra om en sträng som innehåller svenska tecken eller accenter.

$title = "Jag håller med";
$url_title = url_title($title);
echo $url_title;

Detta skulle bara eka ut Jag-h, allt från och med det svenska tecknet strippas bort, vilket naturligtvis inte är önskvärt. Som tur är kan man i Codeigniter åsidosätta de inbyggda funktionerna med sina egna om man vill, genom att skapa en egen helper i katalogen application/helpers/, exempelvis better_helper.php. I den här filen lägger vi en funktion med samma namn som den inbyggda, i detta fall url_title. Nu kommer vår funktion i better_helper.php att användas istället för den inbyggda. Vi måste även se till att ladda vår nya helper innan URL Helper, annars kommer vår nya funktion inte att fungera.

Vår nya funktion som ska ligga i better_helper.php och som min kollega Jocke ligger bakom, ser ut så här:


/**
* Create better url_titles
*/
if ( ! function_exists(‘url_title’))
{
 function url_title($str, $separator = ‘dash’)
 {
  $separator = ($separator == ‘underscore’) ? ‘_’ : ‘-’;
  $str = strtolower(htmlentities($str, ENT_COMPAT, ‘UTF-8′));
  $str = preg_replace(‘/&(.)(acute|cedil|circ|grave|ring|tilde|uml);/’, “$1″, $str);
  $str = preg_replace(‘/([^a-z0-9]+)/’, $separator, html_entity_decode($str, ENT_COMPAT, ‘UTF-8′));
  $str = trim($str, $separator);
  return $str;
 }
}
// ————————————————————————

Den här funktionen gör om svenska tecken till a respektive o, samt tar bort accenter, så om vi kör samma kod igen får vi följande.

$title = "Jag håller med";
$url_title = url_title($title);
echo $url_title;

Detta ekar ut Jag-haller-med, vilket är vad vi vill ha. Tack Jocke 🙂

Uppdatera en div med jQuery i oändlig loop.

onsdag, september 1st, 2010

Jag kom fram till en smidig lösning idag när en kund behövde en sida som automatiskt laddade om för att visa sju olika sidor i tur och ordning och den lösningen tänkte jag dela med mig av. Sidorna som skulle laddas hette någonting i stil med sida.php?id=123. Jag tyckte att sidladdningar var onödigt och ville istället ladda sidan inuti en div-container med hjälp av jQuery. Så här gjorde jag.


var sidIdArr = ['1','2','3','4','5'];
laddaOm(sidIdArr.length);

function laddaOm(idx) {
  if(idx>=sidIdArr.length) {
    idx=0;
  }

  $("#main_box").load("/sida.php?id="+sidIdArr[idx++]+" #main_box>*","");
  timerID=setTimeout('laddaOm('+idx+')', 30000);
}

Arrayen sidIdArr innehåller alltså id på de sidor vi vill ladda. I funktionen laddaOm kontrollerar vi om vi är på sista positionen i arrayen, om vi är det sätter vi nyckeln till 0 för att börja om från början igen.

I nästa steg laddar vi alltså div’en main_box med innehållet av sidan sida.php?id=XXX, där XXX är aktuellt array-värde. Som ni ser står det #main_box i slutet av urlen, genom att ange en container efter url’en så laddas bara innehållet i denna container, i detta fall är det samma container som vi vill visa datat i. På detta vis kan vi koda hela funktionaliteten i en och samma sida, vi bara byter parameter i anropet. I sidIdArr[idx++] ökar vi även värdet på idx.

I det sista steget använder vi setTimeout för att köra funktionen laddaOm efter 30 sekunder igen.

Istället för att surfa till sju olika sidor i tur och ordning har vi nu byggt ett script som automatiskt växlar innehåll var 30’e sekund, utan sidladdning. När det kommer till slutet börjar det om från början igen. En perfekt lösning för exempelvis ett bildspel på webben, eller som i detta fall, visning av statistik.