DOM = {};

DOM.userAgent = navigator.userAgent.toLowerCase(); 
DOM.isKonq = DOM.userAgent.indexOf('konqueror') != -1 || DOM.userAgent.indexOf('safari') != -1;
DOM.isGecko = !DOM.isKonq && DOM.userAgent.indexOf('gecko') != -1;
DOM.isOpera = DOM.userAgent.indexOf('opera') != -1;
DOM.isIE = DOM.userAgent.indexOf('msie') != -1 && !DOM.isOpera;
DOM.isIE7 = DOM.isIE && window.XMLHttpRequest;
DOM.isWebKit = DOM.userAgent.indexOf('webkit') != -1;
DOM.isChrome = DOM.userAgent.indexOf('chrome') != -1;

DOM.eventListeners = {};

// This calls document.getElementById
DOM.get = function(id) {
    return document.getElementById(id);
}

// This calls document.getElementById, but fixes internet explorer 6 bugs about that
DOM.getOnlyById = function(id) {
    if (DOM.isIE) {
        var list = document.getElementsByName(id);
        var i;
        for (i = 0; i < list.length; i++) {
            if (list[i].id == id) {
                return list[i];
            }
        }
        return null;
    } else {
        return document.getElementById(id);
    }
}

DOM.getAllNodesBetweeen = function(element1, element2) {
		if (element1 == element2) {
			return [];
		}
		if (element1.firstChild) {
			return [ element1.firstChild ].concat(DOM.getAllNodesBetweeen(element1.firstChild, element2));
		} else if (element1.nextSibling) {
			return [ element1.nextSibling ].concat(DOM.getAllNodesBetweeen(element1.nextSibling, element2));
		} else {
			while (element1.parentNode && element1.parentNode != element2) {
				var i, nodes;
				nodes = element1.parentNode.childNodes;
				for (i = 0; i < nodes.length; i++) {
					if (nodes[i] == element1) {
						break;
					}
				}
				if (i + 1 < nodes.length) { // if the element is not the last one
					return DOM.getAllNodesBetweeen(nodes[i + 1], element2);
				}
				// the element is the last one
				element1 = element1.parentNode;
			}
			return []; // We have no more parents
		}
}

DOM.getElementsByClassName = function(node, className) {
    var results = [], elements = node.getElementsByTagName('*');
    for (var i = 0; i < elements.length; ++i) {
        if (elements[i].className && DOM.hasClass(elements[i], className)) {
            results.push(elements[i]);
        }
    }
    return results;
}


// Returns true if the element has that css class name (it may also have others)
DOM.hasClass = function(element, className) {
    return !!element.className && VAR.hasWord(element.className, className)
}

// Adds that css class name to the element
DOM.addClass = function(element, className) {
    element.className = VAR.addWord(element.className, className)
}

// Removes that css class name from the element
DOM.removeClass = function(element, className) {
    element.className = VAR.removeWord(element.className, className)
}

// Toggles that css class name in the element
DOM.toggleClass = function(element, className) {
    if (DOM.hasClass(element, className)) {
        DOM.removeClass(element, className);
    } else {
        DOM.addClass(element, className);
    }
}

// Ensures the element has (or not) the className
DOM.setHasClass = function(element, className, addIfTrueRemoveIfFalse) {
    if (addIfTrueRemoveIfFalse) {
        DOM.addClass(element, className);
    } else {
        DOM.removeClass(element, className);
    }
}

DOM.getPositionFromEvent = function(event) {
    if (event.pageX) { /* Standards... */
        return {x: event.pageX, y: event.pageY};
    } else { /* ie ... */
        var pos = DOM.getScrollBarPositions();
        return {x: event.clientX + pos.x, y: event.clientY + pos.y};
    }
}

DOM.getButtonFromEvent = function(event) {
    if (event.button == 2) {
        return 'right';
    } else if (DOM.isGecko) {
        if (event.button == 0) {
            return 'left';
        } else {
            return 'middle';
        }
    } else {
        if (event.button == 1) {
            return 'left';
        } else {
            return 'middle';
        }
    }
}

DOM.preventDefault = function(event) {
    if (event.preventDefault) {
        event.preventDefault();
    } else {
        event.returnValue = false;
    }
}

DOM.stopPropagation = function(event) {
    if (event.stopPropagation) {
        event.stopPropagation();
    } else {
        event.cancelBubble = true;
    }
}

DOM.cancelEvent = function(event) {
    if (!event) {
        event = window.event;
    }
    DOM.preventDefault(event);
    DOM.stopPropagation(event);
}

DOM.getElementFromEvent = function(event) {
    if (event.target) {
        return event.target;
    } else {
        return event.srcElement;
    }
}

DOM.getPosition = function(obj, dontWrapBody) {
    var left = obj.offsetLeft;
    var top = obj.offsetTop;
    while (obj.offsetParent) {
        obj = obj.offsetParent;
        left += obj.offsetLeft - obj.scrollLeft;
        top += obj.offsetTop - obj.scrollTop;
    }
    var body = (!dontWrapBody && window.LOG) ? window.LOG.getBody() : document.body;
    left += body.scrollLeft;
    top += body.scrollTop;
    return { x: left, y: top };
}

