﻿/**
*	@property	app
*
*	Defines the global application instance
*/

var app = null;

/**
*	@property	page
*
*	Defines the global page instance
*/

var page = null;

/**
*	@class 				AbstractScreen
*
*	@usage 				Used to display and define all abstract elements within a page. All site pages will extend this class
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var AbstractScreen = AbstractView.extend(
	{
		/**
		*   init
		*
		*   Constructs the screen
		*
		*	@param	t - type
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*/
		init: function(t, m, h)
		{
			this._super( t, m, h );
			
			//alert( t + " initiating..." );
			
			// define internal instance
			var obj = this;
			
			// first : hide the no script message
			// we do this immediately so that it is not displayed
			// at all to the user
			$( 'noscript' ).hide();
			
			// instantiate all utility classes
			this.browser = new Browser();
			this.utilFrm = new FormUtility();
			
			// instantate all managers
			this.dialogueManager = new DialogueManager( this.manager.getCore() );
			//$( this.dialogueManager ).bind( 'onDialogueOpened', function( evt, data ) { obj.updateComponents( evt, data ); } );
			//$( this.dialogueManager ).bind( 'onDialogueClosed', function( evt, data ) { obj.updateComponents( evt, data ); } );
			
			// get any URL request vars
			this.urlVars = this.browser.getUrlVars();
			
			// define all page props
			
			// @@ static
			this.BUILD_MODE_USER = "buildModeUser";
			this.BUILD_MODE_NO_USER = "buildModeNoUser";
			this.BUILD_MODE_DEFAULT = this.BUILD_MODE_NO_USER;
			
			// @@ private
			this.buildMode = this.BUILD_MODE_DEFAULT;
			
			// listen to any applicable model events
			$( this.manager.getCore() ).bind( 'onLoggedInUserReceived', function( evt, data ) { obj.setup(); } );
			$( this.manager.getCore() ).bind( 'onMessageShow', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onMessageHide', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onGetCreditTopUpProductsFailed', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onGetCreditTopUpProductsSuccess', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onReserveCreditsFailed', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onReserveCreditsSuccess', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onAddCreditsFailed', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onAddCreditsSuccess', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onRemoveCreditsFailed', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onRemoveCreditsSuccess', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onPaypalCreditTXManagementFailed', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onPaypalCreditTXManagementSuccess', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onMakePurchaseFailed', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onMakePurchaseSuccess', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onManageCreditPurchaseFailed', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onManageCreditPurchaseSuccess', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onErrorDetected', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onDialogueOpened', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onDialogueClosed', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onDialogueMessageShow', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onDialogueMessageHide', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onUserLogInFailed', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onUserLogInSuccess', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onCreditChargeAccepted', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onCreditChargeDeclined', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onCreditChargeRequestFailed', function( evt, data ) { obj.updateComponents( evt, data ); } );
			$( this.manager.getCore() ).bind( 'onCreditChargeRequestReceived', function( evt, data ) { obj.updateComponents( evt, data ); } );
		
			// get the logged in user
			// this will initialise the screen
			this.manager.core.getLoggedInUser();
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*
		*	@param	o - forum owner id
		*/
		setup: function()
		{
			//alert( "setting up screen" );
			
			// build the screen
			this.build();
			
			//alert( "Paypal tx : " + this.urlVars["tx"] + " ?? " + this.manager.core.userProfile );
			
			// handle any url requests
			// @@ paypal re-directs
			if ( this.urlVars["tx"] != undefined ) {
				// if no user logged in
				if ( !this.manager.core.userProfile )
					return;
				// else add the purchased credits
				this.manager.getControl( "CreditControl" ).managePaypalCreditTX(
					this.manager.core.userProfile.getUserId(), this.urlVars["tx"]															
				);
			}
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building screen" );
			
			var obj = this;
			
			// build abstract screen elements
			
			// if there is a user logged in
			// then the build mode is set to 'user'
			if ( this.manager.core.getUserProfile() != null )
				this.buildMode = this.BUILD_MODE_USER;
			
			// setup generic content
			
			// show the main content div now all page elements have loaded
			$( 'div.main' ).css( 'display', 'block' );
			
			// setup buttons
			
			// @@ miss ukff button
			$( "div#btn_miss_ukff" ).append(
				'<a href="' + this.manager.core.getPrefix() + 'girls/missukff.php" target="_self">' +
					'<img src="' + this.manager.core.getPrefix() + 'images/mechs/UKFF_Spacer.gif" border="0px" width="160px" height="180px" />' +
				'</a>'						
			);
				
			// swith on build mode
			switch ( this.buildMode )
			{
				// @@ case - build mode set to user
				case this.BUILD_MODE_USER:
				
					this.buildForUser();
				
					break;
					
				// @@ case - build mode set to no user
				case this.BUILD_MODE_NO_USER:
				
					this.buildForNoUser();
				
					break;
			}
			
			// build abstract screen components
			this.buildComponents();
			
			// handle any global 'post-build' page functionality
			
			// fix all PNG
			this.fixScreenPNG();
			
			// fix the IE box model
			$( 'div' ).fixBoxModel().fixDoubleMargin();
			$( 'ul' ).fixBoxModel().fixDoubleMargin();
			$( 'li' ).fixBoxModel().fixDoubleMargin();
			$( 'span' ).fixBoxModel().fixDoubleMargin();
			
			// fix the fonts in IE
			Cufon.now();
		},
		
		/**
		*   buildForUser
		*
		*   Builds the view to display to a logged user
		*/
		buildForUser: function()
		{
			var obj = this;
			
			// setup buttons
			
			// @@ buy credits / sign up button
			if ( $('#btn_buy_credits').hasClass( "a_sign_up_btn_134x60" ) )
				$('#btn_buy_credits').removeClass( "a_sign_up_btn_134x60" );
			$('#btn_buy_credits').addClass( "a_buy_credits_btn_134x60" );
			$('#btn_buy_credits').click(
				function() {
					// open the buy credits dialogue
					obj.dialogueManager.openDialogue( "dialog_buy_credits", true );
					return false;
				}
			);
		},
		
		/**
		*   buildForNoUser
		*
		*   Builds the view to display to a non-logged user
		*/
		buildForNoUser: function()
		{
			var obj = this;
			
			// setup buttons
			
			// @@ buy credits / sign up button
			if ( $('#btn_buy_credits').hasClass( "a_buy_credits_btn_134x60" ) )
				$('#btn_buy_credits').removeClass( "a_buy_credits_btn_134x60" );
			$('#btn_buy_credits').addClass( "a_sign_up_btn_134x60" );
			$('#btn_buy_credits').click(
				function() {
					// open the buy credits dialogue
					obj.manager.getControl( "GeneralControl" ).changePage( obj.manager.core.getPrefix() + "pages/user/signup.php?ut=1" );
					return false;
				}
			);
		},
		
		/**
		*   buildComponents
		*
		*   Builds the screen components
		*/
		buildComponents: function()
		{
			//alert( "building screen components" );
			
			var obj = this;
			
			// @@ navigation
			this.nav = new Navigation( this.getManager(), "div#comp_nav" );
			this.nav.setup();
			
			// @@ footer
			this.footer = new Footer( this.getManager(), "div#comp_footer" );
			this.footer.setup();
			
			// @@ messages
			this.messages = new Messages( this.getManager(), "div#comp_msges" );
			this.messages.setup();
			
			// @@ user bar
			this.userBar = new UserBar( this.getManager(), "div#comp_user_bar" );
			this.userBar.setup();
			
			// add all dialogues to manager
			
			// @@ buy credits dialogue
			var buyCreditsDData = new DialogueData();
				buyCreditsDData.setDialogId( "dialog_buy_credits" );
				buyCreditsDData.setDisplayData( { open: 
					function(event, ui) { 
						window.setTimeout(function() { 
								jQuery(document).unbind('mousedown.dialog-overlay').unbind('mouseup.dialog-overlay'); 
							}, 100
						); 
					}, 
					autoOpen: false, 
					width: 622, 
					position: ["center",120], 
					modal: true 
				});
			this.dialogueManager.addDialogue( 
				"dialog_buy_credits", new BuyCreditsDialogue( this.getManager(), "div#comp_buy_credits", buyCreditsDData )
			);
			
			// @@ loader dialogue
			var loaderDData = new DialogueData();
				loaderDData.setDialogId( "dialog_loader" );
				loaderDData.setDisplayData( { 
					autoOpen: false, 
					width: 400,
					modal: true, 
					open: function(evt, ui) {
						$(this).parents(".ui-dialog:first").find(".ui-dialog-titlebar-close").hide(); 
						return false;
					} 
				});
			this.dialogueManager.addDialogue( 
				"dialog_loader", new LoaderDialogue( this.getManager(), "div#comp_loader", loaderDData )
			);
			
			// @@ payment dialogue
			var paymentDData = new DialogueData();
				paymentDData.setDialogId( "dialog_payment" );
				paymentDData.setDisplayData( { open: 
					function(event, ui) { 
						window.setTimeout(function() { 
								jQuery(document).unbind('mousedown.dialog-overlay').unbind('mouseup.dialog-overlay'); 
							}, 100
						); 
					}, 
					autoOpen: false, 
					width: 622, 
					position: ["center",120], 
					modal: true, 
					buttons: { 
						"Purchase": function() {
							obj.dialogueManager.getDialogue( "dialog_payment" ).submitForm();
						}
					}
				});
			this.dialogueManager.addDialogue( 
				"dialog_payment", new PaymentDialogue( this.getManager(), "div#comp_payment", paymentDData )
			);
			
			// @@ credit charge dialogue
			var chargeDData = new DialogueData();
				chargeDData.setDialogId( "dialog_accept_credit_charge" );
				chargeDData.setDisplayData( { autoOpen: false, width: 622, position: ["center","center"], modal: true, buttons: { 
					"Accept": function() {
						obj.dialogueManager.getDialogue( "dialog_accept_credit_charge" ).acceptCharge();
					},
					"Decline": function() {
						obj.dialogueManager.getDialogue( "dialog_accept_credit_charge" ).declineCharge();
					}}
				});
			this.dialogueManager.addDialogue( 
				"dialog_accept_credit_charge", new AcceptCreditChargeDialogue( this.getManager(), "div#comp_accept_credit_charge", chargeDData )
			);
			
			// hide the loader as default
			this.hideLoader();
			
			// update the components
			// do this by passing a 'dummy' event into the update function
			this.updateComponents( { type: "onComponentsBuilt" }, null );
		},
		
		/**
		*   showLoader / hideLoader
		*
		*   Shows / Hides the loader dialogue
		*/
		showLoader: function()
		{
			// open the loader dialogue
			this.dialogueManager.openDialogue( "dialog_loader", true );
		},
		
		hideLoader: function()
		{
			// close the loader dialogue
			this.dialogueManager.closeDialogue( "dialog_loader" );
		},
		
		/**
		*   fixScreenPNG
		*
		*   Fixes all the screen png's
		*/
		fixScreenPNG: function()
		{
			DD_belatedPNG.fix( "a.a_sign_up_btn_134x60, .a_sign_up_btn_134x60 span" );
			DD_belatedPNG.fix( "a.a_buy_credits_btn_134x60, .a_buy_credits_btn_134x60 span" );
		},
		
		/**
		*   updateComponents
		*
		*   Updates the screen components
		*
		*	@param	evt - event
		*	@param	data - data object
		*/
		updateComponents: function(evt, data)
		{
			//alert( "updating screen components : " + evt.type + " : " + data );
			
			switch ( evt.type )
			{
				// @@ onErrorDetected - error has been detected
				case "onErrorDetected":
				
					switch ( data.getErrorType() )
					{
						// @@ err - no paypal auth token has been set
						case "ErrorNoPPAuthTokenSet":
						// @@ err - paypal tx code invalid
						case "ErrorPPTXInvalid":
						
							// post a message
							var msge = new MessageData();
								msge.setMessageType( "bad" );
								msge.setMessage( "Sorry. There has been an error. Your credits have not been added to your account. Please contact us immediately." );
							this.manager.getControl( "GeneralControl" ).showMessage( msge );
						
							break;
					}
				
					break;
					
				// @@ onCreditChargeAccepted - credit charge accepted
				case "onCreditChargeAccepted":
				
					// close the credit charge accept dialogue
					this.dialogueManager.closeDialogue( "dialog_accept_credit_charge" );
				
					break;
				
				// @@ onCreditChargeDeclined - credit charge declined
				case "onCreditChargeDeclined":
				
					// close the credit charge accept dialogue
					this.dialogueManager.closeDialogue( "dialog_accept_credit_charge" );
				
					break;
					
				// @@ onAddCreditsFailed - add credits failed
				case "onAddCreditsFailed":
				
					// post a message
					var msge = new MessageData();
						msge.setMessageType( "bad" );
						msge.setMessage( "Sorry. There has been an error. Your credits have not been added to your account. Please contact us immediately." );
					this.manager.getControl( "GeneralControl" ).showMessage( msge );
				
					break;
					
				// @@ onAddCreditsSuccess - add credits success
				case "onAddCreditsSuccess":
				
					// post a message
					var msge = new MessageData();
						msge.setMessageType( "bad" );
						msge.setMessage( "Thankyou. Your credits have been added to your account." );
					this.manager.getControl( "GeneralControl" ).showMessage( msge );
				
					break;
					
				// @@ onPaypalCreditTXManagementFailed - paypal TX details failed
				case "onPaypalCreditTXManagementFailed":
				
					// post a message
					var msge = new MessageData();
						msge.setMessageType( "bad" );
						msge.setMessage( "Sorry. An Error has occured. We were unable to add your credits. Please contact us immediately." );
					this.manager.getControl( "GeneralControl" ).showMessage( msge );
				
					break;
					
				// @@ onPaypalCreditTXManagementSuccess - paypal TX details success
				case "onPaypalCreditTXManagementSuccess":
				
					// post a message
					var msge = new MessageData();
						msge.setMessageType( "good" );
						msge.setMessage( "Thankyou. Your credits have been added to your account." );
					this.manager.getControl( "GeneralControl" ).showMessage( msge );
				
					break;
					
				// @@ onManageCreditPurchaseFailed - manage credit purchase failed
				case "onManageCreditPurchaseFailed":
				
					// post a message
					var msge = new MessageData();
						msge.setMessageType( "bad" );
						msge.setMessage( "Sorry. An Error has occured. We were unable to add your credits. Please contact us immediately." );
					this.manager.getControl( "GeneralControl" ).showMessage( msge );
				
					break;
					
				// @@ onManageCreditPurchaseSuccess - manage credit purchase success
				case "onManageCreditPurchaseSuccess":
				
					// post a message
					var msge = new MessageData();
						msge.setMessageType( "good" );
						msge.setMessage( "Thankyou. Your credits have been added to your account." );
					this.manager.getControl( "GeneralControl" ).showMessage( msge );
				
					break;
					
				// @@ onMakePurchaseSuccess - the purchase has been successful
				case "onMakePurchaseSuccess":
				
					// close the payment dialogue
					this.dialogueManager.closeDialogue( "dialog_payment" );
				
					// get the product control
					var pc = this.manager.getControl( "ProductsControl" );
					
					// open a new message string
					var msgeStr = "Thankyou. Your payment has been received. ";
					
					// switch on the purchased product id
					// here we conclude what to do with the success event
					// now that the payment has been received
					switch ( data.getProductType() )
					{
						// @@ case : product :
						case pc.PRODUCT_TYPE_CREDIT_TOP_UP:
						
							this.manager.getControl( "CreditControl" ).manageCreditPurchase(
								this.manager.core.userProfile.getUserId(), data.productTypeData.getCredits(), data.productTypeData.getAddOn()														
							);
							
							// append the message
							msgeStr += "Your credits are now being added.";
						
							break;
					}
					
					// post a message
					var msge = new MessageData();
						msge.setMessageType( "good" );
						msge.setMessage( msgeStr );
					this.manager.getControl( "GeneralControl" ).showMessage( msge );
				
					break;
					
				// @@ onDialogueClosed - dialogue has been closed
				case "onDialogueClosed":
				
					// hide the dialogue
					this.dialogueManager.closeDialogue( data.getDialogId() );
				
					break;
					
				// @@ onDialogueOpened - dialogue has been opened
				case "onDialogueOpened":
				
					// open the dialogue
					this.dialogueManager.openDialogue( data.getDialogId(), data.getSolo(), data.getContentData() );
				
					break;
					
				// @@ onUserLogInFailed - user login has failed
				case "onUserLogInFailed":
				
					// post a message
					var msge = new MessageData();
						msge.setMessageType( "bad" );
						msge.setMessage( "Login Failed. Please try again" );
					this.manager.getControl( "GeneralControl" ).showMessage( msge );
				
					break;
					
				// @@ onUserLogInSuccess - user login has been a success
				case "onUserLogInSuccess":
				
					this.manager.getControl( "GeneralControl" ).changePage( this.manager.core.getPrefix() );
				
					break;
			}
			
			this.nav.update( evt.type, data );
			this.footer.update( evt.type, data );
			this.messages.update( evt.type, data );
			this.userBar.update( evt.type, data );
			
			// update all dialogues
			this.dialogueManager.updateDialogues( evt.type, data );
		}
	}
);

