/*dependencies: 
    content_manager/lib_js/
                            node.js
                            filters.js
*/

function DOM(){
}

/*************************
**DOM BROWSING FUNCTIONS**
**************************/

//MUST disappear!!! beware of confusion
DOM.firstChild=function(elem, tagName){
    var children=elem.childNodes;
    for(var i=0;i<children.length;i++){
        var child=children[i];
        if(child && child.nodeType==Node.ELEMENT_NODE && (!tagName || child.tagName==tagName)){
            return child
        }
    }
    return null;
};

/*TODO: rename to firstChildTag*/
DOM.firstTag=function(elem, filter){
    return DOM.childTagAt(elem, 0, filter);
};
DOM.firstChildTag=DOM.firstTag;

DOM.lastChildTag=function(elem, filter){
    if(!elem || !elem.childNodes)return null;
    var children=elem.childNodes;
    for(var i=children.length - 1;i>=0;i--){
        var child=children[i];
        if(child && child.nodeType==Node.ELEMENT_NODE && (!filter || filter.apply(child)))
            return child;
    }
    return null;
};

DOM.firstChildNode=function(elem, filter){
    return DOM.childNodeAt(elem, 0, filter);
};

DOM.childTagAt=function(elem, pos, filter){
    if(!elem || !elem.childNodes)return null;
    var children=elem.childNodes;
    var count=0;
    for(var i=0;i<children.length;i++){
                
        var child=children[i];
        /*if(elem.id == "tm_1")
            alert("childTagAt: elem_id: " + elem.id + "child_tag: " + child.tagName);*/
        if(child && child.nodeType==Node.ELEMENT_NODE && (!filter || filter.apply(child))){
            
            if(count==pos){
                //alert(child.className);
                return child;
            }
            else
                count++;
        }
    }
    //alert("null");
    return null;
};

DOM.childNodeAt=function(elem, pos, filter){
    if(!elem || !elem.childNodes)return null;
    var children=elem.childNodes;
    var count=0;
    for(var i=0;i<children.length;i++){
        var child=children[i];
        if(child && (!filter || filter.apply(child))){
            if(count==pos)
                return child;
            else
                count++;
        }
    }
    return null;
}

/*
return direct (direct) parent tag
note: filter is optional
*/
DOM.parentTag=function(elem, filter){
    if(elem!=null && elem.nodeType==Node.ELEMENT_NODE){
      do{
        elem=elem.parentNode;
      }while(elem != null && (elem.nodeType!=Node.ELEMENT_NODE || (filter && !filter.apply(elem))));
      return elem;
    }
    return null
};

/*
if no filter => elem itself is returned.
else => dom tree is walked until filter returns true.
note: filter is optional
*/
DOM.ancestorTag=function(elem, filter){
    while(elem!=null && (elem.nodeType!=Node.ELEMENT_NODE || (filter && !filter.apply(elem)))){
        elem = elem.parentNode;
        /*if(elem.nodeType==Node.ELEMENT_NODE)
            alert(elem.tagName + " filter returns " + filter.apply(elem) + " id: " + elem.id);*/
    }
    return elem;
};

/*computes position according to filter*/
DOM.position=function(elem, filter){
    if(!elem || !elem.parentNode)return null;
    var count=-1;
    var children=elem.parentNode.childNodes;
    var nb=children.length;
    for(var i=0;i<=nb;i++){
        var child=children[i];
        if(filter.apply(child))
            count++;
        if(child==elem)
            return count;
    }
    return count;
}

/*return all children tags according to filter*/
DOM.childTags=function(elem, filter){
    var tags=new Array();
    var children=elem.childNodes;
    var nb=children.length;
    for(var i=0;i<nb;i++){
        var child=children[i];
        if(child.nodeType==Node.ELEMENT_NODE && filter.apply(child))
            tags[tags.length]=child;
    }
    return tags;
};

DOM.followingSibling=function(elem, filter){
    do{
            elem=elem.nextSibling;
    }while(elem && (elem.nodeType!=Node.ELEMENT_NODE || (filter && !filter.apply(elem))));
    return elem;
};
DOM.nextSibling=DOM.followingSibling;

DOM.followingSiblingNode=function(elem, filter){
    do{
            elem=elem.nextSibling;
    }while(elem && filter && !filter.apply(elem));
    return elem;
};
DOM.nextSiblingNode=DOM.followingSiblingNode;

DOM.precedingSibling=function(elem, filter){
    do{
            elem=elem.previousSibling;
    }while(elem && (elem.nodeType!=Node.ELEMENT_NODE || (filter && !filter.apply(elem))));
    return elem;
};
DOM.previousSibling=DOM.precedingSibling;

DOM.precedingSiblingNode=function(elem, filter){
    do{
            elem=elem.previousSibling;
    }while(elem && filter && !filter.apply(elem));
    return elem;
};
DOM.previousSiblingNode=DOM.precedingSiblingNode;

/*************************
**DOM QUERYING FUNCTIONS**
**************************/

DOM.fulfills=function(elem, filter){
    return filter.apply(elem);
};

/*****************************
**DOM MANIPULATING FUNCTIONS**
******************************/

DOM.removeClass=function(elem, searchedClass){
    if(elem){
        var classes=elem.className.split(" ");
        var nb=classes.length;
        var newClasses= new Array();
        for(var i=0;i<nb;i++){
            if(classes[i]!=searchedClass)
                newClasses[newClasses.length]=classes[i];
        }
        elem.className=newClasses.join(" ");
    }
};

DOM.addClass=function(elem, searchedClass){
    if(elem){
        var classes=elem.className.split(" ");
        var nb=classes.length;
        var selected=false;
        for(var i=0;i<nb;i++){
            if(classes[i]==searchedClass)
                return ;
        }
        classes[classes.length]=searchedClass;
        elem.className=classes.join(" ");
    }
};

DOM.toggleClass=function(elem, className){
    if(elem){
        if(DOM.fulfills(elem, new Filters.ContainsClass(className)))
            DOM.removeClass(elem, className);
        else
            DOM.addClass(elem, className);
    }
};


DOM.removeChildren=function(elem){
   while (elem.hasChildNodes())
      elem.removeChild(elem.firstChild);
}