

/* --- finding elements --- */
function id( name ) {
	return document.getElementById( name );	// -> HTML element
};

	/* === fix document.getElementById for IE - based on code by J. Max Wilson: http://www.sixteensmallstones.org/ie-javascript-bugs-overriding-internet-explorers-documentgetelementbyid-to-be-w3c-compliant-exposes-an-additional-bug-in-getattributes === */ 
	document.nativeGetElementById = document.getElementById;
	document.getElementById = function( id ) {
	    if ( document.all ) {   // only override when document.all is supported (IE + Opera)
	
	        document.getElementById = function( id ) {
	            var elem = document.nativeGetElementById( id );
	            if ( !elem ) return null;
	            if ( elem.attributes['id'] && elem.attributes['id'].value == id ) return elem;							// make sure that it is a valid match on id
	
	            for ( var i = 1; i < document.all[ id ].length; i++ ) {															// otherwise find the correct element
	                if ( document.all[ id ][ i ].attributes[ 'id' ].value == id ) return document.all[ id ][ i ];
	            }
	        };
	    } else {    // otherwise change back to original
	        document.getElementById = document.nativeGetElementById;
	        document.nativeGetElementById = null;  																						// we don't need it anymore
	    }
	};
	document.getElementById();																													// run document.getElementById() once to let it rewrite itself
	/* --- /fix document.getElementById for IE --- */

function tag( name, elem ) {
	return ( elem || document ).getElementsByTagName( name );	// -> Array
};

function withClass( name, sel, sel2 ) {														// sel and sel2 are both optional and can be either an element or a tag (one of each)
	var haveClass = [];
	var regExp = new RegExp( "(^|\\s)" + name + "(\\s|$)" );								// allows for multiple class names
	var tagName = sel.constructor == String ? sel : sel2;
	var elem = sel.constructor == String ? sel2 : sel;
	var elements = ( elem || document).getElementsByTagName( tagName || "*" );		// use document if no element has been specified and get all elements if no tag name has been specified
	for ( var e = 0; e < elements.length; e++) {
		var element = elements[ e ];
		if ( hasClass( element, name )) haveClass[ haveClass.length ] = element;
	}
	return haveClass;																					// -> Array
};

function hasClass( elem, name ) {
	if ( !name && elem.className != "") return true;			// if no className has been specified any className will do | -> Boolean
	var regExp = new RegExp( "(^|\\s)" + name + "(\\s|$)" );	// allows for multiple class names
	if ( regExp.test( elem.className )) return true;			// -> Boolean
	return false;															// -> Boolean
};

function prev( elem ) {
	do {
		elem = elem.previousSibling;
	} while ( elem && elem.nodeType != 1 );
	return elem;
}

function next( elem ) {
	do {
		elem = elem.nextSibling;
	} while ( elem && elem.nodeType != 1 );
	return elem;
}

function first( elem ) {
	elem = elem.firstChild;
	return elem && elem.nodeType != 1 ? next( elem ) : elem;
}

function last( elem ) {
	elem = elem.lastChild;
	return elem && elem.nodeType != 1 ? next( elem ) : elem;
}


/* --- get/set attributes --- */
function attr( elem, attrib ) {															// attrib can be a String (get) or an Object (set)
	if ( attrib.constructor == String ) {
		name = validName( attrib );
		return elem[ name ] || elem.getAttribute( name ) || '';					// -> String (attribute value)
	}
	else if ( attrib.constructor == Object ) {
		for ( n in attrib ) {
			var value = attrib[ n ];
			name = validName( n );
			if ( name == "className" || name == "rel" || name == "rev" ) {
				addToAttr( elem, name, value );
			} else {
				elem[ name ] = value;														// do it quick if possible
				if ( elem.setAttribute ) elem.setAttribute( name, value );		// XML fallback
			}
		}
		return true;																			// -> Boolean (values are set)
	}
	function validName( name ) {
		return { 'for': 'htmlFor', 'class': 'className' }[ name ] || name;	// rename in case of 'for' or 'class' attribute
	};
	return '';																					// -> String (empty: attrib was neither a String or Object)
};

function addClass( elem, name ) {
	addToAttr( elem, "className", name );
}

function removeClass( elem, name ) {
	removeFromAttr( elem, "className", name );
}

function addToAttr( elem, attr, value ) {	// can be used for class, rel and rev attributes
	removeFromAttr( elem, attr, value );	// make sure there won't be any doubles
	elem[ attr ] += " " + value;
}

function removeFromAttr( elem, attr, value ) {									// can be used for class, rel and rev attributes
	var remain = [];
	var values = elem[ attr ].split(/\s+/);										// seperate class names (devided by one or more whitespaces)
	for ( var v = 0; v < values.length; v++ ) {
		if ( values[ v ] != value ) remain[ remain.length ] = values[ v ];
	}
	elem[ attr ] = remain.join( " " );
}