var Debug = {
	write: function( text )
	{
		if( jsDebug && ! Object.isUndefined( window.console ) )
		{
			console.log( text );
		}
	},
	
	error: function( text )
	{
		if( jsDebug && ! Object.isUndefined( window.console ) )
		{
			console.error( text );
		}
	},
	
	dir: function( values )
	{
		if( jsDebug && ! Object.isUndefined( window.console ) )
		{
			console.dir( values );
		}
	},
	
	warn: function( text )
	{
		if( jsDebug && ! Object.isUndefined(window.console) )
		{
			console.warn( text );
		}
	},
	
	info: function( text )
	{
		if( jsDebug && ! Object.isUndefined(window.console) )
		{
			console.info( text );
		}
	},
}

Prototype.Browser.IE6 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 6;
Prototype.Browser.IE7 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 7;
Prototype.Browser.IE8 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 8;
Prototype.Browser.IE9 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 9;

/* Add in stuff prototype does not include */
Prototype.Browser.Chrome = Prototype.Browser.WebKit && ( navigator.userAgent.indexOf('Chrome/') > -1 );

/* ===================================================================================================== */
/* OVERWRITE getOffsetParent TO FIX TD ISSUE */

function isBody(element) {
  return element.nodeName.toUpperCase() === 'BODY';
}

function isHtml(element) {
  return element.nodeName.toUpperCase() === 'HTML';
}

function isDocument(element) {
  return element.nodeType === Node.DOCUMENT_NODE;
}

function isDetached(element) {
  return element !== document.body &&
   !Element.descendantOf(element, document.body);
}

Element.Methods.getOffsetParent = function(element) {
	element = $(element);
	
	if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
	return $(document.body);
	
	if( Prototype.Browser.IE ){
		if (element.offsetParent && element.offsetParent != document.body && Element.getStyle( element.offsetParent, 'position' ) != 'static') return $(element.offsetParent);
		if (element == document.body) return $(element);
	} else {	
		var isInline = (Element.getStyle(element, 'display') === 'inline');
		if (!isInline && element.offsetParent && Element.getStyle(element.offsetParent,'position') != 'static') return $(element.offsetParent);
	}

	while ((element = element.parentNode) && element !== document.body) {
		if (Element.getStyle(element, 'position') !== 'static') {
			return isHtml(element) ? $(document.body) : $(element);
		}
	}

	return $(document.body);
}

window.DM = Class.create({
	namePops: [],
	config: [],
	images: [],
	templates: [],
	lang: [],
	initDone: false,
	
	initialize: function()
	{
		Debug.write( 'Loading theme...' );
		
		document.observe("dom:loaded", function()
		{
   			this.Cookie.init();
			jQuery.ajaxSetup(
			{
				beforeSend: function()
				{
					/*if( ! jQuery('#ajax_loading') )
					{
						jQuery('#dm_body').after( dm.templates['ajax_loading'] );
					}
					
					jQuery('#ajax_loading').fadeIn( 2000 );*/
				},
				
				complete: function()
				{
					/*if( ! jQuery('#ajax_loading') ){ return; }
					jQuery('#ajax_loading').fadeOut( 2000 );*/
					twttr.widgets.load();
					FB.XFBML.parse();
					gapi.plusone.go();
				}
		
			 });
			
			Ajax.Responders.register(
			{
			    onLoading: function()
				{
					/*if( ! $('ajax_loading') )
					{
						if( !dm.templates['ajax_loading'] ){ return; }
						$('dm_body').insert( dm.templates['ajax_loading'] );

					}
				
					var effect = new Effect.Appear( $('ajax_loading'), { duration: 0.2 } );*/
			    },

			  	onComplete: function() 
				{
					/*if( ! $('ajax_loading') ){ return; }
			    	var effect = new Effect.Fade( $('ajax_loading'), { duration: 0.2 } );*/
					twttr.widgets.load();
					FB.XFBML.parse();
					gapi.plusone.go();
			 	}
			});
	
			if(jQuery('#tabs,#bar'))
			{
				Debug.write("Loading tabs");
				
					jQuery('#tabs > ul, #bar').tabs(
					{
						spinner: 'Loading...',
						ajaxOptions: {
							error: function( xhr, status, index, anchor ) {
								jQuery( anchor.hash ).html(
									"" );
							}
						},
						fx: { opacity: 'toggle' }
					});
			}
			
			dm.delegate.initialize();
			
			dm.initDone = true;
			 
		}.bind(this));
	}
});

DM.prototype.delegate = {
	store: $A(),
	
	initialize: function()
	{
		document.observe( 'click', function( e )
		{
			if( Event.isLeftClick( e ) || Prototype.Browser.IE )
			{
				var elem    = null;
				var handler = null;
			
				var target = dm.delegate.store.find( function( item )
				{
					elem = e.findElement( item['selector'] );
					
					if( elem )
					{
						handler = item;
						
						return true;
					}
					else
					{
						return false;
					}
				});
			
				if( ! Object.isUndefined( target ) )
				{				
					if( handler )
					{
						Debug.write( "Disparando chamada para o seletor " + handler['selector'] );
						
						handler['callback']( e, elem, handler['params'] );
					}
				}
			}
        })
	},
	
	register: function( selector, callback, params )
	{
		dm.delegate.store.push( { selector: selector, callback: callback, params: params } );
	}
}

DM.prototype.Cookie = {
	store: [],
	initDone: false,
	
	set: function( name, value, sticky )
	{
		var expires = '';
		var path = '/';
		var domain = '';
		
		if( !name )
		{
			return;
		}
		
		if( sticky )
		{	
			if( sticky == 1 )
			{
				expires = "; expires=Wed, 1 Jan 2020 00:00:00 GMT";
			}
			else if( sticky == -1 ) // Delete
			{
				expires = "; expires=Thu, 01-Jan-1970 00:00:01 GMT";
			}
			else if( sticky.length > 10 )
			{
				expires = "; expires=" + sticky;
			}
		}
		if( dm.config['cookie_domain'] )
		{
			domain = "; domain=" + dm.config['cookie_domain'];
		}
		if( dm.config['cookie_path'] )
		{
			path = dm.config['cookie_path'];
		}
		
		document.cookie = dm.config['cookie_id'] + name + "=" + escape( value ) + "; path=" + path + expires + domain + ';';
		
		dm.Cookie.store[ name ] = value;
		
		Debug.write( "Set cookie: " + dm.config['cookie_id'] + name + "=" + value + "; path=" + path + expires + domain + ';' );
	},
	get: function( name )
	{
		/* Init done yet? */
		if ( dm.Cookie.initDone !== true )
		{
			dm.Cookie.init();
		}
		
		if( dm.Cookie.store[ name ] )
		{
			return dm.Cookie.store[ name ];
		}
		
		return '';
	},
	doDelete: function( name )
	{
		Debug.write("Deleting cookie " + name);
		dm.Cookie.set( name, '', -1 );
	},
	init: function()
	{
		// Already init?
		if ( dm.Cookie.initDone )
		{
			return true;
		}
		
		// Init cookies by pulling in document.cookie
		skip = [];
		cookies = $H( document.cookie.replace(" ", '').toQueryParams(";") );
	
		if( cookies )
		{
			cookies.each( function(cookie){
				cookie[0] = cookie[0].strip();
				
				if( dm.config['cookie_id'] != '' )
				{
					if( !cookie[0].startsWith( dm.config['cookie_id'] ) )
					{
						return;
					}
					else
					{
						cookie[0] = cookie[0].replace( dm.config['cookie_id'], '' );
					}
				}
				
				if( skip[ cookie[0] ] )
				{
					return;
				}
				else
				{
					dm.Cookie.store[ cookie[0] ] = unescape( cookie[1] || '' );
					Debug.write( "Loaded cookie: " + cookie[0] + " = " + cookie[1] );
				}				
			});
		}
		
		dm.Cookie.initDone = true;	
	}
};

/* ===================================================================================================== */
/* AUTOCOMPLETE */

