function jsonPost(url, data)
{
  var req = MochiKit.Async.getXMLHttpRequest();

  try 
  {
    req.open('POST', url, true);
  } 
  catch (err) 
  {
    return MochiKit.Async.fail(err);
  }

  req.setRequestHeader('Content-Type', 'text/x-json');

  return MochiKit.Async.sendXMLHttpRequest(req);
}

function postAndLoad(url, data)
{
  data = queryString(data);
  var req = MochiKit.Async.getXMLHttpRequest();

  try 
  {
    req.open('POST', url, true);
  } 
  catch (err) 
  {
    return MochiKit.Async.fail(err);
  }

  req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  req.setRequestHeader("Content-length", data.length);
  req.setRequestHeader("Connection", "close");

  return MochiKit.Async.sendXMLHttpRequest(req, data);
}

// TODO remove alias with typo
function postAndloadJSONDoc(url, data) {
    return postAndLoadJSONDoc(url, data);
}

function postAndLoadJSONDoc(url, data)
{
  var d = postAndLoad(url, data);
  d = d.addCallback(MochiKit.Async.evalJSONRequest);
  return d;
}

// This function is in MochiKit 1.4 but not 1.3 stable
MochiKit.DOM.getViewportPosition = function () {
    var c = new MochiKit.DOM.Coordinates(0, 0);
    var d = MochiKit.DOM._document;
    var de = d.documentElement;
    var db = d.body;
    if (de && (de.scrollTop || de.scrollLeft)) {
        c.x = de.scrollLeft;
        c.y = de.scrollTop;
    } else if (db) {
        c.x = db.scrollLeft;
        c.y = db.scrollTop;
    }
    return c;
}

MochiKit.DOM.Rectangle = function (x, y, w, h) {
    this.w = w;
    this.h = h;
    this.x = x;
    this.y = y;
};

MochiKit.DOM.Rectangle.prototype.repr = function () {
    var repr = MochiKit.Base.repr;
    return "{x: "  + repr(this.x) + ", y: " + repr(this.y) + ", w: "  + repr(this.w) + ", h: " + repr(this.h) + ", right: " + repr(this.right()) + ", bottom: " + repr(this.bottom()) + "}";
};

MochiKit.DOM.Rectangle.prototype.toString = function () {
    return this.repr();
};

MochiKit.DOM.Rectangle.prototype.top = function () {
    return this.y;
};

MochiKit.DOM.Rectangle.prototype.left = function () {
    return this.x;
};

MochiKit.DOM.Rectangle.prototype.right = function () {
    return this.x + this.w;
};

MochiKit.DOM.Rectangle.prototype.bottom = function () {
    return this.y + this.h;
};

MochiKit.DOM.Rectangle.prototype.setTop = function (top) {
    this.y = top;
};

MochiKit.DOM.Rectangle.prototype.setLeft = function (left) {
    this.x = left;
};

MochiKit.DOM.Rectangle.prototype.setRight = function (right) {
    this.x = right - this.w;
};

MochiKit.DOM.Rectangle.prototype.setBottom = function (bottom) {
    this.y = bottom - this.h;
};

MochiKit.DOM.Rectangle.prototype.isPointInside = function (x, y) {
    return (
        x >= this.left() &&
        x <= this.right() &&
        y >= this.top() &&
        y <= this.bottom()      
    );
};

// Combines two rectangles together
MochiKit.DOM.Rectangle.prototype.union = function (rect) {
    var newRect = this.clone();

    if ( rect.left() < newRect.left() )
    {
        newRect.w = newRect.right() - rect.left()
        newRect.x = rect.left();
    }

    if ( rect.top() < newRect.top() )
    {
        newRect.h = newRect.bottom() - rect.top()
        newRect.y = rect.top();
    }

    if ( rect.right() > newRect.right() )
    {
        newRect.w = rect.right() - newRect.left()
    }

    if ( rect.bottom() > newRect.bottom() )
    {
        newRect.h = rect.bottom() - newRect.top()
    }

    return newRect;
};

MochiKit.DOM.Rectangle.prototype.clone = function (rect) {
    return new MochiKit.DOM.Rectangle(this.x, this.y, this.w, this.h);
};

function getViewportRect()
{
    var position = MochiKit.DOM.getViewportPosition();
    var size     = MochiKit.DOM.getViewportDimensions();

    return new MochiKit.DOM.Rectangle(position.x, position.y, size.w, size.h);
}

function elementRect(element)
{
    var position = MochiKit.DOM.elementPosition(element);
    var size     = MochiKit.DOM.elementDimensions(element);

    return new MochiKit.DOM.Rectangle(position.x, position.y, size.w, size.h);
}

/** @id MochiKit.DOM.insertSiblingNodesBefore */
MochiKit.DOM.insertSiblingNodesBefore = function (node/*, nodes...*/) {
    var elem = node;
    var self = MochiKit.DOM;
    if (typeof(node) == 'string') {
        elem = self.getElement(node);
    }
    var nodeStack = [
        self.coerceToDOM(
            MochiKit.Base.extend(null, arguments, 1),
            elem
        )
    ];
    var parentnode = elem.parentNode;
    var concat = MochiKit.Base.concat;
    while (nodeStack.length) {
        var n = nodeStack.shift();
        if (typeof(n) == 'undefined' || n === null) {
            // pass
        } else if (typeof(n.nodeType) == 'number') {
            parentnode.insertBefore(n, elem);
        } else {
            nodeStack = concat(n, nodeStack);
        }
    }
    return parentnode;
};

insertSiblingNodesBefore  = MochiKit.DOM.insertSiblingNodesBefore;

/** @id MochiKit.DOM.insertSiblingNodesAfter */
MochiKit.DOM.insertSiblingNodesAfter = function (node/*, nodes...*/) {
    var elem = node;
    var self = MochiKit.DOM;

    if (typeof(node) == 'string') {
        elem = self.getElement(node);
    }
    var nodeStack = [
        self.coerceToDOM(
            MochiKit.Base.extend(null, arguments, 1),
            elem
        )
    ];

    if (elem.nextSibling) {
        return self.insertSiblingNodesBefore(elem.nextSibling, nodeStack);
    }
    else {
        return self.appendChildNodes(elem.parentNode, nodeStack);
    }
};

insertSiblingNodesAfter = MochiKit.DOM.insertSiblingNodesAfter;