Moin.
Diejenigen von euch, die sich seit längerem mit JavaScript herumschlagen mussten, habe sich mit der Zeit eventuell eine eigene Bibliothek von Skripten zugelegt.
Ich würde gerne sehen, was sich bei anderen so angesammelt hat. Dabei sollten die Skripte
- nützlich
- kurz
- browserübergreifend funktionstüchtig
sein. Zwei von drei Punkten sollten mindestens erfüllt sein.
Ich mache mal den Anfang:
--- clone() ---
Echte prototypische Vererbung mit der von Mozilla bekannten \_\_proto\_\_
Eigenschaft. Anders als in Geckos ist diese browserübergreifend jedoch nur bei Objekterzeugung setzbar.
function clone(obj) {
if(obj.isPrototypeOf(this))
this.__proto__ = obj;
else return new arguments.callee(arguments.callee.prototype = obj);
}
--- hash() ---
Hashfunktion für beliebige Datentypen. Erlaubt es, Objekte als Maps mit beliebigen Schlüsseln zu verwenden - unterscheidet '5' und 5 und versieht Objekte mit eindeutiger Id.
function hash(value) {
return (typeof value) + ' ' + (value instanceof Object ?
(value.__hash || (value.__hash = ++arguments.callee.current)) :
value.toString());
}
hash.current = 0;
--- each() ---
Iteration über die objekteigenen Eigenschaften.
function each(obj, func) {
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
func.call(obj, prop, obj[prop]);
}
}
--- XMLHttpRequest() ---
Erlaubt es, Request-Objekte auch im IE über new XMLHttpRequest()
zu erzeugen.
if(typeof window.XMLHttpRequest !== 'function' &&
typeof window.ActiveXObject === 'function') {
window.XMLHttpRequest = function() {
try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}
try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
return null;
};
}
--- onready() ---
Browserübergreifender Ersatz für das DOMContentLoaded-Ereignis. Erwartet eine Liste von Funktionen als Argumente.
function onready() {
var args = arguments;
var timeout = arguments.callee.timeout;
(function() {
if(document.body && document.body.lastChild) {
for(var i = 0; i < args.length; ++i)
args[i]();
}
else setTimeout(arguments.callee, timeout);
})();
}
onready.timeout = 100;
--- capture() ---
Nicht wirklich kurz, aber dafür äußerst nützlich: Vereinfacht die Ereignis-Behandlung enorm. Erwartet als Argmente:
1. den Ereignis-Typ (z.B. 'click')
2. eine Auswahlregel, welche Elemente als Ereignis-Quellen in Frage kommen
3. die Funktion, die das Ereignis verarbeitet
Erlaubte Werte für die Auswahlregel sind
- true
:
Das Ereignis wird immer abgefangen
- eine Zeichenkette:
Beginnt diese mit '#', werden Elemente mit entsprechender Id behandelt. Beginnt sie mit '.', werden Elemente mit entsprechender Klasse behandelt. Ansonsten wird die Zeichenkette als Element-Name interpretiert.
- ein regulärer Ausdruck:
Der Ausdruck wird gegen die className
-Eigenschaft eines Elements geprüft.
- eine beliebige Funktion:
Das zu überprüfende Element wird als this
übergeben; die Funktion muss einen Wahrheitswert zurückgeben.
Sowohl in standardkonformen Browsern als auch im IE wird der Verarbeitungsfunktion die Ereignis-Quelle als this
und das Ereignis-Objekt als erstes Argument übergeben. Liefert die Funktion false
zurück, wird die Standard-Behandlung des Ereignisses (Formular absenden, Link verfolgen, ...) ausgesetzt.
var capture = (function() {
function noCapture() {
throw new Error('event capture unsupported');
}
function returnTrue() {
return true;
}
function createChecker(condition) {
if(condition === true)
return returnTrue;
if(typeof condition === 'string') {
switch(condition.charAt(0)) {
case '#': {
var id = condition.substring(1);
return function() {
return this.id === id;
}
}
case '.': {
return createChecker(eval('/(^|\s)' +
condition.substring(1) + '(\s|$)/'));
}
default: {
var tagName = condition.toLowerCase();
return function() {
return this.nodeName.toLowerCase() === tagName;
};
}
}
}
if(condition instanceof RegExp) {
return function() {
return condition.test(this.className);
};
}
if(typeof condition === 'function')
return condition;
throw new Error('unsupported capture condition: ' + condition);
}
function addCapture(type, condition, handler) {
var checker = createChecker(condition);
document.addEventListener(type, function(event) {
if(checker.apply(event.target) &&
handler.call(event.target, event) === false) {
event.preventDefault();
}
}, false);
}
function attachCapture(type, condition, handler) {
var checker = createChecker(condition);
document.attachEvent('on' + type, function() {
if(checker.apply(event.srcElement) &&
handler.call(event.srcElement, event) === false) {
event.returnValue = false;
}
});
}
return document.addEventListener ? addCapture :
document.attachEvent ? attachCapture :
noCapture;
})();
Und jetzt ihr ;)
Christoph