DM.prototype.Autocomplete = Class.create( {
	
	initialize: function(id, options)
	{
		this.id = $( id ).id;
		this.timer = null;
		this.last_string = '';
		this.internal_cache = $H();
		this.pointer = 0;
		this.items = $A();
		this.observing = true;
		this.objHasFocus = null;
		this.options = Object.extend({
			min_chars: 3,
			multibox: false,
			global_cache: false,
			classname: 'autocomplete',
			templates: 	{ 
							wrap: new Template("<ul id='#{id}'></ul>"),
							item: new Template("<li id='#{id}'>#{itemvalue}</li>")
						}
		}, arguments[1] || {});
		
		//-----------------------------------------
		
		if( !$( this.id ) ){
			Debug.error("Invalid textbox ID");
			return false;
		}
		
		this.obj = $( this.id );
		
		if( !this.options.url )
		{
			Debug.error("No URL specified for autocomplete");
			return false;
		}
		
		$( this.obj ).writeAttribute('autocomplete', 'off');
		
		this.buildList();
		
		// Observe keypress
		$( this.obj ).observe('focus', this.timerEventFocus.bindAsEventListener( this ) );
		$( this.obj ).observe('blur', this.timerEventBlur.bindAsEventListener( this ) );
		$( this.obj ).observe('keypress', this.eventKeypress.bindAsEventListener( this ) );
		
	},
	
	eventKeypress: function(e)
	{
		if( ![ Event.KEY_TAB, Event.KEY_UP, Event.KEY_DOWN, Event.KEY_LEFT, Event.KEY_RIGHT, Event.KEY_RETURN ].include( e.keyCode ) ){
			return; // Not interested in anything else
		}
		
		if( $( this.list ).visible() )
		{
			switch( e.keyCode )
			{
				case Event.KEY_TAB:
				case Event.KEY_RETURN:
					this.selectCurrentItem(e);
				break;
				case Event.KEY_UP:
				case Event.KEY_LEFT:
					this.selectPreviousItem(e);
				break;
				case Event.KEY_DOWN:
				case Event.KEY_RIGHT:
					this.selectNextItem(e);
				break;
			}
			
			Event.stop(e);
		}	
	},
	
	// MOUSE & KEYBOARD EVENT
	selectCurrentItem: function(e)
	{
		var current = $( this.list ).down('.active');
		this.unselectAll();
		
		if( !Object.isUndefined( current ) )
		{
			var itemid = $( current ).id.replace( this.id + '_ac_item_', '');
			if( !itemid ){ return; }
			
			// Get value
			var value = this.items[ itemid ].replace('&amp;', '&');
			
			if( this.options.multibox )
			{
				// some logic to get current name
				if( $F( this.obj ).indexOf(',') !== -1 )
				{
					var pieces = $F( this.obj ).split(',');
					pieces[ pieces.length - 1 ] = '';

					$( this.obj ).value = pieces.join(',') + ' ';
				}
				else
				{
					$( this.obj ).value = '';
				}
				
				$( this.obj ).value = $F( this.obj ) + value + ', ';
			}
			else
			{
				$( this.obj ).value = value;
				var effect = new Effect.Fade( $(this.list), { duration: 0.3 } );
				this.observing = false;
			}			
		}
		
		$( this.obj ).focus();
	},
	
	// MOUSE EVENT
	selectThisItem: function(e)
	{
		this.unselectAll();
		
		var items = $( this.list ).immediateDescendants();
		var elem = Event.element(e);
		
		// Find the element
		while( !items.include( elem ) )
		{
			elem = elem.up();
		}
		
		$( elem ).addClassName('active');
	},
	
	// KEYBOARD EVENT
	selectPreviousItem: function(e)
	{
		var current = $( this.list ).down('.active');
		this.unselectAll();
		
		if( Object.isUndefined( current ) )
		{
			this.selectFirstItem();
		}
		else
		{
			var prev = $( current ).previous();
			
			if( prev ){
				$( prev ).addClassName('active');
			}
			else
			{
				this.selectLastItem();
			}
		}
	},
	
	// KEYBOARD EVENT
	selectNextItem: function(e)
	{
		// Get the current item
		var current = $( this.list ).down('.active');
		this.unselectAll();
		
		if( Object.isUndefined( current ) ){
			this.selectFirstItem();
		}
		else
		{
			var next = $( current ).next();
			
			if( next ){
				$( next ).addClassName('active');
			}
			else
			{
				this.selectFirstItem();
			}
		}				
	},
	
	// INTERNAL CALL
	selectFirstItem: function()
	{
		if( !$( this.list ).visible() ){ return; }
		this.unselectAll();
		
		$( this.list ).firstDescendant().addClassName('active');		
	},
	
	// INTERNAL CALL
	selectLastItem: function()
	{
		if( !$( this.list ).visible() ){ return; }
		this.unselectAll();
		
		var d = $( this.list ).immediateDescendants();
		var l = d[ d.length -1 ];
		
		if( l )
		{
			$( l ).addClassName('active');
		}
	},
	
	unselectAll: function()
	{
		$( this.list ).childElements().invoke('removeClassName', 'active');
	},
	
	// Ze goggles are blurry!
	timerEventBlur: function(e)
	{
		window.clearTimeout( this.timer );
		this.eventBlur.bind(this).delay( 0.6, e );
	},
	
	// Phew, ze goggles are focussed again
	timerEventFocus: function(e)
	{
		this.timer = this.eventFocus.bind(this).delay(0.4, e);
	},
	
	eventBlur: function(e)
	{
		this.objHasFocus = false;
		
		if( $( this.list ).visible() )
		{
			var effect = new Effect.Fade( $(this.list), { duration: 0.3 } );
		}
	},
	
	eventFocus: function(e)
	{
		if( !this.observing ){ return; }
		this.objHasFocus = true;
		
		// Keep loop going
		this.timer = this.eventFocus.bind(this).delay(0.6, e);
		
		var curValue = this.getCurrentName();
		if( curValue == this.last_string ){ return; }
		
		if( curValue.length < this.options.min_chars ){
			// Hide list if necessary
			if( $( this.list ).visible() )
			{
				var effect = new Effect.Fade( $( this.list ), { duration: 0.3, afterFinish: function(){ $( this.list ).update() }.bind(this) } );
			}
			
			return;
		}
		
		this.last_string = curValue;
		
		// Cached?
		json = this.cacheRead( curValue );
		
		if( json == false ){
			// No results yet, get them
			var request = new Ajax.Request( this.options.url + escape( curValue ),
								{
									method: 'get',
									evalJSON: 'force',
									onSuccess: function(t)
									{
										if( Object.isUndefined( t.responseJSON ) )
										{
											// Well, this is bad.
											Debug.error("Invalid response returned from the server");
											return;
										}
										
										if( t.responseJSON['error'] )
										{
											switch( t.responseJSON['error'] )
											{
												case 'requestTooShort':
													Debug.warn("Server said request was too short, skipping...");
												break;
												default:
													Debug.error("Server returned an error: " + t.responseJSON['error']);
												break;
											}
											
											return false;
										}
										
										if( t.responseText != "[]" )
										{
										
											// Seems to be OK!
											this.cacheWrite( curValue, t.responseJSON );
											this.updateAndShow( t.responseText.evalJSON() );
										}
									}.bind( this )
								}
							);
		}
		else
		{
			this.updateAndShow( json );
		}				
		
		//Debug.write( curValue );
	},
	
	updateAndShow: function( json )
	{
		if( !json ){ return; }
		
		this.updateList( json );

		if( !$( this.list ).visible() && this.objHasFocus )
		{
			Debug.write("Showing");
			var effect = new Effect.Appear( $( this.list ), { duration: 0.3, afterFinish: function(){ this.selectFirstItem(); }.bind(this) } );
		}
	},
	
	cacheRead: function( value )
	{
		if( this.options.global_cache != false )
		{
			if( !Object.isUndefined( this.options.global_cache[ value ] ) ){
				Debug.write("Read from global cache");
				return this.options.global_cache[ value ];
			}
		}
		else
		{
			if( !Object.isUndefined( this.internal_cache[ value ] ) ){
				Debug.write("Read from internal cache");
				return this.internal_cache[ value ];
			}
		}
		
		return false;
	},
	
	cacheWrite: function( key, value )
	{
		if( this.options.global_cache !== false ){
			this.options.global_cache[ key ] = value;
		} else {
			this.internal_cache[ key ] = value;
		}
		
		return true;
	},
	
	getCurrentName: function()
	{
		if( this.options.multibox )
		{
			// some logic to get current name
			if( $F( this.obj ).indexOf(',') === -1 ){
				return $F( this.obj ).strip();
			}
			else
			{
				var pieces = $F( this.obj ).split(',');
				var lastPiece = pieces[ pieces.length - 1 ];
				
				return lastPiece.strip();
			}
		}
		else
		{
			return $F( this.obj ).strip();
		}
	},
	
	buildList: function()
	{
		if( $( this.id + '_ac' ) )
		{
			return;
		}
		
		var ul = this.options.templates.wrap.evaluate({ id: this.id + '_ac' });
		$$('body')[0].insert( {bottom: ul} );
		
		var finalPos = {};
		
		// Position menu to keep it on screen
		var sourcePos = $( this.id ).viewportOffset();
		var sourceDim = $( this.id ).getDimensions();
		var delta = [0,0];
		var parent = null;
		var screenScroll = document.viewport.getScrollOffsets();
		
		if (Element.getStyle( $( this.id ), 'position') == 'absolute')
		{
			parent = element.getOffsetParent();
			delta = parent.viewportOffset();
	    }
	
		finalPos['left'] = (sourcePos[0] - delta[0]) - 6;
		finalPos['top'] = (sourcePos[1] - delta[1] + screenScroll.top) - 10;
		
		// Now try and keep it on screen
		finalPos['top'] = finalPos['top'] + sourceDim.height;
		
		$( this.id + '_ac' ).setStyle('position: absolute; top: ' + finalPos['top'] + 'px; left: ' + finalPos['left'] + 'px;').hide();
		
		
		this.list = $( this.id + '_ac' );
	},
	
	updateList: function( json )
	{
		if( !json || !$( this.list ) ){ return; }
	
		var newitems ='';
		this.items = $A();
		
		json = $H( json );
		
		json.each( function( item )
			{		
				var li = this.options.templates.item.evaluate({ id: this.id + '_ac_item_' + item.key,
				 												itemid: item.key,
				 												itemvalue: item.value['showas'] || item.value['name'],
				 												img: item.value['img'] || '',
																img_w: item.value['img_w'] || '',
																img_h: item.value['img_h'] || ''
															});
				this.items[ item.key ] = item.value['name'];
	
				newitems = newitems + li;
			}.bind(this)
		);
		
		$( this.list ).update( newitems );
		$( this.list ).immediateDescendants().each( function(elem){
			$( elem ).observe('mouseover', this.selectThisItem.bindAsEventListener(this));
			$( elem ).observe('click', this.selectCurrentItem.bindAsEventListener(this));
			$( elem ).setStyle('cursor: pointer');
		}.bind(this));
		
		if( $( this.list ).visible() )
		{
			this.selectFirstItem();
		}
	}
				
});


