/* @name:		Enhancement scripts
 *					NOW INCLUDES FORM ENHANCEMENT
 *
 * @site:		ME Bank
 * @author:		RBurnie, Hugeobject, http://www.hugeobject.com.au
 *
 *	REQUIRES: mootools
 *
 *	CONTENTS
 *		# GENERAL DOMREADY ENHANCEMENT (window domready)
 *		# Implement Class: Accordion
 *		# Class: Collapsable_widgets	- runs automatically
 *		# Class: Footnote_tips		- runs automatically
 *		# Class: Window_links		- runs automatically
		# Class: Sitemap		- runs automatically (if div#sitemap found)
 *		
 *	FORM ENHANCEMENT and VALIDATION
 *		# new Callback_forms // not ie6  - runs automatically
 *		# new Contact_forms // not ie6	 - runs automatically
 *		# new Mobile_lenders_clickthru;	 - runs automatically (if div#mobile_banking_managers_header found)
 *		
 */


/* = GENERAL DOMREADY ENHANCEMENT = ____________________________________________________ */
// AUTOMATED CALL on domready ============================================================

window.addEvent('domready',function(){	
	// = RUN DEVELOPEMNT SCRIPTS !!!!!!!!!!!!!!!!!!!
	// new ME_development();// <-- COMMENT OUT FOR LIVE
	// At the mo' the class above will add the getRate code in the actual
	// markup so you can see it easy - for checking if right code used
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	// = Add hover events for ie6 (for non a tags) =
	if(window.ie6) {
		// == buttons ==
		var buttons = $$('button');
		buttons.each(function(btn){
			btn.addEvent('mouseover',function(){ this.addClass('hover'); });
			btn.addEvent('mouseout',function(){ this.removeClass('hover'); });
		});
	}
	// == Hover event for blue snippets inner <a>'s ==
	// Will change hoev state of snippet if an inner <a> is hovered
	var snippets_standard = $$('div.snippet');
	var snippets_large = $$('div.snippet-large');
	var snippets = snippets_standard.merge(snippets_large);
	snippets.each(function(snippet){
		if(snippet.hasClass('blue')) {
			// Apply to any a tags mouseover instead of actual snippet
			var as = $ES('a',snippet);
			if($chk(as)) {
				as.each(function(a){
					if(!a.hasClass('footnote-link')) {
						a.addEvent('mouseover',function(){ snippet.addClass('hover'); });
						a.addEvent('mouseout',function(){ snippet.removeClass('hover'); });
					}
				});
			}
		}
	});
		
	// = RUN THE OTHER ENHANCEMENT CLASSES DEFINED BELLOW =
	new Collapsable_widgets();
	new Footnote_tips();
	new Window_links();
	new Table_colours();
	
	// = Page Specific enhancement =
	new Sitemap(); // only runs if div#sitemap is found (which only exists in sitemap.html)

	// = FORMS =
	if(!window.ie6) {
		// We dont want to enhance for ie6 cause theres too many issues#
		// what this means is all the links that would normally open a
		// modal style form on current page will instead go to the actual form
		// on the original form page (for the call back forms) and on ContactME
		// the forms will be left as is not hidden and enhanced
		// actual form functionality in ie6 will still work as expected
		//new Callback_forms();  -- no longer used
		new Contact_forms();
	}
	// Page Specific
	new Mobile_lenders_clickthru();
	
});

// End AUTOMATED CALL ======================================================================

// = Implement Class: Accordion = - http://forum.mootools.net/viewtopic.php?id=2713
if($chk(Accordion)) {
	Accordion.implement({
	    showAll: function() {
		var obj = {};
		this.previous = -1;
		this.elements.each(function(el, i){
		    obj[i] = {};
		    this.fireEvent('onActive', [this.togglers[i], el]);
		    for (var fx in this.effects) obj[i][fx] = el[this.effects[fx]];
		}, this);
		return this.start(obj);
	    },
	    hideAll: function() {
		var obj = {};
		this.previous = -1;
		this.elements.each(function(el, i){
		    obj[i] = {};
		    this.fireEvent('onBackground', [this.togglers[i], el]);
		    for (var fx in this.effects) obj[i][fx] = 0;
		}, this);
		return this.start(obj);
	    }
	});
}

/* = Class: Collapsable_widgets = _____________________________________________________
 *	Searches for all dl.collapseable in div#sub_2 > div.quick-links
 *	and turns them into collapsable items where dt is trigger dd is content
 *	NB:
 *	Requires that the definition list is structured correctly 
 *	Example: This is one item set in the dl - remember dt/dd association isnt done by nesting like other
 *	elements.
 *	<dl>
 *		<dt>
 *		<dd>
 */
var Collapsable_widgets = new Class({
	initialize: function() {
		var dls = $ES('dl.collapser',$('sub_2'));
		// = TOGGLE DISPLAY =
		dls.each(function(dl,i){
			var expansion_mode = (dl.hasClass('all-expandable') ? 'all-expandable' : 'one-at-a-time');
			var parent = dl.getParent();
			if(!parent.hasClass('quick-links')){ return; }
			// CONTINUE if the dl's parent has class quick-links
			
			// If the dl is the last element in the quick-links wrapper
			//  Close the bottom (css rule applies border)
			//  Make ul siblings open-end
			var siblings = parent.getChildren();
			var is_last = false;
			if(dl==siblings.getLast()) {
				siblings.each(function(sibling){
					if(sibling.getTag()=='ul' && !sibling.hasClass('closed')) {
						sibling.addClass('open-end');
					}
				});
				dl.addClass('closed');
				is_last = true;
			}
			
			var item_sets = [];
			var kids = dl.getChildren();
			// Loop thru kids - remember that dt/dd are at same level so the
			// 1st kid should be dt and 2nd a dd
			kids.each(function(kid,i){
				var tag = kid.getTag();
				// If modulo is 0 it should be a dt
				// store it in an array and push that array into the item_sets array
				if(i%2==0 && tag=='dt'){
					var set = [kid];
					item_sets.push(set);
				}else if(tag=='dd'){
					var set = item_sets.getLast();
					if(set.length==1) {
						kid.setStyle('display','none');
						if(kid==kids.getLast()) {
							kid.addClass('last');
						}
						set.push(kid);	
					}
				}
			});
			// Now loop thru the grouped items
			item_sets.each(function(set,i){
				// == dt == ---------------------------------------
				set[0].addClass('toggle');
				set[0].addEvent('mouseover',function() { 
					this.addClass('hover');
				});
				set[0].addEvent('mouseout',function() { 
					this.removeClass('hover');
				});
				// Events
				set[0].addEvent('click',function() {
					if(set[0].hasClass('expanded')) {
						set[0].fireEvent('collapse');
					}else{
						// Collapse others
						if(expansion_mode!='all-expandable') {
							item_sets.each(function(set){
								set[0].fireEvent('collapse');
							});
						}
						set[0].fireEvent('expand');
					}
				});
				set[0].addEvent('expand',function() {
					set[0].addClass('expanded');
					set[1].addClass('expanded');
					set[1].setStyle('display','block');
					// if an argument is set (in this case "no-glow" - see line bellow to initially expand items)
					// we want to prevent the glow - well actually fire it but use the set event so its white straight
					// away, that way if the blue bg version the item will be white as expacted
					if($chk(arguments[0])) {					
						set[1].fireEvent('glow','set');
					}else{
						set[1].fireEvent('glow');
					}
				});
				set[0].addEvent('collapse',function(){
					set[0].removeClass('expanded');
					set[1].removeClass('expanded');
					set[1].setStyle('display','none');
				});
				
				set[1].addEvent('glow',function(){
					var glow = new Fx.Style(set[1],'background-color',{duration:500,transition: Fx.Transitions.Circ.easeInOut});
					if($chk(arguments[0])) {			
						glow.set('#fff');
					}else{
						glow.start('#ecf3f6','#fff');
					}
				});
				// Check if we want it initially expanded
				if(set[1].hasClass('expanded')) {
					set[0].fireEvent('expand','no-glow');
				}
			},this);
		},this);
	}
});

