imos.element = function (element) {
    element = $(element);
    var extendedElement = imos.Object.extend(element, imos.element.prototypes.HTMLDOMElement);
    return imos.Object.extend(extendedElement, imos.element.getPrototype(element));
}
imos.element.getPrototype = function (element) {
    if (typeof element.tagName == 'undefined') {
        return {};
    }
    switch(element.tagName.toLowerCase()) {
        case 'input':
            return imos.element.prototypes['HTMLInputElement']();
        case 'select':
            return imos.element.prototypes['HTMLSelectElement'](element);
        case 'textarea':
            return imos.element.prototypes['HTMLTextAreaElement'];
        case 'option':
            return imos.element.prototypes['HTMLOptionElement'](element);
    }
    return {};
}

imos.element.prototypes = {};
imos.element.prototypes.HTMLDOMElement = {
    addEvent: function (onEvent, cbFunction) {
        if (typeof window.addEventListener != 'undefined') {

            this.addEventListener(onEvent, function(event) { cbFunction(event, this); }, false);
        } else {
            var nodeName = typeof this.tagName != 'undefined'?this.tagName:null;
            this.attachEvent('on' + onEvent, function(event) {
                    cbFunction(event, nodeName == null || event.srcElement.tagName == nodeName?event.srcElement:imos.element(event.srcElement).parentNodeByTagName(nodeName))
                }
            );
        }
    },
    parentNodeByTagName: function (nodeName) {
        var element = this.parentNode;
        while(element.nodeName.toLowerCase() != 'html') {
            if (element.nodeName.toLowerCase() == nodeName.toLowerCase()) {
                return imos.element(element);
            } else {
                element = element.parentNode;
            }
        }
        return null;
    },
    childNodesByTagName: function (tagName) {
        var result = [];
        var childs = this.childNodes;
        for (var i = 0; i < childs.length; i++) {
            if (typeof childs[i].tagName != 'undefined' && childs[i].tagName.toLowerCase() == tagName.toLowerCase()) {
                result.push(childs[i]);
            }
        }
        return result;
    },
    nextSiblingByTagName: function (nodeName) {
        var element = this.nextSibling;
        while (element != null) {
            if (element.nodeName.toLowerCase() == nodeName.toLowerCase()) {
                return imos.element(element);
            } else {
                element = element.nextSibling;
            }
        }
        return null;
    },
    previousSiblingByTagName: function (nodeName) {
        var element = this.previousSibling;
        while (element != null) {
            if (element.nodeName.toLowerCase() == nodeName.toLowerCase()) {
                return imos.element(element);
            } else {
                element = element.previousSibling;
            }
        }
        return null;
    },
    siblingByIndex: function (index) {

        if (index > 0) {
            var sibling = this.nextSiblingByTagName(this.tagName);
            if (sibling == null) {
                return this;
            }
            for (var i = 1; i < index; i++) {
                if ((tmpSibling = sibling.nextSiblingByTagName(this.tagName)) != null) {
                    //sibling = tmpSibling;
                }
            }
        } else if(index < 0) {
            var sibling = this.previousSiblingByTagName(this.tagName);
            if (sibling == 0) {
                return this;
            }
            for (var i = -1; i > index; i--) {
                if ((tmpSibling = sibling.previousSiblingByTagName(this.tagName)) != null) {
                    sibling = tmpSibling;
                }
            }
        } else {
            return this;
        }
        return sibling;
    },
    hide: function() {
        this.style.display = 'none';
    },
    show: function() {
        this.style.display = '';
    }

}
imos.element.prototypes.HTMLInputElement = function() {
    return {};
}
imos.element.prototypes.HTMLSelectElement = function (element){
    var prototype = {};
    if (element.multiple) {
        prototype.selectAll = function() {
            var options = this.getElementsByTagName('option');
            for (i = 0; i < options.length; i++) {
                options[i].selected = true;
            }
        }
        prototype.selectedElements = function() {
            var elementList = [];
            var options = this.getElementsByTagName('option');
            for (i = 0; i < options.length; i++) {
                if (options[i].selected) {
                    elementList.push(imos.element(options[i]));
                }
            }
            return elementList;
        }
    }
    if (!element.multiple) {
        prototype.selectedElement = function() {
            return imos.element(this.getElementsByTagName('option')[this.selectedIndex]);
        }
    }
    return prototype;
}
imos.element.prototypes.HTMLOptionElement = function (element) {
    var prototype = {};
    prototype.toString = function () {
        return '[imos.option]';
    }
    prototype.moveUp = function () {
        var select = imos.element(this.parentNodeByTagName('select'));
        var options = this.getElementsByTagName('option');
        var sibling = this.previousSiblingByTagName('option');
        if (sibling != null) {
            select.insertBefore(this, sibling);
        }
    }
    prototype.moveDown = function () {
        var index = typeof arguments[0] != 'undefined'?arguments[0]:1;
        var sibling = this.siblingByIndex(index);
        var select = imos.element(this.parentNodeByTagName('select'));
        if (sibling != null) {
            select.insertBefore(this, sibling.nextSiblingByTagName('option'));
        } else {
            //alert('foo');
        }
    }
    return prototype;
}
imos.element.prototypes.HTMLTextAreaElement = function() {
    return {}
}