/* ==================================================================================================== */
/* ELEMENT EXTENSIONS (tooltips, authorpane etc.) */

Element.addMethods( {
	
	tooltip: function( element, options ){
		
		options = Object.extend( {
			template: new Template("<div class='ipsTooltip' id='#{id}' style='display: none'><div class='ipsTooltip_inner'>#{content}</div></div>"),
			position: 'auto',
			content: $( element ).readAttribute("data-tooltip"),
			animate: true,
			overrideBrowser: true,
			delay: 0.4
		}, options);
		
		var show = function(e){
			if( options.delay && !options._still_going ){
				return; // Action has been cancelled
			}
			
			var id = $(element).identify();

			if( !$( id + '_tooltip' ) ){
				$( document.body ).insert({ 'bottom': options.template.evaluate({ 'id': id + '_tooltip', 'content': options.content }) } );
			}

			if( options.overrideBrowser && $(element).hasAttribute('title') ){
				$(element).writeAttribute("data-title", $(element).readAttribute('title')).writeAttribute("title", false);
			}

			var tooltip = $(id + '_tooltip').setStyle({position: 'absolute'});
			
			// Add word wrap for calculations
			//$(tooltip).setStyle('white-space: nowrap');
			
			var layout = $(element).getLayout();
			var position = $(element).cumulativeOffset();
			var dims = $( id + '_tooltip' ).getDimensions();
			var docDim = $( document.body ).getLayout();
			
			// Detect best position for tooltip
			if( options.position == 'auto' ){
				if( position.left + (layout.get('width')/2) - (dims.width/2) < 0 ){
					options.position = 'right';
				} else if( position.left + (dims.width/2) > docDim.get('width') ){
					options.position = 'left';
				} else {
					options.position = 'top';
				}				
			}
			
			Debug.write( dims );
			
			// And now position
			switch( options.position ){
				case 'top':
					$(tooltip).setStyle( { top: (position.top - dims.height - 1) + 'px', left: (position.left + (layout.get('width')/2) - (dims.width/2)) + 'px' } ).addClassName('top');
				break;
				case 'bottom':
					$(tooltip).setStyle( { top: (position.top + layout.get('height') + 1) + 'px', left: (position.left + (layout.get('width')/2) - (dims.width/2)) + 'px' } ).addClassName('bottom');

				break;
				case 'left':
					$(tooltip).setStyle( { top: (position.top - (layout.get('height') / 2)) + 'px', left: (position.left - dims.width -  3) + 'px' }).addClassName('left');
				break;
				case 'right':
					$(tooltip).setStyle( { top: (position.top - (layout.get('height') / 2)) + 'px', left: (position.left + layout.get('width') - 3) + 'px' }).addClassName('right');
				break;
			}
			
			// Remove word wrap
			//$(tooltip).setStyle('white-space: normal');

			if( options.animate ){
				new Effect.Appear( $(tooltip), { duration: 0.3, queue: 'end' } );
			} else {
				$(tooltip).show();
			}
		},
		hide = function(e){
			var id = $(element).identify();
			if( !$(id + '_tooltip') ){ return; }
			
			if( options.animate ){
				new Effect.Fade( $(id + '_tooltip'), { duration: 0.2, queue: 'end' });
			} else {
				$(id + '_tooltip').hide();
			}
		};
		
		$( element ).observe("mouseenter", function(e){
			if( options.delay ){
				options._still_going = true;
				show.delay( options.delay, e );
			} else {
				show(e);
			}
		}).
		observe("click", function(e){
			options._still_going = false;
			hide();
		}).
		observe("mouseleave", function(e)
		{
			options._still_going = false;
			hide();				
		});	
	}
});

