/* Copyright (c) 2006 Xprima.com Corporation, All Rights Reserved */

/*
============================= Notes ================================
Author(s):
  Francis Caporuscio

Dependencies:
  XLib
  YAHOO
  YAHOO.util.Dom
  YAHOO.util.Event
  YAHOO.util.Easing
  YAHOO.util.Anim
  YAHOO.util.Motion
====================================================================
*/

//
// XObjectManager
//
XObjectManager_Counter = 0;
XObjectManager_inProgress = false;
XObjectManager_managerList = [];

function XObjectManager_findObject(objType, id) {
  // this will return the first match... it is possible that two managers contain the same ids... so we need to be careful.
  var o = null;
  for(var i = 0; o == null && i < XObjectManager_managerList.length; i++) {
    o = XObjectManager_managerList[i].findObject(objType, id);
  }
  return o;
};

var $fo=function(o,i){return XObjectManager_findObject(o,i)};

var XObjectManager = function(containerid, params) {
  this.container = $e(containerid);
  this.selectedObjects = [];
  this.className = (params != null && params.className != null) ? params.className : "";
  this.maxitems = (params != null && params.maxitems != null) ? params.maxitems : 6;
  this.columns = (params != null && params.columns != null) ? params.columns : 2;
  this.moveSpeed = (params != null && params.moveSpeed != null) ? params.moveSpeed : 0.25;
  this.onSelect = (params != null && params.onSelect != null) ? params.onSelect : null;
  this.onUnselect = (params != null && params.onUnselect != null) ? params.onUnselect : null;
  
  this.container_root = "XObj" + XObjectManager_Counter.toString() + "C";
  XObjectManager_Counter++;

  if(this.container != null)
    this.init();
  XObjectManager_managerList.push(this);
};

