String.prototype.trim = function() {
  return this.replace(/^\s+|\s+$/g,"");
}

// General hover classes
var Hover = {
  over: function(evt) {
    evt.element().up('tr').addClassName('hover');
  }.bindAsEventListener(),
  
  out: function(evt) {
    evt.element().up('tr').removeClassName('hover');
  }.bindAsEventListener()
};

var Overlay = function() {
  var clickHandler,
      create;
  
  clickHandler = function(evt) {
    evt.element().remove();
    evt.stop();
  }.bindAsEventListener();
  
  create = function(width, height, handler) {          
    var el = new Element('div', {'class': 'overlay'})
      .setStyle({
        'width': width + 'px',
        'height': height + 'px',
        'opacity': .2,
        'background': 'black',
        'position': 'absolute',
        'top': 0,
        'left': 0,
        'cursor': 'pointer',
        'z-index': 10
      })
      .observe('click', clickHandler);
    
    if (Object.isFunction(handler))
      el.observe('click', handler);
    
    return el;
  };
  
  return {
    drawOverDocument: function(handler) {
      var html = $$('html')[0],
          body = $$('body')[0],
          element;

      element = create(html.getWidth(), html.getHeight(), handler);
      body.insert({top: element});
      
      return element;
    },
    
    drawOver: function(container, handler) {
      var element;
      
      container = $(container);
      
      element = create(container.getWidth(), container.getHeight(), handler);
      container.insert({bottom: element});
      
      return element;
    }
  }
}(); // Execute the function immediately - results in a singleton

Function.prototype.memoize = function() {
  var func = this;
  return function() {
    var output = func();
    func = function() { return output; }
    return func();
  };
};

Event.delegate = function(rules) {
  return function(e) {
    var element = $(e.element());
    for (var selector in rules)
    if (element.match(selector)) return rules[selector].apply(this, $A(arguments));
  }
};

Element.addMethods('SELECT', {
  setValue: function(element, value) {
    var success = false;
    element = $(element);
    element.select('option').each(function(option, index) {
      if (option.value == value) {
        element.selectedIndex = index;
        success = true;
        throw $break;
      }
    });
    return success;
  }
});

function getCurrentURI() {
  return matchURI(window.location.href);
}

function matchURI(uri) {
  return (uri.match(/^http:\/\/.+?(\/.+?(\?.*)?)?$/)[1] || '/');
}

// base target aware js redirect
function redirectTo(url, base_target_aware) {
  if (typeof(base_target_aware) == 'undefined') {
    base_target_aware = true;
  }

  if (!base_target_aware) {
    window.location.href = url;
  }
  else {
    var $base = $$('base')[0];
    if (!$base) {
      window.location.href = url;
    }
    else {
      var target = $base.readAttribute('target'); 
      if (target == '_blank') {
        window.open(url);
      }
      else if (target == '_top') {
        if (window.top) {
          window.top.location = url;
        }
        else { // HACK: load within current frame if has no access to top-most frame
          window.location.href = matchURI(url)
        }
      }
    }
  }
}

