Rheinwerk Computing <openbook>
Rheinwerk Computing - Programming the Net


JavaScript von Christian Wenz
Browserübergreifende Lösungen
JavaScript - Zum Katalog
gp Kapitel 24 Lösungen

Kapitel 24 Lösungen

Prüfungen sind deshalb so scheußlich, weil der größte Trottel mehr fragen kann, als der klügste Mensch zu beantworten vermag.
– Charles Caleb Colson

In diesem Kapitel finden Sie die Lösungen zu den Aufgaben der vorhergehenden Kapitel. Aus Platzgründen sind die Lösungen sehr kurz gefasst und meistens ist nur der wichtige Code wiedergegeben. Die Lösungen zu den schwierigsten Aufgaben sind meistens recht lang. Aus diesem Grund finden Sie sie in MyGalileo.

Kapitel 3

1. Winnie-the-Pooh ist ungültig wegen der Minus-Zeichen, 1Winnie wegen der führenden Ziffer, Winnie Pooh wegen dem Leerzeichen. Die anderen Variablennamen sind gültig.
2. Mit dem Backslash kann man Anführungszeichen in JavaScript-Zeichenketten entwerten, aber nicht innerhalb von HTML-Tags. Für den HTML-Interpreter endet daher die Zeichenkette nach dem Backslash und nicht nach der schließenden Klammer.
3. Bei einer do-while-Schleife wird der Anweisungsblock auf jeden Fall mindestens einmal ausgeführt; bei einer while-Schleife nur dann, wenn die Bedingung am Anfang erfüllt ist.
4. while (Zeichenkette.indexOf(" ")>-1){ io = Zeichenkette.indexOf(" ") Zeichenkette = Zeichenkette.substring(0, io) + "%20" +
     Zeichenkette.substring(io+1, Zeichenkette.length) }

Kapitel 4

1. Es war freigestellt, welches der Beispiele umgeschrieben werden sollte; an dieser Stelle wird das Beispiel mit dem Array vorgeführt. Hierbei muss bedacht werden, dass auf den Dezember der Januar folgt, man benötigt also beispielsweise ein weiteres Formularelement.

var m = new MakeArray(13)
m[0] = "Unbekannter Monat"
m[1] = "Januar"
m[2] = "Februar"
m[3] = "März"
m[4] = "April"
m[5] = "Mai"
m[6] = "Juni"
m[7] = "Juli"
m[8] = "August"
m[9] = "September"
m[10] = "Oktober"
m[11] = "November"
m[12] = "Dezember"
m[13] = "Januar"
monat =  11
document.write("Der nächste Monat heißt: "+ m[monat+1])

2. Es bleibt nur noch die switch-Anweisung übrig:

switch (monat){
   case 12: var m = "Januar"; break
   case 1: var m = "Februar"; break
   case 2: var m = "März"; break
   case 3: var m = "April"; break
   case 4: var m = "Mai"; break
   case 5: var m = "Juni"; break
   case 6: var m = "Juli"; break
   case 7: var m = "August"; break
   case 8: var m = "September"; break
   case 9: var m = "Oktober"; break
   case 10: var m = "November"; break
   case 11: var m = "Dezember"; break
   default: var m = "Unbekannter Monat"
}
document.write(m)

3. Die folgende Funktion erfüllt alle Teile der Aufgabenstellung:

function istSchaltjahr(n){
   return (n%4==0&&(n%100!=0||n%400==0))
}

4. Idee: für alle Zahlen von 2 bis n-1 wird geprüft, ob sie einen Teiler der Zahl darstellen. Es gibt effizientere Algorithmen, diese darzustellen soll aber nicht Teil dieses Buches sein.

function istPrim(n){
   if (n=1)
      return false
   for (var i=2; i<n; i++)
      if (n%i==0)
         return false
   return true
}

5. Die entsprechenden Funktionen sind Methoden, da sie mit Klammern aufgerufen werden und Parameter haben.

function MakeArray(n,m){
  for (var i=0; i<n; i++)
     this [i] = (m==null)? 0:m
  this.length=n
}

Kapitel 5