_popup = window.DM;
_popup.prototype.Popup = Class.create({
		
	initialize: function( id, options, callbacks )
	{
		/* Set up properties */
		this.id				= '';
		this.wrapper		= null;
		this.inner			= null;
		this.stem			= null;
		this.options		= {};
		this.timer			= [];
		this.ready			= false;
		this._startup		= null;
		this.hideAfterSetup	= false;
		this.eventPairs		= {	'mouseover': 	'mouseout',
								'mousedown': 	'mouseup'
							  };
		this._tmpEvent 		= null;
		
		/* Now run */
		this.id = id;
		this.options = Object.extend({
			type: 				'pane',
			w: 					'500px',
			modal: 				false,
			modalOpacity: 		0.4,
			hideAtStart: 		true,
			delay: 				{ show: 0, hide: 0 },
			defer: 				false,
			hideClose: 			false,
			closeContents: 		dm.templates['close_popup']		
		}, arguments[1] || {});
		
		this.callbacks = callbacks || {};
		
		// Are we deferring the load?
		if( this.options.defer && $( this.options.attach.target ) )
		{
			this._defer = this.init.bindAsEventListener( this );
			$( this.options.attach.target ).observe( this.options.attach.event, this._defer );
			
			if( this.eventPairs[ this.options.attach.event ] )
			{
				this._startup = function(e){ this.hideAfterSetup = true; this.hide() }.bindAsEventListener( this );
				$( this.options.attach.target ).observe( this.eventPairs[ this.options.attach.event ], this._startup  );
			}
		}
		else
		{
			this.init();
		}
	},
	
	init: function()
	{
		try {
			Event.stopObserving( $( this.options.attach.target ), this.options.attach.event, this._defer );
		} catch(err) { }
		
		this.wrapper = new Element('div', { 'id': this.id + '_popup' } ).setStyle('z-index: 16000').hide().addClassName('popupWrapper');
		this.inner = new Element('div', { 'id': this.id + '_inner' } ).addClassName('popupInner');

		if( this.options.w ){ this.inner.setStyle( 'width: ' + this.options.w ); }
		if( this.options.h ){ this.inner.setStyle( 'max-height: ' + this.options.h ); }
		this.wrapper.insert( this.inner );
		
		if( this.options.hideClose != true )
		{
			this.closeLink = new Element('div', { 'id': this.id + '_close' } ).addClassName('popupClose').addClassName('clickable');
			this.closeLink.update( this.options.closeContents );
			this.closeLink.observe('click', this.hide.bindAsEventListener( this ) );
			this.wrapper.insert( this.closeLink );
		}
		
		$$('body')[0].insert( this.wrapper );
		
		if( this.options.classname ){ this.wrapper.addClassName( this.options.classname ); }
		
		if( this.options.initial ){
			this.update( this.options.initial );
		}
		
		// Callback
		if( Object.isFunction( this.callbacks['beforeAjax'] ) )
		{
			this.callbacks['beforeAjax']( this );
		}
		
		// If we are updating with ajax, handle the show there
		if( this.options.ajaxURL ){
			this.updateAjax();
			setTimeout( this.continueInit.bind(this), 80 );
		} else {
			this.ready = true;
			this.continueInit();
		}
		
		// Need to set a timeout for continue,
		// in case ajax is still running
	},
	
	continueInit: function()
	{
		if( !this.ready )
		{
			setTimeout( this.continueInit.bind(this), 80 );
			return;
		}
		
		//Debug.write("Continuing...");
		// What are we making?
		if( this.options.type == 'balloon' ){
			this.setUpBalloon();
		} else {
			this.setUpPane();
		}
		
		// Set up close event
		try {
			if( this.options.close ){
				closeElem = $( this.wrapper ).select( this.options.close )[0];
				
				if( Object.isElement( closeElem ) )
				{
					$( closeElem ).observe( 'click', this.hide.bindAsEventListener( this ) );
				}
			}
		} catch( err ) {
			Debug.write( err );
		}
		
		// Callback
		if( Object.isFunction( this.callbacks['afterInit'] ) )
		{
			this.callbacks['afterInit']( this );
		}
		
		if( !this.options.hideAtStart && !this.hideAfterSetup )
		{
			this.show();
		}
		if( this.hideAfterSetup && this._startup )
		{	
			Event.stopObserving( $( this.options.attach.target ), this.eventPairs[ this.options.attach.event ], this._startup );
		}
	},
	
	updateAjax: function()
	{
		new Ajax.Request( this.options.ajaxURL,
						{
							method: 'get',
							onSuccess: function(t)
							{
								if( t.responseText != 'error' )
								{
									if( t.responseText == 'nopermission' )
									{
										alert( dm.lang['no_permission'] );
										
										return;
									}
									
									//Debug.write( t.responseText );
									Debug.write( "AJAX done!" );
									this.update( t.responseText );
									this.ready = true;
									
									// Callback
									if( Object.isFunction( this.callbacks['afterAjax'] ) )
									{
										this.callbacks['afterAjax']( this, t.responseText );
									}
								}
								else
								{
									Debug.write( t.responseText );
									return;
								}
							}.bind(this)
						});
	},
	
	show: function(e)
	{
		if( e ){ Event.stop(e); }
		
		if( this.timer['show'] ){
			clearTimeout( this.timer['show'] );
		}
		
		if( this.options.delay.show != 0 ){
			this.timer['show'] = setTimeout( this._show.bind( this ), this.options.delay.show );
		} else {
			this._show(); // Just show it
		}
	},
	
	hide: function(e)
	{
		if( e ){ Event.stop(e); }
		if( this.document_event ){
			Event.stopObserving( document, 'click', this.document_event );
		}
		
		if( this.timer['hide'] ){
			clearTimeout( this.timer['hide'] );
		}
				
		if( this.options.delay.hide != 0 ){
			this.timer['hide'] = setTimeout( this._hide.bind( this ), this.options.delay.hide );
		} else {
			this._hide(); // Just hide it
		}
	},
	
	_show: function()
	{		
		if( this.options.modal == false ){
			new Effect.Appear( $( this.wrapper ), { duration: 0.3, afterFinish: function(){
				if( Object.isFunction( this.callbacks['afterShow'] ) )
				{
					this.callbacks['afterShow']( this );
				}
			}.bind(this) } );
			this.document_event = this.handleDocumentClick.bindAsEventListener(this);
			Event.observe( document, 'click', this.document_event );
		} else {
			new Effect.Appear( $('document_modal'), { duration: 0.3, to: this.options.modalOpacity, afterFinish: function(){
				new Effect.Appear( $( this.wrapper ), { duration: 0.4, afterFinish: function(){
					if( Object.isFunction( this.callbacks['afterShow'] ) )
					{
						this.callbacks['afterShow']( this );
					}
			 	}.bind(this) } )
			}.bind(this) });
		}
	},
	
	_hide: function()
	{
		if( this._tmpEvent != null )
		{
			Event.stopObserving( $( this.wrapper ), 'mouseout', this._tmpEvent );
			this._tmpEvent = null;
		}
		
		if( this.options.modal == false ){
			new Effect.Fade( $( this.wrapper ), { duration: 0.3, afterFinish: function(){
				if( Object.isFunction( this.callbacks['afterHide'] ) )
				{
					this.callbacks['afterHide']( this );
				}
			}.bind(this) } );
		} else {
			new Effect.Fade( $( this.wrapper ), { duration: 0.3, afterFinish: function(){
				new Effect.Fade( $('document_modal'), { duration: 0.2, afterFinish: function(){
					if( Object.isFunction( this.callbacks['afterHide'] ) )
					{
						this.callbacks['afterHide']( this );
					}
				}.bind(this) } )
			}.bind(this) });
		}
	},
	
	handleDocumentClick: function(e)
	{
		if( !Event.element(e).descendantOf( this.wrapper ) )
		{
			this._hide(e);
		}
	},
	
	update: function( content, evalScript )
	{
		this.inner.update( content );
		
		// Should this popup eval scripts? Default is YES
		if( Object.isUndefined( evalScript ) || evalScript != false ){
			this.inner.innerHTML.evalScripts();
		}
	},
	
	setUpBalloon: function()
	{
		// Are we attaching?
		if( this.options.attach )
		{
			var attach = this.options.attach;
			
			if( attach.target && $( attach.target ) )
			{
				if( this.options.stem == true )
				{
					this.createStem();
				}
				
				// Get position
				if( !attach.position ){ attach.position = 'auto'; }
				
				if( Object.isUndefined( attach.offset ) ){ attach.offset = { top: 0, left: 0 } }
				if( Object.isUndefined( attach.offset.top ) ){ attach.offset.top = 0 }
				if( Object.isUndefined( attach.offset.left ) ){ attach.offset.left = 0 }
				
				if( attach.position == 'auto' )
				{
					Debug.write("Popup: auto-positioning");
					var screendims 		= document.viewport.getDimensions();
					var screenscroll 	= document.viewport.getScrollOffsets();
					var toff			= $( attach.target ).viewportOffset();
					var wrapSize 		= $( this.wrapper ).getDimensions();
					var delta 			= [0,0];
					
					if (Element.getStyle( $( attach.target ), 'position') == 'absolute')
					{
						var parent = element.getOffsetParent();
						delta = parent.viewportOffset();
				    }

				    toff['left'] = toff[0] - delta[0];
					toff['top'] = toff[1] - delta[1] + screenscroll.top;

					//Debug.write( toff['left'] + "    " + toff['top'] );
					// Need to figure out if it will be off-screen
					var start 	= 'top';
					var end 	= 'left';

					//Debug.write( "Target offset top: " + toff.top + ", wrapSize Height: " + wrapSize.height + ", screenscroll top: " + screenscroll.top);
					if( ( toff.top - wrapSize.height - attach.offset.top ) < ( 0 + screenscroll.top ) ){
						var start = 'bottom';
					}
					
					if( ( toff.left + wrapSize.width - attach.offset.left ) > ( screendims.width - screenscroll.left ) ){
						var end = 'right';
					}

					finalPos = this.position( start + end, { target: $( attach.target ), content: $( this.wrapper ), offset: attach.offset } );
					
					if( this.options.stem == true )
					{
						finalPos = this.positionStem( start + end, finalPos );
					}
				}
				else
				{
					Debug.write("Popup: manual positioning");
					
					finalPos = this.position( attach.position, { target: $( attach.target ), content: $( this.wrapper ), offset: attach.offset } );
					
					if( this.options.stem == true )
					{
						finalPos = this.positionStem( attach.position, finalPos );
					}
				}
				
				// Add mouse events
				if( !Object.isUndefined( attach.event ) ){
					$( attach.target ).observe( attach.event, this.show.bindAsEventListener( this ) );
					
					if( attach.event != 'click' && !Object.isUndefined( this.eventPairs[ attach.event ] ) ){
						$( attach.target ).observe( this.eventPairs[ attach.event ], this.hide.bindAsEventListener( this ) );
					}
						
					$( this.wrapper ).observe( 'mouseover', this.wrapperEvent.bindAsEventListener( this ) );					
				}				
			}
		}

		Debug.write("Popup: Left: " + finalPos.left + "; Top: " + finalPos.top);
		$( this.wrapper ).setStyle( 'top: ' + finalPos.top + 'px; left: ' + finalPos.left + 'px; position: absolute;' );
	},
	
	wrapperEvent: function(e)
	{
		if( this.timer['hide'] )
		{
			// Cancel event now
			clearTimeout( this.timer['hide'] );
			this.timer['hide'] = null;
			
			if( this.options.attach.event && this.options.attach.event == 'mouseover' )
			{
				// Set new event to account for mouseout of the popup,
				// but only if we don't already have one - otherwise we get
				// expontentially more event calls. Bad.
				if( this._tmpEvent == null ){
					this._tmpEvent = this.hide.bindAsEventListener( this );
					$( this.wrapper ).observe('mouseout', this._tmpEvent );
				}
			}
		}
	},
	
	positionStem: function( pos, finalPos )
	{
		var stemSize = { height: 16, width: 31 };
		var wrapStyle = {};
		var stemStyle = {};
		
		switch( pos.toLowerCase() )
		{
			case 'topleft':
				wrapStyle = { marginBottom: stemSize.height + 'px' };
				
				stemStyle = { bottom: -(stemSize.height) + 'px', left: '5px' };
				finalPos.left = finalPos.left - 15;
				
				break;
			case 'topright':
				wrapStyle = { marginBottom: stemSize.height + 'px' };

				stemStyle = { bottom: -(stemSize.height) + 'px', right: '5px' };
				finalPos.left = finalPos.left + 15;
				
				break;
			case 'bottomleft':
				wrapStyle = { marginTop: stemSize.height + 'px' };

				stemStyle = { top: -(stemSize.height) + 'px', left: '5px' };
				finalPos.left = finalPos.left - 15;
				
				break;
			case 'bottomright':
				wrapStyle = { marginTop: stemSize.height + 'px' };

				stemStyle = { top: -(stemSize.height) + 'px', right: '5px' };
				finalPos.left = finalPos.left + 15;
				
				break;
		}

		$( this.wrapper ).setStyle( wrapStyle );
		$( this.stem ).setStyle( stemStyle ).setStyle('z-index: 6000').addClassName( pos.toLowerCase() );
		
		return finalPos;
	},
	
	position: function( pos, v )
	{
		finalPos = {};
		var toff			= $( v.target ).viewportOffset();
		var tsize	 		= $( v.target ).getDimensions();
		var wrapSize 		= $( v.content ).getDimensions();
		var screenscroll 	= document.viewport.getScrollOffsets();
		var offset 			= v.offset;
		var delta			= [0,0];
		
		if (Element.getStyle( $( v.target ), 'position') == 'absolute')
		{
			var parent = element.getOffsetParent();
			delta = parent.viewportOffset();
	    }
		
		toff['left'] = toff[0] - delta[0];
		toff['top'] = toff[1] - delta[1];

		if( !Prototype.Browser.Opera ){
			toff['top'] += screenscroll.top;
		}
		
		switch( pos.toLowerCase() )
		{
			case 'topleft':
				finalPos.top = ( toff.top - wrapSize.height - tsize.height ) - offset.top;

				finalPos.left = toff.left + offset.left;
				
				break;
			case 'topright':
			 	finalPos.top = ( toff.top - wrapSize.height - tsize.height ) - offset.top;

				finalPos.left = ( toff.left - ( wrapSize.width - tsize.width ) ) - offset.left;
				
				break;
			case 'bottomleft':
				finalPos.top = ( toff.top + tsize.height ) + offset.top;
				
				finalPos.left = toff.left + offset.left;
				
				break;
			case 'bottomright':
				finalPos.top = ( toff.top + tsize.height ) + offset.top;

				finalPos.left = ( toff.left - ( wrapSize.width - tsize.width ) ) - offset.left;
				
				break;
		}
		
		return finalPos;
	},
	
	createStem: function()
	{
		this.stem = new Element('div', { id: this.id + '_stem' } ).update('&nbsp;').addClassName('stem');
		this.wrapper.insert( { top: this.stem } );
	},
	
	setUpPane: function()
	{
		// Does the document have a modal blackout?
		if( !$('document_modal') ){
			this.createDocumentModal();
		}
		
		this.positionPane();	
	},
	
	positionPane: function()
	{
		// Position it in the middle
		var elem_s = $( this.wrapper ).getDimensions();
		var window_s = document.viewport.getDimensions();
		var window_offsets = document.viewport.getScrollOffsets();

		var center = { 	left: ((window_s['width'] - elem_s['width']) / 2),
						 top: (((window_s['height'] - elem_s['height']) / 2)/2)
					}
						
		if( center.top < 10 ){ center.top = 10; }
						
		$( this.wrapper ).setStyle('top: ' + center['top'] + 'px; left: ' + center['left'] + 'px; position: fixed;');
	},
			
	createDocumentModal: function()
	{
		var pageLayout = $( document.body ).getLayout();
		var pageSize = { width: pageLayout.get('width'), height: pageLayout.get('margin-box-height') };
		var viewSize = document.viewport.getDimensions();
		
		var dims = [];
		
		Debug.dir( pageSize );
		Debug.dir( viewSize );
		
		if( viewSize['height'] < pageSize['height'] ){
			dims['height'] = pageSize['height'];
		} else {
			dims['height'] = viewSize['height'];
		}
		
		if( viewSize['width'] < pageSize['width'] ){
			dims['width'] = pageSize['width'];
		} else {
			dims['width'] = viewSize['width'];
		}
		
		var modal = new Element( 'div', { 'id': 'document_modal' } ).addClassName('modal').hide();
		
		modal.setStyle('width: ' + dims['width'] + 'px; height: ' + dims['height'] + 'px; position: absolute; top: 0px; left: 0px; z-index: 15000;');
		
		$$('body')[0].insert( modal );
	},
	
	getObj: function()
	{
		return $( this.wrapper );
	}
});

