Element.addMethods({
    getElementsByAttribute: function(element, attrName, attrValue, multi, index) {
        if (attrValue) {
            attrValue = attrValue.replace(/\|/g,'\\|').replace(/\[/g,'\\[').replace(/\(/g,'\\(').replace(/\+/g,'\\+').replace(/\./g,'\\.').replace(/\*/g,'\\*').replace(/\?/g,'\\?').replace(/\//g,'\\/');
        }
        var
            multi = typeof multi != 'undefined' ? multi: false,
            index = typeof index != 'undefined' ? index: 'all',
            cIterate = element.getElementsByTagName('*'),
            aResponse = [],
            attr,
            re = new RegExp(multi?'\\b'+attrValue+'\\b':'^'+attrValue+'$'),
            i = 0,
            elm;
        while (elm = cIterate.item(i++)) {
            attr = elm.getAttributeNode(attrName);
            if (attr && attr.specified && (!attrValue || attr.value == attrValue || re.test(attr.value)) ) {
                if (index == 'all') {
                    aResponse.push($(elm));
                }
                else if (!index--) {
                    return $(elm);
                }
            }
        }
        if (index == 'all') {
            return aResponse;
        }
        return null;
    },
    getElementByAttribute: function(element, attrName, attrValue, multi, index) {
        index = typeof index != 'undefined' ? index: 0;
        return element.getElementsByAttribute(attrName, attrValue, multi, index);
    },
    getParentsByAttribute: function(element, attrName, attrValue, multi, index) {
        if (attrValue) {
            attrValue = attrValue.replace(/\|/g,'\\|').replace(/\[/g,'\\[').replace(/\(/g,'\\(').replace(/\+/g,'\\+').replace(/\./g,'\\.').replace(/\*/g,'\\*').replace(/\?/g,'\\?').replace(/\//g,'\\/');
        }
        var
            multi = typeof multi != 'undefined' ? multi: false,
            index = typeof index != 'undefined' ? index: 'all',
            aResponse = [],
            attr,
            re = new RegExp(multi?'\\b'+attrValue+'\\b':'^'+attrValue+'$'),
            i = 0,
            elm = element;
        while (elm = elm.parentNode) {
            attr = elm.getAttributeNode(attrName);
            if (attr && attr.specified && (!attrValue || attr.value == attrValue || re.test(attr.value)) ) {
                if (index == 'all') {
                    aResponse.push($(elm));
                }
                else if (!index--) {
                    return $(elm);
                }
            }
            if (elm.nodeName.toLowerCase() == 'html') {
                break;
            }
        }
        if (index == 'all') {
            return aResponse;
        }
        return null;
    },
    getParentByAttribute: function(element, attrName, attrValue, multi, index) {
        index = typeof index != 'undefined' ? index: 0;
        return element.getParentsByAttribute(attrName, attrValue, multi, index);
    },
    getElementsByClassName: function(element, className, index) {
        return element.getElementsByAttribute('class', className, true, index);
    },
    getElementByTagName: function(element, tagName, index) {
        var
            index = typeof index != 'undefined' ? index: 0,
            cIterate = element.getElementsByTagName(tagName),
            i = 0,
            elm;
        while (elm = cIterate.item(i++)) {
            if (!index) {
                return $(elm);
            }
            index--;
        }
        return null;
    }
});
document.getElementsByAttribute = function(attrName, attrValue, multi, index) {
    return $(document.body).getElementsByAttribute(attrName, attrValue, multi, index);
}
document.getElementsByClassName = function(className, index) {
    return $(document.body).getElementsByClassName(className, index);
}


