JavaScript OOP für PHP-Entwickler

Für PHP-Entwickler ist es relativ schwer sich an die OOP von JavaScript zu gewöhnen. Das liegt daran, dass JavaScript-Klassen Prototype-basiert sind und die Klassen daher anders definiert werden als man es aus PHP, Java oder C# kennt. Um die Umstellung von PHP/Java/C# etwas leichter zu gestalten, habe ich mal ein JavaScript-PHP-Equivalent von zwei einfachen Klassen geschrieben, die exakt das gleiche tun.

Normale Klasse

Fangen wir mal an mit einer einfachen Person-Klasse, die nur einen Namen und die Anrede kennt und die Person ansprechen bzw. verabschieden kann.

Die Klasse in PHP:

<?php
class Person
{
	protected $name;
	protected $gender;
 
	public function __construct($name, $gender)
	{
		$this->name = $name;
		$this->gender = $gender;
		$this->sayHello();
	}
 
	public function sayHello()
	{
		echo "Hallo $this->gender $this->name.";
	}
 
	public function sayGoodbye()
	{
		echo "Bis bald $this->gender $this->name.";
	}
}

Und die gleiche Klasse in JavaScript:

View Code JAVASCRIPT
function Person(name, gender) {
	if(name && gender)
	{
		this.name = name;
		this.gender = gender;
		this.sayHello();
	}
}
 
Person.prototype.sayHello = function() {
	document.write("Hallo "+this.gender+" "+this.name+".");
};
 
Person.prototype.sayGoodbye = function() {
	document.write("Bis bald "+this.gender+" "+this.name+".");
};

Vererbung

Als nächstes eine einfache Vererbung. Es gibt eine zweite Klasse „Scientist“, die alle Eigenschaften und Methoden von Person erbt und sie um jeweils eine Eigenschaft und eine Methode erweitert.

Vererbung in PHP:

<?php
require_once 'Person.php';
 
class Scientist extends Person
{
	protected $department;
 
	public function __construct($name, $gender, $department)
	{
		$this->department = $department;
		parent::__construct($name, $gender);
	}
 
	public function research()
	{
		echo "$this->name forscht $this->department.";
	}
}

Und die gleiche Vererbung in JavaScript:

View Code JAVASCRIPT
function Scientist(name, gender, department) {
	Person.call(this, name, gender);
	this.department = department;
}
 
Scientist.prototype = new Person();
Scientist.prototype.constructor = Scientist;
Scientist.prototype.research = function() {
	document.write(this.name+" forscht "+this.department+".");
};

Aufruf der Klassen

Kommen wir nun zum leichtesten Teil – dem Aufruf bzw. Verwendung der Klassen. Hier unterscheiden sich JavaScript und PHP fast gar nicht.

PHP:

$einstein = new Person("Albert Einstein", "Herr");
echo "<br/>";
$einstein->sayGoodbye();
echo "<br/><br/>";
 
$newton = new Scientist("Isaac Newton", "Herr", "Physik");
echo "<br/>";
$newton->research();
echo "<br/>";
$newton->sayGoodbye();

Und in JavaScript:

View Code JAVASCRIPT
var einstein = new Person("Albert Einstein", "Herr");
document.write("<br/>");
einstein.sayGoodbye();
document.write("<br/><br/>");
 
var newton = new Scientist("Isaac Newton", "Herr", "Physik");
document.write("<br/>");
newton.research();
document.write("<br/>");
newton.sayGoodbye();

Die Ausgabe ist für beide identisch:

Hallo Herr Albert Einstein.
Bis bald Herr Albert Einstein.

Hallo Herr Isaac Newton.
Isaac Newton forscht Physik.
Bis bald Herr Isaac Newton.

Ich hoffe ich konnte euch damit die Unterschiede der beiden Sprachen klar machen. Wer möchte kann sich die Beispiele auch als ZIP-Archiv herunterladen.

Mit CSS Radio-Buttons stylen

Es ist relativ kompliziert einen Radio-Button bzw. eine Checkbox mit CSS zu stylen, aber mit Hilfe von JavaScript trotzdem kein Problem.
Das folgende Beispiel lässt sich dennoch gut einbauen und benötigt lediglich die Standard jQuery-Library.

Zuerst das HTML:

<form action="css-radio-demo.html" method="post">
	<div>
		<label for="foo">
			<span class="styled"><input type="radio" name="radiotest" id="foo" value="Foo" checked/></span>
			Foo
		</label>
		<label for="bar">
			<span class="styled"><input type="radio" name="radiotest" id="bar" value="Bar"/></span>
			Bar
		</label>
	</div>
	<br/>
	<button type="submit">Absenden</button>
</form>

Um den Radio-Button kommt noch ein span-Tag mit der Klasse styled. Auf Grundlage dieser Klasse wird das folgende CSS und JavaScript aufgebaut.
Ebenfalls sehr wichtig ist der Label-Tag, damit der Browser den später versteckten original Radio-Button immer noch anwählen kann. Bitte beachten: Wenn das Label-Feld nicht um das input-Feld gelegt wurde, müssen das for-Attribut und die ID des Input-Elements identisch sein.

Der CSS-Code:

.styled {
	background: url(radio-sprite.png) 0 0 no-repeat scroll transparent;
	display: inline-block;
	vertical-align: middle;
	width: 32px;
	height: 32px;
	cursor: pointer;
}
.styled.checked {
	background-position: 0 -32px;
}
.styled input {
	position: absolute;
	z-index: -1;
}

Das span mit der Klasse styled bekommt ein austauschbares Hintergrundbild (dies sollte der gestylte Radio-Button sein) und das eigentliche input-Element wird versteckt. Mit absoluter Positionierung und einem negativen z-index wird das input-Element einfach unter dem übergeordneten Elementen platziert. Damit ist der Radio-Button zwar noch da, wird aber nicht mehr angezeigt und genau das ist wichtig, damit die Funktion des Elements für das Formular weiterhin gegeben ist.
Dazu kommt noch eine checked-Klasse mit der das Hintergrundbild bei einem angewählten Radio-Button geändert wird.

Der JavaScript-Code:

View Code JAVASCRIPT
$(document).ready(function() {
	$(".styled input:checked").parent().addClass("checked");
	$(document).on("change", ".styled input", function() {
		var $this = $(this);
		var form = $this.closest("form");
		form.find("input[name='"+$this.attr("name")+"']").parent().removeClass("checked");
		$this.parent().addClass("checked");
	});
});

Mit dem ersten Befehl (Zeile 2), wird die checked-Klasse hinzugefügt, wenn der Radio-Button bereits vorausgewählt wurde. In dem darauffolgenden Codeblock wird ein neues onchange-Event auf das Input-Element gelegt, das die checked-Klassen entfernt bzw. bei dem neu ausgewählten Element hinzufügt.

Und hier geht’s zur Demo:
CSS Radio-Button Demo

Die Demo funktioniert übrigens in allen Browsern (sogar im IE6, wenn man gif-Bilder statt PNG verwendet).