/*  Juice Library bubble.juice.js, version 0.1.3.20080820
 *  Copyright (c) 2007, 2008 Stephen Whiteley (http://jui.ce.it)
 *
 *  See core.juice.js for full license.
 *
/*--------------------------------------------------------------------------*/

(function() {

	if ( typeof Juice == 'undefined' ) {
		throw new Error( 'bubble.juice.js requires the core.juice.js component.' );
	}

	Juice.Bubble = function( node, setup ) {

		var bubble, container, content, pointer, xhttp, myself = this;

		this.setup = function() {

			if ( (node.title == '' || node.alt == '') && !setup.ajax ) { return false; }

			bubble = {
				node:			node,
				directory:	setup.directory || Juice.Prefs.image + 'bubble/',
				value:		node.title || node.alt,
				width:		setup.width || 200,
				height:		setup.height || 'auto',
				maxHeight:	setup.height || 150,
				parent:		Juice.Element.output( Juice.Prefs.container ),
				align:		setup.align || 'center',
				offset:		10
			};

			node.title = node.alt = '';

			container = Juice.Container.create( {
				id: 'juiceBubble',
				width: bubble.width,
				padding: 10
			} );

			container.outer.style.font = '12px/15px arial, verdana';
			container.outer.style.textAlign = 'left';

			container.inner.style.background = '#FFFFe5';

			content = Juice.Element.create( 'DIV', setup.ajax ? '&nbsp;' : bubble.value );

			pointer = Juice.Element.create( 'DIV' );
			pointer.style.position = 'absolute';
			pointer.style.width = '22px';
			pointer.style.height = '11px';

			Juice.Element.append( container.outer, pointer );
			Juice.Element.append( container.inner, content );

			Juice.Event.add( bubble.node, setup.method == 'click' ? 'click' : 'mouseover', myself.show );
			Juice.Event.add( document.body, 'resize', myself.hide );

		};

		this.show = function() {

			myself.clear();

			var exists;
			if ( exists = Juice.$( 'juiceBubble' ) ) {
				exists.parentNode.removeChild( exists );
			}
			
			if ( setup.ajax && typeof xhttp !== 'object' ) {
				if ( typeof Juice.Ajax == 'undefined' ) {
					throw new Error( 'bubble.juice.js requires the core.juice.js component.' );
				} else if ( !bubble.value ) {
					content.innerHTML = '&nbsp;';
					content.style.background = 'url(' + bubble.directory + 'loading.gif) center center no-repeat';
					xhttp = new Juice.Ajax();
					xhttp.ready = function( res ) {
						res = xhttp.evaluate( res );
						content.style.background = 'none';
						content.innerHTML = res.output;
						if ( setup.reload != true ) {
							bubble.value = res.output;
						}
					}
					xhttp.request( setup.ajax, 'GET' );
				}
			}

			Juice.Container.render( container );

			myself.position();

			Juice.Event.add( bubble.node, 'mouseout', myself.delay );
			Juice.Event.add( container.outer, 'mouseover', myself.clear );
			Juice.Event.add( container.outer, 'mouseout', myself.delay );

		};

		this.position = function() {

			var pos = {
				element:		Juice.Element.position( bubble.node ),
				dimensions:	Juice.Element.dimensions( bubble.node ),
				screen:		Juice.Browser.dimensions(),
				scroll:		Juice.Element.scroll()
			};

			var alignment = this.align( pos );

			if ( alignment.container < 0 ) {
				bubble.align = 'left';
			} else if ( alignment.container > pos.screen.width - bubble.width ) {
				bubble.align = 'right';
			}

			alignment = this.align( pos );

			container.outer.style.top = pos.element.top + pos.dimensions.height + bubble.offset + 'px';
			container.outer.style.left = alignment.container + 'px';

			pointer.style.left = alignment.pointer + 'px';

			this.pointer( pos );

			Juice.Container.fix( container );

		};

		this.pointer = function( pos ) {

			var d = Juice.Element.dimensions( container.outer );

			if ( d.height > bubble.maxHeight ) {
				content.style.height = bubble.maxHeight + 'px';
				content.style.overflow = 'auto';
				d.height = Juice.Element.dimensions( container.outer ).height;
			}

			if ( pos.element.top + pos.dimensions.height + bubble.offset + d.height > pos.screen.height ) {
				container.outer.style.top = ( pos.element.top - d.height - bubble.offset ) + 'px';
				pointer.style.background = 'url(' + bubble.directory + 'pointer.gif) center bottom no-repeat';
				pointer.style.top = 'auto';
				pointer.style.bottom = '-10px';
			} else {
				pointer.style.background = 'url(' + bubble.directory + 'pointer.gif) center top no-repeat';
				pointer.style.top = '-10px';
				pointer.style.bottom = 'auto';
			}

		};

		this.align = function( pos ) {

			var a = { container: 0, pointer: 0 };

			switch ( bubble.align ) {
				case 'left':
					a.container = ( pos.element.left - bubble.offset );
					a.pointer = 20;
				break;
				case 'right':
					a.container = ( pos.element.left + pos.dimensions.width + bubble.offset - bubble.width );
					a.pointer = bubble.width - 20 - 22;
				break;
				default:
					a.container = ( pos.element.left - ( bubble.width / 2 ) + ( pos.dimensions.width / 2 ) );
					a.pointer = ( bubble.width ) / 2 - 11;
			}

			return a;

		};

		this.hide = function() {
		
			if ( typeof xhttp == 'object' ) {
				xhttp.abort();
				xhttp = false;
			}

			myself.clear();

			try {
				bubble.parent.removeChild( container.outer );
			} catch ( e ) {}

			Juice.Event.remove( bubble.node, 'mouseout', myself.delay );
			Juice.Event.remove( container.outer, 'mouseover', myself.clear );
			Juice.Event.remove( container.outer, 'mouseout', myself.delay );

		};

		this.delay = function() {

			myself.clear();
			bubble.delay = setTimeout( myself.hide, 500 );

		};

		this.clear = function() {

			bubble.delay = clearTimeout( bubble.delay );

		};

		this.setup();

	}

	Juice.Event.add( window, 'load', function() {

		var elements = document.getElementsByTagName( '*' );
		var expr = new RegExp( 'juiceBubble(?:\\[([^\\]]+)\\])?', 'i' );

		for ( var i = 0; i < elements.length; i++ ) {

			var node = elements[i], matches	= expr.exec( node.className ), width = height = false;

			if ( matches ) {
				if ( matches[1] ) {
					var dimensions = matches[1].split( 'x' );
					width = parseInt( dimensions[0] );
					height = parseInt( dimensions[1] );
				}
				new Juice.Bubble( elements[i], { width: width, height: height } );
			}

		}

	} );

})();