/*******************************************************************************************************************

Dialogue Classes

********************************************************/

/**
*   Class : DialogueData
*
*   Class holds all data necessary to esatblish a dialogue object
*
*   @usage    Used by all elements
*   @author   Daniel Ivanovic dan@substance001.com
*/
var DialogueData = AbstractObject.extend(
	{
		/**
		*   init
		*
		*   Constructs the data object
		*/
		init: function()
		{
			this._super( "DialogueData" );
			
			this.dialogId = 0;
			this.displayData = null;
			this.solo = false;
			this.contentData = null;
		},
		
		/**
		*   setDialogId / getDialogId
		*
		*   Sets / Returns the dialogue id
		*/
		setDialogId: function(s) { this.dialogId = s; },
		getDialogId: function() { return this.dialogId; },
		
		/**
		*   setDisplayData / getDisplayData
		*
		*   Sets / Returns the dialog display data 
		*/
		setDisplayData: function(s) { this.displayData = s; },
		getDisplayData: function() { return this.displayData; },
		
		/**
		*   setSolo / getSolo
		*
		*   Sets / Returns the solo boolean 
		*/
		setSolo: function(s) { this.solo = s; },
		getSolo: function() { return this.solo; },
		
		/**
		*   setContentData / getContentData
		*
		*   Sets / Returns the content data object 
		*/
		setContentData: function(s) { this.contentData = s; },
		getContentData: function() { return this.contentData; }
	}
);

/**
*	@class 				DialogueManager
*
*	@usage 				Used to manage the display of application dialogues
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var DialogueManager = AbstractManager.extend(
	{
		/**
		*   init
		*
		*   Constructs the dialogue
		*
		*	@param	c - model instance
		*/
		init: function(c)
		{
			this._super( "DialogueManager", c );
			
			// define props
			this.dialogues = new Array();
			this.openDialogues = new Array();
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*/
		setup: function()
		{
			//alert( "setting up" );
		},
		
		/**
		*   addDialogue / getDialogue
		*
		*   Adds / Returns a dialogue to / from the dialogue array
		*
		*	@param	id - dialogue id
		*	@param	d - dialogue object
		*/
		addDialogue: function(id, d)
		{
			//alert( "adding dialogue : " + id );
			
			if ( !id || !d ) {
				alert( "WARNING! : Dialogue id and/or object cannot be recognised" );
				return;
			}
			
			this.dialogues[ id ] = d;
			this.dialogues[ id ].setup();
			
			var obj = this;
			
			// assign to open event
			// This will open the dialogue objects when a dialog is opened
			$( "#" + id ).bind( 'dialogopen', function(evt, ui) {
				//alert( "opening dialogue " + id );
				// handle all open functionality
				// open the dialogue object
				obj.dialogues[ id ].openDialogue();
				// add to open array
				obj.openDialogues[ id ] = obj.dialogues[ id ];
				// broadcast dialog manager event
				// dialog opened
				obj.broadcast( 'onDialogueOpened', obj.dialogues[ id ] );
				// force return (for IE6)
				return false;
			});
			
			// assign to close event
			// we do this just in case the user closes by means of 'x' button,
			// this will keep the manager up to date on open / closed dialogues
			$( "#" + id ).bind( 'dialogclose', function(evt, ui) {
				//alert( "closing dialogue " + id );
				// handle all close functionality
				// close the dialogue object
				obj.dialogues[ id ].closeDialogue();
				// remove from open array
				delete obj.openDialogues[ id ];
				// broadcast dialog manager event
				// dialog closed
				obj.broadcast( 'onDialogueClosed', obj.dialogues[ id ] );
				// force return (for IE6)
				return false;
			});
		},
		
		getDialogue: function(id)
		{
			//alert( "getting dialogue" );
			
			if ( !this.dialogues[ id ] ) {
				alert( "WARNING! : There is no dialogue named " + id );	
				return;
			}
			
			return this.dialogues[ id ];
		},
		
		/**
		*   openDialogue / closeDialogue
		*
		*   Opens / Closes a dialogue
		*
		*	@param	id - dialogue id
		*	@param	s - solo boolean
		*	@param	d - dialogue content data
		*/
		openDialogue: function(id, s, d)
		{
			//alert( "opening dialogue " + id + " : " + s + " : " + d );
			
			// if set to display solo
			// then close all the open dialogues
			if ( s != undefined && s )
				this.closeDialogues();
			
			// if content data has been passed
			// then add the data to the dialog
			if ( d != undefined && d )
				this.dialogues[ id ].setContentData( d );
				
			// scroll the window to the top of the page
			window.scroll( 0, 0 );
			
			// open the dialog panel
			$( "#" + id ).dialog( "open" );
		},
		
		closeDialogue: function(id)
		{
			//alert( "closing dialogue " + id );
			
			// close the dialog panel
			$( "#" + id ).dialog( "close" );
		},
		
		/**
		*	closeDialogues
		*
		*	Closes all open dialogues
		*/
		closeDialogues: function()
		{
			//alert( "closing dialogues" );
			
			for ( var i in this.openDialogues )
			{
				this.closeDialogue( i );
			}
		},
		
		/**
		*   updateDialogues
		*
		*   Updates all the dialogues
		*
		*	@param	t - event type
		*	@param	d - event data
		*/
		updateDialogues: function(t, d)
		{
			//alert( "updating dialogues " + t );
			
			for ( var i in this.dialogues )
			{
				this.dialogues[ i ].update(t, d);	
			}
		}
	}
);

/**
*	@class 				AbstractScreen
*
*	@usage 				Used to display and define all abstract elements within a dialogue. All site dialogues will extend this class
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var AbstractDialogue = AbstractView.extend(
	{
		/**
		*   init
		*
		*   Constructs the dialogue
		*
		*	@param	t - type string
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*	@param	o - dialogue data object
		*/
		init: function(t, m, h, d)
		{
			this._super( t, m, h );
			
			// @@ define props
			this.STATE_OPEN = "stateOpen";
			this.STATE_CLOSED = "stateClosed";
			this.STATE_DEFAULT = this.STATE_CLOSED;
			
			// @@ private
			this.currentState = this.STATE_DEFAULT;
			this.dialogueData = d;
			this.contentData = d.getContentData();
			this.dialogueBuilt = false;
			this.compLoader = "div#comp_loader";
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*/
		setup: function()
		{
			//alert( "setting up dialogue : " + this.dialogueData.getDialogId() );
			
			if ( !this.dialogueData ) {
				alert( "WARNING! : No dialogue data set " + this.getType() );
				return;
			}
			
			$( "#" + this.dialogueData.getDialogId() ).dialog(
				this.dialogueData.getDisplayData()
			);
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building" );
			
			// build components
			this.buildComponents();
			
			// register as built
			this.dialogueBuilt = true;
		},
		
		/**
		*   buildComponents
		*
		*   Builds the screen components
		*/
		buildComponents: function()
		{
			//alert( "building dialogue components" );
			
			var obj = this;
			
			// @@ messages
			this.dialogueMessages = new DialogueMessages( this.getManager(), "div#" + this.dialogueData.getDialogId() + "_comp_dialogue_msges" );
			this.dialogueMessages.setup();
		},
		
		/**
		*   openDialogue / closeDialogue
		*
		*   Opens / Closes the dialogue
		*/
		openDialogue: function()
		{
			//alert( "opening" );
			
			// register the current state
			this.currentState = this.STATE_OPEN;
			
			// build
			this.build();
		},
		
		closeDialogue: function()
		{
			//alert( "closing" );
			
			// register the current state
			this.currentState = this.STATE_CLOSED;
		},
		
		/**
		*   showLoader / hideLoader
		*
		*   Shows / Hides the loader dialogue
		*/
		showLoader: function()
		{
			// if no loader established
			if ( !$( this.compLoader ) )
				return;
				
			// show the loader
			$( this.compLoader ).show();
		},
		
		hideLoader: function()
		{
			// if no loader established
			if ( !$( this.compLoader ) )
				return;
				
			// hide the loader
			$( this.compLoader ).hide();
		},
		
		/**
		*   setContentData / getContentData
		*
		*	Sets / Returns the dialogue content data object 
		*/
		setContentData: function(d) { this.contentData = d; },
		getContentData: function() { return this.contentData; },
		
		/**
		*   update
		*
		*   Updates the view
		*
		*	@param	t - event type
		*	@param	d - data
		*/
		update: function(t, d)
		{
			//alert( "updating : " + t + " : " + d );
			
			// if the dialogue has not yet been built
			// return before trying to update components
			if ( !this.dialogueBuilt )
				return;
			
			// update components
			this.dialogueMessages.update( t, d );
		}
	}
);

/**
*	@class 				LoaderDialogue
*
*	@usage 				Used to display the loader dialogue
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var LoaderDialogue = AbstractDialogue.extend(
	{
		/**
		*   init
		*
		*   Constructs the dialogue
		*
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*	@param	o - dialogue data object
		*/
		init: function(m, h, d)
		{
			this._super( "LoaderDialogue", m, h, d );
		}
	}
);

