﻿/// <reference name="MicrosoftAjax.js"/>

// Setup browser params
var fMozilla	= (typeof document.implementation != 'undefined') && (typeof document.implementation.createDocument != 'undefined') && (typeof HTMLDocument!='undefined');
var fSafari		= navigator.userAgent.toLowerCase().indexOf("safari") != -1;
var fIE			= !this.fMozilla && !this.fSafari;	// default to IE

/*
 * Create namespaces
 */
function ninemsn(){}
ninemsn.mylocal = function(){};
ninemsn.mylocal.util = function(){};

var utl = ninemsn.mylocal.util;

/*
 * Array containing ref's to event handles
 */
var g_handlers = [];

/* 
 *  YSM Configs
 */
var ysmOrganic = "mylocal";
var ysmDefault = "mylocal_default";
var ysmSearchType = "accountFilters=msn_au_mylocal&termFilters=msn_au_mylocal&urlFilters=msn_au_mylocal";
var ysmDefaultCollection = [ 'deposit term', 'cheap flight', 'auto insurance', 'car insurance', 'broadband', 'card credit', 'car', 'job search', 'ebay', 'home loan', 'job', 'air travel' ];
var ysmParams = { partnerId : "msncom_au_xml_mylocal", start : 1, count : 3, searchType : "", keywords : "", forceDefaultKeywords : false, forcedSearchType : ysmDefault, keywordCollection : ysmDefaultCollection };
var ysmConfig = { titleLength : 75, descLength : 60, hideImages : true, adImageHeight : 55 };

/*
 * Replaces {0}..{n} substrings with argument values
 * @return {string} The newly formatted string
 */
String.prototype.format = function()
{
	var s = this;
	for (var i=0; i < arguments.length; i++)
	{
	    var repl = "{" + (i) + "}";
	    while(s.indexOf(repl) != -1)
		    s = s.replace(repl, arguments[i]);
	}
	return(s);
};

/**
 * Trims non-text characters from the beginning of the string
 * @return {string} The newly trimmed string
 */
String.prototype.lTrim = function () {return this.replace(/^\s*/, "");};

/**
 * Trims non-text characters from the end of the string
 * @return {string} The newly trimmed string
 */
String.prototype.rTrim = function () {return this.replace(/\s*$/, "");};

/**
 * Trims non-text characters from the beginning and the end of the string
 * @return {string} The newly trimmed string
 */
String.prototype.trim = function () {return this.rTrim().lTrim();};

/**
 * Trims non-alphanum, apostrophe, or space characters from anywhere within the string
 * @return {string} The newly trimmed string
 */