DOM.getScrollBarPositions = function() {
    var x, y;
    if (typeof document.documentElement != 'undefined' && typeof document.documentElement.scrollLeft != 'undefined') {
        x = document.documentElement.scrollLeft;
        y = document.documentElement.scrollTop;
    } else if (typeof window.pageXOffset != 'undefined') {
        x = window.pageXOffset;
        y = window.pageYOffset;
    } else {
        x = document.body.scrollLeft;
        y = document.body.scrollTop;
    }
    return {x: x, y: y}
}

DOM.getWindowInnerSize = function() {
    var w, h;
    if (self.innerHeight) { // all except Explorer
        w = self.innerWidth;
        h = self.innerHeight;
    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
        w = document.documentElement.clientWidth;
        h = document.documentElement.clientHeight;
    } else if (document.body) { // other
        w = document.body.clientWidth;
        h = document.body.clientHeight;
    }
    return {w: w, h: h}
}

if (DOM.isIE) {
    DOM.addEventToRegistry = function(element, eventString, handler, useCapture, eventRegistry) {
        if (!eventRegistry[eventString]) {
            eventRegistry[eventString] = [];
        }
        var item = {
            handler: handler,
            element: element,
            useCapture: useCapture
        };
        eventRegistry[eventString].push(item);
    }

    DOM.removeEventFromRegistry = function(element, eventString, handler, useCapture, eventRegistry) {
        var list = eventRegistry[eventString];
        var pos;
        for (var i = 0; i < list.length; ++i) {
            if (list[i].handler == handler && list[i].element == element && list[i].useCapture == useCapture) {
                pos = i;
                break;
            }
        }
        list.splice(pos, 1);
        if (list.length == 0) {
            delete eventRegistry[eventString];
        }
    }

    DOM.addEventListener = function(element, eventString, handler, useCapture) {
        useCapture = !!useCapture;
        element.attachEvent("on" + eventString, handler);
        DOM.addEventToRegistry(element, eventString, handler, useCapture, DOM.eventListeners);
    }

    DOM.removeEventListener = function(element, eventString, handler, useCapture) {
        useCapture = !!useCapture;
        DOM.removeEventFromRegistry(element, eventString, handler, useCapture, DOM.eventListeners);
        element.detachEvent("on" + eventString, handler);
    }

    DOM.removeAllEventListeners = function() {
        DOM.removeAllEventListenersInRegistry(DOM.eventListeners);
    }

    DOM.removeAllEventListenersInRegistry = function(eventRegistry) {
        var eventString, list, item;
        for (eventString in eventRegistry) {
            list = eventRegistry[eventString];
            while (list.length > 0) {
                item = list[0];
                DOM.removeEventListener(item.element, eventString, item.handler, item.useCapture, eventRegistry);
            }
        }
    }

    DOM.addEventListener(window, 'unload', DOM.removeAllEventListeners);

} else {

    DOM.addEventListener = function(element, eventString, handler, useCapture) {
        element.addEventListener(eventString, handler, useCapture);
    }

    DOM.removeEventListener = function(element, eventString, handler, useCapture) {
        element.removeEventListener(eventString, handler, useCapture);
    }

}

DOM.createEventHandler = function(obj, methodName, parameter) {
    return function(event) {
        if (!event) {
            event = window.event;
        }
        obj[methodName].call(obj, event, parameter);
    }
}

DOM.setHeight = function(element, newHeight) {
    if (newHeight >= 0) {
        element.style.height = newHeight + 'px';
    }
}

DOM.setStyle = function(element, styleProperties) {
    for(var prop in styleProperties) {
        element.style[prop] = styleProperties[prop];
    }
}

DOM.getSize = function(element) {
		return {
			w: element.offsetWidth,
			h: element.offsetHeight
		}
	}

// Returns if the position.x and position.y are inside the element position considering its size
DOM.positionIsInsideElement = function(position, element) {
    var elementPos = DOM.getPosition(element, true);
    elementPos.x1 = elementPos.x + element.offsetWidth;
    elementPos.y1 = elementPos.y + element.offsetHeight;
    return position.x >= elementPos.x && position.x <= elementPos.x1 && position.y >= elementPos.y && position.y <= elementPos.y1;
}

DOM.getElementBoundaries = function(element) {
    var elementPos = DOM.getPosition(element, true);
    return {
        x0: elementPos.x,
        x1: elementPos.x + element.offsetWidth,
        y0: elementPos.y,
        y1: elementPos.y + element.offsetHeight
    }
}