/**
*	@class 				BuyCreditsDialogue
*
*	@usage 				Used to display the buy-credits dialogue
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var BuyCreditsDialogue = AbstractDialogue.extend(
	{
		/**
		*   init
		*
		*   Constructs the dialogue
		*
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*	@param	o - dialogue data object
		*/
		init: function(m, h, d)
		{
			this._super( "BuyCreditsDialogue", m, h, d );
			
			// @@ static
			this.TOP_UP_BRONZE = "topUpBronze";
			this.TOP_UP_SILVER = "topUpSilver";
			this.TOP_UP_GOLD = "topUpGold";
			
			// define props
			this.creditTopUps = new Array();
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*/
		setup: function()
		{
			//alert( "setting up" );
			
			// call super
			this._super();
		},
		
		/**
		*   openDialogue / closeDialogue
		*
		*   Opens / Closes the dialogue
		*/
		openDialogue: function()
		{
			//alert( "opening" );
			
			// define the object scope
			
			var obj = this;
			
			// register the current state
			this.currentState = this.STATE_OPEN;
			
			// @@ load the mark-up
			$( this.getHolder() ).load( 
				this.manager.core.getPrefix() + "pages/dialogue/buycredits.php", function () {
					obj.manager.getControl( "CreditControl" ).getCreditTopUpProducts();
				}
			);
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building" );
			
			// call super
			this._super();
			
			var obj = this;
			
			// build the bespoke dialogue
			
			// assign click to buy-now buttons
			
			// @@ bronze
			$( "a#btn_buy_credits_bronze" ).append( 
				'<img src="' + this.manager.core.getPrefix() + 'images/mechs/dialogue/buycredits/UKFF_Credit_Option_Bronze.jpg" border="0px" alt="Credit option \'Bronze\'" />' 
			);
			$( "a#btn_buy_credits_bronze" ).live( 'click', function() {
				obj.submitForm( obj.TOP_UP_BRONZE );
				return false;
			});
			
			// @@ silver
			$( "a#btn_buy_credits_silver" ).append( 
				'<img src="' + this.manager.core.getPrefix() + 'images/mechs/dialogue/buycredits/UKFF_Credit_Option_Silver.jpg" border="0px" alt="Credit option \'Silver\'" />' 
			);
			$( "a#btn_buy_credits_silver" ).live( 'click', function() {
				obj.submitForm( obj.TOP_UP_SILVER );
				return false;
			});
			
			// @@ gold
			$( "a#btn_buy_credits_gold" ).append( 
				'<img src="' + this.manager.core.getPrefix() + 'images/mechs/dialogue/buycredits/UKFF_Credit_Option_Gold.jpg" border="0px" alt="Credit option \'Gold\'" />' 
			);
			$( "a#btn_buy_credits_gold" ).live( 'click', function() {
				obj.submitForm( obj.TOP_UP_GOLD );
				return false;
			});
			
			// post the info message
			var msge = new MessageData();
			msge.setMessageType( "good" );
			msge.setMessage( "You will be taken to Paypal to pay for your credits. Once you have made payment you will be re-directed back to www.ukffgirls.com. It is important that you wait to be returned to www.ukffgirls.com, as your credits will not be added until this point.<BR/><BR/> NOTE : All credits will expire if not used within 30 days of the purchase date" );
			this.dialogueMessages.showMessage( msge );
		},
		
		/**
		*   submitForm
		*
		*   Submits the buy credits form
		*
		*	@param	c - credit package
		*/
		submitForm: function(c)
		{
			//alert( "submitting form" );
			
			// get the necessary controls
			var pc = this.manager.getControl( "ProductsControl" );
			
			// open the payment dialogue
			// passing the payment data object
			
			// create the product type data
			var ptData = new CreditTopupData();
				ptData.setTopupId( this.creditTopUps[c].topup_id );
				ptData.setCredits( this.creditTopUps[c].credits );
				ptData.setAddOn( this.creditTopUps[c].add_on );
			
			// create a product data object
			var prData = new ProductData();
				prData.setProductId( this.creditTopUps[c].product_id );
				prData.setProductType( this.creditTopUps[c].type );
				prData.setProductName( this.creditTopUps[c].name );
				prData.setProductPrice( this.creditTopUps[c].price );
				prData.addProductAddOn( "Additional Forum Posts", this.creditTopUps[c].add_on );
				prData.addProductAddOn( "Additional Photo Comments", this.creditTopUps[c].add_on );
				prData.setProductTypeData( ptData );
			
			// create a payment data object
			var pData = new PaymentData();
				pData.setProductData( prData );
				
			this.manager.getControl( "GeneralControl" ).openDialogue( 
				"dialog_payment", true, pData
			);
		},
		
		/**
		*   update
		*
		*   Updates the view
		*
		*	@param	t - event type
		*	@param	d - data
		*/
		update: function(t, d)
		{
			//alert( "updating : " + t + " : " + d );
			
			switch ( t )
			{
				// @@ onGetCreditTopUpsFailed - get top ups request failed
				case "onGetCreditTopUpProductsFailed":
				
					// post a message
					var msge = new MessageData();
						msge.setMessageType( "bad" );
						msge.setMessage( "Sorry. There has been an error, please refresh the page." );
					this.dialogueMessages.showMessage( msge );
				
					break;
					
				// @@ onGetCreditTopUpsSuccess - top ups request success
				case "onGetCreditTopUpProductsSuccess":
				
					// define the credit top ups array
					this.creditTopUps[ this.TOP_UP_BRONZE ] = d.credits[0];
					this.creditTopUps[ this.TOP_UP_SILVER ] = d.credits[1];
					this.creditTopUps[ this.TOP_UP_GOLD ] = d.credits[2];
					
					// ...and build
					this.build();
				
					break;
			}
			
			// if the dialogue has not yet been built
			// return before trying to update components
			if ( !this.dialogueBuilt )
				return;
			
			// call to super
			this._super( t, d );
		}
	}
);

/**
*	@class 				PaymentDialogue
*
*	@usage 				Used to display the payment dialogue
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var PaymentDialogue = AbstractDialogue.extend(
	{
		/**
		*   init
		*
		*   Constructs the dialogue
		*
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*	@param	o - dialogue data object
		*/
		init: function(m, h, d)
		{
			this._super( "PaymentDialogue", m, h, d );
			
			// @@ static
			
			// define props
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*/
		setup: function()
		{
			//alert( "setting up" );
			
			// call super
			this._super();
		},
		
		/**
		*   openDialogue / closeDialogue
		*
		*   Opens / Closes the dialogue
		*/
		openDialogue: function()
		{
			//alert( "opening" );
			
			var obj = this;
			
			// register the current state
			this.currentState = this.STATE_OPEN;
			
			// @@ load the mark-up
			$( this.getHolder() ).load( 
				this.manager.core.getPrefix() + "pages/dialogue/payment.php", function () {
					obj.build();
				}
			);
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building" );
			
			// call super
			this._super();
			
			var obj = this;
			
			// define the product data
			var targetProductData = this.contentData.getProductData();
			
			// setup the form
			
			// fill in all fields
			
			// @@ accepted card types
			$( "img#img_accepted_types" ).attr( 
				"src", this.manager.core.getPrefix() + 'images/mechs/dialogue/payment/UKFF_PaymentDialogue_CC_LogoBar.jpg' 
			);
			
			// @@ purchase details : product name
			$( "div#text_product_name" ).append( '<span class="bc_11_ffffff">' + targetProductData.getProductName() + '</span>' );
			
			// @@ purchase add-ons
			var addOnsHTML = "";
			for ( var i=0; i<targetProductData.getProductAddOns().length; i++ )
			{
				addOnsHTML += '<span class="bc_11_ffffff">' 
					+ targetProductData.getProductAddOns()[i].title 
					+ " x " 
					+ targetProductData.getProductAddOns()[i].value 
					+ '</span><br/>';
			}
			$( "div#text_purchase_add_ons" ).append( addOnsHTML );
			
			// @@ purchase price
			$( "div#text_purchase_price" ).append( "&pound;" + targetProductData.getProductPrice() );
		},
		
		/**
		*   submitForm
		*
		*   Submits the buy credits form
		*/
		submitForm: function()
		{
			//alert( "submitting form " + page.utilFrm );
			
			var paymentData = new PaymentData();
			
			// validate the data
			// @@ cutomer name
			paymentData.setCustomerName( $( "input[name=cust_name]" ).val() );
			// @@ cutomer name
			paymentData.setCardNumber( $( "input[name=card_num]" ).val() );
			// @@ card start date
			paymentData.setCardStart( String($( "select[name=card_start_1]" ).val()+$( "select[name=card_start_2]" ).val()) );
			// @@ card expiry date
			paymentData.setCardEnd( String($( "select[name=card_expiry_1]" ).val()+$( "select[name=card_expiry_2]" ).val()) );
			// @@ card issue number
			paymentData.setCardIssue( $( "input[name=card_issue]" ).val() );
			// @@ card cvv
			paymentData.setCardCVV( $( "input[name=card_cvv]" ).val() );
			// @@ customer address
			paymentData.setCustomerAddress( String($( "input[name=cust_address_1]" ).val() + "\n"
				+ $( "input[name=cust_address_2]" ).val() + "\n"
				+ $( "input[name=cust_address_3]" ).val() + "\n"
				+ $( "input[name=cust_address_4]" ).val())
			);
			// @@ customer postcode
			paymentData.setCustomerPostCode( $( "input[name=cust_postcode]" ).val() );
			// @@ customer country
			paymentData.setCustomerCountry( $( "select[name=cust_country]" ).val() );
			// @@ product data
			paymentData.setProductData( this.contentData.getProductData() );
			// @@ customer email
			paymentData.setCustomerEmail( this.manager.core.userProfile.getUserEmail() );
			// @@ customer phone
			paymentData.setCustomerTel( this.manager.core.userProfile.getUserPhone() );
			// @@ transaction description
			paymentData.setTransactionDescription( this.contentData.getProductData().getProductName() );
			// @@ transaction price
			paymentData.setTransactionAmount( this.contentData.getProductData().getProductPrice() );
			// @@ transaction test mode
			paymentData.setTransactionCurrency( "GBP" );
			// @@ transaction class
			paymentData.setTransactionClass( "MoTo" );
			// @@ transaction type
			paymentData.setTransactionType( "Sale" );
			// @@ transaction test mode
			paymentData.setTransactionTestMode( 0 );
			
			// pass the correct data to the control
			this.manager.getControl( "PurchasesControl" ).makePurchase( 
				this.manager.core.userProfile.getUserId(), paymentData 
			);
		},
		
		/**
		*   update
		*
		*   Updates the view
		*
		*	@param	t - event type
		*	@param	d - data
		*/
		update: function(t, d)
		{
			//alert( "updating : " + t + " : " + d );
			
			switch ( t )
			{
				// @@ onErrorDetected - error has been detected
				case "onErrorDetected":
				
					switch ( d.getErrorType() )
					{
						// @@ err - ??
						case "??":
						
							// post a message
							var msge = new MessageData();
								msge.setMessageType( "bad" );
								msge.setMessage( "Sorry. ??." );
							this.dialogueMessages.showMessage( msge );
						
							break;/**/
					}
				
					break;
					
				// @@ onMakePurchaseFailed - the purchase has been un-successful
				case "onMakePurchaseFailed":
				
					// post a message
					var msge = new MessageData();
						msge.setMessageType( "bad" );
						msge.setMessage( "Sorry. We were unable to take your payment, please check your details & try again. Your card has not been debited." );
					this.dialogueMessages.showMessage( msge );
				
					break;
			}
			
			// if the dialogue has not yet been built
			// return before trying to update components
			if ( !this.dialogueBuilt )
				return;
			
			// call to super
			this._super( t, d );
		}
	}
);

/**
*	@class 				AcceptCreditChargeDialogue
*
*	@usage 				Used to display the accept-credit-charge dialogue
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var AcceptCreditChargeDialogue = AbstractDialogue.extend(
	{
		/**
		*   init
		*
		*   Constructs the dialogue
		*
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*	@param	o - dialogue data object
		*/
		init: function(m, h, d)
		{
			this._super( "AcceptCreditChargeDialogue", m, h, d );
			
			//alert( this.getType() + " initiating..." );
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*/
		setup: function()
		{
			//alert( this.getType() + " setting up" );
			
			// call super
			this._super();
		},
		
		/**
		*   openDialogue / closeDialogue
		*
		*   Opens / Closes the dialogue
		*/
		openDialogue: function()
		{
			//alert( this.getType() + " opening" );
			
			var obj = this;
			
			// register the current state
			this.currentState = this.STATE_OPEN;
			
			// @@ load the mark-up
			$( this.getHolder() ).load( 
				this.manager.core.getPrefix() + "pages/dialogue/creditcharge.php", function () {
					obj.build();
				}
			);
			
			// if no content data has been defined
			// then exit the function
			if ( !this.contentData )
				return;
			
			// handle any bespoke functionality
			// get the credit charge data
			this.manager.getControl( "CreditControl" ).getCreditCharge( 
				this.contentData
			);
		},
		
		closeDialogue: function()
		{
			//alert( "closing" );
			
			// call to super
			this._super();
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( this.getType() + " building" );
			
			// call super
			this._super();
			
			// if no content data has been defined
			// then exit the function
			if ( !this.contentData )
				return;
				
			// clear the text fields
			
			// @@ product : title
			$( "div#text_product_title" ).html( "Loading..." );
			
			// @@ charge : price
			$( "div#text_charge_amt" ).html( "Loading..." );
		},
		
		/**
		*   displayCharge
		*
		*   Displays the charge once received from the database
		*/
		displayCharge: function()
		{
			//alert( this.getType() + " displaying charge" );
			
			// poulate all text fields
			
			// @@ product : title
			$( "div#text_product_title" ).html( this.contentData.getName() );
			
			// @@ charge : price
			if ( this.contentData.getCharge() == 1 )
				$( "div#text_charge_amt" ).html( this.contentData.getCharge() + " Credit" );
			else 
				$( "div#text_charge_amt" ).html( this.contentData.getCharge() + " Credits" );
		},
		
		/**
		*   acceptCharge
		*
		*   Accepts the credit charge
		*/
		acceptCharge: function()
		{
			this.manager.getControl( "CreditControl" ).acceptCreditCharge( this.contentData );
		},
		
		/**
		*   declineCharge
		*
		*   Declines the credit charge
		*/
		declineCharge: function()
		{
			this.manager.getControl( "CreditControl" ).declineCreditCharge( this.contentData );
		},
		
		/**
		*   update
		*
		*   Updates the view
		*
		*	@param	t - event type
		*	@param	d - data
		*/
		update: function(t, d)
		{
			//alert( "updating : " + t + " : " + d );
			
			switch ( t )
			{
				// @@ onCreditChargeRequestReceived - credit charge request received
				case "onCreditChargeRequestReceived":
				
					//alert( "credit charge received for : " + d.getCode() );
					
					// if no content data has been defined
					// then exit the function
					if ( !this.contentData )
						return;
					
					// append the received data onto the content data object
					// we cannot just replace it or risk over-writing any bespoke charge request data
					this.contentData.setChargeId( d.getChargeId() );
					this.contentData.setName( d.getName() );
					this.contentData.setCode( d.getCode() );
					this.contentData.setCharge( d.getCharge() );
					
					// display the charge
					this.displayCharge();
				
					break;
					
				// @@ onCreditChargeRequestFailed - credit charge request failed
				case "onCreditChargeRequestFailed":
				
					// post a message
					var msge = new MessageData();
					msge.setMessageType( "bad" );
					msge.setMessage( "There has been an error : We were unable to obtain the credit charge for this product. Please try again later." );
					this.manager.getControl( "GeneralControl" ).showMessage( msge );
				
					break;
			}
			
			// if the dialogue has not yet been built
			// return before trying to update components
			if ( !this.dialogueBuilt )
				return;
			
			// call to super
			this._super( t, d );
		}
	}
);