String.prototype.trimPunc = function () {return this.replace(/[^a-zA-Z0-9\s']/gi, " ").trim()};

/**
 * Trims non-alphanum, apostrophe, or space characters from anywhere within the string
 * @return {string} The newly trimmed string
 */
String.prototype.trimDSpace = function () {return this.replace(/\s+/gi, " ")};

/**
 * Trims non-alphanum, apostrophe, or space characters from anywhere within the string
 * @return {string} The newly trimmed string
 */
String.prototype.escapeApst = function () {return this.trimPunc().replace(/'/gi,"\\'").trim()};

/**
 * Converts the first letter of each word to a capital letter
 * @return {string} The newly cased string
 */
String.prototype.toProperCase = function () {return this.toLowerCase().replace(/^(.)|\s(.)/g, function($1) { return $1.toUpperCase(); });};

/**
 *  Converts state names to uppercase
 *  @return {string} The newly cased string
 */
String.prototype.stateToUpper = function () {return this.replace(/\b(nsw|sa|qld|vic|nt|wa|act|tas)\b/ig, function($1) { return $1.toUpperCase(); });}

/**
 * Returns true if the string is null or empty
 * @return {boolean} true if the object is null, undefined or empty string.
 */
ninemsn.mylocal.util.IsNullOrEmpty = function(value) {return typeof(value) == "undefined" || (value == null) || (typeof(value) == "string" && value == '');};

/**
 * This function returns true if a is an object, array, or function.
 * @return {boolean} It returns false if a is a string, number, Boolean, null, or undefined.
 */
ninemsn.mylocal.util.isObject = function(a) { return (typeof a == 'object' && !!a) || ninemsn.mylocal.util.isFunction(a); };

/**
 * This function returns true if a is a function. Beware that some native functions in IE 
 * were made to look like objects instead of functions. This function does not detect that.
 * Netscape is better behaved in this regard.
 * @return {boolean} It returns false if not a function type
 */
ninemsn.mylocal.util.isFunction = function(a) { return typeof a == 'function'; };

/***
 * ninemsn.mylocal.init
 * decription   : called on document load, initialise the mylocal portal
 */
ninemsn.mylocal.init = function()
{   
    try
    {
        /*
         *  Set the page title
         */
        //if (!window.g_defaultTitle)
        //    ninemsn.mylocal.util.setPageTitle();
        
        var noMap = ninemsn.mylocal.util.getQueryParam("noMap");
                 
        if (!noMap && window.g_renderMap)     
            ninemsn.mylocal.maps.initVEMaps('right_column');
        
        /*
         *  Render platinum ad if on search restuls page
         */
        if (document.getElementById('DisplayPlatinumAds'))
            ninemsn.mylocal.util.renderPlatinumAd(window.g_where, window.g_postcode, window.g_categoryID)
         
        /*
         *  Configure Search Keyword from destination
         *  Execute YSM Sponsored site get
         */  
        if (document.getElementById('sponsored_sites'))
        {
            var ysmWhat = utl.IsNullOrEmpty(window.g_what) ? "" : window.g_what; 
            ninemsn.mylocal.util.showSponsoredListings('sponsored_sites', ysmWhat);
        }
          
        /*
         *  Pop gui fields with QS param values
         */
        ninemsn.mylocal.util.prePopulateFields();
        
        /*
         *  Wireup search filter checkbox event handlers
         */
        if (document.getElementById(window.g_servicingID))
            ninemsn.mylocal.search.bindFilters(window.g_servicingID, window.g_surroundingID, window.g_relevanceID, window.g_nameID, window.g_distanceID);

        /*
         *  Wireup List Controls
         */
        if (window.ListControl)
        {
            ninemsn.mylocal.controls.refine = new ListControl();
            ninemsn.mylocal.controls.refine.initialise(0);
            
            ninemsn.mylocal.controls.scratchPad = new ListControl();
            ninemsn.mylocal.controls.scratchPad.initialise(1);
            
            ninemsn.mylocal.controls.scratchPadMain = new ListControl();
            ninemsn.mylocal.controls.scratchPadMain.initialise(2);
            
            ninemsn.mylocal.controls.searched = new ListControl();
            ninemsn.mylocal.controls.searched.initialise(3);
            
            ninemsn.mylocal.controls.viewed = new ListControl();
            ninemsn.mylocal.controls.viewed.initialise(4);
            
            ninemsn.mylocal.controls.searchedMain = new ListControl();
            ninemsn.mylocal.controls.searchedMain.initialise(5);
            
            ninemsn.mylocal.controls.viewedMain = new ListControl();
            ninemsn.mylocal.controls.viewedMain.initialise(6);
        }
        
        /*
         *  Wireup Ratings Control
         */
        var ratingsDiv = document.getElementById('ratings_edit');
        if (ratingsDiv)
        {
            ninemsn.mylocal.controls.ratings = new RatingsControl();
            ninemsn.mylocal.controls.ratings.initialise('ratings_edit');
        }
        
        /*
         *  Register the tab control if required
         */
        if (window.g_registerTabControl && window.TabControl)
        {
            ninemsn.mylocal.controls.tab = new TabControl()
            ninemsn.mylocal.controls.tab.initialise(0);
        }

        /*
         *  Initiate survey doodad
         */
        if (!utl.IsNullOrEmpty(ninemsn.mylocal.survey)) {
            var survey = new ninemsn.mylocal.survey();
            survey.initiate();
        }                
        
        /* 
        *  Setup detatch of all events on window unload
        */ 
        utl.attachEvent(window, "onunload", utl.detachAllEvents);
                 
    }
    catch (ex)
    {   
        /*
         *  Write out excetions to debug panel
         */
         utl.debout("** EXCEPTION ** ninemsn.mylocal.init : {0}".format(ex.description));
    }
    
    return false;
};


/*
 *  renderPlatinumAd 
 *
 *  @param  {string} where : the where term entered by the user
 *  @return {string} null
 */
ninemsn.mylocal.util.renderPlatinumAd = function(where, postCode, categoryID)
{
    try 
    {
        var platinumLocation = utl.isStateSearch(where);
        if (!platinumLocation)
            platinumLocation = postCode;            
        utl.debout("** Platinum: " + platinumLocation);
            
        Ninemsn.MyLocalMigration.Proxies.Proxy.GetPlatinumAds(categoryID, platinumLocation, ninemsn.mylocal.util.platinumAdCallback);
    }
    catch (ex)
    {
        /*
         *  Write out excetions to debug panel
         */
         utl.debout("** EXCEPTION ** ninemsn.mylocal.utl.renderPlatinumAd : {0}".format(ex.description));
    }
}

/*
 *  isStateSearch
 *  description:    
 *  Confirms whether or not a where is state only
 */ 
ninemsn.mylocal.util.isStateSearch = function(location)
{
    var searchLocation = location.toString();
    switch (searchLocation.toUpperCase().replace(",", ""))
    {
        case "NSW":
        case "NEW SOUTH WALES":
            return "NSW";
        case "AUSTRALIAN CAPITAL TERRITORY":
        case "ACT":       
            return "ACT";
        case "VICTORIA":
        case "VIC":
            return "VIC";
        case "SOUTH AUSTRALIA":
        case "SA":
            return "SA";
        case "WESTERN AUSTRALIA":
        case "WA":
            return "WA";
        case "NORTHERN TERRITORY":
        case "NT":
            return "NT";
        case "TASMANIA":
        case "TAS":
            return "TAS";
        case "QUEENSLAND":
        case "QLD":
            return "QLD";            
        default:
            return null;
    }
};


/*
 *  platinumAdCallback
 *
 *  @param  {string} code : code returned from the platinum ad call
 *  @return {string} null
 */
ninemsn.mylocal.util.platinumAdCallback = function(code)
{
    try
    {
        if (utl.IsNullOrEmpty(code))
            return false;
        
        var platinumArray = code.toString().split('[mspace]');
        if (platinumArray.length - 1 < 1) 
            return false;
        
        /*
         *  Build platinum ad HTML
         */     
        var platinumAdHTML = [];
        var adFunction = "";
        for(var i = 0; i < platinumArray.length - 1; i++)
        {
            adFunction = platinumArray[i];
            platinumAdHTML.push("<div class='platinum_ad'>{0}</div>".format(eval(adFunction)));
        }
        
        /*
         *  Insert platinum ad into page
         */
        var platinumAdDiv = document.getElementById('DisplayPlatinumAds');
        if (!platinumAdDiv)
            return false;
        
        platinumAdDiv.innerHTML     = "<div id='yellow_PlatinumDisp'><div class='platinum_display'>{0}</div></div>".format(platinumAdHTML.join(''));
        platinumAdDiv.style.display = "block";
    }
    catch (ex)
    {
        /*
         *  Write out excetions to debug panel
         */
         utl.debout("** EXCEPTION ** ninemsn.mylocal.util.platinumAdCallback : {0}".format(ex.description));
    }

    return false;
}

/**
  * Reads a cookie value
  *
  * @param  {string} strName The name of the cookie
  * @return {string} The cookie value
  */
ninemsn.mylocal.util.readCookie = function(strName)
{
	var strCookie = document.cookie;
	
	var ca = strCookie.split(";");
	for(var i=0; i < ca.length; i++)
	{
		var va = ca[i].split("=");
		if (va[0].trim() == strName)
			return va[1];
	}
	
	return null;
};

 /**
  * Writes a cookie value
  *
  * @param {string} strName The name of the cookie
  * @param {string} strVal The value of the cookie
  * @param {string} strDomain The domain of the cookie (optional)
  */
ninemsn.mylocal.util.writeCookie = function(strName, strVal, strDomain)
{
	var newExpiry;
    
	newExpiry = new Date();
	newExpiry.setYear(newExpiry.getFullYear() + 5);
	
	if (typeof document!='undefined')
	{
		var strCook = (strName+"="+strVal+";expires=" + newExpiry.toGMTString() + ";path=/");
		
		if (strDomain)
		    strCook += ";domain=" + strDomain;

		document.cookie = strCook;
    }
};

 /**
  * Deletes a cookie value
  * 
  * @param {string} strCookieName The name of the cookie
  * @param {string} strDomain The domain of the cookie (optional)
  */
ninemsn.mylocal.util.deleteCookie = function(strCookieName, strDomain)
{
    var ca = document.cookie.split(';');

    if (ca != null)
    {
        for(var i=0;i<ca.length;i++)
        {
            var c = ca[i];
            
            var n = c.split("=");
            if (n.length > 0)
            {
				var strName = n[0].lTrim();
				
				if (strName == strCookieName)
				{
				    var strCook = strName + "=; expires=Fri, 31 Dec 1999 23:59:59 GMT;";
				    if (strDomain)
				        strCook += "domain=" + strDomain + ";";
				        
					document.cookie = strCook;
				}
            }
        }
    }
};


/*
 *  ninemsn.mylocal.util.setPageTitle
 *  Grab the data out of the what and where fields, set it in the title
 */
ninemsn.mylocal.util.setPageTitle = function()
{
    try
    {
        if (!utl.IsNullOrEmpty(window.g_whatID) && !utl.IsNullOrEmpty(window.g_whereID))
        {
            var what = document.getElementById(window.g_whatID).value;
            var where = document.getElementById(window.g_whereID).value;
                                    
            if (!utl.IsNullOrEmpty(what) && !utl.IsNullOrEmpty(where) 
                    && what != ninemsn.mylocal.search.defaultWhat && where != ninemsn.mylocal.search.defaultWhere)
                document.title = "{0} in {1} - ninemsn mylocal".format(what, where);
        }
    }
    catch (ex)
    {   
        /*
         *  Write out excetions to debug panel
         */
         utl.debout("** EXCEPTION ** ninemsn.mylocal.util.setPageTitle : {0}".format(ex.description));
    }
    
    return;
};

/*
 *  Pre Populate Direction Fields
 *  Populate any input fields with values taken from the query string
 */
ninemsn.mylocal.util.prePopulateFields = function()
{
    try
    {
        /*
         *  If on details page, Check for any tab states requested
         */
        if (window.g_businessDetails)
        {
            var tab = ninemsn.mylocal.util.getQueryParam("tab");
            if (tab)
                ninemsn.mylocal.util.handleTabClick(tab);
        }
        
        /*
         *  Direction fields only available on the directions page
         */         
        if (!window.g_mapDirections || utl.IsNullOrEmpty(window.g_formStreet))
            return false;
            
        document.getElementById('text_street').value = window.g_formStreet;
        document.getElementById('text_suburb').value = window.g_formSuburb;
        document.getElementById('option_' + window.g_formState).selected = true;
        document.getElementById('text_postcode').value = window.g_formPostcode;
        document.getElementById(window.g_formRoute).checked = true;
    }
    catch (ex)
    {
        /*
         *  Write out excetions to debug panel
         */
         utl.debout("** EXCEPTION ** ninemsn.mylocal.util.prePopulateFields : {0}".format(ex.description));
    }
    return false;
};

ninemsn.mylocal.util.handleKeyDown = function(e)
{      
    if (!fIE)
        window.event = e;
            
    if (window.event.keyCode != 13)
        return false;
    
    var autoCompleteDiv = document.getElementById('AutoCompleteEx_completionListElem');
    if (autoCompleteDiv && autoCompleteDiv.style.display != 'none')
        return false;
    
    ninemsn.mylocal.search.handleSearchClick();
    
    window.event.returnValue = false;
    window.event.cancel = true; 
    return false;   
}

 /**
  * ninemsn.mylocal.util.isArray
  * @param {string} a : Element to test for array type
  * description :
  * Returns true if element is an array type, else return false
  */
ninemsn.mylocal.util.isArray = function(a)
{
	if (!isObject(a))
		return false;
	
	if (isDate(a))
		return false;
	
	// HACK: just check for a few known funcs	
	if (typeof(a.pop) == "function" && typeof(a.join) == "function" && typeof(a.splice) == "function")
		return true;
		
	return false;
};

 /**
  * Retrieves a query string parameter
  * @param {string} strName : Name of the query string parameter
  * @return {string} The query string value or null
  * description :
  * Retrieves a query string parameter
  */
ninemsn.mylocal.util.getQueryParam = function(strName)
{
	var strQueryParams = window.location.href;
    
    var a = strQueryParams.split("?");
    if (a.length < 2)
        return null;
        
    var aa = a[1].split("&");
    for(var i=0; i < aa.length; i++)
    {
        var aaa = aa[i].split("=");
        
        if (aaa[0].toUpperCase() == strName.toUpperCase())
            return aaa[1];
    }
    
    return null;
};

/**
 * Implements the insertAdjacentHTML method as described by IE in other browsers
 *
 * @param {Element} el The element that is receiving the new HTML
 * @param {String} sWhere Name of location for HTML insertion point
 * @param {String} sHTML Text of the HTML to insert
 */
ninemsn.mylocal.util.insertAdjacentHTML = function (el, sWhere, sHTML)
{
    if (fIE)
    {
	    el.insertAdjacentHTML(sWhere, sHTML);
	    return;
    }
	
    var df;	// : DocumentFragment
    var r = el.ownerDocument.createRange();
	
    switch (String(sWhere).toLowerCase())
    {
	    case "beforebegin":
		    r.setStartBefore(el);
		    df = r.createContextualFragment(sHTML);
		    el.parentNode.insertBefore(df, el);
		    break;
		
	    case "afterbegin":
		    r.selectNodeContents(el);
		    r.collapse(true);
		    df = r.createContextualFragment(sHTML);
		    el.insertBefore(df, el.firstChild);
		    break;
		
	    case "beforeend":
		    r.selectNodeContents(el);
		    r.collapse(false);
		    df = r.createContextualFragment(sHTML);
		    el.appendChild(df);
		    break;
		
	    case "afterend":
		    r.setStartAfter(el);
		    df = r.createContextualFragment(sHTML);
		    el.parentNode.insertBefore(df, el.nextSibling);
		    break;
		    
		default:
		    break;
    }	
};

/**
 * Creates a callback function that will be called with arbitrary additional arguments.
 * For example:
 *    var fnc = createCallback(foo, 1,2,3);
 *    fnc(10);
 *
 * Will call function foo with parameters 10, 1, 2, 3
 *
 * @param {Function} fnc The function to call
 * @param {params} p Any number of params
 * @return {Function} The new callback
 */
ninemsn.mylocal.util.createCallback = function(fnc)
{
	var args = [];
	for(var i=1; i < arguments.length; i++)
		args.push(arguments[i]);
		
	return function()
	{
		for(var i=0; i < arguments.length; i++)
			args.push(arguments[i]);
			
		return fnc.apply(undefined, args);
	};
};

/**
 * Same as createCallback except an extra this parameter is passed which is used
 * to reference the callback function
 *
 * @param {object} obj The this reference, on which the strFunc exists
 * @param {strFunc} strFunc The name of the function on obj to call
 * @param {params} p Any number of params
 * @return {Function} The new callback
 */
ninemsn.mylocal.util.createThisCallback = function(obj, strFunc)
{
	var temp = obj;
	var args = [];
	for(var i=2; i < arguments.length; i++)
		args.push(arguments[i]);
		
	return function()
	{
		// Add args we were passed onto the end
		for(var i=0; i < arguments.length; i++)
			args.push(arguments[i]);
		
		if (temp[strFunc])
			return temp[strFunc].apply(obj, args);
	};
};

/**
 * Same as createCallback except an array of arguments can be passed
 *
 * @param {function} fnc The function to call
 * @param {Array} args Any number of params
 * @return {Function} The new callback
 */
ninemsn.mylocal.util.createCallbackArgs = function(fnc, args)
{
	var argsSave = args;
		
	return function()
	{
		for(var i=0; i < arguments.length; i ++)
			argsSave.push(arguments[i]);
			
		return fnc.apply(undefined, argsSave);
	};
};

function handleEvent(e)
{
	if (!fIE)
	{
		window.event = e;
		//added for FF compatibility
		try
		{
			var node = e.target;
			while(node.nodeType != node.ELEMENT_NODE)
				node = node.parentNode;
			window.event.srcElement = node;
		}
		catch(ex)
		{
		}
	}
}

/**
 * Adds an event listener in a browser independent way.  Adds the event handler to a global list of handler
 * such that it can be removed en masse in detachAllEvents
 *
 * @param {Object} o Object to which event handler is attached
 * @param {String} evt Name of event to which to attach (ex: onclick)
 * @param {Function} fnc Function to call when event is fired
 */
ninemsn.mylocal.util.attachEvent = function(o, evt, fnc)
{
	if (!o)
		return;
		
	if (!fIE)
	{
		// Remove the "on" prefix
		if (evt.substr(0,2).toLowerCase() == "on")
			evt = evt.substr(2);
	}

	g_handlers.push({o:o,evt:evt,fnc:fnc});
	
	if (!fIE)
	{
		o.addEventListener(evt, handleEvent, false);
		o.addEventListener(evt, fnc, false);		// Hook the actual event		
	}
	else
		o.attachEvent(evt, fnc);
};

/**
 * Same as attachCallback except an object can be passed with a named function as the callback
 *
 * @param {Object} o Object to which event handler is attached
 * @param {String} evt Name of event to which to attach (ex: onclick)
 * @param {Object} th The object containing the callback function
 * @param {String} strFunc The name of the callback function attribute on the object
 */
ninemsn.mylocal.util.attachEventThisCallback = function(o, evt, th, strFunc)
{
	if (!o)
		return;
		
	if (!fIE)
	{
		// Remove the "on" prefix
		if (evt.substr(0,2).toLowerCase() == "on")
			evt = evt.substr(2);
	}
	
	var args = [];
	args.push(th);
	args.push(strFunc);
	for(var i=4; i < arguments.length; i++)
		args.push(arguments[i]);
		
	var fncNew = utl.createThisCallback.apply(null, args); // t  utl.createThisCallbackArgs(th, strFunc, args);
		
	g_handlers.push({o:o,evt:evt,fnc:fncNew});
	
	if (!fIE)
	{
		o.addEventListener(evt, handleEvent, false);
		o.addEventListener(evt, fncNew, false);		// Hook the actual event		
	}
	else
		o.attachEvent(evt, fncNew);
};

/**
 * Same as attachEvent except an argument list can also be passed to the callback
 *
 * @param {Object} o Object to which event handler is attached
 * @param {String} evt Name of event to which to attach (ex: onclick)
 * @param {Function} fnc Function to call when event is fired
 * @param {Object} p Arbitrary additional arguments
 */
ninemsn.mylocal.util.attachEventCallback = function(o, evt, fnc)
{
	if (!o)
		return;
		
	if (!fIE)
	{
		// Remove the "on" prefix
		if (evt.substr(0,2).toLowerCase() == "on")
			evt = evt.substr(2);
	}
	
	var args = [];
	for(var i=3; i < arguments.length; i++)
		args.push(arguments[i]);
		
	var fncNew = utl.createCallbackArgs(fnc, args);
		
	g_handlers.push({o:o,evt:evt,fnc:fncNew});
	
	if (!fIE)
	{
		o.addEventListener(evt, handleEvent, false);		// Hook the actual event		
		o.addEventListener(evt, fncNew, false);		// Hook the actual event		
	}
	else
		o.attachEvent(evt, fncNew);
};

/**
 * Removes an event handler in a browser independent way
 *
 * @param {Object} o Object to which event handler is attached
 * @param {String} evt Name of event to which to attach (ex: onclick)
 * @param {Function} fnc Function specified as the callback
 */
ninemsn.mylocal.util.detachEvent = function(o, evt, fnc)
{
	if (!fIE)
	{
		// Remove the "on" prefix
		if (evt.substr(0,2).toLowerCase() == "on")
			evt = evt.substr(2);
			
		o.removeEventListener(evt, handleEvent, false);
		o.removeEventListener(evt, fnc, false);
	}
	else
		o.detachEvent(evt, fnc);
};

/**
 * Removes all known event handlers.  Called primarily to reduce memory leaks due to circular references.
 */
ninemsn.mylocal.util.detachAllEvents = function()
{
	for(var i=0; i < g_handlers.length; i++)
	{
		var h = g_handlers[i];
		
		ninemsn.mylocal.util.detachEvent(h.o, h.evt, h.fnc);
	}
	
	g_handlers = null;
};

/**
 * ninemsn.mylocal.util.getNumbers
 * @param {string}  inString
 * description:    
 * Accepts a string and returns the integer potion only, eg: Sydney NSW 2000 will return 2000
 */ 
ninemsn.mylocal.util.getNumbers = function(inString) 
{
    var number = inString.match(/\d+(,\d{3})*(\.\d{1,2})?/g);
    number = postCode ? postCode[0] : null;
    
    return number;
};

/*
 *  ninemsn.mylocal.util.getBaseUrl
 *  
 */
ninemsn.mylocal.util.getBaseUrl = function()
{
    return "{0}/{1}{2}".format(document.location.protocol, "/", document.location.hostname); /* concatenate // to prevent error in compression */
};

/*
 *  ninemsn.mylocal.util.redirect
 *  
 */
ninemsn.mylocal.util.redirect = function(url)
{
    try
    {
        /*
         *  Append http if it doesn't exist already
         */
        if (url.indexOf('http://') < 0)
            url = "http://{0}".format(url);
            
        window.open(url);
    }
    catch (ex)
    {
        /*
         *  Write out excetions to debug panel
         */
         utl.debout("** EXCEPTION ** ninemsn.mylocal.util.redirect : {0}".format(ex.description));
    }
    
};

/*
 *  handledirectionskeydown
 *  Simple field validation & form submit
 */
ninemsn.mylocal.util.handleDirectionsKeyDown = function()
{
    if (window.event.keyCode != 13)
        return false;
        
    ninemsn.mylocal.util.handleDirectionsClick();    
};

/*
 *  handledirectionsclick
 *  Simple field validation & form submit
 */
ninemsn.mylocal.util.handleDirectionsClick = function()
{
    var street = document.getElementById('text_street');
    if (!street.value)
        return false;
        
    var suburb = document.getElementById('text_suburb');
    if (!suburb.value)
        return false;
        
    var state = document.getElementById('list_state');
    if (!state.selectedIndex)
        return false;
        
    var postcode = document.getElementById('text_postcode');
    if (!postcode)
        return false;
    
    /*
     *  Submit the form
     */
    document.forms[0].submit();
    
    return false;   
};

/*
 *  handleTabClick & handleTabCloseClick
 *  Very basic tab control functionality, customised for the details page
 *  Need to abstract if re-use is identified.
 *  div id / class names prefixed with "option_body"
 */
ninemsn.mylocal.util.handleTabClick = function(elPanelId)
{          
    for (var i = 1; i < 4; i++)
    {
        var panel = document.getElementById("option_body" + i);
        if (i == elPanelId)
            panel.style.display = "block";
        else
            panel.style.display = "none";
    }
};

ninemsn.mylocal.util.handleTabCloseClick = function(elPanelId)
{          
    var panel = document.getElementById("option_body" + elPanelId);
    panel.style.display = "none";
};

/*
 *  ninemsn.mylocal.util.handleClearTabClick
 *  description:
 *  Occurs when a user clicks on the "clear all" tab within the scratchpad listing page
 */
ninemsn.mylocal.util.handleClearTabClick = function()
{
    try
    {
        var emptyText = document.getElementById('empty_scratch_pad');
        emptyText.style.display = 'block';
        
        var clearTab = document.getElementById('clear_all_tab');
        clearTab.style.display = 'none';
        
        var listings = document.getElementById('scratch_pad_listings');
        listings.style.display = 'none';
        
        /*
         *  Persist modification
         */
        Ninemsn.MyLocalMigration.Proxies.Proxy.DeleteScratchPadByPUIDHash(utl.getPUIDHash());
    }
    catch (ex)
    {   
        /*
         *  Write out excetions to debug panel
         */
         utl.debout("** EXCEPTION ** ninemsn.mylocal.search.handleMouseOverListing : {0}".format(ex.description));
    }
    
    return false;
};

/*
 *  handleFeebackSubmit
 *  description:
 *  captures the mouse click over the send to friend 'submit' button.
 *  wires into our proxy class
 */
ninemsn.mylocal.util.handleEmailSubmit = function()
{
    try
    {
        /*
         *  Retrieve form elements
         */
        var elName = document.getElementById("name");
        var elToEmail = document.getElementById("to_email");
        var elFromEmail = document.getElementById("from_email");
        var elMessage = document.getElementById("message");
     
        /*
         *  Test fields are not filled
         */
        if (!elName || utl.IsNullOrEmpty(elName.value)
         || !elToEmail || utl.IsNullOrEmpty(elToEmail.value)
         || !elFromEmail || utl.IsNullOrEmpty(elFromEmail.value)
         || !elToEmail.value.match(/^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/) || !elFromEmail.value.match(/^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/))   
        {
            var errorMsg = document.getElementById('error_msg');
            errorMsg.style.display = "block";
            
            return false;
        }
        
        var companyName = !utl.IsNullOrEmpty(window.g_companyName) ? window.g_companyName : "";
        var address = !utl.IsNullOrEmpty(window.g_address) ? window.g_address : "";
        var telephone = !utl.IsNullOrEmpty(window.g_telephone) ? window.g_telephone : "";
        
        Ninemsn.MyLocalMigration.Proxies.Proxy.SendToEmail(elFromEmail.value, elToEmail.value, elMessage.value, elName.value, companyName, address, telephone);
        
        document.getElementById("email_success").style.display = "block";
        document.getElementById("email_body").style.display = "none";
        document.getElementById("error_msg").style.display = "none";
    }
    catch (ex)
    {
        /*
         *  Write out excetions to debug panel
         */
        utl.debout("** EXCEPTION ** ninemsn.mylocal.util.handleEmailSubmit : {0}".format(ex.description));
    }
};


ninemsn.mylocal.util.handleAccountSubmit = function()
{
    try
    {
        /*
         *  Hide warning and success messages
         */
        document.getElementById('profile_success').style.display = "none";
        document.getElementById('email_error').style.display = "none";
    
        var elScreenName = document.getElementById(window.g_screenNameID);
        var elFirstName = document.getElementById(window.g_firstNameID);
        var elLastName = document.getElementById(window.g_lastNameID);
        var elEmail = document.getElementById(window.g_emailID);
        var elMobile = document.getElementById(window.g_mobileID);
        var elMobileService = document.getElementById(window.g_mobileServiceID);
        var elSex = document.getElementById(window.g_sexID);
        var elBirthDate = document.getElementById(window.g_birthDateID);
        var elOccupation = document.getElementById(window.g_occupationID);
        var elIncome = document.getElementById(window.g_incomeID);
        
        var elHomeAddress = document.getElementById(window.g_homeAddressID);
        var elHomeSuburb = document.getElementById(window.g_homeSuburbID);
        var elHomePostCode = document.getElementById(window.g_homePostCodeID);
        var elHomeState = document.getElementById(window.g_homeStateID);
        var elWorkAddress = document.getElementById(window.g_workAddressID);
        var elWorkSuburb = document.getElementById(window.g_workSuburbID);
        var elWorkPostCode = document.getElementById(window.g_workPostCodeID);
        var elWorkState = document.getElementById(window.g_workStateID);
        
        /*
         *  Test validity of email address
         */
        if (utl.IsNullOrEmpty(elEmail.value) || !elEmail.value.match(/^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/))
        {
            document.getElementById('email_error').style.display = "block";
            return false;
        }            
           
           
            
        /*
         *  Push data out to proxy  
         *  Ninemsn.MyLocalMigration.Proxies.Proxy.InsertCompanyRating(utl.getPUIDHash(), rating, companyId, me.ratingInsertSuccess, me.ratingInsertError);
         */
         
         //prepare callbacks
         var onSuccess = function(){
            document.getElementById('profile_success').style.display = "block";
            window.setTimeout(function(){document.getElementById('profile_success').style.display = "none";}, 8000)
            
         }
         
         var onFail = function(){
             document.getElementById('profile_success').innerText = "There was a problem. Please try again later";
             document.getElementById('profile_success').style.display = "block"
             window.setTimeout(function(){document.getElementById('profile_success').style.display = "none";}, 8000)
         }
         
         
         Ninemsn.MyLocalMigration.Proxies.Proxy.UpdateProfileByPUIDHash(utl.getPUIDHash(), 
                                                                       elEmail.value, 
                                                                       elScreenName.value, 
                                                                       elFirstName.value, 
                                                                       elLastName.value, 
                                                                       elMobile.value, 
                                                                       elMobileService.value, 
                                                                       elSex.value, 
                                                                       elBirthDate.value, 
                                                                       elOccupation.value, 
                                                                       elIncome.value, 
                                                                       elHomeAddress.value, 
                                                                       elHomeSuburb.value, 
                                                                       elHomePostCode.value, 
                                                                       elHomeState.value, 
                                                                       elWorkAddress.value, 
                                                                       elWorkSuburb.value, 
                                                                       elWorkState.value, 
                                                                       elWorkPostCode.value,
                                                                       onSuccess,
                                                                       onFail
                                                                       );

        /*
         *  display success message
         */
        //document.getElementById('profile_success').style.display = "block";
        
    }
    catch (ex)
    {
        /*
         *  Write out excetions to debug panel
         */
        utl.debout("** EXCEPTION ** ninemsn.mylocal.util.handleAccountSubmit : {0}".format(ex.description));
    }
    
    return false;
};

/*
 *  handleFeebackSubmit
 *  description:
 *  captures the mouse click over the feedback 'submit' button.
 *  wires into our proxy class
 */
ninemsn.mylocal.util.handleFeebackSubmit = function()
{    
    try
    {
        /*
         *  Retrieve form elements
         */
        var elName = document.getElementById("first_name");
        var elEmail = document.getElementById("email");
        var elCheck1 = document.getElementById("checkbox1");
        var elCheck2 = document.getElementById("checkbox2");
        var elCheck3 = document.getElementById("checkbox3");
        var elCheck4 = document.getElementById("checkbox4");
        var elFreeText = document.getElementById("freeform_text");
     
        /*
         *  Test fields are not filled
         */
        if (!elFreeText || utl.IsNullOrEmpty(elFreeText.value))   
        {
            var errorMsg = document.getElementById('error_msg');
            errorMsg.style.display = "block";
            
            return false;
        }
        
        var regarding = [];
        if (elCheck1.checked)
            regarding.push("option1");
        if (elCheck2.checked)
            regarding.push("option2");
        if (elCheck3.checked)
            regarding.push("option3");
        if (elCheck4.checked)
            regarding.push("option4");
        
        if (regarding.length < 1)
            regarding.push("None specified");
            
        Ninemsn.MyLocalMigration.Proxies.Proxy.InsertIntoFeedback(elName.value, elFreeText.value, elEmail.value, regarding.join(","));
        
        document.getElementById("left_panel").style.display = "none";
        document.getElementById("instruction").style.display = "none";
        document.getElementById("submit").style.display = "none";
        document.getElementById("helpful_links").style.display = "none";
        document.getElementById("feedback_success").style.display = "block";
    }
    catch (ex)
    { 
        /*
         *  Write out excetions to debug panel
         */
         utl.debout("** EXCEPTION ** ninemsn.mylocal.util.handleFeebackSubmit : {0}".format(ex.description));
    }    
    return false
}; 


/*
 *  Call the proxy to send to mobile phone
 *  with inline success handler
 */
ninemsn.mylocal.util.sendToMobile = function(businessName, businessPhone, mobileNumber)
{   
     var appendTo = $get("option_body2").childNodes[0];
     var loadingSpinner = ninemsn.mylocal.util.toggleLoadingSpinner(appendTo);
     
     //for testing
     //setTimeout(function(){ninemsn.mylocal.util.sendToMobileSuccess("success")}, 2000);
     
     //call the ASP.NET AJAX proxy
     Ninemsn.MyLocalMigration.Proxies.Proxy.SendToMobile(businessName, businessPhone, mobileNumber,
        function(result) {
            ninemsn.mylocal.util.sendToMobileSuccess(result, appendTo, loadingSpinner);
        }
     );
};

ninemsn.mylocal.util.sendToMobileSuccess = function(result, elParent, loadingSpinner)
{

    /*
     *  hide spinner
     */
     ninemsn.mylocal.util.toggleLoadingSpinner(elParent, loadingSpinner);
     var message;
     var allowFurtherInput = false;
            
     if (result.toString().toUpperCase().indexOf("SUCCESS") > -1)
     {
          message = "An SMS has been successfully sent to the specified mobile number.";
     }
     else if (result.toString().toUpperCase().indexOf("INVALID") > -1)
     {
          message = "Please provide a valid mobile number";
          allowFurtherInput = true;
     }
     else
     {
          message = "The SMS could not  be sent. Please try again later.";
     }            
     
     //leave only the message node unless further input allowed
     if (!allowFurtherInput)
     {
         for (i = 0; i < elParent.childNodes.length; i++)
         {
            if (elParent.childNodes[i].style)
                elParent.childNodes[i].style.display = "none";
         }
     }  
          
     var messageSpan = document.createElement('span');
     messageSpan.innerText = message;
     elParent.appendChild(messageSpan);
};

/*
 *  toggle loading spinner as the last child of
 *  the element specified in the first argument.
 *  optionally a spinner graphic URL can be supplied.
 */
ninemsn.mylocal.util.toggleLoadingSpinner = function(elParent, el, spinner)
{        
    //create an image element from the supplied URI
    var loadingSpinner = new Image();

    if (!spinner)
        loadingSpinner.src = "img/loading.gif";
    else
        loadingSpinner.src = spinner;

    if (el) 
        elParent.removeChild(el);      
    else 
        elParent.appendChild(loadingSpinner);  
        
    return loadingSpinner;    
}

ninemsn.mylocal.util.listingsPopout = function(id)
{
    try
    {
        /*
         *  Check of 
         *
         */
        if (ninemsn.mylocal.util.isSignedIn())
        {
            ninemsn.mylocal.search.navigateToPage('Details.aspx', null, id);
            return;
        }
        
        /*
         *  Retrieve popout div
         */         
        var idPrefix = "signin_popout_";
        var popoutDiv = document.getElementById(idPrefix + id);
        
        if (!popoutDiv)
            return false;
            
        /*
         *  Display the popout
         */
        popoutDiv.style.display = "block";
        
    }
    catch (ex)
    {
        /*
         *  Write out excetions to debug panel
         */
         utl.debout("** EXCEPTION ** ninemsn.mylocal.util.listingsPopout : {0}".format(ex.description));
    }
    
    return false;
};

ninemsn.mylocal.util.listingsPopin = function(id)
{
    try
    {
        /*
         *  Retrieve popout div
         */         
        var idPrefix = "signin_popout_";
        var popoutDiv = document.getElementById(idPrefix + id);
        
        if (!popoutDiv)
            return false;
            
        /*
         *  Display the popout
         */
        popoutDiv.style.display = "none";
        
    }
    catch (ex)
    {
        /*
         *  Write out excetions to debug panel
         */
         utl.debout("** EXCEPTION ** ninemsn.mylocal.util.listingsPopin : {0}".format(ex.description));
    }
    
    return false;
};

ninemsn.mylocal.util.getPUIDHash = function()
{
    var returnVal;
    try
    {
        /*
         *  Try and get the signed in puid first
         */
        returnVal = utl.readCookie("ML_PUID");
        
        if (!returnVal)
            returnVal = utl.readCookie("ML_ANON");
        
        /* ONLY HERE UNTIL WE SETUP A REAL MECHANISM FOR PUID RETREIVAL */
        //var g_PUIDHash = "5D648299AFD4366C2BA054E2DAA0DE77";

    }
    catch (ex)
    {
        /*
         *  Write out excetions to debug panel
         */
         utl.debout("** EXCEPTION ** ninemsn.mylocal.util.getPUIDHash : {0}".format(ex.description));
         returnVal = null;
    }
    
    utl.debout("Puid#: " + returnVal);
    return returnVal;
};


ninemsn.mylocal.util.isSignedIn = function()
{
    var returnVal;
    
    try
    {
        if (utl.readCookie("ML_PUID"))
            returnVal = true;
        
    }
    catch (ex)
    {
        /*
         *  Write out excetions to debug panel
         */
         utl.debout("** EXCEPTION ** ninemsn.mylocal.util.isSignedId : {0}".format(ex.description));
         returnVal = null;
    }
    
    return returnVal;
};


/*
 *  showSponsoredListings
 *  @param {element} elName : name of element to display the sponsored listings within
 *  @param {element} keyword : keyword for YSM to search with
 */
ninemsn.mylocal.util.showSponsoredListings = function(elName, keyword)
{
    try
    {
        /* 
         *  Clear Inner Text
         */
        document.getElementById(elName).innerHTML = "";
        
        /*
         *  Setup type
         */
        var ysmTypeId = ysmOrganic;
        ysmParams.keywords = keyword;    
        var ysmEnabeDefault = true;   // allow second call in YSM generator if no result is returned from the first keyword          
        
        /**
         *  if keyword is null, use the default
         */
        if (utl.IsNullOrEmpty(keyword))
        {
            ysmTypeId = ysmDefault;
            ysmEnableDefault = false; // Don't allow second call in YSM generator
            
            /*
             *  Randomise keyword
             */
            var rand = (Math.floor(Math.random() * ysmDefaultCollection.length + 1 ));
            ysmParams.keywords = ysmDefaultCollection[rand];
        }   
        
        /*
         *  Configure Search Keyword from company name
         *  Execute YSM Sponsored site if not disabled
         */        
        if(!g_disableYsm) {
            ysmParams.searchType = ysmTypeId;
            ysmParams.additionalParams = ysmSearchType;
            ysmParams.forceDefaultKeywords = ysmEnabeDefault;
            
            var ysmmylocalContextAds = new ninemsn.ysmGenerator(elName, ysmParams, ysmConfig);
            ysmmylocalContextAds.execute();
		}
        
        return false;
    }
    catch (ex)
    {
        /*
         *  Write out excetions to debug panel
         */
        utl.debout("** EXCEPTION ** ninemsn.mylocal.util.showSponsoredListings : {0}".format(ex.description));
    }
};

/********* DEBUGGER ************/

var _divDebug;
var _strDebPre = "";
  
ninemsn.mylocal.util.debout = function(str)
{	    
    /* 
     *  Allow output when document.body doesn't exist
     */
    if (!document.body)
    {
        utl.attachEventCallback(window, "onload", ninemsn.mylocal.util.debout, str);
        return false;
    }
    
    /*
     *  Always display the debug panel on dev
     *  Toggle on live
     */
    if (window.g_environment != "development" && utl.IsNullOrEmpty(ninemsn.mylocal.util.getQueryParam("debug")))
        return false;
        
    /*
     *  Allow force turn off on dev
     */
    if (window.g_environment == "development" && ninemsn.mylocal.util.getQueryParam("debug") == "false")
        return false;
        
    if (!_divDebug)  
    {
        _divDebug = document.createElement("div");
	    _divDebug.style.cssText = "display:block;z-index:100000;position:absolute;right:10px;top:5px;border:#84c2d0 1px solid;width:210px;height:400px;filter:alpha(opacity=90);moz-opacity:.90;overflow:auto;color:#005e73;font-family:Calibri;font-size:11px;font-weight:700;padding:2px 0px 0px 5px;background-color:#e8f3f6;";	
    	document.body.appendChild(_divDebug);    	
    }  
        
	str = "<div style='width:100%;word-wrap:break-word;padding-bottom:3px;'>&gt;&nbsp;" + str + "</div>";	
	utl.insertAdjacentHTML(_divDebug,"beforeend", str);
	
	return false;
};

/********* END OF DEBUGGER ************/