XObjectManager.prototype = {
  findObject: function(objType, id) {
    var s = this.selectedObjects;
    for(var i = 0; i < s.length; i++) {
      if(s[i].prototype.objType == objType && s[i].id == id)
        return s[i];
    }
    return null;
  },
  
  init: function() {
    if(XLib.browserInfo.browserSupported) {
      containerWidth = parseInt(YAHOO.util.Dom.getStyle(this.container, "width") || 0);
      if(isNaN(containerWidth)) {
        containerWidth = parseInt(YAHOO.util.Dom.getStyle(this.container.parentNode, "width") || 0);
        if(isNaN(containerWidth)) {
          containerWidth = 136;
        }
      }
    }
    else {
      containerWidth = 136;
    }
    
    table = document.createElement("table");
    table.className = this.className;
    table.setAttribute("cellpadding", "0");
    table.setAttribute("cellspacing", "0");
    table.setAttribute("border", "0");
    
    if(XLib.browserInfo.browserSupported) {
      XLib.applyStyles(table, { border:"0", width:containerWidth + "px", padding:"4px" });
    }
    
    var tdnodes = new Array();
    for(var i = 0; i < this.maxitems; i++) {
      var td = document.createElement("td");
      td.className = this.className;
      
      td.setAttribute("id", this.container_root + (i + 1).toString());
      
      if(XLib.browserInfo.browserSupported) {
        YAHOO.util.Dom.setStyle(td, "width", (containerWidth / this.columns).toString() + "px");
      }
      
      tdnodes.push(td);
      
      if((i + 1) % this.columns == 0 || i == this.maxitems - 1) {
        var tr = document.createElement("tr");
        for(var j = 0; j < tdnodes.length; j++) tr.appendChild(tdnodes[j]);
        table.appendChild(tr);
        tdnodes = new Array();
      }
    }
    
    this.container.appendChild(table);
    this.container.innerHTML = this.container.innerHTML;
  },
  
  processSelection: function(o, objType, params) {
    if(o.checked) {
      if(this.selectedObjects.length < this.maxitems) {
        if(params == null) params = {}
        params._processor = this;
        params._associatedObject = o;
        var containerNumber = this.selectedObjects.length + 1;
        var objContainer = this.container_root + containerNumber.toString();
        var obj = new objType($e(objContainer), params);
        this.selectedObjects.push(obj);
        var containerXY = this.getContainerXY(containerNumber);
        
        obj.fadeExpand(0.4);
        obj.move(containerXY, 0.4);
        
        if(this.onSelect)
          this.onSelect(obj.id);
        return true;
      }
    }
    else {
      // Remove an element!
      var obj = this.findObject(objType.prototype.type, o.value);
      if(obj != null) {
        var objContainerID = obj.container.id;
      
        var removeIdx = this.getIndexForContainerID(objContainerID);
        var lastIdx = this.selectedObjects.length - 1;
        
        if(removeIdx >= 0) {
          if(removeIdx == lastIdx) {
            // we're removing the last entry... so there's no need to "reshuffle"
            // remove the object... simply fade it away!
            obj.fadeShrink(this.fadeSpeed, function() {obj.destroy();});
            this.selectedObjects.pop(); // we don't care about retriving... we just want it gone!
          }
          else {
            lastObject = this.selectedObjects.pop();
            this.selectedObjects[removeIdx] = lastObject;
            
            var containerXY = this.getContainerXY(removeIdx + 1);
            obj.fadeShrink(this.fadeSpeed, function() {obj.destroy();});
            var onComplete = function() {
              lastObject.changeParent($e(objContainerID));
            };
            
            lastObject.move(containerXY, lastObject.moveSpeed, onComplete);
          }
        }
      }
      
      if(this.onUnselect)
        this.onUnselect(obj != null ? obj.id : null);
      return true;
    }
    
    return false;
  },
  
  getContainerXY: function(containerNumber) {
    if(XLib.browserInfo.browserSupported) {
      var el = $e(this.container_root + containerNumber.toString());
      if(el != null)
        return YAHOO.util.Dom.getXY(el);
    }
    return [0, 0];
  },
  
  findObject: function(type, id) {
    for(var i = 0; i < this.selectedObjects.length; i++) {
      var obj = this.selectedObjects[i];
      if(obj.type == type && obj.id == id) {
        return obj;
      }
    }
    return null;
  },
  
  getIndexForContainerID: function(containerId) {
    // it's the last number in the ID!
    var s = containerId.substring(this.container_root.length);
    if(s != null) {
      try { return parseInt(s) - 1; }
      catch(e) {}
    }
    return -1;
  },
  
  getObjectIDs: function() {
    var a = [];
    for(var i = 0; i < this.selectedObjects.length; i++) {
      var obj = this.selectedObjects[i];
      if(obj != null) {
        a.push(obj.id);
      }
      else {
        a.push("null");
      }
    }
    return a;
  }
};

//
// XTools
//
var XTools = {
  fixCoords: function(xy, add_x, add_y) {
    return [ xy[0] + add_x, xy[1] + add_y ];
  },
  
  generateId: function(elem, basename) {
    var i = 0;
    while($e(basename + i.toString()) != null) i++;
    return basename + i.toString();
  }
};

//
// textObject
//
var textObject = function(parentEl, params) {
  if(params != null && params.serialized != null) {
    //eval("var ser = " + params.serialized);
    var ser = XLib._unserializeObject(params.serialized);
    if(ser != null) {
      parentEl = (ser.parentEl != null) ? ser.parentEl : parentEl;
      params = (ser.params != null) ? ser.params : params;
    }
  }

  this.container = parentEl;
  this.params = (params == null) ? {} : params;
  this.width = 128;
  this.moveSpeed = 0.2;
  this.fadeSpeed = 0.2;
  
  if(XLib.browserInfo.browserSupported) {
    this.moveEasing = YAHOO.util.Easing.easyOut;
    this.fadeEasing = YAHOO.util.Easing.easyOut;
  }
  else {
    this.moveEasing = 0;
    this.fadeEasing = 0;
  }
  this.init();
}