/*******************************************************************************************************************

Gloabl Functionality

********************************************************/

/**
 * 	postMessageToFacebook function
 *
 * 	<p>Posts a message to facebook</p>
 *
 *	@author		Daniel Ivanovic dan@substance001.com
 * 
 * 	@param 		n 		message
 * 
 * 	@return 	none
 *
 * 	@see		none
 */
function postMessageToFacebook(m)
{
	FB.Connect.streamPublish( m );	
}

/**
*   ImageWizardInterface
*
*   Interface offers open methods used by the image wizard
*
*   @usage    Used by all pages
*   @author   Daniel Ivanovic dan@anti-blanks.co.uk
*/

// @@ define the global interface var
var wizardInterface = this;

/**
*   gotoPage
*
*   Deep links flash app to passed page / content
*
*	@param	pagetype - the type of page ( panel / screen etc )
*	@param	page - the page id string
*/
function gotoPage(ct, c, at) 
{
	getMovie("imagewizard").gotoPage( ct, c, at );
}

/**
*   openWizard / closeWizard
*
*   Opens / Closes the currently open wizard browser window
*/
function openWizard()
{
	$('#dialog_im_wizard').dialog('open');
	$( this ).trigger( "onImageWizardOpened" );
}

function closeWizard() 
{
	$('#dialog_im_wizard').dialog('close');
	$( this ).trigger( "onImageWizardClosed" );
}

/**
*	uploadStarted / uploadComplete / uploadCompleteDataReceived
*
*	Broadcasts event - updates the js app of wizard upload status
*
*	@param	d - file data
*/
function uploadStarted(d)
{
	//alert( "upload started " + d );
	
	$( this ).trigger( "onUploadStarted", d );
}

function uploadComplete(d)
{
	//alert( "upload complete " + d );
	
	$( this ).trigger( "onUploadComplete", d );
}

function uploadCompleteDataReceived(d)
{
	//alert( "upload complete : data received " + d );
	
	$( this ).trigger( "onUploadCompleteDataReceived", d );
}

/**
*	uploadReturnScriptExecuted
*
*	Broadcasts event - updates the js app of wizard upload status
*	This data comes directly from a return PHP script, so we use eval to convert any strings back into objects
*	NOTE : The data passed must be in string format
*
*	@param	d - JSON string
*/
function uploadReturnScriptExecuted(d)
{
	//alert( "upload return script complete : data received " + d );
	
	$( this ).trigger( "onUploadReturnScriptExecuted", eval('(' + d + ')') );
}

/**
*   uploadQueueStarted / uploadQueueComplete
*
*   Broadcasts event - updates the js app of wizard upload queue status
*
*	@param	d - wizard data
*/
function uploadQueueStarted(d) 
{ 
	$( this ).trigger( "onUploadQueueStarted", d );
}

function uploadQueueComplete(d) 
{ 
	$( this ).trigger( "onUploadQueueComplete", d );
}

/**
*   Class : MessageData
*
*   Class holds all data necessary to esatblish a message element
*
*   @usage    Used by all forum elements
*   @author   Daniel Ivanovic dan@substance001.com
*
*	@param	name - element name
*	@param	action - element action
*/
var MessageData = AbstractObject.extend(
	{
		/**
		*   init
		*
		*   Constructs the button dat6a object
		*/
		init: function()
		{
			this._super( "MessageData" );
			
			this.messageType = '';
			this.message = '';
		},
		
		/**
		*   setMessageType / getMessageType
		*
		*   Sets / Returns the message type
		*/
		setMessageType: function(s) { this.messageType = s; },
		getMessageType: function() { return this.messageType; },
		
		/**
		*   setMessage / getMessage
		*
		*   Sets / Returns the message
		*/
		setMessage: function(s) { this.message = s; },
		getMessage: function() { return this.message; }
	}
);

/**
*	@class 				Messages
*
*	@usage 				Used to display any messages on the pages
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var Messages = AbstractView.extend(
	{
		/**
		*   init
		*
		*   Constructs the messages view
		*
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*/
		init: function(m, h)
		{
			this._super( "Messages", m, h );
			
			// define props
			var obj = this;
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*/
		setup: function()
		{
			//alert( "setting up messages : " + this.getManager().getCore() );
			
			// get the buttonData array
			this.build();
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			// No build here
		},
		
		/**
		*   showMessage
		*
		*   Shows a new message
		*
		*	@param	m - message data object
		*/
		showMessage: function(m)
		{
			//alert( "showing message : " + m.messageType );
			
			if ( m.messageType == null ) return;
			
			// flush the object
			this.flush( this );
			
			var s1 = ( m.messageType == "good" ) ? 'ui-state-highlight' : 'ui-state-error';
			var s2 = ( m.messageType == "good" ) ? 'ui-icon-info' : 'ui-icon-alert';
			
			var d0 = $(document.createElement( 'div' )).addClass( "msge_holder" );
			var d1 = $(document.createElement( 'div' )).addClass( "ui-widget" );
			var d2 = $(document.createElement( 'div' )).addClass( s1 ).addClass( "ui-corner-all" ).addClass( "msge" );
			
			var p = $(document.createElement( 'p' ));
			var sp = $(document.createElement( 'span' )).addClass( s2 ).addClass( "ui-icon" ).addClass( "msge-ui-icon" );
			var ul = $(document.createElement( 'ul' )).append( '<li>' + m.message + '</li>' );
			
			$( p ).append( sp );
			$( p ).append( ul );
			$( d2 ).append( p );
			$( d1 ).append( d2 );
			$( d0 ).append( d1 );
			
			// add elements
			this.addElement( "Message", d0 );
			
			// add to holder
			$( this.getHolder() ).append( this.getElement( "Message" ) );
			
			// scroll window so user can see message
			window.scroll( 0, 0 );
		},
		
		/**
		*   hideMessage
		*
		*   Hides a message
		*
		*	@param	m - message data object
		*/
		hideMessage: function(m)
		{
			//alert( "hiding message : " + m.messageType );
			
			// flush the object
			this.flush( this );
		},
		
		/**
		*   update
		*
		*   Updates the view
		*
		*	@param	t - event type
		*	@param	d - data
		*/
		update: function(t, d)
		{
			//alert( "updating : " + t + " : " + d );
			
			switch ( t )
			{
				// @@ show a new message
				case "onMessageShow":
				
					this.showMessage( d );
				
					break;
				// @@ hide an existing message
				case "onMessageHide":
				
					this.hideMessage( d );
				
					break;
			}
		}
	}
);

/**
*	@class 				DialogueMessages
*
*	@usage 				Used to display any messages on the dialogue panels
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var DialogueMessages = AbstractView.extend(
	{
		/**
		*   init
		*
		*   Constructs the dialogue messages view
		*
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*/
		init: function(m, h)
		{
			this._super( "DialogueMessages", m, h );
			
			// define props
			var obj = this;
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*/
		setup: function()
		{
			//alert( "setting up messages : " + this.getManager().getCore() );
			
			// get the buttonData array
			this.build();
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			// hide messages as default
			this.hideMessage( null );
		},
		
		/**
		*   showMessage
		*
		*   Shows a new message
		*
		*	@param	m - message data object
		*/
		showMessage: function(m)
		{
			//alert( "showing message : " + m.messageType );
			
			if ( m.messageType == null ) return;
			
			// flush the object
			this.hideMessage( null );
			
			var s1 = ( m.messageType == "good" ) ? 'ui-state-highlight' : 'ui-state-error';
			var s2 = ( m.messageType == "good" ) ? 'ui-icon-info' : 'ui-icon-alert';
			
			var d0 = $(document.createElement( 'div' )).addClass( "msge_holder" );
			var d1 = $(document.createElement( 'div' )).addClass( "ui-widget" );
			var d2 = $(document.createElement( 'div' )).addClass( s1 ).addClass( "ui-corner-all" ).addClass( "msge" );
			
			var p = $(document.createElement( 'p' ));
			var sp = $(document.createElement( 'span' )).addClass( s2 ).addClass( "ui-icon" ).addClass( "msge-ui-icon" );
			var ul = $(document.createElement( 'ul' )).append( '<li>' + m.message + '</li>' );
			
			$( p ).append( sp );
			$( p ).append( ul );
			$( d2 ).append( p );
			$( d1 ).append( d2 );
			$( d0 ).append( d1 );
			
			// add to holder
			$( this.getHolder() ).append( d0 );
			
			// scroll the window if necessary
			// we only do this if the message is out of sight
			if ( $( window ).scrollTop() > $( this.getHolder() ).parent().offset().top )
				window.scroll( 0, $( this.getHolder() ).parent().offset().top );
				
			// show the holder
			$( this.getHolder() ).show();
		},
		
		/**
		*   hideMessage
		*
		*   Hides a message
		*
		*	@param	m - message data object
		*/
		hideMessage: function(m)
		{
			//alert( "hiding message : " + m.messageType );
			
			// flush the holder
			$( this.getHolder() ).html( "" );
			
			// hide the holder
			$( this.getHolder() ).hide();
		},
		
		/**
		*   update
		*
		*   Updates the view
		*
		*	@param	t - event type
		*	@param	d - data
		*/
		update: function(t, d)
		{
			//alert( this.getType() + " updating : " + t + " : " + d );
			
			switch ( t )
			{
				// @@ show a new message
				case "onDialogueMessageShow":
				
					this.showMessage( d );
				
					break;
				// @@ hide an existing message
				case "onDialogueMessageHide":
				
					this.hideMessage( d );
				
					break;
			}
		}
	}
);

/**
*	@class 				Footer
*
*	@usage 				Used to display the footer element of the site
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var Footer = AbstractView.extend(
	{
		/**
		*   init
		*
		*   Constructs the footer view
		*
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*/
		init: function(m, h)
		{
			this._super( "Footer", m, h );
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*/
		setup: function()
		{
			//alert( "setting up footer : " + this.getManager() );
			
			// define props
			this.links = [
				{ label: "Help", funct: "javascript:app.generalControl.changePage( \'mailto:ukffgirls@ukfootballfinder.co.uk\' );" },
				{ label: "Contact Us", funct: "javascript:app.generalControl.changePage( \'mailto:ukffgirls@ukfootballfinder.co.uk\' );" },
				{ label: "Terms Of Service", funct: "javascript:app.generalControl.changePage( \'" + this.manager.core.getPrefix() + "pages/info/terms.php" + "\' );" },
				{ label: "Privacy", funct: "javascript:app.generalControl.changePage( \'" + this.manager.core.getPrefix() + "pages/info/privacy.php" + "\' );" }
			];
			
			// get the buttonData array
			this.build();
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building footer : " + this.getManager() + " : " + $( this.getHolder() ) );
			
			// add the credit card logo bar
			$( this.getHolder() ).append( '<img src="' + this.manager.core.getPrefix() + 'images/mechs/UKFF_CC_LogoBar.jpg" border="0px" />' );
			
			this.h = $(document.createElement('div')).addClass('footer_holder');
			$( this.h ).addClass( 'bc_9_ffffff_b' );
			
			for ( i=0; i<this.links.length; i++ )
			{
				var a = $(document.createElement( 'a' )).addClass( 'a_ffffff_n_u_r_9' ).append( this.links[i].label );
				$( a ).attr( 'href', this.links[i].funct );
				$( this.h ).append( a );
				
				// create a spacer
				if ( i != this.links.length-1 ) {
					$( this.h ).append( "&nbsp;&nbsp;|&nbsp;&nbsp;" );
				}
			}
			
			// append to page
			$( this.getHolder() ).append( this.h );
		}
	}
);

