//********************************************************************
// domfunc.js
// 
// getElementsByClass(node, class, tag)
//   Pretty obvious.  Class and tag are strings that get turned into
//   patterns; tag is optional.
//
// getElementsByTagMatch(node, pattern)
//   Try to guess...
//
// getElementsByAttrMatch(node, attribute, pattern)
//   There is no rocket science in this module.  The pattern is
//   optional; without it, the elements just need to have the
//   attribute defined.
//
// hasClass(element, class)
//   Not too tricky, either.
//
// addClass(element, class)
//   Also fairly obvious.
//
// delClass(element, class)
//   Alles klar?
//
// getStyle(element, property)
//   Pretty obvious.  Use this for computed style values (lengths,
//   pretty much) that can't be gotten directly from the style
//   property.
//
// getStyleStandard(element, property)
//   Standards compliant way of getting a computed style.
//
// getStyleIE(element, property)
//   IE specific way of getting a computed style.
//
//   Author:    Colin J. Wynne <cwynne(at)avtokrator(dot)org>
//   Created:   2006-08-21
//   Version:   (see RCS string below)
//
//********************************************************************
// $Id: domfunc.js,v 1.5 2006/12/14 17:28:49 cwynne Exp $
//********************************************************************

  // Select all elements of a class.
  //   node = parent node from which to search
  //   cls  = class for which to search
  //   tag  = pattern for tag names to include in search.
function getElementsByClass(node, cls, tag) {

    if(!node) node    = document;

    var tagElem   = getElementsByTagMatch(node, tag);
    var classElem = [];

    if( !cls) return tagElem;

    for(i = 0; i < tagElem.length; ++i)
        if( hasClass(tagElem[i], cls) )
            classElem.push( tagElem[i] );

    return classElem;
}

  // Select all descendant elements of a node with a tag name matching
  // a specified pattern or RegExp.
function getElementsByTagMatch(node, pat) {

    if(!node) return [];

      // Short-cut if we get the easy case.
    if(!pat || pat == "*")
        return node.getElementsByTagName("*");
    
      // Make sure we have a RegExp object.
    if(!pat.test) pat = new RegExp(pat);

      // Make pattern case insensitive.
    pat.ignoreCase = true;

    var patElem = [];
    var allElem = node.getElementsByTagName("*");

      // Filter for pattern matches.
    for(i = 0; i < allElem.length; ++i)
        if( pat.test(allElem[i].nodeName) ) patElem.push( allElem[i] );

    return patElem;
}

  // Get descendant elements with an attribute matching a pattern.
function getElementsByAttrMatch(node, attr, pat) {

    if(!node) node = document;
    if(!attr) return [];

      // Make sure we have a RegExp object.
    if(!pat.test) pat = new RegExp(pat);

      // Make pattern case insensitive.
    pat.ignoreCase = true;

    var patElem = [];
    var allElem = node.getElementsByTagName("*");

    for(i = 0; i < allElem.length; ++i) {

        var val = allElem[i].attributes[attr];

        if( val && pat.test(val) ) patElem.push( allElem[i] );
    }

    return patElem;
}

  // See if an element has a specific class.
function hasClass(el, cls) {

    if( !el) return 0;
    if(!cls) return 0;

    var pat = new RegExp("\\b" + cls + "\\b", "i");

    return pat.test( el.className );
}

  // Add a class to an elements className string.
function addClass(el, cls) {

    if( !el) return 0;
    if(!cls) return 0;

    if( el.className )
        el.className = el.className + " " + cls;
    else
        el.className = cls;

    return cls;
}

  // Delete a class from an element's className string.
function delClass(el, cls) {

    if( !el) return 0;
    if(!cls) return 0;

      // Three patterns to test, for when class is (1) not at start of
      // class list, (2) not at end of class list, or (3) the only
      // class in class list.
    var pat1 = new RegExp(  " " + cls + "\\b", "i");
    var pat2 = new RegExp("\\b" + cls +   " ", "i");
    var pat3 = new RegExp("\\b" + cls + "\\b", "i");

    if     ( pat1.test( el.className ) )
        return el.className = el.className.replace(pat1, "");
    else if( pat2.test( el.className ) )
        return el.className = el.className.replace(pat2, "");
    else if( pat3.test( el.className ) )
        return el.className = el.className.replace(pat3, "");

    return 0;
}

    // Get a current style value.  You can give multiple properties in
    // the arg list, to try and test for alternate browser names.
function getStyle(elem, prop) {

    var style = null;
    var i;
        // Return on the first prop we find.
    for(i = 1; i < arguments.length; ++i) {

        if(!style) style = getStyleStandard( elem, arguments[i] );
        if(!style) style = getStyleIE(       elem, arguments[i] );

        if( style) return style;
    }

    return style;
}

  // This method uses the DOM specified defaultView property.
function getStyleStandard(elem, prop) {

    var style;

    if(window.getComputedStyle) {
        style = document.defaultView.getComputedStyle(elem, null);
        style = style.getPropertyValue(prop);

        return style;
    }

    return null;
}

  // This is how IE does computed styles.
function getStyleIE(elem, prop) {

    if(elem.currentStyle)
        return elem.currentStyle[prop];

    return null;
}

//********************************************************************
// END
//********************************************************************
