/**
 * ElementMaxHeight class
 */
var ElementMaxHeight = function() {
  this.initialize.apply(this, arguments);
}

/**
 * ElementMaxHeight class methods
 */
ElementMaxHeight.prototype = {
	/**
	 * Constructor
	 */
  initialize: function(className) {
    this.elements = document.getElementsByClassName(className || 'maxheight');

    this.textElement = document.createElement('span');
    this.textElement.appendChild(document.createTextNode('A'));
    this.textElement.style.display = 'none';
    this.textElement.style.position = 'absolute';
    this.textElement.style.fontSize = '1em';
    document.body.appendChild(this.textElement);
    this.textElementHeight = document.getDimensions(this.textElement).height;

    this.checkFontSizeInterval = window.setInterval(this.checkFontSize.bind(this), 500);

    this.expand();
        
    // Refresh elements height onResize event
    if (window.addEventListener) {
      window.addEventListener('resize', this.expand.bindAsEventListener(this), false);
    } else if (window.attachEvent) {
      window.attachEvent('onresize', this.expand.bindAsEventListener(this));
    }
  },


  /**
   * Expand elements verticaly to it's parent
   * using style.height
   */
  expand: function() {
  	this.reset();
  	for (var i = 0; i < this.elements.length; i++) {  	
      this.elements[i].style.height = document.getDimensions(this.elements[i].parentNode).height + 'px';
  	}
  },

  /**
   * Set elements style.height to auto
   */
  reset: function() {
    for (var i = 0; i < this.elements.length; i++) {    
      this.elements[i].style.height = 'auto';
    }
  },
  
  checkFontSize: function() {
  	var height = document.getDimensions(this.textElement);
  	if(this.textElementHeight != height) {
  		this.textElementHeight = height;
  		this.expand();
  	}
  }
}


/******************************************************************************
 *  DOM Extensions from Prototype lib [ http://prototypejs.org ]
 ******************************************************************************/

/**
 * Change functions context when called as event handler
 * see http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Function:apply
 */
Function.prototype.bindAsEventListener = function(object) {
  var __method = this;
  return function(event) {
    return __method.apply(object, [( event || window.event)]);
  }
}

/**
 * Change functions context
 * see http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Function:apply
 */
Function.prototype.bind = function(object) {
  var __method = this;
  var args = arguments;
 return function() {
    return __method.apply(object);
  }
}

/**
 * Opera bug fix for Array.concat
 */
if(window.opera){
  Array.prototype.concat = function(){
    var array = [];
    for(var i = 0, length = this.length; i < length; i++) array.push(this[i]);
    for(var i = 0, length = arguments.length; i < length; i++) {
      if(arguments[i].constructor == Array) {
        for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
          array.push(arguments[i][j]);
      } else {
        array.push(arguments[i]);
      }
    }
    return array;
  }
}


/**
 * Return element by XPath expression
 * for browsers with XPath support  
 */
if (!!document.evaluate) {
  document._getElementsByXPath = function(expression, parentElement) {
    var results = [];
    var query = document.evaluate(expression, parentElement || document,
      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    for (var i = 0, length = query.snapshotLength; i < length; i++)
      results.push(query.snapshotItem(i));
    return results;
  }
}

/**
 * Returns true if element has className
 */
document.hasClassName = function(element, className) {
  var elementClassName = element.className;
  if (elementClassName.length == 0) return false;
  if (elementClassName == className ||
      elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
    return true;
  return false;
}


/**
 * Return element by class name
 */
document.getElementsByClassName = function(className, parentElement) {
  if (!!document.evaluate) {
    var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
    return document._getElementsByXPath(q, parentElement);
  } else {
    var children = (parentElement || document.body).getElementsByTagName('*');
    var elements = [], child;
    for (var i = 0, length = children.length; i < length; i++) {
      child = children[i];
      if (document.hasClassName(child, className))
        elements.push(child);
    }
    return elements;
  }
}


/**
 * Returns elements width and height in px
 */
document.getDimensions = function (element) {
  var display = element.style.display;
  if (display != 'none' && display != null) // Safari bug
    return {width: element.offsetWidth, height: element.offsetHeight};

  // All *Width and *Height properties give 0 on elements with display none,
  // so enable the element temporarily
  var els = element.style;
  var originalVisibility = els.visibility;
  var originalPosition = els.position;
  var originalDisplay = els.display;
  els.visibility = 'hidden';
  els.position = 'absolute';
  els.display = 'block';
  var originalWidth = element.clientWidth;
  var originalHeight = element.clientHeight;
  els.display = originalDisplay;
  els.position = originalPosition;
  els.visibility = originalVisibility;
  return {width: originalWidth, height: originalHeight};
}