/**
*	@class 				Navigation
*
*	@usage 				Used to display the navigation element of the site
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var Navigation = AbstractView.extend(
	{
		/**
		*   init
		*
		*   Constructs the navigation view
		*
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*/
		init: function(m, h)
		{
			this._super( "Navigation", m, h );
			
			// define props
			var obj = this;
			this.d = $(document.createElement('div')).addClass( 'nav_holder' );
			this.buttons = new Array();
			this.buttonData = new Array();
			
			// define all the action types
			this.NAV_ACTION_TYPE_PAGE_CHANGE = "actionTypePageChange";
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*/
		setup: function()
		{
			//alert( "setting up nav : " + this.getManager() );
			
			// get the buttonData array
			this.build();
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building nav : " + this.getManager() );
			
			var obj = this;
			this.buttonData = [];
			if ( this.manager.core.getUserProfile() == null ) {
			// if there is no user logged in
				//alert( "hi!" );
				var detailsLink = "" + this.manager.core.getPrefix() + "pages/user/login.php";
				this.buttonData.push( this.getHomeButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getLoginButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getSignUpButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getGirlsButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getBoysButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getAgenciesButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getCompsButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getCastingButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getEventsButton( this.manager.core.getPrefix() ) );
				//this.buttonData.push( this.getMessagesButton( this.manager.core.getPrefix() ) );
				//this.buttonData.push( this.getDetailsButton( this.manager.core.getPrefix(), detailsLink ) );
			} else {
			// if there is a user logged
				var detailsLink = "" + this.manager.core.getPrefix() + "pages/user/profile.php?utype=" + this.manager.core.userProfile.getUserType() + "&pid=" + this.manager.core.userProfile.getProfileId();
				this.buttonData.push( this.getHomeButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getGirlsButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getBoysButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getAgenciesButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getCompsButton( this.manager.core.getPrefix() ) );
				//this.buttonData.push( this.getMessagesButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getCastingButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getEventsButton( this.manager.core.getPrefix() ) );
				this.buttonData.push( this.getDetailsButton( this.manager.core.getPrefix(), detailsLink ) );
			}
			
			var u = $(document.createElement( 'ul' ));
			$( this.d ).append( u );
			
			for ( i=0; i<this.buttonData.length; i++ )
			{
				// create the button
				var btn = new NavigationButton( this.getManager(), $( u ) );
					btn.setup( this.buttonData[i] );
					btn.enable();
				
				$( btn ).bind( 'onButtonRolledOver', function( evt, data ) { 
					obj.showButtonDropDown( data.id );
					return false;
				});
				
				$( btn ).bind( 'onButtonReleased', function( evt, data ) { 
					//alert( data.id + " : " + data.funct + " : " + data.page );
					// switch on the passed functionality
					switch ( data.funct )
					{
						// @@ case : NAV_ACTION_TYPE_PAGE_CHANGE : Change the page as requested
						case obj.NAV_ACTION_TYPE_PAGE_CHANGE:
						
							obj.manager.getControl( "GeneralControl" ).changePage( data.page );
						
							break;
					}
					return false;
				});/**/
				
				// if not the last item
				// create a spacer
				if ( i != this.buttonData.length-1 )
				{
					var s = $(document.createElement('li')).addClass( 'navspacer' );
					$( s ).append( "|" );
					$( u ).append( s ); 
				}
				
				this.buttons.push( btn );
			}
			
			$( this.getHolder() ).append( this.d );
			
			// position nav : centrally
			$( this.d ).css( { "position" : "relative", "left" : "50%", "margin-left" : -($( this.d ).width() * 0.5) } );
		},
		
		/**
		*   showButtonDropDown
		*
		*   Shows a specified buttons drop down
		*
		*	@param	id - button id
		*/
		showButtonDropDown: function(id)
		{
			//alert( "showing drop down : " + id );
			
			for ( var i in this.buttons )
			{
				//if ( this.buttons[i].getButtonData().id != id ) {
					if ( this.buttons[i].getDropDown() != null ) {
						//alert( "hiding : " + this.buttons[i].getButtonData().id );
						this.buttons[i].hideDropDown();
					}
				//}
				if ( this.buttons[i].getButtonData().id == id ) {
					if ( !this.buttons[i].getSelected() && this.buttons[i].getDropDown() != null ) 
						this.buttons[i].showDropDown();
				}
			}
		},
		
		/**
		*   getHomeButton
		*
		*   Returns the home button object
		*/
		getHomeButton: function(prefix)
		{
			return { 
				id: "NvBtn_Hme",
				label: "HOME", 
				alt: "HOME",
				active: 1,
				funct: "actionTypePageChange",
				page: prefix + "index.php",
				sublinks: null
			};
		},
		
		/**
		*   getLoginButton
		*
		*   Returns the login button object
		*/
		getLoginButton: function(prefix)
		{
			return { 
				id: "NvBtn_Log", 
				label: "LOG IN", 
				alt: "LOG IN",
				active: 1,
				funct: "actionTypePageChange",
				page: prefix + "pages/user/login.php",
				sublinks: null
			};
		},
		
		/**
		*   getSignUpButton
		*
		*   Returns the sign up button object
		*/
		getSignUpButton: function(prefix)
		{
			return { 
				id: "NvBtn_Sign", 
				label: "SIGN UP",
				alt: "SIGN UP",
				active: 1,
				funct: null,
				sublinks: [ 
					{ label: "Sign up as 'Girl'", funct: "javascript:GoToWindow( \'" + prefix + "pages/user/signup.php?ut=1\' );" },
					{ label: "Sign up as 'Guy'", funct: "javascript:GoToWindow( \'" + prefix + "pages/user/signup.php?ut=4\' );" },
					{ label: "Sign up as 'Photographer'", funct: "javascript:GoToWindow( \'" + prefix + "pages/user/signup.php?ut=2\' );" },
					{ label: "Sign up as 'Promotion Company'", funct: "javascript:GoToWindow( \'" + prefix + "pages/user/signup.php?ut=2\' );" },
					{ label: "Sign up as 'Publication Company'", funct: "javascript:GoToWindow( \'" + prefix + "pages/user/signup.php?ut=2\' );" },
					{ label: "Sign up as 'TV/Film Company'", funct: "javascript:GoToWindow( \'" + prefix + "pages/user/signup.php?ut=2\' );" },
					{ label: "Sign up as 'Make Up Artist'", funct: "javascript:GoToWindow( \'" + prefix + "pages/user/signup.php?ut=2\' );" },
					{ label: "Sign up as 'Presenter'", funct: "javascript:GoToWindow( \'" + prefix + "pages/user/signup.php?ut=2\' );" },
					{ label: "Sign up as 'Designer'", funct: "javascript:GoToWindow( \'" + prefix + "pages/user/signup.php?ut=2\' );" },
					{ label: "Sign up as 'Other Directory Listing'", funct: "javascript:GoToWindow( \'" + prefix + "pages/user/signup.php?ut=2\' );" }
				]
			};
		},
		
		/**
		*   getGirlsButton
		*
		*   Returns the girls button object
		*/
		getGirlsButton: function(prefix)
		{
			return { 
				id: "NvBtn_Girls", 
				label: "GIRLS",
				alt: "GIRLS",
				active: 1,
				funct: null,
				sublinks: [ 
					{ label: "Find a girl", funct: "javascript:GoToWindow( \'" + prefix + "pages/find.php?utype=1\' );" },
					{ label: "Featured girls", funct: "javascript:GoToWindow( \'" + prefix + "pages/featured.php\' );" }
				]
			};
		},
		
		/**
		*   getBoysButton
		*
		*   Returns the boys button object
		*/
		getBoysButton: function(prefix)
		{
			return { 
				id: "NvBtn_Boys", 
				label: "GUYS",
				alt: "GUYS",
				active: 1,
				funct: null,
				sublinks: [ 
					{ label: "Find a guy", funct: "javascript:GoToWindow( \'" + prefix + "pages/find.php?utype=4\' );" }
				]
			};
		},
		
		/**
		*   getAgenciesButton
		*
		*   Returns the agencies button object
		*/
		getAgenciesButton: function(prefix)
		{
			return { 
				id: "NvBtn_Agencies", 
				label: "DIRECTORY",
				alt: "DIRECTORY",
				active: 1,
				funct: null,
				sublinks: [ 
					{ label: "Find photographers", funct: "javascript:GoToWindow( \'" + prefix + "pages/find.php?utype=2\' );" },
					{ label: "Find promotion companies", funct: "javascript:GoToWindow( \'" + prefix + "pages/find.php?utype=2\' );" },
					{ label: "Find publication companies", funct: "javascript:GoToWindow( \'" + prefix + "pages/find.php?utype=2\' );" },
					{ label: "Find TV/Film companies", funct: "javascript:GoToWindow( \'" + prefix + "pages/find.php?utype=2\' );" },
					{ label: "Find make up artists", funct: "javascript:GoToWindow( \'" + prefix + "pages/find.php?utype=2\' );" },
					{ label: "Find presenters", funct: "javascript:GoToWindow( \'" + prefix + "pages/find.php?utype=2\' );" },
					{ label: "Find designers", funct: "javascript:GoToWindow( \'" + prefix + "pages/find.php?utype=2\' );" },
					{ label: "Find other directory listings", funct: "javascript:GoToWindow( \'" + prefix + "pages/find.php?utype=2\' );" }
				]
			};
		},
		
		/**
		*   getCompsButton
		*
		*   Returns the comps button object
		*/
		getCompsButton: function(prefix)
		{
			return { 
				id: "NvBtn_CComp", 
				label: "CURRENT COMPS", 
				alt: "CURRENT COMPS",
				active: 1,
				funct: null,
				sublinks: [ 
					{ label: "Miss UKFF 2010", funct: "javascript:GoToWindow( \'" + prefix + "pages/missukffvote.php\' );" },
					{ label: "Sexy Football", funct: "javascript:GoToWindow( \'http://www.ukfootballfinder.co.uk/sf/\' );" },
					{ label: "UKFF Girls League Table", funct: "javascript:GoToWindow( \'" + prefix + "pages/leaguetable.php?utype=1\' );" },
					{ label: "UKFF Directory League Table", funct: "javascript:GoToWindow( \'" + prefix + "pages/leaguetable.php?utype=2\' );" }
				]
			};
		},
		
		/**
		*   getMessagesButton
		*
		*   Returns the messages button object
		*/
		getMessagesButton: function(prefix)
		{
			return { 
				id: "NvBtn_Msge", 
				label: "MESSAGES",
				alt: "MESSAGES",
				active: 0,
				funct: "actionTypePageChange",
				page: prefix + "index.php",
				sublinks: null
			};
		},
		
		/**
		*   getCastingButton
		*
		*   Returns the casting button object
		*/
		getCastingButton: function(prefix)
		{
			var sublinks = new Array();
				sublinks.push( { label: "Find a casting", funct: "javascript:GoToWindow( \'" + prefix + "pages/castings.php?cmd=find\' );" } );
			
			if ( this.manager.core.getUserProfile() ) {
			// if there is a ussr logged in
				if ( this.manager.core.userProfile.getUserType() == USER_TYPE_AGENCY ) {
				// and if the user type is agency
					// add the agency specific page links
					sublinks.push( { label: "Add a casting", funct: "javascript:GoToWindow( \'" + prefix + "pages/castings.php?cmd=add\' );" } );
					sublinks.push( { label: "My castings", funct: "javascript:GoToWindow( \'" + prefix + "pages/user/mycastings.php\' );" } );
				}
			}
			
			return { 
				id: "NvBtn_Cast", 
				label: "CASTINGS",
				alt: "COMING SOON",
				active: 0,
				funct: null,
				sublinks: sublinks
			};
		},
		
		/**
		*   getEventsButton
		*
		*   Returns the events button object
		*/
		getEventsButton: function(prefix)
		{
			return { 
				id: "NvBtn_Events", 
				label: "EVENTS",
				alt: "COMING SOON",
				active: 0,
				funct: null,
				sublinks: [
					{ label: "Miss UKFF 2010 Grand Final", funct: "javascript:GoToWindow( \'" + prefix + "pages/events/missukfffinal.php\' );" }
				]
			};
		},
		
		/**
		*   getDetailsButton
		*
		*   Returns the details button object
		*
		*	@param l - details button link
		*/
		getDetailsButton: function(prefix, weblink)
		{
			return { 
				id: "NvBtn_Dets", 
				label: "MY DETAILS", 
				alt: "MY DETAILS",
				active: 1,
				funct: "actionTypePageChange",
				page: weblink,
				sublinks: null
			};
		}
	}
);