1. Anhand des Werts, der von getTime() zurückgeliefert wird, kann die ungefähre Jahreszahl bestimmt werden (Wert ist die Anzahl der seit dem 1. Januar 1970 verstrichenen Millisekunden), indem der Wert durch 1 000 ¥ 60 ¥ 60 ¥ 24 ¥ 365.25 dividiert wird und das Ergebnis zu 1970 dazugezählt wird. Der Rest geht wie bekannt.
2. Man benötigt mehrere if-Abfragen, um Dubletten zu verhindern.

   var z1 = Math.floor(49*Math.random())+1
   var z2=z1
   while (z1==z2)
      z2 = Math.floor(49*Math.random())+1
   var z3=z1
   while (z1==z3||z2==z3)
      z3 = Math.floor(49*Math.random())+1
   var z4=z1
   while (z1==z4||z2==z4||z3==z4)
      z4 = Math.floor(49*Math.random())+1
   var z5=z1
   while (z1==z5||z2==z5||z3==z5||z4==z5)
      z5 = Math.floor(49*Math.random())+1
   var z6=z1
   while (z1==z6||z2==z6||z3==z6||z4==z6||z5==z6)
      z6 = Math.floor(49*Math.random())+1
   var zusatz=z1
   while(z1==zusatz||z2==zusatz||z3==zusatz||z4==zusatz||
     z5==zusatz||z6==zusatz)
      zusatz = Math.floor(49*Math.random())+1

3. Anstelle der document.write()-Anweisungen muss man location.href=zufallsurl verwenden, das war aber auch schon alles.
4. Nach der Bestimmung von Browserhersteller und Versionsnummer benötigt man lediglich noch folgende Zeilen:

browserurl = (netscapebrowser) ? "nn" : "ie"
location.href = browserurl + versionsnummer + ".html"

Kapitel 6

1. Es gibt mit JavaScript alert()-Fenster, confirm()-Fenster und prompt()-Fenster. Man verwendet alert() zur Ausgabe von Hinweistexten, während confirm() dem Benutzer eine Ja/Nein-Abfrage präsentiert. Bei prompt() kann der Benutzer einen Text eingeben.
2. Mit window.back() navigiert man durch die globale History des Fenster, während window.history.back() auf die lokale History des einzelnen Frames beschränkt ist.
3. Bei history.go(0) bleiben Formulareingaben erhalten (weiches Neuladen), bei location.reload() nicht (hartes Neuladen).
4. Die drei Möglichkeiten sind:
JavaScript-Neuladen innerhalb des Werbeframes:

setTimeout("location.reload()", 120000)

Rekursives JavaScript-Neuladen von einem anderen Frame aus:

function neuladen(){
   top.werbeframe.location.reload()
   setTimeout("neuladen()", 120000)
}
neuladen()

Die dritte Möglichkeit besteht aus purem HTML:

<META HTTP-EQUIV="REFRESH" CONTENT="120">

Kapitel 7

1. Diese Aufgabe läßt sich in Anlehnung an Kapitel 6 lösen:

