  Array.prototype.in_array = function(value,comp_func)
   {
       comp_func=(!comp_func) ? function (comp,value){ return comp===value;  }  : comp_func;
 
	var l = this.length;
	for (var i = 0; i < l; i++)
        {
       	if ( comp_func(this[i], value)===true ) { return i;}
        }
 	return false;
   };

function $(id)
 {
	return document.getElementById(id);
 }

/*
function screenSize() 
 {
      var w, h; // Объявляем переменные, w - длина, h - высота
      w = (window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.offsetWidth));
      h = (window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.offsetHeight));
      return {w:w, h:h};
 }
*/

function disableSelection(target)
 {
   if (typeof target.onselectstart!="undefined") //IE route
	target.onselectstart=function(){return false}
    else 

 if  (typeof target.style=="undefined") {  return;} 

if (typeof target.style.MozUserSelect!="undefined") //Firefox route
	target.style.MozUserSelect="none";
/*
else //All other route (ie: Opera)
	target.onmousedown=function(){return false}
*/

//target.style.cursor = "default"
}

//exp ->exeption name or object which not test on condition;
//r_id-> test condition
//st_f ->test function

function test_child(obj,r_id,st_f,exp)
 {
    var result=[];
 
   if ((!st_f && obj.id==r_id) ) return true;

    if (st_f)
     { var res=st_f(obj,r_id);
          
      if (res!=false)
       result.push(res);
     }

     for ( var i = 0; i < obj.childNodes.length; i++ )
      {
         if  (!(!exp) && (obj.childNodes[i].id==exp || obj.childNodes[i]===exp ) ) continue;

          var res=test_child(obj.childNodes[i],r_id,st_f,exp);
           if ( res!=false )
            { result=result.concat(res);
            }
      }

    if (st_f)
     result= (result.length==0)? false: result ;
      else 
       result= (result.length==0)? false: true;

      return result;
 }

 function test_parent(obj,r_id,st_f)
  {
     st_f=(!st_f)? function (obj,r_id) { return obj.id===r_id;  }  :st_f;

       do
         {
   if (obj===document.body) return false;

        var res=st_f(obj,r_id);
         if (res!=false)
          return res;
         }      while (obj=obj.parentNode);
   }

function clearSelection()
{
var sel;
if(document.selection && document.selection.empty)
{
document.selection.empty();
}
else if(window.getSelection)
{
sel = window.getSelection();
if(sel && sel.removeAllRanges)
sel.removeAllRanges();
}
}

function enableSelection(target) 
 {
   if (typeof target.onselectstart!="undefined") target.onselectstart=null;
    else 
    if  (typeof target.style=="undefined") {  return;} 

     if (typeof target.style.MozUserSelect!="undefined") //Firefox route
	target.style.MozUserSelect="tri-state";
 }

 function disable_all_Selection(obj,en)
  {
    if (en)
    enableSelection(obj);
     else
      disableSelection(obj);

/*     for ( var i = 0; i < obj.childNodes.length; i++ )
      {
         disable_all_Selection( obj.childNodes[i],en);
      }
*/
  }

function getElementsByClassName(obj,className)
 {
 if (obj.getElementsByClassName) 
  {
 return obj.getElementsByClassName(className);
  }

var arrayClassElements=[];

  function getElementsByClassName (obj,ClassName ) 
   {
     if ( obj.className == ClassName ) 
      {
        arrayClassElements[arrayClassElements.length] = obj;
      }
         for ( var i = 0; i < obj.childNodes.length; i++ )
          getElementsByClassName( obj.childNodes[i],ClassName  );
   }
        getElementsByClassName(obj,className);

 return arrayClassElements;
   }


function findparent(_parent,id,d)
 {  
  if (_parent==document.body ) return false;
   if (_parent.id==id) return _parent;

     do {
         _parent=_parent.parentNode;
          if (_parent==null) return false;
           if (!(!d))
             alert("t_p="+_parent.id+" t_id="+id);
          if (_parent.id==id){ return _parent;}
       } 
      while (_parent!==document.body);
        return false;
 }


 function GetAbsCoords (_obj) 
  {

    var isMSIE = (navigator.appVersion.indexOf("MSIE") != -1);

    var _top=0;
    var _left=0;
    var _parent=_obj;

     if (_parent==null ) { alert("GetAbsCoords\r\nNot Found  parent Object "+_obj.id);  return [0,0]; }

      _top+=_parent.offsetTop;
      _top+=_parent.clientTop;

     _left+=_parent.offsetLeft;
     _left+=_parent.clientLeft;

//     alert(_parent.offsetParent);

     do {
          if (!_parent.offsetParent ) { alert("GetAbsCoords\r\nNot Found Parent Object "+_parent.id);  return [0,0]; }
         _parent=_parent.offsetParent;
         _top+=_parent.offsetTop;
         _top+=_parent.clientTop;
         _left+=_parent.offsetLeft;
         _left+=_parent.clientLeft;

       } 
      while (_parent!==document.body);
//+document.body.scrollTop
//+document.body.scrollLeft

   if (isMSIE) { _top-=2; _left-=2;}

       return [_left,_top];
  }

	  function fixEvent(event) {
	    event = event || window.event
	   	      if (!event) return false;
	    if ( event.isFixed ) {
	      return event
	    }
	    event.isFixed = true

	    if (!event.target) {
	        event.target = event.srcElement
	    }
	  
	    event.preventDefault = event.preventDefault || function(){this.returnValue = false}
	    event.stopPropagation = event.stopPropagaton || function(){this.cancelBubble = true}
	   
	    if (!event.relatedTarget && event.fromElement) {
	        event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
	    }
	   
	    if ( event.pageX == null && event.clientX != null ) {
	        var html = document.documentElement, body = document.body;
	        event.pageX = event.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0);
	        event.pageY = event.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0);
	    }
	   
	    if ( !event.which && event.button ) {
	        event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
	    }
	     
	    return event
	  }