var ME_tip = new Class({
	set_options: function(options){
		this.options = {
			tip_class: 'tips',
			inject: 'injectInside',
			content: false
		};
		Object.extend(this.options, options || {});
	},
	
	initialize: function(options) {
		this.set_options(options);
		this.tip_open = false;
		// Build the tip and make invisible ready for population and use
		this.tip = new Element('div',{'class':this.options.tip_class}).setOpacity(0);//sets also visibility == hidden
		this.e_content = new Element('div',{'class':'content'});
		this.tip.adopt(
			new Element('div',{'class':'top'}),
			this.e_content,
			new Element('div',{'class':'btm'})
		);
		// Inject the tip to DOM
		this.tip[this.options.inject]( $(this.options.parent) || $E('body') );
		if(this.options.content) {
			this.set_content(this.options.content);
		}
	},
	
	set_content: function(content) {
		if($type(content)=='string') {
			this.e_content.setHTML(content);
		}else if($type(content)=='element') {
			this.e_content.adopt(content);
		}else{
			return;
		}
	},
	
	show: function(position) {
		var fade = new Fx.Style(this.tip,'opacity',{duration:250});
		if($chk(position)) {
			this.tip.setStyles({
				'position': 'absolute',
				'top': position[0],
				'left': position[1]
			});
		}
		fade.start(0,1);
	},
	
	hide: function() {
		var fadeout = new Fx.Style(this.tip,'opacity',{duration:500});
		fadeout.start(1,0);
	}
});

var Footnote_tips = new Class({
	set_options: function(options){
		this.options = {
			offsets: {x:16,y:16}
		};
		Object.extend(this.options, options || {});
	},
	
	initialize: function(options) {
		this.set_options();
		this.content = $('content');
		// Get footnotes
		var footnotes = $ES('p[id]',$('footnotes'));
		var tips = {};
		if(footnotes.length>0) {
			// Continue...
			var links = $$('a');
			links.each(function(a) {
				footnotes.each(function(footnote){
					if(a.href.indexOf('#'+footnote.id)>-1) {
						// If not created yet make the tip
						if( !$chk(tips[footnote.id]) ){
							tips[footnote.id] = new ME_tip({
								content: footnote.innerHTML
							});
						}
						
						// Check if the content has any links - if so we will add a delay to the hide function
						var as = $ES('a',tips[footnote.id].tip);
						var delay_time = (as.length>0 ? 500 : 0);
						
						a.addClass('footnote-link');
						
						a.addEvent('mouseenter',function(e){
							var e = new Event(e);
							var position = this.get_position(e,tips[footnote.id].tip);
							tips[footnote.id].show(position);
							a.addClass('hover');
						}.bind(this));
						
						a.addEvent('mouseleave',function(){
							(function(){
								// We only want this to happen if the user has not hovered over the tip
								if(tips[footnote.id].tip.hasClass('hover')) { return; }
								tips[footnote.id].hide();
								a.removeClass('hover');
							}).delay(delay_time);
						}.bind(this));
						
						// Highlight footnote if linked to then fade highlight
						a.addEvent('click',function(){
							var glow = new Fx.Style(footnote,'background-color',{duration:2000,transition: Fx.Transitions.Circ.easeInOut});
							glow.start('#FEFFAF','#fff');
						});
						
						// Add events to tip so we can control when it gets hidden
						// Only do this if there is a delay
						if(delay_time>0) {
							tips[footnote.id].tip.addEvent('mouseenter',function(){ tips[footnote.id].tip.addClass('hover'); });
							tips[footnote.id].tip.addEvent('mouseleave',function(){ 
								tips[footnote.id].tip.removeClass('hover');
								a.fireEvent('mouseout');
							});
						}
					}
				},this);
			},this);
		}
	},
	
	get_position: function(e,tip) {
		var tip_size = tip.getSize();
		var w_size = window.getSize();
		
		var top = e.client.y + w_size.scroll.y + this.options.offsets.y;
		var left = e.client.x + this.options.offsets.x;
		
		// Adjust the positions if required
		if( (left + tip_size.size.x) > w_size.size.x ) {
			left = w_size.size.x - tip_size.size.x - this.options.offsets.x;
			left = (left<0 ? (this.options.offsets.x + w_size.scroll.x) : left);
		}
		if( (top+tip_size.size.y) > (w_size.size.y+w_size.scroll.y) ) {
			top = (e.client.y + w_size.scroll.y) - (tip_size.size.y + this.options.offsets.y);
		}
		
		return [top,left];
	}
});

/* = Class: New_window_links = __________________________________________________________
	Generic window opening
	Usage:
		*	ALL EXTERNAL LINKS HAVE FUNCTIONALITY APPLIED AUTOMATICALLY
			TO PREVENT THIS ADD THE ATTRIBUTE rel="same-window" TO THE <a>
			- The windows will have menu's etc.
			
		* 	PDF LINKS  HAVE FUNCTIONALITY APPLIED AUTOMATICALLY
			- The window will have NO menu's etc.
			
		*	EXTERNAL LINKS WITH NO MENUS OR DIFFERENT OPTIONS
			- 	Adding rel="new-window" will make the new window open with no
				menus
			-	adding a json string of options will add/overwrite any standard options
				ex.
				rel="new-win[{width:640,height:480,location:'yes'}]"
				
		*	OPEN INTERNAL LINK IN NEW WINDOW
			- add rel="new-win" OR
			- with options rel="new-win[{width:640,height:480,location:'yes'}]"
				BY DEFAULT THERE WILL BE NO MENU BARS ETC. THIS CAN BE FORCED BY ADDING
				CUSTOM OPTION allmenus:'yes'		
		
*/
var Window_links = new Class({
	initialize: function() {
		var local_domain = document.location.href.split('/');
		local_domain = local_domain[0]+'//'+local_domain[2];
		$$('a').each(function(a,i){
			var rel = ($chk(a.getProperty('rel')) ? a.getProperty('rel') : '');
			// Exit if theres a rel="same-window" (used to prevent enhancement)
			if(rel.indexOf('same-window')>-1) { return; }
			
			var title = ( $chk(a.getProperty('title')) ? a.getProperty('title') : '' );
			var new_title = ( title=='' ? '[opens in new window]' : a.getProperty('title')+' [opens in new window]' );
			var win_title = ( title=='' ? 'new_win'+i : title.replace(/ /g,'_').replace(/\W/g,'') );
			
			var open_new = false;
			// if its an external link
			if(a.href.indexOf('http')>-1 && a.href.indexOf(local_domain)<0){ 
				a.addClass('external-link');
				a.addEvent('click',function() {
				   pageTracker._trackPageview('/outgoing/'+this.href.split("://")[1]);
				});
				open_new = true;
			} else if(a.href.slice(a.href.length-4).toLowerCase() == '.pdf') {
				// If a .pdf document
				a.addClass('pdf-link');
				a.addEvent('click',function() {
				   pageTracker._trackPageview(this.href.split(location.hostname)[1]);
				});
				open_new = true;
			} else if(rel.indexOf('app-link')>-1) {
				// If internal with app-win rel
				a.addClass('app-link');
				a.addEvent('click',function() {
				   pageTracker._trackPageview(this.href.split(location.hostname)[1]);
				});
				open_new = true;
			} else if(rel.indexOf('new-win')>-1) {
				// If internal with new-win rel
				a.addClass('new-win-link');
				open_new = true;
			}
			
			if(open_new) {
				var optns = this.return_options(a,rel);
				a.setProperty('title',new_title);
				a.addEvent('click',function(e){
					new Event(e).stop();
					var win = window.open(a.href,win_title,optns);
					win.focus();
				});	
			}
			
		},this);
	},
	
	return_options: function(a,rel) {
		// NEW WINDOW OPTIONS DEFAULTS
			// Defaults based on old sites settings for opening new windows
			// can be over written by setting json string in rel attribute of link
			// EX: 
			// A 640 * 480 window with no scroll bar and a location bar would be
			// <a href="whatever" rel="new-win[{width:640,height:480,scrollbars:'no',location:'yes'}]">
			// Any additional option added this way will be added to the options
			
			var s_optns = '';
			var optns = {
				toolbar:'yes',
				status:'yes',
				location:'yes',
				menubar:'yes',
				directories:'yes',
				scrollbars:'yes',
				resizable:'yes'
			};
			
			var rel_optns = (rel.indexOf('new-win[')>-1 ? rel.split('[')[1].replace(']','') : '');
			// If the link has a rel value or rel_options has "allmenus" or its a pdf-link
			// hide the menu options. NB: if any of those options are specified they will
			// be re-written 
			if( (rel!='' && !$chk(rel_optns.allmenus)) || a.hasClass('pdf-link')) {
				optns.toolbar = 'no';
				optns.location = 'no';
				optns.menubar = 'no';
				optns.directories = 'no';
			}
			// CHECK FOR NEW OPTIONS AND ADD/REPLACE
			//if(rel_optns){
				// only filter options if the new-win contains a json string
				if(rel_optns.charAt(0)=='{' && rel_optns.charAt(rel_optns.length -1)=='}') {
					rel_optns = eval('('+rel_optns+')');
					$H(rel_optns).keys().each(function(k){
						optns[k] = rel_optns[k];
					});
				}
			//}
			// If no width or height supplied set it to be slightly smaller than screen
			if(!$chk(optns.width) || !$chk(optns.height)) {
				optns.width = screen.availWidth - 40;
				optns.height = screen.availHeight - 75;
				optns.screenX =0;
				optns.screenY =0;
				optns.top =10;
				optns.left =10;
			}
			
			// CONVERT OPTIONS TO STRING
			var ignore = ['allmenus'];
			$H(optns).keys().each(function(k) {
				if(ignore.indexOf(k)==-1) {
					s_optns += k+'='+optns[k]+',';
				}
			});
			s_optns = s_optns.slice(0,s_optns.length-1);
			
			return s_optns;
	}
});

