
var FreeBubbleDefaultConfig = {
	border_width : 25, 
	border_height : 25, 
	with_pointer : true,
	tab_visible : true, 
	frame_color : "rgb(171,171,171)",
	frame_background_color : "#FFF",
	frame_img_path : "http://map.hongkonghomes.com/map_lib_svg/images/bubble_bg.gif",
	fitting_type : 1,
	align : "center",
	margin_left : 20,
	margin_top : 0,
	extend_mode : 0, // 0 = not allow extend, 1 = within frame, 2 = full screen
	extend_border_width : 20
}

var HkhBubbleConfig = {
	border_width : 4,
	border_height : 4,
	with_pointer : true,
	with_close : false,
	tab_visible : false,
	frame_color : "#000",
	frame_background_color : "#FFF",
	frame_img_path : "http://map.hongkonghomes.com/map_lib_svg/images/bubble_bg.gif",
	fitting_type : 1,
	align : "right",
	margin_left : 11,
	margin_top : 31,
	expend_mode : 0,
	expend_border_width : 0,
	override_sub_div_config : {
		sub9 : {
			style : {width:"7px", height:"10px", overflow:"hidden",position:"absolute",border:"0px #000 solid"},
			inner_html : '<img src="##img_path##" style="left:0px;top:-28px;position:absolute;">'
		},
		sub0 : {
			style : {height:"4px", width:"4px", left:"0px", top:"0px", overflow:"hidden", position:"absolute"},
			inner_html : '<img src="##img_path##" style="left:0px;top:0px;position:absolute;">'
		},
		sub2 : {
			style : {height:"4px", width:"4px", left:"0px", top:"0px", overflow:"hidden", position:"absolute"},
			inner_html : '<img src="##img_path##" style="left:-29px;top:0px;position:absolute;">'
		},	
		sub8 : {
			style : {height:"4px", width:"4px", left:"0px", top:"0px", overflow:"hidden", position:"absolute"},
			inner_html : '<img src="##img_path##" style="left:-29px;top:-28px;position:absolute;">'
		},
		sub6 : {
			style : {height:"4px", width:"4px", left:"0px", top:"0px", overflow:"hidden", position:"absolute"},
			inner_html : '<img src="##img_path##" style="left:0px;top:-6px;position:absolute;">'
		}		
	},
	edge_frame : document.body
}
var HkhHighlightBubbleConfig = {
	border_width : 4,
	border_height : 4,
	with_pointer : true,
	with_close : false,
	tab_visible : false,
	frame_color : "#000",
	frame_background_color : "#FFF",
	frame_img_path : "http://map.hongkonghomes.com/map_lib_svg/images/bubble_bg.gif",
	fitting_type : 1,
	align : "right",
	margin_left : 17,
	margin_top : 41,
	expend_mode : 0,
	expend_border_width : 0,
	override_sub_div_config : {
		sub9 : {
			style : {width:"7px", height:"10px", overflow:"hidden",position:"absolute",border:"0px #000 solid"},
			inner_html : '<img src="##img_path##" style="left:0px;top:-28px;position:absolute;">'
		},
		sub0 : {
			style : {height:"4px", width:"4px", left:"0px", top:"0px", overflow:"hidden", position:"absolute"},
			inner_html : '<img src="##img_path##" style="left:0px;top:0px;position:absolute;">'
		},
		sub2 : {
			style : {height:"4px", width:"4px", left:"0px", top:"0px", overflow:"hidden", position:"absolute"},
			inner_html : '<img src="##img_path##" style="left:-29px;top:0px;position:absolute;">'
		},	
		sub8 : {
			style : {height:"4px", width:"4px", left:"0px", top:"0px", overflow:"hidden", position:"absolute"},
			inner_html : '<img src="##img_path##" style="left:-29px;top:-28px;position:absolute;">'
		},
		sub6 : {
			style : {height:"4px", width:"4px", left:"0px", top:"0px", overflow:"hidden", position:"absolute"},
			inner_html : '<img src="##img_path##" style="left:0px;top:-6px;position:absolute;">'
		}		
	},
	edge_frame : document.body
}

var MapBubble = Class.create();
 