var _menu = window.DM;
_menu.prototype.menus = {
	registered: $H(),
	closeCallBack: false,
	
	init: function()
	{
		Debug.write("Initializing dm.menu.js");
		document.observe("dom:loaded", function(){
			dm.menus.initEvents();
		});
	},
	
	initEvents: function()
	{  
		// Set document event
		Event.observe( document, 'click', dm.menus.docCloseAll );
		
		// Auto-find menus
		$$('.dmmenu').each( function(menu){
			id = menu.identify();
			if( $( id + "_menucontent" ) )
			{ 
				new dm.Menu( menu, $( id + "_menucontent" ) );
			}
		});
	},
	
	register: function( source, obj )
	{
		dm.menus.registered.set( source, obj );
	},
	
	registerCloseCallBack: function( callBack )
	{
		dm.menus.closeCallBack = callBack;
	},
	
	docCloseAll: function( e )
	{
		dm.menus.closeAll( e );
	},
	
	closeAll: function( except )
	{ 
		dm.menus.registered.each( function(menu, force){
		
			if( typeof( except ) == 'undefined' || ( except && menu.key != except ) )
			{
				try{
					if( !(except.target && $(except.target).descendantOf( menu.value.target )) && except != menu.key ){
						menu.value.doClose();
					}
				} catch(err) {
					// Assume this menu gone byebye
				}
			}
		});
		
		/* Could make this an array and chain events */
		if ( Object.isFunction( dm.menus.closeCallBack ) )
		{
			dm.menus.closeCallBack();
		}
	}	
};