// this function is needed to work around 
// a bug in IE related to element attributes
function hasClass(obj) {
   var result = false;
   if (obj.getAttributeNode("class") != null) {
      result = obj.getAttributeNode("class").value;
   }
   return result;
}  

function stripe(id) {

   // the flag we'll use to keep track of 
   // whether the current row is odd or even
   var even = false;
   
   // if arguments are provided to specify the colours
   // of the even & odd rows, then use the them;
   // otherwise use the following defaults:
   var evenColor = arguments[1] ? arguments[1] : "#fff";
   var oddColor = arguments[2] ? arguments[2] : "#eee";
   
   // obtain a reference to the desired table
   // if no such table exists, abort
   var table = document.getElementById(id);
   if (! table) { return; }
   
   // by definition, tables can have more than one tbody
   // element, so we'll have to get the list of child
   // &lt;tbody&gt;s 
   var tbodies = table.getElementsByTagName("tbody");
   
   // and iterate through them...
   for (var h = 0; h < tbodies.length; h++) {
   
      // find all the &lt;tr&gt; elements... 
      var trs = tbodies[h].getElementsByTagName("tr");
      
      // ... and iterate through them
      for (var i = 0; i < trs.length; i++) {
      
         // avoid rows that have a class attribute
         // or backgroundColor style
         if (! hasClass(trs[i]) &&
            ! trs[i].style.backgroundColor) {
         
            // get all the cells in this row...
            var tds = trs[i].getElementsByTagName("td");
            
            // and iterate through them...
            for (var j = 0; j < tds.length; j++) {
            
               var mytd = tds[j];
               
               // avoid cells that have a class attribute
               // or backgroundColor style
               if (! hasClass(mytd) &&
                   ! mytd.style.backgroundColor) {
               
                 mytd.style.backgroundColor =
                   even ? evenColor : oddColor;
               
               }
            }
         }
         // flip from odd to even, or vice-versa
         even =  ! even;
      }
   }
}
var Table_colours = Class({
   initialize: function() {
      $$("div#main tbody").each(function(tbody){
         $ES("tr", tbody).each(function(row,i){
            if ( i % 2 == 1 )
               row.addClass("even");
            else
               row.addClass("odd");
         });
         var rowcount = 0;
         $ES("tr", tbody).each(function(row,i){
            rowcount++;
         });
         var table = tbody.getParent("table");
         if (!table.hasChild("thead"))
            table.addClass("border-top");
         if (rowcount % 2 == 1 && !table.hasChild("tfoot"))
            table.addClass("border-bottom");
      });
   }
});

var Sitemap = new Class({
	initialize: function() {
		// Sitemap
		var sitemap = $('sitemap');
		if($chk(sitemap)) {
			// Exit if the Accordion class is missing in mootools.js
			if(!$chk(Accordion)) { return; }
			var toggles = $ES('h2.toggle',sitemap);
			var lists = $ES('ul.list',sitemap);
			// only continue if there is a match on toggle/list count
			if(toggles.length!=lists.length){ return; }

			// I was using the each list as the collapsable element but
			// because the class sets overflow:hidden; and that was hiding
			// the first level ul bullet images will nest them in divs and
			// use the divs as the collapsable elements		
			var divs = [];
			lists.each(function(list){
				var div = new Element('div').injectBefore(list);
				div.adopt(list);
				divs.push(div);
			});
			// Add hover event to toggle
			toggles.each(function(t){
				t.addEvent('mouseover',function() {
					this.addClass('hover');
				});
				t.addEvent('mouseout',function() {
					this.removeClass('hover');
				});
			});
			sitemap.addClass('accordion');
			var sitemap_accordion = new Accordion(toggles,divs,{
				opacity: false,
				onActive: function(toggler, element){
					toggler.addClass('open');
				},
			 
				onBackground: function(toggler, element){
					toggler.removeClass('open');
				},
				alwaysHide: true
			},sitemap);
			// add buttons to hideAll and Collapse All
			var btn_wrapper = new Element('p').addClass('buttons');
			var show = new Element('a').adopt(new Element('span').appendText('Expand All ')).addClass('button').addEvent('click',function(){
				sitemap_accordion.showAll();
			});
			var hide = new Element('a').adopt(new Element('span').appendText('Collapse All')).addClass('button').addEvent('click',function(){
				sitemap_accordion.hideAll();
			});
			btn_wrapper.adopt(show,hide).injectTop(sitemap);
		
		}
	}
});


// Function to expand and collapse interest rate table
function ShowHideRateTable(boxID, newState) {
  
   /* preload image */
   var collimg = new Image();
   collimg.src = '../images/icons/minus.gif';
   var expimg = new Image();
   collimg.src = '../images/icons/plus.gif';
   
   /* Obtain reference for the selected boxID layer and its button */
   var box = $('box'+boxID);
   var boxbtn = $('btn'+boxID);
   
   /* If the selected box is currently invisible, show it */
   if(box.style.display == 'none' || box.style.display=='' || newState == 'expand') {
      box.style.display = 'block';
      boxbtn.src = '../images/icons/minus.gif';
   }
   /* otherwise hide it */
   else {
      box.style.display = 'none';
      boxbtn.src = '../images/icons/plus.gif';
   }
   //temporary fix which must be removed when BB tables are introduced
   //this is hard-coded and a dodgy hack
   var allOpen = true;
   [1,2,3].each(function(b){
      if($('box'+b).style.display == 'none' || $('box'+b).style.display=='') {
         $('box4').style.display = '';
         $('btn4').src = '../images/icons/plus.gif';
         allOpen = false;
      }
   });
   if(allOpen) {
      //temporary fix which must be removed when BB tables are introduced
      //this is hard-coded and a dodgy hack
      $('box4').style.display = 'block';
      $('btn4').src = '../images/icons/minus.gif';
   }
   //end of dodgy hack
}