textObject.prototype = {
  type: 'textObject',
  
  repr: function() {
    var s = '{ ';
    s += 'type: ' + this.type + ', ';
    s += 'id: ' + this.id + ', ';
    s += 'text: "' + this.text + '", ';
    s += 'url: "' + this.url + '", ';
    s += 'containerid: "' + this.container.id + '" ';
    s += '}';
    return s;
  },
  
  serialize: function(toBase64) {
    var ser = XLib._serializeObject(this.params);
    if(toBase64) ser = XLib.encode64(ser);
    return ser;
  },
  
  init: function() {
    this.id = this.params.id;
    this.text = this.params.text;
    this.url = this.params.url;
    this.className = this.params.className;
    
    this.elem = document.createElement("div");
    this.elem.className = this.className;
    if(XLib.browserInfo.browserSupported) {
      this.elem.setAttribute("id", YAHOO.util.Dom.generateId(this.elem, 'XObj'));
      XLib.applyStyles(this.elem, {
        height:"70px"
      });
    }
    else {
      this.elem.setAttribute("id", XTools.generateId(this.elem, 'XObj'));
    }
    
    this.a = document.createElement("a");
    this.a.className = this.className;
    if(this.params.url)
      this.a.setAttribute("href", this.params.url);
    this.a.innerHTML = "&nbsp;&nbsp;&nbsp;" + this.text;
    
    this.elem.appendChild(this.a);
    
    // Hide on creation... we'll show if later, if the user requested to showImmediately
    XLib.applyStyles(this.elem, {opacity:"0"});
    
    this.a2 = document.createElement("a");
    this.a2.setAttribute("href","#");
    this.a2.innerHTML = "X";
     
    XLib.applyStyles(this.a2, {
      "font-family":"arial,sans-serif",
      "font-size":"10px",
      "border-right":"1px solid #ffffff",
      "border-bottom":"1px solid #ffffff",
      "position":"absolute",
      "background-color":"#999",
      "padding":"1px",
      "left":"0",
      "top":"0",
      opacity:"0.8"
    });
    
    if(XLib.browserInfo.browserSupported) {
      YAHOO.util.Event.addListener(this.a2, 'click', function(e,obj){obj.removeFromSelector();YAHOO.util.Event.stopEvent(e);}, this);
    }
    else {
      this.a2.innerHTML = "&nbsp;[X]&nbsp;";
      this.a2.setAttribute("href","javascript:(function(){o=$fo('" + this.type + "','" + this.id + "');if(o!=null)o.removeFromSelector();})();");
      
      var curStyle = this.a2.getAttribute("style");
      //alert(XLib._serializeObject(this.elem.getAttribute("style")));
      curStyle.backgroundColor = "#999999";
      //curStyle.float = "right";      
      this.a2.setAttribute("style", curStyle);
    }
    
    this.elem.appendChild(this.a2);      
    this.container.appendChild(this.elem);
    
    // We can only obtain the XY once the element is added to the DOM tree, so we do it here!
    if(this.params.startXY != null) {
      if(XLib.browserInfo.browserSupported) {
        YAHOO.util.Dom.setXY(this.elem, YAHOO.util.Dom.getXY(this.params.startXY));
      }
    }
    
    if(this.params.showImmediately != null && this.params.showImmediately) {
      if(XLib.browserInfo.browserSupported) {
        YAHOO.util.Dom.setStyle(this.elem, 'opacity', 1);
      }
    }
  },
  
  clone: function(container) {
    return new textObject(container, this.params);
  },

  shrink: function(speed, onCompleteFunction) {
    if(onCompleteFunction != null) {
      onCompleteFunction();
    }
  },
  
  expand: function(speed, onCompleteFunction) {
    if(onCompleteFunction != null) {
      onCompleteFunction();
    }
  },
  
  fadeShrink: function(speed, onCompleteFunction) {
    this.fadeOut(speed, onCompleteFunction);
  },

  fadeExpand: function(speed, onCompleteFunction) {
    this.fadeIn(speed, onCompleteFunction);
  },

  fadeIn: function(speed, onCompleteFunction) {
    if(XLib.browserInfo.browserSupported) {
      var anim = new YAHOO.util.Anim(this.elem.id, { opacity: { from:0.0, to:1.0 } }, speed == null ? this.fadeSpeed : speed, this.fadeEasing);
      if(onCompleteFunction != null)
        anim.onComplete.subscribe(onCompleteFunction);
      anim.animate();
    }
    else {
      if(onCompleteFunction != null) {
        onCompleteFunction();
      }
    }
  },
  
  fadeOut: function(speed, onCompleteFunction) {
    if(XLib.browserInfo.browserSupported) {
      var anim = new YAHOO.util.Anim(this.elem.id, { opacity: { from:1.0, to:0.0 } }, speed == null ? this.fadeSpeed : speed, this.fadeEasing);
      if(onCompleteFunction != null)
        anim.onComplete.subscribe(onCompleteFunction);
      anim.animate();
    }
    else {
      if(onCompleteFunction != null) {
        onCompleteFunction();
      }
    }
  },
  
  removeFromSelector: function() {
    if(this.params != null && this.params._processor != null) {
      if(this.params._associatedObject != null) {
        var o = $e("_sel_" + this.params._associatedObject.value);
        if(o != null)
          o.checked = false;
      }
      this.params._processor.processSelection({checked:false, value:this.id}, eval(this.params.objType), this.params);
    }
  },
  
  destroy: function() {
    var p = this.elem.parentNode;
    p.removeChild(this.elem);
  },

  move: function(xyCoords, speed, onCompleteFunction) {
    if(XLib.browserInfo.browserSupported) {
      curXY = YAHOO.util.Dom.getXY(this.elem);
      var speedOverride = null;
      speed = (speedOverride == null) ? speed : speedOverride;
    
      var attributes = {
        points: {
          to: xyCoords
        }
      };

      if(Math.abs(curXY[0] - xyCoords[0]) > 100) {
        attributes.points.control = [ [960, curXY[1]], [900, curXY[1] - 100] ];
        speedOverride = 0.5;
      }    
      else {
        attributes.points.control = [ [960, curXY[1]], [900, curXY[1] - 100] ];
      }

      var motion = new YAHOO.util.Motion(this.elem.id, attributes, speed == null ? this.moveSpeed : speed, this.moveEasing);
      motion.animate();
      
      if(onCompleteFunction != null) {
        var timeDelayAnim = new YAHOO.util.Anim(this.elem.id, { opacity: { from:0.5, to:1.0 }}, speed == null ? this.moveSpeed : speed, this.fadeEasing);
        timeDelayAnim.onComplete.subscribe(onCompleteFunction);
        timeDelayAnim.animate();
      }
    }
    else {
      if(onCompleteFunction != null) {
        onCompleteFunction();
      }
    }
  },

  replace: function(elem, copyID) {
    p = elem.parentNode;
    id = elem.id;

    if(this.elem.parentNode != null)
      this.elem.parentNode.removeChild(this.elem);

    if(copyID == true)
      this.elem.setAttribute("id", id);

    p.removeChild(elem);
    p.appendChild(this.elem);
  },

  changeParent: function(newParent) {
    if(this.container != newParent) {
      var oldParent = this.elem.parentNode;
      if(XLib.browserInfo.browserSupported) {
        var newParentXY = YAHOO.util.Dom.getXY(newParent);
        var oldParentXY = YAHOO.util.Dom.getXY(oldParent);
      }
      
      oldParent.removeChild(this.elem);
      newParent.appendChild(this.elem);
      this.container = newParent;
      
      if(XLib.browserInfo.browserSupported) {
        YAHOO.util.Dom.setXY(this.elem, newParentXY);
      }
    }
  }
};

