/**
*	Class.extend
*
*	Extension class that allows for MVC class patterns
*/
// Inspired by base2 and Prototype
(function(){
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

  // The base Class implementation (does nothing)
  this.Class = function(){};
 
  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;
   
    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;
   
    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;
           
            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];
           
            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);       
            this._super = tmp;
           
            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }
   
    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }
   
    // Populate our constructed prototype object
    Class.prototype = prototype;
   
    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;
   
    return Class;
  };
})();

/**
*	AbstractObject
*
*	@param	t - type string
*/
var AbstractObject = Class.extend(
	{
		init: function(t)
		{
			this.type = t;
			this.doc = new Document();
		},
		
		getType: function()
		{
			return this.type;
		},
		
		includeScript: function(s)
		{
			this.doc.includeScript(s); 	
		},
		
		/**
		*   broadcast
		*
		*   Broadcasts an event object
		*
		*	@param	t - event type
		*	@param	d - event data
		*/
		broadcast: function(t, d)
		{
			//alert( $( this ) + " firing event " + t + " containing : " + d );
			
			$( this ).trigger( t, d ); 
		}
	}
);

/**
*	AbstractModel
*
*	@param	t - type string
*	@param	p - application prefix
*/
var AbstractModel = AbstractObject.extend(
	{
		init: function(t, p)
		{
			this._super( t );
			
			// define props
			this.prefix = p;
		},
		
		/**
		*   getPrefix
		*
		*   Returns the application prefix
		*/
		getPrefix: function()
		{
			return this.prefix;
		}
	}
);

/**
*	AbstractControl
*
*	@param	t - type string
*	@param	c - model instance
*/
var AbstractControl = AbstractObject.extend(
	{
		init: function(t, c)
		{
			this._super( t );
			
			// set props
			this.core = c;
		},
		
		/**
		*   getCore
		*
		*   Returns the application model instance
		*/
		getCore: function()
		{
			return this.core;
		}
	}
);