Event = (function() {
 
	  var guid = 0;
 	   
	  /* Вызывается в контексте элемента всегда this = element */
	  function commonHandle(event) {
	    event = fixEvent(event);
	     
	    var handlers = this.events[event.type]
	 
	    for ( var g in handlers ) {
	      var handler = handlers[g]
	 
	      var ret = handler.call(this, event)
	      if ( ret === false ) {
	          event.preventDefault()
	          event.stopPropagation()
	      }
	    }
	  }
	   
	  return {
	    add: function(elem, type, handler) {
	      if (elem.setInterval && ( elem != window && !elem.frameElement ) ) {
	        elem = window;
	      }
	       
	      if (!handler.guid) {
	        handler.guid = ++guid;
	      }
	       
	      if (!elem.events) {
	        elem.events = {}
	        elem.handle = function(event) {
	          if (typeof Event !== "undefined") {
	            return commonHandle.call(elem, event)
	          }
	        }
	      }
	       
	      if (!elem.events[type]) {
	        elem.events[type] = {}       
	       
	        if (elem.addEventListener)
	          elem.addEventListener(type, elem.handle, false)
	        else if (elem.attachEvent)
	          elem.attachEvent("on" + type, elem.handle)
	      }
	       
	      elem.events[type][handler.guid] = handler;
                           return handler.guid;
	    },
	     
	    remove: function(elem, type, handler) {
	      var handlers = elem.events && elem.events[type]
	       
     	      if (!handlers) return
             if (!handler)  
              {
	        for ( var handle in handlers ) {
	            delete handlers[handle];
	        }
	        return
       	    }

	      delete handlers[handler];
	       
	      for(var any in handlers) return
	      if (elem.removeEventListener)
	        elem.removeEventListener(type, elem.handle, false)
	      else if (elem.detachEvent)
	        elem.detachEvent("on" + type, elem.handle)
	         
	      delete elem.events[type]
	     
	       
	      for (var any in elem.events) return
	      try {
	        delete elem.handle
	        delete elem.events
	      } catch(e) { // IE
	        elem.removeAttribute("handle")
	        elem.removeAttribute("events")
	      }
	    }
	  }
	}())

function ExtractNumber(value)
 {
	var n = parseInt(value);
	
	return n == null || isNaN(n) ? 0 : n;
  }