<HTML>
<HEAD>
<TITLE>Laufschrift</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var lauftext = " +++ Read my lips: no tax on beer "
function laufschrift(){
   document.forms[0].lauf.value = lauftext
   lauftext = lauftext.substring(1, lauftext.length) +
     lauftext.substring(0,1)
   setTimeout("laufschrift()", 100)  //Weiter nach einer Zehntelsekunde
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="laufschrift()">
<H3>Laufschrift mit JavaScript</H3>
<FORM>
<INPUT TYPE="TEXT" NAME="lauf" onFocus="this.blur()">
</FORM>
</BODY>
</HTML>

2. Zur Strategie: Als Zeichensatz sollte eine nichtproportionale Schrift eingestellt werden, und Sie müssen mitzählen, welches Zeichen sich gerade links im Texteingabefeld befindet, um festzustellen, welche News gerade angezeigt wird. Hier nun der entsprechende Code:

<HTML>
<HEAD>
<TITLE>Laufschrift</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var trenn = "  +++  "  //Trennzeichen im Ticker
var position = 0       //globale Variable, zählt die Position

var meldungen = new Array()
meldungen[0] = "Netscape Navigator – einer der ersten Browser"
meldungen[1] = "Internet Explorer – der momentane Marktführer"
meldungen[2] = "Opera – Der Geheimtipp aus dem fernen Norwegen"

var urls = new Array()
urls[0] = "http://home.netscape.com/download"
urls[1] = "http://www.microsoft.com/windows/ie_intl/de/
  download/default.htm"
urls[2] = "http://www.opera.com"

var lauftext = ""
for (var i=0; i<meldungen.length; i++)
  lauftext += meldungen[i] + trenn

function laufschrift(){
  document.forms[0].lauf.value = lauftext
  lauftext = lauftext.substring(1, lauftext.length) + lauftext.substring(0, 1)
  position = (position < lauftext.length-1) ? position + 1 : 0
  setTimeout("laufschrift()", 100)
}

function go(){
  var laenge = 0
  for (var i=0; i<meldungen.length; i++){
    laenge += meldungen[i].length + trenn.length
    if (laenge>position){
      location.href = urls[i]
      return true
    }
  }
}

//--></SCRIPT>
<STYLE><!--
  INPUT {font-family: Courier;}
--></STYLE>
<BODY onLoad="laufschrift()">
<H3>Laufschrift mit JavaScript</H3>
<FORM>
<FONT FACE="Courier New,Courier">
<INPUT TYPE="TEXT" NAME="lauf" onFocus="go()" SIZE="30">
</FONT>
</FORM>
</BODY>
</HTML>

3. Der Fehler liegt in dieser Zeile:

eval("var radiogroup = f."+i.name)

Erinnern Sie sich daran, dass Sie bei f.elements[] nicht unbedingt einen numerischen Index verwenden müssen, sondern auch das name-Attribut des gewünschten Formularelements übergeben können. Das folgende Kommando macht das Skript wirklich universell:

var radiogroup = f.elements[i.name]

4. Sie müssen sich eine Namenskonvention für Pflichtfelder einfallen lassen, beispielsweise »NAME-Attribut beginnt mit p_«. Das können Sie dann in der for-in-Schleife ungefähr so überprüfen:

if (i.value==""&&i.name.indexOf("p_")==0)
   ...

5.
 <HTML> <HEAD> <TITLE>Navigation mit JavaScript</TITLE>
<SCRIPT LANGUAGE="JavaScript">

<!-- function laden(f){ if (f.auswahl.selectedIndex>0)
 location.href = f.auswahl.options[f.auswahl.
         selectedIndex].value } //-->
 </SCRIPT> </HEAD> 
<BODY> <H3>Navigation mit JavaScript</H3> 
<FORM> <SELECT NAME="auswahl" onChange="laden(this.form)">
<OPTION>Bitte wählen</OPTION> 
<OPTION VALUE="http://www.compaq.de">Compaq</OPTION> 
<OPTION VALUE="http://www.dell.de">Dell</OPTION> 
<OPTION VALUE="http://www.hewlett-packard.de">HP</OPTION> 
</SELECT> 
<INPUT TYPE="BUTTON" VALUE="Laden"
 onClick="laden(this.form)"> 
 </FORM> </BODY> </HTML>

Kapitel 8

1. Von C nach H: parent.parent.parent.frames[1].frames[1].frames[1]
Von H nach C: parent.parent.parent.frames[0].frames[2].frames[0] Von A nach I: parent.parent.frames[2] Von I nach A: parent.frames[0].frames[0] Sie dürfen top nicht verwenden, da die Seite laut Aufgabenstellung ja selbst auch in einem Unterframe aufgerufen werden kann.
2. Sie müssen die Funktion rekursiv wieder aufrufen:

function subframes(frameref){
   if (frameref.frames.length==0)
      return 1
   else{
      var summe = 0
      for (var i=0; i<frameref.frames.length; i++)
         summe += subframes(frameref.frames[i])
      return summe
   }
}

3. Die Lösung zu dieser Aufgabe finden Sie (aufgrund der Länge und der Verteilung auf mehrere Dateien) in MyGalileo.

Kapitel 9

1. Sie benötigen zwei Grafiken, eine leer Füllgrafik leer.gif und eine sichtbare Grafik nichtleer.gif.

<HTML><HEAD><TITLE>Hier gehts zum Chat</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function omo(num){
   if (document.images) {
      if (num==0) {
         document.images[0].src="leer.gif"
         document.images[1].src="nichtleer.gif"}
   else {
      document.images[1].src="leer.gif"
      document.images[0].src="nichtleer.gif"}
   }
}
//--></SCRIPT>
</HEAD>
<BODY>
<A HREF="#" onMouseover="omo(0)"><IMG SRC="nichtleer.gif"
  BORDER=0></A>
<HR>
<A HREF="#" onMouseover="omo(1)"><IMG SRC="leer.gif"
  BORDER=0></A>
</BODY></HTML>

2. Sie müssen hierzu mit Timeouts arbeiten. Jede Sekunde muss sich die Grafik bewegen, außer, der Benutzer fährt mit der Maus darüber. Dann muss der Timeout gelöscht werden und ein neuer gestartet werden. Das komplette Skript finden Sie in MyGalileo.
3. Der einzige Unterschied im HTML-Code liegt darin, dass die aktuelle Unterkategorie durch die fette Grafik dargestellt wird. Dies kann mit JavaScript erledigt werden, indem der onLoad-Event-Handler jedes <BODY>-Tags auf init() gesetzt wird. Diese Funktion sieht dann folgendermaßen aus:

function init(){
   for (var i=1;i<=urls.length;i++)
      klapp_zu(i)
   var img = eval("document.menu_"+kategorie+"_"+menuepunkt)
   img.src="menu_"+kategorie+"_"+menuepunkt+"_f.gif"
}

4. Der Trick besteht hier darin, die Funktion fertig() mit Timeouts peridodisch, etwa einmal pro Sekunde, aufzurufen.

Kapitel 10

1. Das geht analog zur Standard-Fernsteuerung. Die Links haben dann alle das Format <A HREF="#Marke" TARGET="Ziel">...</A>
2. Die Koordinaten der linken oberen Ecke berechnen sich nach folgender Formel:

x = (Bildschirmbreite – Browserbreite) / 2
y = (Bildschirmhöhe – Browserhöhe) / 2

Damit läßt sich die Funktion einfach schreiben:

function center(){
   var x = (screen.availWidth – window.outerWidth) / 2
   var y = (screen.availHeight – window.outerHeight)
   window.moveTo(x, y)
}

3. Ganz einfach: Man scrollt sehr weit nach unten; der Browser scrollt dann soweit wie nur möglich:

window.scrollBy(0, 10000)

4. Wie im Kapitel gezeigt, gibt es keine Fensteroptionen, die das neue Fenster im Internet Explorer 4 in der linken oberen Ecke öffnen. Aber es gibt dennoch einen Ausweg: moveTo() gibt es in dieser Browserversion schon!

var w = window.open("", "w", "height=100,width=100")
w.moveTo(0,0)

Kapitel 11

1. Man unterscheidet zwischen temporären und permanenten Cookies; Definitionen im Kapitel.
2. Die bereits bekannten Funktionen getCookie() und setCookie() werden verwendet:

var anzahl = getCookie("Besuche")
if (anzahl=="")
   anzahl = 0
setCookie("Besuche", anzahl+1)

3. Nicht möglich, da Cookies nicht browserübergreifend gespeichert werden.
4. Man kann die Zeit messen, die zwischen dem Setzen des Cookies und der Ausführung des nächsten Befehls vergeht. Erhält der Benutzer beim Setzen von Cookies eine Warnmeldung, so wird der nächste JavaScript-Befehl erst dann ausgeführt, wenn der Benutzer die Warnmeldung bestätigt oder das Cookie abgelehnt hat. Die Unterscheidung zwischen Cookie akzeptieren/ablehnen geschieht wie gehabt:

vat t1 = new Date().getTime()
setCookie("test", "test")
var t2 = new Date().getTime()
var test = getCookie("test")
if (t2-t1>100)
   document.write("Warnmeldung<BR>")
else
   document.write("Keine Warnmeldung<BR>")
if (test=="test)
   document.write("Cookie akzeptiert")
else
   document.write("Cookie abgelehnt")

5. Die (recht lange) Lösung zu dieser Aufgabe finden Sie in MyGalileo.

Kapitel 12

1. Sie müssen <INPUT TYPE="SUBMIT" VALUE="Zum Download"> ersetzen durch <INPUT TYPE="BUTTON" VALUE="Zum Download" onClick="download()">. Die Funktion download() sieht dann folgendermaßen aus:

function download(){
   var ls = ""
   if (document.forms[0].sommer.checked)
      ls += "&sommer=on"
   if (document.forms[0].othello.checked)
      ls += "&othello=on"
   if (document.forms[0].venedig.checked)
      ls += "&venedig=on"
   if (ls.charAt(0)=="&")
      ls = ls.substring(1, ls.length)
   location.href="download.html?"+ls
}

2. Die Lösung gestaltet sich analog zu einer Übungsaufgabe aus Kapitel 7, »Formular I«, und wird deshalb hier nicht aufgeführt.
3. Unter anderem sind die folgenden Kriterien denkbar:
    gp  Genau ein Klammeraffe in der Zeichenkette
    gp  Mindestens ein Punkt nach dem Klammeraffen
    gp  Das dritt-, viert- oder fünftletzte Zeichen muss ein Punkt sein.
4. Vierbuchstabige Wörter: \w\w\w\w
    gp  Gerade, positive Zahlen: (\d)*[02468]
    gp  Jahreszahlen aus dem 20. Jahrhundert: 19\d\d
    gp  Email-Adressen (einfache Prüfung):
[a-zA-Z0-9_-~]*@[a-zA-Z0-9_-~]*\.[a-zA-Z0-9_-~]*
(Zeichenfolge-@-Zeichenfolge-.-Zeichenfolge)

function lohn(s){
   var zeit = /(\d\d):(\d\d)/
   if (zeit.test(s)){
      stunde = s.replace(zeit, "$1")
      minute = s.replace(zeit, "$2")
      return 8*stunde + minute*8/60
}

5. Dreibuchstabige Wörter werden durch den regulären Ausdruck \w\w\w dargestellt, und beim Aufruf von replace() muss das Dollerzeichen entwertet werden (also \$0). Der Rest läuft wie im Kapitel ab.
6. Der entsprechende reguläre Ausdruck lautet ganz einfach <[^<]*> – keine weitere öffnende spitze Klammer ist erlaubt.

Kapitel 13

1. function numsort(a, b){ return a-b }
2. Das Einfügen in den Konstruktor wird hier nicht vorgeführt, lediglich die Funktion selbst. Die Eigenschaft length muss um Eins verringert werden, und zur Sicherheit wird der Wert des letzten Elements gelöscht.

function arraypop(){
   this[this.length-1] = ""
   this.length--
}

3. function arrayswap(i, j){
var temp = this[j] this[j] = this[i] this[i] = temp }
4. function arraysplice(ab, anzahl){
for (var i=ab+anzahl, i<this.length; i++) this[i-anzahl] = this[i] this.length -= anzahl }
5. Beim Mischen kann die Funktion arraysplice() verwendet werden. Das komplette Listing finden Sie hier:

<HTML>
<HEAD>
<TITLE>Karten spielen mit JavaScript</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
//Funktionen des MakeArray-Objekts
function MakeArray(){
   for (var i=0; i<MakeArray.arguments.length; i++)
      this[i] = MakeArray.arguments[i]
   this.length = MakeArray.arguments.length
   this.toString = arraytoString
   this.push = arraypush
   this.sort = arraysort
   this.splice = arraysplice
}
//Methoden
function arraytoString(){
   var returnstring = ""
   for (var i=0; i<this.length-1; i++)
      returnstring += this[i] + ","
   returnstring += this[this.length-1]
   return returnstring
}
function arraypush(){
   for (var i=0; i<arraypush.arguments.length; i++)
      this[this.length+i] = arraypush.arguments[i]
   this.length += arraypush.arguments.length
}
function arraysort(){
   var sortiert = false //Überprüfung, ob sortiert
   while (!sortiert){
      sortiert = true
      for (var i=0; i<this.length-1; i++)
         if (groesser(this[i], this[i+1], arraysort.arguments[0])){
            sortiert = false
            hilfsvariable = this[i]
            this[i]=this[i+1]
            this[i+1] = hilfsvariable
         }
   }
}
function arraysplice(ab, anzahl){
   for (var i=ab+anzahl; i<this.length; i++)
      this[i-anzahl] = this[i]
   this.length -= anzahl
}
function groesser(a, b, arg){
   if (!arg)
      return (a>b)
   else{
      var erg = eval(arg + "(\"" + a + "\", \"" + b + "\")")
      return (erg>0)
   }
}
// *** Das eigentliche Programm ***
//Hilfsvariablen für die Kartenbezeichnungen
var kartenname = new MakeArray("Zwei", "Drei", "Vier", "Fünf",
  "Sechs", "Sieben", "Acht", "Neun", "Zehn", "Bube", "Dame",
  "König", "As")
var farben = new MakeArray("Herz", "Karo", "Pik", "Kreuz")
//Initialisierung des Kartenarrays
var cards = new MakeArray()
for (var i=0; i<13; i++)
   for (var j=0; j<4; j++){
      karte = kartenname[i]+" "+farben[j]
      cards.push(karte)
   }
//Karten mischen
var cards2 = new MakeArray()
while (cards.length>0){
   var zufall = Math.floor(Math.random()*cards.length)
   karte = cards[zufall]
   cards.splice(zufall, 1)
   cards2.push(karte)
}

//Karten auf vier Personen verteilen
var hand1 = new MakeArray()
var hand2 = new MakeArray()
var hand3 = new MakeArray()
var hand4 = new MakeArray()
for (i=0; i<=12; i++)
   hand1.push(cards2[i])
for (i=13; i<=25; i++)
   hand2.push(cards2[i])
for (i=26; i<=38; i++)
   hand3.push(cards2[i])
for (i=39; i<=51; i++)
   hand4.push(cards2[i])
//Karten sortieren
hand1.sort("cardsort")
hand2.sort("cardsort")
hand3.sort("cardsort")
hand4.sort("cardsort")

//Sortierfunktion
function cardsort(a, b){
   var wert_a = a.substring(0, a.indexOf(" "))
   var wert_b = b.substring(0, b.indexOf(" "))
   var index_a = -1; var index_b = -1
   for (var i=0; i<kartenname.length; i++){
      if (kartenname[i]==wert_a)
         index_a = i
      if (kartenname[i]==wert_b)
         index_b = i
   }
   if (index_a>index_b) return 1
   else if (index_a<index_b) return -1
   var farbe_a = a.substring(a.indexOf(" ")+1, a.length)
   var farbe_b = b.substring(b.indexOf(" ")+1, b.length)
   return (farbe_a>farbe_b) ? 1 : 0
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Karten spielen mit JavaScript</H3>
<SCRIPT LANGUAGE="JavaScript"><!--
function br() { return "<" + "BR" + ">" }
document.write("Hand 1: " + hand1.toString() + br())
document.write("Hand 2: " + hand2.toString() + br())
document.write("Hand 3: " + hand3.toString() + br())
document.write("Hand 4: " + hand4.toString() + br())
//--></SCRIPT>
</BODY>
</HTML>

Kapitel 15

1. Vereinfacht gesagt durchwandern Ereignisse beim Netscape Navigator die Objekthierarchie von oben nach unten, beim Internet Explorer von unten nach oben.
2. Laden Sie das folgende Dokument in Ihren Webbrowser und doppelklicken Sie in das Fenster.

<HTML>
<HEAD>
<TITLE>Neue Mausereignisse</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function mclick() { window.status += "[click]" }
function mup() { window.status += "[mouseup]" }
function mdown() { window.status += "[mousedown]" }
function init(){
   window.status = ''
   with (document){
      onclick = mclick
      onmouseup = mup
      onmousedown = mdown
   }
}
window.onload = init
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Neue Mausereignisse</H3>
</BODY>
</HTML>

3. Mit handleEvent() kann man ein Ereignis an ein anderes Objekt weiterleiten; routeEvent() sorgt dafür, dass ein mit captureEvents() angefangenes Ereignis dort ausgeführt wird, wofür es bestimmt war.
    gp  a.Der Event-Handler wird mit return false verlassen.
    gp  b.cancelBubble wird auf true gesetzt.
    gp  c.Man ist oben in der Objekthierarchie angekommen.
4. Die entsprechende JavaScript-Funktion finden Sie im Folgenden abgedruckt, der HTML-Teil wird ausgelassen.

function mclick(e){
   var ev = (window.Event) ? e : window.event
   var ziel = (window.Event) ? ev.target : ev.srcElement
   location.href = ziel.value
}
if (window.Event)
   document.captureEvents(Event.MOUSEUP)
document.onclick = mclick

5. Die Zeile

} else { //IE

muss geändert werden in

} else if (window.event){

Kapitel 16

1. Mittels parentLayer.parentLayer.document.
a. von rechts:

var layer_x
function init(){
   if (document.layers){
      layer_x = document.logo.left
      document.logo.left += 500
      //Animation starten
      animate()
   }
}
function animate(){
   if (document.logo.left<layer_x)
      document.logo.left = layer_x
   if (document.logo.left>layer_x){
      document.logo.left -= 3
      setTimeout("animate()", 50)
   }
}

b. von links oben:

var layer_x, layer_y
function init(){
   if (document.layers){
      layer_x = document.logo.left
      layer_y = document.logo.top
      document.logo.left -= 200
      document.logo.top -= 200
      //Animation starten
      animate()
   }
}
function animate(){
   if (document.logo.left>layer_x)
      document.logo.left = layer_x
   if (document.logo.left<layer_x){
      document.logo.left += 3
   if (document.logo.top>layer_y)
      document.logo.top = layer_y
   if (document.logo.top<layer_y){
      document.logo.top += 3
      setTimeout("animate()", 50)
   }
}

2. Sie stellen eine Überlappung des Textes fest. Dies läßt sich verhindern, wenn eine Hintergrundfarbe definiert wird Beispielsweise könnte man den Inhalt jedes Registers in eine Tabelle legen, die eine weiße Hintergrundfarbe hat.
3. Wenn Sie irgend etwas in Richtung window.close() versucht haben, haben Sie leider aufs falsche Pferd gesetzt. Dabei ist die Lösung gar nicht so schwer: Die visibility-Eigenschaft muss auf hidden gesetzt werden:

<A HREF="javascript:document.logo.visibility='hidden';"> ...

Kapitel 17

1. Da der <DIV>-Container kein eigenes Unterobjekt mit document-Eigenschaft ist, kann man ganz einfach mit dem Schlüsselwort document auf das Hauptdokument zugreifen.
2. a. von rechts:

function init(){
   if (document.all)
      document.all.logo.style.posLeft += 500
   //Animation starten
   animate()
}
function animate(){
   if (document.all.logo.style.posLeft<0)
      document.all.logo.style.posLeft = 0
   if (document.all.logo.style.posLeft>0){
      document.all.logo.style.posLeft -= 3
      setTimeout("animate()", 50)
   }
}

b. von links oben

function init(){
   if (document.all)
      document.all.logo.style.posLeft -= 200
      document.all.logo.style.posTop -= 200
   //Animation starten
   animate()
}
function animate(){
   if (document.all.logo.style.posLeft>0)
      document.all.logo.style.posLeft = 0
   if (document.all.logo.style.posLeft<0){
      document.all.logo.style.posLeft += 3
   if (document.all.logo.style.posTop>0)
      document.all.logo.style.posTop = 0
   if (document.all.logo.style.posTop<0){
      document.all.logo.style.posTop += 3
      setTimeout("animate()", 50)
   }
}

3. Siehe Lösung zu Aufgabe 16.5:

<A HREF="javascript:document.all.logo.style.visibility='hidden';"> ...

Kapitel 18

1. Da der <DIV>-Container kein eigenes Unterobjekt mit document-Eigenschaft ist, kann man ganz einfach mit dem Schlüsselwort document auf das Hauptdokument zugreifen.
2. a. von rechts:

function init(){
   if (document.getElementById)
      document.getElementById("logo").style.left = 
         parseInt(document.getElementById("logo").style.left)
           + 500
   //Animation starten
   animate()
}
function animate(){
   if (parseInt(document.getElementById("logo").style.left)<0)
      document.getElementById("logo").style.left = 0
   if (parseInt(document.getElementById("logo").style.left)){
      document.getElementById("logo").style.left -= 3
      setTimeout("animate()", 50)
   }
}

b. von links oben

function init(){
   if (document.getElementById)
      document.getElementById("logo").style.left =
         parseInt(document.getElementById("logo").style.left)
           – 200
      document.getElementById("logo").style.top =
         parseInt(document.getElementById("logo").style.top)
           – 200
   //Animation starten
   animate()
}
function animate(){
   if (parseInt(document.getElementById("logo").style.left)>0)
      document.getElementById("logo").style.left = 0
   if (parseInt(document.getElementById("logo").style.left)<0){
      document.getElementById("logo").style.left =
         parseInt(document.getElementById("logo").style.left) + 3
   if (parseInt(document.getElementById("logo").style.top)>0)
      document.getElementById("logo").style.top = 0
   if (parseInt(document.getElementById("logo").style.top)<0){
      document.getElementById("logo").style.top =
         parseInt(document.getElementById("logo").style.top) + 3
      setTimeout("animate()", 50)
   }
}

3. Siehe Lösung zu Aufgabe 16.5:

<A HREF="javascript:document.getElementById('logo').style.
  visibility = 'hidden';"> ...

Kapitel 19

1. Siehe Lösung zu Aufgabe 17.1 und 18.1 – das geht browserübergreifend mit document.
2. Zwei Funktionen, setzelinks() und setzeoben(), werden eingeführt. Der Rest des Codes geht analog zu den Aufgaben in den vorherigen drei Kapiteln und wird deswegen nicht mehr extra aufgeführt.

function setzelinks(n){
   if (document.all)
      document.all.logo.style.posLeft = n
   else if (document.layers)
      document.logo.left = n
   else if (document.getElementById)
      document.getElementById("logo").style.left = n
}
function setzeoben(n){
   if (document.all)
      document.all.logo.style.posTop = n
   else if (document.layers)
      document.logo.top = n
   else if (document.getElementById)
      document.getElementById("logo").style.top = n
}

3. Diese Lösung ist die Verbindung der Aufgaben 16.5, 17.3 und 18.3. Aus Übersichtlichkeitsgründen wird das Ausblenden des Werbebanners in eine Funktion ausgegliedert:

function bannerweg(){
   if (document.all)
      document.all.logo.style.visibility = 'hidden'
   else if (document.layers)
      document.logo.visibility = 'hidden'
   else if (document.getElementById)
      document.getElementById("logo").style.visibility = 'hidden'
}

Es muss nur noch der Link entsprechend angepaßt werden:

<A HREF="javascript:bannerweg()"> ...

Kapitel 20

1. Nein! Diese Verwechslung wird von Anfängern oft gemacht, aber spätestens nach Lektüre des Kapitels dürften einige Unterschiede klar sein.
2. Java ist plattformunabhängig. Kostspielige Portierungen auf andere Plattformen entfallen also.
3. Als public deklarierte Methoden können von überall aus aufgerufen werden, auch von JavaScript aus; bei private ist das nicht möglich. Wenn man nicht will, dass jede Eigenschaft der Methode direkt manipuliert wird, sollte man sie als private deklarieren und statt dessen eine public-Methode zum Ändern der Eigenschaft anbieten. Vor allem, wenn Methoden und Eigenschaften direkt zusammenhängen (vergleiche beispielsweise das MakeArray-Objekt), ist es sinnvoll, so genanntes Data Hiding zu betreiben.
4. Eine Methode besteht darin, ein neues Fenster mit dem Applet zu öffnen. Da der Name des Applets bekannt ist, können Sie mit document.write() HTML-Code mit dem Applet erzeugen. Sie haben dann Zugriff auf alle als public deklarierten Methoden des Applets.

appleturl = "http://www.ihrserver.de/applets/applet.class"
var f = window.open("", "appletwindow")
f.document.open()
f.document.write("<HTML><BODY><APPLET NAME='a' CODE='"
  + appleturl + "'></APPLET></BODY></HTML>")
f.document.close()
//Zugriff ab jetzt mit f.document.a.methode()

Kapitel 22

1. Als Parameter an mausklick() wird der anfängliche Index der Grafik übergeben. Wird aber beispielsweise die erste Grafik entfernt, so gibt es keine Grafik mit Index 3 mehr, ein Klick auf die am weitesten rechts stehende Grafik führt also zu einer Fehlermeldung.
2. Eine der (vielen) Möglichkeiten besteht darin, in einem Array den aktuellen Index in childNodes[] der aktuellen Grafik zu speichern. Nach jedem Löschen wird das Array angepaßt.
3. Auch hier kann man wieder ein Array verwenden, in welchem der aktuelle Status der entsprechenden Grafik gespeichert wird (noch nie angeklickt, einmal angeklickt).

Kapitel 23

1. Die Lösung zu dieser Aufgabe finden Sie online bei MyGalileo.
2. Die Nummer der Zeile, in der der Fehler aufgetreten ist, wird als dritter Parameter an die Fehlerbehandlungsfunktion übergeben. Sie können also explizit darauf prüfen, ob der Fehler in der einen bestimmten Zeile aufgetreten ist, und dann die Funktion mit return true verlassen.
3. Der Debugger hat vermutlich das Programm analysiert und festgestellt, dass eine neue Variable mit Namen summe in der Funktion definiert wird.
4. Es gibt auch sogenannte bedingte Breakpoints. Beispielsweise können Sie den Debugger instruieren, bei einem bestimmten Breakpoint nur anzuhalten, wenn eine Variable einen bestimmten Wert hat. Die Bedingung ist mit true vorbesetzt, und das ist immer erfüllt, deswegen führen Breakpoints normalerweise immer zur Unterbrechung des Programms, außer Sie ändern das eben um.
  

JavaScript

jQuery

Einstieg in JavaScript

Responsive Webdesign

Suchmaschi-
nen-Optimie-
rung




Copyright © Rheinwerk Verlag GmbH 2001 - 2002
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken und speichern. Ansonsten unterliegt das <openbook> denselben Bestimmungen wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.
Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung der Rheinwerk Verlag GmbH. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: >> Zum Feedback-Formular


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, fon: 0228.42150.0, fax 0228.42150.77, service@rheinwerk-verlag.de