/**
*	AbstractView
*
*	@param	t - type string
*	@param	m - manager instance
*	@param	h - view holder instance
*/
var AbstractView = AbstractObject.extend(
	{
		init: function(t, m, h)
		{
			this._super( t );
			
			// define props
			this.manager = m;
			this.holder = h;
			this.elements = new Object();
		},
		
		/**
		*   getManager
		*
		*   Returns the views manager instance
		*/
		setManager: function(e) { this.manager = e; },
		getManager: function() { return this.manager; },
		
		/**
		*   getHolder
		*
		*   Returns the views holder instance
		*/
		setHolder: function(e) { this.holder = e; },
		getHolder: function() { return this.holder; },
		
		/**
		*   getElements
		*
		*   Returns the main display element
		*/
		setElements: function(e) { this.elements = e; },
		getElements: function() { return this.elements; },
		
		/**
		*   addElement / getElement / removeElement
		*
		*   Adds an element to the view elements array
		*
		*	@param	id - element id
		*	@param	e - element
		*/
		addElement: function(id, e) 
		{ 
			this.elements[id] = e;
		},
		
		getElement: function(id) 
		{ 
			return this.elements[id];
		},
		
		removeElement: function(id) 
		{ 
			$( this.elements[id] ).remove();
			delete this.elements[id];
		},
		
		/**
		*   flush
		*
		*   Flushes a view of all its elements
		*
		*	@param	e - element to flush
		*/
		flush: function(e) 
		{ 
			for ( var i in e.elements )
			{
				$( e.elements[i] ).remove();
				delete e.elements[i];
			}
		},
		
		/**
		*   buildCallbackString
		*
		*   Builds a callback function based upon the contents of a callback object
		*
		*	@param	c - callback object
		*/
		buildCallbackString: function(c) 
		{
			// open a callback string
			callback = c.scope + '.' + c.call + '( ';
												  
			// loop through args and compile accordingly
			if ( c.args != null ) {
			// if there have been arguments set
				for ( i=0; i<c.args.length; i++ )
				{
					switch ( c.args[i].dataType )
					{
						// @@ case - string - callback data is typed string
						case "string":
						
							callback += '\'' + c.args[i].arg + '\'';
						
							break;
							
						// @@ case - number - callback data is typed number
						case "number":
						
							callback += c.args[i].arg;
						
							break;
					}
					
					if ( i != c.args.length-1 )
						callback += ', ';
				}
			}
			
			// finish string
			callback += ' );';
			
			// ...and return
			return callback;
		},
		
		/**
		*   executeCallback
		*
		*   Executes a callback function based upon the contents of a callback object
		*
		*	@param	c - callback object
		*/
		executeCallback: function(c) 
		{
			// TODO : Function to execute callbacks
			// NOTE : See : ActionDropDown form class
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*/
		setup: function()
		{
			// sets up the view
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			// builds the view
		},
		
		/**
		*   update
		*
		*   Updates the view
		*
		*	@param	t - event type
		*	@param	d - data
		*/
		update: function(t, d)
		{
			// updates the view
		}
	}
);

/**
*	AbstractManager
*
*	@param	t - type string
*	@param	c - model instance
*/
var AbstractManager = AbstractObject.extend(
	{
		init: function(t, c)
		{
			this._super( t );
			
			// set props
			this.core = c;
			this.controls = new Object();
		},
		
		/**
		*   getCore
		*
		*   Returns the application model instance
		*/
		getCore: function()
		{
			return this.core;
		},
		
		/**
		*   setControls
		*
		*   Sets the manager controls array
		*
		*	@param	c - controls array
		*/
		setControls: function(c)
		{
			this.controls = c;
		},
		
		/**
		*   addControl / getControl
		*
		*   Adds / Returns a control instance
		*
		*	@param	id - control id
		*	@param	c - control instance
		*/
		addControl: function(id, c)
		{
			this.controls[id] = c;
		},
		getControl: function(id)
		{
			return this.controls[id];
		}
	}
);

/**
*	AbstractButton
*
*	@param	t - type string
*/
var AbstractButton = AbstractView.extend(
	{
		/**
		*   init
		*
		*   Constructs the button view
		*
		*	@param	t - button type
		*	@param	m - manager instance
		*	@param	h - holder instance
		*/
		init: function(t, m, h)
		{
			this._super( t, m, h );
			
			// define props
			this.buttonData = null;
			this.button = null;
			this.buttonAnchor = null;
		},
		
		/**
		*   setup
		*
		*   Sets up the view
		*
		*	@param	d - button data object
		*/
		setup: function(d)
		{
			//alert( "setting up" );
			
			// register button data
			this.buttonData = d;
			
			// then build
			this.build();
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building" );
		},
		
		/**
		*   enableButton / disableButton
		*
		*   Enables / disables the button
		*/
		enable: function()
		{
			if ( !this.button )
				alert( "WARNING : This button has not been registered" );
				
			// dispatch events
			var obj = this;
			$( this.button ).mouseover( function() { 
				obj.onButtonRollOver();
				return false;
			});
			$( this.button ).mouseout( function() { 
				obj.onButtonRollOut(); 
				return false;
			});
			$( this.button ).click( function() { 
				obj.onButtonRelease();
				return false;
			});
		},
		
		disable: function()
		{
			if ( !this.button )
				alert( "WARNING : This button has not been registered" );
				
			// dispatch events
			var obj = this;
			$( this.button ).mouseover( function() { return false; } );
			$( this.button ).mouseout( function() { return false; } );
			$( this.button ).click( function() { return false; } );
		},
		
		/**
		*   onButtonRollOver / onButtonRollOut / onButtonReleased
		*
		*   Called upon roll over of button
		*/
		onButtonRollOver: function()
		{
			this.broadcast( "onButtonRolledOver", this.buttonData );
		},
		
		onButtonRollOut: function()
		{
			this.broadcast( "onButtonRolledOut", this.buttonData );
		},
		
		onButtonRelease: function()
		{
			this.broadcast( "onButtonReleased", this.buttonData );
		},
		
		/**
		*   setButtonData / getButtonData
		*
		*   Sets / Returns the buttons data object
		*/
		setButtonData: function(e) { this.buttonData = e; },
		getButtonData: function() { return this.buttonData; },
		
		/**
		*   setButton / getButton
		*
		*   Sets / Returns the button instance
		*/
		setButton: function(e) { this.button = e; },
		getButton: function() { return this.button; },
		
		/**
		*   setButtonAnchor / getButtonAnchor
		*
		*   Sets / Returns the button anchor instance
		*/
		setButtonAnchor: function(e) { this.buttonAnchor = e; },
		getButtonAnchor: function() { return this.buttonAnchor; }
	}
);

/**
*	ButtonData
*/
var ButtonData = AbstractObject.extend(
	{
		/**
		*   init
		*
		*   Constructs the button dat6a object
		*/
		init: function()
		{
			this._super( "ButtonData" );
			
			// @@ define props
			this.buttonId = "";
			this.label = "";
			this.alternateText = "";
			this.active = false;
			this.href = "";
			this.sublinks = new Array();
			this.arguments = null;
		},
		
		/**
		*   setButtonId / getButtonId
		*
		*   Sets / Returns the button id
		*/
		setButtonId: function(s) { this.buttonId = s; },
		getButtonId: function() { return this.buttonId; },
		
		/**
		*   setLabel / getLabel
		*
		*   Sets / Returns the button label
		*/
		setLabel: function(s) { this.label = s; },
		getLabel: function() { return this.label; },
		
		/**
		*   setAlternateText / getAlternateText
		*
		*   Sets / Returns the button alternate text
		*/
		setAlternateText: function(s) { this.alternateText = s; },
		getAlternateText: function() { return this.alternateText; },
		
		/**
		*   setActive / getActive
		*
		*   Sets / Returns the button active boolean
		*/
		setActive: function(s) { this.active = s; },
		getActive: function() { return this.active; },
		
		/**
		*   setHref / getHref
		*
		*   Sets / Returns the button href
		*/
		setHref: function(s) { this.href = s; },
		getHref: function() { return this.href; },
		
		/**
		*   setSublinks / getSublinks
		*
		*   Sets / Returns the button sublinks
		*/
		setSublinks: function(s) { this.sublinks = s; },
		getSublinks: function() { return this.sublinks; },
		
		/**
		*   setArguments / getArguments
		*
		*   Sets / Returns the button arguments data object
		*/
		setArguments: function(s) { this.arguments = s; },
		getArguments: function() { return this.arguments; }
	}
);

/**
*	AbstractEvent
*
*	@param	t - type string
*	@param	e - event type string
*	@param	d - data object
*/
var AbstractEvent = AbstractObject.extend(
	{
		init: function(t, e, d)
		{
			this._super( t );
			
			// set props
			this.eventType = e;
			this.data = d;
		},
		
		/**
		*   setEventType / getEventType
		*
		*   Sets / Returns the event type sring
		*/
		setData: function(d) { this.eventType = d; },
		getData: function() { return this.eventType; },
		
		/**
		*   setData / getData
		*
		*   Sets / Returns the event data object
		*/
		setData: function(d) { this.data = d; },
		getData: function() { return this.data; }
	}
);

/**
*	AbstractTab
*/
var AbstractTab = AbstractButton.extend(
	{
		/**
		*   init
		*
		*   Constructs the button view
		*
		*	@param	t - button type
		*	@param	m - manager instance
		*	@param	h - holder instance
		*/
		init: function(t, m, h)
		{
			this._super( t, m, h );
			
			// define props
			this.selected = false;
		},
		
		/**
		*   setup
		*
		*   Sets up the view
		*
		*	@param	d - button data object
		*/
		setup: function(d)
		{
			//alert( "setting up" );
			
			this._super( d );
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building" );
			
			this._super();
		},
		
		/**
		*   enableButton / disableButton
		*
		*   Enables / disables the button
		*/
		enable: function()
		{
			// call to super
			this._super();
		},
		
		disable: function()
		{
			this._super();
		},
		
		/**
		*   onButtonRollOver / onButtonRollOut / onButtonReleased
		*
		*   Called upon roll over of button
		*/
		onButtonRollOver: function()
		{
			this._super();
		},
		
		onButtonRollOut: function()
		{
			this._super();
		},
		
		onButtonRelease: function()
		{
			this._super();
		},
		
		/**
		*   selectTab / deSelectTab
		*
		*   Selects / De-selects the tab
		*/
		selectTab: function()
		{
			//alert( "selecting tab" );
			
			this.selected = true;
			
			// broadcast event
			this.broadcast( "onTabSelected", this.buttonData );
		},
		
		deSelectTab: function()
		{
			//alert( "de-selecting tab" );
			
			this.selected = false;
			
			// broadcast event
			this.broadcast( "onTabDeselected", this.buttonData );
		}
	}
);

/**
*	TabData
*/
var TabData = ButtonData.extend(
	{
		/**
		*   init
		*
		*   Constructs the button dat6a object
		*/
		init: function()
		{
			this._super();
		}
	}
);

/**
*	AbstractForm
*
*	@param	t - type string
*	@param	f - form data object
*	@param	h - holder instance
*/
var AbstractForm = AbstractView.extend(
	{
		init: function(t, f, h)
		{
			this._super( t, null, h );
			
			if ( f == null || f == undefined ) alert( t + "WARNING : No form data object defined" );
			
			// define all props
			this.setFormData( f );
			this.inputs = [];
			this.form = null;
			this.delay = null;
		},
		
		/**
		*   submitForm
		*
		*   Submits the form
		*/
		submitForm: function()
		{
			//alert( "submitting form : " + this.formData.getName() );
			
			var form = $( "#" + this.formData.getName() + "_id" );
				form.submit();
		},
		
		/**
		*	textCounter
		*	
		*	Counts the remeining text in a passed text area
		*
		*	@param	f - field
		*	@param	cf - count field
		*	@param	mx - max limit
		*/
		textCounter: function( f, cf, mx ) 
		{
			// check if length has reached max
			if ( f.value.length > mx )
			{
				f.value = f.value.substring( 0, mx );
				alert( 'Sorry! You cannot enter more than ' + mx + 'characters in your biography' );
				return false;
			} else {
				// display the count
				cf.value = mx - f.value.length;
			}
		},
		
		/*
		*	build
		*
		*   Builds the form
		*/
		build: function()
		{
			this.form = $(document.createElement('form'));
			$( this.form ).attr( 'id', this.formData.getName() + "_id" );
			$( this.form ).attr( 'name', this.formData.getName() );
			$( this.form ).attr( 'action', this.formData.getAction() );
			$( this.form ).attr( 'method', this.formData.getMethod() );
			
			// create the hidden submit field
			var hid = new InputData();
				hid.setName( this.formData.getName() + "_submit" );
				hid.setType( 'hidden' );
				hid.setValue( 1 );
			var s = this.getInput( hid );
			$( this.form ).append( s );
			
			// append to holder
			$( this.getHolder() ).append( this.form );
		},
		
		/*
		*	getInput
		*
		*	Returns a form input tag
		*
		*	@param	iData - input data object
		*/
		getInput: function(iData)
		{
			//alert( this.getType() + " getting input " + iData );
			
			if ( this.inputs[iData.name] != undefined ) 
				return this.inputs[iData.name];
			
			var el = $(document.createElement('input'));
			if ( iData.name != null ) 			$( el ).attr( 'name', iData.name );
			if ( iData.type != null ) 			$( el ).attr( 'type', iData.type );
			if ( iData.size != null ) 			$( el ).attr( 'size', iData.size );
			if ( iData.maxChars != null ) 		$( el ).attr( 'maxlength', iData.maxChars );
			if ( iData.value != null ) 			$( el ).attr( 'value', iData.value );
			if ( iData.cssClass != null ) 		$( el ).attr( 'class', iData.cssClass );
			
			return el;
		},
		
		/*
		*	getTextArea
		*
		*	Returns a text area
		*
		*	@param	props - array of properties to add - array [ { attribute: "", value: "" } ]
		*	@param	value - input value
		*/
		getTextArea: function(props, value)
		{
			var el = $(document.createElement('textarea'));
			for ( var i in props )
			{
				$( el ).attr( props[i].attribute, props[i].value );
			}
			$( el ).append( value );
			
			return el;
		},
		
		/*
		*	getDropDownMenu
		*
		*	Returns a drop down menu based on an array of props
		*
		*	@param	name - name string
		*	@param	value - value
		*	@param	options - array [ { label: "", value: "" } ]
		*/
		getDropDownMenu: function(name, value, opts)
		{
			var el = $(document.createElement('select'));
			$( el ).attr( 'id', name );
			$( el ).attr( 'name', name );
			$( el ).attr( 'size', '1' );
			
			for ( i=0; i<opts.length; i++ )
			{
				var opt = $(document.createElement('option')).append( opts[i].label );
				$( opt ).attr( 'value', opts[i].value );
				
				if ( opts[i].value == value ) 
					alert( "selecting : " + opts[i].value );
					//$( opt ).attr( 'selected' );
					
				$( el ).append( opt );
			}
			
			return el;
		},
		
		/*
		*	getCheckbox
		*
		*	Returns a check box
		*
		*	@param	prop - prop name string
		*	@param	value - value
		*	@param	selected - selected flag
		*/
		getCheckbox: function(prop, value, selected)
		{
			/*$checked = ( $selected == 1 ) ? 'checked' : '';
			
			return '<input name="' . $prop . '" type="checkbox" value="' . $value . '" ' . $checked . ' />';*/
		},
		
		/**
		*   setFormData / getFormData
		*
		*   Sets / Returns the form data object
		*/
		setFormData: function(s) { this.formData = s; },
		getFormData: function() { return this.formData; },
		
		/**
		*   getName
		*
		*   Returns the form data name
		*/
		getName: function() { return this.formData.getName(); },
		
		/**
		*   getAction
		*
		*   Returns the form data action
		*/
		getAction: function() { return this.formData.getAction(); },
		
		/**
		*   getForm
		*
		*   Returns the form instance
		*/
		getForm: function() { return this.form; }
	}
);

/**
*	AbstractDropDown
*
*	@param	t - types string
*	@param	h - holder instance
*/
var AbstractDropDown = AbstractView.extend(
	{
		init: function(t, h)
		{
			this._super( t, null, h );
			
			// define props
			this.name = "dropdown_default";
			this.items = new Array();
			this.cssClass = "class_default";
			this.size = 25;
		},
		
		/**
		*   setup
		*
		*   Sets up the component
		*
		*	@param	n - name string
		*	@param	a - items array
		*	@param	c - class string
		*/
		setup: function(n, a, c)
		{
			//alert( "setting up component : " + a );
			
			if ( n != null && n != undefined ) this.setName( n );
			if ( a != null && a != undefined ) this.setItems( a );
			if ( c != null && c != undefined ) this.setClass( c );
			
			// and build
			this.build();
		},
		
		/**
		*   build
		*
		*   Builds the component
		*/
		build: function()
		{
			//alert( "building component : " + this.items.length );
			
			// build the select menu
			var dd = $(document.createElement('select'));
			$( dd ).attr( 'id', this.getName() );
			$( dd ).attr( 'name', this.getName() );
			$( dd ).attr( 'size', '1' );
			$( dd ).attr( 'class', this.getClass() );
			$( this.getHolder() ).append( dd );
			
			if ( this.items.length != 0 )
				this.loadItems();
		},
		
		/**
		*   loadItems
		*
		*   Loads the options into the drop down
		*/
		loadItems: function()
		{
			//alert( "loading items : " + this.getName() + " : " + this.items.length );
			
			for ( j=0; j<this.items.length; j++ )
			{
				var opt = $(document.createElement('option')).append( this.items[j].label );
				$( opt ).attr( 'value', this.items[j].value );
				
				$( "select#"+this.getName() ).append( opt );
			}
		},
		
		/**
		*   clearItems
		*
		*   Clears the options from the dropdown
		*/
		clearItems: function()
		{
			// refresh array
			this.items = new Array();
			
			// clear the menu
			$( "select#"+this.getName() ).html( "" );
		},
		
		/**
		*   addItem
		*
		*   Adds an item to the dropdown
		*
		*	@param	o - item object
		*/
		addItem: function(o)
		{
			if ( this.items == null )
				this.items = new Array();
			
			// add to array
			this.items.push( o );
		},
		
		/**
		*   setItems / getItems
		*
		*   Sets / Returns the items array
		*/
		setItems: function(s) { this.items = s; },
		getItems: function() { return this.items; },
		
		/**
		*   setName / getName
		*
		*   Sets / Returns the name string
		*/
		setName: function(s) { this.name = s; },
		getName: function() { return this.name; },
		
		/**
		*   setClass / getClass
		*
		*   Sets / Returns the dd class
		*/
		setClass: function(s) { this.cssClass = s; },
		getClass: function() { return this.cssClass; },
		
		/**
		*   setSize / getSize
		*
		*   Sets / Returns the dd size
		*/
		setSize: function(s) { this.size = s; },
		getSize: function() { return this.size; },
		
		/**
		*   getValue
		*
		*   Returns the selected value
		*/
		getValue: function() 
		{
			if ( document.getElementById( this.getName() ).selectedIndex != -1 ) {
				return document.getElementById( this.getName() ).options[document.getElementById( this.getName() ).selectedIndex].value;
			} else {
				return 0;	
			}
		}
	}
);

/**
*   Class : FormData
*
*   Class holds all data necessary to esatblish a form element
*
*   @usage    Used by all form elements
*   @author   Daniel Ivanovic dan@substance001.com
*
*	@param	name - element name
*	@param	action - element action
*/
var FormData = AbstractObject.extend(
	{
		/**
		*   init
		*
		*   Constructs the button dat6a object
		*/
		init: function()
		{
			this._super( "FormData" );
			
			// @@ name
			this.name = 'default';
			// @@ action
			this.action = '_self';
			// @@ method
			this.method = 'post';
			// @@ submit callback 
			this.callBack = null;
		},
		
		/**
		*   setName / getName
		*
		*   Sets / Returns the form data name
		*/
		setName: function(s) { this.name = s; },
		getName: function() { return this.name; },
		
		/**
		*   setAction / getAction
		*
		*   Sets / Returns the form data action
		*/
		setAction: function(s) { this.action = s; },
		getAction: function() { return this.action; },
		
		/**
		*   setMethod / getMethod
		*
		*   Sets / Returns the form data method
		*/
		setMethod: function(s) { this.method = s; },
		getMethod: function() { return this.method; },
		
		/**
		*   setCallback / getCallback
		*
		*   Sets / Returns the call back object
		*/
		setCallback: function(s) { this.callBack = s; },
		getCallback: function() { return this.callBack; }
	}
);

/**
*   Class : InputData
*
*   Class holds all data necessary to esatblish a form input element
*
*   @usage    Used by all form input elements
*   @author   Daniel Ivanovic dan@substance001.com
*
*	@param	name - element name
*	@param	type - element input type
*	@param	size - element size
*	@param	maxChars - element max chars value
*/
var InputData = AbstractObject.extend(
	{
		/**
		*   init
		*
		*   Constructs the button dat6a object
		*/
		init: function()
		{
			this._super( "InputData" );
			
			// name
			this.name = "input";
			// input type
			this.type = "text";
			// size
			this.size = 25;
			// max chars
			this.maxChars = 100;
			// value
			this.value = "";
			// class
			this.cssClass = "";
		},
		
		/**
		*   setName / getName
		*
		*   Sets / Returns the input data name
		*/
		setName: function(s) { this.name = s; },
		getName: function() { return this.name; },
		
		/**
		*   setType / getType
		*
		*   Sets / Returns the input data type
		*/
		setType: function(s) { this.type = s; },
		getType: function() { return this.type; },
		
		/**
		*   setSize / getSize
		*
		*   Sets / Returns the input data size
		*/
		setSize: function(s) { this.size = s; },
		getSize: function() { return this.size; },
		
		/**
		*   setMaxChars / getMaxChars
		*
		*   Sets / Returns the input data max chars value
		*/
		setMaxChars: function(s) { this.maxChars = s; },
		getMaxChars: function() { return this.maxChars; },
		
		/**
		*   setValue / getValue
		*
		*   Sets / Returns the input data value
		*/
		setValue: function(s) { this.value = s; },
		getValue: function() { return this.value; },
		
		/**
		*   setClass / getClass
		*
		*   Sets / Returns the input class
		*/
		setClass: function(s) { this.cssClass = s; },
		getClass: function() { return this.cssClass; }
	}
);

/**
*	AbstractScrollbar
*/
var AbstractScrollbar = AbstractView.extend(
	{
		/**
		*   init
		*
		*   Constructs the scrollbar view
		*
		*	@param	t - type string
		*	@param	m - manager instance
		*	@param	h - holder instance
		*/
		init: function(t, m, h)
		{
			this._super( t, m, h );
		},
		
		/**
		*   setup
		*
		*   Sets up the view
		*/
		setup: function(sc, sp)
		{
			//alert( "setting up" );
			
			// call to super
			this._super();
		},
		
		/**
		*   build
		*
		*   Builds the view
		*/
		build: function()
		{
			//alert( "building" );
			
			var obj = this;
			
			// setup the slider
			$( this.getHolder() + " > div.slider" ).slider(
				{ change: obj.change, slide: obj.slide, min: -100, max: 0 }
			);
		},
		
		/**
		*   change
		*
		*   Called upon event of scroll change
		*
		*	@param	evt - slider change event
		*	@param	ui - ui element
		*/
		change: function(evt, ui)
		{
			var maxScroll = $( this.getHolder() + " > div.scroller" ).attr("scrollHeight") - $( this.getHolder() + " > div.scroller" ).height();
			$( this.getHolder() + " > div.scroller" ).animate(
				{ scrollTop: -ui.value * (maxScroll / 100) }, 1000
			);
		},
		
		/**
		*   slide
		*
		*   Called upon event of scroll slide
		*/
		slide: function()
		{
			var maxScroll = $( this.getHolder() + " > div.scroller" ).attr("scrollHeight") - $( this.getHolder() + " > div.scroller" ).height();
			$( this.getHolder() + " > div.scroller" ).attr(
				{ scrollTop: -ui.value * (maxScroll / 100) }
			);
		},
		
		/**
		*   enableButton / disableButton
		*
		*   Enables / disables the button
		*/
		enable: function()
		{
			// TODO : Complete logic here
		},
		
		disable: function()
		{
			// TODO : Complete logic here
		}
	}
);

/**
*	AbstractList
*/
var AbstractList = AbstractView.extend(
	{
		/**
		*   init
		*
		*   Constructs the abstract list - all list classes will extend this object
		*
		*	@param	t - type string
		*	@param	m - manager instance
		*	@param	h - view holder instance
		*/
		init: function(t, m, h)
		{
			this._super( t, m, h );
			
			// define vars
			this.listItems = new Array();
		},
		
		/**
		*   setup
		*
		*   Sets up the view instance
		*/
		setup: function()
		{
			//alert( "setting up" );
		},
		
		/**
		*   build
		*
		*   Builds the view
		*
		*	@param	d - league table data object
		*/
		build: function(d)
		{
			//alert( "building : " + this.listItems.length );
		},
		
		/**
		*   addItem
		*
		*   Adds a list item to the items array
		*
		*	@param	i - list item object
		*/
		addItem: function(i)
		{
			//alert( "adding item : " + i );
			
			// add data object to items array
			this.listItems.push( i );
		},
		
		/**
		*   clearItems
		*
		*   Clears all the items for the list holder
		*/
		clearItems: function()
		{
			//alert( "clearing items : " + this.listItems.length );
			
			// clear the list items array
			this.listItems = new Array();
			
			// clear the items from the list
			$( this.getHolder() ).html( "" );
		},
		
		/**
		*   loadItems
		*
		*   Loads all the items into the list holder
		*/
		loadItems: function()
		{
			//alert( "loading items : " + this.listItems.length );
		},
		
		/**
		*   update
		*
		*   Updates the view
		*
		*	@param	t - event type
		*	@param	d - data
		*/
		update: function(t, d)
		{
			// add generic update functionality here
		}
	}
);