/**
*	@class 				NavigationButton
*
*	@usage 				Used to display the navigation buttons
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var NavigationButton = AbstractButton.extend(
	{
		/**
		*   init
		*
		*   Constructs the navigation button view
		*
		*	@param	m - manager instance
		*	@param	h - holder instance
		*/
		init: function(m, h)
		{
			this._super( "NavigationButton", m, h );
			
			// define all object props
			this.selected = false;
			this.dropdown = null;
		},
		
		/**
		*   setup
		*
		*   Sets up the view
		*
		*	@param	d - button data object
		*/
		setup: function(d)
		{
			//alert( "setting up" );
			
			// call super last to build button
			this._super( d );
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building nav button : " + this.buttonData.label );
			//alert( "building nav button : " + this.getHolder() );
			
			var obj = this;
			
			var a = $(document.createElement( 'a' )).addClass( 'a_ffffff_b_r_9' ).append( this.buttonData.label );
			$( a ).attr( 'href', "javascript: void(); return false;" );
			$( a ).attr( 'title', ( this.buttonData.active != 0 ) ? this.buttonData.alt : "COMING SOON" );
			
			this.button = $(document.createElement( 'li' )).addClass( 'navbutton' );
			$( this.button ).append( a );
			
			$( this.getHolder() ).append( this.button );
			
			if ( this.buttonData.sublinks != null ) {
				//$( this.button ).mouseover( function() { if ( !obj.selected ) obj.showDropDown(); });
				this.buildDropDown( this.buttonData.sublinks );
			}
			
			// call super last to build button
			this._super();
		},
		
		/**
		*   onButtonRollOver / onButtonRollOut
		*
		*   Called upon roll over of button
		*/
		onButtonRollOver: function()
		{
			//alert( "rolled over" );
			
			// call super at end
			this._super();
		},
		
		onButtonRollOut: function()
		{
			//alert( "rolled out" );
			
			// call super at end
			this._super();
		},/**/
		
		/**
		*   buildDropDown
		*
		*   Builds the drop down menu for a nav element
		*
		*	@param	sl - sublinks array
		*/
		buildDropDown: function(sl) 
		{
			if ( this.dropdown != null ) return;
			
			// create the drop down window
			this.dropdown = $(document.createElement( 'div' ));
			
			// create the list
			var dul = $(document.createElement( 'ul' )).addClass( 'nav_drop_dwn' );
			$( this.dropdown ).append( dul );
			
			// NOTE : It seems that because i used an 'i' in the loop int made it continuous
			
			for ( j=0; j<this.buttonData.sublinks.length; j++ )
			{
				// create the sub link
				var l = $(document.createElement( 'li' ));
				$( dul ).append( l );
				
				var a = $(document.createElement( 'a' )).addClass( 'a_ffffff_n_r_9' ).append( this.buttonData.sublinks[j].label );
				$( a ).attr( 'href', this.buttonData.sublinks[j].funct );
				$( l ).append( a );
			}
			
			$( "body" ).append( this.dropdown );
			
			// hide
			this.hideDropDown();
		},
		
		/**
		*   showDropDown
		*
		*   Shows the drop down menu for a nav element
		*/
		showDropDown: function()
		{
			//alert( "showing drop down : " + this.getButtonData().id + " : " + this.dropdown );
			
			// register as selected
			this.selected = true;
			
			// show the panel
			var obj = this;
			var ddul = $( this.dropdown ).children( "ul.nav_drop_dwn" );
			$( ddul ).show();
			
			//alert( "showing button menu : " + $( this.button ).position().top + " : " + $( this.button ).position().left );
			
			// define the position of the drop down
			// check the browser and if IE then display the menu differently
			var posTop = $( this.button ).offset().top + 2;
			var posLeft = $( this.button ).offset().left;
			
			// position 
			$( ddul ).css( { 'position' : 'absolute', 'left' : String( posLeft + "px" ), 'top' : String( posTop + "px" ) } );
			
			// handle hover
			$( ddul ).hover( function() {}, function() { obj.hideDropDown(); return false; } );
		},
		
		/**
		*   hideDropDown
		*
		*   Hides the drop down menu for a nav element
		*/
		hideDropDown: function()
		{
			//alert( "hiding drop down : " + this.getButtonData().id + " : " + this.getSelected() + " : " + this.dropdown );
			
			// register as un-selected
			this.selected = false;
			
			// hide the drop down list
			var ddul = $( this.dropdown ).children( "ul.nav_drop_dwn" );
			$( ddul ).hide();
		},
		
		/**
		*   getSelected
		*
		*   Returns the buttons selected boolean
		*/
		setSelected: function(e) { this.selected = e; },
		getSelected: function() { return this.selected; },
		
		/**
		*   getDropDown
		*
		*   Returns the buttons dropdown instance
		*/
		setDropDown: function(e) { this.dropdown = e; },
		getDropDown: function() { return this.dropdown; }
	}
);

/**
*	@class 				UserBar
*
*	@usage 				Used to display the userbar element in the site header
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var UserBar = AbstractView.extend(
	{
		/**
		*   init
		*
		*   Constructs the user bar view
		*
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*/
		init: function(m, h)
		{
			this._super( "UserBar", m, h );
			
			// define props
			this.links = new Array();
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*/
		setup: function()
		{
			//alert( "setting up" );
			
			// exit function if no user logged in
			if ( this.manager.core.getUserProfile() == null )
				this.buildForVisitor();
			else 
				this.buildForUser();
		},
		
		/**
		*   buildForVisitor
		*
		*   Builds the view for a visitor
		*/
		buildForVisitor: function()
		{
			//alert( "building for visitor" );
			
			var obj = this;
			
			// clear the current html
			$( this.getHolder() ).html( "" );
			
			// append the new html
			$( this.getHolder() ).append( '<div class="form">' +
				'<form name="frm_userbar_login" action="_self" method="post">' +
					'<div class="title email bc_11_ffffff">Email</div>' +
					'<div class="input"><input name="frm_userbar_email" type="text" size="25" class="input_w_180_h_18_r input_standard" /></div>' +
					'<div class="title password bc_11_ffffff">Password</div>' +
					'<div class="input"><input name="frm_userbar_password" type="password" size="25" class="input_w_180_h_18_r input_standard" /></div>' +
					'<div class="button"><a href="javascript: void();" class="a_lozenge_btn_feb20e_60x22_strd" id="btn_login"><div class="label">Login</div></a></div>' +
					'<div class="button"><a href="javascript: void();" class="a_lozenge_btn_feb20e_60x22_strd" id="btn_forgot_password"><div class="label">Forgot?</div></a></div>' +
				'</form>' +
			'</div>' );
			
			// setup the correct buttons
			// @@ login button
			$( "a#btn_login" ).bind( 'click', null, function(evt) {
				obj.manager.getControl( "GeneralControl" ).logInUser(
					$("input[name=frm_userbar_email]").val(),
					$("input[name=frm_userbar_password]").val()
				);
				return false;
			});
			// @@ forgot password button
			$( "a#btn_forgot_password" ).bind( 'click', null, function(evt) {
				obj.manager.getControl( "GeneralControl" ).changePage(
					obj.manager.core.getPrefix() + "pages/user/getpassword.php"
				);
				return false;
			});
		},
		
		/**
		*   buildForUser
		*
		*   Builds the view for a logged in user
		*/
		buildForUser: function()
		{
			//alert( "building for logged user" );
			
			var obj = this;
			
			// clear the current html
			$( this.getHolder() ).html( "" );
			
			// append the new html
			$( this.getHolder() ).append( '<ul></ul>' );
			
			// clear the links array
			this.links = new Array();
			
			// add all the standard links
			// @@ greeting
			this.addLink( "passive", "HELLO : " + this.manager.core.userProfile.getName().toUpperCase() );
			// @@ my account
			this.addLink( "active", "MY ACCOUNT", this.manager.core.getPrefix() + "pages/user/account.php" );
			// @@ edit details
			this.addLink( "active", "EDIT DETAILS", this.manager.core.getPrefix() + "pages/user/editprofile.php" );
			
			// @@ admin link ( if permitted )
			// this id simply states whether the userbar will allow opening of the admin system
			// there is a secondary check behind the scenes whenevr a user tries to view the admin area
			if ( this.manager.core.userProfile.getUserPermissionId() != 0 )
				this.addLink( "active", "ADMIN", this.manager.core.getPrefix() + "admin/" );
				
			// @@ log out
			this.addLink( "active", "LOG OUT", this.manager.core.getPrefix() + "pages/user/logout.php" );
			
			// loop an display the links
			for ( i=0; i<this.links.length; i++ )
			{
				if ( this.links[i].type == "active" ) {
					$( this.getHolder() + " > ul" ).append( '<li class="active_link"><a href="' + this.links[i].href + '" class="a_ffffff_b_r_9">' + this.links[i].label + '</a></li>' );
				} else {
					$( this.getHolder() + " > ul" ).append( '<li class="passive_link">' + this.links[i].label + '</li>' );
				}
				
				if ( i != this.links.length-1 )
					$( this.getHolder() + " > ul" ).append( '<li class="divide">|</li>' );
			}
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building" );
		},
		
		/**
		*	AddLink
		*
		*	Adds a link to the messages array
		*
		*	@param	t - type
		*	@param	l - label
		*	@param	h - href link
		*/
		addLink: function(t, l, h)
		{
			//alert( "adding link " + t );
			
			var ubLink = {
				type: t,
				label: l,
				href: h
			};
			
			this.links.push( ubLink );
		}
	}
);

/**
*	@class 				AbstractAdvert
*
*	@usage 				Base display class for all advert instances. All adverts will extend this class
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var AbstractAdvert = AbstractView.extend(
	{
		/**
		*   init
		*
		*   Constructs the advert
		*
		*	@param	t - type string
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*/
		init: function(t, m, h)
		{
			this._super( t, m, h );
			
			// define statics
			this.AD_TYPE_SWF = "swf";
			this.AD_TYPE_IMAGE = "img";
			this.AD_TYPE_DEFAULT = this.AD_TYPE_IMAGE;
			
			// @@ define props
			this.adverts = new Array();
			this.placementData = null;
			this.adType = this.AD_TYPE_DEFAULT;
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*
		*	@param	d - placement data object
		*/
		setup: function(d)
		{
			//alert( "setting up : " + d );
			
			// register the placement data
			this.placementData = d;
			
			// build
			this.build();
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building" );
			
			if ( this.adverts.length == 0 )
				return;
				
			// else show the first
			// TODO : Show first ad here
		},
		
		/**
		*   addAdvert
		*
		*   Adds an advert to the adverts array
		*
		*	@param	f - ad file
		*/
		addAdvert: function(f)
		{
			//alert( "adding advert : " + f );
			
			this.adverts[ f ] = f;
		},
		
		/**
		*   showAdvert
		*
		*   Shows an advert from the adverts array
		*
		*	@param	id - ad id
		*/
		showAdvert: function(id)
		{
			//alert( "showing advert : " + id );
			
			// split the file name string to ascertain the file type
			var strArray = String( id ).split( "." );
			var fileType = strArray[ strArray.length-1 ];
			
			if ( fileType == this.AD_TYPE_SWF )
				this.adType = this.AD_TYPE_SWF;
				
			switch ( this.adType )
			{
				// @@ ad is of type : .swf
				case this.AD_TYPE_SWF:
				
					var att = { 
						data: this.manager.core.getPrefix()+'adverts/'+this.placementData.getDirectory()+'/'+this.adverts[ id ], 
						width: this.placementData.getWidth(), 
						height: this.placementData.getHeight(),
						wmode: "opaque"
					};
					var par = {};
					var id = "comp_ad_" + this.placementData.placementId + "_content";
					
					swfobject.createSWF( att, par, id );
				
					break;
				
				// @@ ad is of type .img [ .jpg / .gif / .png ]
				case this.AD_TYPE_IMAGE:
				
					$( "div#comp_ad_" + this.placementData.placementId + "_content" ).html(
						'<img src="' + this.manager.core.getPrefix() + 'adverts/' + this.placementData.getDirectory() + '/' + 
						this.adverts[ id ] + '" border="0px" width="' + this.placementData.getWidth() + 'px" height="' + this.placementData.getHeight() + 'px" />'
					);
				
					break;
			}
		},
		
		/**
		*   update
		*
		*   Updates the view
		*
		*	@param	t - event type
		*	@param	d - data
		*/
		update: function(t, d)
		{
			//alert( "updating : " + t + " : " + d );
			
			switch ( t )
			{
				// @@ assigned ads have been received
				case "onAssignedAdsReceived":
				
					if ( d.ads[0].placement_id != this.placementData.getPlacementId() )
						return;
						
					// else if the id matches
					for ( i=0; i<d.ads.length; i++ )
					{
						if ( !this.adverts[ d.ads[i].file ] )
							this.addAdvert( d.ads[i].file );
					}
					
					// show the first
					this.showAdvert( d.ads[0].file );
				
					break;
			}
		}
	}
);

/**
*	@class 				Advert
*
*	@usage 				advert display class
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var Advert = AbstractAdvert.extend(
	{
		/**
		*   init
		*
		*   Constructs the advert
		*
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*/
		init: function(m, h)
		{
			this._super( "Advert", m, h );
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*
		*	@param	d - placement data object
		*/
		setup: function(d)
		{
			//alert( "setting up : " + d );
			
			// call super
			this._super( d );
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building" );
			
			// call super
			this._super();
		}
	}
);

/**
*	@class 				AbstractUpload
*
*	@usage 				Base display class for the image wizard upload. All upload instances will extend this class
*
*	@author 			Daniel Ivanovic dan@anti-blanks.co.uk
*/

