Javascript Programmieren – Der Anfang

Heute möchte ich eine kleine Einführung in Javascript starten, denn ohne Javascript kommt keine halbwegs moderne Webseite mehr aus. Dabei gibt es Sitten und jede Menge Unsitten, die vorkommen können. Ohne lange in Einzelheiten zur Historie von Javascript, den vielen Browser Inkompatibilitäten oder dem Funktionsumfang von Javascript zu verbringen, starten wir heute mit einem Crashkurs.

Javascript muß man nicht extra nachinstallieren, denn es ist bereits in jedem Browser enthalten. Es kann auf zwei Wegen in den Code der Webseite eingebaut werden:

a) ausgelagert in eine externe Datei:

<script type="text/Javascript" src="/equery.js"></script>

oder b) direkt im Programmcode:

<script type="text/Javascript">
     document.writeln("Hallo Welt");
</script>

Da Javascript eigentlich für die Verarbeitung von Events gedacht ist, die z.b. beim Klicken auf ein Button erzeugt werden, kann man Javascriptanweisungen auch direkt in einzelne Elemente in deren Eventhandler einbauen:

onclick="foo()" class=button>Hier drücken

Randnotiz: Auch wenn Javascript sehr nützlich ist, kann es auch diverse Nachteile mit sich bringen. Es läßt sich i.d.R. nur sehr schwer abschalten, weswegen ich nur zum Einsatz von NOSCRIPT raten kann. Damit kann man Scripte sehr gezielt abschalten bzw. überhaupt erst erlauben. Viele Social Web Seiten tracken zudem über deren Javascriptcode Besucher anderer Webseiten, egal ob man auf die Like/Sharebuttons drückt oder nicht. Diesen Seiten kann man nur entkommen, indem man einfach nicht alles ausführt was auf einer Webseite eingebunden ist.

In dieser Einführung geht es nicht um „Wie schreibe ich Javascriptprogramme“, sondern, wie schreibe ich das „heute“. Damit meine ich natürlich den Einsatz von Frameworks. Das wohl bekannteste ist JQuery (JQ) , aber auch darum wird es heute nicht gehen, denn JQuery macht einige Sachen durchaus anders, als Sie gehandhabt werden könnten. Oder einfacher ausgedrückt, EQuery (EQ) ist um einiges einfacher gebaut und schneller.

Vorweg seit gesagt, daß man alles was gleich folgen wird, auch in Plain Javascript ( JS ) schreiben kann. Frameworks nehmen einem einfach viel Arbeit ab und korrigieren i.d.R. die kleinen Unterschiede zwischen den Browsern, so daß der eingesetzte Code nicht selbst an den IE/Opera usw. angepaßt werden muß. Das W3C gibt in seinen Spezifikationen eigentlich vor, wie etwas im Web funktionieren sollte, bis hin zu konkreten Beispielen. Leider schaffen es die großen Hersteller trotzdem daran vorbei zu implementieren.

Wie bindet man so einen Framework ein ?

Oben wurde ja schon gezeigt, wie man JS mit einer externen Datei in die Seite einbindet, ein Framework ist auch nur Javascript. Üblicherweise fügt man das in den Head einer Seite ein :

<script type=“text/Javascriptsrc=“/equery.js“></script>

In diesem Beispiel liegt die EQuery Datei direkt in dem Verzeichnis im dem auch die Webseite aufgerufen wird.Man kann als Quelle aber natürlich auch eine komplette URL angeben:

<script type="text/Javascript" src="http://meinequery.com/equery.js"></script>

Damit Javascript nach dem Laden der Webseite gestartet werden kann, muß man den OnLoad() Event-Handler des aktuellen Fenster überschreiben. JQ Programme arbeiten auch gerne mit dem OnReady()-Handler, der hat aber den Nachteil, daß nicht sichergestellt ist, daß da nicht doch noch was fehlt. OnLoad dagegen meint wirklich, wenn die Seite komplett da ist und alles was statisch geladen werden sollte, auch wirklich bereit ist. Der Unterschied kann für Ihr Programm einmal sehr wichtig werden.

