text: /*
  	Copyright (c) 2004-2006, The Dojo Foundation
  	All Rights Reserved.
  
  	Licensed under the Academic Free License version 2.1 or above OR the
  	modified BSD license. For more information on Dojo licensing, see:
  
  		http://dojotoolkit.org/community/licensing.shtml
  */
  
  dojo.provide("dojo.widget.html.Tooltip");
  dojo.require("dojo.widget.html.ContentPane");
  dojo.require("dojo.widget.Tooltip");
  dojo.require("dojo.uri");
  dojo.require("dojo.widget.*");
  dojo.require("dojo.event");
  dojo.require("dojo.style");
  dojo.require("dojo.html");
  
  dojo.widget.html.Tooltip = function(){
  	// mix in the tooltip properties
  	dojo.widget.Tooltip.call(this);
  	dojo.widget.html.ContentPane.call(this);
  }
  dojo.inherits(dojo.widget.html.Tooltip, dojo.widget.html.ContentPane);
  dojo.lang.extend(dojo.widget.html.Tooltip, {
  
  	// Constructor arguments (should these be in tooltip.js rather than html/tooltip.js???)
  	caption: "",
  	showDelay: 500,
  	hideDelay: 100,
  	connectId: "",
  
  	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlTooltipTemplate.html"),
  	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlTooltipTemplate.css"),
  
  	connectNode: null,
  
  	// Tooltip has the following possible states:
  	//   erased - nothing on screen
  	//   displaying - currently being faded in (partially displayed)
  	//   displayed - fully displayed
  	//   erasing - currently being faded out (partially erased)
  	state: "erased",
  
  	fillInTemplate: function(args, frag){
  		if(this.caption != ""){
  			this.domNode.appendChild(document.createTextNode(this.caption));
  		}
  		this.connectNode = dojo.byId(this.connectId);		
  		dojo.widget.html.Tooltip.superclass.fillInTemplate.call(this, args, frag);
  	},
  	
  	postCreate: function(args, frag){
  		// The domnode was appended to my parent widget's domnode, but the positioning
  		// only works if the domnode is a child of document.body
  		document.body.appendChild(this.domNode);
  
  		dojo.event.connect(this.connectNode, "onmouseover", this, "onMouseOver");
  		dojo.widget.html.Tooltip.superclass.postCreate.call(this, args, frag);
  	},
  	
  	onMouseOver: function(e) {
  		this.mouse = {x: e.pageX, y: e.pageY};
  
  		if(!this.showTimer){
  			this.showTimer = setTimeout(dojo.lang.hitch(this, "show"), this.showDelay);
  			dojo.event.connect(document.documentElement, "onmousemove", this, "onMouseMove");
  		}
  	},
  
  	onMouseMove: function(e) {
  		this.mouse = {x: e.pageX, y: e.pageY};
  
  		if(dojo.html.overElement(this.connectNode, e) || dojo.html.overElement(this.domNode, e)) {
  			// If the tooltip has been scheduled to be erased, cancel that timer
  			// since we are hovering over element/tooltip again
  			if(this.hideTimer) {
  				clearTimeout(this.hideTimer);
  				delete this.hideTimer;
  			}
  		} else {
  			// mouse has been moved off the element/tooltip
  			// note: can't use onMouseOut to detect this because the "explode" effect causes
  			// spurious onMouseOut/onMouseOver events (due to interference from outline)
  			if(this.showTimer){
  				clearTimeout(this.showTimer);
  				delete this.showTimer;
  			}
  			if((this.state=="displaying"||this.state=="displayed") && !this.hideTimer){
  				this.hideTimer = setTimeout(dojo.lang.hitch(this, "hide"), this.hideDelay);
  			}
  		}
  	},
  
  	show: function() {
  		if(this.state=="erasing"){
  			// we are in the process of erasing; when that is finished, display it.
  			this.displayScheduled=true;
  			return;
  		}
  		if ( this.state=="displaying" || this.state=="displayed" ) { return; }
  
  		// prevent IE bleed through (iframe creation is deferred until first show()
  		// call because apparently it takes a long time)
  		if(!this.bgIframe){
  			this.bgIframe = new dojo.html.BackgroundIframe(this.domNode);
  		}
  
  		this.position();
  
  		// if rendering using explosion effect, need to set explosion source
  		this.explodeSrc = [this.mouse.x, this.mouse.y];
  
  		this.state="displaying";
  
  		dojo.widget.html.Tooltip.superclass.show.call(this);
  	},
  
  	onShow: function() {
  		dojo.widget.html.Tooltip.superclass.onShow.call(this);
  		
  		this.state="displayed";
  		
  		// in the corner case where the user has moved his mouse away
  		// while the tip was fading in
  		if(this.eraseScheduled){
  			this.hide();
  			this.eraseScheduled=false;
  		}
  	},
  
  	hide: function() {
  		if(this.state=="displaying"){
  			// in the process of fading in.  wait until that is finished and then fade out
  			this.eraseScheduled=true;
  			return;
  		}
  		if ( this.state=="displayed" ) {
  			this.state="erasing";
  			if ( this.showTimer ) {
  				clearTimeout(this.showTimer);
  				delete this.showTimer;
  			}
  			if ( this.hideTimer ) {
  				clearTimeout(this.hideTimer);
  				delete this.hideTimer;
  			}
  			dojo.event.disconnect(document.documentElement, "onmousemove", this, "onMouseMove");
  			dojo.widget.html.Tooltip.superclass.hide.call(this);
  		}
  	},
  
  	onHide: function(){
  		this.state="erased";
  
  		// in the corner case where the user has moved his mouse back
  		// while the tip was fading out
  		if(this.displayScheduled){
  			this.display();
  			this.displayScheduled=false;
  		}
  	},
  
  	position: function(){
  		dojo.html.placeOnScreenPoint(this.domNode, this.mouse.x, this.mouse.y, [10,15], true);
  		this.bgIframe.onResized();
  	},
  
  	onLoad: function(){
  		// the tooltip has changed size due to downloaded contents, so reposition it
  		dojo.lang.setTimeout(this, this.position, 50);
  		dojo.widget.html.Tooltip.superclass.onLoad.apply(this, arguments);
  	},
  
  	onParentResized: function() {
  		// onParentResized() is called when the user has resized the browser window,
  		// but that doesn't affect this widget (or this widget's children)
  		// so it can be safely ignored
  	}
  });
  