// Function to expand and collapse interest rate table
function ToggleRateTables(boxIDs) {
   var anyBoxCollapsed = false;
   boxIDs.each(function(boxID){
      var box = $('box'+boxID);
      if(box.style.display == 'none' || box.style.display=='') {
         anyBoxCollapsed = true;
      }
   });
   
   //if any table is collapsed, expand all tables
   if(anyBoxCollapsed) {
      boxIDs.each(function(boxID){
         ShowHideRateTable(boxID, 'expand');
      });
   }
   //otherwise hide all tables
   else {
      boxIDs.each(function(boxID){
         ShowHideRateTable(boxID, 'collapse');
      });
   }
}
  

// Function to expand and collapse interest rate table
function ToggleRateTable(boxID) {
   ShowHideRateTable(boxID, 'toggle');
}

var ME_development = new Class({
		initialize: function() {
			/*
			Test data for rates/dates inserted via <getRate> xml tag
				This will display the actual code used just before the actual output
				with a yellow background. Use as a visual reference to make sure correct codes used
			*/
			$ES('span[rel]').each(function(rate){
				if(rate.getProperty('rel').indexOf('getRate')<0) { return; }
				var code = rate.getProperty('rel').split('[')[1].replace(']','');		
				var div = new Element('div').appendText(code).setStyle('background','yellow').setProperty('title',code+'\n Turn off by commenting out new ME_development(); in enhance.js');
				div.injectBefore(rate);
			});	
			
		}
});
// ==========================================================================================
// = FORM ENHANCEMENT AND VALIDATION
// ==========================================================================================

/* = CALLBACK BUTTON FUNCTIONALITY =
 * This enhancement fetches the call_back forms markup via ajax from /contact/call_back.html
 * and uses the specified form in a modal box.
 * If JavaScript is disabled (or is ie6) the callback link will go directly to the specific
 * form on the actual call back form page.
 */
//THIS FUNCTION IS NO LONGER USED AND IS HERE FOR FUTURE REFERENCE ONLY
var Callback_forms = new Class({
	initialize: function() {
		if(document.URL.indexOf('call_back.html')>-1) { return; }
		// Continue...

		var callback_links = $ES('a.request');
		if(callback_links.length == 0){ return; }
		
		// Create div to hold the temp ajax data 
		var temp_data_div = new Element('div').setStyle('display','none');
		/*
		IE was being stupid - I was loading data into 1 div then grabbing the forms, emptying div html and
		putting the forms back. This is fine on all browsers except IE which decides you want to also empty
		out all content of the forms. So instead have to use 2 data divs.
		NB: Even tho were no longer enhancing for ie6 leaving this here incase ie7 has this same issue
		*/
		var data_div = new Element('div').setStyles({
			'width':900,
			'position':'absolute',
			'left': '-9999px',
			'top':0,
			'visibility':'hidden'		
		});
		var url = false;
		$E('body').adopt(temp_data_div,data_div);
		var n_valid_links = 0;	
			
		callback_links.each(function(link){
			if(link.href.indexOf('call_back.html#call_back_personal')>-1 || link.href.indexOf('call_back.html#call_back_business')>-1) {
				n_valid_links++;
				var split_link = link.href.split('#');				
				url = split_link[0];
				var f_id = split_link[1];
				link.addEvent('click',function(event) {
					var form = data_div.getElementById(f_id);
					if(!$chk(form)){ return; }				
					// Continue...
					var event = new Event(event); event.preventDefault();
					// Change the layout to suit the modal 
					form.addClass('modal');	
					var form_size = form.getSize().scrollSize;	
					// Unfortunately a few browser inconsistencies
					// adjust size for IE
					form_size.width = (window.ie ? form_size.x+2 : form_size.x);
					form_size.height = (window.ie ? form_size.y+2 : form_size.y);
					// adjust height for opera
					form_size.height = (window.opera ? form_size.height+100 : form_size.height);
					
					
					
					var close = new Element('div').appendText('X').addClass('close');
					
					var modal = new MooPrompt('',form, {
						width: form_size.width,
						height: form_size.height,
						button1: close,
						return_content_to_dom: true
					});
				
					// also add a cancel button
					// but first we need to remove it if it allready exists
					var cancel = $(f_id+'_cancel_btn');
					if($chk(cancel)){ cancel.remove(); }
				
					cancel = new Element('a').addClass('button-white').setProperty('id',f_id+'_cancel_btn');
					cancel.adopt( new Element('span').appendText('Cancel') );
					cancel.addEvent('click',function(event){
						var event = new Event(event);
						event.preventDefault();				
						modal.close();
					});
					// For some reason in opera the cancel button is ontop of submit if injected
					// before so if opera inject after all others before
					cancel['inject'+(window.opera ? 'After' : 'Before')]( $E('button.submit',form) );
					
				});
			}
		});
		
		if(n_valid_links>0) {
			// request the html from /contact/call_back.html
			new Ajax(url,{
				method: 'get',
				update: temp_data_div,
				onComplete: function() { 
					// Now filter out all the html crap except the two forms
					var form1 = $('call_back_personal');
					var form2 = $('call_back_business');
					if(!$chk(form1) || !$chk(form2)) {
						temp_data_div.remove();
						data_div.remove();
						return; 
					}
					data_div.adopt(form1,form2);
					temp_data_div.remove();
					// in ie7 the ME_callback_validation() runs when the code is grabed via ajax
					// all other browsers it doesn't - which is prob more correct
					// so lets run the ME_callback_validation() if not ie
					if(!window.ie) { ME_callback_validation(); }
				}
			}).request();
		}else{
			temp_data_div.remove();
			data_div.remove();
		}
	}
});

/* = MAKE FORMS IN CONTACT PAGE COLLAPSEABLE =
 * - Enhances the two forms on /contact/index.html to appear in a modal box
 *		NB: This inhancement is only specific to the /contact/index.html it is
 *			 different to the callback form functionality
 */
var Contact_forms = new Class({
	initialize: function() {
		var contact_forms = $$(['pb_enquiry_form','bb_enquiry_form']);
		if(contact_forms.length == 0) { return; }
		
		contact_forms.each(function(form){
			// = Find the toggle link =
			var f_id = form.getProperty('id');
			var t_id = 'show_'+f_id;
			var show = $(t_id);
			if(!$chk(show)) {
				var msg = 'No matching toggle element with id="'+t_id+'" found.\nAborting collapseable enhancement on form id="'+f_id+'".\n This will not effect the forms performance.';
				//$chk(console) ? console.error(msg) : alert(msg); 
				return;
			}
			
			var form_size = form.getSize().scrollSize;
			
			form.setStyle('border-width',1);			
			form.getParent().setStyle('display','none');
			
			show.addEvent('click',function(event){
				var event = new Event(event);
				event.preventDefault();
				
				var close = new Element('div').appendText('X').addClass('close');
				
				var modal = new MooPrompt('',form, {
					width: form_size.x,
					height: form_size.y,
					button1: close,
					return_content_to_dom: true
				});
				
				// also add a cancel button
				// but first we need to remove it if it allready exists
				var cancel = $(f_id+'_cancel_btn');
				if($chk(cancel)){ cancel.remove(); }
				
				cancel = new Element('a').addClass('button-white').setProperty('id',f_id+'_cancel_btn');
				cancel.adopt( new Element('span').appendText('Cancel') );
				cancel.addEvent('click',function(event){
					var event = new Event(event);
					event.preventDefault();				
					modal.close();
				});
				// For some reason in opera the cancel button is ontop of submit if injected
				// before so if opera inject after all others before
				cancel['inject'+(window.opera ? 'After' : 'Before')]( $E('button.submit',form) );
				
			});			
			
		});
	}
});

