Inhaltsverzeichnis

Javascript

Selfhtml - JavaScript 1.5 Guide - JavaScript 1.5 Reference - Gecko DOM Reference - M$ HTML and DHTML Reference - Dojo Toolkit - Web Applications and HTML5 - Standalone Javascript

Variables

var Keyword

Within functions always prefix variables with var, otherwise they become global! See Avoid Global namespace

Strings

A string can be an instance of the String class or a string literal. More

String Literals

There is no difference between 'A string' and "A string" More

A string literal is temporarely converted into a String object as soon as you apply methods of String class to the string literal.

Creating Strings

var s1 = "foo";             //creates a string literal value  
var s2 = new String("foo"); //creates a String object  

More

String Concatenation

var a= "al" + "pha" // a == "alpha"
a   += "bet"        // a = "alphabet"

String Comparison

FIXME Because Strings are ojects, String comparison is the same as object comparison :?:

String Methods/Property

String length: var len = mystring.length;

All string methods

Arrays

An Array is an instance of the Array class. More

Creating Arrays

var arr= new Array(element0, element1, ..., elementN);
var arr= [element0, element1, ..., elementN];
 
var arr= new Array(arrayLength);
var arr= [];

Array Methods/Property

Array length: var len = myarray.length;

Array Methods

Objects and Inheritance

Object creation

The classic Java-like way

function Point(x, y) {this.x=x; this.y=y;}
Point.prototype.toString = function() {return "("+this.x+"/"+this.y+")";}
Point.prototype.shift    = function(dx, dy) {this.x+=dx; this.y+=dy;}
 
var p  = new Point(3,4);
document.write("p:"+p.toString());

The closure way

(closures see below)

function makePoint(x, y) { return {
    toString: function() {return "("+x+"/"+y+")";}
    shift:    function(dx, dy) {x+=dx; y+=dy;}
};}
 
var p  = makePoint(3,4);
document.write("p:"+p.toString());

FIXME

Object literals

FIXME

Object cloning

Objects are passed by refernce

> Something like a copy constructor is necessary:

function Point(x, y) {this.x=x; this.y=y;}
Point.prototype.clone= function() {return new Point(this.x, this.y);}
Point.prototype.toString= function() {return "("+this.x+"/"+this.y+") ";}
 
var p  = new Point(3,4);
var pr = p;		// a reference to p
var q  = p.clone();	// a new Point instance with the same coordinates as p
p.x= 9; p.y=-2;		// change content of p
document.write("p:"+p.toString()+ "pr:"+pr.toString()+ "q:"+ q.toString());
// result: p:(9/-2) pr:(9/-2) q:(3/4)

Object Comparison

FIXME

Defining Methods

Method definition inline inside of the constuctor

function MyClass() {  // constructor
    this.method1= function(arg) {/* code */}; // method
}
function MyClass_method1(arg) {/* code */} //  method
function MyClass() {this.method1= MyClass_method1} // constructor

Not recommendable, because

function MyClass() {} // constructor
MyClass.method1= function(arg) {/* code */} //  method

Not possible, causes an js-error if called from an MyClass instace. This is a static method, see below

function MyClass() {} // constructor
MyClass.prototype.method1= function(arg) {/* code */} //  method

Seems to be the best solution :-)

Public Access

function MyClass() {         // The constructor
    this.publicVariable= 10; // A public instance variable
}
MyClass.prototype.publicMethod= function() { // A public (instace) method
    document.write(this.publicVariable + 1 + ' ');
    document.write(MyClass.publicVariable + 1 + ' ');
    document.write(this.publicStaticVariable + 1 + ' ');
    document.write(MyClass.publicStaticVariable + 1 + '<br>');
}
MyClass.publicStaticVariable = 20;           // A public class variable
MyClass.publicStaticMethod= function() {     // A public class method
    document.write(this.publicVariable + 2 + ' ');
    document.write(MyClass.publicVariable + 2 + ' ');
    document.write(this.publicStaticVariable + 2 + ' ');
    document.write(MyClass.publicStaticVariable + 2 + '<br>');
}
// Test:
var myclass= new MyClass();
 
document.write(myclass.publicVariable + '<br>');       // 10
document.write(MyClass.publicVariable + '<br>');       // undefined
 
myclass.publicMethod();   // 11 NaN NaN 21
//MyClass.publicMethod(); // error!
 
document.write(myclass.publicStaticVariable + '<br>'); // undefined
document.write(MyClass.publicStaticVariable + '<br>'); // 20
 
//myclass.publicStaticMethod(); // error!
MyClass.publicStaticMethod(); // NaN NaN 22 22

Public Access

Private methods are possible as inline constructor functions:

function MyClass() {         // The constructor
    var privateVariable= 10; // A private instance variable
    var privMeth1= function {...} // A private method
    fuction privMeth2 {...}       // private method (shortcut)
    var that= this;          // To make this available for priv methods
}