MapBubble.prototype = {
 frame : null,
 object : null,
 div : null,
 content_div : null,
 
 config : FreeBubbleDefaultConfig,
 default_config : FreeBubbleDefaultConfig,
 
 current_tab : null,
 initialize : function (frame, config) 
 {
  try{
  
   if(frame == null)
    return false;
    
   this.map = null;
   
   if(frame instanceof Map2)
   {
    //this.map = frame;
    this.lockToMap(frame);
    frame = this.map.overlay_controller.div;
   }
   
   if(typeof(frame.appendChild) != "function" && typeof(frame.appendChild) != "object")
    return false; 
   
   this.tabs = [];
   
   this.frame = frame;
   this.object = null;
   this.bubble_show_listener = [];
   this.bubble_hide_listener = [];
   
   if(config != null && typeof(config) != "undefined")
    this.config = config;
   
   this.edge_frame = this.config.edge_frame; 
   this.div = document.createElement("DIV");
   
   Element.setStyle(this.div, {display:"none", zIndex:"900", overflow:"visible", position:"absolute", left:"0px", top:"0px"});
 
   this.exp_div = document.createElement("DIV");
   
   Element.setStyle(this.exp_div, {display:"none", zIndex:"900", overflow:"visible", position:"absolute", left:"0px", top:"0px"});
   
   this.exp_shield_div = document.createElement("DIV");
   Element.setStyle(this.exp_div, {display:"none", zIndex:"900", overflow:"visible", position:"absolute", left:"0px", top:"0px"});
   //alert("a");
   this._createObjectComponent();
   //alert("z");
   this.frame.appendChild(this.div);
   this.frame.appendChild(this.exp_div);
   this.frame.appendChild(this.exp_shield_div);
   
  }catch(e)
  {
   this.frame = null;
   this.object = null;
   this.div = null;
   this.tabs = [];
   return false;
  }
 },
 addOnBubbleShowListener : function (func)
 {
  //alert("xx");
  if(typeof(func) != "function")
   return false;
   
  for(var i=0; i < this.bubble_show_listener.length; i++)
  {
   if(this.bubble_show_listener[i] == func)
    return false;
  }
  
  this.bubble_show_listener.push(func);
  //alert( this.bubble_show_listener.length);
 },
 removeOnBubbleShowListener : function (func)
 {
  if(typeof(func) != "function")
   return false;
    
  var pos = -1;
  for(var i=0; i < this.bubble_show_listener.length; i++)
  {
   if(this.bubble_show_listener[i] == func)
   {
    pos = i;
    break;
   }
  }
  if(pos != -1)
  {
   this.bubble_show_listener.splice(pos, 1);
   return true;
  }
  else
  {
   return false;
  }  
 },
 addOnBubbleHideListener : function (func)
 {
 
  if(typeof(func) != "function")
   return false;
   
  for(var i=0; i < this.bubble_hide_listener.length; i++)
  {
   if(this.bubble_hide_listener[i] == func)
    return false;
  }
  
  this.bubble_hide_listener.push(func); 
 },
 removeBubbleHideListener : function (func)
 {
  if(typeof(func) != "function")
   return false;
    
  var pos = -1;
  for(var i=0; i < this.bubble_hide_listener.length; i++)
  {
   if(this.bubble_hide_listener[i] == func)
   {
    pos = i;
    break;
   }
  }
  if(pos != -1)
  {
   this.bubble_hide_listener.splice(pos, 1);
   return true;
  }
  else
  {
   return false;
  } 
 }, 
 _createObjectComponent : function ()
 {
  
  this.sub_div = [];
  this.exp_sub_div = [];
  
  var style = {};
  var inner_html = "";
  var num_of_component = 13;
  
  for(var i=0; i < num_of_component; i++)
  {
   this.sub_div[i] = document.createElement("DIV");
   this.exp_sub_div[i] = document.createElement("DIV");
   
   this.div.appendChild(this.sub_div[i]);
   
   style = {};
   inner_html = "";
   
   switch(i)
   {
    case 0:
     if(this.config.override_sub_div_config != null && this.config.override_sub_div_config.sub0 != null)
     {    
      if(this.config.override_sub_div_config.sub0.style != null && this.config.override_sub_div_config.sub0.style != "")
      {
       style = this.config.override_sub_div_config.sub0.style;
      }
      if(this.config.override_sub_div_config.sub0.inner_html != null && this.config.override_sub_div_config.sub0.inner_html != "")
      {
       inner_html = this.config.override_sub_div_config.sub0.inner_html.replace("##img_path##", this.config.frame_img_path);
      }     
     }
     else
     {
     style = {height:this.config.border_height+"px", width:this.config.border_width+"px", left:"0px", top:"0px", overflow:"hidden", position:"absolute"};
     if(this.config.frame_img_path != null && this.config.frame_img_path != "")
      inner_html = '<img src="'+this.config.frame_img_path+'" style="left:0px;top:0px;position:absolute;">';
     else if(this.config.frame_color != null && this.config.frame_color != "")
     {
      inner_html = "";
      style.borderLeft = "1px solid "+this.config.frame_color;
      style.borderTop = "1px solid "+this.config.frame_color;
     }
     }
     break;
    case 1:
     style = {width:this.config.border_width+"px", height:this.config.border_height+"px", overflow:"hidden", position:"absolute", left:this.config.border_width+"px", top:this.config.border_height+"px", borderTop : "1px solid "+this.config.frame_color,backgroundColor:"#FFF"};
     break;
    case 2:
     if(this.config.override_sub_div_config != null && this.config.override_sub_div_config.sub2 != null)
     {    
      if(this.config.override_sub_div_config.sub2.style != null && this.config.override_sub_div_config.sub2.style != "")
      {
       style = this.config.override_sub_div_config.sub2.style;
      }
      if(this.config.override_sub_div_config.sub2.inner_html != null && this.config.override_sub_div_config.sub2.inner_html != "")
      {
       inner_html = this.config.override_sub_div_config.sub2.inner_html.replace("##img_path##", this.config.frame_img_path);
      }     
     }
     else
     {    
     style = {width:this.config.border_width+"px", height:this.config.border_height+"px", overflow:"hidden", position:"absolute", left:"0px", top:"0px"};
 
     if(this.config.frame_img_path != null && this.config.frame_img_path != "")
      inner_html = '<img src="'+this.config.frame_img_path+'" style="left:-665px;top:0px;position:absolute;">';
     else if(this.config.frame_color != null && this.config.frame_color != "")
     {
      inner_html = "";
      style.borderRight = "1px "+this.config.frame_color+" solid";
      style.borderTop = "1px "+this.config.frame_color+" solid";
     } 
     }
     break;
    case 3:
     style = {width:this.config.border_width+"px", height:this.config.border_height+"px", overflow:"hidden", position:"absolute", left:"0px", top:"25px", borderLeft:"1px solid "+this.config.frame_color,backgroundColor:"#FFF"};
     break;
    case 4:
     style = {overflow:"visible", position:"absolute", left:this.config.border_width+"px", top:this.config.border_height+"px", draggable:false, backgroundColor:"#FFF"};
     this.content_div = this.sub_div[4];
     break;
    case 5:
     style = { width:(this.config.border_width)+"px", height:this.config.border_height+"px", overflow:"hidden", position:"absolute", left:"25px", top:"25px", borderRight:"1px solid "+this.config.frame_color ,backgroundColor:"#FFF" };
     break;
    case 6:
     if(this.config.override_sub_div_config != null && this.config.override_sub_div_config.sub6 != null)
     {    
      if(this.config.override_sub_div_config.sub6.style != null && this.config.override_sub_div_config.sub6.style != "")
      {
       style = this.config.override_sub_div_config.sub6.style;
      }
      if(this.config.override_sub_div_config.sub6.inner_html != null && this.config.override_sub_div_config.sub6.inner_html != "")
      {
       inner_html = this.config.override_sub_div_config.sub6.inner_html.replace("##img_path##", this.config.frame_img_path);
      }     
     }
     else
     {    
     style = {width:this.config.border_width+"px", height:this.config.border_height+"px", overflow:"hidden", position:"absolute", left:"0px", top:"25px"};
     if(this.config.frame_img_path != null && this.config.frame_img_path != "")
      inner_html = '<img src="'+this.config.frame_img_path+'" style="left:0px;top:-665px;position:absolute;">';
     else if(this.config.frame_color != null && this.config.frame_color != "")
     {
      inner_html = "";
      style.borderLeft = "1px solid "+this.config.frame_color;
      style.borderBottom = "1px solid "+this.config.frame_color;
     } 
     }
     break;
    case 7:
     style = {width:this.config.border_width+"px", height:this.config.border_height+"px", overflow:"hidden", position:"absolute", left:this.config.border_width+"px", top:this.config.border_height+"px", borderBottom : "1px solid "+this.config.frame_color,backgroundColor:"#FFF"};    
     break;
    case 8:
     if(this.config.override_sub_div_config != null && this.config.override_sub_div_config.sub2 != null)
     {    
      if(this.config.override_sub_div_config.sub8.style != null && this.config.override_sub_div_config.sub8.style != "")
      {
       style = this.config.override_sub_div_config.sub8.style;
      }
      if(this.config.override_sub_div_config.sub8.inner_html != null && this.config.override_sub_div_config.sub8.inner_html != "")
      {
       inner_html = this.config.override_sub_div_config.sub8.inner_html.replace("##img_path##", this.config.frame_img_path);
      }     
     }
     else
     {    
     style = {width:this.config.border_width+"px", height:this.config.border_height+"px", overflow:"hidden", position:"absolute"};
     if(this.config.frame_img_path != null && this.config.frame_img_path != "")
      inner_html = '<img src="'+this.config.frame_img_path+'" style="left:-665px;top:-665px;position:absolute;">';
     else if(this.config.frame_color != null && this.config.frame_color != "")
     {
      inner_html = "";
      style.borderRight = "1px solid "+this.config.frame_color;
      style.borderBottom = "1px solid "+this.config.frame_color;
     }  
     }    
     break;
    case 9:
     if(this.config.override_sub_div_config != null && this.config.override_sub_div_config.sub9 != null)
     {
      if(this.config.override_sub_div_config.sub9.style != null && this.config.override_sub_div_config.sub9.style != "")
      {
       style = this.config.override_sub_div_config.sub9.style;
      }
      if(this.config.override_sub_div_config.sub9.inner_html != null && this.config.override_sub_div_config.sub9.inner_html != "")
      {
       inner_html = this.config.override_sub_div_config.sub9.inner_html.replace("##img_path##", this.config.frame_img_path);
      }      
     }
     else
     {
      style = {width:"98px", height:"96px", overflow:"hidden",position:"absolute"};
      inner_html = '<img src="'+this.config.frame_img_path+'" style="left:0px;top:-690px;position:absolute;">';
     }
     break;
    case 10:
     style = {cursor:"pointer",width:"10px", height:"30px", overflow:"hidden", position:"absolute"};
     inner_html = 'x';
     Event.observe(this.sub_div[i], "click", this.hide.bindAsEventListener(this)); 
     break;
    case 11:
     style = { height:"30px", left:"0px", top:"-24px", overflow:"visible", position:"absolute", display:"none"};
     break;
    case 12: //Enlarge Component
     style = {cursor:"pointer",width:"20px", height:"20px", overflow:"hidden", position:"absolute"};
     inner_html = '<div style="position:absolute;left:15px;top:5px;font-size:11px;color:'+this.config.frame_color+';">*</div>';
     Event.observe(this.sub_div[i], "click", this.expendCollapse.bindAsEventListener(this));     
     break;
   }
   
   Element.setStyle(this.sub_div[i], style);
   this.sub_div[i].innerHTML = inner_html;
  }
 },
 _refreshComponentPosition : function ()
 {
  var margin_top = 0;
 
  if(this.tabs.length > 0 && this.config.tab_visible)
  {
   this.sub_div[11].style.display = "block";
   if(this.sub_div[4].childNodes.length > 0)
    this.sub_div[11].style.width = this.sub_div[4].childNodes[0].offsetWidth+"px";
   else
    this.sub_div[11].style.width = this.sub_div[4].offsetWidth+"px";
   this.sub_div[11].style.left = this.config.border_width+"px";
   this.sub_div[11].style.top = "0px";
   margin_top = 24;
  }
  else
   this.sub_div[11].style.display = "none";
 
  var sub4width = this.sub_div[4].offsetWidth;
  var sub4height = this.sub_div[4].offsetHeight;
  
  this.sub_div[0].style.top = (0)+"px";
  this.sub_div[1].style.top = (0)+"px";
  this.sub_div[2].style.top = (0)+"px";
  
  this.sub_div[3].style.top = (this.config.border_height)+"px";
  this.sub_div[4].style.top = (this.config.border_height)+"px";
  this.sub_div[5].style.top = (this.config.border_height)+"px";
  
  this.sub_div[10].style.top = (1)+"px";
 
  this.sub_div[3].style.height = sub4height+"px";
  this.sub_div[5].style.height = sub4height+"px";
  //if(this.sub_div[4].childNodes.length > 0 && typeof(this.sub_div[4].childNodes[0]) == "object")
  if(this.sub_div[4].childNodes.length > 0 && typeof(this.sub_div[4].childNodes[0]) == "object" && typeof(this.sub_div[4].childNodes[0].tagName) != "undefined")
  {
   this.sub_div[3].style.height = this.sub_div[4].childNodes[0].offsetHeight+"px";
   this.sub_div[5].style.height = this.sub_div[4].childNodes[0].offsetHeight+"px";
  }
  this.sub_div[6].style.top = (this.config.border_height+sub4height)+"px";
  this.sub_div[7].style.top = (this.config.border_height+sub4height)+"px";
  this.sub_div[8].style.top = (this.config.border_height+sub4height)+"px";
  this.sub_div[9].style.top = (this.config.border_height+sub4height+1)+"px";
 
  this.sub_div[1].style.width = (sub4width)+"px";
  this.sub_div[7].style.width = (sub4width)+"px";
  this.sub_div[2].style.left = (this.config.border_width+sub4width)+"px";
  this.sub_div[5].style.left = (this.config.border_width+sub4width)+"px";
  this.sub_div[8].style.left = (this.config.border_width+sub4width)+"px";
  //this.sub_div[10].style.left = (sub4width)+"px";
  this.sub_div[3].style.height = sub4height+"px";
  this.sub_div[5].style.height = sub4height+"px";
  if(margin_top > 0)
  {
   for(var i=0; i < this.sub_div.length-1; i++)
   {
    this.sub_div[i].style.top = (this.sub_div[i].offsetTop+margin_top)+"px";
   }
  }
  var left = (((sub4width/2)-10)*(-1));
  this.div.style.left = left+"px";
  
  this.sub_div[9].style.left = ((sub4width/2))+"px";
  
  if(this.config != null && this.config.with_close != null && !this.config.with_close)
  {
   this.sub_div[10].style.display = "none";
  }
  else
  {
   this.sub_div[10].style.display = "block";
   this.sub_div[10].style.left = (this.__getBubbleWidth()-this.sub_div[10].offsetWidth)+"px";
  }
   
  if(this.config != null && this.config.expend_mode != null && this.config.expend_mode > 0)
  {
  
  }
  else
   this.sub_div[12].style.display = "none";
  
  var top = 0;
  if(this.config.with_pointer != null && this.config.with_pointer == false)
  {
   top = ((sub4height+this.config.border_height)*(-1));
   this.sub_div[9].style.display = "none";
  }
  else
   top = ((sub4height+this.config.border_height+this.sub_div[9].offsetHeight)*(-1));
  
  
  if(this.object != null && !isNaN(this.object.offsetHeight))
  {
   top -= this.object.offsetHeight;
  }
  if(margin_top > 0)
  {
   top-=(margin_top-2);
  }
  
  this.div.style.top = (top)+"px"; 
 },
 _setTabPosition : function ()
 {
  var zIndex = 65;
  var width_margin = (this.tabs.length*102)-(this.sub_div[11].offsetWidth);
  //alert(this.tabs.length+" , "+width_margin);
  if(width_margin > 0)
  {
   var width_ratio = Math.floor(width_margin/(this.tabs.length-1));
   //alert(width_ratio);
   for(var i=0; i < this.tabs.length; i++)
   {
    if(i > 0)
    {
     //alert((this.tabs[i-1].div.offsetLeft+(102-width_ratio)));
     //alert(width_ratio+" , "+this.tabs[i-1].div.offsetLeft);
     this.tabs[i].div.style.left = (this.tabs[i-1].div.offsetLeft+(width_ratio-107))+"px";
    }
    else
     this.tabs[i].div.style.left = "0px";
 
    if(this.current_tab == i)
    {
     //alert(i);
     this.tabs[i].div.style.zIndex = "68";
    }
    else
    {
     this.tabs[i].div.style.zIndex = zIndex;
     if(this.current_tab == 0)
      zIndex--
     else
      zIndex++;
    }
   }
 
  }
  else
  {
   for(var i=0; i < this.tabs.length; i++)
   {
    this.tabs[i].div.style.left = (i*102)+"px";
    this.tabs[i].div.style.zIndex = zIndex;
    if(this.current_tab == i)
    {
     this.tabs[i].div.style.zIndex = "69";
    }
    else
    {
     this.tabs[i].div.style.zIndex = zIndex;
     if(this.current_tab == 0)
      zIndex--
     else
      zIndex++;
    }
   }
  } 
 },
 setConfig : function (config)
 {
  if(typeof(config) == "object")
  {
   this.config = config;
   return true;
  }
  return false;
 },
 detach : function ()
 {
  this.hide();
  this.object.bubble = null;
  this.object = null;
 },
 /*
 attachToMapPoint : function (map_point)
 {
  if(!(map_point instanceof MapPoint))
   return false;
  
 },
 */
 attachToObject : function (div_object)
 {
  //alert(typeof(div_object));
  if(typeof(div_object) != "object")
   return false;
   
  this.object = div_object;
  this.object.bubble = this;
 },
 __getOffset : function(obj, bool)
 {
  var total=0;
  while(obj!=null)
  {
   total+=obj["offset"+(bool?"Left":"Top")];
 
   obj=obj.offsetParent;
  }
  return total;
 }, 
 __getBubbleWidth : function ()
 {
  return this.sub_div[3].offsetWidth+this.sub_div[4].offsetWidth+this.sub_div[5].offsetWidth;
 },
 __getBubbleHeight : function ()
 {
  return this.sub_div[0].offsetHeight+this.sub_div[3].offsetHeight+this.sub_div[6].offsetHeight+this.sub_div[9].offsetHeight;
 },
 __mapOnZoomListener : function ()
 {
  //alert("z");
 
  if(this.div.style.display == "none")
   return false;
  //alert(xy);
  if(this.object != null)
   this.show();
  else
  {
   if(this.coor == null)
    return false;
   
   //alert(this.coor);
   
   var xy = this.map.__getClientXYByCoor(this.coor[0], this.coor[1]); 
   
   this.show(xy[0], xy[1], true); 
  }
 },
 lockToMap : function (map)
 {
  if(map == null || typeof(map.addOnZoomListener) != "function")
   return false;
  
  this.coor = null;
  this.map = map;
  this.map.addOnZoomListener(this.__mapOnZoomListener.bind(this));
  
  return true;
 },
 unlockToMap : function ()
 {
  this.map = null;
 },
 showByEvent : function (e)
 {
  if(e.clientX == null || e.clientY == null)
   return false;
  var mx = e.clientX;
  var my = e.clientY;
  if(this.map != null)
  {
   mx = e.clientX-this.__getOffset(this.map.overlay_controller.div, true);
   my = e.clientY-this.__getOffset(this.map.overlay_controller.div, false);
  }
//this.coor = this.map.__getCoorByClientXY2(mx+this.__getOffset(this.map.overlay_controller.div, true), my+this.__getOffset(this.map.overlay_controller.div, false));
  this.show(mx,my); 
 },
 show : function (mx, my, b)
 {
  //if(this.object == null)
  // return false;
  for(var i=0; i < this.bubble_show_listener.length; i++)
   this.bubble_show_listener[i](this,0);
     
  if(mx != null && my != null && !isNaN(mx) && !isNaN(my))
  {
   if(this.current_tab == null)
    this.current_tab = this.tabs.length-1;
    
   this.switchTab(this.current_tab);
   this.div.style.display = "block";
   this._refreshComponentPosition();
   this._setTabPosition();   
   //alert(this.div.offsetHeight+" , "+this.div.offsetWidth);
   
   var x = mx-Math.round(this.__getBubbleWidth()/2)+this.config.margin_left;
   var y = my-this.__getBubbleHeight()+this.config.margin_top;
    
 
    
   if(this.object != null && !isNaN(this.object.offsetHeight))
    y -= this.object.offsetHeight;
 
   if(this.config != null && this.config.align != null && this.config.align != "")
   {
    switch (this.config.align)
    {
     case "right":
      var x = (mx+this.config.margin_left);
      this.sub_div[9].style.left = this.config.margin_left+"px";
      break;
     case "left":
      var x = (mx)-Math.round(this.__getBubbleWidth()/2)+this.config.margin_left;
      break;
    }
   }
         
   this.div.style.left=x+"px";
   this.div.style.top=y+"px";
   
   if(this.map != null && b == null)
   {
    this.coor = this.map.__getCoorByClientXY2(mx+this.__getOffset(this.map.overlay_controller.div, true), my+this.__getOffset(this.map.overlay_controller.div, false));
   }
  }
  else
  {
   if(this.object == null)
    return false;
   else
   {
    if(this.current_tab == null)
     this.current_tab = this.tabs.length-1;
     
    this.switchTab(this.current_tab);
    this.div.style.display = "block";
    this._refreshComponentPosition();
    this._setTabPosition();
    
    //var x = this.__getOffset(this.object, true)-Math.round(this.__getBubbleWidth()/2)+this.config.margin_left;
    //var y = this.__getOffset(this.object, false)-this.__getBubbleHeight()+this.config.margin_top;
    var x = (this.object.offsetLeft+(this.object.offsetWidth/2))-Math.round(this.__getBubbleWidth()/2)+this.config.margin_left;
    if(this.config != null && this.config.align != null && this.config.align != "")
    {
     switch (this.config.align)
     {
      case "right":
       var x = (this.object.offsetLeft+this.config.margin_left);
       //this.sub_div[9].style.left = this.config.margin_left+"px";       
       this.sub_div[9].style.left = "0px";       
       break;
      case "left":
       var x = (this.object.offsetLeft+(this.object.offsetWidth))-Math.round(this.__getBubbleWidth()/2)+this.config.margin_left;
       break;
     }
    }
    
    var y = this.object.offsetTop-this.__getBubbleHeight()+this.config.margin_top;
 
    //y -= this.sub_div[9].offsetHeight;
    
    //if(this.object != null && !isNaN(this.object.offsetHeight))
    // y -= this.object.offsetHeight;
     
    this.div.style.left=x+"px";
    this.div.style.top=y+"px";
    
    if(this.map != null)
    {
     this.coor = this.map.__getCoorByClientXY2(this.__getOffset(this.object, true), this.__getOffset(this.object, false));
    }    
   }
  }
  for(var i=0; i < this.bubble_show_listener.length; i++)
   this.bubble_show_listener[i](this,1);  
  //this._checkEdge();
 },
 hide : function ()
 {
 try{
  if(this.div == null || this.div.tagName != "DIV")
   return false;
  for(var i=0; i < this.bubble_hide_listener.length; i++)
   this.bubble_hide_listener[i](this,0);  
  this.div.style.display = "none";
  for(var i=0; i < this.bubble_hide_listener.length; i++)
   this.bubble_hide_listener[i](this,1);   
  return true;
 }catch(e) { return false; }
 },
 isCloseElementClick : function (e, force_not_close)
 {
  if(e.target == this.sub_div[10] || e.target == this.sub_div[10].childNodes[0])
  {
   if(force_not_close != true)
    this.hide();
   return true;
  }
  else
   return false;
 },
 setTab : function (ptitle, pcontent, pwidth, pheight)
 {
  if(ptitle == null || pcontent == null)
   return false;
   
  for(var i=0; i < this.tabs.length; i++)
  {
   if(ptitle == this.tabs[i].title)
   {
    this.tabs[i].content = pcontent;
    if(pwidth != null)
     this.tabs[i].width = pwidth+"px";
    if(pheight != null)
     this.tabs[i].height = pheight+"px";
    return i;
   }
  }
  
  var tmp = {title:ptitle, content:pcontent, width:pwidth+"px", height:pheight+"px"};
  tmp.div = document.createElement("DIV");
  tmp.div.style.width = "102px";
  tmp.div.style.height = "25px";
  tmp.div.style.overflow = "hidden";
  tmp.div.style.position = "absolute";
  tmp.div.style.cursor = "pointer";
  //tmp.div.onclick = this.switchTab.bind(this, i);
  
  tmp.div.style.top = "0px";
  tmp.div.innerHTML = '<img src="'+this.config.frame_img_path+'" style="left:-200px;top:-690px;position:absolute;">';
  tmp.header_div = document.createElement("DIV");
  tmp.header_div.style.width = "102px";
  tmp.header_div.style.height = "22px";
  tmp.header_div.style.overflow = "hidden";
  tmp.header_div.style.position = "absolute";
  tmp.header_div.style.left = "0px";
  tmp.header_div.style.top = "5px";
  tmp.header_div.align = "center";
  tmp.header_div.style.fontSize = "11px";
  tmp.header_div.style.color = "#333333";
  tmp.header_div.innerHTML = tmp.title;
  tmp.div.title = tmp.title;
  tmp.div.appendChild(tmp.header_div);
  this.sub_div[11].appendChild(tmp.div);
  this.tabs[this.tabs.length] = tmp;  
  Event.observe(tmp.div, "click", this.switchTab.bind(this, this.tabs.length-1));
  
  //if(this.current_tab == null)
  // this.current_tab = (this.tabs.length-1);
  return (this.tabs.length-1);
 },
 tabVisible : function (bool)
 {
  if(typeof(bool) != "boolean")
   return false;
   
  this.config.tab_visible = bool;
 },
 _switchTabAction : function (idx)
 {
  if(idx < 0 || idx >= this.tabs.length)
   return false;
   
  //alert("xxx"+this.tabs[idx].width+", "+this.tabs[idx].height);
  
  this.content_div.innerHTML = this.tabs[idx].content;
  this.content_div.style.width = this.tabs[idx].width;
  this.content_div.style.height = this.tabs[idx].height;
  
  var zIndex = 65;
  
  /*if(idx == 0)
  {
  for(var i=this.tabs.length-1; i >= 0; i--)
  {
   if(i == idx)
   {
    this.tabs[i].div.style.zIndex = 70;
   }
   else
   {
    this.tabs[i].div.style.zIndex = zIndex;
    zIndex++;
   }
  }  
  }
  else
  {*/
  for(var i=0; i < this.tabs.length; i++)
  {
   if(i == idx)
   {
    this.tabs[i].div.style.zIndex = 70;
    this.tabs[i].div.childNodes[0].style.left = "-100px";
   }
   else
   {
    this.tabs[i].div.style.zIndex = zIndex;
    this.tabs[i].div.childNodes[0].style.left = "-200px";
    if(idx == 0)
     zIndex--;
    else
     zIndex++;
   }
  }
  //}
  
 },
 switchTab : function (index)
 {
  //alert(index+" "+typeof(index));
  if(typeof(index) == "string")
  {
   for(var i=0; i < this.tabs.length; i++)
   {
    if(this.tabs[i].title == index)
    {
     this.current_tab = i;
     return this._switchTabAction(i);
    }
   }
  }
  else if(typeof(index) == "integer" || typeof(index) == "number")
  {
   this.current_tab = index;
   return this._switchTabAction(index);
  }
 },
 getSnap : function (return_type)
 {
  var snap_obj = {};
  snap_obj.tabs = this.tabs.toJSON();
  snap_obj.config = Object.toJSON(this.config);
  
  if(return_type == "object")
   return snap_obj;
  else if(return_type == "string")
   return Object.toJSON(snap_obj);
  
 },
 _validateSnapObject : function (obj)
 {
  return true; 
 },
 _processSnapStringObject : function (str)
 {
  if(!str.isJSON())
   return false;
   
  var json = str.evalJSON();
  /*if(json.tabs != null && json.tabs.isJSON())
  {
   json.tabs = json.tabs.evalJSON();
  }*/
  
  return json;
 },
 _setCurrentObject : function (obj)
 {
 try{
  if(this._validateSnapObject(obj) === false) 
   return false;
   
  this.config = obj.config;
  
  for(var i=0; i < obj.tabs.length; i++)
  {
   if(obj.title == null || obj.content == null)
    continue;
    
   if(obj.tabs[i].width != null && obj.tabs[i].height != null)
    this.setTab(obj.tabs[i].title, obj.tabs[i].content, obj.tabs[i].width, obj.tabs[i].height);
   else
    this.setTab(obj.tabs[i].title, obj.tabs[i].content);
  }
  return true;
 }
 catch(e)
 {
  alert(e.message);
  return false;
 }
 },
 parseSnap : function (obj_str)
 {
  if(typeof(obj_str) == "string")
  {
   var r = this._processSnapStringObject(obj_str);
   if(r === false)
    return false;
   else 
    return this._setCurrentObject(r);
  }
  else if(typeof(obj_str) == "object")
  {
   return this._setCurrentObject(obj_str);
 
  }
 },
 _setExpendElementsPosition : function ()
 {
 
 },
 expend : function ()
 {
  var width = this.frame.offsetWidth;
  var height = this.frame.offsetHeight;
  
  var div_width = width;
  var div_height = height;
  
  if(this.config != null && this.config.expend_border_width != null && !isNaN(this.config.expend_border_width))
  {
   div_width = width-(this.config.expend_border_width*2);
   div_height = height-(this.config.expend_border_width*2);
  }
  
  Element.setStyle(this.exp_shield_div, {height:height+"px", width:width+"px", backgroundColor:"#333"});
  Element.setOpacity(this.exp_shield_div, 0.5);
  
  Element.setStyle(this.exp_div, {height:div_height+"px", width:div_width+"px"});
  this._setExpendElementsPosition();
 },
 expendAction : function ()
 {
 
 },
 collapse : function ()
 {
  this.exp_div.style.display = "none";
  this.exp_shield_div.style.display = "none";
 },
 collapseAction : function ()
 {
 
 },
 expendCollapse : function (e)
 {
  if(e.target.getAttribute("status") == null || e.target.getAttribute("status") == "")
   return false;
   
  switch (e.target.getAttribute("status"))
  {
   case "expend":
   case "1":
    this.collapse();
    break;
   case "collapse":
   case "0":
    this.expend();
    break;
  }
 },
 setExpendContent : function (html)
 {
  this.exp_sub_div[4].innerHTML = html;
 },
 setFrame : function (obj)
 {
  this.edge_frame = obj;
 },
 checkEdge : function (frame)
 {
  if(frame != null && typeof(frame) == "object")
  {
   var frame_left_1 = this.__getOffset(frame, true);
   var frame_top_1 = this.__getOffset(frame, false);
     
   var frame_left_2 = frame_left_1+frame.offsetWidth;
   var frame_top_2 = frame_top_1+frame.offsetHeight;   
  }
  else if(this.edge_frame != null)
  {
   var frame_left_1 = this.__getOffset(this.edge_frame, true);
   var frame_top_1 = this.__getOffset(this.edge_frame, false);
     
   var frame_left_2 = frame_left_1+this.edge_frame.offsetWidth;
   var frame_top_2 = frame_top_1+this.edge_frame.offsetHeight;   
  }
  else
  {
   var frame_left_1 = this.__getOffset(this.frame, true);
   var frame_top_1 = this.__getOffset(this.frame, false);
     
   var frame_left_2 = frame_left_1+this.frame.offsetWidth;
   var frame_top_2 = frame_top_1+this.frame.offsetHeight;  
  }
  
  var div_left_1 = this.__getOffset(this.div, true);
  var div_top_1 = this.__getOffset(this.div, false);
  
  var div_left_2 = div_left_1+this.__getBubbleWidth();
  var div_top_2 = div_top_1+this.__getBubbleHeight();
  
  //alert("frame: "+frame_left_1+" , "+frame_top_1+" - "+frame_left_2+" , "+frame_top_2+" - "+this.frame.offsetWidth+" , "+this.frame.offsetHeight);
  //alert("div: "+div_left_1+" , "+div_top_1+" - "+div_left_2+" , "+div_top_2);
  
  //Check Top
  
  var top_edge = 0;
  var left_edge = 0;
  
  if(div_top_1 <  frame_top_1)
   top_edge = frame_top_1-div_top_1;
  else if(div_top_2 > frame_top_2)
   top_edge = frame_top_2-div_top_2;
   
  if(div_left_1 < frame_left_1)
   left_edge = frame_left_1-div_left_1;
  else if(div_left_2 > frame_left_2)
   left_edge = frame_left_2-div_left_2;
  
  return [left_edge,top_edge];
 },
 checkMapEdge : function (map, frame, margin)
 {
  var edge = this.checkEdge(frame);
  
  if(margin != null && !isNaN(margin) && edge[0] != 0)
  {
   if(edge[0] > 0)
    edge[0]+=margin;
   else
    edge[0]-=margin;
  }
   
  if(margin != null && !isNaN(margin) && edge[1] != 0)
  {
   if(edge[1] > 0)
    edge[1]+=margin;
   else
    edge[1]-=margin;
  }
    
  map.moveToByXY(edge[0], edge[1]);
 }
 
}