/* = Class: Mobile_lenders_clickthru = ________________________________________________________
	Explaination:
	The page /personal/mobile_banking/ will have a link in the header to the book.html form page
	it will be a direct link - the base fallback for users with js disabled. 
	Then we enhance with js:
	- remove the link and replace with a form to check users post code
	- if theres a mobile banking manager in area form will redirect page to the url
	  taken from the original removed link
	  
	TODO: 	further enhance so the form doesnt redirect but instead grabs the form from the book.html page
			and load into a modal box via ajax.
	
	Expected markup:
	<div id="mobile_banking_managers_header" class="banner clearfix">
		<img src="../images/demo-image-banner.jpg" alt="Mobile Banking Managers"/>
		<a href="#">Book a mobile banking manager</a>
	</div>
	
	Transformed markup:
	<div id="mobile_banking_managers_header" class="banner clearfix">
		<img src="../images/demo-image-banner.jpg" alt="Mobile Banking Managers"/>
		<form action="#" method="post">
			<fieldset>
				<legend>Book a mobile banking manager</legend>
				<label for="ml_postcode">Your Post Code</label>
				<input type="text" name="ml_postcode" id="ml_postcode" size="20" value="Enter Your Post Code"/>
				<button type="submit" class="go">Go</button>
			</fieldset>
		</form>
	</div>
*/
var Mobile_lenders_clickthru = new Class({
	initialize: function() {
		// == Mobile Banking Managers ==
		var ml_header = $('mobile_banking_managers_header');
		if(!$chk(ml_header)) { return; }
		// Were using the Class ME_postcodes to check postcode input so if its not found exit enhancement
		if(!$chk(ME_postcodes)) { return; }
		// Continue...
		this.postcodes = new ME_postcodes();
		// Get the a tag
		var a = $E('a',ml_header);
		if(!$chk(a)) { return; }
		// Continue...
		var url = a.getProperty('href');
		var lenders_form = false;
		// Grab the mobile lenders form from the page a is pointing to so we can use in modal
//		if(!window.ie6) {		
//			var temp_data_div = new Element('div').setStyle('display','none');
//			var data_div = new Element('div').setStyles({
//				'width':900,
//				'position':'absolute',
//				'left': '-9999px',
//				'top':0,
//				'visibility':'hidden'		
//			});
//			$E('body').adopt(temp_data_div,data_div);
//			var that = this;
//			new Ajax(url,{
//				method: 'get',
//				update: temp_data_div,
//				onComplete: function() {
//					// Now filter out all the html crap except the form
//					lenders_form = temp_data_div.getElementById('request_mobile_lender');
//					if($chk(form)) {
//						data_div.adopt(lenders_form);
//					}
//					temp_data_div.remove();
//					// in ie7 the ME_lenders_validation() runs when the code is grabed via ajax
//					// all other browsers it doesn't - which is prob more correct
//					// so lets run the ME_lenders_validation() if not ie
//					if(!window.ie) { ME_lenders_validation(); }
//				}
//			}).request();
//		}

		this.label_text = 'Enter Your Post Code';
		var input_id = 'ml_postcode';
		var legend = new Element('legend').appendText(a.innerHTML);
		var label = new Element('label').appendText(this.label_text).setProperty('for',input_id);
		this.input = new Element('input').setProperties({
			'type':	'text',
			'name':	input_id,
			'id':	input_id,
			'size':	20,
			'value':this.label_text
		});
		var button = new Element('button').appendText('Go').setProperty('type','submit').setProperty('onClick','pageTracker._trackPageview(\'/mobilelender\'); return true;').addClass('go');
		var form = new Element('form');
		
		// = TRANSFORM INNER HTML =
		a.remove();
		ml_header.adopt(
			form.adopt(
				new Element('fieldset').adopt(
					legend,label,this.input,button
				)
			)			
		);
		
		// = ADD FUNCTIONALITY =
		// Once off clear of the text field
		var input_focus = function(){
			this.setProperty('value','');
			this.removeEvents('focus');
		}
		this.input.addEvent('focus',input_focus);
		// I did have the functionality on the submit event but it didnt work
		// in ie 6/7 for some reason so instead on the button
		form.addEvent('submit',function(e) {
			new Event(e).stop();
		});

		button.addEvent('click',function(e) {
			new Event(e).stop();
			
			if(this.validate()){
				if(lenders_form==false) {				
					document.location = url;
				}
				else{
					// Form in modal
					lenders_form.addClass('modal');
					var form_size = lenders_form.getSize().scrollSize;	
					// Unfortunately a few browser inconsistencies
					// adjust size for IE
					form_size.width = (window.ie ? form_size.x+2 : form_size.x);
					form_size.height = (window.ie ? form_size.y+2 : form_size.y);
					// adjust height for opera
					form_size.height = (window.opera ? form_size.height+100 : form_size.height);

					var close = new Element('div').appendText('X').addClass('close');

					var modal = new MooPrompt('',lenders_form, {
						width: form_size.width,
						height: form_size.height,
						button1: close,
						return_content_to_dom: true
					});
					var f_id = lenders_form.getProperty('id');
					var cancel = $(f_id+'_cancel_btn');
					if($chk(cancel)){ cancel.remove(); }

					cancel = new Element('a').addClass('button-white').setProperty('id',f_id+'_cancel_btn');
					cancel.adopt( new Element('span').appendText('Cancel') );
					cancel.addEvent('click',function(event){
						var event = new Event(event);
						event.preventDefault();				
						modal.close();
					});
					// For some reason in opera the cancel button is ontop of submit if injected
					// before so if opera inject after all others before
					cancel['inject'+(window.opera ? 'After' : 'Before')]( $E('button.submit',lenders_form) );
				}
			}else{
				var value = this.input.getProperty('value');
				// Not valid so we will reset the input and make it glow
				// Add default text to input and once off focus event again
				this.input.setProperty('value',this.postcodes.error_msg);
				this.input.addEvent('focus',input_focus);
				var glow = new Fx.Style(this.input,'background-color',{duration:500,transition: Fx.Transitions.Circ.easeInOut});
				glow.start('#FEFFAF','#fff').chain(function(){
						(function(){
							if(value.trim()!='') {
								this.input.setProperty('value',value);	
							}else{
								this.input.setProperty('value',this.label_text);
							}
						}.bind(this)).delay(250);									
				}.bind(this));
				
			}
		}.bind(this));
		
		if(!window.opera) {
			// For some reason fireEvent is playing up in opera in this instance so when you
			// hit enter the modal opens with weird content but clicking the submit button works fine
			// both should be the same and is on every other browser - so for opera not offering the enter key functionality
			// Update: it seems that opera fires the click event on key enter without us needing to tell it too so all
			// good as long as we dont add this event in opera.
			this.input.addEvent('keydown',function(event){
				var event = new Event(event);
				if(event.key=='enter') {
					button.fireEvent('click',event);	
				}
			});
		}
	},
	
	validate: function() {
			value = this.input.getProperty('value').trim();
			if(value == '' || value == this.label_text) {
				return false;	
			}else{
				return this.postcodes.validate_postcode(value);
			}
	}
});

/*
 * Class: ME_validation
 *
 * NORMAL USAGE:
 *	The easiest way to use is to call the Class after the from in the markup like so:
 * (after the form in question) =========================================================
 *	<script type="text/javascript" defer="defer">
 *
 *	var pb_rules = {
 *		form: 'pb_enquiry_form',
 *		fields: {
 *			'pb_title': { label: 'Title', rule: ''  }, // not required
 *			'pb_firstname': { label: 'First name', rule:'required|alpha|min_length[2]' },
 *			'pb_surname': { label: 'Surname', rule:'required|alpha|min_length[2]' },
 *			'pb_email':{ label: 'Email', rule:'required|email' },
 *			'pb_phone':{ label: 'Phone', rule:'required|phone|min_length[8]|max_length[10]' },
 *			'pb_postcode':{ label: 'Postcode', rule:'required|postcode' },
 *			// is required but all options have a value so we dont need to bother validating
 *			'pb_day':{ label: 'Day', rule:'' },						
 *			'pb_time':{ label: 'Time', rule:'' },
 *			'pb_message':{ label: 'Message', rule:'required' }						
 *		}
 *	}
 *	var pb_validation = new ME_validation(pb_rules);
 *
 *	</script>
 * =======================================================================================
 *
 * For the Call Back forms we do it differently because most the time the form is pulled from another page
 * Call Back forms use the global function: ME_callback_validation (defined after this Class - and uses this Class)
 *		
 */
