if (typeof Element != 'undefined') Object.extend(Element, {
  /**
    Sets the opacity of an element in a browser independent fashion.
    Arguments are:
     - element: DOM node or ID of the element to change the opacity of
     - opacity: value between 0 (fully transparent) and 1 (fully opaque). Setting
         this to '' will remove the opacity settings, which is necessary to fix
         some display problems in IE
  */
  setOpacity: function(element, value) {
    if (value === '') {
      $(element).style[is_ie ? 'filter' : 'opacity'] = '';
      return;
    }
    
    with($(element).style) {
      if (is_ie)  filter = 'alpha(opacity=' + (value * 100) + ')';
      if (!is_ie) opacity = value;
    }
  },
  
  /**
    Returns the position of 'element' on the page.
  */
  getPosition: function(element) {
    element = $(element);
    
    var position = {
      x: element.offsetParent ? element.offsetLeft : 0,
      y: element.offsetParent ? element.offsetTop  : 0
    }
    
    while (element = element.offsetParent) {
      position.x += element.offsetLeft;
      position.y += element.offsetTop;
    }
    
    return position;
  },
  
  /**
    Toggles a className in element's class attribute. Arguments are:
     - element: DOM node or ID to toggle the class of
     - className: Class name to toggle
     - altClassName: Optional. If present, className will be replaced by this
    Returns boolean value indicating if className is currently in element's class
  */
  toggleClassName: function(element, className, altClassName) {
    var altClassName = altClassName || '';
    var hasClass = Element.hasClassName(element, className);
    Element[hasClass ? 'removeClassName' : 'addClassName'](element, className);
    Element[hasClass ? 'addClassName' : 'removeClassName'](element, altClassName);
    return !hasClass;
  },
  
  /**
    Finds all elements that are descents of 'element', are of type 'tag', and
    have 'className' in their class attribute
  */
  getByTagClass: function(element, tag, className) {
    return $A(element.getElementsByTagName(tag)).findAll(function(e) {
      return Element.hasClassName(e, className);
    });
  }
});

if (typeof Ajax != 'undefined') {
  Object.extend(Ajax, {
    /**
      Converts 'param_hash' to a string that can be used in Ajax.Request and
      Ajax.Updater calls.
    */
    parameters: function(param_hash) {
      var params = [];
      Hash._each.call(param_hash, function(pair) { params.push(pair.join('=')); });
      return params.join('&');
    }
  });
  
  Ajax.AdvancedPeriodicalUpdater = Class.create();
  Object.extend(Ajax.AdvancedPeriodicalUpdater.prototype, Ajax.PeriodicalUpdater.prototype);
  Object.extend(Ajax.AdvancedPeriodicalUpdater.prototype, {
    parent: Ajax.PeriodicalUpdater.prototype,
    
    // If 'url' is a function, then it will be called on every update. Its
    // return value will be used as the URL to request.
    initialize: function(container, url, options) {
      this.orig_url = url;
      this.parent.initialize.call(this, container, url, options)
    },
    
    start: function() {
      this.status = true;
      this.parent.start.call(this);
    },
    
    stop: function() {
      this.status = false;
      this.parent.stop.call(this);
    },
    
    onTimerEvent: function() {
      if (!this.status) return;
      
      if (typeof this.orig_url == 'function') this.url = this.orig_url();
      this.parent.onTimerEvent.call(this);
    },
    
    updateComplete: function(request) {
      if (!this.status) return;
      this.parent.updateComplete.call(this, request);
    },
    
    oneShot: function() {
      if (!this.status) {
        this.status = true;
        this.onTimerEvent();
        this.status = false;
      } else {
        this.stop(); this.start();
      }
    },
    
    running: function() { return this.status; }
  });
}

Object.extend(String.prototype, {
  limit: function(length) {
    return this.length <= length ? this : (this.substring(0, length) + '...');
  },
  
  inspect: function() {
    return '"' + this.replace('\\', '\\\\').replace('"', '\\\"') + '"';
  }
});

Object.compose = function() {
  for (var i=1; i<arguments.length; i++)
    arguments[0] = Object.extend(arguments[0], arguments[i]);
  return arguments[0];
}