Alle unsere Beispiele werden im OnLoad- Handler mit Hilfe einer anonymen Funktion durchgeführt:

window.onload = function() {
     alert("Hallo Welt!");
}

eine anonyme Funktion hat keinen Namen und kann daher auch nur einmal referenziert werden, ohne Namen kann man sie ja schlecht aufrufen.

Wenn man das obige Beispiel mit einer „normalen“ Funktion machen will, könnte das so aussehen :

function foo() {
     alert("Hallo Welt!");
}
window.onload = foo;

Bei ohnehin nur einmal verwendeten Funktionen sind anonyme Funktionen schon wegen der besseren Lesbarkeit vorzuziehen. Beachten Sie bitte, daß der Handler einen „Zeiger“ auf die Funktion haben möchte, weswegen im Beispiel oben die Klammern ()  im Funktionaufruf fehlen. Würde man das so schreiben:

window.onload = foo();

würde der onLoad-Handler das Ergebnis der Funktion Foo bekommen, was in der Regel wohl vollkommener Murks sein dürfte. Natürlich kann man eine Funktion schreiben, die eine Funktion als Rückgabewert hat, aber das dürfte eher in den Bereich der Theorie fallen.

Selektoren

Frameworks lösen für den Benutzer das Problem, selbst nach Elementen suchen zu müssen, was die Lesbarkeit des Codes erhöht, aber die Verarbeitungsschwindigkeit erheblich reduziert. Besonders bei Seiten mit vielen Elementen sind solche Selectionen ein echtes Performanceproblem.

Für unsere Beispiele beziehen wir uns auf diesen Webseitencode:

id="outer" class="outerdiv">

Der einfachste Selektor im EQ ist die Suche nach einem einzelnen Element :