var ME_validation = new Class({
	initialize: function(rules_object){
		this.rules = rules_object;
		if(!$type(this.rules)=='object') {
			return;
		}
		// Continue...
		this.form = ($chk(this.rules.form) ? $(this.rules.form) : false);
		if(!$chk(this.form)) { return; }
		// Continue...
		// Do a run thru the fields and apply some basic functionality
		this.fields = $H(this.rules.fields).keys();
		this.fields.each(function(field) {
				var f = this.form.getElementById(field);
				if(!$chk(f)) { return; }
				// Continue...
				f = $(f); // make sure element is extended (for ie6)
				// For some reason in ie6 this.form.getElementById(field) doesn't return
				// the full extended element as $() even tho getElementById is suposed to
				// be extended to $()
				f.addEvent('focus',function(){ f.addClass('focus'); });
				f.addEvent('blur',function(){ f.removeClass('focus'); });
				// Prevent form submission on key: enter
				f.addEvent('keydown',function(e){
					var e = new Event(e);
					if(e.key == 'enter') { 
						e.stop(); 
					}
				});
		},this);
		
		// fix key enter event for checkboxes and radios
		var checkboxes = $ES('input[type=checkbox]',this.form);
		var radios = $ES('input[type=radio]',this.form);
		var c_and_r = checkboxes.merge(radios);
		c_and_r.each(function(input){
			input.addEvent('keydown',function(e) {
				var e = new Event(e);
					if(e.key == 'enter') { 
						e.stop();
						if(this.getProperty('checked')==true) {
							this.removeProperty('checked');
						}else{
							this.setProperty('checked','checked');
						}
					}
			});
		});

		this.form.addEvent('submit',function(e){
			if(!this.validate_all()){
				new Event(e).stop();
				this.show_errors();
			}else{
				// form should submit
				this.form.submit();
			}
		}.bind(this));
	},
	
	validate_all: function() {
		this.valid = true;
		this.errors = {};
		this.fields.each(function(id){
			var field_obj = {
				e: this.form.getElementById(id),
				id: id,
				label: this.rules.fields[id].label
			}
			if(!$chk(field_obj.e)) { return; }
			// Continue...
			field_obj.e.removeClass('error');
			var rules = this.rules.fields[id].rule.split('|');
			rules.each(function(rule){
				if(rule=='') { return; }
				// Continue...
				// Check if its a rule with params
				var b = rule.indexOf('[');
				if(b>-1) {
					var param = rule.slice(b+1,-1);
					rule = rule.slice(0,b);
					if($chk(this[rule])) {
						this[rule](field_obj,param);
					}
				}else if($chk(this[rule])) {
					this[rule](field_obj);
				}
			},this);
		},this);
		return this.valid;
	},
	
	// VALIDATION FUNCTIONS (function name corresponds to rule name)
	required: function(field_obj) {
		if(field_obj.e.getProperty('value').trim()=='') {
			this.add_error('required',field_obj.id,field_obj.label); // 3rd param used in message string
			this.valid =  false;
		}
	},
	
	email: function(field_obj) {
		// [rb] match taken from original ME forms.js
		var match = field_obj.e.value.match(/\b(^(\S+@).+((\.com)|(\.biz)|(\.info)|(\.name)|(\.museum)|(\.net)|(\.edu)|(\.mil)|(\.gov)|(\.org)|(\..{2,2}))$)\b/gi);
		if(!match) {
			this.add_error('email',field_obj.id,field_obj.label); // 3rd param used in message string
			this.valid =  false;
		}
	},
	
	postcode: function(field_obj) {
		// [rb] match taken from original ME forms.js
		if(!field_obj.e.value.match(/^\d\d\d\d$/)) {
			this.add_error('postcode',field_obj.id,field_obj.label); // 3rd param used in message string
			this.valid =  false;
		}
	},
	
	alpha: function(field_obj) {
		if(!field_obj.e.value.test(/^\D*$/)) {
			this.add_error('alpha',field_obj.id,field_obj.label); // 3rd param used in message string
			this.valid =  false;
		}
	},
	
	numeric: function(field_obj) {
		if(!field_obj.e.value.test(/^\d*([\.,]\d+)?$/)) {
			this.add_error('numeric',field_obj.id,field_obj.label); // 3rd param used in message string
			this.valid =  false;
		}
	},
	
	phone: function(field_obj) {
		if (!field_obj.e.value.match(/^[0-9+-\. ()]*$/)) {
			this.add_error('phone',field_obj.id,field_obj.label); // 3rd param used in message string
			this.valid =  false;
		}
	},
	// min_length[#]
	min_length: function(field_obj,amount) {
		if (field_obj.e.value.length < amount) {
			this.add_error('min_length',field_obj.id,field_obj.label,amount); // 3rd and 4th param used in message string
			this.valid =  false;
		}
	},
	// max_length[#]
	max_length: function(field_obj,amount) {
		if (field_obj.e.value.length > amount) {
			this.add_error('max_length',field_obj.id,field_obj.label,amount); // 3rd and 4th param used in message string
			this.valid =  false;
		}
	},
	// exact_length[#]
	exact_length: function(field_obj,amount) {
		if (field_obj.e.value.length != amount) {
			this.add_error('exact_length',field_obj.id,field_obj.label,amount); // 3rd and 4th param used in message string
			this.valid =  false;
		}
	},
	// Not is useful for dropdowns where each option has a value but 1 of them would be considered a non value
	// such as "-select-" which would pass the "required" validation but not the "not[-select-]" validation
	not: function(field_obj,not_value) {
		if(field_obj.e.value.trim()==not_value) {
			this.add_error('not',field_obj.id,field_obj.label,not_value); // 3rd and 4th param used in message string
			this.valid =  false;
		}
	},
	
	// = ERROR REPORTING =
	messages: {
		required: "The %s field is required.",
		email: "The %s field must contain a valid email address.",
		alpha: "The %s field may only contain alphabetical characters.",
		numeric: "The %s field must contain a number.",
		not: "The %s field must have a value other than %s",
		phone: "The %s field must be a valid phone number.",
		postcode: "The %s field must be a valid Australian postcode.",
		min_length: "The %s field must be at least %s characters in length.",
		max_length: "The %s field cannot exceed %s characters in length.",
		exact_length: "The %s field must be exactly %s characters in length."
	},
	// arguments[2] + are strings to be replaced in the messages %s
	add_error: function (rule,id) {
		var msg = this.messages[rule];
		for (var i = 2; i < arguments.length; i++) {
			msg = msg.replace(/%s/, arguments[i]);
		}
		if(!$chk(this.errors[id])) { this.errors[id] = []; }
		var field = $(id);
		this.errors[id].push(msg);
	},
	
	show_errors: function() {
		var error_keys = $H(this.errors).keys();
		
		if(window.ie6) {
			// ie6 causing too much grief with overlays etc - given time restraints and the fact that
			// were not enhancing the other form functionality in ie6 we will just use an alert
			var msg = 'The form contains the following errors:\n\n';
			error_keys.each(function(field_id){
				var field_errors = this.errors[field_id];
				field_errors.each(function(error){
					msg += '- '+error+'\n';
				});
				this.error_field_event($(field_id));
			},this);
			alert(msg);
		}else{
			var form_coords = this.form.getCoordinates();
			// Make the form position relative if not a modal
			if(!this.form.hasClass('modal')) {
				this.form.setStyle('position','relative');
			}
			var error_box = new Element('div').addClass('form_errors').setStyles({
				'position':'absolute',
				'top':8,
				'left':8,
				'width': form_coords.width-20,
				'height': form_coords.height-20,
				'overflow': 'auto'
			});
			error_box.setOpacity(0);
			error_box.injectTop(this.form);
			var ul = new Element('ul');
			var ok = new Element('a').addClass('button').adopt( new Element('span').appendText('OK') );
			error_box.adopt( 
				new Element('p').appendText('The form contains the following errors:'), 
				ul, 
				new Element('p').adopt(ok).addClass('buttons')
			);
			
			error_keys.each(function(field_id){
				var field_errors = this.errors[field_id];
				field_errors.each(function(msg){
					ul.adopt(new Element('li').appendText(msg));
				});
				
				this.error_field_event($(field_id));
				
			},this);
	
			// for some reason <sup>'s keep poking thru the error box so we
			// will hide them while its open
			var sups = $ES('sup',this.form);
			sups.each(function(sup){
				sup.setStyle('visibility','hidden');
			});
			var fade = new Fx.Style(error_box,'opacity',{duration:200});
			fade.start(0,1);
			ok.addEvent('click',function(e){
				var e = new Event(e).preventDefault();
				sups.each(function(sup){
					sup.setStyle('visibility','visible');
				});
				fade.start(1,0).chain(function(){
					error_box.remove();
				});
			});
		}
	},
	
	error_field_event: function(field) {
		field.addClass('error');
		var field_event = 'click';
		var type = field.getProperty('type');
		if(!$chk(type)) { type = field.getTag(); }
		switch(type) {
			case 'text': field_event = 'keydown';
				break;
			case 'textarea': field_event = 'keydown';
				break;
			case 'password': field_event = 'keydown';
				break;
			case 'radio': field_event = 'change';
				break;
			case 'checkbox': field_event = 'change';
				break;
			case 'select': field_event = 'change';
				break;
		}
		field.addEvent(field_event,function() {
			field.removeClass('error');
		});
	}
});
// = Validation for Call back forms =
// Because were using these forms in every page via MooPrompt we will
// put the validation here in a global function
// in the actual call_back.html the validation is applied by adding this bellow the form in markup:
//	 <script type="text/javascript" defer>ME_callback_validation();</script>
// NB: make sure its after the forms
//
// For the MooPrompt versions this function is called from within the Callback_forms Class
function ME_callback_validation() { 
	var personal_rules = {
		form: 'call_back_personal',
		fields: {
			'cb_pb_title': { label: 'Title', rule: '' },
			'cb_pb_firstname': { label: 'First name', rule:'required|alpha|min_length[2]' },
			'cb_pb_surname': { label: 'Surname', rule:'required|alpha|min_length[2]' },
			'cb_pb_email':{ label: 'Email', rule:'required|email' },
			'cb_pb_phone1':{ label: 'Phone', rule:'required|phone|min_length[8]|max_length[10]' },
			'cb_pb_phone2':{ label: 'Phone', rule:'required|phone|min_length[8]|max_length[10]' },
			'cb_pb_postcode':{ label: 'Postcode', rule:'required|postcode' },
			'cb_pb_time':{ label: 'Time of Day', rule:'' },
			'cb_pb_existing_customer':{ label: 'Customer Type', rule:'' },
			'cb_pb_existing_account':{ label: 'Existing Account?', rule:'' }
		}
	}
	var business_rules = {
		form: 'call_back_business',
		fields: {
			'cb_bb_title': { label: 'Title', rule: '' },
			'cb_bb_firstname': { label: 'First name', rule:'required|alpha|min_length[2]' },
			'cb_bb_surname': { label: 'Surname', rule:'required|alpha|min_length[2]' },
			'cb_bb_email':{ label: 'Email', rule:'required|email' },
			'cb_bb_phone':{ label: 'Phone', rule:'required|phone|min_length[8]|max_length[10]' },
			'cb_bb_postcode':{ label: 'Postcode', rule:'required|postcode' },
			'cb_bb_day':{ label: 'Day', rule:'' },
			'cb_bb_time':{ label: 'Time', rule:'' }						
		}
	}
	var personal_validation = new ME_validation(personal_rules);
	var business_validation = new ME_validation(business_rules);
}
// Validation for FHSA Registration form = 
// Same as above
function FHSA_registration_validation() {
	var rules = {
		form: 'fhsa_registration',
		fields: {
			'fhsa_title': { label: 'Title', rule: '' },
			'fhsa_firstname': { label: 'First name', rule:'required|alpha|min_length[2]' },
			'fhsa_surname': { label: 'Surname', rule:'required|alpha|min_length[2]' },
			'fhsa_email':{ label: 'Email', rule:'required|email' },
			'fhsa_phone':{ label: 'Phone', rule:'required|phone|min_length[8]|max_length[10]' },
			'fhsa_postcode':{ label: 'Postcode', rule:'required|postcode' },
			'fhsa_day':{ label: 'Day', rule:'' },
			'fhsa_time':{ label: 'Time', rule:'' }
		}
	}
	var fhsa_validation = new ME_validation(rules);
}
// Validation for Mobile Banking Managers form = 
// Same as above
function ME_lenders_validation() {
	var rules = {
		form: 'request_mobile_lender',
		fields: {
			'rml_title': { label: 'Title', rule: '' },
			'rml_firstname': { label: 'First name', rule:'required|alpha|min_length[2]' },
			'rml_surname': { label: 'Surname', rule:'required|alpha|min_length[2]' },
			'rml_email':{ label: 'Email', rule:'required|email' },
			'rml_phone':{ label: 'Phone', rule:'required|phone|min_length[8]|max_length[10]' },
			'rml_postcode':{ label: 'Postcode', rule:'required|postcode' },
			'rml_day':{ label: 'Day', rule:'' },
			'rml_time':{ label: 'Time', rule:'' },
			'rml_borrow_amount':{label: 'Borrow amount', rule: 'numeric'},
			'rml_income':{label: 'Household income', rule: 'not[-select-]'}
		}
	}
	var lenders_validation = new ME_validation(rules);
}
// ==========================================================================================
// ==========================================================================================
// = 3RD PARTY SCRIPTS and EXTENSIONS =