_menu.prototype.Menu = Class.create({
	initialize: function( source, target, options, callbacks ){
		if( !$( source ) || !$( target ) ){ return; }
		if( !$( source ).id ){
			$( source ).identify();
		}
		this.id = $( source ).id + '_menu';
		this.source = $( source );
		this.target = $( target );
		this.callbacks = callbacks || {};
		
		this.options = Object.extend( {
			eventType: 'click',
			stopClose: true,
			offsetX: 0,
			offsetY: 0
		}, arguments[2] || {});
		
		// Set up events
		$( source ).observe( 'click', this.eventClick.bindAsEventListener( this ) );
		$( source ).observe( 'mouseover', this.eventOver.bindAsEventListener( this ) );
		$( target ).observe( 'click', this.targetClick.bindAsEventListener( this ) );

		// Set up target
		$( this.target ).setStyle( 'position: absolute;' ).hide().setStyle( { zIndex: 9999 } );
		$( this.target ).descendants().each( function( elem ){
			$( elem ).setStyle( { zIndex: 10000 } );
		});
		
		dm.menus.register( $( source ).id, this ); 
		
		if( Object.isFunction( this.callbacks['afterInit'] ) )
		{
			this.callbacks['afterInit']( this );
		}
	},
	
	doOpen: function()
	{
		Debug.write("Menu open");
		var pos = {};
		
		var _source = ( this.options.positionSource ) ? this.options.positionSource : this.source;
	
		// This is the positioned offset of the source element
		var sourcePos		= $( _source ).positionedOffset();
		
		// Cumulative offset (actual position on the page, e.g. if you scrolled down it could be higher than max resolution height)
		var _sourcePos		= $( _source ).cumulativeOffset();
		
		// Cumulative offset of your scrolling (how much you have scrolled)
		var _offset			= $( _source ).cumulativeScrollOffset();
		
		// Real source position: Actual position on page, minus scroll offset (provides position on page within viewport)
		var realSourcePos	= { top: _sourcePos.top - _offset.top, left: _sourcePos.left - _offset.left };
		
		// Dimensions of source object
		var sourceDim		= $( _source ).getDimensions();
		
		// Viewport dimensions (e.g. 1280x1024)
		var screenDim		= document.viewport.getDimensions();
		
		// Target dimensions
		var menuDim			= { width: $( this.target ).measure('border-box-width'), height: $(this.target).measure('border-box-height') };
		
		var isFixed = $( _source ).ancestors().find( function(el){ return el.getStyle('position') == 'fixed'; } );
		
		// Some logging	
		Debug.write( "realSourcePos: " + realSourcePos.top + " x " + realSourcePos.left );
		Debug.write( "sourcePos: " + sourcePos.top + " x " + sourcePos.left );
		Debug.write( "scrollOffset: " + _offset.top + " x " + _offset.left );
		Debug.write( "_sourcePos: " + _sourcePos.top + " x " + _sourcePos.left );
		Debug.write( "sourceDim: " + sourceDim.width + " x " + sourceDim.height);
		Debug.write( "menuDim: " + menuDim.height );
		Debug.write( "screenDim: " + screenDim.height );
		Debug.write( "manual ofset: " + this.options.offsetX + " x " + this.options.offsetY );

		// Ok, if it's a relative parent, do one thing, else be normal
		// Getting fed up of this feature and IE bugs
		_a = _source.getOffsetParent();
		_b = this.target.getOffsetParent();
		
		Debug.write("_a is " + _a );
		Debug.write("_b is " + _b );
		
		if( isFixed )
		{
			$( this.target ).setStyle('position: fixed');
			
			if( ( _sourcePos.left + menuDim.width ) > screenDim.width ){
				diff = menuDim.width - sourceDim.width;
				pos.left = _sourcePos.left - diff + this.options.offsetX;
			} else {
				pos.left = (_sourcePos.left) + this.options.offsetX;
			}
			
			if( ( _sourcePos.top + menuDim.height ) > screenDim.height ){
				pos.top = _sourcePos.top - menuDim.height + this.options.offsetY;
			} else {
				pos.top = _sourcePos.top + sourceDim.height + this.options.offsetY;
			}
			
			
			$( this.target ).setStyle( 'top: ' + (pos.top-1) + 'px; left: ' + pos.left + 'px;' );
		}
		else
		{
			if( _a != _b )
			{
				// Left
				if( ( realSourcePos.left + menuDim.width ) > screenDim.width ){
					diff = menuDim.width - sourceDim.width;
					pos.left = _sourcePos.left - diff + this.options.offsetX;
				} else {
					if( Prototype.Browser.IE7 ){
						pos.left = (_sourcePos.left) + this.options.offsetX;
					} else {
						pos.left = (_sourcePos.left) + this.options.offsetX;
					}
				}
			
				// Top
				/* If there's no space to open downwards, open upwards *unless*
				/* it would go off the top of the screen (i.e. < 0px ) Bug #18270 */
				if( 
					( ( ( realSourcePos.top + sourceDim.height ) + menuDim.height ) > screenDim.height ) &&
					( sourcePos.top - menuDim.height + this.options.offsetY ) > 0 )
				{
					pos.top = _sourcePos.top - menuDim.height + this.options.offsetY;
				} else {
					pos.top = _sourcePos.top + sourceDim.height + this.options.offsetY;
				}
			}
			else
			{
				Debug.write("MENU: source offset EQUALS target offset");
			
				// Left
				if( ( realSourcePos.left + menuDim.width ) > screenDim.width ){
					diff = menuDim.width - sourceDim.width;
					pos.left = sourcePos.left - diff + this.options.offsetX;
				} else {
					pos.left = sourcePos.left + this.options.offsetX;
				}
			
				// Top
				/* If there's no space to open downwards, open upwards *unless*
				/* it would go off the top of the screen (i.e. < 0px ) Bug #18270 */
				if( 
					( ( ( realSourcePos.top + sourceDim.height ) + menuDim.height ) > screenDim.height ) &&
					( _sourcePos.top - menuDim.height + this.options.offsetY ) > 0 )
				{
					pos.top = sourcePos.top - menuDim.height + this.options.offsetY;
				} else {
					pos.top = sourcePos.top + sourceDim.height + this.options.offsetY;
				}
			}
			
			//$( this.target ).setStyle( 'top: ' + (pos.top-1) + 'px; left: ' + pos.left + 'px;' );
		}
		
		$( this.source ).addClassName('menu_active'); // Set active class on the source
		
		// Now set pos
		Debug.write("Menu position: " + pos.top + " x " + pos.left );
		
		
		// If we have any fixed ancestors, then fix the menu too
		/*if( isFixed ){
			$( this.target ).setStyle('position: fixed');
		}*/
		
		// And show
		new Effect.Appear( $( this.target ), { duration: 0.2, afterFinish: function(e){
				if( Object.isFunction( this.callbacks['afterOpen'] ) )
				{
					this.callbacks['afterOpen']( this );
				}
		}.bind(this) } );
		
		// Set key event so we can close on ESC
		Event.observe( document, 'keypress', this.checkKeyPress.bindAsEventListener( this ) );
	},
	
	checkKeyPress: function( e )
	{
		//Debug.write( e );
		
		if( e.keyCode == Event.KEY_ESC )
		{
			this.doClose();
		}		
	},

	doClose: function()
	{
		new Effect.Fade( $( this.target ), { duration: 0.3, afterFinish: function(e){
				if( Object.isFunction( this.callbacks['afterClose'] ) )
				{
					this.callbacks['afterClose']( this );
				}
		 }.bind( this ) } );
		
		//Debug.write( "Closing " + $( this.source ).id );
		this.source.removeClassName('menu_active');
	},
	
	targetClick: function(e)
	{
		if( !this.options.stopClose ){
			alert('targetclick');
			this.doClose();
		}
		
		/*try
		{
			var elem = Event.findElement(e);
			
			if ( elem.hasClassName('_noCloseMenuUponClick') )
			{
				Event.stop(e);
			}
		}
		catch(e) { }
		
		if( ( this.options.stopClose && !$(elem).match("input") || $(elem).match("input") ) ){
			//if( $(e.target).match("[type=checkbox]")){
			//	Debug.write( $(e.target).checked );
			//	$(e.target).checked = true;
			//}
			Event.stop(e);
		}*/
	},
	
	eventClick: function(e)
	{
		Event.stop(e);
		
		if( $( this.target ).visible() ){
			
			if( Object.isFunction( this.callbacks['beforeClose'] ) )
			{
				this.callbacks['beforeClose']( this );
			}
			
			this.doClose();
		} else {
			dm.menus.closeAll( $(this.source).id );
			
			if( Object.isFunction( this.callbacks['beforeOpen'] ) )
			{
				this.callbacks['beforeOpen']( this );
			}
			
			this.doOpen();
		}
	},
	
	eventOver: function()
	{
		
	}
});