//
// carObject
//
var carObject = function(parentEl, params) {
  //
  // parentEl: the node which will be the parent element of the current -> parentEl.appendChild() is used.
  // params:
  //   id: object id (not the elementid, whatever the object is... projectid, itemid, userid...
  //   photo: photo src
  //   url: url link
  //   className: the class to associate to this object (div[className] + img[className])
  //   showImmadiately: set the opacity to 1 once added to the DOM tree, default is 0 and a "fadeIn()" should be used
  //   startXY: node from which to obtain the XY information.  Node must be part of the DOM tree.
  //

  if(params != null && params.serialized != null) {
    //eval("var ser = " + params.serialized);
    var ser = XLib._unserializeObject(params.serialized);
    alert(XLib._serializeObject(ser));
    if(ser != null) {
      params = (ser.params != null) ? ser.params : params;
    }
  }

  this.container = parentEl;
  this.params = (params == null) ? {} : params;
  this.width = 90;
  this.moveSpeed = 0.2;
  this.fadeSpeed = 0.2;
  
  if(XLib.browserInfo.browserSupported) {
    this.moveEasing = YAHOO.util.Easing.easyOut;
    this.fadeEasing = YAHOO.util.Easing.easyOut;
    this.startWidth = (params != null && params.startWidth != null) ? params.startWidth : this.width;
  }
  else {
    this.moveEasing = 0;
    this.fadeEasing = 0;
    this.startWidth = this.width;
  }

  this.init();
};