/* ========================================================	
	Class: MooPrompt - http://www.clanccc.co.uk/box/box.html
	
	NB:	I have had to modify this Class due to a few probs
			plus fixes to fx.Style etc now Fx.Style
			
			Have now added more custom code to this class
			do not replace with fresh version without adding
			the fixes.
	========================================================
*/
var MooPrompt = box = new Class({
	setOptions: function(options){
		this.options = {
			buttons: 1,
			width: 300, // Set width of the box
			height: 0, // Set height of the box (0 = sized to content)
			maxHeight: 500, // Maximum height of the dialog box
			vertical: 'middle', // top middle bottom
			horizontal: 'center', // left center right
			delay: 0, // Delay before closing (0=no delay)
			overlay: true, // Cover the page
			effect: 'grow',
			return_content_to_dom: false 
			// [rb] - 	if true the content (if element) will first be returned to its original parent before
			//			removing the MooPrompt container
			
				// 'grow' - Expands box from a middle point and fades in content
				// 'slide' - Slides in the box from the nearest side.
			// button1: 'Ok' --- supply this for setting button text
			// onButton1: function --- supply function for button action
		};
		Object.extend(this.options, options || {});
	},
	
	initialize: function(title, content, options){
		this.setOptions(options);
		this.title = title;
		this.text = content;
		
		//[rb] changed: if (document.all && document.compatMode) {
		if(window.ie && !window.ie7) {
			this.iframe = new Element('iframe').addClass('cbIframe').setStyles({
				'position': 'absolute', 'top': 0, 'left': 0,
				'height': Window.getScrollHeight()+'px', 'width': Window.getScrollWidth()+'px'
			}).setProperties({
				'frameborder': 0, 
				'scrolling': 'no'
			}).injectInside(document.body);
		}
		
		
		if (this.options.overlay) {
			if ($('cbOverlay')) {
				this.overlay = $('cbOverlay');
			} else {
				this.overlay = new Element('div').setProperty('id', 'cbOverlay');
				this.overlay.setStyles({
					'position': 'absolute', 'top': 0, 'left': 0, 'width': '100%', 'visibility': 'hidden'
				}).injectInside(document.body);
			}
		}
		this.container = new Element('div').setProperty('class', 'cbContainer');
		this.container.setStyles({
			'position': 'absolute', 'visibility': 'hidden'
		}).injectInside(document.body);
		this.box = new Element('div').setProperty('class', 'cbBox');
		this.box.setStyles({
			'width': this.options.width+'px',
			'overflow': 'auto'
		}).injectInside(this.container);
		// [rb] Added check to see if needed
		if(this.title.trim()!='') {
			this.header = new Element('h3').setProperty('class', 'cbHeader').appendText(this.title).injectInside(this.box);
		}
		this.content = new Element('div').setProperty('class', 'cbContent').injectInside(this.box);
		if ($type(content) == 'element' ) {
			if(this.options.return_content_to_dom) {// [rb] custom
				this.inner_content = content;
				this.inner_content_parent = content.getParent();
			}
			content.injectInside(this.content);
		} else {this.content.appendText(this.text);}
		this.buttons = new Element('div').setProperty('class', 'cbButtons').injectInside(this.box);
		for (var i = 1; i <= this.options.buttons; i++) {
			if (typeof(this.options['button'+i]) == 'undefined') {
				this.options['button'+i] = 'Button';
			}
			if ($type(this.options['button'+i]) == 'element') {
				this['button'+i] = this.options['button'+i]
				this['button'+i].injectInside(this.buttons);
			} else {
				this['button'+i] = new Element('input').setProperties({type: 'button', value: this.options['button'+i]}).injectInside(this.buttons);
			}
			if ($type(this.options['button'+i]) != 'function') {
				this.options['button'+i] = function() {};
			}
			this['button'+i].onclick = this.close.pass([this.options['onButton'+i]], this);
		}
		this.boxHeight = (this.box.offsetHeight < this.options.maxHeight) ? this.box.offsetHeight : this.options.maxHeight;
		this.boxHeight = (this.options.height > 0) ? this.options.height : this.boxHeight;
		this.box.setStyle('display', 'none');
		this._position();
		this.eventPosition = this._position.bind(this);
		window.addEvent('scroll', this.eventPosition).addEvent('resize', this.eventPosition);
		if (this.options.overlay && this.overlay.getStyle('visibility') == 'hidden') {
			this.fx1 = new Fx.Style(this.overlay, 'opacity', {duration:500}).custom(0, .8);
		}
		if (this.options.effect == 'grow') {
			this.container.setStyle('top', (Window.getScrollTop()+(Window.getHeight()/2))+'px');
			var style = {}; style.height = 0; style.width = 0;
			if (this.options.horizontal != 'center') {
				style[this.options.horizontal] = (this.options.width/2)+'px';
			}
			if (this.options.vertical == 'top') {
				style[this.options.vertical] = (Window.getScrollTop()+(this.boxHeight/2))+'px';
			} else if (this.options.vertical == 'bottom') {
				style.top = (Window.getScrollTop()+Window.getHeight()-(this.boxHeight/2)-25)+'px';
			}
			this.container.setStyles(style);
			this.container.setStyle('visibility', '');
			this.fx2 = new Fx.Styles(this.container, {duration: 500});
			this.fx2.custom({
				'width': [0, this.options.width], 'margin-left': [0, -this.options.width/2], 'margin-right': [0, -this.options.width/2],
				'height': [0, this.boxHeight], 'margin-top': [0, -this.boxHeight/2], 'margin-bottom': [0, -this.boxHeight/2]
			}).chain(function() {
				this.box.setStyles({
					'visibility': 'hidden', 'display': '', 'height': this.boxHeight+'px'
				});
				new Fx.Style(this.box, 'opacity', {duration: 500}).custom(0, 1).chain(function() {
					this.box.setStyle('filter', '');
					if (this.options.delay > 0) {
						var fn = function () {
							this.close()
						}.bind(this).delay(this.options.delay);
					}
				}.bind(this));
			}.bind(this));
		} else {
			this.container.setStyles({
				'height': this.boxHeight, 'width': this.options.width,
				'left': '', 'visibility': 'hidden'
			});
			this.box.setStyles({
				'visibility': '', 'display': '', 'height': this.boxHeight+'px'
			});
			this.fx2 = new Fx.Styles(this.container, {duration: 500});
			var special = {};
			if (this.options.horizontal != 'center') {
				special[this.options.horizontal] = [-this.options.width, 0];
			} else {
				this.container.setStyles({
					'left': '50%', 'margin-left': (-this.options.width/2)+'px', 'margin-right': (-this.options.width/2)+'px'
				});
			}
			if (this.options.vertical == 'top') {
				special[this.options.vertical] = [Window.getScrollTop()-this.boxHeight, Window.getScrollTop()];
			} else if (this.options.vertical == 'bottom') {
				special.top = [Window.getScrollTop()+Window.getHeight(), Window.getScrollTop()+Window.getHeight()-this.boxHeight-25];
			} else {
				this.container.setStyles({
					'top': (Window.getScrollTop()+(Window.getHeight()/2))+'px', 'margin-top': (-this.boxHeight/2)+'px', 'margin-bottom': (-this.boxHeight/2)+'px'
				});
			}
			special.opacity = [0, 1];
			this.fx2.custom(special).chain(function() {
				if (this.options.delay > 0) {
					var fn = function () {
						this.close()
					}.bind(this).delay(this.options.delay);
				}
			}.bind(this));
		}
	},
	
	_position: function() {
		var wHeight = (Window.getScrollHeight() > Window.getHeight()) ? Window.getScrollHeight() : Window.getHeight();
		var lr = (this.options.effect == 'grow') ? this.options.width/2 : 0;
		var tb = (this.options.effect == 'grow') ? this.boxHeight/2 : 0;
		if (this.iframe) {

			this.iframe.setStyles({
				'height': Window.getScrollHeight()+'px',
				'width': Window.getScrollWidth()+'px'
			});
		}
		if (this.options.overlay) {
			this.overlay.setStyles({height: wHeight+'px'});
		}
		switch(this.options.vertical) {
			case 'top':
				this.container.setStyle('top', (Window.getScrollTop()+tb)+'px');
				break;
			case 'middle':
				this.container.setStyle('top', (Window.getScrollTop()+(Window.getHeight()/2))+'px');
				break;
			case 'bottom':
				this.container.setStyle('top', (Window.getScrollTop()+Window.getHeight()-this.boxHeight+tb-25)+'px');
				break;
		}
		if (this.options.horizontal == 'center') {
			this.container.setStyle('left', '50%');
		} else {
			this.container.setStyle(this.options.horizontal, lr+'px');
		}
	},
	
	close: function(fn) {
		for (var i = 1; i <= this.options.buttons; i++) {
			this['button'+i].onclick = null;
		}
		if ($type(this.fx1) == 'object') {
			this.fx1.clearTimer();
		}
		this.fx2.clearTimer();
		if (typeof(fn) == 'function') {fn();}
		if (this.options.overlay && this.overlay.getStyle('opacity') == 0.8) {
			new Fx.Style(this.overlay, 'opacity', {duration:250}).custom(0.8, 0);
		}
		new Fx.Style(this.container, 'opacity', {duration:250,
			onComplete: function() {
				window.removeEvent('scroll', this.eventPosition).removeEvent('resize', this.eventPosition);
				if (this.options.overlay) {
					this.overlay.remove();
				}
				if(this.options.return_content_to_dom) {// [rb] custom
					this.inner_content.injectInside(this.inner_content_parent); 
				}
				this.container.remove();
				if (this.iframe) {
					this.iframe.remove();
				}
			}.bind(this)
		}).custom(1, 0);
	}
});
MooPrompt.implement(new Chain);
