Övningar i JavaScript – del 4

Medieteknik
Övningar i JavaScript – del 4 I dessa övningar ska du dels hantera ett formulär och dels arbeta med några textsträngar.
1. Dokument i övningsmappen
Övningsmappen som du laddar ner från laborationens webbsida innehåller exempel 4 från föreläsning
F12. I denna laboration arbetar du vidare med det formulär som finns där.
2. Funktion för att beräkna kostnaden
Du ska nu skriva funktionen för att beräkna kostnaden av de val som användaren gör.
Definiera funktionen och anropa den från knappen •
Skriv in följande funktion längst ner i script-filen:
function calculateCost() {
}
•
Lägg in ett onclick-attribut i input-taggen för knappen "Beräkna kostnaden":
<input type="button" value="Beräkna kostnad"
onclick="calculateCost()">
Tagg för resultat Resultatet av beräkningen ska skrivas i span-taggen med id="totalCost", så skapa en referens till den i
JavaScript-koden.
•
Lägg till en global variabel högst upp i script-filen:
var totalCostTag;
•
Initiera variabeln i funktionen init:
function init() {
...
totalCostTag = document.getElementById("totalCost");
...
}
2012-11-19 – Rune Körnefors ([email protected])
1
Medieteknik
Avläs menyn för antal nätter Menyn består av ett select-element med ett antal option-taggar. Man refererar till select-elementet och
avgör vilken option-tagg som är vald. Sedan kan man avläsa value-attributet i den option-taggen.
•
Lägg till följande rader i funktionen, för att avläsa antal nätter:
function calculateCost() {
var nightOption, nrOfNights, roomPrice, totalCost, i, theValue;
nightOption = formTag.nights.selectedIndex;
nrOfNights = Number(formTag.nights.options[nightOption].value);
totalCostTag.innerHTML = nrOfNights;
}
Ett antal lokala variabler införs. Just nu behövs endast de två första. Övriga behövs i
kommande övningar, men vi inför dem redan nu, så är det gjort.
o Variabeln formTag är initierad i funktionen init och är en referens till form-elementet i
HTML-koden.
o I HTML-koden finns ett select-element med name="nights". Det innehåller också ett antal
option-taggar. Med formTag.nights får vi en referens till select-elementet. Observera att vi
nu använder referens via namn istället för id. Egenskapen selectedIndex är ett tal som är
index till det alternativ som är valt i menyn. Index börjar på 0, för det första alternativet.
o Med formTag.nights.options får vi en array bestående av alla option-taggar i menyn.
Genom att indexera med det index som togs fram på föregående rad, får vi den optiontagg som är vald. Där avläser vi value-attributet från HTML-koden. (Titta i HTMLdokumentet och kontrollera att antal nätter är inlagda i alla option-taggars value-attribut.)
o Eftersom innehållet i value-attributet i första hand tolkas som text, så konverterar vi till ett
tal med Number.
o För att kontrollera att vi får fram rätt värde, så skriver vi ut antal nätter i taggen för total
kostnad. Detta ska sedan ändras.
Testa i webbläsaren.
o Välj ett antal nätter i menyn och klicka på knappen "Beräkna kostnad".
o
•
Avläs radioknapparna för rumstyp Radioknapparna är ett antal input-taggar med type="radio". De hr också ett name-attribut med samma
namn. Därmed grupperas de och endast en av dem kan vara vald. Varje knapp har också en egenskap
kallad checked, som är true om knappen är vald, annars false.
•
Utöka nu funktionen med följande rader:
function calculateCost() {
var nightOption, nrOfNights, roomPrice, totalCost, i, theValue;
nightOption = formTag.nights.selectedIndex;
nrOfNights = Number(formTag.nights.options[nightOption].value);
for (i=0; i<formTag.room.length; i++) {
if (formTag.room[i].checked) {
theValue = formTag.room[i].value;
roomPrice = Number(theValue.split(",")[1]);
break;
}
}
totalCostTag.innerHTML = roomPrice;
}
o
I HTML-koden har radioknapparna samma namn, room. För att ta reda på vilken som är
vald, kan vi inte göra på samma sätt som för menyn. I detta fall finns inget selectedIndex.
Istället får vi kontrollera knapp för knapp och se om egenskapen checked är true.
2012-11-19 – Rune Körnefors ([email protected])
2
Medieteknik
Med formTag.room får vi en array med alla input-taggar med name="room". Med
egenskapen length får vi fram hur många det är. Därmed kan vi gå igenom dem i en forloop.
o I if-satsen kontrolleras aktuell knapp och dess egenskap checked. Är den true, så har vi
hittat den knapp som är vald. Då avläser vi dess value-attribut från HTML-koden.
o Värdet är t.ex. "enkelrum,600" (se HTML-koden). Texten "enkelrum" finns med, eftersom
vi vill ha med den, då formulärets data skickas iväg för att göra beställningen. Men just nu
vill vi endast ha priset, som är tecknen efter kommatecknet. Det får vi genom att dela upp
strängen till en array med komma som skiljetecken. Det andra elementet (som indexeras
med 1) blir priset. Vi ser också till att det tolkas som ett tal, genom att konvertera med
Number.
o Då vi hittat den knapp som är vald, behöver vi inte fortsätta i loopen, utan den avbryts
med break.
o Utskriften i taggen för totala kostnaden ändras nu till roomPrice, så att vi kan kontrollera
att vi får fram rätt värde.
Testa i webbläsaren.
o
•
Avläs kryssknapparna för tilläggen Kryssknappar fungerar som radioknappar, men man kan där välja flera alternativ eller inget, även om
de har samma namn i name-attributet.
•
Lägg till följande kod för att avläsa tilläggen:
function calculateCost() {
...
for (i=0; i<formTag.extra.length; i++) {
if (formTag.extra[i].checked) {
theValue = formTag.extra[i].value;
roomPrice += Number(theValue.split(",")[1]);
}
}
totalCost = nrOfNights * roomPrice;
totalCostTag.innerHTML = totalCost + " kr";
}
Alla kryssknappar för tilläggen ha samma namn, extra. Därmed kan vi referera till dem
som en array och gå igenom dem i en loop på samma sätt som för radioknapparna. Men i
detta fall kan flera knappar vara valda, så vi avbryter inte loopen, utan går igenom alla
knappar.
o Även i detta fall består value-attributet av två delar, t.ex. "Internet,40", och det är den
andra delen som är priset. Så vi tar ut det på samma sätt som i föregående steg med
rumspriset.
o För varje extra tillägg som valts, ökar rumspriset, så det läggs till med +=.
Testa i webbläsaren.
o
•
Kontrollera också om alternativet är aktivt eller ej Om du först valt enkelrum eller dubbelrum, går det välja sjöutsikt. Väljer du sedan familjerum, så
gråmarkeras alternativet med sjöutsikt, men det är fortfarande valt och kommer därför med i priset. Vi
måste alltså också testa egenskapen disabled för knapparna.
2012-11-19 – Rune Körnefors ([email protected])
3
Medieteknik
•
Lägg till ett test av disabled i if-satsen:
function calculateCost() {
...
for (i=0; i<formTag.extra.length; i++) {
if (formTag.extra[i].checked && !formTag.extra[i].disabled) {
theValue = formTag.extra[i].value;
roomPrice += Number(theValue.split(",")[1]);
}
}
...
}
Observera utropstecknet framför testet. Egenskapen disabled är true om knappen är
inaktiv och false om den är aktiv. Det är endast då den är aktiv, dvs disabled är false som
vi ska ta med den i beräkningen. Vi inverterar därför värdet med utropstecknet, dvs det
som testas är att den inte är disabled.
Testa i webbläsaren.
o
•
3. Kontroll av formuläret innan det skickas
Då man klickar på submit-knappen inträffar händelsen onsubmit. Denna fångas upp i form-taggen (se
HTML-koden) och funktionen checkForm anropas. I denna funktion finns redan en del kontroll av
innehållet, men du ska nu fylla på med lite mer.
Kontrollera att alla textfält är ifyllda Input-taggarna för textfälten har olika namn, så vi kan inte komma åt dem som en grupp på samma sätt
som menyn, radioknapparna och kryssknapparna. Men vi kan omge dem med ett div-element och via
det komma åt input-taggarna och på så sätt referera till dem som en array.
•
Lägg till div-taggar, som omger textfälten i HTML-koden:
...
<div id="customerdata">
<p><label>Ankomstdatum:<br><input type="date" name="arrivaldate"></label></p>
<p><label>Namn:<br><input type="text" name="name"></label></p>
<p><label>Gatuadress:<br><input type="text" name="street"></label></p>
<p><label>Postnummer:<br><input type="text" name="zipcode"></label></p>
<p><label>Ort:<br><input type="text" name="town"></label></p>
</div>
...
•
Högst upp i script-filen lägger du till en global variabel:
var customerTags;
•
I init-funktionen lägger du till en initiering av variabeln:
function init() {
...
customerTags =
document.getElementById("customerdata").getElementsByTagName("input");
...
}
o
Referensen görs först till div-taggen med id="customerdata". Där refereras det sedan till
alla input-taggar. Variabeln customerTags blir därmed en array med referenser till
textfälten.
2012-11-19 – Rune Körnefors ([email protected])
4
Medieteknik
Kontrollera nu om textfälten är tomma.
•
Lägg till följande kod i funktionen checkForm:
function checkForm() {
...
for (i=0; i<customerTags.length; i++) {
if (customerTags[i].value == "") {
alert("Alla textfält måste vara ifyllda");
return false;
}
}
return true;
}
Om ett textfält är tomt (jämförs med en tom textsträng, två citationstecken, utan något
mellan dem), ges ett felmeddelande och funktionen avbryts med return false. Det
returneras då false till onsubmit i form-taggen och formuläret skickas ej.
Testa i webbläsaren.
o Om något textfält är tomt, får du felmeddelandet. Om alla textfält är ifyllda, skickas
formuläret (i HTML-koden finns det inget i action-attributet i form-taggen, så det skickas
ingenstans, men du ser att formuläret töms).
o
•
4. Konvertera namn
Du ska nu konvertera kundens namn, så att varje del i namnet skrivs med inledande versal och resten
med gemener. Vi gör detta i två steg.
Dela upp namnet med blanktecken som skiljetecken •
Konverteringen görs i en separat funktion, så skriv in följande funktion i script-filen:
function initialUpperCase(word) {
word = word.charAt(0).toUpperCase() +
word.substring(1).toLowerCase();
return word;
}
Ordet som ska konverteras kommer in i parametern word.
Det första tecknet tas ut med charAt(0) och det konverteras till en versal med
toUpperCase().
o Tecknen från position 1 (dvs det andra tecknet) och resten av strängen tas ut med
substring(1). Denna sträng konverteras till gemener med toLowerCase().
Skriv sedan in följande kod i funktionen checkForm under den loop där dubbla blanktecken tas
bort:
o
o
•
function checkForm() {
var name, town, zipcode, dblSpacePos, i, nameArr, nameArr2;
...
nameArr = name.split(" ");
for (i=0; i<nameArr.length; i++) {
nameArr[i] = initialUpperCase(nameArr[i]);
}
name = nameArr.join(" ");
formTag.name.value = name;
...
}
o
Inför två nya lokala variabler. Variabeln nameArr används här och namArr2 kommer att
användas i nästa steg.
2012-11-19 – Rune Körnefors ([email protected])
5
Medieteknik
Kundens namn finns redan i variabeln name. Detta delas upp i en array, så att varje del
som åtskiljs av blanktecken blir varsitt element i arrayen.
o Denna array genomlöps i en loop. För varje del av namnet anropas initialUpperCase, för
att konvertera till inledande versal.
o Efter loopen sätts arrayen samman till en sträng igen och som skiljetecken används ett
blanktecken.
Testa i webbläsaren.
o Lämna fältet med postnummer tomt, så skickas inte formuläret iväg. Då blir innehållet
kvar i formuläret och du kan se om konverteringen av namnet fungerar.
o
•
Dubbelnamn med bindestreck Namnen kan ju också vara uppdelade med bindestreck, t.ex. Karl-Oskar. Med ovanstående kod blir det
Karl-oskar. Så nu ska vi se till att även namnet efter bindestrecket får inledande versal.
•
Lägg till en if-sats i loopen, så att for-loopen blir:
function checkForm() {
...
for (i=0; i<nameArr.length; i++) {
if (nameArr[i].indexOf("-") != -1) {
nameArr2 = nameArr[i].split("-");
nameArr[i] = initialUpperCase(nameArr2[0]) + "-" +
initialUpperCase(nameArr2[1]);
}
else nameArr[i] = initialUpperCase(nameArr[i]);
}
...
}
I if-satsen kontrolleras det om det finns ett bindestreck i namnet. Detta görs med indexOf.
Om bindestreck finns ger indexOf positionen för tecknet, annars -1. Vi är inte intresserade
av vilken position det är, så vi kontrollerar bara om det är skilt från -1. Då finns det alltså
ett bindestreck.
o Namnet i nameArr[i] delas då upp i en array med bindestreck som skiljetecken. Denna
array sparas i nameArr2.
o De båda delarna i nameArr2 (dvs delarna indexerade med 0 och 1) konverteras var för sig
och sätts samman med ett bindestreck till en ny sträng i nameArr[i].
o Om det inte finns något bindestreck, så går vi in i else-delen och utför konverteringen så
som tidigare.
Testa i webbläsaren.
o
•
Slut
I dessa övningar tog vi upp:






Referens till element i formulär med hjälp av namnen i name-attributen.
Referens till option-taggar i en meny.
Referens till radioknappar.
Referens till kryssknappar.
Referens till flera input-taggar med hjälp av getElementsByTagName.
Stränghantering med funktionerna:
o charAt()
o substring()
o toLowerCase()
o toUpperCase()
o indexOf()
2012-11-19 – Rune Körnefors ([email protected])
6