$(„!outer“) liefert direkt nur ein Element zurück, welches die ID „outer“ hat. Das ist sehr schnell, da kaum Overhead beim Suchen benutzt wird. In JQ wäre das $(„#outer“) .

Der normale Selector $(„outer“) findet unser Element auch, braucht dazu aber deutlich länger. Allerdings hat dies den Vorteil, daß auch mögliche andere Elemente gefunden werden, denn $(„!…“) liefert nur genau ein Element zurück, i.d.R. das Erste im DOM. Damit entspricht es der im Browser eingebauten Funktion „document.getElementById()“.

Wenn in einer Webseite mehrere Elemente sind, die übrigens gegen die W3C Vorgaben verstoßen würden, aber ggf. nicht vermieden werden können, z.b. weil Seiteninhalte mehrfach geladen werden müssen, würden diese nicht gefunden. Mit $(„name“) bekommen man alle Elemente geliefert. JQ und der JS Standart geben hier vor, daß bei der mehrfach Findung von Elementen, nur das Erste zurück gegeben wird. Mit $(„!…“) wäre das auch im EQ der Fall.

Folgende Selectoren gibt es:

$(„!…“)    Direktsuche nach Element.id

$(„#…“)   filtert nach Klassennamen

$(„…“)     filtert nach „Element.id“

$(„…#“)   filtert nach „Element.id endet mit …“

$(„§…“)    filtert nach „Element.type“

$(„TAG“) bspw. $(„BODY“) , filtert nach TAG Typen

Im EQ gilt, daß wenn mehrere Elemente gefunden werden, stehts ein Array zurück geben wird.

id="outer1" class="outerdiv">

Beispiel:

$("#outerdiv").each(function(elem) {
       elem.HTML("Neuer Inhalt");
});

Alternative:

$("outer#").each(function(elem) {
       elem.HTML("Neuer Inhalt");
});

Ergebnis:

id="outer1" class="outerdiv">Neuer Inhalt
Neuer Inhalt
Neuer Inhalt

Wenn man das jetzt nur auf eine Id beschränkten will, sieht das so aus.

Beispiel:

$("outer1").HTML("Neuer Inhalt");

Ergebnis:

id="outer1" class="outerdiv">Neuer Inhalt

In dem Fall kann man auch alternativ anwenden:   $(„!outer1“).HTML(„Neuer Inhalt“);

Natürlich gibt es eine ganze Fülle an Funktionen :

Für Elemente:

Element.setClass(Classname) : Setzt diese Klasse(n) .
Element.addClass(str) : fügt die Klasse str in den Klassennamen des Elements hinzu.
Element.delClass(str) : entfernt die Klasse str aus den Klassennamen des Elements.
Element.HTML(str) : Setzt den „Inhalt“ eines Elements
Element.addHTML(str) : fügt dem „Inhalt“ eines Elements mehr HTML Code hinzu.
Element.toURI() : wandelt das Element in ein URI Argument um.
Element.loadURL(url, passData) : Ruft per Ajax die URL auf und schickt als Payload passData mit.
Element.getHTML() :  gibt den HTML Code eines Elements zurück,
Checkbox / Textarea usw. geben immer das Value zurück, bei der Selextbox wird
der Auswahltext zurück
Element.getValue() : gibt das Value eines Elements zurück, z.b. ob eine Checkbox gecheckt ist,
oder das ausgewählte Element einer Selectbox, bzw. den Inhalt eines Tags ( innerHTML )
Element.addSubElement(Type, Name, Id, CSS, Html) : Fügt diesem Element ein neues ChildElement hinzu.
Element.attr(name,value) : Setzt das Attribute name auf den Wert value
Element.contextmenu( func ) : setzt für das Element das ContextMenü auf die angebene Funktion
Element.addEvent( eventname, func ) : setzt für den Event die Callbackfunktion func
Element.each( func(elem) ) : Diese Funktion ist als Fallback für den Fall gedacht, daß bei einem Selector
ein Array erwartet wird, aber nur ein Element kommt.

Für Strings:

String.trim() : entfernt Leerzeichen vom Anfang und Ende des Strings : x = x.trim();
String.startsWith(str) : gibt zurück, ob der String str in dem String anfängt: if ( x.contains(„y“) ) …
String.endsWith(str) : gibt zurück, ob der String str in dem String endet: if ( x.endsWith(„y“) ) …
String.contains(str)  : gibt zurück, ob der String str in dem String enthalten ist: if ( x.contains(„y“) ) …
String.executeScripts() : führt Scripte aus, die in diesem String enthalten sind: x.loadURL(url).executeScripts();

Für Arrays:

Hinweis: Die meisten Funktionen sind analog zu den Elementfunktionen aufgebaut, wobei diese auf alle Elemente eines Arrays angewendet wird. Die meisten Funktionen geben auch den Array zurück, so daß Anweisungen gechaint werden können. Beispiel:  elements.delClass(„old“).addClass(„new);

Array.contextmenu( func )
Array.HTML(str)
Array.addHTML(str)
Array.setClass(str)
Array.addClass(str)
Array.delClass(str)
Array.getValue(str)
Array.onclick(func)
Array.toURI() : Baut abweichend von der Elementfunktion einen ganzen Querystring zusammen.
Array.loadURL(url)
Array.attr(name,value)
Array.getAttribute(name): Gibt einen Array aller gesuchten Element-Attributen zurück.
Array.each( func(elem) ) : Übergibt einer Funktion func, jeweils einzeln alle Elemente des Arrays.
Array.size() :  gibt die Anzahl der Elemente des Arrays zurück.

Object.each( func( object,name ) ) : Übergibt einer Funktion func, jeweils einzeln alle Elemente des Objekts und des Keyname.
Object.size() :  gibt die Anzahl der Keys des Objects zurück.

Hier mal ein Beispiel:

window.onload = function() {

 var test = document.createElement("div")
 test.loadURL("cmd/status","");
 $("abmelden").style.display = "none";
if ( test.getValue().trim() == "FIRSTLOGIN" ) {
     $("anzeige").loadURL("register.html","");
     $("loginbutton").onclick = register;
     $("user").onfocus = function() { focusme( this ,"Benutzername"); };
     $("user").onblur = function() { blurme( this ,"Benutzername"); };
     $("pass").onkeyup = function(event) { if ( TastewarReturn(event) ) { register() } };
} else if ( test.getValue().trim() == "OK" ) {
     $("abmelden").style.display = "inline-block";
     $("anmelden").style.display = "none";
     auflisten();
} else {
     anmelden();
}
$("anmelden").onclick = function(){
     anmelden();
}

Ohne ins Detail zu gehen, kann man hier schon die Grundfunktion ablesen. Da es immer HTML Elemente oder Arrays sind, kann man auch immer die üblichen Attribute und Funktionen von HTML Elementen benutzen, wie z.b.  .style.display = „none“; oder $(„anmelden“).onclick = function(){ … };

Für heute, solls es erstmal genug sein.

Tomcat: Manager App nicht verfügbar

Kleine Ursache, großes Tralala

Einer meiner Tomcats hat mich heute mit der Meldung beglückt, daß er die Resource „/manager/html“ nicht zur Verfügung stellen könne, obwohl die Anwendung installiert ist. Das ist ist immer, da diese zum Defaultzustand eines Tomcats dazugehört. Darüber lassen sich Webanwendungen als WAR File installieren.

Jetzt findet man im Netz alle erdenklichen Ansätze, leider half heute nicht einer.

Das erste was auffiel war, daß das Manager Verzeichnis zwar da war, aber die anderen normalen Verzeichnisse im webapps Verzeichnis  nicht:

drwxr-xr-x  5 root root     4096 13. Aug 2013  host-manager
drwxr-xr-x  5 root root     4096 13. Aug 2013  manager
drwxr-xr-x  3 root root     4096 18. Feb 2012  plattform
drwxr-xr-x  3 root root     4096 13. Aug 2013  ROOT

Wenn das nicht der Fall ist, kann es gehen, muß aber nicht. Diese holt man sich aus dem Tomcat ZIP/TGZ File. Wenn man dies nicht mehr zur Hand hat, einfach nochmal von der Webseite runterladen.

Die eigentliche Störungsquelle

Damit habe ich dann nicht gerechnet. Die eigentliche Störungsquelle war trivialer Natur. Die früher installierte Webanwendung war defekt und verhinderte den korrekten Start des Tomcats, obwohl im Logfile dazu kein Hinweis stand! Mit sowas rechnet man nicht, daß bis dato die Webanwendung lief.

In dem Fall einfach von Hand die alte WAR Datei aus dem Webapps Verzeichnis entfernen und den Tomcat neustarten.

Danach war auch der Manager wieder erreichbar.

 

 

 

 

 

 

Eclipse in Fedora auf Englisch umstellen

Fachbegriffe  ins Deutsche zu übersetzen kann für Experten zur Qual werden, wenn man vertraute Begriffe nicht wieder findet. So geschehen in der IDE Eclipse der Eclipse Foundation . Unter Windows war die Sprache Englisch, unter Linux installierte sich gleich mal die deutsche Übersetzung mit hinzu, sehr zum Nachteil der Useability. Google war auch nicht besonders hilfreich, da es ständig nur Seiten gefunden hat, die genau das Gegenteil von dem wollten, was ich will, nämlich Deutsch loswerden. Aber manchmal ist es viel einfacher als man denkt und ich  präsentiere den Ausweg aus dem Dilemma:

yum remove eclipse-nls-de

Einfach das deutsche Sprachpaket entfernen ( wenn man weiß, das es das ist ) .

Natürlich kann man das auch über den Paketmanager der Oberfläche machen, dann dauert es aber etwas länger..