var DragDrop={
   _startX : 0,			// mouse starting positions
   _startY : 0,
  _offsetX : 0,			// current element offset
  _offsetY : 0,
_oldZIndex : 0,			// we temporarily increase the z-index during drag
_newWidth : 0,
_newHeight : 0,
_ZIndex : 10000,
move_el : ["drag",'window','layer'],
move_rs : ["resize_xy","resize_x","resize_y"],
recip_el : "recip",
recip_cl: "recip_cl",
//con_array: [],
rs_cfg:{min_w:100 , min_h:100,max_w:1000 ,max_h:1000},
mv_cfg:{max_w:null,max_h:null},

//ac_con_array: {},
_dragElement:null,// needs to be passed from OnMouseDown to OnMouseMove
_rs_evElement:null,

recipients:{length:0},
dragpanels:{},

offset_rec_x:1,
offset_rec_y:1,
recip_hist:[],
redo_hist:[],
ac_con_v:true, // true-> connect el-s only in ac_con_array.length>0; false->not connect  el-s in ac_con_array 
tag_except:['block','close_w','max_win','min_win','tray_win','close_win','textarea','input','select','option','iframe'],
initobj:false,

     addEvent:function(obj, type, fn)
      {
         Event.add(obj, type, fn);
      },

     addEvent_m : function(obj, type, fn,method)
      {
        var func=function(event) { fn[method](event,fn); };
         Event.add(obj, type, func);
      },

     delEvent_m: function (obj, type)
      {
         Event.remove(obj, type);
      },

     init_doc_ev: function ()
       {
 this.addEvent_m(document,"mousedown",this,"OnMouseDown");
       },

  destroy_doc_ev: function ()
     {
       this.delEvent_m(document,"mousedown");
       this.delEvent_m(document,"mouseup");
     }, 

     InitDragDrop: function ()
      {
           this.init_doc_ev();
  
                 var r=getElementsByClassName(document,this.recip_el);

       for (var i=0; i<r.length; i++)
        {
         this.add_recip(r[i]);
        }
            this.initobj=true;
      },

  get_recip_p: function (sr)
   {
    if (typeof(sr)=="undefined" || sr.s==null) { return;}
     var st=sr.s.style;       
         
    sr.x_min=ExtractNumber(st.left);
    sr.y_min=ExtractNumber(st.top);
         
   if (sr.s.style.display=="none" ) 
    {
       sr.x_min=null;
       sr.y_min=null;
       sr.x_max=null;
       sr.y_max=null;
         return;
    }

    if (sr.x_min==0 || sr.y_min==0 || sr.s.style.position==null || sr.s.style.position!="absolute"  )
     {
         var xy=GetAbsCoords(sr.s);
       sr.x_min=xy[0];
       sr.y_min=xy[1];
     }

    sr.x_max=sr.x_min+sr.s.offsetWidth;
    sr.y_max=sr.y_min+sr.s.offsetHeight;
    sr.ofs_x=this.offset_rec_x;
    sr.ofs_y=this.offset_rec_y;
  },

 add_recip: function (recip,_f_i,_f_o,_f_u,_f_tst_r,_f_tst_ins,_m_ad,_ac_p,_ac_c_arr)
  {
    switch (typeof(recip) )
     { 
      case  "string": recip=document.getElementById(recip);
     }

      if (recip==null)
       {
         alert("Not Set Recipient Object!!");
           return;
       }
     var sr={};
     sr.s=recip;
     this.get_recip_p(sr);

     sr.f_i=(!_f_i)? null: _f_i;
     sr.f_o=(!_f_o)? null: _f_o;
     sr.f_u=(!_f_u)? null: _f_u;
     sr.m_ad=(!_m_ad)? null: _m_ad;

     sr.test_coord_recip= (!_f_tst_r)? this.test_coord_recip : _f_tst_r; 
     sr.get_insert_pos= (!_f_tst_ins)? this.get_insert_pos : _f_tst_ins; 
     
     sr.ac_p=(!_ac_p)? this.ac_con_v: _ac_p;

     sr.ac_con_array={length:0 }

      if (!_ac_c_arr)  sr.ac_con_array={length:0  }
       else 
        {  sr.ac_con_array={};
           sr.ac_con_array.length=_ac_c_arr.length;
        for (var i=0; i<_ac_c_arr.length; i++)
         { 
          sr.ac_con_array[_ac_c_arr[i]]="";
         }
       }

     sr.con_array={length:0};
     this.recipients[sr.s.id]=(sr);
     this.recipients.length++;
  },


  del_recip: function (recip)
   {
    switch (typeof(recip) )
     { 
      case  "object": recip=document.getElementById(recip).id;
     }

if (this.recipients[recip].con_array.length==0)
 {
   delete this.recipients[recip];
  this.recipients.length--;
   return;
 }
 if (this.debug) alert(recip+" Have child objects!!");

   },

 test_dragpanel: function (target) 
  {
     for (var key in this.dragpanels)
      {
        var res=findparent(target,key);
         if (res!=false ) return res;
      }
          return false;
  },

 init_resize_el: function (e,target,rs_i)
  {
            var rs_func={resize_xy:"OnMouseMove_rs",resize_x:"OnMouseMove_rs_x",resize_y:"OnMouseMove_rs_y" }

            this._rs_evElement=target;

            target=target.parentNode;

  		t._startX = e.clientX;
           	t._startY = e.clientY;

		// grab the clicked element's position
		t._offsetX = ExtractNumber(target.style.left);
		t._offsetY = ExtractNumber(target.style.top);

            if ( target.style.position!="absolute"  )
             {
               var xy=GetAbsCoords(target);
                t._offsetX=xy[0];
                t._offsetY=xy[1];
             }
		
		// bring the clicked element to the front while it is being dragged

		document.body.focus();

		// prevent IE from trying to drag an image
		target.ondragstart = function() { return false; };
		// prevent text selection (except IE)
		t._dragElement = target;

             t.addEvent_m(document,"mousemove",this,rs_func[this.move_rs[rs_i]] );
              
             t.addEvent_m(document,"mouseup",this,"OnMouseUp");

           clearSelection();
            disable_all_Selection(document.body,false);

            disable_all_Selection(t._dragElement,false);
             var frame=test_child(t._dragElement,'',function (obj,ir) { if (obj.tagName=="IFRAME"){ obj.style.visibility="hidden"; }}   )

  },

 init_drag_el: function(e,target)
    {
      var t=this;
           target.title=target.id.toLowerCase();
           target.alt=target.id.toLowerCase();
 
             // grab the mouse position
              t._startX = e.pageX;
              t._startY = e.pageY;

		// grab the clicked element's position

              t._offsetX = ExtractNumber(target.style.left);
      	  t._offsetY = ExtractNumber(target.style.top);
		
		t._oldZIndex = target.style.zIndex;

		document.body.focus();

		 t._dragElement = target;
 
       if (t.recipients.length>0 ||   (t._ZIndex>10000 ) || (t._oldZIndex>=10000) )
            {
             t._ZIndex++;
              t._dragElement.style.zIndex = t._ZIndex;
             } else 
                t._dragElement.style.zIndex = 10000;
             
              t.addEvent_m(document,"mousemove",t,"OnMouseMove" );

              t.addEvent(document,"dragstart",function() { return false; });

              t.addEvent_m(document,"mouseup",this,"OnMouseUp");

clearSelection();
               disable_all_Selection(t._dragElement,false);

             disable_all_Selection(document.body,false);

             var frame=test_child(t._dragElement,'',function (obj,ir) { if (obj.tagName=="IFRAME"){ obj.style.visibility="hidden"; }}   )

   },

 OnMouseDown: function(e)
  {
    t=this;

       e=fixEvent(e);
       var target = e.target  

     if (e.which != 1) return false;
         var p_target=target.parentNode;

     // $("test").innerHTML="1:"+p_target.tagName.toLowerCase()+" "+p_target.className;

    if ( t.tag_except.in_array(target, function (comp,value)
        { 
          return ( (value.tagName.toLowerCase().indexOf(comp)>-1) ||  (value.className.toLowerCase().indexOf(comp)>-1)  );   } )!==false
      ) { return false; }


       if ( typeof(p_target)!="undefined" && p_target.tagName && p_target.tagName.toLowerCase()=="td")
        p_target=p_target.parentNode;

        if (typeof(p_target)!="undefined" && p_target.tagName  &&  p_target.tagName.toLowerCase()=="tr")
         {    
            target=p_target.parentNode.parentNode;
             p_target=p_target.parentNode;
     //              $("test").innerHTML="2:"+target.tagName.toLowerCase()+" "+target.className;

    if ( t.tag_except.in_array(target, function (comp,value)
        { 
          return ( (value.tagName.toLowerCase().indexOf(comp)>-1) ||  (value.className.toLowerCase().indexOf(comp)>-1)  );   } )!==false
      ) { return false; }

         }  


 var rs_i=t.move_rs.in_array(target,function (comp,value){return value.id.indexOf(comp)>-1;   } );
 
         if ( rs_i!==false )
           {
              t.init_resize_el(e,target,rs_i);
              return false;
           }

 var drg_p=t.test_dragpanel(target);
 
   if  ( drg_p!==false 
 || this.move_el.in_array([target,p_target], 
                             function (comp,value) 
                              {  for (var i=0; i<value.length; i++) 
                                   { 
                                      var t_obj=value[i];
                                      if (  (t_obj.id && t_obj.id.toLowerCase().indexOf(comp)>-1) ||  
                                             (t_obj.className && t_obj.className.toLowerCase().indexOf(comp)>-1) )
                                        return true;
                                    }
                                         return false;
                              }  )!==false 

       )
         {
          if ( drg_p!=false)
           target=drg_p;
 
            t.init_drag_el(e,target);
    
              return false;
	}

},


OnMouseMove_rs: function(e)
 {
   clearSelection();
   var t=this;
      
       if (t._dragElement==null)
        {
          return false;
        }
        e=fixEvent(e);

          var offsetX = e.pageX - t._offsetX;

            var offsetY = e.pageY - t._offsetY;

             t._newWidth=offsetX;
            t._newHeight=offsetY;

                t.rs_cfg.min_w=ExtractNumber(t._dragElement.style.minWidth) || t.rs_cfg.min_w;
                t.rs_cfg.min_h=ExtractNumber(t._dragElement.style.minHeight)  || t.rs_cfg.min_h;

                t.rs_cfg.max_w=ExtractNumber(t._dragElement.style.maxWidth)  || t.rs_cfg.max_w;
                t.rs_cfg.max_h=ExtractNumber(t._dragElement.style.maxHeight) || t.rs_cfg.max_h;


               t._newWidth = Math.max(t._newWidth,t.rs_cfg.min_w);
              t._newHeight = Math.max(t._newHeight,t.rs_cfg.min_h);

               t._newWidth = Math.min(t._newWidth, t.rs_cfg.max_w);
              t._newHeight = Math.min(t._newHeight,t.rs_cfg.max_h);

                var old_with=ExtractNumber(t._dragElement.style.width);
              var old_height=ExtractNumber(t._dragElement.style.height);
 
          
              t._dragElement.style.width = t._newWidth + "px";
              t._dragElement.style.height = t._newHeight + "px";
                 
                 if (t._dragElement.resizefunc ) t._dragElement.resizefunc("resize_xy");
    },

OnMouseMove_rs_x: function(e)
 {

clearSelection();
   var t=this;
       if (t._dragElement==null)
        {
          return false;
        }

	if (e == null) 
	 var e = window.event;

          var offsetX = e.clientX - t._offsetX;
///+document.body.scrollLeft;
      //      var offsetY = e.clientY - t._offsetY+document.body.scrollTop;

            t._newWidth=offsetX;
      //      t._newHeight=offsetY;

                t.rs_cfg.min_w=ExtractNumber(t._dragElement.style.minWidth) || t.rs_cfg.min_w;
      //          t.rs_cfg.min_h=ExtractNumber(t._dragElement.style.minHeight)  || t.rs_cfg.min_h;

                t.rs_cfg.max_w=ExtractNumber(t._dragElement.style.maxWidth)  || t.rs_cfg.max_w;
       //         t.rs_cfg.max_h=ExtractNumber(t._dragElement.style.maxHeight) || t.rs_cfg.max_h;


              t._newWidth = Math.max(t._newWidth,t.rs_cfg.min_w);
       //       t._newHeight = Math.max(t._newHeight,t.rs_cfg.min_h);

              t._newWidth = Math.min(t._newWidth, t.rs_cfg.max_w);
        //      t._newHeight = Math.min(t._newHeight,t.rs_cfg.max_h);

              t._dragElement.style.width = t._newWidth + "px";
         //     t._dragElement.style.height = t._newHeight + "px";

                 if (t._dragElement.resizefunc ) t._dragElement.resizefunc("resize_x");
   },

OnMouseMove_rs_y: function(e)
 {

clearSelection();
   var t=this;
       if (t._dragElement==null)
        {
          return false;
        }

	if (e == null) 
	 var e = window.event;

      //    var offsetX = e.clientX - t._offsetX+document.body.scrollLeft;
            var offsetY = e.clientY - t._offsetY+document.body.scrollTop;

      //      t._newWidth=offsetX;
            t._newHeight=offsetY;

      //          t.rs_cfg.min_w=ExtractNumber(t._dragElement.style.minWidth) || t.rs_cfg.min_w;
                t.rs_cfg.min_h=ExtractNumber(t._dragElement.style.minHeight)  || t.rs_cfg.min_h;

      //          t.rs_cfg.max_w=ExtractNumber(t._dragElement.style.maxWidth)  || t.rs_cfg.max_w;
                t.rs_cfg.max_h=ExtractNumber(t._dragElement.style.maxHeight) || t.rs_cfg.max_h;


       //       t._newWidth = Math.max(t._newWidth,t.rs_cfg.min_w);
              t._newHeight = Math.max(t._newHeight,t.rs_cfg.min_h);

       //       t._newWidth = Math.min(t._newWidth, t.rs_cfg.max_w);
              t._newHeight = Math.min(t._newHeight,t.rs_cfg.max_h);

        //      t._dragElement.style.width = t._newWidth + "px";
              t._dragElement.style.height = t._newHeight + "px";
            
                 if (t._dragElement.resizefunc ) t._dragElement.resizefunc("resize_y");
   },

 OnMouseMove: function(e)
  {
  clearSelection();
    var t=this;

     if (t._dragElement==null)
      {
        return;
      }
    
      var x_pos=(t._offsetX + e.pageX - t._startX);
      var y_pos=(t._offsetY + e.pageY - t._startY);

      var t_w=  ExtractNumber(t._dragElement.offsetWidth);
      var t_h=  ExtractNumber(t._dragElement.offsetHeight);

      if ( this.mv_cfg.max_w && (x_pos+t_w>this.mv_cfg.max_w ) )
        {
           t._dragElement.style.left =this.mv_cfg.max_w-t_w-2 + 'px';
        } else 
	t._dragElement.style.left =Math.max( x_pos,0) + 'px';

      if ( this.mv_cfg.max_h && (y_pos+t_h>this.mv_cfg.max_h ) )
        {
           t._dragElement.style.top =this.mv_cfg.max_h-t_h-2 + 'px';
        } else 
             t._dragElement.style.top = Math.max( y_pos,0) + 'px';

             t._dragElement.startX=ExtractNumber(t._dragElement.style.left);

             t._dragElement.startY=ExtractNumber(t._dragElement.style.top);
                 if (t._dragElement.movefunc ) t._dragElement.movefunc("move");

   var r_m=false;
   r_m=this.test_child_recip(t._dragElement,false);
          if ( r_m!=false )
           {
             for (var i_r_m=0; i_r_m<r_m.length; i_r_m++)
              {
                this.get_recip_p(this.recipients[r_m[i_r_m]]);

              this.move_recip_obj(r_m[i_r_m]);
              }
            }
                 if (t._dragElement.movefunc ) t._dragElement.movefunc();
  
},


  save_hist_recip: function (id_con,drg,id_recip,pos_c,pos_r)
   {
     this.recip_hist.push({id_con:(!id_con)?false:id_con,
                           id_drg:drg.id,
                           id_recip:(!id_recip)? false:id_recip  ,pos_c:( (pos_c==null )? false :  pos_c ) ,pos_r: ( (pos_r==null) ? false : pos_r ),
                           _offsetX:this._offsetX,
                           _offsetY:this._offsetY,
                           _X:ExtractNumber(drg.style.left),
                           _Y:ExtractNumber(drg.style.top) });
   },

  calculate_rcp_pos: function (id_rcp,id_drg)
   {
      var i=0;
     for (var key in this.recipients[id_rcp].con_array  )
      {
          if (key=="length") continue;

           if (key==id_drg) return i;
            i++; 
       }
   }, 

  undo_hist_recip: function(lastpos) 
   {
    if (this.recip_hist.length==0 ) return;

     lastpos=(!lastpos)? this.recip_hist.length : lastpos;

     var end_pos=this.recip_hist.length-lastpos;

      this.redo_hist.length=0;

     for (var i=this.recip_hist.length-1; i>=end_pos; i--)
      {
          with ( this.recip_hist[i] )
           { 
       if ( $(id_drg)==null  || (id_con!=false && $(id_con)==null) || (id_recip!=false && $(id_recip)==null))
        { end_pos=(end_pos==0)? end_pos: (end_pos-1); 
           alert(id_drg+" "+id_con+" rcp: "+id_recip);
           continue; 
        } 
           this.redo_hist.push({id_con:id_recip,
                           id_drg:id_drg,
                           id_recip:id_con,pos_c:pos_r ,pos_r: pos_c,
                           _offsetX:_X,
                           _offsetY:_Y,
                           _X:_offsetX,
                           _Y:_offsetY});

           if (id_con!=false)
            {
             this.set_obj_to_recip(id_drg,id_con,pos_c, 1,1);
            } else 
               if (id_recip!=false)
                {
                 this.del_obj_recip(id_drg , _offsetX , _offsetY ,id_recip );
                } else 
                   {
                  $(id_drg).style.left=_offsetX+'px';
                   $(id_drg).style.top=_offsetY+'px';
                    this.refresh_parent(id_drg);
                   }
      }

     }
   this.recip_hist.splice(end_pos,this.recip_hist.length-end_pos);
   },


  redo_hist_recip: function(lastpos) 
   {
//  alert(this.redo_hist.toSource());

       if (this.redo_hist.length==0 ) return;
        lastpos=(!lastpos)? this.redo_hist.length : lastpos;

     var end_pos=this.redo_hist.length-lastpos;

     for (var i=this.redo_hist.length-1; i>=end_pos; i--)
      {
        with ( this.redo_hist[i] )
         { 

         if ( $(id_drg)==null  || (id_con!=false && $(id_con)==null) || (id_recip!=false && $(id_recip)==null))
          { end_pos=(end_pos==0)?end_pos: (end_pos-1); continue; } 

             this.recip_hist.push({id_con:id_recip,
                             id_drg:id_drg,
                           id_recip:id_con,pos_c:pos_r ,pos_r: pos_c,
                           _offsetX:_X,
                           _offsetY:_Y,
                                 _X:_offsetX,
                                 _Y:_offsetY});

           if (id_con!=false)
            {
             this.set_obj_to_recip(id_drg,id_con,pos_c, 1,1);
            } else 

              if (id_recip!=false)
               {
                 this.del_obj_recip(id_drg , _offsetX , _offsetY ,id_recip );
               } else 
                   {
                  $(id_drg).style.left=_offsetX+'px';
                   $(id_drg).style.top=_offsetY+'px';
                    this.refresh_parent(id_drg);
                   }
      }

     }

  this.redo_hist.splice(end_pos,this.redo_hist.length-end_pos);
         
   },

 

 in_con_arr: function(i_id)
  {
    if (typeof(i_id)=="object" )
     {
       for ( var i in this.recipients )
        {
         if (i=="length") continue;

          for ( var j in this.recipients[i].con_array )
           {
            if (j=="length") continue;
             var res=findparent(i_id,j);

              if (res!=false ) return i;
            }
          } 
            return false;
     }

   for (var key in this.recipients)
    { 
      if (key=="length") continue;

        if ( typeof(this.recipients[key].con_array[i_id])!="undefined")
         return key;
     }
          return false;
     },

  get_con_arr_hist: function(i_id)
   {
    var res=[];
      do 
       {
        var in_con=this.test_parent_recip_con(i_id);

             if (in_con!=false)
              {
               res.push(in_con);
                  i_id=$(in_con);
                   
//                alert("r_c: "+in_con+" i_id: "+i_id);

              }
       } while (in_con!==false);

         return (res.length==0)? false: res;
   },

  in_ac_con_arr: function (r_id,i_id)
   {
     switch ( typeof(r_id) )
      {
       case "object":
        id_r=r_id.id;
        break;
      }

     var ac_p=this.recipients[r_id].ac_p;

 //  alert(ac_p+"; "+this.recipients[r_id].ac_con_array.length +" "+r_id+" "+i_id);

      if (this.recipients[r_id].ac_con_array.length==0) return (ac_p)? 0:-1;
   if ( typeof(this.recipients[r_id].ac_con_array[i_id])!="undefined")
    {
      return (ac_p)? -1: 0;
    }
      return (ac_p)? 0:-1;
 },

 get_insert_pos: function (_dragElement,sobj)
  {
    var pos=-1;  
     var i=0;

       var x_pos= ExtractNumber(_dragElement.style.left);
       var y_pos= ExtractNumber(_dragElement.style.top);
           var w= _dragElement.offsetWidth;
           var h= _dragElement.offsetHeight;

    for (var key in sobj)
     {
          if (key=="length") continue;
    
         
          var obj=$(key);

           var x_min=ExtractNumber(obj.style.left);
           var y_min=ExtractNumber(obj.style.top);

           var x_max=x_min+obj.offsetWidth;
           var y_max=y_min+obj.offsetHeight;
                
         if ( x_pos<=x_max &&
                 ( x_pos>=x_min || x_pos+w>=x_min )&& 
                   y_pos<=y_max && 
                 ( y_pos>=y_min || y_pos+h>=y_min )
                 )
             {

               pos=i;

              break;
             }

            i++;
     }
 
      return pos;
  },

 change_sequence: function (_sobj,new_obj,num) 
  {
   var  sobj=this.recipients[_sobj].con_array;

    if (num==-1 || num==sobj.length )
     {
        sobj[new_obj.k]=new_obj.v;
         sobj.length++;
         return (sobj.length-1);
     }
      var tmpl_ar=[];

       for (var key in sobj)
        {
         if (key=="length") continue;
          tmpl_ar.push({k: key, v: sobj[key]});
           delete sobj[key];
        }
       sobj.length++;
        tmpl_ar.splice(num,0,new_obj);
         delete this.recipients[_sobj].con_array;

          this.recipients[_sobj].con_array={length:tmpl_ar.length};

           for (var i=0; i<tmpl_ar.length; i++)
            {
             this.recipients[_sobj].con_array[tmpl_ar[i].k]=tmpl_ar[i].v;
            }
               return num;
   },

 test_child_recip: function(_dragElement,exp,wchld)
  {
    var result=[];
    var res=test_child(_dragElement,this.recipients,function (obj,tst) 
              {
                for (var key in tst )
                 { 
                  if (key=="length") continue;
                   if ( key == obj.id ) return key;
                 }
                    return false;
               } ,exp);

   if (res!=false && wchld)
    {
     result=result.concat(res);

   for (var i=0; i<res.length; i++)
    {
      for (var key in this.recipients[res[i]].con_array)
       {
        if (key=="length") continue;
        var res_c=this.test_child_recip($(key),exp,true);
          if (res_c!=false)
           result=result.concat(res_c);
       }
    } 
   
    } else
      result=res;

     return result;

  },

 test_parent_recip_con: function(_dragElement)
  {
     return  test_parent(_dragElement,this.recipients,function (obj,tst) 
              {
                for (var key in tst )
                 { 
                   if (key=="length") continue;
                    if ( typeof (tst[key].con_array[obj.id])!="undefined") return key;
                 }
                    return false;
               } )
  },


  parent_move_recip_obj: function(r_id)
   {
   var recip=this.recipients[r_id];
 //    this.get_recip_p(recip);
      var k=0;
       var x_pos=0;
        var y_pos=0;

    for (var j in  recip.con_array)
     {
      if (j=="length") continue;
       var  _dragElement=$(j);

       x_pos=Math.round(recip.x_max-recip.x_min-_dragElement.offsetWidth)/2;
	_dragElement.style.left=recip.x_min+ x_pos + 'px';
      _dragElement.style.top=recip.y_min+ y_pos + 'px';
     
       this._ZIndex++;
      _dragElement.style.zIndex=this._ZIndex;

       j=this.test_child_recip(_dragElement);

       if ( j!=false )
        {
           for (var i_j=0; i_j<j.length ; i_j++)
            {
      
            this.get_recip_p(this.recipients[j[i_j]]);
            this.move_recip_obj(j[i_j]);
            }
        }
           y_pos+=(_dragElement.offsetHeight);


              k++;
    }
       k=ExtractNumber(recip.s.style.minHeight);
        recip.s.style.height=Math.max(k,(y_pos+recip.ofs_y))  + 'px';

          this.get_recip_p(recip);
 },

  move_recip_obj  : function (r_id)
   {
      if (typeof(this.recipients[r_id])=="undefined" ) 
       {
//         alert("Not Found Recipients "+r_id); 
        return;
       }

        if (this.recipients[r_id].f_u!=null)
        {
         if (this.recipients[r_id].f_u(this,r_id)==false) return;
        }
         this.parent_move_recip_obj(r_id);
    },
  
  refresh_parent : function(par_i,d )
   {
    var r_par=par_i;
     var r_m=this.find_update_recip($(par_i));
 
      par_i=(r_m==false)? [par_i] : r_m; 
  
            for (var i_par_i=0; i_par_i<par_i.length; i_par_i++)
             {
               /* if (d)
                   alert("tst: "+par_i[i_par_i]+" "+d); 
               */
                  this.get_recip_p(this.recipients[ par_i[i_par_i]]);
                // alert(par_i[i_par_i]);
                   this.move_recip_obj(par_i[i_par_i]);  
             }
    }, 

 refresh_id_con: function(id_con)
  {
                        var par_i=this.get_con_arr_hist(this.recipients[id_con].s);
                        par_i=(par_i!=false)? par_i=par_i[par_i.length-1]:id_con;
                        this.refresh_parent(par_i);           
  },

 set_to_recip: function (id_con,_dragElement,r_id,expt,pos,ignore_hist)
  {
    var recip=this.recipients[r_id];
    var d_id=_dragElement.id;

    var w=_dragElement.offsetWidth;
    var h=_dragElement.offsetHeight;

    var x_pos=ExtractNumber(_dragElement.style.left);
    var y_pos=ExtractNumber(_dragElement.style.top);


    var c_pos=(id_con!=false)? this.calculate_rcp_pos(id_con,d_id): false;

    var ac_con=this.in_ac_con_arr(r_id, d_id);

      if (!expt)
       if ( ac_con!=-1 ||
          ( recip.m_ad!=null && 
            recip.m_ad<=recip.con_array.length )
          )
             {

//         x_pos-=w-(recip.x_min-x_pos);
//         y_pos-=h-(recip.y_min-y_pos);

          x_pos=recip.x_min;
          y_pos=recip.y_max;

/*         _dragElement.style.left = x_pos + 'px';
         _dragElement.style.top =  y_pos + 'px';
*/

 if ( id_con!=false)
  {
      this.refresh_id_con(id_con);
     return true;
  }

_dragElement.style.left=this._offsetX+'px';
_dragElement.style.top=this._offsetY+'px';
this.refresh_parent(_dragElement.id);

         return true;
        }

           if ( id_con!=false /* && id_con!=r_id */ )
            {
              delete this.recipients[id_con].con_array[d_id];
               this.recipients[id_con].con_array.length--;
                this.refresh_id_con(id_con);
                 if (this.recipients[id_con].f_o!=null) 
                  if  ( this.recipients[id_con].f_o(this,id_con)==false ) 
                   { /* if ( !ignore_hist ) this.save_hist_recip(id_con,_dragElement,false,c_pos); */  return true; }
            }

//            if (id_con==false || id_con!=r_id ) {

               if (recip.f_i!=null) 
                if ( recip.f_i(this,r_id)==false ) 
                 { 
                    if ( !ignore_hist )
                     this.save_hist_recip(id_con,_dragElement,false,c_pos);
                     return true; 
                 }
        
       pos=((pos==null)? recip.get_insert_pos(_dragElement,recip.con_array): ( ( pos==-1)? pos=recip.con_array.length : pos  ) );
        pos=this.change_sequence( r_id  ,{k:d_id,v:pos},pos);

//             }

           if ( !ignore_hist )
            {
              this.save_hist_recip(id_con,_dragElement,r_id,  c_pos    ,pos);
            }
//-----------------------------------------------------------
    var par_i=this.get_con_arr_hist(recip.s);

//-------------------------------------------------------------------------
              par_i=(par_i!=false)? par_i=par_i[par_i.length-1]:r_id;
//-------------------------------------------------------------------------
              this.refresh_parent(par_i,_dragElement.id);


    return true;
  },

del_obj_recip : function (obj,x_pos,y_pos,id_con,ignore_hist )
 {
    switch (typeof(obj) )
     {
       case "string": obj=document.getElementById(obj);
     }
   id_con=(!id_con)? this.in_con_arr(obj.id) : id_con;

      if (id_con==false)  return;

//       this._dragElement=obj;


var c_pos=this.calculate_rcp_pos(id_con,obj.id);

 delete this.recipients[id_con].con_array[obj.id];
        this.recipients[id_con].con_array.length--;

        this._ZIndex++;
          obj.style.zIndex = this._ZIndex;
          obj.style.left = x_pos + 'px';
          obj.style.top =  y_pos + 'px';    
         this._dragElement=obj;

         this.refresh_id_con(id_con);

         this.refresh_parent(obj.id);

    if (this.recipients[id_con].f_o!=null)
     if  ( this.recipients[id_con].f_o(this,id_con)==false){ this._dragElement=null; return;}
    

         if ( !ignore_hist )
            {
              
              this.save_hist_recip(id_con,this._dragElement,false, c_pos   );
            }

     this._dragElement=null;
 },

 del_all_obj_recip: function(x_pos,y_pos) 
  {
     for (var i in this.recipients)
     {
      if (i=="length") continue;
        if ( this.recipients[i].con_array.length>0 )
        for (var j in this.recipients[i].con_array)
         {
             if (j=="length") continue;
              x_pos+=this.recipients[i].ofs_x;
              y_pos+=this.recipients[i].ofs_y;
            this.del_obj_recip(j,x_pos,y_pos,i);
       
//               alert(x_pos+" "+y_pos+" ofs="+this.recipients[i].ofs_y);
         }
     }
  },

set_obj_to_recip : function (obj,recip,pos,ignore_con,ignore_hist)
 {
    switch (typeof(recip) )
     { 
      case  "object": recip=recip.id;
     }

    switch ( typeof(obj) )
     { 
       case "string": obj=document.getElementById(obj);
     }

     if ( typeof(this.recipients[recip])=="undefined" ||
          obj==null || 
          obj.id==this.recipients[recip].s.id ) return;
     
        var id_con=this.in_con_arr(obj.id);
         this._dragElement=obj;

           if (this.recipients.length>0)
            {
             this._ZIndex++;
              obj.style.zIndex = this._ZIndex;
            } else
               obj.style.zIndex = 10000;
 
    if ( (ignore_con!=null  ) ||  ( this.in_ac_con_arr(recip, obj.id)==-1 ||
          ( this.recipients[recip].m_ad!=null && 
            this.recipients[recip].m_ad<=this.recipients[recip].con_array.length )
          )
       )
        {
         this.get_recip_p(this.recipients[recip]);
         this.set_to_recip(id_con,obj,recip,1,((pos==null)? -1: pos),ignore_hist); 
        }
          this._dragElement=null;
  },

 test_coord_recip: function (_dragElement,recip)
  {
        /*    if ( x_pos<=this.x_max &&
                 ( x_pos>=recip.x_min || x_pos+w>=recip.x_min )&& 
                   y_pos<=recip.y_max && 
                 ( y_pos>=recip.y_min || y_pos+h>=recip.y_min ) && (st_t==false)
                 )
        */

       var x_pos= ExtractNumber(_dragElement.style.left);
       var y_pos= ExtractNumber(_dragElement.style.top);
           var w= _dragElement.offsetWidth;
           var h= _dragElement.offsetHeight;

        return ( x_pos<=recip.x_max && 
               ( x_pos>=recip.x_min || x_pos+w>=recip.x_min) &&  
                 y_pos<=recip.y_max && 
               ( y_pos>=recip.y_min) );
  },

 set_con_recip: function (_dragElement,id_con,i,r_m,par_i)
  {
    var  recip=this.recipients[i];
     if (recip.x_min==null || recip.y_min==null ) return false;

      var con;
       var  d_id= _dragElement.id;

           var par_d=this.get_con_arr_hist(_dragElement);
               par_d=(par_d)? par_d=par_d[par_d.length-1]: par_d;

            if (!par_i)
             {
             var par_i=this.get_con_arr_hist(recip.s);
              par_i=(par_i)? par_i=par_i[par_i.length-1]: i;
             }

       var st_t=false;

          if (r_m!=false && par_i!=false )
           {
              
              for (var i_r_m=0; i_r_m<r_m.length; i_r_m++)
               { 

                 if  (par_i==r_m[i_r_m]) return;
               }          
           } 

              for (var i_r_m=0; i_r_m<r_m.length; i_r_m++)
               {
                 if (i==r_m[i_r_m]) st_t=true;
               } 

              if ( recip.test_coord_recip(_dragElement,recip) && (st_t==false) )
               {
                var con_ar=recip.con_array;

                 if ( con_ar.length>0)
                  {
                    for (var key in con_ar)
                     { 
                        if (key=="length") continue;

                         var rec=this.test_child_recip($(key));

                      if ( rec!=false )
                       for (var i_r=0; i_r<rec.length; i_r++)
                        {
                            con=this.set_con_recip(_dragElement,id_con,rec[i_r],r_m,par_i);
                            if (con) { return true; }
                        }
                     }
                  }

       if ( par_i==par_d && par_d!=false)
        { 
         this.move_recip_obj(par_i);
          return true;
        }
        else
         {
          con=this.set_to_recip(id_con,_dragElement,i);
               if (con) 
                {    
                  if (this.debug)
                   alert("end_p "+par_i); 
                     return true; 
                }
         }
             } 

        return false;
},


 find_update_recip : function (_dragElement)
  {

   if (_dragElement===document.body || _dragElement.className=="recip_blocks" ){ return false; }

    var  result=[];
     var res=this.test_child_recip(_dragElement);
      if (res!=false) result=res;  
       var _parent=_dragElement.parentNode;

        if (_parent===document.body || _parent.className=="recip_blocks"){  return result}; 

         do {
            if (_parent==null){ break; }
             var res=this.test_child_recip(_parent,_dragElement);
              if (res!=false) result=result.concat(res);     
               _dragElement=_parent;
               _parent=_parent.parentNode;
            }
              while (_parent!==document.body && _parent.className!="recip_blocks" );
               return result;
  },

set_to_rec: function (_dragElement)
 {
   if (!_dragElement)  _dragElement=this._dragElement;
    var con=false;
     // test on unconnect
     var id_con=this.in_con_arr(_dragElement.id);

   var r_m=false;
     // test on has recip object
   r_m=this.test_child_recip(_dragElement,null,true); 
    var con=false;

    for (var i in this.recipients)
     {
       if (i=="length") continue;

        this.get_recip_p(this.recipients[i]);

         if (this.debug)
          {
             alert(x_pos+" "+y_pos+"\r\n"+this.recipients[i].x_min+" "+this.recipients[i].y_min+"\r\n"+
                                          this.recipients[i].x_max+" "+this.recipients[i].y_max);
          }

          if ( this.set_con_recip(_dragElement,id_con,i,r_m)) {  con=true; break; }
     }
         if (this.debug)
          {
             alert(con);
          }
            if (con==false)
             {
               if (id_con!=false )
                {
                  this.save_hist_recip(id_con,_dragElement,false,this.calculate_rcp_pos(id_con,_dragElement.id));
                 delete this.recipients[id_con].con_array[_dragElement.id];
                 this.recipients[id_con].con_array.length--;
                 this.refresh_id_con(id_con);
                 if (this.recipients[id_con].f_o!=null) if ( this.recipients[id_con].f_o(this,id_con)==false ) return;
                } else 
                   this.save_hist_recip(false,_dragElement);
             }
      },

    OnMouseUp :function (e)
     {
             
      var t=this;
                        if (!t._dragElement) return;
          if (t.recipients.length>0 && t._dragElement.id.toLowerCase().indexOf(this.recip_cl)>-1 )
           {
             t.set_to_rec();
           } 

            t.delEvent_m(document,"mousemove");
            t.delEvent_m(document,"dragstart");
            t.delEvent_m(document,"mouseup");
            clearSelection();
            disable_all_Selection(document.body,true);


           disable_all_Selection(t._dragElement,true);
             var frame=test_child(t._dragElement,'',function (obj,ir) { if (obj.tagName=="IFRAME") {obj.style.visibility="visible"; }}   )

    		t._dragElement = null;
  },

 set_style_recip : function (r_id,param)
  {
    switch (typeof(r_id) )
     { 
      case  "object": r_id=r_id.id;
     }
   for (var pk in param)
    {    
      this.recipients[r_id].s.style[pk]=param[pk];
    }

     r_id=this.find_update_recip(this.recipients[r_id].s);
      if ( r_id==false ) return;
    
   for (i_r_id=0; i_r_id<r_id.length; i_r_id++)
     for (var j in  this.recipients[r_id[i_r_id]].con_array)
      {
        if (j=="length") continue;
     
         var  _dragElement=$(j);

          j=this.find_update_recip(_dragElement);

         if ( j!=false )
          {
           for (var i_j=0; i_j<j.length; i_j++)
            {
             this.set_style_recip(j[i_j],param);
             }  

          }
          for (var pk in param)
           {    
            _dragElement.style[pk]=param[pk];
           }
      }

  }  

}