Notes:

Sources & more information:

Inheritance

FIXME see JS Guide 1.5 and dynWidget.js

Misc

Constants

const is mentioned in the Mozilla guide but dosen't work with Rhino version :?: and probabaly neither with IE

Events

For event handling see: Mozilla & Selfhtml

See also Dojo events

Get the Source of the Event

/** conchange event handler function */
function getNameAndValueOfInputField(event) {
    var name, value;
    if (event) {
        name  = event.target.name;
        value = event.target.value;
    } else {  // IE specific code. I hate it!
        name  = window.event.srcElement.name;
        value = window.event.srcElement.value;
    }
    return {"name":name, "value":value};
}
 
// set conchange event for input field: 
var input = document.getElementById("franz"):
input.onchange = getNameAndValueOfInputField;

Event handler for value input fields

Closures

From MDC

Principle

A closure is a special kind of object that combines two things: a function, and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created. Consequently, you can use a closure anywhere that you might normally use an object with only a single method.

Instead of

function Statusbar(elementId) { /* class constructor */
    this.target  = document.getElementById(elementId);
    this.setText = function(text) { this.target.innerHTML= text; }
}
var statusbar = new Statusbar("statusbar");
statusbar.setText("some text");

you can use:

function makeStatusTextSetter(elementId) { /* closure factory */
    var target= document.getElementById(elementId);
    return function(text) { target.innerHTML= text; }
}
var setStatusText= makeStatusTextSetter("statusbar");
setStatusText("some text");

Practical Usage

Imho mainly as callbacks for events:

<html><head>
    <script type="text/javascript" src="copy.js"></script>
</head><body>
<form id="form" action="dummy">
  <textarea id="inbox" name="inbox" cols="80" rows="10"></textarea>
</form>
<pre id="outbox">...</pre>
</body></html>
function makeCopyFkt(inboxNode, outboxNode) {
    /* inner funct is a closure witch gets attached the environment (including
	passed arguments) of the outer function  */
    return function () { outboxNode.innerHTML= inboxNode.value; }
}
 
window.onload = function() { /* called when html is loaded completely */
    var inboxNode  = document.getElementById('inbox');
    var outboxNode = document.getElementById('outbox');
    var copyFkt= makeCopyFkt(inboxNode, outboxNode);
    inboxNode.onblur= copyFkt;
};

Using class member methods as event callbacks

Global functions, i.e. functions which are defined outside of a class can easily be used as event callbacks for DOM nodes, but what about class member methods?

The following example will not work, because the callback function copy has no access to this at the time being called:

function Copier(inboxNode, outboxNode) {
    this.inboxNode  = inboxNode;
    this.outboxNode = outboxNode;
    this.copy = function () { this.outboxNode.innerHTML= this.inboxNode.value; }
}
 
window.onload = function() { /* called when html is loaded completely */
    var inboxNode  = document.getElementById('inbox');
    var outboxNode = document.getElementById('outbox');
    var copier= new Copier(inboxNode, outboxNode);
    inboxNode.onblur= copier.copy;
};

But it works with the closure way:

function Copier(inboxNode, outboxNode) {
    this.inboxNode  = inboxNode;
    this.outboxNode = outboxNode;
    this.copy = function () { self.outboxNode.innerHTML= self.inboxNode.value; }
    var self= this; // reference to this is saved in environment for closures
}

Or even shorter:

function Copier(inboxNode, outboxNode) {
    this.copy = function () { outboxNode.innerHTML= inboxNode.value; }
}

But the best solution is imho to leave the class clean and pass the DOM node not directly the member function but an additional (anonymous) wrapper function as closure. This works also with real (prototype) methods:

function Copier(inboxNode, outboxNode) {
    this.inboxNode  = inboxNode;
    this.outboxNode = outboxNode;
}
Copier.prototype.copy= function() {this.outboxNode.innerHTML= this.inboxNode.value;};
 
window.onload = function() { /* called when html is loaded completely */
    var inboxNode  = document.getElementById('inbox');
    var outboxNode = document.getElementById('outbox');
    var copier= new Copier(inboxNode, outboxNode);
    inboxNode.onblur= function() { copier.copy(); }; // <== "wrapper" closure
};

:!: Take care if you want to initialize more than on DOM callback in a loop. For this a callback factory function is necessary. See JavaScript Guide

FIXME Check out Emulating private methods with closures

Ajax

Links

Basic principles from Mastering Ajax series at IBM developerWorks - Simple AJAX Code-Kit - Raw cross browser code

Sending JSON to Server

To convert any javscript value to a JSON string, use json2.js at json.org

Todo / Pending

Cookies

Code for writing and reading cookies by javascript is available here. An example can be found in my plainGTD App. Note that cookies can be manipulated easier by server side scripting, eg PHP

Dojo Toolkit

See Dojo Toolkit

Using Javascript from the Command Line

See Standalone Javascript