// Returns null if the position if outside the boundaries or the position.x and position.y relative to the element
DOM.getPositionInsideBoundaries = function(position, boundaries) {
    if (position.x >= boundaries.x0 && position.x <= boundaries.x1 && position.y >= boundaries.y0 && position.y <= boundaries.y1) {
        return {
            x: position.x - boundaries.x0,
            y: position.y - boundaries.y0
        };
    } else {
        return null;
    }
}

// Returns null if the position if outside the element or the position.x and position.y relative to the element
DOM.getPositionInsideElement = function(position, element) {
    return DOM.getPositionInsideBoundaries(position, DOM.getElementBoundaries(element));
}

DOM.mouseIsInside = function(element, event) {
    return DOM.positionIsInsideElement(DOM.getPositionFromEvent(event), element);
}

DOM.createElementInDocument = function(ownerDocument, tagName, attributes, childNodes) {
   var element;
    if (DOM.isIE && tagName == 'input' && attributes && attributes.type) {
        element = ownerDocument.createElement('<input type="' + attributes.type + '"' + (attributes.name ? ' name="' + attributes.name + '"' : '') + (attributes.id ? ' id="' + attributes.id + '"' : '') + '>');
    } else {
        element = ownerDocument.createElement(tagName);
    }
    var styleProperties, item;
    var type;
    for (var attribute in attributes) {
        type = typeof attributes[attribute];
        if (type == 'function') {
            if (DOM.isIE) {
                DOM.addEventListener(element, attribute.substr(2), attributes[attribute]);
            } else {
                element[attribute] = attributes[attribute];
            }
        } else if (type == 'boolean') {
            element[attribute] = attributes[attribute];
        } else if (attribute == 'style' && typeof attributes[attribute] == 'object') {
            styleProperties = attributes[attribute];
            for (item in styleProperties) {
                if (styleProperties[item] !== null) {
                    element.style[item] = styleProperties[item];
                }
            }
        } else if (attribute == 'class') {
            element.className = attributes[attribute];
        } else if (attribute == 'maxlength') { // IE doesn't support setting the maxlength attribute
            element.maxLength = attributes[attribute];
        } else if (attributes[attribute] === null) {
            continue;
        } else if (!DOM.isIE || tagName != 'input' || (attributes[attribute] != 'type' && attributes[attribute] != 'name')) {
            element.setAttribute(attribute, attributes[attribute]);
        }
    }
    if (childNodes) {
        DOM.appendChildren(element, childNodes);
    }
    return element;
}

DOM.createElement = function(tagName, attributes, childNodes) {
    return DOM.createElementInDocument(document, tagName, attributes, childNodes);
}

DOM.appendChildren = function(parent, childNodes) {
    if (typeof childNodes == 'string' || typeof childNodes.length == 'undefined') {
        return;
    }
    for (var i = 0; i < childNodes.length; ++i) {
        DOM.appendChild(parent, childNodes[i]);
    }
}

DOM.appendChild = function(parent, child) {
    try {
        if (child == null) {
            return;
        } else if (typeof child == 'string' || typeof child == 'number') {
            parent.appendChild(parent.ownerDocument.createTextNode(child));
        } else {
            var domNode;
            if (child.getDomNode) {
                domNode = child.getDomNode();
            } else {
                domNode = child;
            }
            parent.appendChild(domNode);
        }
    } catch (e) {
        throw e;
    }
}

DOM.removeAllChildren = function(element) {
    while (element.firstChild) {
        DOM.removeChild(element, element.firstChild);
    }
}

DOM.removeChild = function(parent, child) {
    if (child === null) {
        return;
    } else {
        parent.removeChild(child);
    }
}

DOM.obj_event_listeners_count = 0;

DOM.addObjEventListener = function(obj, element, event_string, handler) {
    var item, pos = DOM.obj_event_listeners_count;
    ++DOM.obj_event_listeners_count;
    if (!element.DOM_ObjEventListeners) {
        element.DOM_ObjEventListeners = {};
    }
    item = {
        obj: obj,
        element: element,
        event_string: event_string,
        handler: handler
    };
    item['internal_handler'] = function(event) { DOM.runObjEventHandler(event, item) };
    element.DOM_ObjEventListeners[pos] = item;
    DOM.addEventListener(element, event_string, item.internal_handler);
}

DOM.removeObjEventListener = function(obj, element, event_string, handler) {
    var item, pos;
    for (pos in element.DOM_ObjEventListeners) {
        item = element.DOM_ObjEventListeners[pos];
        if (item.obj == obj && item.element == element && item.event_string == event_string && item.handler == handler) {
            DOM.removeEventListener(element, event_string, item.internal_handler);
            delete(element.DOM_ObjEventListeners[pos]);
            break;
        }
    }
}

DOM.runObjEventHandler = function(event, item) {
    item.handler.call(item.obj, event);
}

DOMUtils = {};

DOMUtils.getValue = function(object) {
    if (object.getValue) {
        return object.getValue();
    } else {
        if (typeof object.value == 'undefined') {
            return object;
        } else if (object.type && object.type == 'checkbox') {
            return object.checked;
        } else {
            return object.value;
        }
    }
}