Kategorien
Diplomarbeit Sonstiges

Javascript-Klassen und Objekte

Habe gerade noch das hier gefunden: Class-Based vs. Prototype-Based Languages

Ich hab zwar schon hier auf einen schönen Artikel verwiesen, aber jetzt nochmal das ganze aus meinem Munde.

Javascript is Objektorientiert. Schon immer. Glaub ich. 1995 das erstmal mit Netscape veröffentlicht, sind wir inzwischen bei Javascript 1.8 angekommen (seit 18. Dezember 2007). Javascript wird übrigens von Mozilla „gemanaged“. Und Javascript ist nicht Ecmascript. Vielmehr ist Javascript ein Dialekt von Ecmascript.

Soviel dazu. Javascript implementiert ECMAScript, genauer ECMA-262, edition 3. Innerhalb davon gibt es keine „Klassen“ im eigentlichen Sinne. Viel eher werden direkt Objekte geboren.

function meinObjekt () {
    this.zahl = 1;
}

Und schon haben wir ein Objekt/Klasse mit dem Namen „meinObjekt“. Und eine Eigenschaft „zahl“ hat es auch.

var objekt = new meinObjekt();
window.alert(objekt.zahl);

Und somit kriegen wir ein Fenster mit einer „1“ drinnen. Es gibt auch private und öffentliche Eigenschaften/Methoden, allerdings ist Javascript da etwas bockig:

function meinObjekt () {
     var self = this;
 
    /** @private */
    var foobar = "private";
    var privateMethod = function () {
        window.alert(foobar  + " " + self.barfoo);
    };
 
    /** @public */
    this.barfoo = "public";
    this.public_method = function () {
        window.alert(foobar + " " + this.barfoo);
        private_method();
    };
}

Wer sich wundert was das „self“ soll, das liegt an Javascript. Während der Zugriff von öffentlichen auf private Methoden prima klappt, ist der Zugriff von privaten auf öffentliche Methoden … anders :). Hierzu wird einfach „this“ in „self“ kopiert und dann kann wie „this“ verwendet werden. Jippie.

Ich verwende den Spass gerade so:

var logger = function() {
};
logger.prototype = {
	log : function(msg) {
		console.log(this.getNow() + msg);
	},
	getNow : function() {
		return new Date();
	}
};
var foobar = new logger();
logger.log("foobar"); // prints "foobar"

Man spricht hier von „prototyp-basierter“ Objektorientierung. Interessant wirds in dem „neuen“ Standard ECMA-262, edition 4. Dort gibt es dann tatsächlich auch Klassen:

class C {
	var val // a variable property
	var large = Infinity // a variable property
	const x = 3.14 // a constant property
	function f(n) { return n+val*2 } // a method property
}

Da ja Javascript schön dynamisch ist, gibt es auch dynamische Klassen:

dynamic class C {
}
c = new C
c.x = 37 // adds a property
delete c.x // removes it again

Weiter gehts mit Vererbung, jetzt mit Schlüsselwörtern wie „extends“:

class C {
	var val
	function f(n) { return n+1 }
}
class BetterC extends C {
	var large = 123456 // new value property
	override function f(n) { return n*3 } // overridden method property
}

Es gibt auch „final“ als Schlüsselwort, eine so bezeichnete Klasse kann dann keine Kinder kriegen. Und zu guter Letzt werden auch Interfaces eingeführt. Somit wird Ecmascript und somit auch Javascript an die „normale“ Objektorientierung herangeführt. Die komplette Spezifikation des „neuen“ ECMAScripts findet sich unter:

http://www.ecmascript.org/es4/spec/overview.pdf

Kategorien
Spass

Der Storch

via eisdiele

Kategorien
Diplomarbeit

Javadoc für Javascript

http://www.jsdoctoolkit.org/

Erster Eindruck: Exzellent.

Kategorien
Diplomarbeit

Test und so

hab heute mein eigenes Unit-Test-Dings geschrieben. Kann nix, bin aber stolz wie Oskar 🙂

Kategorien
Diplomarbeit

Javascript aus FF-Erweiterung in der Webseite benutzen

Langer Titel, kurzer Blogeintrag. Ich bastel gerade daran rum, diverse Javascript-Funktionen innerhalb der HTML-Seite zu benutzen. Das kann ziemlich hässlich werden:

var head = this.getContentDocument().getElementsByTagName("head")[0];
var script = this.getContentDocument().createElement("script");
var showImage = this.getContentDocument().createTextNode("function showImage(id) { "
		 + "var image = document.getElementById(id);"
		 + "image.style.display = \"inline\"; "
		 + "image.parentNode.previousSibling.addEventListener(\"mouseout\",
		 function() {"
		 + "window.setTimeout(fadeImage, 1500, id);"
		 + "}, false)"
		 + "}");
script.appendChild(showImage);
head.appendChild(script);

Alles doppelt escapen und so. Kein Spass. Hässlich zum Lesen. Lösung:

var head = this.getContentDocument().getElementsByTagName("head")[0];
var script = this.getContentDocument().createElement("script");
script.setAttribute("src", "resource://jslibs/foobar.js");
script.setAttribute("type", "text/javascript");
head.appendChild(script);

Nix spektakuläres, aber innerhalb der Datei „foobar.js“ kann man jetzt ‚ganz normales‘ Javascript schreiben. Ich freu mich über sowas 😉

Kategorien
Sonstiges

The Strangers

Gestern war wieder „Sneaktime“. Nunja, zumindest theoretisch. Der aufmerksame Leser hat sich bestimmt sofort an einen älteren Eintrag erinnert: Ja, der Film ist jetzt wohl auch in Deutschland gelandet. Und dazu gleich noch eine zweite Premiere: Ich bin nach 10min oder so wieder aus dem Kino raus. Das hat zwei Gründe

  • Ich kenne den Film schon und er ist schlecht
  • Der Film ist schlecht und ich kenne ihn schon

Im Nachhinein hätte ich noch warten sollen bis Liv Tyler spricht, ich kann mich gar nicht an die deutsche Stimme erinnern. Viel wichtiger als das alles ist aber:

Sehr gut. SEHR GUT.

Kategorien
Diplomarbeit Sonstiges

Registry Pattern in Javascript

Wer globale Objekte vermeiden will, aber trotzdem globalen Zugriff will (z.B. auf eine Datenbankinstanz) baut sich eine Registry. Im Prinzip nur das Singleton-Pattern mit get und set-Methoden:

registry = (function() {
	// private attributes
	var blubb = new Array();
	// private methods
	var getIndex = function(_name) {
		for (var i = 0; i < blubb.length; i++) {
			if (blubb[i].name == _name) {
				return i;
			}
		}
		return null;
	};

	return {
		// public attributes

		// public methods
		setValue : function(_name, _value) {
			var foo = this.getValue(_name);
			if (foo == null) {
				var temp = new Object();
				temp.name = _name;
				temp.value = _value;
				blubb.push(temp);
			} else {
				blubb[getIndex(_name)].value = _value;
			}
		},
		getValue : function(_name) {
			for (var i = 0; i < blubb.length; i++) {
				if (blubb[i].name == _name) {
					return blubb[i].value;
				}
			}
			return null;
		}
	}
})();
// registry is already available
registry.setValue("foo", "bar");
registry.getValue("foo"); // gives "bar"
registry.getValue("bar"); // gives null
[/sourcecode]

Siehe auch: http://yuiblog.com/blog/2007/06/12/module-pattern/

Kategorien
PC & Accessoires

Lightning

Also, ich bin ja echt zufrieden mit Lightning als Kalendererweiterung zu Thunderbird. Vor allem in Verbindung mit Provider for Google Calendar habe ich zuhause einen schönen Kalender und unterwegs Google Calendar (bisher ungeschlagen gut in Usability und Schnelligkeit).

Allerdings hapert er immer ein bisschen. Zum Beispiel funktioniert die Verbindung mit Google Calendar nur wenn man online ist. Einen Cache und danach synchronisierung wenn man wieder online ist gibt es nicht. Oder wenigstens einen schreibgeschützten Zugriff während man offline ist auf seine Kontakte. Korrektur, geht doch. Lästig ist es allerdings, dass man seine Kalender alle manuell eintragen muss und nicht etwa eine Liste von Google geholt wird, aus denen man auswählen könnte. Dazu gibt es aber schon einen Bug.

Der eigentliche Grund für diesen Beitrag ist aber:

Weil ich schreibfaul bin, wollte ich „24.-30. November 2008“ und „Kalenderwoche: 48“ kopieren. Geht aber nicht, lässt sich nicht markieren. Schade.

Kategorien
Sonstiges Spass

Geschlecht: Jungen

Ein Bulldozerspielzeug mit „Geschlecht: Jungen“. Ich finds witzig, weil unglücklich formuliert 🙂

Quelle: LEGO Technic 8275 – RC Bulldozer mit Motor bei amazon.de

Kategorien
Diplomarbeit Spass

Wie man das Laden einer Seite abfängt …

Ohne Witz. Seit 4 Wochen doktor ich daran rum und ENDLICH hab ich den richtigen (bzw. funktionellen) Weg gefunden wie man es macht:
overlay.xul:

<overlay id="extensionId" 
    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <script type="application/x-javascript" src="chrome://extensionId/content/myJs.js"/>
</overlay>
</pre>
<strong>myJs.js:</strong>
<pre lang="javascript">
Components.utils.import("resource://jslibs/test.js");
function startupWrapper() {
	var appcontent = document.getElementById("appcontent"); // browser
	if (appcontent) {
		appcontent.addEventListener("DOMContentLoaded", function() {
					justATest(getBrowser());
				}, true);
	}
}

test.js:

var EXPORTED_SYMBOLS = ["justATest"];
justATest = function(gBrowser) {
	var body = gBrowser.mCurrentBrowser.contentDocument.getElementsByTagName('body')[0];
}

Herzlichen Glückwunsch. Vorher hab ich „nur“ auf DOMContentLoaded gehört, das hat mir dann aber beschert, dass meine Funktion pro XUL-Dokument aufgerufen wurde, also z.B. für die Web Developer Toolbar, die Locationbar, den Browser an sich und dann erst die Webseite. Vorher hab ich das kläglich mit

if (gBrowser.mCurrentBrowser.contentDocument.documentURI != "about:blank") {
  // do something
}

abbeholfen, aber das ist ja doof 🙂 Jetzt gehts. Hooray