/*
Version: 2.3: Fixes to addClassName() and removeClassName()
Version: 2.2: New function: removeCSSFile() Removes a CSS-file
Version: 2.1: New function: addCSSFile() Loads a CSS-file
Version: 2.0: New function: hasClassName() Checks whether an element has at least one of specified classNames.
Version: 1.9: getElementsByTagAndType - now accepts Array for type parameter. addClassName-fix.
Version: 1.8: New function: Added createInput (cross-browser create input method)
Version: 1.7: New functions: getSubFakeArguments(), searchForWholeWords() (used in getElementsByClassFrom()
Version: 1.6: Converted to class + New functions: getUniqueContainerWithItems(), addClassName(), moveChildren();
Version: 1.5: getElementsByClass + TagName - now accepts Array for classAttribute and tagName parameters.
Version: 1.4: getKin() - added className-parameter
Version: 1.3: New functions: moveContent(), checkByName() and IE:fix: changed for(in)-loop
Version: 1.2: New function: getFakeClassArguments()
*/

var Utilities = {
  debug : false,
  debugPreString : "c_utilities.js: ",
  debugPostString : "-error: ",

  //getElements-methods
  getElementsByClassAndTagName : function(classAttribute, tagName, element, allowMultipleClasses, onlyFirst, wholeWordSearch) {
      try {
      	if (typeof(classAttribute) == "string") classAttribute = new Array(classAttribute);
  	    if (typeof(tagName) == "string") tagName = new Array(tagName);
        var elements = new Array();
        for(var i=0; i<tagName.length; i++) {
          var tags;
          if(element == undefined) tags = document.getElementsByTagName(tagName[i]);
          else tags = element.getElementsByTagName(tagName[i]);
          for(var x=0; x<tags.length; x++) elements.push(tags[x]);
        }
        return Utilities.getElementsByClassFrom(elements, classAttribute, allowMultipleClasses, onlyFirst, wholeWordSearch);
      }
      catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "getElementsByClassAndTagName" + Utilities.debugPostString + err);}
  },
  
  getElementsByClassFrom : function(elementsArray, classAttribute, allowMultipleClasses, onlyFirst, wholeWordSearch) {
      if (typeof(classAttribute) == "string") classAttribute = new Array(classAttribute);
      if(allowMultipleClasses == undefined) allowMultipleClasses = true;
      if(wholeWordSearch == undefined) wholeWordSearch = false;
      if(onlyFirst == undefined) onlyFirst = false;
      var elementsInClass = new Array();
      try {
        for(var i=0; i<elementsArray.length; i++) {
            //alert("type: " + elementsArray[i].type + "className: " + elementsArray[i].className + "nodeName: " + elementsArray[i].nodeName + "tagName: " + elementsArray[i].tagName);
            if(elementsArray[i].nodeName != undefined) {
                var elementClass;
                if(elementsArray[i].className) {
                    elementClass = elementsArray[i].className;
                    for(var x=0; x<classAttribute.length; x++) {
                      if(elementClass.indexOf(classAttribute[x]) != -1) {
                          if(allowMultipleClasses || elementClass == classAttribute[x]) {
                            if(!wholeWordSearch || Utilities.searchForWholeWords(elementClass, classAttribute[x])) {
                              elementsInClass.push(elementsArray[i]);
                              if(onlyFirst) return elementsInClass;
                              else break;
                            }
                          }
                      }
                    }
                }
            }
        }
      }
      catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "getElementsByClassFrom" + Utilities.debugPostString + err);}
      return elementsInClass;
  },
  
  getElementsByTagAndType : function(tag, type, elements) {
      var typeElements = new Array();
      try {
        if (typeof(type) == "string") type = new Array(type);
        if(elements == undefined) elements = document;
        var tagElements = elements.getElementsByTagName(tag);
        for(var i=0; i < tagElements.length; i++) {
          for(var x=0; x < type.length; x++) {
            if(tagElements[i].type == type[x]) typeElements.push(tagElements[i]);
          }
        }
      } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "getElementsByTagAndType" + Utilities.debugPostString + err);}
      return typeElements;
  },
  