var _global = window.DM;

_global.prototype.global = {
	fetchMore: {},
	activeTab: 'latest',
	
	init: function()
	{
		Debug.write( 'Loading global' );
		
		document.observe("dom:loaded", function()
		{
			dm.global.initEvents();
		});
		
		Event.observe( window, 'load', function(){
			// Resize images
			$$('.post').each( function(elem){
				dm.global.findImgs( $( elem ) );
			});
		});
	},
	
	initEvents: function()
	{
		dm.delegate.register('a[rel~="external"]', dm.global.openNewWindow );
		dm.delegate.register(".__magazine", dm.global.magazinePopup);
		dm.delegate.register('.tb_toggle', dm.global.changeTabContent );
		//dm.delegate.register(".share-btn", dm.global.showShareBox );
		
		/* This is needed for RTL - the generic anchoring isn't working on RTL for some reason */
		if( $('backtotop') ){
			$('backtotop').observe( "click", function(e){ Event.stop(e); window.scroll( 0, 0 ); } );
		}
		
		// Tooltips
		$$("[data-tooltip]").invoke('tooltip');
		
		if($('load_more'))
		{
			$('load_more').observe('click',dm.global.loadMore);
			$('.more-news-btn').show();
		}
		
		$$('.__share').each( function( elem )
		{
			try
			{
				var row = $(elem).up(".__post");
				var id = $(row).readAttribute("data-id")
				//_key = $(elem).readAttribute( "hovercard-ref" );
				
				//$$( '.shortlink' ).identify();
				
				var callback = { 
					afterOpen: function( popup ){
						try {
							$( $("shortlink_" + id + "_input") ).activate();
						}
						catch(err){ }
					}
				};
				
				new dm.Menu( $("__share" + id), $("share_" + id + "_menucontent"), { stopClose: true }, callback );
			}
			catch( err )
			{
				Debug.error( err );
			}
		} );
	},
	
	loadMore: function( e )
	{
		Event.stop(e);		
		if( !dm.global.fetchMore ){ return; }
		
		dm.global.fetchMore['startPage'] += 1;
		
		var url = dm.config['admin_ajax'] + "?action=load_more_stories&" + $H(dm.global.fetchMore).toQueryString();
		Debug.write( url );
		new Ajax.Request( url.replace(/&amp;/g, '&'),
						{
							method: 'get',
							evalJSON: 'force',
							onSuccess: function(t){
								Debug.dir( t.responseJSON );
								if( t.responseJSON['posts'] == '' )
								{
									jQuery('.more-news-btn').update("<span class='desc lighter'>No more posts to show</span>");
									return;
								}
								
								$$('div.dynamic_update').invoke("removeClassName", "dynamic_update");
								var newtbody = new Element("div", {'class': 'dynamic_update'});
								$('panes_wrap').select('div:last')[0].insert({ 'before': newtbody});
								newtbody.update( t.responseJSON['posts'] );
								
								if( t.responseJSON['posts'] == '' || t.responseJSON['hasMore'] == false)
								{
									jQuery('.more-news-btn').update("<span class='desc lighter'>No more posts to show</span>");
									return;
								}								
							}
						});
	},
	
	changeTabContent: function(e, elem)
	{
		Event.stop(e);
		var id = elem.id.replace('tb_link:', '');
		if( !id || id.blank() ){ return; }
		
		if( dm.global.activeTab == id )
		{
			return;
		}
		
		oldTab = dm.global.activeTab;
		dm.global.activeTab = id;
		
		if( !$('pane_' + id) )
		{
			new Ajax.Request( dm.config['admin_ajax'],
							{
								method: 'post',
								parameters: { action: 'retrieve_home_content_ajax', tab: id },
								evalJS: true,
								asynchronous: true,
								
								onSuccess: function(t)
								{
									if( t.responseText != 'error' )
									{
										Debug.write(t.responseText);
										
										var newdiv = new Element('div', { 'id': 'pane_' + id } ).hide().update( t.responseText );
										$('panes_wrap').insert( newdiv );
										
										dm.global.togglePanes( id );
									}
									else
									{
										alert( dm.lang['action_failed'] );
										return;
									}
								}
							});
		}
		else
		{
			dm.global.togglePanes( id );
		}
		
	},
	
	togglePanes: function( newid )
	{
		var currentID = $('feed').select("a.current")[0].up("div").id.replace('tb_link:', '');
		var currentPane = $('pane_' + currentID);
		
		var newPane = $('pane_' + newid);
		
		Debug.write('pane_' + currentID);
		Debug.write('pane_' + newid);
		
		var curHeight = $(currentPane).measure('height');
		var newHeight = $(newPane).measure('height');
		
		// Hide current one
		$('panes_wrap').setStyle( { height: curHeight + "px" } );
		$( currentPane ).absolutize();
		new Effect.Fade( $( currentPane ), { duration: 0.2 } );
		
		// Resize container
		new Effect.Morph( $('panes_wrap'), { style: 'height: ' + newHeight + 'px', duration: 0.2, afterFinish: function(){
			new Effect.Appear( newPane, { duration: 0.2, afterFinish: function(){
				$('panes_wrap').setStyle( { height: 'auto' } );
				$( currentPane ).setStyle( { position: 'static', height: 'auto' } );
			} } );
		} } );
		
		//dm.global.togglePanes.executeJavascript( $( newPane ) );
		
		$('feed').select(".tb_toggle > a").invoke("removeClassName", "current");
		$('tb_link:' + newid).down("a").addClassName('current');
	},
	
	showShareBox: function(e, elem)
	{				
		Event.stop(e);
		
		var toggle = $(elem).down(".expander");
		var row = $(elem).up(".__post");
		var id = $(row).readAttribute("data-id");
		
		
		alert('aqui' + id);
		if( !id ){ return; }
		
		//if( $("share_" + id) )
		//{
			//new dm.Menu( $(".__share" + id), $("share_" + id + '_menucontent') );
			/*if( $("share_wrap_" + id).visible() )
			{ 
				new Effect.BlindUp( $("share_wrap_" + id), { duration: 0.3, afterFinish: function(){ $('share_' + id).hide(); } } );
				row.removeClassName('highlighted');*/
				//$( toggle ).addClassName('closed').removeClassName('open');
			/*}
			else
			{
				alert('aqui 2');
				$('share_' + id).show();
				new Effect.BlindDown( $("share_wrap_" + id), { duration: 0.3 } );
				row.addClassName('highlighted');*/
				//$( toggle ).addClassName('open').removeClassName('closed');
			//}
			
			
		//}
		
		//var _url 		= dm.config['admin_ajax'] + '?action=share_links';
		/*sharebox = new dm.Popup( 'sharebox', {type: 'balloon',
																stem: true,
																attach: { target: elem, position: 'auto' }, modal: false, w: '200px', h: 500, ajaxURL: _url, hideAtStart: false } );*/
	},
	
	/*initTabs: function()
	{
		$$('.tb_toggle').each( function(elem){
			Debug.write(elem.identify());
			$(elem).observe('click', dm.global.changeTabContent );
		});
	},
	
	changeTabContent: function(e)
	{
		Event.stop(e);
		elem = Event.findElement(e, 'div');
		if( !elem.hasClassName('tb_toggle') || !elem.id ){ return; }
		ol = elem.up('ol');
		id = elem.id.replace('tb_link_', '');
		if( !id || id.blank() ){ return; }
		if( !$('tb_content_' + id ) ){ return; }
		
		if( dm.global.activeTab == id )
		{
			return;
		}
		
		oldTab = dm.global.activeTab;
		dm.global.activeTab = id;
		
		// OK, we should have an ID. Does it exist already?
		if( !$('tb_' + id ) )
		{
			ol.select('.tb_toggle').each( function(otherelem){
				_id = otherelem.id.replace('tb_link_', '');
				if ( $('tb_content_' + _id ) )
				{
					$( $('tb_content_' + _id ) ).hide();
				}
			});
			
			$('tb_content_' + id ).show();
		}
		else
		{
			new Effect.Parallel( [
				new Effect.BlindUp( $('tb_content_' + oldTab), { sync: true } ),
				new Effect.BlindDown( $('tb_content_' + dm.global.activeTab), { sync: true } )
			], { duration: 0.4 } );
		}
		
		ol.select('.tb_toggle').each( function(otherelem){
			$(otherelem).removeClassName('current');
		});
		
		$(elem).addClassName('current');
		
	},*/
	
	/* ------------------------------ */
	/**
	 * Initializes stuff for image scaling
	*/
	/*initImageResize: function()
	{
		var dims = document.viewport.getDimensions();
		 
		dm.global.screen_w 	= dims.width;
		dm.global.screen_h 	= dims.height;
		dm.global.max_w		= Math.ceil( dm.global.screen_w * .8 ); //( dm.config['image_resize'] / 100 ) ); image_resize is always 0 or 1, so this was broke
	},*/
	
	/* ------------------------------ */
	/**
	 * Find large images in the given wrapper
	 * 
	 * @param	{element}	wrapper		The wrapper to search in
	*/
	/*findImgs: function( wrapper )
	{
		if( !$( wrapper ) ){ return; }
		if( !dm.config['image_resize'] ){ return; }
		if( $( wrapper ).hasClassName('imgsize_ignore') ){ Debug.write("Ignoring this post for image resizing..."); return; }
		
		// Resize images
		$( wrapper ).select('img').each( function(elem){
			
			if( !dm.global.screen_w )
			{
				Debug.write("Initializing resizing...");
				dm.global.initImageResize();
			}
			
			dm.global.resizeImage( elem );
		});
	},*/
	
	/* ------------------------------ */
	/**
	 * Resizes a large image
	 * 
	 * @param	{element}	elem	The image to resize
	*/
	/*resizeImage: function( elem )
	{
		if( elem.tagName != 'IMG' ){ return; }
		if( elem.readAttribute('handled') ){ Debug.write("Handled..."); return; }
		
		Debug.write("We here yet...");
		
		// Check we have a cached post size
		if( !dm.global.post_width )
		{
			var post	= $( elem ).up('.post');
			Debug.write(post);
			
			if( !Object.isUndefined( post ) )
			{
				Debug.write("post 2");
				
				var extra = parseInt( post.getStyle('padding-left') ) + parseInt( post.getStyle('padding-right') );
				dm.global.post_width = $( post ).getWidth() - ( extra * 2 );
			}
		}
		
		var quotewidth	= 0;
		var quote	= $( elem ).up('.quote');
		
		if( !Object.isUndefined( quote ) )
		{
			var extra = parseInt( quote.getStyle('padding-left') ) + parseInt( quote.getStyle('padding-right') );
			quotewidth = $( quote ).getWidth() - ( extra * 2 );
		}
		
		// Uses post width if it can work it out, otherwise screen width
		var widthCompare = ( dm.config['image_resize_force'] ) ? dm.config['image_resize_force'] : ( quotewidth ? quotewidth : ( dm.global.post_width ? dm.global.post_width : dm.global.max_w ) );
		var dims = elem.getDimensions();

		if( dims.width > widthCompare )
		{
			// Remove center tags if they are there
			if ( _parent = elem.up('.aligncenter') )
			{
				_parent.removeClassName('aligncenter');
			}
		
			//elem.width = dm.global.max_w;
			var percent = Math.ceil( ( widthCompare / dims.width) * 100 );
	
			if( percent < 100 )
			{
				elem.height = dims.height * ( percent / 100 );
				elem.width = dims.width * ( percent / 100 );
			}
			
			var temp = dm.templates['resized_img'];
			
			var wrap = $( elem ).wrap('div').addClassName('resized_img');
			$( elem ).insert({ before: temp.evaluate({ percent: percent, width: dims.width, height: dims.height }) });
			
			$( elem ).addClassName('resized').setStyle('cursor: pointer;');
			$( elem ).writeAttribute( 'origWidth', dims.width ).writeAttribute( 'origHeight', dims.height ).writeAttribute( 'shrunk', 1 );
			$( elem ).writeAttribute( 'newWidth', elem.width ).writeAttribute( 'newHeight', elem.height ).writeAttribute( 'handled', 1 );
			
			// SKINNOTE: Add event handler
			$( elem ).observe('click', dm.global.enlargeImage);
		}	
	},*/
	
	/* ------------------------------ */
	/**
	 * Resizes a shrunk image back to normal
	 * 
	 * @param	{event}		e		The event
	*/
	/*enlargeImage: function(e)
	{
		var elem = Event.element(e);
		if( !elem.hasClassName('resized') ){ elem = Event.findElement(e, '.resized'); }
		
		//var img = elem.down('img.resized');
		var img = elem;
		
		if( !img ){ return; }
		
		if( $( img ).readAttribute( 'shrunk' ) == 1 )
		{
			$( img ).setStyle( 'width: ' + img.readAttribute('origWidth') + 'px; height: ' + img.readAttribute('origHeight') + 'px; cursor: pointer');
			$( img ).writeAttribute( 'shrunk', 0 );
		}
		else
		{
			$( img ).setStyle( 'width: ' + img.readAttribute('newWidth') + 'px; height: ' + img.readAttribute('newHeight') + 'px; cursor: pointer');
			$( img ).writeAttribute( 'shrunk', 1 );
			Debug.write("width: " + img.readAttribute('newWidth'));
		}
	},*/
	
	magazinePopup: function( e, elem )
	{
		Event.stop(e);
		
		var sourceid = elem.identify();
		var edition = $( elem ).className.match('__id([0-9]+)');

		if( edition == null || Object.isUndefined( edition[1] ) ){ Debug.error("Error showing popup"); return; }
		var popid = 'popup_' + edition[1] + '_edition';
		var _url  = dm.config['theme_url'] + '/download.php?id=' + edition[1];
		
		new Ajax.Request( _url,
							{
								method: 'get',
								onSuccess: function(t)
								{
									return;
								}
							});
		
		/*dm.namePops[ edition ]	 = new dm.Popup( popid, {   type: 'balloon',
			 												ajaxURL: _url,
			 												stem: false,
															hideAtStart: false,
			 												attach: { position: 'auto' },
			 												w: '900px'
														});*/
	},
	
	convertSize: function(size)
	{
		var kb = 1024;
		var mb = 1024 * 1024;
		var gb = 1024 * 1024 * 1024;
		
		if( size < kb ){ return size + " B"; }
		if( size < mb ){ return ( size / kb ).toFixed( 2 ) + " KB"; }
		if( size < gb ){ return ( size / mb ).toFixed( 2 ) + " MB"; }
		
		return ( size / gb ).toFixed( 2 ) + " GB";
	},
			
	toggleSpoiler: function(e, button)
	{
		Event.stop(e);
		
		var returnvalue = $(button).up().down('.bbc_spoiler_wrapper').down('.bbc_spoiler_content').toggle();
		
		if( returnvalue.visible() )
		{
			$(button).value = 'Hide';
		}
		else
		{
			$(button).value = 'Show';
		}
	},
	
	openNewWindow: function(e, link, force)
	{		
		var ourHost	= document.location.host;
		var newHost = link.host;

		/**
		 * Open a new window, if link is to a different host
		 */
		if( ourHost != newHost || force )
		{
			window.open(link.href);
			Event.stop(e);
			return false;
		}
		else
		{
			return true;
		}
	}
};

dm = new DM;
dm.global.init();
dm.menus.init();