carObject.prototype = {
  type: 'carObject',
  
  repr: function() {
    var s = '{ ';
    s += 'type: ' + this.type + ', ';
    s += 'id: ' + this.id + ', ';
    s += 'photo: "' + this.photo + '", ';
    s += 'url: "' + this.url + '", ';
    s += 'containerid: "' + this.container.id + '" ';
    s += '}';
    return s;
  },

  serialize: function(toBase64) {
    var ser = XLib._serializeObject(this.params);
    if(toBase64) ser = XLib.encode64(ser);
    return ser;
  },

  init: function() {
    this.id = this.params.id;
    this.photo = this.params.photo;
    this.url = this.params.url;
    this.className = this.params.className;
    
    this.elem = document.createElement("div");
    this.elem.className = this.className;
    
    if(XLib.browserInfo.browserSupported) {
      this.elem.setAttribute("id", YAHOO.util.Dom.generateId(this.elem, 'XObj'));
    }
    else {
      this.elem.setAttribute("id", XTools.generateId(this.elem, 'XObj'));
    }
    
    this.a = document.createElement("a");
    this.a.className = this.className;
    this.a.setAttribute("id", "a_" + this.elem.id);
    if(this.url)
      this.a.setAttribute("href", this.url);

    this.img = document.createElement("img");
    this.img.setAttribute("id", "img_" + this.elem.id);
    this.img.setAttribute("src", this.photo);
    this.img.className = this.className;
    this.img.removeAttribute("height");
    this.img.width = this.startWidth;
    
    if(XLib.browserInfo.browserSupported) {
      /*
      var onMouseUp = function(e, obj) {
        if(e.button == 2) {
          // We need to remove the element...
          obj.removeFromSelector();
          return false;
        }
        return true;
      };
      
      YAHOO.util.Event.addListener(this.img, "mouseup", onMouseUp, this);
      */
    }
    
    // Hide on creation... we'll show if later, if the user requested to showImmediately
    if(XLib.browserInfo.browserSupported) {
      YAHOO.util.Dom.setStyle(this.img, 'opacity', 0);
    }
    this.a.appendChild(this.img);
    this.elem.appendChild(this.a);
    
    this.a2 = document.createElement("a");
    if(XLib.browserInfo.browserSupported) {
      this.a2.setAttribute("href","#");
      this.a2.innerHTML = "X";

      XLib.applyStyles(this.a2, {
        "font-size":"10px",
        "font-family":"arial,sans-serif",
        "text-align":"right",
        "border":"1px solid #ffffff",
        "position":"absolute",
        "background-color":"#999",
        "padding":"1px",
        "left":1,
        "top":1,
        opacity:0.8
      });
      YAHOO.util.Event.addListener(this.a2, 'click', function(e,obj){obj.removeFromSelector();YAHOO.util.Event.stopEvent(e);}, this);
      this.elem.appendChild(this.a2);
    }
    else {
      this.a2.innerHTML = "&nbsp;[X]&nbsp;";
      this.a2.setAttribute("href","javascript:(function(){o=$fo('" + this.type + "','" + this.id + "');if(o!=null)o.removeFromSelector();})();");
      
      var curStyle = this.a2.getAttribute("style");
      curStyle.position = "relative";
      curStyle.top = "-14";
      curStyle.left = "2";
      curStyle.width = "1";
      //curStyle.height = "1";
      curStyle.fontSize = "10px";
      curStyle.fontFamily =  "arial";
      curStyle.backgroundColor = "#999999";
      this.a2.setAttribute("style", curStyle);
      this.elem.appendChild(this.a2);
    }

    this.container.appendChild(this.elem);
    
    

    // We can only obtain the XY once the element is added to the DOM tree, so we do it here!
    if(this.params.startXY != null) {
      if(XLib.browserInfo.browserSupported) {
        YAHOO.util.Dom.setXY(this.elem, YAHOO.util.Dom.getXY(this.params.startXY));
      }
    }
      
    if(this.params.showImmediately != null && this.params.showImmediately) {
      if(XLib.browserInfo.browserSupported) {
        YAHOO.util.Dom.setStyle(this.img, 'opacity', 1);
      }
    }
  },

  clone: function(container) {
    return new carObject(container, this.params);
  },
  
  shrink: function(speed, onCompleteFunction) {
    if(XLib.browserInfo.browserSupported) {
      var anim = new YAHOO.util.Anim(this.img.id, { width: { from:this.width, to:1 } }, speed == null ? this.fadeSpeed : speed, this.fadeEasing);
      if(onCompleteFunction != null)
        anim.onComplete.subscribe(onCompleteFunction);
      anim.animate();
    }
    else {
      if(onCompleteFunction != null) {
        onCompleteFunction();
      }
    }
  },
  
  expand: function(speed, onCompleteFunction) {
    if(XLib.browserInfo.browserSupported) {
      var anim = new YAHOO.util.Anim(this.img.id, { width: { from:1, to:this.width } }, speed == null ? this.fadeSpeed : speed, this.fadeEasing);
      if(onCompleteFunction != null)
        anim.onComplete.subscribe(onCompleteFunction);
      anim.animate();
    }
    else {
      if(onCompleteFunction != null) {
        onCompleteFunction();
      }
    }
  },
  
  fadeShrink: function(speed, onCompleteFunction) {
    if(XLib.browserInfo.browserSupported) {
      var attributes = {
        points: { to: XTools.fixCoords(YAHOO.util.Dom.getXY(this.img), 32, 32) }
      };
      
      var anim = new YAHOO.util.Anim(this.img.id, { opacity: { from:1.0, to:0.0 }, width: { from:this.width, to:1 } }, speed == null ? this.fadeSpeed : speed, this.fadeEasing);
      var motion = new YAHOO.util.Motion(this.img.id, attributes, speed == null ? this.fadeSpeed : speed, this.moveEasing);
      if(onCompleteFunction != null)
        anim.onComplete.subscribe(onCompleteFunction);
      motion.animate();
      anim.animate();
    }
    else {
      if(onCompleteFunction != null) {
        onCompleteFunction();
      }
    }
  },  

  fadeExpand: function(speed, onCompleteFunction) {
    if(XLib.browserInfo.browserSupported) {
      var anim = new YAHOO.util.Anim(this.img.id, { opacity: { from:0.0, to:1.0 }, width: { from:1, to:this.width } }, speed == null ? this.fadeSpeed : speed, this.fadeEasing);
      if(onCompleteFunction != null)
        anim.onComplete.subscribe(onCompleteFunction);
      anim.animate();
    }
    else {
      if(onCompleteFunction != null) {
        onCompleteFunction();
      }
    }
  },

  fadeIn: function(speed, onCompleteFunction) {
    if(XLib.browserInfo.browserSupported) {
      var anim = new YAHOO.util.Anim(this.img.id, { opacity: { from:0.0, to:1.0 } }, speed == null ? this.fadeSpeed : speed, this.fadeEasing);
      if(onCompleteFunction != null)
        anim.onComplete.subscribe(onCompleteFunction);
      anim.animate();
    }
    else {
      if(onCompleteFunction != null) {
        onCompleteFunction();
      }
    }
  },
  
  fadeOut: function(speed, onCompleteFunction) {
    if(XLib.browserInfo.browserSupported) {
      var anim = new YAHOO.util.Anim(this.img.id, { opacity: { from:1.0, to:0.0 } }, speed == null ? this.fadeSpeed : speed, this.fadeEasing);
      if(onCompleteFunction != null)
        anim.onComplete.subscribe(onCompleteFunction);
      anim.animate();
    }
    else {
      if(onCompleteFunction != null) {
        onCompleteFunction();
      }
    }
  },
  
  removeFromSelector: function() {
    if(this.params != null && this.params._processor != null) {
      if(this.params._associatedObject != null) {
        var o = $e("_sel_" + this.params._associatedObject.value);
        if(o != null)
          o.checked = false;
      }
      this.params._processor.processSelection({checked:false, value:this.id}, eval(this.params.objType), this.params);
    }
  },
  
  destroy: function() {
    // remove it from the DOM
    var p = this.elem.parentNode;
    p.removeChild(this.elem);
  },

  move: function(xyCoords, speed, onCompleteFunction) {
    if(XLib.browserInfo.browserSupported) {
      curXY = YAHOO.util.Dom.getXY(this.img);
      var speedOverride = null;
      speed = (speedOverride == null) ? speed : speedOverride;
      
      var attributes = {
        points: {
          to: xyCoords
        }
      };

      if(Math.abs(curXY[0] - xyCoords[0]) > 100) {
        attributes.points.control = [ [960, curXY[1]], [900, curXY[1] - 100] ];
        speedOverride = 0.5;
      }    
      else {
        attributes.points.control = [ [960, curXY[1]], [900, curXY[1] - 100] ];
      }

      var motion = new YAHOO.util.Motion(this.elem.id, attributes, speed == null ? this.moveSpeed : speed, this.moveEasing);
      motion.animate();
      
      if(onCompleteFunction != null) {
        var timeDelayAnim = new YAHOO.util.Anim(this.elem.id, { opacity: { from:0.5, to:1.0 }}, speed == null ? this.moveSpeed : speed, this.fadeEasing);
        timeDelayAnim.onComplete.subscribe(onCompleteFunction);
        timeDelayAnim.animate();
      }
    }
    else {
      if(onCompleteFunction != null) {
        onCompleteFunction();
      }
    }
  },

  replace: function(elem, copyID) {
    p = elem.parentNode;
    id = elem.id;

    if(this.elem.parentNode != null)
      this.elem.parentNode.removeChild(this.elem);

    if(copyID == true)
      this.elem.setAttribute("id", id);

    p.removeChild(elem);
    p.appendChild(this.elem);
  },

  changeParent: function(newParent) {
    if(this.container != newParent) {
      var oldParent = this.elem.parentNode;
      
      if(XLib.browserInfo.browserSupported) {
        var newParentXY = YAHOO.util.Dom.getXY(newParent);
        var oldParentXY = YAHOO.util.Dom.getXY(oldParent);
      }
      
      oldParent.removeChild(this.elem);
      newParent.appendChild(this.elem);
      this.container = newParent;
      
      if(XLib.browserInfo.browserSupported) {
        YAHOO.util.Dom.setXY(this.elem, newParentXY);
      }
    }
  }
};