//CSS-ClassName functions
  getFakeClassArguments : function(element, className) {
      try {
        fakeArguments = new Array();
        if(element.className) {
          var classStartIndex = element.className.indexOf(className);
          var classEndIndex = element.className.indexOf(" ", classStartIndex);
          var fakeArgumentClassString;
          if(classEndIndex == -1) fakeArgumentClassString = element.className.substring(classStartIndex);
          else fakeArgumentClassString = element.className.substring(classStartIndex, classEndIndex);
          fakeArguments = fakeArgumentClassString.split("_");
        }
        return fakeArguments;
      } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "getFakeClassArguments" + Utilities.debugPostString + err);}
  },
  
  setFakeClassArguments : function(element, className, arguments) {
      try {
        var fakeArgumentClassString = className;
        for(var i=0; i<arguments.length; i++) {
          fakeArgumentClassString += ("_" + arguments[i]);        
        }
        if(element.className == "") element.className = fakeArgumentClassString;
        else element.className += (" " + fakeArgumentClassString);
      } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "setFakeClassArguments" + Utilities.debugPostString + err);}  
  },

  getSubFakeArguments : function(fakeargument) {
    var subArguments = new Array(fakeargument);
    try {
        if(fakeargument.indexOf("-") != -1) subArguments = fakeargument.split("-");
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "getSubFakeArguments" + Utilities.debugPostString + err);}  
    return subArguments;  
  },
  
  addClassName : function(element, newClassName) {
      try {
        if (typeof(newClassName) == "string") newClassName = new Array(newClassName);
        for(var i=0; i<newClassName.length; i++) {
          if(element.className == "") element.className = newClassName[i];
          else if(element.className.indexOf(" " + newClassName[i]) == -1 &&
                  element.className.indexOf(newClassName[i] + " ") == -1
          ) element.className += " " + newClassName[i];
          //In other cases the element className already is equal to newClassName[x] and needn't be changed.
        }
      } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "addClassName" + Utilities.debugPostString + err);} 
  },
  
  removeClassName : function(element, className) {
    try {
      if (typeof(className) == "string") className = new Array(className);
        for(var i=0; i<className.length; i++) {
          var classNames = new RegExp("\\b" + className[i] + "\\b", "g");
          element.className = element.className.replace(classNames, "");
          var multipleSpaces = /\s\s+|\s/;
          element.className = element.className.replace(multipleSpaces, " ");
        }
      } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "removeClassName" + Utilities.debugPostString + err);} 
  },
  
  hasClassName : function(element, className) {
      try {
        if (typeof(className) == "string") className = new Array(className);
        for(var i=0; i<className.length; i++) {
          if(element.className.indexOf(className[i]) != -1) {
            return true;
          }
        }          
        return false;
      } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "hasClassName" + Utilities.debugPostString + err); return false; } 
  },
  
  addCSSFile : function(href) {
      try {  
        var head = document.getElementsByTagName("head")[0];      
        var cssLink = document.createElement('link');
        cssLink.type = 'text/css';
        cssLink.rel = 'stylesheet';
        cssLink.href = href;
        cssLink.media = 'screen';
        head.appendChild(cssLink);
      } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "addCSSFile" + Utilities.debugPostString + err); } 
  },
  removeCSSFile : function(href) {
      try {  
        var links = document.styleSheets;
        var cssLink = null;
      	for(var i=0; i<links.length; i++) {
      	  if(links[i].href && links[i].href.indexOf(href) != -1) {
            cssLink = links[i];
            break;
          }
      	}
      	if(cssLink) {
          cssLink.disabled = true;
          if(cssLink.ownerNode) cssLink.ownerNode.removeChild(cssLink);
          else if (cssLink.owningElement) cssLink.owningElement.removeChild(cssLink);
        }
      } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "removeCSSFile" + Utilities.debugPostString + err); } 
  },
  
  getActualStyleValue : function(element, cssStyleName, jsStyleName) {
      var styleValue = null;
      try {
      	if (element.currentStyle) styleValue = element.currentStyle[jsStyleName];
      	else if (window.getComputedStyle) styleValue = getComputedStyle(element,null).getPropertyValue(cssStyleName);
      } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "getActualStyleValue" + Utilities.debugPostString + err); } 
    	return styleValue;
  },

  //DOM-methods
  createNamedElement : function(type, name) {
     var element = null;
     // Try the IE way; this fails on standards-compliant browsers
     try {
        element = document.createElement('<'+type+' name="'+name+'">');
     } catch (e) {
     }
     if (!element || element.nodeName != type.toUpperCase()) {
        // Non-IE browser; use canonical method to create named element
        element = document.createElement(type);
        element.name = name;
     }
     return element;
  },

  createInput : function(type, name) {
     var element = null;
     // Try the IE way; this fails on standards-compliant browsers
     try {
        element = document.createElement('<input type="'+type+'" name="'+name+'">');
     } catch (e) {
     }
     if (!element || element.nodeName != "INPUT") {
        // Non-IE browser; use canonical method to create named element
        element = document.createElement("INPUT");
        element.type = type;
        element.name = name;
     }
     return element;
  },
  
  getTwin : function(element, direction, tagName, type) {
    try {
      if(tagName == undefined) tagName = element.tagName;
      if(type == undefined) type = null;
      var twin = element;
      while(twin) {
        if(direction == "next") twin = twin.nextSibling;
        else twin = twin.previousSibling;
        if(!twin) break;
        if(type) {
          if(twin.tagName == tagName && twin.type == type) break;
        }
        else {
          if(twin.tagName == tagName) break;
        }
      }
      return twin; 
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "getTwin" + Utilities.debugPostString + err);}
  },
  
  getKin : function(element, direction, tagName, className, stepLimit) {
    try {
      if(stepLimit == undefined) stepLimit = -1;
      if(tagName == undefined) tagName = element.tagName;
      var steps = 0;
      var kin = element;
      while(kin) {
        if(direction == "next") kin = kin.nextSibling;
        else if(direction == "previous") kin = kin.previousSibling;
        else if(direction == "child") { kin = kin.firstChild; direction = "next"; }
        else if(direction == "firstChild") kin = kin.firstChild;
        else if(direction == "lastChild") kin = kin.lastChild;
        else if(direction == "parent") kin = kin.parentNode;
        else kin = kin.previousSibling;
  
        if(!kin) break;
        
        if(kin.tagName == tagName && className == undefined) break;
        else if((kin.tagName == tagName || tagName == "#") && kin.className == className && className != undefined) break;
        
        steps++;
        if(stepLimit != -1 && steps >= stepLimit) return null;
      }
      return kin; 
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "getTwin" + Utilities.debugPostString + err);}
  },
  
  moveChildren : function(srcEl, destEl) {
    try {
      while (srcEl.hasChildNodes()) {  
          var child = srcEl.childNodes[0];  
          destEl.appendChild(child);  
      }
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "moveChildren" + Utilities.debugPostString + err);} 
  },
  
  //switch-methods
  switchElements : function(element, otherElement) {
    try {
      var parent = element.parentNode;
      var element_clone=element.cloneNode(true);
      var otherElement_clone=otherElement.cloneNode(true);
      var elementTemp = parent.insertBefore(element_clone,element);
      var otherElementTemp = parent.insertBefore(otherElement_clone,otherElement);
      parent.replaceChild(element, otherElementTemp);
      parent.replaceChild(otherElement, elementTemp);
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "switchElements" + Utilities.debugPostString + err);}
  },
  
  
  switchInnerHTML : function(element, otherElement) {
    try {
      var element_html = element.innerHTML;
      var otherElement_html = otherElement.innerHTML;
      otherElement.innerHTML = element_html;
      element.innerHTML = otherElement_html;
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "switchInnerHTML" + Utilities.debugPostString + err);}
  },
  
  switchValues : function(element, otherElement) {
    try {
      var element_value = element.value;
      var otherElement_value = otherElement.value;
      otherElement.value = element_value;
      element.value = otherElement_value;
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "switchValues" + Utilities.debugPostString + err);}
  },
  
  moveContent : function(contentId, destinationContainerId) {
    try {
      var content = document.getElementById(contentId);
      var destination = document.getElementById(destinationContainerId);
      if(content && destination) {
        destination.appendChild(content);    
      }
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "moveContent" + Utilities.debugPostString + err);}
  },
  
  //input-methods
  checkIfEmpty : function(inputElements) {
    try {
      var isEmpty = true;
      for(var i=0; i<inputElements.length; i++) {
        if(inputElements[i].value != "") {
            isEmpty = false;
            break;
        }
      }
      return isEmpty;
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "switchValues" + Utilities.debugPostString + err);}
  },
  
  checkIfChecked : function(inputElements) {
    try {
      var isChecked = false;
      var length = inputElements.length;
      for(var i=0; i<length; i++) { 
        if(inputElements[i].checked) {
            isChecked = true;
            break;
          }
      }
      return isChecked;
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "checkIfChecked" + Utilities.debugPostString + err);}
  },
  
  checkHowManyChecked : function(inputElements) {
    try {
      thisMany = 0;
      for(var i=0; i < inputElements.length; i++) { 
        if(inputElements[i].checked) thisMany++;
      }
      return thisMany;
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "checkHowManyChecked" + Utilities.debugPostString + err);}
  },
  
  returnChecked : function(inputElements) {
    try {
      var checkedInputs = new Array();
      for(var i=0; i < inputElements.length; i++) {
        if(inputElements[i].checked) checkedInputs.push(inputElements[i]);
      }
      return checkedInputs;
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "returnChecked" + Utilities.debugPostString + err);}
  },
  
  uncheckAll : function(inputElements) {
    try {
      for(var i=0; i < inputElements.length; i++) { 
        inputElements[i].checked = false;
      }
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "uncheckAll" + Utilities.debugPostString + err);}
  },
  
  checkByName : function(name, value, checked) {
    try {
      if(checked==undefined) checked = true;
      var elements = document.getElementsByName(name);
      if(elements.length > 1) {
        for(var i=0; i<elements.length; i++) {
          if(elements[i].value == value) {
            
            elements[i].checked = checked;
            break;
          }
          else if(value=="all") elements[i].checked = checked;
        }
      }
      else if (elements.length == 1 && value == undefined) {
        elements[0].checked = checked;
      }
      else if (value != undefined) {
        checkByName(name + "." + value, undefined, checked);
      }
      return true;
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "getTwin" + Utilities.debugPostString + err);}  
  },
  
  //Event-methods
  getEventTarget : function(e) {
    try {
      var targ;
      if (!e) var e = window.event;
      if (e.target) targ = e.target;
      else if (e.srcElement) targ = e.srcElement;
      if (targ.nodeType == 3) // defeat Safari bug
      targ = targ.parentNode;
      return targ;
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "getEventTarget" + Utilities.debugPostString + err);}
  },
  
  addEvent : function( obj, type, fn )
  {
  	if (obj.addEventListener)
  		obj.addEventListener( type, fn, false );
  	else if (obj.attachEvent)
  	{
  		obj["e"+type+fn] = fn;
  		obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
  		obj.attachEvent( "on"+type, obj[type+fn] );
  	}
  },
  
  removeEvent : function( obj, type, fn )
  {
  	if (obj.removeEventListener)
  		obj.removeEventListener( type, fn, false );
  	else if (obj.detachEvent)
  	{
  		obj.detachEvent( "on"+type, obj[type+fn] );
  		obj[type+fn] = null;
  		obj["e"+type+fn] = null;
  	}
  },
  
  //mathematical-methods
  isBetween : function(value, a, b) {
    try {
      return (value >= a && value <= b);
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "isBetween" + Utilities.debugPostString + err);}
  },
  
  //Array-methods
  getMatrixColumn : function(matrix, columnNumber) {
    try {
      var columnArray = new Array();
      for(var i=0; i<matrix.length; i++) {
        if(matrix[i].length > columnNumber) columnArray.push(matrix[i][columnNumber]);  
      }
      return columnArray;
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "getMatrixColumn" + Utilities.debugPostString + err);}  
  },
  
  getUniqueContainerWithItems : function(items, containerTagName, subContainerTagName, stepLimit) {
    try {
      var uniqueContainers = new Array();
      var currentContainer;
      var currentSubContainer;
      for(var i=0; i<items.length; i++) {
         var itemContainer = Utilities.getKin(items[i], "parent", containerTagName, undefined, stepLimit);
         if(itemContainer) {
           if(itemContainer != currentContainer || !currentContainer) {
             var subContainers = new Array();
             currentSubContainer = Utilities.getKin(items[i], "parent", subContainerTagName);
             currentContainer = Utilities.getKin(items[i], "parent", containerTagName);
             subContainers.push(currentSubContainer);
             uniqueContainers.push(subContainers);              
           }
           else {
             var itemSubContainer = Utilities.getKin(items[i], "parent", subContainerTagName);
             if(currentSubContainer != itemSubContainer) {
                uniqueContainers[uniqueContainers.length-1].push(itemSubContainer);
                currentSubContainer = itemSubContainer;
              }
           }
         }
      }
      return uniqueContainers;
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "getUniqueContainerWithItems" + Utilities.debugPostString + err);}  
  },
  
  searchForWholeWords : function(string, searchFor) {
    try {
        var re = new RegExp("\\b" + searchFor + "\\b");
        return string.match(re);
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "wholeWordSearch" + Utilities.debugPostString + err); return null;}
  },
  
  capitalize : function(string) {
    try {
      return string.substr(0,1).toUpperCase() + string.substr(1).toLowerCase();
    } catch(err) {if(Utilities.debug) alert(Utilities.debugPreString + "capitalize" + Utilities.debugPostString + err); return null;}
  } 
};