var AbstractUpload = AbstractView.extend(
	{
		/**
		*   init
		*
		*   Constructs the image upload
		*
		*	@param	t - type string
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*/
		init: function(t, m, h)
		{
			this._super( t, m, h );
			
			this.flashvars = new Object();
			this.params = new Object();
			this.attributes = new Object();
			this.crops = 1;
			this.resizes = 1;
			this.upload = null;
			this.crop = null;
			this.resize = null;
			this.directory = null;
			this.uploadfolder = null;
			this.uploadscript = null;
			this.returnscript = null;
			this.types = null;
			this.uploadsMax = 25;
			this.fileSizeMax = 350000;
			this.xml = 'config';
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*/
		setup: function()
		{
			//alert( "setting up" );
			
			this.build();
		},
		
		/**
		*   embedSWF
		*
		*   Embeds the swf
		*/
		embedSWF: function()
		{
			//alert( "holder : " + document.getElementById( this.getHolder() ) + " : " + this.getHolder() );
			
			if ( !document.getElementById( this.getHolder() ) )
				$( "div#dialog_im_wizard" ).append( '<div id="' + this.getHolder() + '"></div>' );
			
			// create the flash vars string
			var flashvarsStr = '';
			var j = 0;
			for ( var i in this.flashvars )
			{
				if ( j != 0 )
					flashvarsStr += "&";
				flashvarsStr += i + "=" + this.flashvars[i];
				j++;
			}
			
			var att = { data:this.manager.core.getPrefix()+'imagewizard/ImageWizard.swf', width:"400", height:"292" };
			var par = { flashvars: flashvarsStr };
			var id = this.getHolder();
			
			swfobject.createSWF(att, par, id);
		},
		
		/**
		*   removeSWF
		*
		*   Removes the embedded swf
		*/
		removeSWF: function()
		{
			swfobject.removeSWF( this.getHolder() );
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building" );
			
			if ( this.upload == null ) 			alert( "WARNING : No upload bool set" );
			if ( this.crop == null ) 			alert( "WARNING : No crop bool set" );
			if ( this.resize == null ) 			alert( "WARNING : No resize bool set" );
			if ( this.directory == null ) 		alert( "WARNING : No directory set" );
			if ( this.uploadfolder == null ) 	alert( "WARNING : No upload folder set" );
			if ( this.uploadscript == null )	alert( "WARNING : No upload script set" );
			if ( this.returnscript == null )	alert( "WARNING : No return script set" );
			if ( this.types == null ) 			alert( "WARNING : No file types set" );
			
			// @@ flash vars
			this.flashvars.defaultscreen = "UploadScreen";
			this.flashvars.upload = this.upload;
			this.flashvars.uploadsMax = this.uploadsMax;
			this.flashvars.fileSizeMax = this.fileSizeMax;
			this.flashvars.crop = this.crop;
			this.flashvars.resize = this.resize;
			this.flashvars.directory = this.directory;
			this.flashvars.uploadfolder = this.uploadfolder;
			this.flashvars.uploadscript = this.uploadscript;
			this.flashvars.returnscript = this.returnscript;
			this.flashvars.types = this.types;
			this.flashvars.xml = this.xml;
			
			// @@ params
			this.params.allowScriptAccess = "always";
			
			// @@ attribs
			this.attributes.id = "imagewizard";
			this.attributes.name = "imagewizard";
			
			this.embedSWF();
		},
		
		/**
		*   setUpload / getUpload
		*
		*   Sets / Returns the upload bool
		*/
		setUpload: function(f) { this.upload = f; },
		getUpload: function() { return this.upload; },
		
		/**
		*   setUploadsMax / getUploadsMax
		*
		*   Sets / Returns the upload max value
		*/
		setUploadsMax: function(f) { this.uploadsMax = f; },
		getUploadsMax: function() { return this.uploadsMax; },
		
		/**
		*   setFileSizeMax / getFileSizeMax
		*
		*   Sets / Returns the upload max value
		*/
		setFileSizeMax: function(f) { this.fileSizeMax = f; },
		getFileSizeMax: function() { return this.fileSizeMax; },
		
		/**
		*   setCrop / getCrop
		*
		*   Sets / Returns the crop bool
		*/
		setCrop: function(f) { this.crop = f; },
		getCrop: function() { return this.crop; },
		
		/**
		*   setResize / getResize
		*
		*   Sets / Returns the resize bool
		*/
		setResize: function(f) { this.resize = f; },
		getResize: function() { return this.resize; },
		
		/**
		*   setDirectory / getDirectory
		*
		*   Sets / Returns the directory
		*/
		setDirectory: function(f) { this.directory = f; },
		getDirectory: function() { return this.directory; },
		
		/**
		*   setUploadFolder / getUploadFolder
		*
		*   Sets / Returns the upload folder
		*/
		setUploadFolder: function(f) { this.uploadfolder = f; },
		getUploadFolder: function() { return this.uploadfolder; },
		
		/**
		*   setUploadScript / getUploadScript
		*
		*   Sets / Returns the upload script
		*/
		setUploadScript: function(f) { this.uploadscript = f; },
		getUploadScript: function() { return this.uploadscript; },
		
		/**
		*   setReturnScript / getReturnScript
		*
		*   Sets / Returns the return script
		*/
		setReturnScript: function(f) { this.returnscript = f; },
		getReturnScript: function() { return this.returnscript; },
		
		/**
		*   setTypes / getTypes
		*
		*   Sets / Returns the file types
		*/
		setTypes: function(f) { this.types = f; },
		getTypes: function() { return this.types; },
		
		/**
		*   setUserId / getUserId
		*
		*   Sets / Returns the target user id
		*/
		setUserId: function(f) { this.userId = f; },
		getUserId: function() { return this.userId; },
		
		/**
		*   setXML / getXML
		*
		*   Sets / Returns the target xml
		*/
		setXML: function(f) { this.xml = f; },
		getXML: function() { return this.xml; },
		
		/**
		*   setFlashVars / getFlashVars
		*
		*   Sets / Returns the flash vars object
		*/
		setFlashVars: function(f) { this.flashvars = f; },
		getFlashVars: function() { return this.flashvars; },
		
		/**
		*   setParams / getParams
		*
		*   Sets / Returns the flash params
		*/
		setParams: function(f) { this.params = f; },
		getParams: function() { return this.params; },
		
		/**
		*   setAttributes / getAttributes
		*
		*   Sets / Returns the flash attributes
		*/
		setAttributes: function(f) { this.attributes = f; },
		getAttributes: function() { return this.attributes; },
		
		/**
		*   addCropCommand
		*
		*   Adds a new crop command
		*
		*	@param	f - format
		*	@param	w - width
		*	@param	h - height
		*	@param	d - directory
		*/
		addCropCommand: function(f, w, h, d) 
		{
			//alert( "adding crop command : " + f );
			//alert( "adding crop command : " + w );
			//alert( "adding crop command : " + h );
			//alert( "adding crop command : " + d );
			
			if ( f == "" || f == null || f == undefined ) {
				alert( "WARNING : No crop format passed" );
				return;
			} else if ( w == "" || w == null || w == undefined ) {
				alert( "WARNING : No crop width passed" );
				return;
			} else if ( h == "" || h == null || h == undefined ) {
				alert( "WARNING : No crop height passed" );
				return;
			} else if ( d == "" || d == null || d == undefined ) {
				alert( "WARNING : No crop folder passed" );
				return;
			}
			
			this.flashvars[ "crop_format_"+this.crops ] = f;
			this.flashvars[ "crop_width_"+this.crops ] = w;
			this.flashvars[ "crop_height_"+this.crops ] = h;
			this.flashvars[ "crop_folder_"+this.crops ] = d;
			
			this.crops++;
		},
		
		/**
		*   addResizeCommand
		*
		*   Adds a new resize command
		*
		*	@param	f - format
		*	@param	d - dimension
		*	@param	s - directory
		*/
		addResizeCommand: function(f, d, s) 
		{ 
			if ( f == "" || f == null || f == undefined ) {
				alert( "WARNING : No resize format passed" );
				return;
			} else if ( d == "" || d == null || d == undefined ) {
				alert( "WARNING : No resize dimension passed" );
				return;
			} else if ( s == "" || s == null || s == undefined ) {
				alert( "WARNING : No resize folder passed" );
				return;
			}
			
			this.flashvars[ "resize_format_"+this.resizes ] = f;
			this.flashvars[ "resize_dimension_"+this.resizes ] = d;
			this.flashvars[ "resize_folder_"+this.resizes ] = s;
			
			this.resizes++;
		},
		
		/**
		*   addCustomVar
		*
		*   Adds a custom variable to the flash vars object
		*
		*	@param	a - attribute
		*	@param	v - value
		*/
		addCustomVar: function(a, v) 
		{
			//alert( "adding custom var : " + a + " : " + v );
			
			if ( a == "" || a == null || a == undefined ) {
				alert( "WARNING : No custom attribute passed" );
				return;
			} else if ( v == "" || v == null || v == undefined ) {
				alert( "WARNING : No custom value passed" );
				return;
			}
			
			this.flashvars[ a ] = v;
		}
	}
);

/**
*	ActionDropDown
*/
var ActionDropDown = AbstractForm.extend(
	{
		/**
		*   init
		*
		*   Constructs the action input
		*
		*	@param	f - form data object
		*	@param	h - holder instance
		*	@param	l - label
		*	@param	o - items array
		*	@param	c - class
		*/
		init: function(f, h, l, o, c)
		{
			this._super( "ActionDropDown", f, h );
			
			// define props
			this.label = ( l == null || l == undefined ) ? "" : l;
			this.items = ( o == null || o == undefined ) ? new Array() : o;
			this.cssClass = ( c == null || c == undefined ) ? "" : c;
			this.button = null;
			this.dropdown = null;
			
			// build
			this.build();
		},
		
		/**
		*   build
		*
		*   Builds the form
		*/
		build: function()
		{
			//alert( "building : " + this.getHolder() );
			
			var obj = this;
			
			// call super first
			// build the form
			this._super();
			
			// create button
			this.button = $(document.createElement('a'));
			$( this.button ).addClass( "a_lozenge_btn_feb20e_60x22" );
			$( this.button ).attr( "href", "javascript: void();" );
			$( this.button ).append( '<div class="label">' + this.getLabel() + '</div>' );
			$( this.getForm() ).append( this.button );
			//$( this.button ).click( function() { obj.onButtonRelease(); } );
			
			// create drop down holder
			var ddh = $(document.createElement('div'));
				$( ddh ).css( { "float" : "right" } );
			$( this.getForm() ).append( ddh );
			
			// @@ create dropdown
			this.dropdown = new AbstractDropDown( "ActionDropDown", ddh );
			this.dropdown.setup( this.getName()+"_dropdown", null, this.getClass() );
			
			if ( this.formData.getCallback() != null ) {
			// if a callback has been requested
				$( this.button ).click( function() { 
					obj.formData.callBack.scope[obj.formData.callBack.call]( obj.dropdown.getValue() );
					return false;
				});
			}
		},
		
		/**
		*   loadItems
		*
		*   Loads the options into the drop down
		*/
		loadItems: function()
		{
			//alert( "loading items : " + this.getName() + " : " + this.dropdown );
			
			if ( this.dropdown == null )
				return;
			
			this.dropdown.loadItems();
		},
		
		/**
		*   clearItems
		*
		*   Clears the options from the dropdown
		*/
		clearItems: function()
		{
			//alert( "clearing items : " + this.getName() );
			
			if ( this.dropdown == null )
				return;
			
			this.dropdown.clearItems();
		},
		
		/**
		*   addItem
		*
		*   Adds an item to the dropdown
		*
		*	@param	o - item object
		*/
		addItem: function(o)
		{
			//alert( "adding item : " + this.getName() );
			
			if ( this.dropdown == null )
				return;
				
			this.dropdown.addItem( o );
		},
		
		/**
		*   setItems / getItems
		*
		*   Sets / Returns the items array
		*/
		setItems: function(s) { this.items = s; },
		getItems: function() { return this.items; },
		
		/**
		*   setClass / getClass
		*
		*   Sets / Returns the dd class
		*/
		setClass: function(s) { this.cssClass = s; },
		getClass: function() { return this.cssClass; },
		
		/**
		*   setLabel / getLabel
		*
		*   Sets / Returns the label prop
		*/
		setLabel: function(s) { this.label = s; },
		getLabel: function() { return this.label; }
	}
);

/**
*	ActionInputPassword
*/
var ActionInputPassword = AbstractForm.extend(
	{
		/**
		*   init
		*
		*   Constructs the action input
		*
		*	@param	fdata - form data object
		*	@param	holder - container
		*	@param	label - label
		*	@param	value - value
		*	@param	cta - call to action
		*/
		init: function(fdata, holder, label, value, cta)
		{
			this._super( "ActionInputPassword", fdata );
			
			// define statics
			this.STATE_OPEN = "stateOpen";
			this.STATE_CLOSED = "stateClosed";
			
			this.holder = holder;
			this.label = label;
			this.value = value;
			this.cta = cta;
			this.name = fdata.name;
			this.currentState = null;
			
			this.build();
		},
		
		/**
		*   build
		*
		*   Builds the form
		*/
		build: function()
		{
			//alert( "building : " );
			
			var obj = this;
			
			// call super
			// build the form
			this._super();
			
			// append class to form
			$( this.form ).addClass( 'action_frm' );
			
			// left section
			var fl = $(document.createElement( 'div' )).addClass( 'frm_left' ).attr( 'name', this.name+'_action_label' ).append( this.label ).addClass( 'bc_11_fea70f_b' );
			$( this.form ).append( fl );
			
			// right section
			var al = $(document.createElement( 'div' )).addClass( 'label' ).attr( 'name', this.name+'_action_prompt' ).append( this.cta );
			this.button = $(document.createElement( 'a' )).addClass( 'action_frm_btn' ).attr( 'href', 'javascript:void();' ).append( al );
			$( this.button ).click( function() {
				//alert( "button clicked" );
				// switch based upon whether the form is open or closed
				switch ( obj.currentState )
				{
					// @@ case - form is closed
					case obj.STATE_CLOSED:
					
						// open the form
						obj.openForm();
					
						break;
					// @@ case - form is open
					case obj.STATE_OPEN:
					
						// submit the form and then close immediately
						obj.broadcast( "ActionFormSubmitted", { 
							val1: $( "input[name=frm_action_password_input1]" ).val(),
							val2: $( "input[name=frm_action_password_input2]" ).val()
						});
						obj.closeForm();
					
						break;
				}
				return false;
			});
			var fr = $(document.createElement( 'div' )).addClass( 'frm_right' ).append( this.button );
			$( this.form ).append( fr );
			
			// mid section
			
			// @@ output
			this.output = $(document.createElement( 'div' )).addClass( 'frm_middle' ).attr( 'name', this.name+'_action_output' ).append( 
				this.value 
			);
			$( this.form ).append( this.output );
			
			// @@ inputs 1 & 2
			
			// @@ 1
			var iPw1 = new InputData();
			iPw1.setName( "frm_action_password_input1" );
			iPw1.setType( "password" );
			iPw1.setSize( 15 );
			iPw1.setValue( this.value );
			iPw1.setClass( "input_w_100_h_18 input_standard" );
			var iCont1 = $(document.createElement( 'div' )).addClass( 'input' ).append( this.getInput( iPw1 ) );
			
			// @@ 2
			var iPw2 = new InputData();
			iPw2.setName( "frm_action_password_input2" );
			iPw2.setType( "password" );
			iPw2.setSize( 15 );
			iPw2.setValue( this.value );
			iPw2.setClass( "input_w_100_h_18 input_standard" );
			var iCont2 = $(document.createElement( 'div' )).addClass( 'input' ).append( this.getInput( iPw2 ) );
			
			// @@ prompt
			var iCont3 = $(document.createElement( 'div' )).addClass( 'prompt' ).append( '( Confirm password )' );
			
			// add all to input
			this.input = $(document.createElement( 'div' )).addClass( 'frm_middle' ).attr( 'name', this.name+'_action_input' );
			
			$( this.input ).append( iCont1 );
			$( this.input ).append( iCont2 );
			$( this.input ).append( iCont3 );
			$( this.form ).append( this.input );
			
			// close as default
			this.closeForm();
		},
		
		/**
		*   checkData
		*
		*   Checks the password data before posting to back end
		*/
		checkData: function()
		{
			var p1 = $(document.getElementsByName( 'frm_action_password_input1' ));
			var p2 = $(document.getElementsByName( 'frm_action_password_input2' ));
			
			alert( "checking : " + $( p1 ).val() + " & " + $( p2 ).val() );
			
			this.closeForm();
			
			if ( $( p1 ).val() == this.value || $( p2 ).val() == this.value ) {
				alert( "Please enter a valid password" );
				//this.closeForm();
				return false;
			} else if ( $( p1 ).val() != $( p2 ).val() ) {
				alert( "Please check that your passwords match" );
				//this.closeForm();
				return false;
			} else {
				//submitForm();
			}
		},
		
		/**
		*   setOutput
		*
		*   Sets the output
		*
		*	@param	v - value to set with
		*/
		setOutput: function(v)
		{
			$( this.output ).html( v );
		},
		
		/**
		*   getOutput
		*
		*   Returns the output
		*/
		getOutput: function()
		{
			return $( this.output + " > div.output" ).html();
		},
		
		/**
		*   openForm
		*
		*   Opens up the action form element
		*/
		openForm: function()
		{
			//alert( "opening : " + this.name );
			
			var obj = this;
			
			// register as open
			this.currentState = this.STATE_OPEN;
			
			// set the button label
			var bl = $(document.getElementsByName( this.name+'_action_prompt' ));
			$( bl ).text( "Submit" );
			
			// toggle mid section
			$( this.output ).hide();
			$( this.input ).show();
		},
		
		/**
		*   closeForm
		*
		*   Closes the form
		*/
		closeForm: function()
		{
			//alert( "closing : " + this.name );
			
			var obj = this;
			
			// register as closed
			this.currentState = this.STATE_CLOSED;
			
			// set the button label
			var bl = $(document.getElementsByName( this.name+'_action_prompt' ));
			$( bl ).text( this.cta );
			
			// toggle mid section
			$( this.output ).show();
			$( this.input ).hide();
		}
	}
);

/**
*	ActionInputStandard
*/
var ActionInputStandard = AbstractForm.extend(
	{
		/**
		*   init
		*
		*   Constructs the action input
		*
		*	@param	fdata - form data object
		*	@param	idata - input data object
		*	@param	holder - container
		*	@param	label - label
		*	@param	value - value
		*	@param	cta - call to action
		*/
		init: function(fdata, idata, holder, label, value, cta)
		{
			this._super( "ActionInputStandard", fdata );
			
			// define statics
			this.STATE_OPEN = "stateOpen";
			this.STATE_CLOSED = "stateClosed";
			
			// define private vars
			this.holder = holder;
			this.label = label;
			this.value = value;
			this.cta = cta;
			this.idata = idata;
			this.name = fdata.name;
			this.currentState = null;
			
			this.build();
		},
		
		/**
		*   build
		*
		*   Builds the form
		*/
		build: function()
		{
			//alert( "building : " );
			
			// define the class object
			var obj = this;
			
			// call super
			// build the form
			this._super();
			
			// append class to form
			$( this.form ).addClass( 'action_frm' );
			
			// left section
			var fl = $(document.createElement( 'div' )).addClass( 'frm_left' ).attr( 'name', this.name+'_action_label' ).append( this.label ).addClass( 'bc_11_fea70f_b' );
			$( this.form ).append( fl );
			
			// right section
			var al = $(document.createElement( 'div' )).addClass( 'label' ).attr( 'name', this.name+'_action_prompt' ).append( this.cta );
			this.button = $(document.createElement( 'a' )).addClass( 'action_frm_btn' ).attr( 'href', 'javascript:void();' ).append( al );
			$( this.button ).click( function() {
				//alert( "button clicked" );
				// switch based upon whether the form is open or closed
				switch ( obj.currentState )
				{
					// @@ case - form is closed
					case obj.STATE_CLOSED:
					
						// open the form
						obj.openForm();
					
						break;
					// @@ case - form is open
					case obj.STATE_OPEN:
					
						// submit the form and then close immediately
						obj.broadcast( "ActionFormSubmitted", { 
							val: $( "input[name="+ obj.idata.getName() +"]" ).val()
						});
						obj.closeForm();
					
						break;
				}
				return false;
			});
			var fr = $(document.createElement( 'div' )).addClass( 'frm_right' ).append( this.button );
			$( this.form ).append( fr );
			
			// mid section
			
			// @@ output
			this.output = $(document.createElement( 'div' )).addClass( 'frm_middle' ).attr( 'name', this.name+'_action_output' ).append( 
				this.value 
			);
			$( this.form ).append( this.output );
			
			// @@ input
			this.input = $(document.createElement( 'div' )).addClass( 'frm_middle' ).attr( 'name', this.name+'_action_input' ).append( 
				this.getInput( this.idata ) 
			);
			$( this.form ).append( this.input );
			
			// close as default
			this.closeForm();
		},
		
		/**
		*   setOutput
		*
		*   Sets the output
		*
		*	@param	v - value to set with
		*/
		setOutput: function(v)
		{
			$( this.output ).html( v );
		},
		
		/**
		*   getOutput
		*
		*   Returns the output
		*/
		getOutput: function()
		{
			return $( this.output + " > div.output" ).html();
		},
		
		/**
		*   openForm
		*
		*   Opens up the action form element
		*/
		openForm: function()
		{
			//alert( "opening : " + this.name );
			
			var obj = this;
			
			// register as open
			this.currentState = this.STATE_OPEN;
			
			// set the button label
			var bl = $(document.getElementsByName( this.name+'_action_prompt' ));
			$( bl ).text( "Submit" );
			
			// toggle mid section
			$( this.output ).hide();
			$( this.input ).show();
		},
		
		/**
		*   closeForm
		*
		*   Closes the form
		*/
		closeForm: function()
		{
			//alert( "closing : " + this.name );
			
			var obj = this;
			
			// register as closed
			this.currentState = this.STATE_CLOSED;
			
			// set the button label
			var bl = $(document.getElementsByName( this.name+'_action_prompt' ));
			$( bl ).text( this.cta );
			
			// toggle mid section
			$( this.output ).show();
			$( this.input ).hide();
		}
	}
);

/**
*	ActionInputBasic
*/
var ActionInputBasic = AbstractForm.extend(
	{
		/**
		*   init
		*
		*   Constructs the action input
		*
		*	@param	fd - form data object
		*	@param	id - input data object
		*	@param	h - container
		*	@param	l - label
		*/
		init: function(fd, id, h, l)
		{
			this._super( "ActionInputBasic", fd );
			
			//alert( this.getType() + " initiating" );
			
			this.holder = h;
			this.idata = id;
			this.label = ( l == null || l == undefined ) ? "" : l;
			
			this.build();
		},
		
		/**
		*   build
		*
		*   Builds the form
		*/
		build: function()
		{
			//alert( this.getType() + " building" );
			
			var obj = this;
			
			// call super
			// build the form
			this._super();
			
			// @@ button
			var b = $(document.createElement('a'));
				$( b ).addClass( "a_lozenge_btn_feb20e_60x22" );
				$( b ).attr( "href", "javascript: void();" );
				$( b ).append( '<div class="label">' + this.getLabel() + '</div>' );
				$(b).bind( 'click', null, function(evt) {
					obj.broadcast( "onFormSubmitted", { value: $("input[name="+obj.idata.getName()+"]").val() } );
					return false;
				});
				
			//var bh = $(document.createElement('div'));
				//$( bh ).css( { "float" : "right" } );
				//$( bh ).append( b );
			
			//$( this.getForm() ).append( bh );/**/
			
			$( this.getForm() ).append( b );
			
			// @@ input
			var i = this.getInput( this.idata );
			var ih = $(document.createElement('div'));
				$( ih ).css( { "float" : "right" } );
				$( ih ).append( i );
				
			$( this.getForm() ).append( ih );
		},
		
		/**
		*   setLabel / getLabel
		*
		*   Sets / Returns the label prop
		*/
		setLabel: function(s) { this.label = s; },
		getLabel: function() { return this.label; }
	}
);

/**
*	SearchAlphabetForm
*/
var SearchAlphabetForm = AbstractForm.extend(
	{
		/**
		*   init
		*
		*   Constructs the action input
		*
		*	@param	f - form data object
		*	@param	h - holder instance
		*	@param	l - label
		*/
		init: function(f, h, l)
		{
			this._super( "SearchAlphabetForm", f, h );
			
			//alert( "initiating..." );
			
			// define props
			this.label = ( l == null || l == undefined ) ? "" : l;
			this.buttons = new Array();
			this.items = [
				{ label: "A", data: 1 },
				{ label: "B", data: 2 },
				{ label: "C", data: 3 },
				{ label: "D", data: 4 },
				{ label: "E", data: 5 },
				{ label: "F", data: 6 },
				{ label: "G", data: 7 },
				{ label: "H", data: 8 },
				{ label: "I", data: 9 },
				{ label: "J", data: 10 },
				{ label: "K", data: 11 },
				{ label: "L", data: 12 },
				{ label: "M", data: 13 },
				{ label: "N", data: 14 },
				{ label: "O", data: 15 },
				{ label: "P", data: 16 },
				{ label: "Q", data: 17 },
				{ label: "R", data: 18 },
				{ label: "S", data: 19 },
				{ label: "T", data: 20 },
				{ label: "U", data: 21 },
				{ label: "V", data: 22 },
				{ label: "W", data: 23 },
				{ label: "X", data: 24 },
				{ label: "Y", data: 25 },
				{ label: "Z", data: 26 }
			];
			this.selectedButton = null;
			this.selectedItem = null;
			
			// build
			this.build();
		},
		
		/**
		*   build
		*
		*   Builds the form
		*/
		build: function()
		{
			//alert( "building : " + this.getHolder() );
			
			var obj = this;
			
			// call super first
			// build the form
			this._super();
			
			// @@ button
			var b = $(document.createElement('a'));
				$( b ).addClass( "a_lozenge_btn_feb20e_60x22" );
				$( b ).attr( "href", "javascript: void();" );
				$( b ).append( '<div class="label">' + this.getLabel() + '</div>' );
				$( b ).bind( 'click', null, function(evt) {
					if ( obj.selectedItem != null )
						obj.broadcast( "onFormSubmitted", obj.selectedItem );
					return false;
				});
			$( this.getForm() ).append( b );
			
			// create the alphabet list holder
			var ah = $(document.createElement('div'));
				$( ah ).css( { "float" : "right" } );
			$( this.getForm() ).append( ah );
			
			// @@ alphabet list
			for ( i=0; i<this.items.length; i++ )
			{
				// create item button
				var a = $(document.createElement( 'a' )).addClass( 'a_ffffff_b_r_11' ).attr( 'href', 'javascript: void();' ).append( this.items[i].label );
					$( a ).bind( 'click', this.items[i], function(evt) {
						obj.selectItem( evt.data );
						return false;
					});
				$( ah ).append( a );
				
				this.buttons[ this.items[i].data ] = a;

				// add spacer
				if ( i != this.items.length-1 )
					$( ah ).append( "&nbsp;" );
			}
		},
		
		/**
		*   selectItem
		*
		*   Selects an item
		*
		*	@param	i - item data object
		*/
		selectItem: function(i)
		{
			//alert( "selecting item : " + i.data + " : " + i.label );
			
			// remove the currently selected ( if there is one )
			if ( this.selectedButton != null ) {
				$( this.selectedButton ).removeClass( 'a_ffffff_b_r_11_selected' );
				$( this.selectedButton ).addClass( 'a_ffffff_b_r_11' );
			}
			
			// register as selected
			this.selectedButton = this.buttons[ i.data ];
			$( this.selectedButton ).removeClass( 'a_ffffff_b_r_11' );
			$( this.selectedButton ).addClass( 'a_ffffff_b_r_11_selected' );
			
			// register the new selected item
			this.selectedItem = i;
		},
		
		/**
		*   setLabel / getLabel
		*
		*   Sets / Returns the label prop
		*/
		setLabel: function(s) { this.label = s; },
		getLabel: function() { return this.label; }
	}
);