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
© Copyright 2024