if (!("console" in window) || !("firebug" in console))
{
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
    "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];

    window.console = {};
    for (var i = 0; i < names.length; ++i) 
    {
        window.console[names[i]] = function () {};
    }
}
/**
 * The HPI JavaScript Library
 *
 * Created by Dean McGill on 6th October 2008
 */

/**
 * Add a comparison method to arrays.
 *
 * Example usage: 
 *
 * arrayA.compare(arrayB);
 *
 * returns true/false on match/mis-match
 **/

Ext.namespace('HPI');

Array.prototype.equals = function(testArr) {
    if (this.length != testArr.length)
    {
        return false;
    }
    for (var i = 0; i < testArr.length; i++) {
        if (this[i].compare) { 
            if (!this[i].compare(testArr[i]))
            {
                return false;
            }
        }
        if (this[i] !== testArr[i])
        {
            return false;
        }
    }
    return true;
};

HPI.VERSION = '0.10';

HPI.StringUtils = {};

/**
 * Returns true if String is empty
 */

HPI.StringUtils.isBlank = function (str)
{
	if (!HPI.StringUtils.trim(str))
	{
		return true;
	}
	else
	{
		return false;
	}

};

/**
 * Trim whitespace from start and end of string and return
 */

HPI.StringUtils.trim = function (str)
{
	return str?str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''):false;
};

/**
 * Trims a string to the specified length including an ellipsis.
 * <p>Optionally provide a length, other defaults to 35 charcaters</p>
 * @param {string} str The string to be trimmed
 * @param {number} vLength (Optional) The length of the returned string
 * @return {string} The string that is returned
 */ 
HPI.StringUtils.trimText = function(value, vLength)
{
    return Ext.util.Format.ellipsis(value, vLength!==null?vLength:35);
};

/**
* extention of EXT's version.
* replace the + sign with space in values
*/
HPI.urlDecode = function(str)
{
  str = str.replace("+", " ");
  return Ext.urlDecode(str);
};

/*
------------------------------------------
TODO: Organise properly
------------------------------------------
*/
HPI.params = HPI.urlDecode(window.location.search.substring(1));

HPI.formatNumber = function (value, decimalPlaces, currencySymbol)
{
	// default to 2 decimal places if not supplied
	decimalPlaces = (decimalPlaces === undefined ? 2 : decimalPlaces);
	currencySymbol = (currencySymbol === undefined ? "" : currencySymbol);
	
	value = Number(value).toFixed(decimalPlaces);
	
	if (value === "" || value === undefined || isNaN(value)) {
	    return "";
	}
	
	value += '';
	x = value.split('.');
	x1 = x[0];
	x2 = x.length > 1 ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
	    x1 = x1.replace(rgx, '$1' + ',' + '$2');
	}
	
	return currencySymbol + x1 + x2;
};

HPI.loadCss = function (urls) {
    if(urls && urls.length > 0)
    {
        var f = arguments.callee;
        if (!('loadedCss' in f))
        { 
             f.loadedCss = [];
        }
        var loadedCss = f.loadedCss;
        
        var headElement = document.getElementsByTagName('head')[0];
        for(i = 0; i < urls.length; i++)
        {
            var cssUrl = urls[i];
            if (!(cssUrl in loadedCss)) { // css isnt yet loaded
                var cssElem = document.createElement('link');
                cssElem.setAttribute("rel", "stylesheet");
                cssElem.setAttribute("type", "text/css");
                cssElem.setAttribute("href", cssUrl);
                headElement.appendChild(cssElem);
                loadedCss.push(cssUrl);
            }
        }
    }
};

/**
 * open the popup window for pdfs.
 *
 * @param {string} target window name for the popup to be loaded
 * @param {boolean} true to flag its a stocklist pdf, otherwise its a stock detail (silent salesman) pdf
 */
HPI.createPdfPopup = function(target, isStockList)
{
    //set the default value
    var pleaseWaitText = "Currently retrieving PDF for the vehicle....";
    
    //change the please wait text depending on the type pdf list (stocklist or stockdetails)
    if(isStockList)
    {
        pleaseWaitText = "Currently retrieving PDF for the list of vehicles....";
    }
    
    //it seems setting the windowTitle when opening causes problem in IE
    var popup = window.open("", theTarget, "width=800,height=600");
    popup.document.clear();
    popup.document.writeln("<html><head><title>Lotus PDF View</title>");
    popup.document.writeln("<link rel='stylesheet' type='text/css' href='static/css/pdfWindow.css'></link>");
    popup.document.writeln("</head><body id='pdfWindow'>");
    popup.document.writeln("<div class='pleaseWaitText'><p>" + pleaseWaitText + "</p><p>Please Wait.</p></div>");
    popup.document.writeln("<div id='progressBar'><img src=\"static/images/progressbar.gif\" id=\"progressBarImg\"/></div>");
    popup.document.writeln("<div id='closeLink'><a href='javascript:window.close();'>Close</a></div>");
    popup.document.writeln("</body></html>");
    
    //a bit of hack for IE to prevent stopping the gif animation by reloading the image.
    if(Ext.isIE)
    {
        setTimeout(function(){
            var imgSrc = popup.document.getElementById("progressBarImg").src;
            popup.document.getElementById("progressBarImg").src = "";
            popup.document.getElementById("progressBarImg").src = imgSrc; //reset
        }, 800); //the millisecond has to be bigger than the one on the submit delay.
    }
    return true;
};

/**
 *  constructs the form to pass the information for pdf creation
 *
 *  the request pdf has to be a post so that a new window can be opened with some content to be replaced
 *  by the pdf content.
 *  if the request is made by a get, the response cannot write to the output stream as the content in the new window
 *  already written and thus making the response "committed".
 *
 * @param {boolean} flag to true if its a stocklist or false for stockdetail pdf
 * @param {string} custId should be provided when stockdetails pdf or single dealer pdf is requested
 * @param {string} stockId for the pdf to be created for. null for stocklist
 */
HPI.printPdf = function(isStockList, custId, p_stockId)
{
    var stockIds = "";
    if(isStockList)
    {
        var vehicleList;
        
        //check if results are for all dealer or single dealer
        if(custId === null) //all dealer
        {
            vehicleList = HPI.ee.results.store.data.items;
            custId = ""; //This is set to blank so that the pdf application will look up the grpspon table for the data
        }
        else //single dealer
        {
            vehicleList = HPI.ee.singleDealerResults.store.data.items;
        }
        
        for(i = 0; i < vehicleList.length; i++)
        {
          stockIds += vehicleList[i].data.stockId;
          if(i < vehicleList.length - 1)
          {
            stockIds += ",";
          }
        }
    }
    else
    {
        stockIds = p_stockId;
    }

    var pdfForm = document.getElementById("pdfForm");
    var stockIdsElement = document.getElementById("pdf_stockIds");
    var custIdElement = document.getElementById("pdf_custId");
    var pdfTypeFlagElement = document.getElementById("pdf_isStockList");
    var dealerTypeElement = document.getElementById("pdf_dealerType");
    
    var dealerType =  HPI.ee.DataManager.isSingleDealer?"SINGLE":"ALL";

    //check if the pdfForm already exists
    if(!pdfForm)
    {
      pdfForm = document.createElement("form");
      stockIdsElement = document.createElement("input");
      custIdElement = document.createElement("input");
      pdfTypeFlagElement = document.createElement("input");
      dealerTypeElement = document.createElement("input");
      theTarget = "pdfWindow";
      
      pdfForm.setAttribute("target", theTarget);
      pdfForm.setAttribute("method", "post");
      pdfForm.setAttribute("id", "pdfForm");
      pdfForm.setAttribute("action", "requestPdf");
      
      stockIdsElement.setAttribute("type", "text");
      stockIdsElement.setAttribute("value", stockIds);
      stockIdsElement.setAttribute("id", "pdf_stockIds");
      stockIdsElement.setAttribute("name", "stockIds");
      
      pdfTypeFlagElement.setAttribute("type", "text");
      pdfTypeFlagElement.setAttribute("value", isStockList);
      pdfTypeFlagElement.setAttribute("id", "pdf_isStockList");
      pdfTypeFlagElement.setAttribute("name", "isStockList");

      dealerTypeElement.setAttribute("type", "text");
      dealerTypeElement.setAttribute("value", dealerType);
      dealerTypeElement.setAttribute("id", "pdf_dealerType");
      dealerTypeElement.setAttribute("name", "dealerType");
      
      custIdElement.setAttribute("type", "text");
      custIdElement.setAttribute("value", custId?custId:"");
      custIdElement.setAttribute("id", "pdf_custId");
      custIdElement.setAttribute("name", "custId");
      
      pdfForm.appendChild(stockIdsElement);
      pdfForm.appendChild(custIdElement);
      pdfForm.appendChild(pdfTypeFlagElement);
      pdfForm.appendChild(dealerTypeElement);
      pdfForm.style.display = "none";
      
      //document.getElementById("root").appendChild(pdfForm);
	  Ext.getBody().appendChild(pdfForm);

    }
    else
    {
        //reset the values to the form input fields
        stockIdsElement.setAttribute("value", stockIds);
        pdfTypeFlagElement.setAttribute("value", isStockList);
        custIdElement.setAttribute("value", custId?custId:"");
        dealerTypeElement.setAttribute("value", dealerType);
    }
    
    //if IE6, it has problem with animated gif, so refresh the image
    if(Ext.isIE)
    {
        pdfForm.onsubmit = function()
        {
            var imgSrc = document.getElementById("progressBarImg").src;
            document.getElementById("progressBarImg").src = "";
            document.getElementById("progressBarImg").src = imgSrc; //reset
        };
    }
    
    //console.log("sending values: stockIds = "+stockIdsElement.value+", custId = "+custIdElement.value+", isStockList = "+pdfTypeFlagElement.value+", dealerType = "+dealerTypeElement.value);
    
    this.createPdfPopup(theTarget, isStockList);
    
    //without timer, submit will for some reason stop the stylesheet in the new window working
    setTimeout(function(){
        pdfForm.submit();
    }, 775);
};

/** 
functions to manage cookies.
taken from: http://www.quirksmode.org/js/cookies.html
**/

/* create cookie
 *
 * @param {string} name/key of the cookie
 * @param {string} value of the cookie
 * @param {number} optional parameter to specify a number of days that the cookie should live.
 * @param {string} optional to set the url path that cookie is set against
 */
HPI.createCookie = function(name,value,days,path)
{
    var expires = "";
    if (days) {
        var date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        expires = "; expires="+date.toGMTString();
    }
    document.cookie = name+"="+value+expires+"; path=/"+path;
};

/* return the value of the cookie, if not found, return default if available 
 *
 * @param {string} name of the cookie to retrive the value for
 * @param {string} optional to define the default value to return if cookie not found
 * @return {string} value of the cookie
 */
HPI.readCookie = function(name, defaultValue)
{
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)===' ')
        {
            c = c.substring(1,c.length);
        }
        if (c.indexOf(nameEQ) === 0)
        {
            return c.substring(nameEQ.length,c.length);
        }
    }
    
    //return default value if provided (even if empty string)
    //check for null specificly as IE seems to return null if default value is an emoty string
    return defaultValue!==null?defaultValue:null;
};

/* erase cookie by setting the expiry to be minus value
 * 
 * @param {string} cookie name/key to be erased 
 */
HPI.eraseCookie = function(name) {
    createCookie(name,"",-1);
};

/**
 * imitate a:hover on buttons to swap the styles
 * 
 * @param {object} button element for the style to be applied
 * @param {boolean} if the mouse is hovered on button or out
 */
HPI.handleButtonHover = function(el, isHovered)
{
    if(!isHovered)
    {
        Ext.get(el).removeClass("hover");
    }
    else
    {
        Ext.get(el).addClass("hover");
    }
};
/**
 * global.js
 *
 * Global variables and other definitions
 *
 * @author		Dean McGill
 * @copyright 	HPI 2008 Ltd
 */

var Ext;	// the Ext namespace for Ext based components
Ext.BLANK_IMAGE_URL = 'http://' + document.domain + '/exchange/static/common/images/s.gif';

Ext.namespace('Ext.ee');
Ext.namespace('HPI.ee');

// define a custom validator for the postcode
Ext.form.VTypes.postcodeVal=/^[a-zA-Z]{1,2}(\d{1,2}|\d[a-zA-Z])(\s?\d[abd-hjlnp-uw-z]{2})$/i;
Ext.form.VTypes.postcodeMask = /[ a-zA-Z0-9]/;
Ext.form.VTypes.postcodeText = 'Must be a valid UK postcode';
Ext.form.VTypes.postcode = function(val)
{
	return Ext.form.VTypes.postcodeVal.test(val);
};

/* postcode validation with allowing prefix only entry */
Ext.form.VTypes.postcodeAllowPrefixOnlyVal = /^[a-zA-Z]{1,2}(\d{1,2}|\d[a-zA-Z])(\s?\d[abd-hjlnp-uw-z]{2})?$/i;
Ext.form.VTypes.postcodeAllowPrefixOnlyMask = /[ a-zA-Z0-9]/;
Ext.form.VTypes.postcodeAllowPrefixOnlyText = 'Must be a valid UK postcode (full or first part only).';
Ext.form.VTypes.postcodeAllowPrefixOnly = function(val)
{
    return Ext.form.VTypes.postcodeAllowPrefixOnlyVal.test(val);
};

// define a custom validator for the telephone number
Ext.form.VTypes.telephoneVal = /^[\- 0-9a-zA-Z]{6,20}$/;
Ext.form.VTypes.telephoneMask = /[\- 0-9a-zA-Z]/;
Ext.form.VTypes.telephoneText = 'Invalid telephone number entered.';
Ext.form.VTypes.telephone = function(val)
{
    return Ext.form.VTypes.telephoneVal.test(val);
};

/**
 * displays an information box in sponsor style
 */
HPI.ee.MsgInfo = {
	// show success message

	show: function (title,msg) {

		Ext.Msg.show({
			title: title,
			msg: msg,
			cls: 'msgbox',
			minWidth: 300,
			buttons: Ext.Msg.OK
		});
	},

	hide: function () {
		Ext.Msg.hide();
	}
};

/**
 * displays an error box in sponsor style
 */
HPI.ee.MsgError = {

	show: function (title,msg) {

		Ext.Msg.show({
			title: title,
			msg: msg,
			cls: 'msgbox',
			minWidth: 300,
			icon: Ext.Msg.ERROR,
			buttons: Ext.Msg.OK
		});
	},

	hide: function () {
		Ext.Msg.hide();
	}
};
/**
 * HPI.ee.Template
 *
 * A collection of templates used throughout the application.
 *
 * @author  Dean McGill
 */

HPI.ee.Template = {


/**
 * Template config objects for the search matrix north region
 */
    backFromAdvertConfig: {
        compareNavigation : [
            {text: 'Back To Compare', action: 'HPI.ee.Action.showCompare(true)'},
            {text: 'New Search', action: 'HPI.ee.Action.newSearch()'}
        ],
        normalNavigation : [
            {text: 'Back To Results', action: 'HPI.ee.Action.showResults()'},
            {text: 'New Search', action: 'HPI.ee.Action.newSearch()'}
        ]
    },

    northConfigMatrix: {
        title: 'Used Car Search',
        introText: 'To begin the search for your perfect Lotus - input your postcode, select which models you are interested in, and use the refine panel to narrow down results.',
        leadGen: [
            {text: 'find me a vehicle',url: 'HPI.ee.FindVehicleForm.init(\'SEARCH\');'}
        ],
        navigation: [
            {text: 'View Results', action: 'HPI.ee.Action.viewResults()'}
        ]
    },
/**
 * Template config objects for the results page north region
 */
    northConfigResults: {
        title: 'Search Results',
        introText: 'Click on a car to see more information. You can narrow your selection further by using the refine panel. You can also compare up to 3 vehicles.',
        leadGen: [
            {text: 'find me a vehicle',url: 'HPI.ee.FindVehicleForm.init(\'RESULTS\');'},
            {text: 'printable version', url: 'HPI.printPdf(true, null);'} 
        ],
        navigation: [
            {text: 'New Search', action: 'HPI.ee.Action.newSearch()', cls: 'submit'},
            {text: 'Compare', action: 'HPI.ee.CompareHandler.show(HPI.ee.results.store.reader.jsonData.resultId)', cls: 'submit'}
        ]
    },
/**
 * Template config objects for the compare page north region for all dealer compare
 */
    northConfigCompareAllDealer: {
        title: 'Compare Vehicles',
        introText: 'Compare up to 3 vehicles by viewing the models below. You can see a car in more detail by selecting the car you are interested in.',
        leadGen: [
            {text: 'find me a vehicle',url: 'HPI.ee.FindVehicleForm.init(\'COMPARE\');'}
        ],
        navigation: [
            {text: 'Back To Results', action: 'HPI.ee.Action.showResults()', cls: 'submit'}
        ]
    },
           
/**
 * Template config objects for the compare page north region for single dealer compare
 */
    northConfigCompareSingleDealer: {
        title: 'Compare Vehicles',
        introText: 'Compare up to 3 vehicles by viewing the models below. You can see a car in more detail by selecting the car you are interested in.',
        leadGen: [
            {text: 'find me a vehicle',url: 'HPI.ee.FindVehicleForm.init(\'COMPARE\');'}
        ],
        navigation: [
            {text: 'Back To Dealer', action: 'HPI.ee.Action.showSingleDealerResults()', cls: 'submit'}
        ]
    },

/**
 * Template config objects for the single dealer results page north region
 */         
    northConfigSingleDealer: {
        title: 'Dealer Stock',
        introText: 'Click on a car to see more information. You can narrow your selection further by using the refine panel. You can also compare up to 3 vehicles.',
        leadGen: [
            {text: 'find me a vehicle',url: 'HPI.ee.FindVehicleForm.init(\'SINGLEDEALER\');'}
        ],
        navigation: [
            {text: 'New Search', action: 'HPI.ee.Action.newSearch()'},
            {text: 'Back To Results', action: 'HPI.ee.Action.showResults(true)'}
        ]
    },
    
/**
 * HPI.ee.ModelMatrix
 * Template for the dataview nodes of the modelMatrix
 */
    modelMatrixNodeTpl : new Ext.XTemplate(
        '<tpl for=".">',
            '<div class="matrix-node',
                '<tpl if="count == 0">',
                    ' fade20',
                '</tpl>',
            '">',
                '<div class="matrix-node-inner">',
                    '<img src="/exchange/'+HPI.properties.sponsor+'/static/images/models/{image}"/><br/>',
                    '<em>{description}</em><br/>',
                    '<em class="stock">Vehicles in stock ',
                        '<tpl if="count &lt;'+HPI.properties.app.countCap+'">',
                            '{count}',
                        '</tpl>',
                        '<tpl if="count &gt;='+HPI.properties.app.countCap+'">',
                            HPI.properties.app.countCap+'+',
                        '</tpl>',
                    '</em>',
                '</div>',
            '</div>',
        '</tpl>').compile(),

/**
 * Vehicle blurb template for the matrix page
 */
    modelMatrixBlurbTpl : new Ext.XTemplate(
        '<h2>{description}</h2>',
        '<p>{blurb}</p>').compile(),

/**
 * Template for the north region of the pages.
 */
    northPanelTpl: new Ext.XTemplate(
        '<div class="title">',
            '<h1>{title}</h1>',
            '<tpl if="[values.leadGen.length] &gt; 0">',
                '<ul class="lg">',
                '<tpl for="leadGen">',
                    '<li><a href="javascript:{url}" class="{cls}">{text}</a></li>',
                '</tpl>',
                '</ul>',
            '</tpl>',
        '</div>',
        '<div class="introText">',
            '<p>{introText}</p>',
        '</div>',
        '<div id="topNavigation">',
            '<tpl if="[values.navigation.length] &gt; 0">',
                '<ul>',
                    '<tpl for="navigation">',
                        '<li><button onclick="{action}" class="submit" onMouseOver="HPI.handleButtonHover(this, true)" onMouseOut="HPI.handleButtonHover(this, false)">{text}</button></li>',
                    '</tpl>',
                '</ul>',
            '</tpl>',
        '</div>').compile(),

/**
 * Template for the north region of the ***Advert*** pages
 */

    northAdvertPanelTpl : new Ext.XTemplate(
        '<div class="introText">',
            '<h3>{values.vehicle.description}</h3>',
            '<div>',
                '<h3 class="right" >{[HPI.formatNumber(values.vehicle.price,0,"&pound;")]}</h3>',
            '</div>',
            '<tpl if="values.vehicle.specialCode">',
                '<div class="special">{[HPI.ee.Template.getSpecialDisplay(values.vehicle.specialCode, values.vehicle.specialDate)]}</div>',
            '</tpl>',
        '</div>').compile(),

    advertNavigationPanelTpl: new Ext.XTemplate(
        '<tpl if="values.type == \'compare\'">',
            '<tpl if="[values.compareNavigation.length] &gt; 0">',
                '<ul class="navigation">',
                    '<tpl for="compareNavigation">',
                        '<li><button class="submit" onclick="{action}" onMouseOver="HPI.handleButtonHover(this, true)" onMouseOut="HPI.handleButtonHover(this, false)">{text}</button></li>',
                    '</tpl>',
                '</ul>',
            '</tpl>',
        '</tpl>',
        '<tpl if="values.type == \'advert\'">',
            '<tpl if="[values.normalNavigation.length] &gt; 0">',
                '<ul class="navigation">',
                    '<tpl for="normalNavigation">',
                        '<li><button class="submit" onclick="{action}" onMouseOver="HPI.handleButtonHover(this, true)" onMouseOut="HPI.handleButtonHover(this, false)">{text}</button></li>',
                    '</tpl>',
                '</ul>',
            '</tpl>',
        '</tpl>').compile(),

    westAdvertPanelTpl : new Ext.XTemplate(
        '<div class="title">',
            '<h1>{title}</h1>',
            '<ul class="lg">',
                '<li><a href="javascript:HPI.ee.FindVehicleForm.init(\'VIEW\');">find me a vehicle</a></li>',
                '<tpl if="values.vehicle.custId">',
                    '<li><a href="javascript:HPI.ee.BookTestDrive.init();">book a test drive</a></li>',
                    '<li><a href="javascript:HPI.ee.EmailFriend.init();">email a friend</a></li>',
                '</tpl>',    
            '</ul>',
            '<tpl if="values.vehicle.custId">',
                '<ul class="lg print">',
                    '<li class="strong"><a class="strong" href="javascript:HPI.printPdf(false, \'{values.vehicle.custId}\',{values.vehicle.stockId});">Printable Version</a></li>',
                '</ul>',
            '</tpl>',
        '</div>').compile(),

/**
 * template for the vehicle details tab of the vehicle info tab panel
 */
    advertVehicleDetailsTpl : new Ext.XTemplate(
        '<table class="vehicle-details">',
        '<tr><td class="label">Model</td><td class="value">',
        '<tpl if="values.stockDetails.model != null">',
            '{values.stockDetails.model}',
        '</tpl>',
        '<tpl if="values.stockDetails.model == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Body type</td><td class="value">',
        '<tpl if="values.stockDetails.bodyType != null">',
            '{values.stockDetails.bodyType}',
        '</tpl>',
        '<tpl if="values.stockDetails.bodyType == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Registration Date</td><td class="value">',
        '<tpl if="values.stockDetails.dateOfRegistration != null">',
            '{[new Date(values.stockDetails.dateOfRegistration.time).format("jS M Y")]}',
        '</tpl>',
        '<tpl if="values.stockDetails.dateOfRegistration == null">',
            '{na}',
        '</tpl>',           
        '</td></tr>',
        '<tr><td class="label">Plate</td><td class="value">',
        '<tpl if="values.stockDetails.registrationPlateId != null">',
            '{values.stockDetails.registrationPlateId}',
        '</tpl>',
        '<tpl if="values.stockDetails.registrationPlateId == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Colour</td><td class="value">',
        '<tpl if="values.stockDetails.simpleColour != null">',
            '{values.stockDetails.simpleColour}',
        '</tpl>',
        '<tpl if="values.stockDetails.simpleColour == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Transmission</td><td class="value">',
        '<tpl if="values.stockDetails.transmissionSpeed != null">',
            '{values.stockDetails.transmissionSpeed}&nbsp;',
        '</tpl>',
        '<tpl if="values.stockDetails.transmissionType != null">',
            '{values.stockDetails.transmissionType}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Engine size</td><td class="value">',
        '<tpl if="values.stockDetails.dvlaCC != null">',
            '{values.stockDetails.dvlaCC} cc',
        '</tpl>',
        '<tpl if="values.stockDetails.dvlaCC == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Mileage</td><td class="value">',
        '<tpl if="values.stockDetails.mileage != null">',
            '{[HPI.formatNumber(values.stockDetails.mileage,0)]} miles',
        '</tpl>',
        '<tpl if="values.stockDetails.mileage == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '</table>',
        '<div class="narrative">',
        '<h3>Dealer comment on this vehicle...</h3>',
        '<tpl if="values.stockDetails.fullServiceHistory == \'M\'">',
            '<p>Full Lotus Service History</p>',
        '</tpl>',
        '<tpl if="values.stockDetails.extendedWarranty == \'Y\'">',
            '<p>Extended Warranty</p>',
        '</tpl>',
        '<p>',
        '<tpl if="narrative == \'\'">',
            'Call us today to book a test drive for this car. We would be delighted to also let you know about the wide range of other services available from us, with competitive offers on finance, warranty and aftersales care',
        '</tpl>',
        '<tpl if="narrative != \'\'">',
          '{narrative}',
        '</tpl>',
        '</p>',
        '</div>').compile(),

/**
 * template for the dealer details panel on the advert page
 */
    advertDealerDetailsTpl : new Ext.XTemplate(
        '<div class="detail">',
            '<h3>{[values.contactDetails.company]}</h3>',
            '<p class="address">',
            '<tpl if="[values.contactDetails.address1] != \'\'">{[values.contactDetails.address1]}, </tpl>',
            '<tpl if="[values.contactDetails.address2] != \'\'">{[values.contactDetails.address2]}, </tpl>',
            '<tpl if="[values.contactDetails.address3] != \'\'">{[values.contactDetails.address3]}, </tpl>',
            '<tpl if="[values.contactDetails.address4] != \'\'">{[values.contactDetails.address4]}, </tpl>',
            '<tpl if="[values.contactDetails.town]">{[values.contactDetails.town]}, </tpl>',
            '<tpl if="[values.contactDetails.county]">{[values.contactDetails.county]}. </tpl>',
            '<tpl if="[values.contactDetails.postcodePrefix]">{[values.contactDetails.postcodePrefix]} {[values.contactDetails.postcodeSuffix]}</tpl>',
            '</p>',
            '<table>',
            '<tr><td class="label">tel:<td><td class="value">{[values.contactDetails.telephone]}</td></tr>',
            '<tr><td class="label">email:<td><td class="value"><a href="mailto:{[values.contactDetails.email]}">{[values.contactDetails.email]}</a></td></tr>',
            '<tr><td class="label">web:<td><td class="value"><a href="{[values.contactDetails.convertedWebSiteAddress]}" target="_blank">{[values.contactDetails.webSiteAddress]}</a></td></tr>',
            '</table>',
            '<p class="dealer-stock">',
                '<a href="javascript:',
                '<tpl if="!values.isSingleDealer">',
                    'HPI.ee.Action.getSingleDealerResults({[values.resultId]},\'{[values.stockDetails.custId]}\')">view all stock for this dealer',
                '</tpl>',
                '<tpl if="values.isSingleDealer">',
                    'HPI.ee.Action.showSingleDealerResults()">back to dealer\'s stock',
                '</tpl>',
                '</a>',
            '</p>').compile(),
/**
 * template for the vehicle equipment tab of the vehicle info tab panel
 */
    advertVehicleEquipmentTpl : new Ext.XTemplate(
        '<div class="equipment">',
            '<h3>Standard equipment with this vehicle:</h3>',
            '<tpl if="[values.standardEquipment.list.length] == 0">',
                '<p class="na">',
                    '{na}',
                '</p>',
            '</tpl>',
            '<tpl if="[values.standardEquipment.list.length] &gt; 0">',
                '<ul>',
                '<tpl for="standardEquipment.list">',
                    '<li>{optionDescription}</li>',
                '</tpl>',
                '</ul>',
            '</tpl>',
            '<h3>Optional equipment with this vehicle:</h3>',
            '<tpl if="[values.optionalEquipment.list.length] == 0">',
                '<p class="na">',
                    '{na}',
                '</p>',
            '</tpl>',
            '<tpl if="[values.optionalEquipment.list.length] &gt; 0">',
                '<ul>',
                '<tpl for="optionalEquipment.list">',
                    '<li>{optionDescription}</li>',
                '</tpl>',
                '</ul>',
            '</tpl>',
        '</div>').compile(),

/**
 * template for the technical data tab of the vehicle info tab panel
 */
    advertVehicleTechnicalDataTpl : new Ext.XTemplate(
        '<table class="technical-data">',
        '<tr><td class="label">Interior Colour</td><td class="value">',
        // interior colour
        '<tpl if="interiorColour != null">',
            '{interiorColour}',
        '</tpl>',
        '<tpl if="interiorColour == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Interior Trim</td><td class="value">',
        // interior trim
        '<tpl if="interiorTrim != null">',
            '{interiorTrim}',
        '</tpl>',
        '<tpl if="interiorTrim == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Insurance Group</td><td class="value">',
        // insurance group
        '<tpl if="insuranceGroup != null">',
            '{insuranceGroup}',
        '</tpl>',
        '<tpl if="insuranceGroup == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">VED Band</td><td class="value">',
        // VED
        '<tpl if="vehicleExciseBand != null">',
            '{vehicleExciseBand}',
        '</tpl>',
        '<tpl if="vehicleExciseBand == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">MOT Expiry Date</td><td class="value">',
        // mot expiry date
        '<tpl if="motExpiryDate != null">',
            '{[new Date(values.motExpiryDate.time).format("jS M Y")]}',
        '</tpl>',
        '<tpl if="motExpiryDate == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Service Interval</td><td class="value">',
        // service mileage
        '<tpl if="averageServiceMileage != null">',
            '{averageServiceMileage}',
        '</tpl>',
        '<tpl if="averageServiceMileage == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Top Speed</td><td class="value">',
        // top speed
        '<tpl if="topSpeed != null">',
            '{topSpeed} mph',
        '</tpl>',
        '<tpl if="topSpeed == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">0-60</td><td class="value">',
        // zero to sixty
        '<tpl if="zeroToSixty != null">',
            '{[HPI.formatNumber(values.zeroToSixty,1)]} secs',
        '</tpl>',
        '<tpl if="zeroToSixty == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Urban MPG</td><td class="value">',
        // urban mpg
        '<tpl if="urbanMpg != null">',
            '{[HPI.formatNumber(values.urbanMpg,0)]}',
        '</tpl>',
        '<tpl if="urbanMpg == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Extra-urban MPG</td><td class="value">',
        // extra urban mpg
        '<tpl if="extraUrbanMpg != null">',
            '{[HPI.formatNumber(values.extraUrbanMpg,0)]}',
        '</tpl>',
        '<tpl if="extraUrbanMpg == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Combined MPG</td><td class="value">',
        // combined mpg
        '<tpl if="combinedMpg != null">',
            '{[HPI.formatNumber(values.combinedMpg,0)]}',
        '</tpl>',
        '<tpl if="combinedMpg == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">CO<sub>2</sub> Emissions</td><td class="value">',
        // co2 rate
        '<tpl if="co2Rate != null">',
            '{co2Rate} g/km',
        '</tpl>',
        '<tpl if="co2Rate == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Horse Power</td><td class="value">',
        // horse power
        '<tpl if="horsePower != null">',
            '{horsePower} bhp',
        '</tpl>',
        '<tpl if="horsePower == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Kerb Weight</td><td class="value">',
        // kerb weight
        '<tpl if="kerbWeight != null">',
            '{kerbWeight} kg',
        '</tpl>',
        '<tpl if="kerbWeight == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Vehicle Length</td><td class="value">',
        // vehicle length
        '<tpl if="vehicleLength != null">',
            '{vehicleLength} mm',
        '</tpl>',
        '<tpl if="vehicleLength == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '<tr><td class="label">Vehicle Width</td><td class="value">',
        // vehicle width
        '<tpl if="vehicleWidth != null">',
            '{vehicleWidth} mm',
        '</tpl>',
        '<tpl if="vehicleWidth == null">',
            '{na}',
        '</tpl>',
        '</td></tr>',
        '</table>').compile(),

/**
 * Vehicle advert paging toolbar
 */
    advertPagingToolbarTpl : new Ext.XTemplate(
        '<table><tr><td class="first">',
        '<tpl if="values.dto.firstAdvertId == 0">',
            '<span class="disabled">',
                'first vehicle',
            '</span>',
        '</tpl>',
        '<tpl if="values.dto.firstAdvertId != 0">',
            '<a class="page-first" href="javascript:HPI.ee.Action.showAdvert({stockId: {values.dto.firstAdvertId}, resultId: {values.dto.resultId}})">',
                'first vehicle',
            '</a>',
        '</tpl>',
        '</td><td class="previous">',
        '<tpl if="values.dto.previousAdvertId == 0">',
            '<span class="disabled">',
                'previous vehicle',
            '</span>',
        '</tpl>',
        '<tpl if="values.dto.previousAdvertId != 0">',
            '<a class="page-previous" href="javascript:HPI.ee.Action.showAdvert({stockId: {values.dto.previousAdvertId}, resultId: {values.dto.resultId}})">',
                'previous vehicle',
            '</a>',
        '</tpl>',
        '</td><td class="next">',
        '<tpl if="values.dto.nextAdvertId == 0">',
            '<span class="disabled">',
                'next vehicle',
            '</span>',
        '</tpl>',
        '<tpl if="values.dto.nextAdvertId != 0">',
            '<a class="page-next" href="javascript:HPI.ee.Action.showAdvert({stockId: {values.dto.nextAdvertId}, resultId: {values.dto.resultId}})">',
                'next vehicle',
            '</a>',
        '</tpl>',
        '</td><td class="last">',
        '<tpl if="values.dto.lastAdvertId == 0">',
            '<span class="disabled">',
                'last vehicle',
            '</span>',
        '</tpl>',
        '<tpl if="values.dto.lastAdvertId != 0">',
            '<a class="page-last" href="javascript:HPI.ee.Action.showAdvert({stockId: {values.dto.lastAdvertId}, resultId: {values.dto.resultId}})">',
                'last vehicle',
            '</a>',
        '</tpl>',
        '</td></tr></table>').compile(),
/**
 * Vehicle advert paging toolbar for compare
 */
    advertComparePagingTpl : new Ext.XTemplate(
        '<div class="vehicle-navigation-compare">',
            '<ul>',
                '<tpl for="values.navigationData">',
                      '<tpl if="parent.current==xindex">',
                            '<li class="current-compare">{#}</li>',
                       '</tpl>',
                       '<tpl if="parent.current!=xindex">',
                            '<li><a class="next-compare" href="javascript:HPI.ee.Action.showAdvert({stockId: {values.stockId}, resultId: {values.resultId}, isCompareAdvert: true})">{#}</a></li>',
                       '</tpl>',
                '</tpl>',
            '</ul>',
        '</div>').compile(),
/**
 * template for results grid body row
 */
    resultsRowBodyTpl : new Ext.XTemplate(
        '<div class="plate">{registrationPlateId}</div>',
        '<div class="special">{[HPI.ee.Template.getSpecialDisplay(values.specialCode, values.specialDate)]}</div>',
        '<div class="colour">{[Ext.util.Format.ellipsis(values.colourDesc,30)]}</div>',
        '<div class="drive">{[Ext.util.Format.ellipsis(values.transmissionSpeed +" "+ values.transmissionType + " " +values.dvlaCC + " cc",25)]}</div>',
        '<div class="compare" style="position:relative;padding-top:7px;">',
        '<input id="compare{stockId}" type="checkbox" name="compare" value="{stockId}" ',
        'onclick="javascript:HPI.ee.CompareHandler.action({stockId},{resultId})"/>',
        '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
        '<a onclick="javascript: HPI.ee.CompareHandler.show({resultId})">Compare</a></div>',
        '<div class="dealerName">{[Ext.util.Format.ellipsis(values.company,32)]}</div>',
        '<div class="dealerTel">&nbsp;<img src="static/images/tel.gif" style="width:15px;height:13px;" alt="tel"/>',
        '<em>{telephone}</em></div>').compile(),

            
/**
 * ImageZoom thumb strip template
 */
    imageZoomThumbStripTpl : new Ext.XTemplate(
        '<div>',
            '<tpl for="values">',
                '<tpl if="values.thumb">',
                    '<img class="thumb" title="{[xindex - 1]}" src="/images/{values.thumb}"/>',
                 '</tpl>',
            '</tpl>',
            '<img id="zoomclose" src="./static/images/zoom-close.gif"/>',
        '</div>').compile(),

/**
 * Application navigation
 */

    appNavigationTpl : new Ext.XTemplate(
        '<div class="navigation">',
            '<ul>',
                '<tpl for="navigation">',
                    '<li><a href="#" class="submit" onclick="{action}">{text}</a></li>',
                '</tpl>',
            '</ul>',
        '</div>').compile(),

    /**
     * Template for compare vehicles panel
     */
    compareVehiclesTpl: new Ext.XTemplate(
        '<div class="compareData">',
        '<div id="compareTop">',
            '<tpl for="data">',
                 // static header components
                '<div class="compareTopCt">',
                    '<h1 class="compareDescription">',
                    '<tpl if="vehicleAvailable">',
                        '{[Ext.util.Format.ellipsis(values.vehicleModelDescription,30)]}',
                    '</tpl>',
                    '<tpl if="!vehicleAvailable">',
                        'Not Available',
                    '</tpl>',
                    '</h1>',
                    '<div class="compareSubHeader">',
                    '<tpl if="vehicleAvailable">',
                        '<h1 class="comparePrice">{[HPI.formatNumber(values.stockDetails.price,0,"&pound;")]}</h1>',
                        '<p class="compareSpecialDisplay">{[HPI.ee.Template.getSpecialDisplay(values.stockDetails.specialDisplay, values.stockDetails.specialDisplayDate)]}</p>',
                    '</tpl>',
                    '<tpl if="!vehicleAvailable">',
                        '&nbsp;',
                    '</tpl>',
                    '</div>',
                    '<div class="clear"></div>',
                        '<div class="compareImageBorder">',
                            '<tpl if="vehicleAvailable">',
                                '<a onclick="HPI.ee.Action.showAdvert({stockId: {stockId}, resultId: {parent.resultId}, isCompareAdvert: true})">',
                                    '<tpl if="exchangeImages.list[0] != undefined">', 
                                        '<img class="compareImage" src="/images/{[values.exchangeImages.list[0].imageId]}" />',
                                    '</tpl>', 
                                    '<tpl if="exchangeImages.list[0] == undefined">', 
                                        '<img class="compareImage" src="static/images/nophoto_E.jpg" />',
                                    '</tpl>',
                                '</a>',
                            '</tpl>',
                            '<tpl if="!vehicleAvailable">',
                                '<img class="compareImage" src="static/images/nophoto_E.jpg" />',
                            '</tpl>',
                        '</div>',
                    '<ul>',
                        '<tpl if="vehicleAvailable">',
                            '<li class="compareLinks compareLinksAdvert" onclick="javascript:HPI.ee.Action.showAdvert({stockId: {stockId}, resultId: {parent.resultId}, isCompareAdvert: true})">view advert</li>',
                        '</tpl>',
                        '<li class="compareLinks compareLinksRemove" onclick="javascript:HPI.ee.CompareHandler.removeItem({[values.stockId]}, {parent.resultId})">remove vehicle</li>', 
                    '</ul>',
                '</div>', // end of top container
            '</tpl>',
        '</div>', // end of top
        
        '<div class="clear"></div>',

        '<div id="compareCenter">',
            '<tpl for="data">',
                '<div class="compareCenterCt">',
                    
                    '<div id="compareVehicleDetails">',
                        '<table>',
                            // model
                            '<tr><td class="label">Model</td><td class="value">',
                            '<tpl if="!vehicleAvailable || stockDetails.model == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.model != null">',
                                '{[HPI.StringUtils.trimText(values.stockDetails.model, 20)]}',
                            '</tpl></tpl>',
                            '</td></tr>',
                            // body
                            '<tr><td class="label">Body</td><td class="value">',
                            '<tpl if="!vehicleAvailable || stockDetails.bodyType == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.bodyType != null">',
                                '{[HPI.StringUtils.trimText(values.stockDetails.bodyType, 20)]}',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            // reg date
                            '<tr><td class="label">Reg. Date</td><td class="value">',
                            '<tpl if="!vehicleAvailable || stockDetails.dateOfRegistration == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.dateOfRegistration != null">',
                                '{[fm.date(new Date(values.stockDetails.dateOfRegistration.time), "F Y")]}',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            // plate
                            '<tr><td class="label">Plate</td><td class="value">',
                            '<tpl if="!vehicleAvailable || stockDetails.registrationPlateId == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.registrationPlateId != null">',
                                '{[values.stockDetails.registrationPlateId]}',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            // colour
                            '<tr><td class="label">Colour</td><td class="value">',
                            '<tpl if="!vehicleAvailable || stockDetails.simpleColour == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.simpleColour != null">',
                                '{[HPI.StringUtils.trimText(values.stockDetails.simpleColour, 20)]}',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            // transmission
                            '<tr><td class="label">Transmission</td><td class="value">',
                            '<tpl if="!vehicleAvailable">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.transmissionSpeed != null">',
                                '<tpl if="stockDetails.transmissionType != null">',
                                    '{[HPI.StringUtils.trimText(values.stockDetails.transmissionSpeed +" "+ values.stockDetails.transmissionType, 20)]}',
                                '</tpl>',
                                '<tpl if="stockDetails.transmissionType == null">',
                                    '{[values.stockDetails.transmissionSpeed]}',
                                '</tpl>',
                            '</tpl>',
                            '<tpl if="stockDetails.transmissionSpeed == null">',
                                '<tpl if="stockDetails.transmissionType != null">',
                                    '{[values.stockDetails.transmissionType]}',
                                '</tpl>',
                                '<tpl if="stockDetails.transmissionType == null">',
                                    '&nbsp;',
                                '</tpl>',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            // engine size
                            '<tr><td class="label">Engine Size</td><td class="value">',
                            '<tpl if="!vehicleAvailable || stockDetails.dvlaCC == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.dvlaCC != null">',
                                '{[values.stockDetails.dvlaCC]} cc',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            // mileage
                            '<tr><td class="label">Mileage</td><td class="value">',
                            '<tpl if="!vehicleAvailable || stockDetails.mileage == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.mileage != null">',
                                '{[HPI.formatNumber(values.stockDetails.mileage, 0)]} miles',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                        '</table>',
                    '</div>', // end of vehicle details

                    '<div class="compareHistoryInformation">',
                        '<tpl if="!vehicleAvailable">',
                            '&nbsp;',
                        '</tpl>',
                        '<tpl if="vehicleAvailable">',
                            '{[this.getHistoryText(values.stockDetails.numberOfPreviousKeepers, values.stockDetails.extendedWarranty, values.serviceHistoryText)]}',
                        '</tpl>',
                    '</div>',  // end of history information

                    '<div class="narrative">',
                        '<h3>Dealer comment on this vehicle...</h3>',
                        '<div class="narrativeBox">',
                            '<tpl if="!vehicleAvailable">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.narrative != \'\'">',
                                '{[values.stockDetails.narrative]}',
                            '</tpl>',
                            '<tpl if="stockDetails.narrative == \'\'">',
                                'Call us today to book a test drive for this car. We would be delighted to also let you know about the wide range of other services available from us, with competitive offers on finance, warranty and aftersales care',
                            '</tpl>',
                            '</tpl>',
                        '</div>',
                    '</div>', // end of narrative

                    '<div id="compareTechnicalDetails">',
                        '<table>',
                            '<tr><td class="label">Interior Colour</td><td class="value">',
                            // interior colour
                            '<tpl if="!vehicleAvailable || stockDetails.interiorColour == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.interiorColour != null">',
                                '{[HPI.StringUtils.trimText(values.stockDetails.interiorColour, 20)]}',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">Interior Trim</td><td class="value">',
                            // interior trim
                            '<tpl if="!vehicleAvailable || stockDetails.interiorTrim == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.interiorTrim != null">',
                                '{[HPI.StringUtils.trimText(values.stockDetails.interiorTrim, 20)]}',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">Insurance Group</td><td class="value">',
                            // insurance group
                            '<tpl if="!vehicleAvailable || stockDetails.insuranceGroup == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.insuranceGroup != null">',
                                '{[values.stockDetails.insuranceGroup]}',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">VED Band</td><td class="value">',
                            // VED
                            '<tpl if="!vehicleAvailable || stockDetails.vehicleExciseBand == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.vehicleExciseBand != null">',
                                '{[values.stockDetails.vehicleExciseBand]}',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">MOT Expiry Date</td><td class="value">',
                            // mot expiry date
                            '<tpl if="!vehicleAvailable || stockDetails.motExpiryDate == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.motExpiryDate != null">',
                                '{[new Date(values.stockDetails.motExpiryDate.time).format("jS M Y")]}',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">Service Interval</td><td class="value">',
                            // service mileage
                            '<tpl if="!vehicleAvailable || stockDetails.averageServiceMileage == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.averageServiceMileage != null">',
                                '{[HPI.StringUtils.trimText(values.stockDetails.averageServiceMileage, 20)]}',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">Top Speed</td><td class="value">',
                            // top speed
                            '<tpl if="!vehicleAvailable || stockDetails.topSpeed == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.topSpeed != null">',
                                '{[values.stockDetails.topSpeed]} mph',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">0-60</td><td class="value">',
                            // zero to sixty
                            '<tpl if="!vehicleAvailable || stockDetails.zeroToSixty == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.zeroToSixty != null">',
                                '{[HPI.formatNumber(values.stockDetails.zeroToSixty,1)]} secs',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">Urban MPG</td><td class="value">',
                            // urban mpg
                            '<tpl if="!vehicleAvailable || stockDetails.urbanMpg == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.urbanMpg != null">',
                                '{[HPI.formatNumber(values.stockDetails.urbanMpg,0)]}',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">Extra-urban MPG</td><td class="value">',
                            // extra urban mpg
                            '<tpl if="!vehicleAvailable || stockDetails.extraUrbanMpg == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.extraUrbanMpg != null">',
                                '{[HPI.formatNumber(values.stockDetails.extraUrbanMpg,0)]}',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">Combined MPG</td><td class="value">',
                            // combined mpg
                            '<tpl if="!vehicleAvailable || stockDetails.combinedMpg == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.combinedMpg != null">',
                                '{[HPI.formatNumber(values.stockDetails.combinedMpg,0)]}',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">CO<sub>2</sub> Emissions</td><td class="value">',
                            // co2 rate
                            '<tpl if="!vehicleAvailable || stockDetails.co2Rate == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.co2Rate != null">',
                                '{[values.stockDetails.co2Rate]} g/km',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">Horse Power</td><td class="value">',
                            // horse power
                            '<tpl if="!vehicleAvailable || stockDetails.horsePower == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.horsePower != null">',
                                '{[values.stockDetails.horsePower]} bhp',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">Kerb Weight</td><td class="value">',
                            // kerb weight
                            '<tpl if="!vehicleAvailable || stockDetails.kerbWeight == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.kerbWeight != null">',
                                '{[values.stockDetails.kerbWeight]} kg',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">Vehicle Length</td><td class="value">',
                            // vehicle length
                            '<tpl if="!vehicleAvailable || stockDetails.vehicleLength == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.vehicleLength != null">',
                                '{[values.stockDetails.vehicleLength]} mm',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                            '<tr><td class="label">Vehicle Width</td><td class="value">',
                            // vehicle width
                            '<tpl if="!vehicleAvailable || stockDetails.vehicleWidth == null">',
                                '&nbsp;',
                            '</tpl>',
                            '<tpl if="vehicleAvailable">',
                            '<tpl if="stockDetails.vehicleWidth != null">',
                                '{[values.stockDetails.vehicleWidth]} mm',
                            '</tpl>',
                            '</tpl>',
                            '</td></tr>',
                        '</table>',
                    '</div>', // end of technical details
                '</div>', // end of compare center data container
            '</tpl>', // end of compare data objects loop
        '</div>', // end of compare center  
        '<div id="compareFooter">',
            '<tpl for="data">', // end of compare data objects loop
                '<div class="compareFooterCt"></div>',  // footer to contain border graphic
            '</tpl>', // end of compare data objects loop
        '</div>',
        '</div>',
        {       
            /**
             * Used in template to derive history information text
             * 
             * @param {Object} previousKeepers
             * @param {Object} extendedWarranty
             * @param {Object} serviceHistory
             */
            getHistoryText: function(previousKeepers, extendedWarranty, serviceHistory) {
                                
                var separator = "";
            
                var historyText = "";
                
                if (previousKeepers !== "")
                {
                    historyText = (1+parseInt(previousKeepers,0))+ " Registered Keeper" + (parseInt(previousKeepers,0)===0?"":"s");
                    separator = ". ";
                }

                if (extendedWarranty=="Y")
                {
                    historyText = historyText + separator + "Extended Warranty";
                    separator = ". ";
                }

                if (serviceHistory !== "")
                {
                    historyText = historyText + separator + serviceHistory;
                    separator = ". ";
                }

                return historyText + separator;
            }
        }).compile(),

            /**
 * Results grid image cell
 */

    resultsImageCellTpl : new Ext.XTemplate(
        '<a onclick="javascript:HPI.ee.Action.showAdvert({stockId: {stockId},resultId: {resultId}})">',
            '<tpl if="!HPI.StringUtils.isBlank(values.imageUrl)">',
                '<img title="{description}" class="timg" src="/images/{imageUrl}"/>',
            '</tpl>',
            '<tpl if="HPI.StringUtils.isBlank(values.imageUrl)">',
                '<img title="No Image Available" class="timg" src="{HPI.properties.noimage.thumbnail}"/>',
            '</tpl>',
        '</a>').compile(),
    /**
     * Used in template to derive special display text
     * 
     * @param {Object} code
     * @param {Object} date
     */
    getSpecialDisplay: function(code, date){
        switch (code) {
            case 'S':
                return 'Privileged Purchase';
            case 'C':
                if (date === null)
                {
                    return 'Due in soon - call us';
                }
                var due = new Date(date.time);
                var today = new Date();
                // we only want the date, not the time
                today.setMilliseconds(0);
                today.setSeconds(0);
                today.setMinutes(0);
                today.setHours(0);
                if (due.getTime() > today.getTime())
                {
                    // date in the future
                    return 'Due in ' + due.format('d/m/y') + ' - call us';
                }
                return '';
            default: 
                return '';
        }
    },

/**
 * ImageZoom thumb strip template
 */
    imageZoomThumbStripTpl : new Ext.XTemplate(
        '<div id="filmstrip">',
            '<tpl for="values.content">',
                '<img class="thumb" rel="{[xindex - 1]}" src="{.}"/>',
            '</tpl>',
            '<img id="zoomclose" src="static/images/zoom-close.gif" />',
        '</div>').compile(),

/**
 * main zoom image template
 */
    imageZoomTpl : new Ext.XTemplate(
        '<img id="zoomimage" src="{values.imageUrl}"/>').compile(),

/**
 * zoom title template
 */
    imageZoomTitleTpl : new Ext.XTemplate(
        '{values.zoomTitle}').compile()

};
/**
 * HPI.ee.Action
 *
 * @author    Dean McGill
 *
 * This action class can be thought of as the application controller. It is responsible for
 * handling the application navigation, resizing viewport regions and updating XTemplates
 * where applicable.
 */

HPI.ee.Action = {

	/**
	 * Default serach options and show matrix search page
	 *
	 */		
	newSearch: function() {
        HPI.ee.viewport.layout.setActiveItem(HPI.ee.SEARCH_MATRIX_VIEW);

		this.resetSearchCriteria();

		// reset starting page, and results per page values
        HPI.params.start = 0;
        HPI.params.limit = 5;
        
        // reset all dealer results sort order
        HPI.ee.DataManager.stores.allDealerStore.sortInfo = {
            field: 'distance',
            direction: 'ASC'
        };

        // reset single dealer results sort order
        HPI.ee.DataManager.stores.singleDealerStore.sortInfo = {
            field: 'price',
            direction: 'ASC'
        };
       
		HPI.ee.matrixRefine.reset();
		HPI.ee.resultsRefine.reset();

        HPI.ee.Action.doStoreUpdate(HPI.params);
	},

	/**
	 * Resets the matrix page for a new search
	 *
	 */		
	resetSearchCriteria: function() {
		for (var param in HPI.params) {
			if (param !== 'postcode') {
				delete HPI.params[param];
			}
		}

		// reset model matrix
		for (var i=0 ; i<HPI.ee.matrix.store.getCount() ; i++ )	{
			HPI.ee.matrix.deselect(i,0,true);
		}
	},
	
	/**
	 * 
	 * An action to display the *multi* dealer results page
     * for the view result button in matrix search page
	 */
	viewResults : function ()
	{
        // postcode check
		if (!HPI.params.postcode || !HPI.ee.matrixRefine.postcodeText.isValid()) {
			HPI.ee.PostcodePopup.init(HPI.ee.matrixRefine.postcodeText.getValue());
			return false;
		}

        HPI.ee.matrixRefine.synchronise(HPI.ee.resultsRefine);
        
        var postcodeVal = HPI.ee.matrixRefine.postcodeText.getValue().replace(" ","");
        HPI.createCookie(HPI.properties.app.postcodeCookieKey,postcodeVal,30,"exchange");

        this.showResults();
		
	},
    
    /**
     * simply display the result page by activating the panel
     **/
    showResults: function()
    {
        //set the single dealer flag
        HPI.ee.DataManager.isSingleDealer = false;

        // write transaction for the current view (as future transaction are fired when the store updates);
        HPI.ee.Transaction.writeResultTransaction(HPI.ee.results.store);

        HPI.ee.viewport.layout.setActiveItem(HPI.ee.RESULTS_ALL_VIEW);
        HPI.ee.CompareHandler.markItems();
    },

	/**
	 *
	 * @param resultId {number}
	 * @param custId   {string}
	 *
	 * Show the single dealer results page. Initially constructed with an empty results grid on entry to the site.  
	 * The result grid is populated by updating the parameters and reloading data of the underlying store.
	 */
	getSingleDealerResults : function (resultId, custId)
	{
		this.showSingleDealerResults(false);
        //add pdf link to the result dealer north config
        Ext.apply(HPI.ee.Template.northConfigSingleDealer.leadGen,
                  [{text: 'find me a vehicle',url: 'HPI.ee.FindVehicleForm.init(\'SINGLEDEALER\');'},
                   {text: 'printable version', url: 'HPI.printPdf(true, \''+custId+'\');'}]);
        HPI.ee.Template.northPanelTpl.overwrite(Ext.getCmp("singleDealerResults-north").body, HPI.ee.Template.northConfigSingleDealer);
        
        HPI.ee.singleDealerResults.params.custId = custId;	
		HPI.ee.singleDealerResults.params.dealerType = 'single';
		HPI.ee.singleDealerResults.params.start = 0;
		HPI.ee.singleDealerResults.params.limit = 5;
		HPI.ee.singleDealerResults.fireEvent('storeupdate', {resultId: resultId, custId: custId,dealerType:'single',start:0, limit:5});
	},

    /**
     * displays singledealer result screen
     */
    showSingleDealerResults: function(writeTransaction)
    {
        HPI.ee.CompareHandler.markItems();
        HPI.ee.viewport.layout.setActiveItem(HPI.ee.RESULTS_SINGLE_VIEW);
        
        if(writeTransaction !== false)
        {
            // write transaction for the current view (as future transaction are fired when the store updates);
            HPI.ee.Transaction.writeResultTransaction(HPI.ee.singleDealerResults.store);
        }
        //set the single dealer flag
        HPI.ee.DataManager.isSingleDealer = true;
        
        HPI.ee.viewport.doLayout();
    },

	/**
	 * @name showAdvert
	 * @memberOf HPI.ee.Action
	 * @description Show the static advert panel view.
     * @param cfg {object} array containing info about advert
	 */  
	showAdvert : function (cfg) 
	{
		HPI.ee.defaultMask.show();

		/**
		 * Accept either stockId & resultId or the DataManager key  TODO: make this better
		 */
		if (cfg.key)
		{
			cfg.stockId = HPI.ee.DataManager.getDTO(cfg.key).stockId;
			cfg.resultId = HPI.ee.DataManager.getDTO(cfg.key).resultId;
		}
		else
		{
			cfg.key = cfg.stockId+'-'+cfg.resultId;
		}
        
        HPI.ee.DataManager.lastViewedKey = cfg.key;

		Ext.apply(cfg, {

			/**
			 * Use the callback function to control the application
			 * when the DTO is ready, either from the DataManager or
			 * by making a new request.
			 */
			callback : function (dto) {
                HPI.ee.vehiclePanel.fireEvent('dtoready',Ext.apply(dto, {isCompareAdvert: cfg.isCompareAdvert}));
				HPI.ee.Transaction.writeTransaction(cfg.stockId,'single');
			}
		});

		/**
		 * Apply the new DTO to the advert panel.
		 */
		HPI.ee.viewport.layout.setActiveItem(HPI.ee.ADVERT_VIEW);
		HPI.ee.DataManager.applyDTO(cfg);
	},

	/**
	 * Show the compare page
	 */
	showCompare : function (suppressMask)
	{
		HPI.ee.viewport.layout.setActiveItem(HPI.ee.COMPARE_VIEW);

		if (true !== suppressMask)
		{
			HPI.ee.defaultMask.show();
		}
		
	},

	/**
	 * A helper method to trigger the store updates on the various components. Should be
	 * called whenever the filter parameters are changed.
     * 
     * @param params {object} array that contains parameters for ajax calls
     * @param combo {object} optional element passed in for combo boxes
     * @param suppressMask {boolean} flag to either suppress showing the default mask
     * @param callbackFunction {object} function object to call callback when the matrix count ajax is done
	 */
	doStoreUpdate : function (params,combo,suppressMask,matrixCountCallback, resultsCallback)
	{
		if(suppressMask !== true)
		{
			HPI.ee.defaultMask.show();
		}

		HPI.params.start = 0;
        
        //setting the ajax process complete flags to false
        HPI.ee.resultsRefine.isUpdateComplete = false;
        HPI.ee.results.isLoadComplete = false; //set the loadComplete flag to false for result grid (all dealer only) 

        Ext.getCmp('resultsGrid').fireEvent('storeupdate',{'params': params, 'callback': resultsCallback});
        
        Ext.Ajax.request({
            url: HPI.properties.urls.matrixCount, 
            method: 'GET',
            params: Ext.apply(HPI.params,{src:'matrixCount'}),
            scope: this,
            success: function(response,request) {
                var jsonData = Ext.util.JSON.decode(response.responseText);
                HPI.ee.matrix.doModelCount(jsonData);
                
				/* 
				 * The Ext framework will expand the selected combo box after 
				 * a load if we don't unset the combo box focus.  We must manually 
				 * set hasFocus to 'false'
				 */
				if (combo)
				{
					combo.hasFocus = false;
				}
				
				HPI.ee.DataManager.stores.bodyStore.loadData(jsonData.body);
				HPI.ee.DataManager.stores.transmissionStore.loadData(jsonData.transmission);
				HPI.ee.DataManager.stores.engineFromStore.loadData(jsonData.engineFrom);
				HPI.ee.DataManager.stores.engineToStore.loadData(jsonData.engineTo);

            },
            failure: function () {
                HPI.ee.MsgError.show('Problem','Sorry, your request cannot be completed at this time.');
            },
			callback: function() {

                //only set the resultsrefine to be completed as matrixrefine does not need this value
                HPI.ee.resultsRefine.isUpdateComplete = true;
                
                if(matrixCountCallback)
                {
                    matrixCountCallback();
                }
                else  if(suppressMask !== true)
				{
				    HPI.ee.defaultMask.hide();
                }
			}
        });
	}
};
/**
 * HPI.ee.BookTestDrive.js
 *
 * Book A Test Drive Form Wizard style
 *
 * 26/10/08     Pulled into sapp and moved into HPI.ee namespace
 *
 * @class   HPI.ee.BookTestDrive
 *
 * @author	Dean McGill 27th September 2008
 **/
HPI.ee.BookTestDrive = {

    init: function() {
		this.context = "VIEW"; //available only on advert
        
        //get vehicle info
        try
        {
            this.vehicleDetailsDto = HPI.ee.DataManager.getCurrentAdvert();
            this.stockId = this.vehicleDetailsDto.stockId;
            this.custId = this.vehicleDetailsDto.stockDetails.custId;
            
            this.vehicleDescription = this.vehicleDetailsDto.stockDetails.vehicleDescription;
            this.vehicleModel = this.vehicleDetailsDto.stockDetails.model;
            this.vehicleModelCode = this.vehicleDetailsDto.stockDetails.modelCode;

			this.vehiclePrice = HPI.formatNumber(this.vehicleDetailsDto.stockDetails.price, 0, '�');
			this.vehicleMileage = HPI.formatNumber(this.vehicleDetailsDto.stockDetails.mileage, 0) + ' miles';
		}
		catch (e)
		{
			this.vehicleDescription = ''; 
		}  

		this.tabform1 = {
			title: 'Personal details',
			height: 400,
			items: [{
				layout: 'form',
				labelWidth: 170,
				defaults: {
					msgTarget: 'side'
				},
				items: [{
					xtype: 'hidden',
					id: 'btdOrganisationName',
					name: HPI.properties.leadGen.paramName.organisationName
				},{
					xtype: 'hidden',
					id: 'btdCustomerAddressLine1',
					name: HPI.properties.leadGen.paramName.customerAddressLine1
				},{
					xtype: 'hidden',
					id: 'btdCustomerAddressLine2',
					name: HPI.properties.leadGen.paramName.customerAddressLine2
				},{
					xtype: 'hidden',
					id: 'btdCustomerAddressLine3',
					name: HPI.properties.leadGen.paramName.customerAddressLine3
				},{
					xtype: 'hidden',
					id: 'btdCustomerAddressLine4',
					name: HPI.properties.leadGen.paramName.customerAddressLine4
				},{
					xtype: 'hidden',
					id: 'btdCustomerAddressLine5',
					name: HPI.properties.leadGen.paramName.customerAddressLine5
				},{
					xtype: 'hidden',
					id: 'btdCustomerAddressPostTown',
					name: HPI.properties.leadGen.paramName.customerAddressPostTown
				},{
					xtype: 'hidden',
					id: 'btdCustomerAddressCounty',
					name: HPI.properties.leadGen.paramName.customerAddressCounty
				},{
					xtype: 'hidden',
					id: 'btdContext',
					name: 'context',
                    value: this.context
				},{
					xtype: 'hidden',
					id: 'btdRequiredVehicleMakeCode',
					name: HPI.properties.leadGen.paramName.vehicleMakeCode,
					value: 'BG'
				},{
					xtype: 'hidden',
					id: 'btdRequiredVehicleMake',
					name: HPI.properties.leadGen.paramName.vehicleMake,
					value: 'Lotus'
				},{
					xtype: 'hidden',
					id: 'btdRequiredVehicleModelCode',
					name: HPI.properties.leadGen.paramName.vehicleModelCode,
                    value: this.vehicleModelCode
				},{
                    xtype: 'hidden',
                    id: 'btdRequiredVehicleModel',
                    name: HPI.properties.leadGen.paramName.vehicleModel,
                    value: this.vehicleModel
                },{
					html: 'Book a test drive for ' + this.vehicleDescription + ', ' + this.vehicleMileage + ', ' + this.vehiclePrice,
					cls: 'bodytext'
				},{
					html: 'Your details',
					cls: 'subtitle'
				},{
					xtype: 'textfield',
					id: 'btdCustomerName',
					name: HPI.properties.leadGen.paramName.customerName,
					fieldLabel: 'Name',
					width: 220,
					labelSeparator: ': *',
					allowBlank: false,
					maxLength: 30
				},{
					xtype: 'textfield',
					id: 'btdCustomerEmailAddress',
					name: HPI.properties.leadGen.paramName.customerEmailAddress,
					fieldLabel: 'Email address',
					width: 220,
					allowBlank: false,
					labelSeparator: ': *',
					vtype: 'email'
				},{
					layout: 'column',
					items: [{
						columnWidth: 0.75,
						layout: 'form',
						labelWidth: 170,
						items: [{
							xtype: 'textfield',
							id: 'btdCustomerPostcode',
							msgTarget: 'side',
							name: HPI.properties.leadGen.paramName.customerAddressPostcode,
							fieldLabel: 'Postcode',
							width: 220,
							allowBlank: false,
							vtype: 'postcode',
							labelSeparator: ': *',
                            listeners: {
                                render: function()
                                {
                                    if(HPI.readCookie(HPI.properties.app.postcodeCookieKey, null) !== null)
                                    {
                                        this.value = HPI.readCookie(HPI.properties.app.postcodeCookieKey, null);
                                    }
                                },
								valid: {
									fn: function () {
										Ext.getCmp('btdAddressFinderButton').enable();
									}
								},
								invalid: {
									fn: function () {
										Ext.getCmp('btdAddressFinderButton').disable();
									}
								}
							}
						}]
					},{
						columnWidth: 0.25,
						layout: 'form',
						items: [{
							xtype: 'button',
							text: 'Find my address',
							id: 'btdAddressFinderButton',
							disabled: true,
							listeners: {
								click: {
									scope: this,
									fn: function () {
										var postcode = Ext.getCmp('btdCustomerPostcode');
										if (postcode.isValid())
										{
											HPI.ee.PafFormWidget.init(postcode.getValue(),'btd');
										}								
									}
								},
                                /**
                                 * The original Ext code suppresses to add/remove disabled style class
                                 * to elements, as IE6 seem to handle the dislabed element with its
                                 * own style that crashes with the Ext disabled item stylying.
                                 * Add them manually so that we can style them as necessary.
                                 */
                                enable: {
                                    fn: function(el) {
                                        if(Ext.isIE6)
                                        {
                                            el.removeClass("x-item-disabled");
                                        }
                                    }
                                },
                                disable: {
                                    fn: function(el) {
                                        if(Ext.isIE6)
                                        {
                                            el.addClass("x-item-disabled");
                                        }
                                    }
                                }
							}
						}]
					}]
				},{
					xtype: 'textarea',
					id: 'btdCustomerAddressPreview',
					name: 'customerAddress',
					fieldLabel: 'Address',
					disabled: true,
					width: 220,
					height: 50,
					cls: 'custAddress',
					allowBlank: false,
					emptyText: 'You can search for your address using the postcode lookup above',
					labelSeparator: ': *',
					listeners: {
						addressUpdate: {
							fn: function (ap) {
								this.setValue(ap);
								Ext.getCmp('btdAddressFinderButton').setText('Edit my address');
                                HPI.ee.BookTestDrive.win.addressFound = true;
							}
						}
					}
				},{
					xtype: 'textfield',
					id: 'btdCustomerTelephone',
					name: HPI.properties.leadGen.paramName.customerTelephone,
					fieldLabel: 'Telephone number',
					width: 220,
					allowBlank: false,
                    vtype: 'telephone',
					labelSeparator: ': *'
				},{
					html: 'Preferred contact details',
					cls: 'subtitle'
				},{
					layout: 'form',
					labelWidth: 170,
					items: [{
						xtype: 'radiogroup',
						fieldLabel: 'Method of contact',
						width: 200,
						items: [{
							boxLabel: 'Phone',
							id: 'btdPreferredContactMethodPhone',
							name: HPI.properties.leadGen.paramName.preferredContactMethod,
							inputValue: 'Telephone',
							checked: true
						},{
							boxLabel: 'Email',
							id: 'btdPreferredContactMethodEmail',
							name: HPI.properties.leadGen.paramName.preferredContactMethod,
							inputValue: 'Email',
							listeners: {
								check: {
									fn: function () {
										Ext.getCmp('btdPreferredContactDate').setDisabled(this.getValue());
										Ext.getCmp('btdPreferredContactTime').setDisabled(this.getValue());
									}
								}
							}
						}]
					},{
						layout: 'column',
						items: [{
							columnWidth: 0.5,
							layout: 'form',
							items: [{
								xtype: 'datefield',
								fieldLabel: 'Date & Time of contact',
								id: 'btdPreferredContactDate',
								name: HPI.properties.leadGen.paramName.preferredContactDate,
								width: 100,
                                editable:false
							}]
						},{
							columnWidth: 0.5,
							items: [{
								xtype: 'timefield',
								fieldLabel: '',
								labelSeparator: '',
								id: 'btdPreferredContactTime',
								name: HPI.properties.leadGen.paramName.preferredContactTime,
								width: 100,
								minValue: '9:00 AM',
								maxValue: '5:00 PM',
								increment: 30,
								forceSelection: true,
                                editable:false
							}]
						}]
					}]
				},{
					html: 'Disclaimer',
					cls: 'smalltitle'				
				},{
					html: 'The details and email address you provide will only be used by Lotus Cars Limited, Group Lotus Plc (or its affiliated or associated companies), or authorised Lotus dealers to keep you informed of new products and services, or for conducting market research. Lotus will not retain or use the details of the data entered, other than to pass to the relevant dealer or manufacturer concerned.',
					cls: 'bodyText'
				},{ 
					xtype: "hidden",
					id: "btdstockId",
					name: HPI.properties.leadGen.paramName.stockId,
					value: this.stockId
				},{ 
					xtype: "hidden",
					id: "btdcustId",
					name: HPI.properties.leadGen.paramName.custId,
					value: this.custId
				},{
					layout: 'form',
					labelWidth: 300,
					
					items: [{
						xtype: 'checkbox',
						fieldLabel: 'If you do not want your information to be used in this way please tick here',
						labelAlign: 'right',
						labelStyle: 'font-weight:normal;width:440px;line-height:18px',
						labelSeparator: ':',
                        name: HPI.properties.leadGen.paramName.marketingOption,
                        inputValue: "true"
					}]
				}]
			}]
		};

		this.tabform2 = {
			title: 'Your requirements',
			cls: 'btd-tab2',
			height: 400,
            width: 560,
			items: [{
				items: [{
					html: 'Book a test drive for ' + this.vehicleDescription + ', ' + this.vehicleMileage + ', ' + this.vehiclePrice,
					cls: 'bodytext'
				},{
					xtype: 'checkbox',
					fieldLabel: '',
					labelSeparator: '',
					boxLabel: '<b>I might be interested in other similar vehicles you have in stock</b>',
                    name: HPI.properties.leadGen.paramName.simiarVehicles,
                    inputValue: 'true'
				}]
			},{
				layout: 'form',
				labelWidth: 170,
				items: [{
					html: 'Your current vehicle',
					cls: 'subtitle',
					style: 'padding-bottom:10px'
				},{
					xtype: 'combo',
					id: 'btdCustomerMake',
					name: HPI.properties.leadGen.paramName.customerVehicleMake,
					fieldLabel: 'Vehicle make',
					width: 180,
					mode: 'remote',
					valueField: 'value',
					displayField: 'text',
					triggerAction: 'all',
                    editable: false,
					listeners: {
						select: {
							fn: function () {
								Ext.getCmp('btdCustomerModel').store.baseParams = {
										make: this.getValue(),
										type: 'allmodels'
								};
								Ext.getCmp('btdCustomerModel').store.load({
									callback: function () {
										Ext.getCmp('btdCustomerModel').enable();
										Ext.getCmp('btdCustomerModel').setValue(null);
									}
								});
							}
						}
					},
					store: new Ext.data.Store({
						baseParams: {type: 'allmakes'},
						proxy: new Ext.data.HttpProxy({
							url: '/exchange/' + HPI.properties.sponsor + '/exchangeData'
						}),
						reader: new Ext.data.JsonReader({
							root: 'make'
						}, [
							{name: 'id'},
							{name: 'value'},
							{name: 'text'}
						])
					})
				},{
					xtype: 'combo',
					id: 'btdCustomerModel',
					name: HPI.properties.leadGen.paramName.customerVehicleModel,
					fieldLabel: 'Vehicle model',
					width: 180,
					mode: 'remote',
					valueField: 'value',
					displayField: 'text',
					triggerAction: 'all',
					disabled: true,
                    editable: false,
					store: new Ext.data.Store({
						proxy: new Ext.data.HttpProxy({
							url: '/exchange/' + HPI.properties.sponsor + '/exchangeData'
						}),
						reader: new Ext.data.JsonReader({
							root: 'model'
						}, [
							{name: 'id'},
							{name: 'value'},
							{name: 'text'}
						])
					})
				}]
			},{
				html: 'Your requirements',
				cls: 'subtitle'
			},{
				html: 'Please give a description of the vehicles you are interested in',
				cls: 'bodytext',
				style: 'padding-bottom:10px;'
			},{
				xtype: 'textarea',
				width: 560,
				height: 80,
				name: HPI.properties.leadGen.paramName.vehicleOtherRequirements,
				maxLength: 250
			},{
				layout: 'form',
				labelWidth: 170,
				style: 'padding-top:10px;',
				items: [{
					xtype: 'combo',
					fieldLabel: 'Timescale for change',
					name: HPI.properties.leadGen.paramName.vehicleTimescale,
					width: 180,
					mode: 'remote',
					triggerAction: 'all',
                    editable:false,
					valueField: 'code',
					displayField: 'description',
					store: new Ext.data.JsonStore({
						url: '/exchange/lotus/remoteCombo',
						root: 'list',
						baseParams: {type: 'timescale'},
						fields: [
							{name: 'code'},
							{name: 'description'}
						]
					})
						
				}]
			}]
		};

		this.tabform3 = {
			title: 'Other Information',
			height: 400,
            width: 560,
			items: [{
				layout: 'form',
				labelWidth: 170,
				items: [{
					html: 'Book a test drive for ' + this.vehicleDescription + ', ' + this.vehicleMileage + ', ' + this.vehiclePrice,
					cls: 'bodytext'
				},{
					html: 'Other Products',
					cls: 'subtitle'
				},{
					html: 'Your local dealer may be able to save you money on finance and insurance services for your next <b>approved used vehicle</b>.',
					cls: 'bodytext',
					style: 'padding-bottom:10px;'
				},{
					xtype: 'checkbox',
					fieldLabel: 'Are you interested in',
					labelSeparator: '?',
					boxLabel: 'Insurance',
					name: HPI.properties.leadGen.paramName.otherServices,
					inputValue: 'Insurance'
				},{
					xtype: 'checkbox',
					labelSeparator: '',
					boxLabel: 'Finance',
					name: HPI.properties.leadGen.paramName.otherServices,
					inputValue: 'Finance'
				},{
					xtype: 'checkbox',
					labelSeparator: '',
					boxLabel: 'Service plan',
					name: HPI.properties.leadGen.paramName.otherServices,
					inputValue: 'Service_Plan'
				}]
			}]
		};

		this.form = new Ext.FormPanel({
			url: '/exchange/' + HPI.properties.sponsor + '/bookTestDrive',
			items: [{
				xtype: 'tabpanel',
				deferredRender: false,
                layoutOnTabChange: true,
                defaults: {hideMode: 'offsets'},
				plain: true,
				activeTab: 0,
				id :'btdTabPanel',
				tabWidth: 200,
				items: [this.tabform1,this.tabform2,this.tabform3],
                listeners: {
                    beforetabchange: {
                        scope: this,
                        fn: function(tab, newTab, currentTab) {
                            if (!this.initilised)
                            {
                                this.initilised = true;
                                return true;
                            }
                            
                            //check if the tab is loaded as window loaded, rather than the tab change
                            if(currentTab)
                            {
                              if (!this.form.getForm().isValid() || !HPI.ee.BookTestDrive.win.addressFound)
                              {
                                  if(!HPI.ee.BookTestDrive.win.addressFound)
                                  {
                                    Ext.getCmp("btdCustomerAddressPreview").markInvalid("Address has not been selected or entered. Please use \"find my address\" button to find your address by the postcode.");
                                  }
                                  Ext.get('btd_tbtext').update('Correct form errors');
                                  Ext.get('btd_tbtext').addClass('error');
                                  return false;
                              }
                              
                              Ext.get('btd_tbtext').update('');
                              Ext.get('btd_tbtext').removeClass();
                            }
                            return true;
                        }
                    }
                }
			}]
		});
			
		this.bbar = new Ext.Toolbar({
			width: 560,
			items: [{
				xtype: 'tbtext',
				text: '<span id="btd_tbtext">*&nbsp;&nbsp;mandatory field</span>',
				id: 'btdStatus'
			},{
				xtype: 'tbfill'
			},{
				xtype: 'button',
				text: 'Cancel',
				listeners: {
					click: {
						scope: this,
						fn: function () {
							this.win.close();
						}
					}
				}
			},{
				xtype: 'button',
				text: 'Submit',
				listeners: {
					click: {
						scope: this,
						fn: function () {
							if (this.form.getForm().isValid() && HPI.ee.BookTestDrive.win.addressFound)
							{
								this.submit();
							}
							else
							{
                                if(!HPI.ee.BookTestDrive.win.addressFound)
                                {
                                  Ext.getCmp("btdCustomerAddressPreview").markInvalid("No address has not been selected or entered. Please use \"find my address\" button to find your address by the postcode.");
                                }
								Ext.getCmp('btdTabPanel').setActiveTab(0);
								Ext.get('btd_tbtext').update('Correct form errors');
								Ext.get('btd_tbtext').addClass('error');
							}
						}
					}
				}
			}]
		});

        this.win = new Ext.Window({
            title: 'Book A Test Drive',
            id: "BookTestDrive",
            width: 600,
           	modal: true,
			shadow: false,
			resizable: false,
			draggable: false,
			cls: 'fl-form',
			closeAction: 'close',
			items: [this.form,this.bbar]
        });

        this.win.show();
	},

    /**
     * Handle the submission of the form data and process the server response
     */
    submit : function () {
		this.form.getForm().submit({
			scope: this,
			success: function () {
				this.win.close();
				HPI.ee.MsgInfo.show('Form Submitted','Thank you for your interest.<br/><br/>Your local dealer will be in touch.');
			},
			failure: function () {
				//this.win.close(); //should it close the original window?
				HPI.ee.MsgError.show('Problem','Sorry, your request cannot be completed at this time.');
			}
		});
    }
};
/**
 * HPI.ee.CompareHandler
 *
 * This class handles the actions of marking/unmarking vehicles to compare on the
 * results page.
 *
 * Will also make sure that any vehicles marked will persist across result paging,
 * and even across different result sets - such as between single/all dealer.<b>
 *
 * When a vehicle is marked for comparison, if the DTO is not already present in the
 * DataManager object, a request will be made for the data.
 **/

HPI.ee.CompareHandlerRunner = function ()
{

/**
 * An array of stock Ids that are currently loaded
 */
	this.keys = [];

/**
 * Maximum number of items allowed in a comparison
 */
	this.maxItems = 3;
};

Ext.extend(HPI.ee.CompareHandlerRunner, Ext.util.Observable, {
	
/**
 * Add or delete (depending on whether stock item is registered with the compare
 * handler) an item. If adding a new stock item, we load an advert panel in the
 * background so the DTO is available
 */
	action : function (stockId,resultId)
	{
    	if (this.keys.indexOf(stockId) > -1)
		{
			this.keys.splice(this.keys.indexOf(stockId),1);
		}
		else
		{
			HPI.ee.DataManager.getVehicleDTO(null,stockId,resultId);
			this.keys.push(stockId);

			if (this.keys.length > this.maxItems)
			{
				var id = this.keys.shift();
				if (Ext.fly('compare'+id))
				{
					Ext.fly('compare'+id).dom.checked = false;
				}
				
			}
		}
	},

/**
 * Call this method on a fresh set of results to mark the checkboxes if any stock
 * items are present in the compare array
 */
	markItems : function ()
	{	
		var nodes = Ext.select('input[name=compare]','resultsGrid');
		for (var i = 0 ; i < nodes.elements.length; i++ )
		{
			if (this.keys.indexOf(parseInt(nodes.elements[i].id.substring(7),10)) !== -1)
			{
				nodes.elements[i].checked = true;
			}
			else
			{
				nodes.elements[i].checked = false;
			}
		}
	},

	removeItem : function (stockId, resultId)
	{
		this.keys.splice(this.keys.indexOf(stockId),1);	
		if (this.keys.length === 0)
		{
            //go back to all or single dealer depending on where it has been before...
            if(HPI.ee.DataManager.isSingleDealer === true)
            {
			    HPI.ee.Action.showSingleDealerResults();
            }
            else
            {
                HPI.ee.Action.showResults();
            }
		}
		else
		{
			Ext.getCmp('compare').updateItems(this.keys, resultId);
		}
	},

	/**
	 * Method that will show the compare page. We check that the vehicle compare
	 * link the user clicked is actually present in the compare array. If this
	 * is not the case, the new vehicle is added.
	 */
	show : function (resultId)
	{
		if (this.keys.length === 0)
		{
			HPI.ee.MsgInfo.show('No Vehicles Selected','You have no vehicles selected to compare.  You may select up to 3 vehicles using the checkboxes provided.');
		}
		else
		{
			HPI.ee.Action.showCompare();

			Ext.getCmp('compare').updateItems(this.keys, resultId);
        
            if(HPI.ee.DataManager.isSingleDealer)
            {
                HPI.ee.Template.northPanelTpl.overwrite(Ext.getCmp("compare-north").body, HPI.ee.Template.northConfigCompareSingleDealer);
            }
            else
            {
                HPI.ee.Template.northPanelTpl.overwrite(Ext.getCmp("compare-north").body, HPI.ee.Template.northConfigCompareAllDealer);
            }

			Ext.apply(HPI.ee.Action.northCfgResults, {
				navigation: [
				{text: 'new search', action: 'HPI.ee.Action.newSearch()'},
				{text: 'back to compare', action: 'HPI.ee.Action.showCompare()'}
			]});

			Ext.apply(HPI.ee.Action.northAdvertNavigation, [
				{text: 'new search', action: 'HPI.ee.Action.newSearch()'},
				{text: 'back to results', action: 'HPI.ee.Action.showResults()'},
				{text: 'back to compare', action: 'HPI.ee.Action.showCompare()'}
			]);
		}	
	},

    /**
	 * Retrieves the index of the supplied vehicle in the compare keys array
	 */
    getColumnIndex: function(dto) {
        return this.keys.indexOf(dto.stockId);
    },

	/**
	 * Sets the width of the center container so the scrollbar remains tight.
	 */
	setCentreWidth: function () {

		switch (HPI.ee.compareData.expectedSize)
		{
			case 1: 
				Ext.get('compareCenter').setWidth(310);
				break;
			case 2:
				Ext.get('compareCenter').setWidth(600);
				break;
			default:
				Ext.get('compareCenter').setWidth(890);
				break;
		}
	}
});

HPI.ee.CompareHandler = new HPI.ee.CompareHandlerRunner();
/**
 * HPI.ee.ComparePanel
 *
 * The root layout of the compare page. Use this to hold and control the individual vehicle
 * compare panels. Any scrolling or UI events can be added to this container panel.
 *
 * An array of items keys is used to keep track of what is in the compare view.<b> 
 *
 */

HPI.ee.compareData = {data: [], expectedSize: 0, resultId: -1};

HPI.ee.ComparePanel = Ext.extend(Ext.Panel, {

	cls: 'compare',
	id: 'compare',
	border: HPI.DEBUG,

	COLUMN_WIDTH: 290,
	COLUMN_HEIGHT: 400,
	
	itemKeys: [],

	initComponent : function () 
	{
		HPI.ee.ComparePanel.superclass.initComponent.call(this);
	},

	/**
	 * Update the compare panel with the new vehicles and refresh the layout. If the
	 * vehicles have not changed from the last view, just return.
	 *
	 * @param {Array} keys       An array of DataManager keys to use for the comparison.
	 * @param {Number} resultId  The result id (is this required?)
	 */
	updateItems : function (keys, resultId)
	{
		if (this.itemKeys.equals(keys))	{
			// if we are comparing the same vehicles as previously, we don't need to update the compare panel
			HPI.ee.defaultMask.hide();
			return true;
		} else {
            
            this.itemKeys = keys.slice();

			HPI.ee.compareData.data = []; // reset the compare data set
			HPI.ee.compareData.expectedSize = this.itemKeys.length;
			HPI.ee.compareData.resultId = resultId;
            
			for (var i=0; i<this.itemKeys.length; i++)	{
				HPI.ee.DataManager.getVehicleDTO(this, this.itemKeys[i], resultId);
			}
		}
	},

	listeners: {
		dtoready: {
			fn: function(dto){
                HPI.ee.compareData.data.push(dto);
                
                if (HPI.ee.compareData.data.length === HPI.ee.compareData.expectedSize)	{
                    var tempArray = [];
                    for(var i=0;i< HPI.ee.compareData.data.length;i++)
                    {
                        tempArray[this.itemKeys.indexOf(HPI.ee.compareData.data[i].stockId)] = HPI.ee.compareData.data[i];
                    }
                    HPI.ee.compareData.data = tempArray;
                    
                    HPI.ee.Template.compareVehiclesTpl.overwrite(Ext.getCmp('compare').body, {
						data: HPI.ee.compareData.data, 
						resultId: HPI.ee.compareData.resultId
					});

                    HPI.ee.CompareHandler.setCentreWidth();
					HPI.ee.defaultMask.hide();
				}
			}
		}
	}
	
});
/**
 * HPI.ee.DataManager
 *
 * This class handles all component requests for vehicle data DTOs. It first checks
 * to see if the requested data is already loaded in its data store, and if so
 * uses this cached data.
 *
 * If the data requested is for a new vehicle, as request is made to the server. On
 * a successful response, the DTO is added to the store.
 *
 * When the DTO is ready, an event is fired back on the calling panel, with the DTO
 * as a parameter.
 *
 * On events which change the search filers, or sorting of the result set - the DTO
 * cache should be purged as the ordering data will be out of date.
 *
 * This is a Runner class and is initilised automatically.
 *
 * @runner HPI.ee.DataManagerRunner
 * @author Damian Ibbotson
 */

/**
 * Requests for data from the server will initiate a transaction record being written.  
 * To override this we ensure that all ajax requests pass a trans parameter with a value of "N".
 */
Ext.Ajax.extraParams = {
	'trans' : 'N'
};

HPI.ee.DataManagerRunner = function ()
{
	this.data = new Ext.util.MixedCollection(false);
	this.data.getKey = function (o)
	{
		return o.dataKey;
	};

	var storeConfig = {reader: new Ext.data.JsonReader({}, [{name: 'id'},{name: 'value'},{name: 'text'}]),proxy: new Ext.data.MemoryProxy()};
	
	this.stores = {

		matrixStore: new Ext.data.Store({
			proxy: new Ext.data.MemoryProxy(),
			reader: new Ext.data.JsonReader({
				root:'models',
				totalProperty: 'totalVehicles'
			}, [
				{name: 'id'},
				{name: 'modelStoreId'},
				{name: 'modelCode'},
				{name: 'description'},
				{name: 'image'},
				{name: 'blurb'},
				{name: 'count'}
			])			
		}),

		distanceStore: new Ext.data.Store(storeConfig),
		priceStore: new Ext.data.Store(storeConfig),
		mileageStore: new Ext.data.Store(storeConfig),
		yearStore: new Ext.data.Store(storeConfig),
		bodyStore: new Ext.data.Store(storeConfig),
		doorsStore: new Ext.data.Store(storeConfig),
		transmissionStore: new Ext.data.Store(storeConfig),
		engineFromStore: new Ext.data.Store(storeConfig),
		engineToStore: new Ext.data.Store(storeConfig),
		colourStore: new Ext.data.Store(storeConfig),

		/**
		 * Store for the standard multi dealer results grid
		 */
		allDealerStore: new Ext.data.Store({
			remoteSort: true,
			storeId: 'alldealerstore',
			sortInfo: {
				field: 'distance',
				direction: 'ASC'
			},
			reader: new Ext.data.JsonReader({
				totalProperty: 'totalVehicles',
				root: 'vehicles',
				id: 'id'
			},Ext.data.Record.create([
				{name: 'id'},
				{name: 'body'}, 
				{name: 'colour'},
				{name: 'colourCode'},
				{name: 'colourDesc'},
				{name: 'company'},
				{name: 'custId'},
				{name: 'description'},
				{name: 'distance'},
				{name: 'doors'},
				{name: 'dvlaCC'},
				{name: 'email'},
				{name: 'fuel'},
				{name: 'image'},
				{name: 'make'},
				{name: 'makeCode'},
				{name: 'mileage'},
				{name: 'model'},
				{name: 'modelCode'},
				{name: 'modelYear'},
				{name: 'narrative'},
				{name: 'optionalEquipment'},
				{name: 'price'},
				{name: 'pricePlusVatIndicator'},
				{name: 'registrationPlateId'},
				{name: 'serviceHistory'},
				{name: 'specialCode'},
				{name: 'specialDate'},
				{name: 'specialDesc'},
				{name: 'sponsor'},
				{name: 'stockId'},
				{name: 'telephone'},
				{name: 'transmissionSpeed'},
				{name: 'transmissionType'},
				{name: 'vrm'},
				{name: 'webSiteAddress'}			
			])),
			proxy: new Ext.data.HttpProxy({
				url: 'resultListServlet',
				params: HPI.params,
				method: 'GET'
			})
		}),

		/**
		 * Store for the single dealer result grid
		 */
		singleDealerStore: new Ext.data.Store({
			remoteSort: true,
			storeId: 'singledealerstore',
			sortInfo: {
				field: 'price',
				direction: 'ASC'
			},
			reader: new Ext.data.JsonReader({
				totalProperty: 'totalVehicles',
				root: 'vehicles',
				id: 'id'
			},
			Ext.data.Record.create([
				{name: 'id'},
				{name: 'body'}, 
				{name: 'colour'},
				{name: 'colourCode'},
				{name: 'colourDesc'},
				{name: 'company'},
				{name: 'custId'},
				{name: 'description'},
				{name: 'distance'},
				{name: 'doors'},
				{name: 'dvlaCC'},
				{name: 'email'},
				{name: 'fuel'},
				{name: 'image'},
				{name: 'make'},
				{name: 'makeCode'},
				{name: 'mileage'},
				{name: 'model'},
				{name: 'modelCode'},
				{name: 'modelYear'},
				{name: 'narrative'},
				{name: 'optionalEquipment'},
				{name: 'price'},
				{name: 'pricePlusVatIndicator'},
				{name: 'registrationPlateId'},
				{name: 'serviceHistory'},
				{name: 'specialCode'},
				{name: 'specialDate'},
				{name: 'specialDesc'},
				{name: 'sponsor'},
				{name: 'stockId'},
				{name: 'telephone'},
				{name: 'transmissionSpeed'},
				{name: 'transmissionType'},
				{name: 'vrm'},
				{name: 'webSiteAddress'}			
			])),
			proxy: new Ext.data.HttpProxy({
				url: 'resultListServlet',
				method: 'GET'
			}),
			listeners: {
				load: {
					fn: function () {
						HPI.ee.Transaction.writeResultTransaction(HPI.ee.singleDealerResults.store);
					}
				}
			}
		})
    };
  
	HPI.ee.DataManagerRunner.superclass.constructor.call(this);
};

Ext.extend(HPI.ee.DataManagerRunner, Ext.util.Observable, {

/**
 * apply a DTO to the advert panel component
 * will use cached DTO if available
 */
	applyDTO : function (cfg)
	{
		if (this.isDTOCached(cfg))
		{
			cfg.callback(this.getDTO(cfg.key));
		}
		else
		{
			this.fetchDTO(cfg);
		}
	},

/**
 * return true if the DTO is present in the DataManager cache
 */
	isDTOCached : function (cfg)
	{
		if (this.data.containsKey(cfg.key))
		{
			return true;
		}
		return false;
	},

/**
 * Make a request for the vehicle data (JSON). On success, registers this DTO with
 * the DataManager 
 *
 * @param stockId {number}  The stock id of the vehicle data required (this also
 *                          acts as the data key)
 * @param resultId {number} The result id  
 */
	fetchDTO : function (cfg)
	{
		Ext.Ajax.request({
			url: HPI.properties.urls.advertData,
			scope: this,
			params: {
				stockId: cfg.stockId,
				resultId: cfg.resultId
			},
			success: function (response,request) {
				var dto = Ext.util.JSON.decode(response.responseText);
                dto = Ext.apply(dto, {
					dataKey: cfg.key,
					resultId: cfg.resultId,
					na: '',
					noEquipment: 'Equipment not defined.'
				});
                this.data.add(dto);

				// execute the callback
                cfg.callback(dto);
			},
			failure: function () {
				HPI.ee.MsgError.show();
			}
		});
	},

/**
 * Return a vehicle DTO by key (key in stockId-resultId format)
 */

	getDTO : function (key)
	{
		return this.data.get(key);
	},


/**
 * get the data of the currently displayed advert
 **/
    getCurrentAdvert : function ()
    {   
        return this.getDTO(this.lastViewedKey);
    },

/**
 * request the static data servlet
*/
	requestStaticData: function() {
		Ext.Ajax.request({
			url: HPI.properties.urls.matrixStatic,
			params: HPI.params,
			method: 'GET',
			scope: this,
			success: function(response,request) {
				// create and populate the static combobox dataStores
				var jsonStaticData = Ext.util.JSON.decode(response.responseText);
				this.stores.distanceStore.loadData(jsonStaticData.distance);
				this.stores.priceStore.loadData(jsonStaticData.price);
				this.stores.mileageStore.loadData(jsonStaticData.mileage);
				this.stores.yearStore.loadData(jsonStaticData.year);
				this.stores.colourStore.loadData(jsonStaticData.colours);
			},
			failure: function () {
				HPI.ee.MsgError.show('Problem','Sorry, your request cannot be completed at this time.');
			}
		});
	},
	
/**
 * loads/gets the requested DTO, when ready fires an event back to the calling
 * component with the DTO passed in as a parameter.
 *
 * @param cmp {Component}   A reference to the calling component, if null no event
 *                          is fired on DTO ready.
 * @param stockId {number}  The stock id of the vehicle data required (this also
 *                          acts as the data key)
 * @param resultId {number} The result id                        
 */
	getVehicleDTO : function (cmp, stockId, resultId)
	{
		if (this.isDTOReady(stockId+"-"+resultId))
        {
			if (cmp)
			{
				cmp.fireEvent('dtoready',this.getDTO(stockId+"-"+resultId));
			}
		}
		else
		{
			this.loadDTO(cmp, stockId, resultId);
		}
	},
	
/**
 * return true if the DTO is present in the DataManager cache
 */
	isDTOReady : function (storeKey)
	{
		if (this.data.containsKey(storeKey))
		{
			return true;
		}
		return false;
	},


/**
 * Make a request for the vehicle data (JSON). On success, registers this DTO with
 * the DataManager and fires an event on the calling component, passing back the DTO
 * as a parameter
 *
 * @param cmp {Component}   A reference to the calling component so an event can
 *                          can be fired when the DTO is ready. If null then no
 *                          event will be fired.
 * @param stockId {number}  The stock id of the vehicle data required (this also
 *                          acts as the data key)
 * @param resultId {number} The result id 
 */
	loadDTO : function (cmp, stockId, resultId)
	{
		Ext.Ajax.request({
			url: HPI.properties.urls.advertData,
			scope: this,
			params: {
				stockId: stockId,
				resultId: resultId
			},
			success: function (response,request) {
				var dto = Ext.util.JSON.decode(response.responseText);
                
                // generate a unique key by stockId and resultId, and append to the DTO
                Ext.apply(dto, {
                    dataKey: stockId + '-' + resultId,
                    resultId: resultId
                });

				this.data.add(dto);

				if (cmp)
				{
                    cmp.fireEvent('dtoready',dto);
				}
			}
		});
	},

/**
 * Purge all DTOs from the manager
 */
	purgeAllDTOs : function ()
	{
		this.data.each(function (item) {
			this.data.remove(item);
		}, this);
	}
});

/**
 * Initialise the DataManager Object
 */
HPI.ee.DataManager = new HPI.ee.DataManagerRunner();

HPI.ee.DataManager.requestStaticData();
/*
 * HPI.ee.EmailFriend.js
 *
 * 26/10/08     Pulled into sapp and moved into HPI.ee namespace
 *
 * opens a lead generation form for emailing a friend.
 */
HPI.ee.EmailFriend = {
    init : function () {

		Ext.QuickTips.init();
        
        this.vehicleDetailsDto = HPI.ee.DataManager.getCurrentAdvert();
        this.stockId = this.vehicleDetailsDto.stockId;
        this.custId = this.vehicleDetailsDto.stockDetails.custId;
		this.vehicleDescription = this.vehicleDetailsDto.stockDetails.vehicleDescription;
		this.price = HPI.formatNumber(this.vehicleDetailsDto.stockDetails.price, 0, "&pound;");
		this.colour = this.vehicleDetailsDto.stockDetails.simpleColour;
		this.mileage = HPI.formatNumber(this.vehicleDetailsDto.stockDetails.mileage, 0, '') + " miles";

		this.bbar = new Ext.Toolbar({
			style: 'margin-top:10px;',
            cls: 'dh-action',
			items: [
            {
                xtype: 'tbtext',
                text: '<span id="ef_tbtext">*&nbsp;&nbsp;mandatory field</span>',
                id: 'btdStatus'
            },
            {xtype: 'tbfill'}, // to make the buttons right aligned
            {
				xtype: 'button',
				text: 'Cancel',
                iconCls: 'r-grey',
                overCls: 'r-red',
				listeners: {
					click: {
                        scope: this,
						fn: function () {
							this.win.close();
						}
					}
				}
			},
            {
                xtype: 'button',
                text: 'Submit',
                iconCls: 'r-grey',
                overCls: 'r-red',
                listeners: {
                    click: {
                        scope: this,
                        fn: function () {
                            if (this.form.getForm().isValid())
                            {
                                this.submit();
                            }
                            else
                            {
                                Ext.get('ef_tbtext').update('Correct form errors');
                                Ext.get('ef_tbtext').addClass('error');
                            }
                        }
                    }
                }
            }
          ]
		});

		this.form = new Ext.FormPanel({
			labelWidth: 200,
            cls: 'form',
			url: "/exchange/lotus/sendEmailToFriend",
			items: [{
				html: 'Vehicle Details',
				cls: 'subtitle'
			},{
				layout: 'table',
				layoutConfig: {
					columns: 2
				},
				items: [{
					html: '<div class="t-label">Vehicle</div>',
                    width: 50
				},{
					html: this.vehicleDescription
				},{
					html: '<div class="t-label">Price</div>'
				},{
					html: this.price
				},{
					html: '<div class="t-label">Colour</div>'
				},{
					html: this.colour
				},{
					html: '<div class="t-label">Mileage</div>'
				},{
					html: this.mileage
				}]
			},{
				html: 'Required Information',
				cls: 'subtitle'
			},{
				xtype: "textfield",
				fieldLabel: "Your Name",
				id: "emailFriend_yourName",
				name: HPI.properties.leadGen.paramName.customerName,
				maxLength: 25,
				maxLengthText: "Value should be no more than 25",
				allowBlank: false,
				labelSeparator: ' <span>*</span>',
				width: 200,
				msgTarget: 'side',
				validationEvent: "blur"
			},{
				xtype: "textfield",
				fieldLabel: "Your Friend's Email Address",
				id: "emailFriend_friendsEmailAddress",
				vtype: "email",
				validationEvent: "blur",
				allowBlank: false,
				labelSeparator: ' <span>*</span>',
				width: 200,
				msgTarget: 'side'
			},{ 
				xtype: "hidden",
				id: "emailFriend_stockId",
				name: HPI.properties.leadGen.paramName.stockId,
				value: this.stockId
			},{ 
				xtype: "hidden",
				id: "emailFriend_custId",
				name: HPI.properties.leadGen.paramName.custId,
				value: this.custId
			}]	
		});

		this.win = new Ext.Window({
			title: "Email a friend",
            id: "emailFriendWindow",
            width: 600,
           	modal: true,
			resizable: false,
			draggable: false,
			cls: 'fl-form',
			closeAction: 'close',
			items: [
                this.form,
                {
                  html: 'Disclaimer',
                  cls: 'subtitle'
                },{
                    html: 'Lotus will not retain or use the details of the data entered, other than to pass to the relevant dealer.',
                    cls: 'bodyText'
                },
                this.bbar]
		});

		this.win.show();
	},

	submit : function () {
		Ext.Ajax.request({
			url: this.form.url,
			params: this.form.getForm().getValues(),
			method: 'POST',
			scope: this,
			callback: function () {
				this.win.close();
			},
			success: function () {
				HPI.ee.MsgInfo.show('Form Submitted','<p>Thank you for completing the form.</p><p>Details of the vehicle have been sent to your friend.</p>');
			},
			failure: function () {
				HPI.ee.MsgError.show('Problem','Sorry, your request cannot be completed at this time.');
			}
		});
	}
};
/**
 * HPI.ee.FindVehicleForm.js
 *
 * Find me a vehicle lead generation form
 *
 * 26/10/08     Pulled into sapp and moved into HPI.ee namespace
 *
 * @class		Ext.ee.FindVehicleForm
 * @requires	Ext.ee.PostcodeAddressFieldset
 *
 * @author		Dean McGill 16th August 2008
 **/

HPI.ee.FindVehicleForm = {

	init : function (context) {

		Ext.QuickTips.init();

		this.tabform1 = {
			title: 'Personal details',
			height: 400,
			items: [{
				layout: 'form',
				id: 'firstform',
				items: [{
					xtype: 'hidden',
					id: 'fvfOrganisationName',
					name: HPI.properties.leadGen.paramName.organisationName
				},{
					xtype: 'hidden',
					id: 'fvfCustomerAddressLine1',
					name: HPI.properties.leadGen.paramName.customerAddressLine1
				},{
					xtype: 'hidden',
					id: 'fvfCustomerAddressLine2',
					name: HPI.properties.leadGen.paramName.customerAddressLine2
				},{
					xtype: 'hidden',
					id: 'fvfCustomerAddressLine3',
					name: HPI.properties.leadGen.paramName.customerAddressLine3
				},{
					xtype: 'hidden',
					id: 'fvfCustomerAddressLine4',
					name: HPI.properties.leadGen.paramName.customerAddressLine4
				},{
					xtype: 'hidden',
					id: 'fvfCustomerAddressLine5',
					name: HPI.properties.leadGen.paramName.customerAddressLine5
				},{
					xtype: 'hidden',
					id: 'fvfCustomerAddressPostTown',
					name: HPI.properties.leadGen.paramName.customerAddressPostTown
				},{
					xtype: 'hidden',
					id: 'fvfCustomerAddressCounty',
					name: HPI.properties.leadGen.paramName.customerAddressCounty
				},{
					xtype: 'hidden',
					id: 'fvfContext',
					name: 'context',
					value: context
				},{
					xtype: 'hidden',
					id: 'fvfRequiredVehicleMakeCode',
					name: HPI.properties.leadGen.paramName.vehicleMakeCode,
					value: 'BG'
				},{
					xtype: 'hidden',
					id: 'fvfRequiredVehicleMake',
					name: HPI.properties.leadGen.paramName.vehicleMake,
					value: 'Lotus'
				},{
					xtype: 'hidden',
					id: 'fvfRequiredVehicleModelCode',
					name: HPI.properties.leadGen.paramName.vehicleModelCode
				},{
					html: 'Your details',
					cls: 'subtitle'
				},{
					layout: 'form',
					labelWidth: 170,
					defaults: {
						msgTarget: 'side'
					},
					items: [{
						xtype: 'textfield',
						id: 'fvfCustomerName',
						name: HPI.properties.leadGen.paramName.customerName,
						fieldLabel: 'Name',
						width: 220,
						labelSeparator: ': *',
						allowBlank: false
					},{
						xtype: 'textfield',
						id: 'fvfCustomerEmailAddress',
						name: HPI.properties.leadGen.paramName.customerEmailAddress,
						fieldLabel: 'Email address',
						width: 220,
						allowBlank: false,
						labelSeparator: ': *',
						vtype: 'email'
					},{
						layout: 'column',
						items: [{
							columnWidth: 0.75,
							layout: 'form',
							labelWidth: 170,
							items: [{
								xtype: 'textfield',
								id: 'fvfCustomerPostcode',
                                cls: 'postcode',
								msgTarget: 'side',
								name: HPI.properties.leadGen.paramName.customerAddressPostcode,
								fieldLabel: 'Postcode',
								width: 220,
								allowBlank: false,
								vtype: 'postcode',
								labelSeparator: ': *',
                                listeners: {
                                    render: function()
                                    {
                                        if(HPI.readCookie(HPI.properties.app.postcodeCookieKey, null) != null)
                                        {
                                            this.value = HPI.readCookie(HPI.properties.app.postcodeCookieKey, null);
                                        }
                                    },
									valid: {
										fn: function () {
											Ext.getCmp('fvfAddressFinderButton').enable();
										}
									},
									invalid: {
										fn: function () {
											Ext.getCmp('fvfAddressFinderButton').disable();
										}
									}
								}
							}]
						},{
							columnWidth: 0.25,
							layout: 'form',
							items: [{
								xtype: 'button',
								text: 'Find my address',
								id: 'fvfAddressFinderButton',
								disabled: true,
								listeners: {
									click: {
										scope: this,
										fn: function () {
											var postcode = Ext.getCmp('fvfCustomerPostcode');
											if (postcode.isValid())
											{
												HPI.ee.PafFormWidget.init(postcode.getValue(),'fvf');
											}								
										}
									},
                                    /**
                                     * The original Ext code suppresses to add/remove disabled style class
                                     * to elements, as IE6 seem to handle the dislabed element with its
                                     * own style that crashes with the Ext disabled item stylying.
                                     * Add them manually so that we can style them as necessary.
                                     */
                                    enable: {
                                        fn: function(el) {
                                            if(Ext.isIE6)
                                            {
                                                el.removeClass("x-item-disabled");
                                            }
                                        }
                                    },
                                    disable: {
                                        fn: function(el) {
                                            if(Ext.isIE6)
                                            {
                                                el.addClass("x-item-disabled");
                                            }
                                        }
                                    }
								}
							}]
						}]
					},{
						xtype: 'textarea',
						id: 'fvfCustomerAddressPreview',
						name: 'customerAddress',
						fieldLabel: 'Address',
                        cls: 'custAddress',
						disabled: true,
						width: 220,
                        height: 50,
						allowBlank: false,
                        emptyText: 'You can search for your address using the postcode lookup above',
						labelSeparator: ': *',
						listeners: {
							addressUpdate: {
								fn: function (ap) {
									this.setValue(ap);
                                    Ext.getCmp('fvfAddressFinderButton').setText('Edit my address');
                                    HPI.ee.FindVehicleForm.win.addressFound = true;
								}
							}
						}
					},{
						xtype: 'textfield',
						id: 'fvfCustomerTelephone',
						name: HPI.properties.leadGen.paramName.customerTelephone,
						fieldLabel: 'Telephone number',
						width: 220,
						allowBlank: false,
                        vtype: 'telephone',
						labelSeparator: ': *'
					}]
				},{
					html: 'Preferred contact details',
					cls: 'subtitle'
				},{
					layout: 'form',
					labelWidth: 170,
					items: [{
						xtype: 'radiogroup',
						fieldLabel: 'Method of contact',
						width: 200,
						items: [{
							boxLabel: 'Phone',
							id: 'fvfPreferredContactMethodPhone',
							name: HPI.properties.leadGen.paramName.preferredContactMethod,
							inputValue: 'Telephone',
							checked: true
						},{
							boxLabel: 'Email',
							id: 'fvfPreferredContactMethodEmail',
							name: HPI.properties.leadGen.paramName.preferredContactMethod,
							inputValue: 'Email',
							listeners: {
								check: {
									fn: function () {
										Ext.getCmp('fvfPreferredContactDate').setDisabled(this.getValue());
										Ext.getCmp('fvfPreferredContactTime').setDisabled(this.getValue());
									}
								}
							}
						}]
					},{
						layout: 'column',
						items: [{
							columnWidth: 0.5,
							layout: 'form',
							items: [{
								xtype: 'datefield',
								fieldLabel: 'Date & Time of contact',
								id: 'fvfPreferredContactDate',
								format: 'd/m/Y',
								minValue: new Date(),
								name: HPI.properties.leadGen.paramName.preferredContactDate,
                                editable:false,
								width: 100
							}]
						},{
							columnWidth: 0.5,
							items: [{
								xtype: 'timefield',
								fieldLabel: '',
								labelSeparator: '',
								id: 'fvfPreferredContactTime',
								name: HPI.properties.leadGen.paramName.preferredContactTime,
								width: 100,
								minValue: '9:00 AM',
								maxValue: '5:00 PM',
								increment: 30,
                                editable:false
							}]
						}]
					}]
				},{
					html: 'Disclaimer',
					cls: 'smalltitle',
					style: 'padding-top:20px;'
				},{
					html: 'The details and email address you provide will only be used by Lotus Cars Limited, Group Lotus Plc (or its affiliated or associated companies), or authorised Lotus dealers to keep you informed of new products and services, or for conducting market research. Lotus will not retain or use the details of the data entered, other than to pass to the relevant dealer or manufacturer concerned.',
					cls: 'bodyText'
				},{
					layout: 'form',
					labelWidth: 300,
					
					items: [{
						xtype: 'checkbox',
						fieldLabel: 'If you do not want your information to be used in this way please tick here',
						labelAlign: 'right',
						labelStyle: 'font-weight:normal;width:440px;line-height:18px',
						labelSeparator: ':',
                        name: HPI.properties.leadGen.paramName.marketingOption,
                        inputValue: "true"
					}]
				}]
			}]
		};

		this.modelStore = new Ext.data.Store({
			baseParams: {type: 'modelsearch'},
			proxy: new Ext.data.HttpProxy({
				url: HPI.properties.urls.exchangeData
			}),
			reader: new Ext.data.JsonReader({
				root: 'model'
			}, [
				{name: 'id'},
				{name: 'value'},
				{name: 'text'}
			])
		});

		this.tabform2 = {
			title: 'Optional Information',
			height: 400,
			items: [{
                html: 'Your requirements',
                cls: 'subtitle'
            },{
                html: 'Please give a description of the vehicles you are interested in',
                cls: 'bodytext',
                style: 'padding-bottom:10px;'
            },{
                xtype: 'textarea',
                width: 560,
                height: 80,
                name: HPI.properties.leadGen.paramName.vehicleOtherRequirements,
                maxLength: 250
            },{
				layout: 'form',
                labelWidth: 170,
  				items: [{
  					html: 'Other Products',
  					cls: 'subtitle'
  				},{
					html: 'Your local dealer may be able to save you money on finance and insurance services for your next <b>approved used vehicle</b>.',
					cls: 'bodytext',
					style: 'padding-bottom:10px;'
  				},{
  					xtype: 'checkbox',
  					fieldLabel: 'Are you interested in',
  					labelSeparator: '?',
  					boxLabel: 'Insurance',
  					name: HPI.properties.leadGen.paramName.otherServices,
  					inputValue: 'Insurance'
  				},{
					xtype: 'checkbox',
					labelSeparator: '',
					boxLabel: 'Finance',
					name: HPI.properties.leadGen.paramName.otherServices,
					inputValue: 'Finance'
  				},{
  					xtype: 'checkbox',
  					labelSeparator: '',
  					boxLabel: 'Service plan',
  					name: HPI.properties.leadGen.paramName.otherServices,
  					inputValue: 'Service_Plan'
  				}]
			}]		
		};
		
		this.form = new Ext.FormPanel({
			url: HPI.properties.urls.findVehicleServlet,
			items: [{
				xtype: 'tabpanel',
				deferredRender: false,
				plain: true,
				activeTab: 0,
				id :'fvfTabPanel',
				tabWidth: 200,
				items: [this.tabform1,this.tabform2],
					
				listeners: {
					beforetabchange: {
						scope: this,
						fn: function(tab, newTab, currentTab) {
							if (!this.initilised)
							{
								this.initilised = true;
								return true;
							}
                            //check if the tab is loaded as window loaded, rather than the tab change
                            if(currentTab)
                            {
                              if (!this.form.getForm().isValid() || !HPI.ee.FindVehicleForm.win.addressFound)
                              {
                                if(!HPI.ee.FindVehicleForm.win.addressFound)
                                {
                                    Ext.getCmp("fvfCustomerAddressPreview").markInvalid("Address has not been selected or entered. Please use \"find my address\" button to find your address by the postcode.");
                                }
                                Ext.get('tbtext').update('Correct form errors');
                                Ext.get('tbtext').addClass('error');
                                return false;
                              }
  
                              Ext.get('tbtext').update('');
                              Ext.get('tbtext').removeClass();
                            }
                            
                            return true;
						}
					}
				}
			}]
		});

		this.tb = new Ext.Toolbar({
			width: 560,
			items: [{
				xtype: 'tbtext',
				text: '<span id="tbtext">*&nbsp;&nbsp;mandatory field</span>',
				id: 'fvfStatus'
			},{
				xtype: 'tbfill'
			},{
				xtype: 'button',
				text: 'Cancel',
				listeners: {
					click: {
						scope: this,
						fn: function () {
							this.win.close();
						}
					}
				}
			},{
				xtype: 'button',
				text: 'Submit',
				listeners: {
					click: {
						scope: this,
						fn: function () {
							if (this.form.getForm().isValid() && HPI.ee.FindVehicleForm.win.addressFound)
							{
								this.submit();
							}
							else
							{
								Ext.getCmp('fvfTabPanel').setActiveTab(0);
                                if(!HPI.ee.FindVehicleForm.win.addressFound)
                                {
                                    Ext.getCmp("fvfCustomerAddressPreview").markInvalid("No address has not been selected or entered. Please use \"find my address\" button to find your address by the postcode.");
                                }
								Ext.get('tbtext').update('Correct form errors');
								Ext.get('tbtext').addClass('error');
							}
						}
					}
				}
			}]
		});
		
		this.win = new Ext.Window({
			id: 'findVehicleForm',
			title: 'Find Me A Vehicle',
			width: 600,
			height: 515,
			modal: true,
			shadow: false,
			resizable: false,
			draggable: false,
			cls: 'fl-form',
			closeAction: 'close',
			items: [this.form,this.tb]
		});

		this.win.show();
	},

	/**
	 * Submit the form
	 */
	submit : function () {

		this.form.getForm().submit({
			scope: this,
			success: function () {
                this.win.close();
				HPI.ee.MsgInfo.show('Form Submitted','Thank you for your interest.<br/><br/>Your local dealer will be in touch.');
			},
			failure: function () {
				HPI.ee.MsgError.show('Problem','Sorry, your request cannot be completed at this time.');
			}
		});
	}
};
/**
 * An Ext implementation of a gallery zoom
 */

HPI.ee.ImageZoom = Ext.extend(Ext.Window, {

	width: 600,
	height: 513,
	draggable: false,
	shadow: false,
	resizable: false,
	modal: true,
	hideBorders: true,
	cls: 'zoom',
	bodyBorder: false,
	border: false,
	closable: false,
	id: 'zoom',
    //animateTarget: Ext.get(Ext.DomQuery.selectNode('li[class=zoomTabTitle] a', 'gallery')),
    //expandOnShow: false,
    //collapsed: true,
    //animCollapse: true,

	initComponent : function (config) 
	{
		Ext.apply(this, {
			
			layout: 'border',
			border: false,
			items: [{
				border: false,
				region: 'center',
				layout: 'border',
				items: [{
					region: 'center',
					border: false,
					items: [this.zoomPanel]
				},{
					region: 'south',
					border: false,
					height: 63,
					items: [this.filmstripPanel]
				}]
			}]
		});

		HPI.ee.ImageZoom.superclass.initComponent.call(this);
  	},

    changeImage: function(index) {

        this.getEl().mask('Fetching image from server...');

        for (var i = 0 ; i < this.tNodes.length ; i++ )
        {
            if (Ext.fly(this.tNodes[i]).hasClass('current'))
            {
                Ext.fly(this.tNodes[i]).removeClass('current');
            }
        }
        
        var that = this;

        /*
         * Make use of image preloader masking out of convenience.
         * We only pass in the single image being requested, but we could change this to load all zoom images up front
         */
        var imageLoader = new ImagePreloader([this.mediumImages[index]], function () {
            Ext.fly('zoomimage').dom.src = this.imagesArray[0].src;
            that.getEl().unmask();
            Ext.fly(that.tNodes[index]).addClass('current');
        });

        imageLoader.preload();
    },


    launch: function(data)
    {
        this.center();
        // register the medium image array
        this.mediumImages = data.mediumImages;

        // template for zoomed image
        HPI.ee.Template.imageZoomTpl.overwrite(this.zoomPanel.body, {
            imageUrl: data.mediumImages[data.currentImage]
        });

        // template for filmstrip
        HPI.ee.Template.imageZoomThumbStripTpl.overwrite(this.filmstripPanel.body, {
            content: data.thumbImages,
            current: data.currentImage
        });		

        this.tNodes = Ext.DomQuery.select('img[class=thumb]','filmstrip');
        Ext.fly(this.tNodes[data.currentImage]).addClass('current');

        Ext.fly('filmstrip').on('click', function (e,node) {
            // to get the rel attribute value as it is non-standard
            if (Ext.fly(node).dom.attributes.getNamedItem('rel'))
            {
                this.changeImage(parseInt(Ext.fly(node).dom.attributes.getNamedItem('rel').value,10));
            }
            
        }, this);

        Ext.fly('zoomclose').on('click', function () {
            this.hide();
        }, this);

        this.doLayout();
        this.show();
        /*
        setTimeout(function(){
            HPI.ee.zoom.expand(true);
            HPI.ee.zoom.center();
        }, 1000);
        */
    },

	zoomPanel : new Ext.Panel({
		border: false
	}),

	filmstripPanel : new Ext.Panel({
		border: false,
        cls: 'filStrip'
	})
});

HPI.ee.zoom = new HPI.ee.ImageZoom();
HPI.ee.zoom.render(Ext.getBody());

function ImagePreloader(images, callback) {
   // store the callback
   this.callback = callback;
   // initialize internal state.
   this.imagesArray = new Array;
   this.imageUrls = images;
}

ImagePreloader.prototype.preload = function()
{
    for (var i=0; i<this.imageUrls.length; i++)
    {
        // create new Image object and add to array
        var oImage = new Image();
        this.imagesArray.push(oImage); //it has to be added before the event handlers are assigned.
                                       //otherwise IE calls the oncomplete handler before the array is filled

        // set up event handlers for the Image object
        oImage.onload = ImagePreloader.prototype.onload;
        oImage.onerror = ImagePreloader.prototype.onerror;
        oImage.onabort = ImagePreloader.prototype.onabort;
        // assign pointer back to this.
        oImage.oImagePreloader = this;
        oImage.bLoaded = false;
        // assign the .src property of the Image object
        oImage.src = this.imageUrls[i];
    }
}

ImagePreloader.prototype.onComplete = function()
{
    if(this.imagesArray.length === this.imageUrls.length)
    {
        this.callback();
    }
}
ImagePreloader.prototype.onload = function()
{
    this.bLoaded = true;
    this.oImagePreloader.nLoaded++;
    this.oImagePreloader.onComplete();
}
ImagePreloader.prototype.onerror = function()
{
    this.bError = true;
    this.oImagePreloader.onComplete();
}
ImagePreloader.prototype.onabort = function()
{
    this.bAbort = true;
    this.oImagePreloader.onComplete();
}
/**
 * HPI.ee.ModelMatrix.js
 *
 * The model matrix component.
 *
 * Expects an element to be passed as a property 'blurbId' into the object configuration.
 * The blurb will be used to update the elements body on mouse over, replacing the default
 * blurb to the element on a delayed mouse out.<b> 
 * 
 * On selection changes will fire events to update the stores, and the current vehicle count
 * on the refineForm panel.<b>
 *
 * @author   Dean McGill
 *
 * @class    HPI.ee.ModelMatrix
 * @extends  Ext.DataView
 */

HPI.ee.ModelMatrix = Ext.extend(Ext.DataView, {

	id: 'modelMatrix',
	cls: 'model-matrix',
	autoHeight: true,
	width: 550,
	multiSelect: true,
	itemSelector: 'div.matrix-node',
	overClass: 'matrix-node-over',
	selectedClass: 'matrix-node-sel',
	simpleSelect: true,
	tpl: HPI.ee.Template.modelMatrixNodeTpl,

	store: HPI.ee.DataManager.stores.matrixStore,
	
/**
 * initilise the components and set up the blurb events
 */	
	initComponent: function()
	{
		// make a request for the static data
		this.getStaticData(HPI.params);

		HPI.ee.ModelMatrix.superclass.initComponent.apply(this, arguments);

		this.on('mouseenter', function (dv,index,node) {
			if (this.task)
			{
				this.task.cancel();
			}
			Ext.fly(this.blurbId).dom.innerHTML = HPI.ee.Template.modelMatrixBlurbTpl.applyTemplate({
				blurb: dv.store.getAt(index).get('blurb'),
				description: dv.store.getAt(index).get('description')
			});
		}, this);

		this.on('mouseleave', function () {
			if (!this.task)
			{
				this.task = new Ext.util.DelayedTask(function () {
					Ext.fly(this.blurbId).dom.innerHTML = this.defaultBlurb;
				}, this);
			}
			this.task.delay(1000);
		}, this);
	},

   // private - override
    onMouseOver: function(e){
        var item = e.getTarget(this.itemSelector, this.el);
        if(item && item !== this.lastItem){
            this.lastItem = item;
            // only apply over class if there are vehicles in stock
            if (this.store.getAt(this.indexOf(item)).get('count') !== 0)
            {
                Ext.fly(item).addClass(this.overClass);
            }
            this.fireEvent("mouseenter", this, this.indexOf(item), item, e);
        }
    },

	 /**
	  * Overrides DataView prepareData function to ensure that the 'other models' matrix component is updated with vald properties
	  */
	prepareData : function(data){

		if (data.modelStoreId === 'BG_OTHER')
		{
			data.description = HPI.properties.others.description;
			data.blurb = HPI.properties.others.blurb;
			data.image = HPI.properties.others.image;
		}

		return data;
	},

/**
 * Request the static data from the server
 */
	getStaticData: function (params)
	{
		Ext.Ajax.request({
			url: HPI.properties.urls.modelMatrixStatic,
			params: params,
			method: 'GET',
			scope: this,
			success: function (response,request) {
				this.store.loadData(Ext.util.JSON.decode(response.responseText));
			},
			failure: function () {
				HPI.ee.MsgError.show('Problem','Sorry, your request cannot be completed at this time.');
			}
		});
	},

	select: function(nodeInfo, keepExisting, suppressEvent) {
		if (this.store.getAt(nodeInfo).get('count') === 0)
		{
			return false;
		}
		
		HPI.ee.ModelMatrix.superclass.select.apply(this, arguments);
        
        //call the store update but suppress any mask to come on to maximise
        //the user experience of multiple model selection
		HPI.ee.Action.doStoreUpdate(Ext.apply(HPI.params,{ 
			models: this.getSelectedModels()
		}), null, true);
	},

	deselect: function(nodeInfo, keepExisting, suppressEvent) {
		
        HPI.ee.ModelMatrix.superclass.deselect.apply(this, arguments);
        
        //do not call the storeupdate if the suppressEvent is set to true
		if (suppressEvent !== true)
		{
			HPI.ee.Action.doStoreUpdate(Ext.apply(HPI.params,{ 
				models: this.getSelectedModels()
			}), null, true);
		}
	},
    
    listeners:
    {
        containerclick: function () {
            // prevent IE from clearing all the model selections...
            return false;
        }
    },

	
	/**
	 * Set the counts of the store. If any nodes are selected and a zero count
	 * is returned the node is deselected.
	 *
	 * @param {Object} An object containing the parameters to pass on the request
	 **/
	setModelCount: function(params) {
		var modelMatrix = this;
		Ext.Ajax.request({
			url: HPI.properties.urls.matrixCount, 
			method: 'GET',
			//params: params,
            params: Ext.apply(params,{src:'matrixCount'}),
			scope: this,
			success: function(response,request) {
				var jsonData = Ext.util.JSON.decode(response.responseText);
                this.doModelCount(jsonData);
			},
			failure: function () {
				HPI.ee.MsgError.show('Problem','Sorry, your request cannot be completed at this time.');
			}
		});
	},

    doModelCount: function(jsonData)
    {
        var index;
        if (jsonData.vehicle !== null) {
            for ( var i = 0 ; i < jsonData.vehicle.length ; i++ ) {
                index = this.store.find('modelStoreId',jsonData.vehicle[i].id);
                if (index > -1) {
                    this.store.getAt(index).set('count',jsonData.vehicle[i].stock);
                }
            }
            HPI.ee.matrixRefine.fireEvent('countupdate',this.getSelectedCount());
            HPI.ee.resultsRefine.fireEvent('countupdate',this.getSelectedCount());
        }
    },
	
	/**
	 * Return the select model codes as a comma seperated string
	 *
	 * @return {String} select models
	 **/
	getSelectedModels: function() {
		
		var rec = this.getSelectedRecords();
		var sel = '';

		for (var i=0; i<rec.length; i++ ){
			if (sel !== '')	{
				sel += ',';
			}
			sel += rec[i].get('modelCode');
		}

		return sel;
	},

	/**
	 * Get the total number of vehicles regardless of selections. Takes into
	 * consideration and count cap.
	 *
	 * @return {int} total number of vehicles
	 **/

	getTotalCount: function() {
		
		var total = 0;

		for (var i=0; i<this.store.getCount(); i++) {
			total += this.store.getAt(i).get('count');
		}
		return total>HPI.properties.app.countCap?(HPI.properties.app.countCap+'+'):total;
	},

	/**
	 * Get the total number of vehicles that are selected models. If no models
	 * are selected the total count is returned.
	 *
	 * @return {number} total number of vehicles selected
	 **/

	getSelectedCount: function() {

		var total = 0;
        var selectedModelCount = 0;

        //only counting the selected model...
		for (var i=0; i<this.store.getCount(); i++ ) {
			if (this.isSelected(i))	{
				total += this.store.getAt(i).get('count');
                selectedModelCount++;
			}
		}

        //get the total count if no model is selected
		return (total===0 && selectedModelCount === 0)?this.getTotalCount():((total>HPI.properties.app.countCap)?(HPI.properties.app.countCap+'+'):total);
	}
});
/**
 * HPI.ee.PafFormWidget.js
 * 
 * @class   HPI.ee.PafFormWidget
 * @author  Dean McGill - 02/09/2008
 * 
 */

HPI.ee.PafFormWidget = {

     /**
     * Initilise and show the PAF address lookup window. Any postcode validation should
     * have already been taken care of by the calling function.
     *
     * @params postcode {String} The clients postcode to be passed on widget initilisation
     * @params prefix   {String} The unique prefix for element id's
     */
	init: function(postcode, prefix) {

		this.form = new Ext.Window({
			id: 'pafWidget',
			title: 'Automatic address lookup',
			width: 400,
			autoHeight: true,
			cls: 'fl-form',
			closeAction: 'close',
			bodyStyle: 'padding:5px 5px 0',
			animateTarget: Ext.get('addressFinderButton'),
			modal: true,
			resizable: false,
			draggable: false,
			listeners: {
				close: function() {
					Ext.StoreMgr.lookup('addressList').removeAll();
				}
			},
			items: [{
				layout: 'form',
				items: [{
					xtype: 'combo',
					id: 'pafSelectAddressCombo',
					fieldLabel: 'Select address',
					anchor: '100%',
					mode: 'local',
					valueField: 'id',
					editable: false,
					displayField: 'description',
					triggerAction: 'all',
					disabled: true,
					emptyText: 'Select your address...',
					store: new Ext.data.JsonStore({
						storeId: 'addressList',
						url: HPI.properties.urls.addressDatasetUrl,
						root: 'PostcodeDataSet',
						baseParams: {
							postcode: postcode
						},
						autoLoad: true,
						fields: [{
							name: 'id'
						},
						{
							name: 'description'
						}],
						listeners: {
							load: {
								scope: this,
								fn: function(store) {
									HPI.ee.defaultMask.hide();
									if (store.getCount() > 0) {
										Ext.getCmp('pafSelectAddressCombo').enable();
									}
									else {
										this.handleNoAddressFoundError();
									}
								}
							},
							loadexception: {
								scope: this,
								fn: function() {
									HPI.ee.defaultMask.hide();
									this.handleNoAddressFoundError();
								}
							}
						}
					}),
					listeners: {
						select: function() {
							HPI.ee.PafFormWidget.getAddressByPafKey(this.getValue());
						}
					}
				},
				{
					html: 'You can manually edit your address if necessary.',
					style: 'margin-bottom:10px',
					cls: 'bodytext'
				},
				{
					xtype: 'textfield',
					id: 'pafOrganisationName',
					fieldLabel: 'Organisation',
					anchor: '100%',
					disabled: false,
					listeners: {
						render: {
							fn: function () {
								this.setValue(Ext.getCmp(prefix+'OrganisationName').getValue());
							}
						}
					}
				},
				{
					xtype: 'textfield',
					id: 'pafLine1',
					fieldLabel: 'Line 1',
					anchor: '100%',
					disabled: false,
					listeners: {
						render: {
							fn: function () {
								this.setValue(Ext.getCmp(prefix+'CustomerAddressLine1').getValue());
							}
						}
					}
				},
				{
					xtype: 'textfield',
					id: 'pafLine2',
					fieldLabel: 'Line 2',
					anchor: '100%',
					disabled: false,
					listeners: {
						render: {
							fn: function () {
								this.setValue(Ext.getCmp(prefix+'CustomerAddressLine2').getValue());
							}
						}
					}
				},
				{
					xtype: 'textfield',
					id: 'pafLine3',
					fieldLabel: 'Line 3',
					anchor: '100%',
					disabled: false,
					listeners: {
						render: {
							fn: function () {
								this.setValue(Ext.getCmp(prefix+'CustomerAddressLine3').getValue());
							}
						}
					}
				},
				{
					xtype: 'textfield',
					id: 'pafLine4',
					fieldLabel: 'Line 4',
					anchor: '100%',
					disabled: false,
					listeners: {
						render: {
							fn: function () {
								this.setValue(Ext.getCmp(prefix+'CustomerAddressLine4').getValue());
							}
						}
					}
				},
				{
					xtype: 'textfield',
					id: 'pafLine5',
					fieldLabel: 'Line 5',
					anchor: '100%',
					disabled: false,
					listeners: {
						render: {
							fn: function () {
								this.setValue(Ext.getCmp(prefix+'CustomerAddressLine5').getValue());
							}
						}
					}
				},
				{
					xtype: 'textfield',
					id: 'pafPostTown',
					fieldLabel: 'Post town',
					anchor: '100%',
					disabled: false,
					listeners: {
						render: {
							fn: function () {
								this.setValue(Ext.getCmp(prefix+'CustomerAddressPostTown').getValue());
							}
						}
					}
				},
				{
					xtype: 'textfield',
					id: 'pafCounty',
					fieldLabel: 'County',
					anchor: '100%',
					disabled: false,
					listeners: {
						render: {
							fn: function () {
								this.setValue(Ext.getCmp(prefix+'CustomerAddressCounty').getValue());
							}
						}
					}
				}]
			}],
			buttons: [{
				xtype: 'button',
				type: 'button',
				text: 'Cancel',
				listeners: {
					scope: this,
					click: function() {
						this.form.close();
					}
				}
			},
			{
				xtype: 'button',
				type: 'button',
				text: 'Accept',
				disabled: false,
				id: 'pafAcceptButton',
				listeners: {
					scope: this,
					click: function() {
						if(HPI.ee.PafFormWidget.populateFormAddress(prefix))
                        {
						  this.form.close();
                        }
					}
				}
			}],
            listeners: {
                beforeshow: {
                    fn: function () {
                        HPI.ee.defaultMask.show();
                    }
                }
            }
		});

		this.form.show();
    },

	/**
     * Get the address detail from the PAF server using the pafKey
     *
     * @params pafKey {String} The PAF key from the selected address
     */

	getAddressByPafKey: function(pafKey) {
		var that = this;

		// get the components
		var organisationName = Ext.getCmp('pafOrganisationName');
		var line1 = Ext.getCmp('pafLine1');
		var line2 = Ext.getCmp('pafLine2');
		var line3 = Ext.getCmp('pafLine3');
		var line4 = Ext.getCmp('pafLine4');
		var line5 = Ext.getCmp('pafLine5');
		var postTown = Ext.getCmp('pafPostTown');
		var county = Ext.getCmp('pafCounty');

		Ext.Ajax.request({
			url: HPI.properties.urls.addressDatasetUrl,
			params: {
				pafKey: pafKey
			},
			success: function(response, request) {
				var json = Ext.util.JSON.decode(response.responseText);

				// set the values
				organisationName.setValue(json.AddressDataSet.organisationName);
				line1.setValue(json.AddressDataSet.line1);
				line2.setValue(json.AddressDataSet.line2);
				line3.setValue(json.AddressDataSet.line3);
				line4.setValue(json.AddressDataSet.line4);
				line5.setValue(json.AddressDataSet.line5);
				postTown.setValue(json.AddressDataSet.postTown);
				county.setValue(json.AddressDataSet.county);

				// enable the field for editing if required
				that.enableFields();
			},
			failure: function() {
				that.handleNoAddressFoundError();
			}
		});
	},

     /**
     * Populate the calling forms hidden address fields
     */

	populateFormAddress: function(prefix) {
		// get the address from the detail fields, preserving any manual edits
		var organisationName = Ext.getCmp('pafOrganisationName').getValue();
		var line1 = Ext.getCmp('pafLine1').getValue();
		var line2 = Ext.getCmp('pafLine2').getValue();
		var line3 = Ext.getCmp('pafLine3').getValue();
		var line4 = Ext.getCmp('pafLine4').getValue();
		var line5 = Ext.getCmp('pafLine5').getValue();
		var postTown = Ext.getCmp('pafPostTown').getValue();
		var county = Ext.getCmp('pafCounty').getValue();

		// set the calling forms hidden address fields
		Ext.getCmp(prefix + 'OrganisationName').setValue(organisationName);
		Ext.getCmp(prefix + 'CustomerAddressLine1').setValue(line1);
		Ext.getCmp(prefix + 'CustomerAddressLine2').setValue(line2);
		Ext.getCmp(prefix + 'CustomerAddressLine3').setValue(line3);
		Ext.getCmp(prefix + 'CustomerAddressLine4').setValue(line4);
		Ext.getCmp(prefix + 'CustomerAddressLine5').setValue(line5);
		Ext.getCmp(prefix + 'CustomerAddressPostTown').setValue(postTown);
		Ext.getCmp(prefix + 'CustomerAddressCounty').setValue(county);

		// set the calling forms address preview, of present
		var apEl = Ext.getCmp(prefix + 'CustomerAddressPreview');
		if (apEl) {
			var ap = '';
			if (!HPI.StringUtils.isBlank(organisationName)) {
				ap += organisationName;
			}
			if (!HPI.StringUtils.isBlank(line1)) {
				if (!HPI.StringUtils.isBlank(ap)) ap += ', ';
				ap += line1;
			}
			if (!HPI.StringUtils.isBlank(line2)) {
				if (!HPI.StringUtils.isBlank(ap)) ap += ', ';
				ap += line2;
			}
			if (!HPI.StringUtils.isBlank(line3)) {
				if (!HPI.StringUtils.isBlank(ap)) ap += ', ';
				ap += line3;
			}
			if (!HPI.StringUtils.isBlank(line4)) {
				if (!HPI.StringUtils.isBlank(ap)) ap += ', ';
				ap += line4;
			}
			if (!HPI.StringUtils.isBlank(line5)) {
				if (!HPI.StringUtils.isBlank(ap)) ap += ', ';
				ap += line5;
			}
			if (!HPI.StringUtils.isBlank(postTown)) {
				if (ap) ap += ', ';
				ap += postTown;
			}
			if (!HPI.StringUtils.isBlank(county)) {
				if (!HPI.StringUtils.isBlank(ap)) ap += ', ';
				ap += county;
			}
            
            if(HPI.StringUtils.isBlank(ap))
            {
                HPI.ee.MsgError.show('Error','Please select or enter your address.');
                return false;
            }
            
            apEl.fireEvent('addressUpdate', ap);
            return true;
		}
	},
	handleNoAddressFoundError: function() {
		HPI.ee.MsgError.show('Error','No addresses found for that postcode.<br/><br/>Please enter your address manually.');
	},
	
	enableFields: function() {
		// enable the field for editing
		Ext.getCmp('pafOrganisationName').enable()
		Ext.getCmp('pafLine1').enable();
		Ext.getCmp('pafLine2').enable();
		Ext.getCmp('pafLine3').enable();
		Ext.getCmp('pafLine4').enable();
		Ext.getCmp('pafLine5').enable();
		Ext.getCmp('pafPostTown').enable();
		Ext.getCmp('pafCounty').enable();

		// enable accept button
		Ext.getCmp('pafAcceptButton').enable();
	}

};
/**
 * Set some parameters when we page
 */

HPI.ee.PagingToolbar = Ext.extend(Ext.PagingToolbar, {

	initComponent : function ()
	{
		HPI.ee.PagingToolbar.superclass.initComponent.apply(this, arguments);
	},

    /**
     * This method overrides Ext.PagingToolbar updateInfo method
     * to display the total number of vehicles capped.
     */
    updateInfo : function(){
       if(this.displayEl){
            var count = this.store.getCount();
            var totalCount = this.store.getTotalCount() > HPI.properties.app.countCap ? HPI.properties.app.countCap + '+' : this.store.getTotalCount();
            var msg = count === 0 ?
                this.emptyMsg :
                String.format(this.displayMsg, this.cursor+1, this.cursor+count, totalCount);
            this.displayEl.update(msg);
       }
    },

    onClick : function(which){
        var store = this.store;
        switch(which){
            case "first":
				this.params.start = 0;
                this.doLoad(this.start);
            break;
            case "prev":
				this.params.start = Math.max(0, this.cursor-this.pageSize);
                this.doLoad(this.params.start);
            break;
            case "next":
				this.params.start = this.cursor+this.pageSize;
                this.doLoad(this.params.start);
            break;
            case "last":
                var total = store.getTotalCount();
                var extra = total % this.pageSize;
                this.params.start = extra ? (total - extra) : total-this.pageSize;
                this.doLoad(this.params.start);
            break;
            case "refresh":
                this.doLoad(this.cursor);
            break;
        }
    },
/**
 * Add our extra HPI params to the request
 */
	doLoad : function(start){
        var o = {}, pn = this.paramNames;
        o[pn.start] = start;
        o[pn.limit] = this.pageSize;
        if(this.fireEvent('beforechange', this, o) !== false){
            this.store.load({params: Ext.applyIf(o,this.params)});
        }
    }
});
/**
 * HPI.ee.PostcodePopup
 *
 * If the postcode is required but not provided, when the user attempts to view the results
 * window will pop up instead.
 *
 * A valid postcode (or just prefix) must then be provided before the user can continue on to
 * the results page
 */

HPI.ee.PostcodePopup = {

	init : function (postcode) {

		this.submit = new Ext.Button ({
			id: 'postcodePopupSubmit',
			type: 'button',
			text: 'View Results',
			disabled: true,
			listeners: {
                click: {
					scope: this,
					fn: function () {
					        this.win.close();
                            HPI.ee.Action.viewResults();
					}
				}
			}	
		});
	
		this.win = new Ext.Window({
			id: 'postcodePopup',
			title: 'Postcode Required',
			cls: 'fl-form',
			draggable: false,
			resizable: false,
			modal: true,
			shadow: false,
			width: 350,
			height: 200,
            validateOnBlur: false,
			items: [{
				layout: 'form',
				width: 300,
				height: 150,
				items: [{
					html: 'Please enter a valid UK postcode, so that we can find available cars which are closest to you.',
					cls: 'bodytext',
					style: 'padding-bottom:10px;'
				},{
					xtype: 'textfield',
					fieldLabel: 'Postcode',
					vtype: 'postcodeAllowPrefixOnly',
					id: 'postcodePopupField',
                    cls: 'postcode',
					allowBlank: false,
					msgTarget: 'under',
                    validationDelay: 500,
                    validateOnBlur: false,
					listeners: {
						valid: {
							fn: function () {
                                var val = Ext.getCmp('postcodePopupField').getValue().replace(" ","");
							
                                HPI.ee.matrixRefine.postcodeText.suspendEvents();
                                HPI.ee.matrixRefine.postcodeText.setValue(val.toUpperCase());
                                HPI.ee.matrixRefine.postcodeText.resumeEvents();
                                HPI.params.postcode = val.toUpperCase();
                                
                                //update the search result with the new postcode value
                                HPI.ee.Action.doStoreUpdate(HPI.params,null,true);
								Ext.getCmp('postcodePopupSubmit').enable();
							}
						},
						invalid: {
							fn: function () {
								Ext.getCmp('postcodePopupSubmit').disable();
							}
						},
						render: {
							fn: function () {
                                this.setValue(postcode);
								this.focus(true,230); //has to have enough delay for IE to focus on the field
							}
						},
						specialkey: {
							fn: function () {
								if (Ext.EventObject.getKey() == Ext.EventObject.ENTER)
								{
									Ext.getCmp('postcodePopupSubmit').fireEvent('click');
								}
							}
						}
					}
				}],
					
				buttons: [this.submit]
			}]
		});

		this.win.show();
	}
};
/**
 * HPI.ee.RefineForm.js
 *
 * A form panel widget that allows the user to filter searches.
 * This widget can be used on both the search and results pages.
 *
 * @author 		Dean McGill
 *
 * @class 		HPI.ee.RefineForm
 * @extends 	Ext.form.FormPanel
 */

// the refine combo box extension
HPI.ee.RefineComboBox = Ext.extend(Ext.form.ComboBox, {
	displayField: 'text',					// shows the 'text' field of the record on the form
	valueField: 'value',					// set the 'value' field of the record as the value of the option
	emptyText: 'Any...',					// sets the empty text, easily overridden if required
	mode: 'local',							// since we are using a MemoryProxy, the data is classed as local
	triggerAction: 'all',					// we want to see all of the data by default in the drop list
	width: 148,
	listWidth: 148,
	forceSelection: true,
	editable: false,
	listClass: 'refine-form-list',
	
	initComponent: function() {
		HPI.ee.RefineComboBox.superclass.initComponent.apply(this, arguments);
	},

/**
 * hide components if so configured
 */
	afterRender: function() {
		HPI.ee.RefineComboBox.superclass.afterRender.apply(this, arguments);
	},
	
	onSelect: function() {

		HPI.ee.RefineComboBox.superclass.onSelect.apply(this, arguments);
		HPI.params[this.name] = this.getValue();

        //call the store update of the refine form (which is parent to the combo)
        this.findParentByType(HPI.ee.RefineForm).callStoreUpdate(this);
    }

});

// the search refine form
HPI.ee.RefineForm = Ext.extend(Ext.FormPanel, {
 
	params: HPI.params,
	frame: true,
	labelAlign: 'top',
	width: 170,
	title: 'Refine Search',
	bodyStyle: 'padding:5px 5px 0',
	labelWidth: 80,
	cls: 'refine-form',
	postcodeRequired: HPI.properties.app.postcodeRequired,
    postcodeCookie: HPI.readCookie(HPI.properties.app.postcodeCookieKey, ""),

	/**
	 * The postcode text field takes a valid UK postcode, and can optionally
	 * accept the prefix only. When the value is validated it will enable
	 * the distance combo.
	 */
	getPostcodeText: function()	{
		
		return new Ext.form.TextField ({
			name: 'postcode',
			fieldLabel: 'Postcode',
            cls: 'postcode',
			vtype: 'postcodeAllowPrefixOnly',
			value: HPI.ee.RefineForm.postcodeCookie,
			validationDelay: 500,
            validateOnBlur: false,
            disabled: this.postcodeDisabled,
			width: 148,
			listeners: {
				render: {
					fn: function() {
						if (HPI.readCookie(HPI.properties.app.postcodeCookieKey, null) !== null)
						{
							this.setRawValue(HPI.readCookie(HPI.properties.app.postcodeCookieKey).toUpperCase());
						}
						else if (typeof HPI.params.postcode !== 'undefined')
						{
							this.setRawValue(HPI.params.postcode.toUpperCase());
						}
						HPI.params.postcode = this.getRawValue();
					}
				},
				valid: {
					scope: this,
					fn: function() {
                        this.distanceCombo.setDisabled(false);

                        //stop doing the validation first time its rendered.
                        if (!this.initialised)
                        {
                            this.initialised = true;
                            return true;
                        }
                        
                        //stop doing the store update if the postcode hasnt been changed
                        if (this.postcodeText.getRawValue() != HPI.params.postcode)
						{
                        	HPI.params.postcode = this.postcodeText.getValue();
                            
							HPI.ee.Action.doStoreUpdate(HPI.params);
						}
					}
				},
				invalid: {
					fn: function () {
						if (HPI.params.postcode)
						{
							delete HPI.params.postcode;
						}
					}
				},
				change: {
					fn: function () {
						this.validate();
					}
				}
			} // end of returned object definition
		});
	},

	/**
	 * The colour picker - essentially a dataview bound to a store with the colour names and 
	 * descriptions. Note that the actual color values are either CSS specified or images
	 */
	getColourDataView: function(parentPanel) {
        var that = this;
		return {
			xtype: 'dataview',
			height: 20,
			store: HPI.ee.DataManager.stores.colourStore,
			tpl: new Ext.XTemplate(
				'<tpl for=".">',
					'<div class="cp-swatch">',
						'<em><span class="swatch-{value}" unselectable="on"><img src="'+Ext.BLANK_IMAGE_URL+'" style="width:13px;height:15px" /></span></em>',
					'</div>',
				'</tpl>'),
			itemSelector: 'div.cp-swatch',
			multiSelect: true,
			simpleSelect: true,
			selectedClass: 'cp-swatch-sel',
			overClass: 'cp-swatch-over',
			listeners: {
				selectionchange: {
					fn: function() {
						delete HPI.params.colour;
						for ( var i = 0 ; i < this.getSelectedRecords().length ; i++ )
						{
							if (typeof HPI.params.colour !== 'undefined')
							{
								HPI.params.colour += ',';
								HPI.params.colour += this.getSelectedRecords()[i].get('value');
							}
							else
							{
								HPI.params.colour = this.getSelectedRecords()[i].get('value');
							}
						}

                        that.callStoreUpdate(null);
					}
				},
				mouseenter: {
					scope: this,
					fn: function (dataView,index,node,e) {
                        parentPanel.colourPicker.items.items[2].body.dom.innerHTML = dataView.store.getAt(index).get('text');
					}
				},
				mouseleave: {
					scope: this,
					fn: function (dataView,index,node,e) {
						parentPanel.colourPicker.items.items[2].body.dom.innerHTML = '&nbsp;';
					}
				}
			}
		};
	},

	getRefineCountPanel: function() {
		return new Ext.Panel({html: '&nbsp;', cls: 'refine-count'});
	},

	/**
	 * Refine combos - combos offering various filters for the search.
	 */
	defineFormElements: function() {
		
		this.refineCountPanel = this.getRefineCountPanel();

		this.distanceCombo = new HPI.ee.RefineComboBox({
			store: HPI.ee.DataManager.stores.distanceStore,
			name:'distance',
			hiddenName:'distance',
			disabled: true,
			fieldLabel: 'Distance'
		});

		this.priceCombo = new HPI.ee.RefineComboBox({
			store: HPI.ee.DataManager.stores.priceStore,
			name:'price',
			hiddenName:'price',
			fieldLabel: 'Price'
		});

		this.mileageCombo = new HPI.ee.RefineComboBox({
			store: HPI.ee.DataManager.stores.mileageStore,
			name: 'mileage',
			hiddenName:'mileage',
			fieldLabel: 'Mileage'
		});

		this.yearCombo = new HPI.ee.RefineComboBox({
			store: HPI.ee.DataManager.stores.yearStore,
			name:'year',
			hiddenName:'year',
			fieldLabel: 'Vehicle age'
		});

		this.transmissionCombo = new HPI.ee.RefineComboBox({
			store: HPI.ee.DataManager.stores.transmissionStore,
			name:'transmission',
			hiddenName: 'transmission',
			fieldLabel: 'Transmission'
		});
		
		this.bodyCombo = new HPI.ee.RefineComboBox({
			store: HPI.ee.DataManager.stores.bodyStore,
			name: 'body',
			hiddenName: 'body',
			fieldLabel: 'Body'
		});
		
		this.doorsCombo = new HPI.ee.RefineComboBox({
			store: HPI.ee.DataManager.stores.doorsStore,
			name: 'doors',
			hiddenName: 'doors',
			fieldLabel: 'Doors'
		});
		
		this.engineFromCombo = new HPI.ee.RefineComboBox({
			store: HPI.ee.DataManager.stores.engineFromStore,
			name: 'engineFrom',
			hiddenName: 'engineFrom',
			fieldLabel: 'Engine Range',
			emptyText: 'From...',
			listAlign: 'bl-tl?'
		});
		
		this.engineToCombo = new HPI.ee.RefineComboBox({
			store: HPI.ee.DataManager.stores.engineToStore,
			name: 'engineTo',
			hiddenName: 'engineTo',
			fieldLabel: '',
			labelSeparator: '',
			emptyText: 'To...',
			listAlign: 'bl-tl?'
		});

		this.colourPicker = this.getColourPicker();
		this.poaCheckBox = this.getPoaCheckBox();
		this.postcodeText = this.getPostcodeText();
	},

	/**
	 * Reset the refine form elements to initial state
	 *
	 */
	reset: function() {
        
        this.form.suspendEvents();
        this.poaCheckBox.suspendEvents();
        this.colourPicker.items.items[1].suspendEvents();
        this.postcodeText.suspendEvents();

		// reset actual form values
        if(HPI.readCookie(HPI.properties.app.postcodeCookieKey, null) !== null)
        {
            this.postcodeText.originalValue = HPI.readCookie(HPI.properties.app.postcodeCookieKey);
        }
        else if (typeof HPI.params.postcode !== 'undefined')
        {
            this.postcodeText.originalValue = HPI.params.postcode;
        }
        this.postcodeText.setValue(this.postcodeText.originalValue);

        this.form.reset();
        this.colourPicker.items.items[1].clearSelections(); //get the dataview that controls the selection and clear
        
        this.form.resumeEvents();
        this.poaCheckBox.resumeEvents();
        this.colourPicker.items.items[1].resumeEvents();
        this.postcodeText.resumeEvents();
	},

	getPoaCheckBox: function() {
        var that = this;
		return new Ext.form.Checkbox({
			hideLabel: true,
			name: 'poa',
			boxLabel: 'show POA',
			hiddenName: 'poa',
			listeners: {
				render: {
					fn: function() {
						if (HPI.params.poa === 'true' || HPI.params.poa === 'on')
						{
							this.suspendEvents(); // to prevent the check listener firing on initial render
							this.setValue(true);
							this.resumeEvents();
						}
					}
				},
				check: {
					fn: function() {
						HPI.params.poa = this.getValue();
                        
                        that.callStoreUpdate(null);
					}
				}
			}
		});
	},

	/**
	 * The complete colour picker component composed of the label, dataview and description text
	 */
	getColourPicker: function() {
		
		return new Ext.Panel(
		{	
			items: [
			{
				html: 'Click to Exclude:',
				cls: 'cp-label'
			},
			this.getColourDataView(this),
			{
				id: "colourDesc",
				html: '&nbsp;',
				cls: 'colour-desc'
			}]  // end of colour picker panel items
		});
	},

	initComponent: function() {

		this.defineFormElements();
			
	    // Build the refine form components
		Ext.apply(this, {
			items: [
				this.refineCountPanel,
				this.postcodeText,
				this.distanceCombo,
				this.priceCombo,
				this.poaCheckBox,
				this.mileageCombo,
				this.yearCombo,
				this.transmissionCombo,
				this.bodyCombo,
				this.engineFromCombo,
				this.engineToCombo,
				this.colourPicker,
				{
					xtype: 'hidden',
					name: 'sponsor',
					value: HPI.properties.sponsor
				},{
					xtype: 'hidden',
					name: 'models',
					id: 'hiddenModels',
					value: ''
				},{
					xtype: 'hidden',
					name: 'colour',
					id: 'hiddenColour',
					value: ''
				}
			] // end of refine form items
		});
  
		HPI.ee.RefineForm.superclass.initComponent.call(this);
        
		this.on('countupdate', function(count) {this.refineCountPanel.el.dom.innerHTML = count + ' vehicles found.';}, this);
	},

	checkPostcode: function (el) {

		if (!el.isValid())
		{
			// invalid postcode
			return false;
		}
		else
		{
			if (this.postcodeRequired && !el.getValue())
			{
				return false;
			}
			else
			{
				return true;
			}
		}
	},

	/**
	 *  Synchronises this forms values with that of the supplied refine form.  This form remains unchanged.
	 */
	synchronise: function(refineForm) {
        refineForm.refineCountPanel.el.dom.innerHTML = this.refineCountPanel.el.dom.innerHTML;
        refineForm.postcodeText.setValue(this.postcodeText.getValue()); 
		refineForm.distanceCombo.setValue(this.distanceCombo.getValue()); 
		refineForm.priceCombo.setValue(this.priceCombo.getValue()); 
		refineForm.mileageCombo.setValue(this.mileageCombo.getValue()); 
		refineForm.yearCombo.setValue(this.yearCombo.getValue()); 
		refineForm.transmissionCombo.setValue(this.transmissionCombo.getValue()); 
		refineForm.bodyCombo.setValue(this.bodyCombo.getValue()); 
		refineForm.engineFromCombo.setValue(this.engineFromCombo.getValue()); 
		refineForm.engineToCombo.setValue(this.engineToCombo.getValue());
        refineForm.colourPicker.items.items[1].select(this.colourPicker.items.items[1].getSelectedIndexes(), false, true);
        refineForm.poaCheckBox.setValue(this.poaCheckBox.getValue());
	},

    callStoreUpdate: function(comboElement)
    {
        if(this === HPI.ee.resultsRefine) //work matrix or result
        {
            //control the masks so that 2 of them dont show up at the same time
            HPI.ee.resultsMask.disable();
            HPI.ee.Action.doStoreUpdate(HPI.params, comboElement, false, 
                                        function(){
                                            HPI.ee.results.handleMasks(HPI.ee.defaultMask, true);
                                            HPI.ee.resultsMask.enable();
                                        },
                                        function(){
                                            HPI.ee.resultsRefine.handleMasks(HPI.ee.defaultMask, true);
                                            HPI.ee.resultsMask.enable();
                                        }
            );
        }
        else
        {
            HPI.ee.Action.doStoreUpdate(HPI.params, comboElement);
        }
    },

    /**
     * handle the masks so that it's hidden only when
     * 2 separate ajax requests (getting the results and populating combo in refine form)
     * are both completed.
     * used in callback of a storeupdate
     * 
     * @param mask {object} the mask to hide
     * @param isResultLoadComplete {boolean} flag to see if the resultlist process is completed
     **/
    handleMasks: function(mask, isResultLoadComplete)
    {
        //if both process has completed, hide the mask thats been passed in
        //unless its a the value is not set ignore?
        if(this.isUpdateComplete == 'undefined' || (this.isUpdateComplete === true && isResultLoadComplete))
        {
            mask.hide();
        }
    }
});
/**
 * Column Model for the standard multi dealer result grid
 */
Ext.ns("HPI.ee.Results.widths");
HPI.ee.Results.widths.IMAGE = 95;
HPI.ee.Results.widths.YEAR = 55;

if (Ext.isIE){
	HPI.ee.Results.widths.DESCRIPTION = 265;
} else {
	HPI.ee.Results.widths.DESCRIPTION = 270;
}

HPI.ee.Results.widths.COLOUR = 70;
HPI.ee.Results.widths.MILEAGE = 70;
HPI.ee.Results.widths.PRICE = 60;
HPI.ee.Results.widths.DISTANCE = 90;
HPI.ee.Results.widths.FUEL = 90;
HPI.ee.Results.widths.GRID = 720;

HPI.ee.AllDealerColumnModel = new Ext.grid.ColumnModel([{
	header: '',
	dataIndex: 'image',
	width: HPI.ee.Results.widths.IMAGE,
	menuDisabled: true,
	sortable: true,
	renderer: function (val, pos, rec, row, col, store) {
		pos.cellAttr = 'rowspan="2"';
		
		return HPI.ee.Template.resultsImageCellTpl.applyTemplate({
			stockId: rec.get('stockId'),
			resultId: store.reader.jsonData.resultId,
			description: rec.get('description'),
			imageUrl: val,
            isSingleDealer: false
		});
	},
	fixed: true
}, {
	header: 'Year',
	dataIndex: 'modelYear',
	width: HPI.ee.Results.widths.YEAR,
	menuDisabled: true,
	sortable: true,
	renderer: function (val, pos, rec)
	{
		if (val) {
			return val; 
		}
		else 
		{
			return '&nbsp;';
		}
	},
	fixed: true
}, {
	header: 'Description',
	dataIndex: 'description',
	width: HPI.ee.Results.widths.DESCRIPTION,
	menuDisabled: true,
	sortable: true,
	renderer: function (val, pos, rec, row, col, store)
	{
		return '<a class="description" title="' + val + '" onclick="javascript:HPI.ee.Action.showAdvert({stockId:\''+rec.get('stockId')+'\',resultId:\''+store.reader.jsonData.resultId+'\'})">' + Ext.util.Format.ellipsis(val,35) + '</a>';
	},
	fixed: true
}, {
	header: 'Colour',
	dataIndex: 'colour',
	align: 'center',
	width: HPI.ee.Results.widths.COLOUR,
	menuDisabled: true,
	sortable: true,
	renderer: function (val)
	{
		return '<div class="cp-swatch"><em><span class="swatch-' + val + '">&#160;</span></em></div>';
	},
	fixed: true
}, {
	header: 'Mileage',
	dataIndex: 'mileage',
	width: HPI.ee.Results.widths.MILEAGE,
	menuDisabled: true,
	sortable: true,
	renderer: function (val)
	{
		return HPI.formatNumber(val,0);
	},
	fixed: true
}, {
	header: 'Price',
	dataIndex: 'price',
	width: HPI.ee.Results.widths.PRICE,
	menuDisabled: true,
	sortable: true,
	renderer: function (val)
	{
		if (val === 0) {
			return 'POA';
		}
		else {
			return HPI.formatNumber(val,0,'&pound;');
		}
	},
	fixed: true
}, {
	header: 'Distance',
	dataIndex: 'distance',
	align: 'right',
	width: HPI.ee.Results.widths.DISTANCE,
	menuDisabled: true,
	sortable: true,
	renderer: function (val)
	{
		return (val === 0 ? '' : val + ' miles');
	},
	fixed: true
}]);

/**
 * Column model for the single dealer results
 */

HPI.ee.SingleDealerColumnModel = new Ext.grid.ColumnModel([{
	header: '',
	dataIndex: 'image',
	width: HPI.ee.Results.widths.IMAGE,
	menuDisabled: true,
	sortable: true,
	renderer: function (val, pos, rec, row, col, store) {
		pos.cellAttr = 'rowspan="2"';
		return HPI.ee.Template.resultsImageCellTpl.applyTemplate({
			stockId: rec.get('stockId'),
			resultId: store.reader.jsonData.resultId,
			description: rec.get('description'),
			imageUrl: val,
            isSingleDealer: true
		});
	},
	fixed: true
}, {
	header: 'Year',
	dataIndex: 'modelYear',
	width: HPI.ee.Results.widths.YEAR,
	menuDisabled: true,
	sortable: true,
	renderer: function (val, pos, rec)
	{
		if (val) {
			return val; 
		}
		else 
		{
			return '&nbsp;';
		}
	},
	fixed: true
}, {
	header: 'Description',
	dataIndex: 'description',
	width: HPI.ee.Results.widths.DESCRIPTION,
	menuDisabled: true,
	sortable: true,
	renderer: function (val, pos, rec, row, col, store)
	{
		return '<a class="description" title="' + val + '" onclick="javascript:HPI.ee.Action.showAdvert({stockId:\''+rec.get('stockId')+'\',resultId:\''+store.reader.jsonData.resultId+'\'})">' + Ext.util.Format.ellipsis(val,38) + '</a>';
	},
	fixed: true
}, {
	header: 'Colour',
	dataIndex: 'colour',
	align: 'center',
	width: HPI.ee.Results.widths.COLOUR,
	menuDisabled: true,
	sortable: true,
	renderer: function (val)
	{
		return '<div class="cp-swatch"><em><span class="swatch-' + val + '">&#160;</span></em></div>';
	},
	fixed: true
}, {
	header: 'Mileage',
	dataIndex: 'mileage',
	width: HPI.ee.Results.widths.MILEAGE,
	menuDisabled: true,
	sortable: true,
	renderer: function (val)
	{
		return HPI.formatNumber(val,0);
	},
	fixed: true
}, {
	header: 'Price',
	dataIndex: 'price',
	width: HPI.ee.Results.widths.PRICE,
	menuDisabled: true,
	sortable: true,
	renderer: function (val)
	{
		if (val === 0) {
			return 'POA';
		}
		else {
			return HPI.formatNumber(val,0,'&pound;');
		}
	},
	fixed: true
}, {
	header: 'Fuel',
	dataIndex: 'fuel',
	align: 'right',
	width: HPI.ee.Results.widths.FUEL,
	menuDisabled: true,
	sortable: true,
	fixed: true
}]);

/**
 * The results grid.
 * A column model and store should be passed in the object configuration
 *
 */

HPI.params.start = 0;
HPI.params.limit = 5;

HPI.ee.ResultsGrid = Ext.extend(Ext.grid.GridPanel, {

	params: {}, // overwrite when creating instances
	cls: 'results',
	width: HPI.ee.Results.widths.GRID,
	stripeRows: true,
	enableColumnMove: false,
    trackMouseOver: false,
    listeners: {
        sortchange: {
            fn: function(){
                this.getSelectionModel().clearSelections();
            }
        }
    },
	initComponent : function ()
	{
		Ext.apply(this, {
			bbar : new HPI.ee.PagingToolbar({
				pageSize: 5,
				params: this.params,
				store: this.store,
                firstText: 'First',
                nextText: 'Next',
                lastText: 'Last',
                previousText: 'Previous',
				displayInfo: true,
				displayMsg: 'Displaying vehicles {0} - {1} of {2}',
				emptyMsg: "No vehicles to display",
                listeners: {
                    render: function(){
                        //set the paging text for the buttons
                        this.first.setText(this.firstText);
                        this.prev.setText(this.previousText);
                        this.next.setText(this.nextText);
                        this.last.setText(this.lastText);
                        this.loading.setText(this.refreshText);
                        
                        /** for IE6 only, to manually add and remove disabled style class */
                        this.first.on("enable", function(el){
                            if(Ext.isIE6)
                            {
                                el.removeClass("x-item-disabled");
                            }
                        });

                        this.first.on("disable", function(el){
                            if(Ext.isIE6)
                            {
                                el.addClass("x-item-disabled");
                            }
                        });

                        this.prev.on("enable", function(el){
                            if(Ext.isIE6)
                            {
                                el.removeClass("x-item-disabled");
                            }
                        });

                        this.prev.on("disable", function(el){
                            if(Ext.isIE6)
                            {
                                el.addClass("x-item-disabled");
                            }
                        });

                        this.next.on("enable", function(el){
                            if(Ext.isIE6)
                            {
                                el.removeClass("x-item-disabled");
                            }
                        });

                        this.next.on("disable", function(el){
                            if(Ext.isIE6)
                            {
                                el.addClass("x-item-disabled");
                            }
                        });

                        this.last.on("enable", function(el){
                            if(Ext.isIE6)
                            {
                                el.removeClass("x-item-disabled");
                            }
                        });

                        this.last.on("disable", function(el){
                            if(Ext.isIE6)
                            {
                                el.addClass("x-item-disabled");
                            }
                        });
                        /** end of IE6 only code **/
                    }
                }
			})
		});

		HPI.ee.ResultsGrid.superclass.initComponent.apply(this, arguments);
        
        var that = this;
		this.store.on('load',function (args) {
            
            // set the compare checkboxes on store reload
            HPI.ee.CompareHandler.markItems();

            // write transaction if the results are reloaded within result page itself
            // by checking if the current active panel is result
            if(HPI.ee.viewport.layout.activeItem.id === HPI.ee.RESULTS_ALL_VIEW)
            {
                HPI.ee.Transaction.writeResultTransaction(HPI.ee.results.store);
            }
            that.isLoadComplete = true;
		});

		this.on('storeupdate',function(args){
            if(this.getSelectionModel().selections.length > 0)
            {
                this.getSelectionModel().clearSelections();
            }
            this.store.load({params: this.params, callback: args.callback});
        });
	},
    
    /**
     * handle the masks so that it's hidden only when
     * 2 separate ajax requests (getting the results and populating combo in refine form)
     * are both completed.
     * used in callback of a storeupdate
     * 
     * @param mask {object} the mask to hide
     * @param isMatrixCountComplete {boolean} flag to see if the matrix count process is completed
     **/
    handleMasks: function(mask, isMatrixCountComplete)
    {
        //if both process has completed, hide the mask thats been passed in
        //unless the value is undefined (which means its single dealer), ignore
        if(this.isLoadComplete == 'undefined' || (this.isLoadComplete === true && isMatrixCountComplete))
        {
            mask.hide();
        }
    }
	
});
/**
 * A class that renders the vehicle data in a panel. The
 * loading of the data is abstracted to the DataManager class.
 *
 * When the DTO is ready (regardless if cached) an event will fire on the
 * this initlised object that will template the data and return the object.
 *
 * Do not apply extra object properties directly to the DTO. Instead pass a
 * into the method and apply with in the function scope.
 */

HPI.ee.VehiclePanel = Ext.extend(Ext.Panel, {

    initComponent : function () 
    {
        Ext.apply(this, {
            layout: 'column',
            id: HPI.ee.ADVERT_PANEL_ID,
            height: HPI.ee.FULL_HEIGHT,
            border: false,
            defaults: {border: false},
            items: [
                this.westAdvertPanel,
                {
                    layout: 'border',
                    height: HPI.ee.FULL_HEIGHT,
                    width: 720 ,
                    items: [{
                        layout: 'column',
                        region: 'north',
                        border: HPI.DEBUG,
                        height: HPI.ee.NORTH_HEIGHT,
                        items: [{
                            id: "advert-north",
                            xtype: 'panel',
                            width: 550,
                            height: HPI.ee.NORTH_HEIGHT,
                            border: HPI.DEBUG
                        },{
                            id: "advert-navigation",
                            xtype: 'panel',
                            width: 170,
                            height: HPI.ee.NORTH_HEIGHT,
                            border: HPI.DEBUG
                        }]
                    },{
                        xtype: 'panel', 
                        region: 'west',
                        id: 'advert-west-ct',
                        width: 320,
                        height: 450,
                        border: HPI.DEBUG,
                        items: [this.imageGallery,this.dealerDetailsPanel]
                    },{
                        xtype: 'panel',
                        region: 'center',
                        height: 450,
                        width: 100,
                        border: HPI.DEBUG,
                        items: [this.getVehicleDetailsTab(), this.advertNavigationToolbar]
                    }]
            }] 
        }, this);

        HPI.ee.VehiclePanel.superclass.initComponent.call(this);

        this.on('dtoready', function (dto) {
            this.dto = dto;
            this.load();
        });
    },

    westAdvertPanel : new Ext.Panel({
        width: 160,
        height: 520
    }),

/**
 * return the dealer details panel (advert)
 * @param {object} data - the DTO for the vehicle
 */
    dealerDetailsPanel : new Ext.Panel({
        cls: 'dealer-details',
        title: 'dealer details',
        width: 302
    }),

/**
 * return the vehicle details tab panel (advert)
 * @param {object} data - the DTO for the vehicle
 */
    vehicleDetailsPanel : new Ext.Panel({
        title: 'vehicle details',
        iconCls: 'tab-icon',
        width: 300,
        autoScroll: true
    }),
/**
 * return the vehicle equipment tab panel (advert)
 * @param {object} data - the DTO for the vehicle
 */
    equipmentPanel : new Ext.Panel({
        title: 'equipment',
        iconCls: 'tab-icon',
        width: 300,
        autoScroll: true
    }),
/**
 * return the vehicle technical data tab panel (advert)
 * @param {object} data - the DTO for the vehicle
 */
    technicalDataPanel : new Ext.Panel({
        title: 'technical data',
        iconCls: 'tab-icon',
        width: 300,
        autoScroll: true
    }),

/**
 * return the vehicle info tab panel container (advert)
 * @param {object} data - the DTO for the vehicle
 */
    getVehicleDetailsTab : function (data) {

        return {
            xtype: 'tabpanel',
            id: 'advert-tabs',
            deferredRender: false,
            cls: 'vehicle-info x-tab-show',
            layoutOnTabChange: true,
            plain: true,
            width: 400,
            height: 435,
            activeTab: 0,
            items: [
                this.vehicleDetailsPanel,
                this.equipmentPanel,
                this.technicalDataPanel
            ]
        };
    },

    advertNavigationToolbar: new Ext.Panel({
        cls: 'vehicle-navigation x-toolbar',
        width: 400,
        height: 25,
        html: "",
        border: false
    }),

    /**
     *
     */
    getImagesForAdvert: function(dto) {
                
        // array of images (conforms to max)
        var imageData = [];
        
        if (dto.exchangeImages.list.length > 0)
        {
            // only display max of 6 images
            for (var i = 0; (i<dto.exchangeImages.list.length && i<6); i++)
            {
                imageData.push({
                    thumb: dto.thumbImages.list[i].imageId,
                    exchange: dto.exchangeImages.list[i].imageId,
                    medium: dto.mediumImages.list[i].imageId,
                    html: '<img src="/images/'+dto.exchangeImages.list[i].imageId+'"/>',
                    title: i + 1
                });
            }
            
            // add a zoom button
            imageData.push({
                html: 'zoom body',
                tabCls: 'zoomTabTitle',
                title: 'Zoom'
            });
        }
        else
        {
            // no image
            imageData.push({
                html: '<img src="' + HPI.properties.noimage.exchange + '"/>',
                tabCls: 'noPhotoTabTitle',
                title: 'Awaiting photography'
            });
        }

        return imageData;
    },

    imageGallery : new Ext.TabPanel({
        tabPosition: 'bottom',
        cls: 'gallery',
        width: 302,
        height: 253,
        deferredRender: false,
        activeTab: 0,
        items: [{
            html: '',
            title: 'loading...',
            id: 'preload',
            tabCls: 'preloadTabTitle'
        },{
            html: '<img src="' + HPI.properties.noimage.exchange + '"/>',
            title: 'awaiting photography',
            id: 'no-photo',
            tabCls: 'noPhotoTabTitle'
        }],
        listeners: {
            render: {
                fn: function () {
                    Ext.getCmp('no-photo').hide();
                    this.hideTabStripItem(Ext.getCmp('no-photo'));
                }
            }
        },
        onStripMouseDown: function (e) {

            /* identify the zoom button by tab button containing "zoom".
             * if zoom tab button clicked, launch the image zoom
             * else display selected image on tab pane
             */
            if (Ext.fly(e.getTarget()).dom.innerHTML.indexOf('zoomTabTitle') == -1 && Ext.fly(e.getTarget()).dom.innerHTML.indexOf('zoom') > -1)
            {
                HPI.ee.vehiclePanel.zoomLauncher();
                return false;
            }
            else
            {
                this.constructor.prototype.onStripMouseDown.apply(this, arguments);
            }
        }
    }),

    doPagingToolbar: function(isUpdate)
    {
        function getNavigationData(dto, navigationData)
        {
            return {
                navigationData: navigationData,
                current: HPI.ee.CompareHandler.getColumnIndex(dto) + 1,
                isSingleDealer: HPI.ee.DataManager.isSingleDealer
             };
        }
            
        if(this.dto.isCompareAdvert)
        {
            var navigationData = [];
            
            var compareKeys = HPI.ee.CompareHandler.keys;

            for (var i=0; i<compareKeys.length; i++) {
                var  compareDto = HPI.ee.DataManager.data.get(HPI.ee.DataManager.data.findIndex('stockId',compareKeys[i]));
                navigationData[i] = {resultId: compareDto.resultId, stockId: compareDto.stockId};
            }

            if(isUpdate)
            {
                HPI.ee.Template.advertComparePagingTpl.overwrite(this.advertNavigationToolbar.body, getNavigationData(this.dto, navigationData));
            }
            else
            {
                this.advertNavigationToolbar.html = HPI.ee.Template.advertComparePagingTpl.applyTemplate(getNavigationData(this.dto, navigationData));
            }
            
        }
        else // when not a compare advert
        {
            if(isUpdate)
            {
                HPI.ee.Template.advertPagingToolbarTpl.overwrite(this.advertNavigationToolbar.body, {dto:this.dto, isSingleDealer:HPI.ee.DataManager.isSingleDealer});
            }
            else  
            {
                this.advertNavigationToolbar.html = HPI.ee.Template.advertPagingToolbarTpl.applyTemplate({dto:this.dto, isSingleDealer:HPI.ee.DataManager.isSingleDealer});
            }
        }
    },

    /**
     * get the configured layout and add to the new panel
     */
    load : function ()
    {
        this.updateAdvertPanel();
        
        HPI.ee.defaultMask.hide();
    },

    /**
     *
     *
     */
    updateAdvertPanel: function() {
    
        if(this.dto.vehicleAvailable)
        {
            Ext.getCmp("advert-tabs").show();
            Ext.getCmp("advert-west-ct").show();
            
            HPI.ee.Template.advertVehicleTechnicalDataTpl.overwrite(this.technicalDataPanel.body,    
                Ext.apply(this.dto.stockDetails,{na: ''})
            );
    
            HPI.ee.Template.advertDealerDetailsTpl.overwrite(this.dealerDetailsPanel.body,  
                Ext.apply(this.dto,{isSingleDealer: HPI.ee.DataManager.isSingleDealer})
            );
            
            HPI.ee.Template.advertVehicleEquipmentTpl.overwrite(this.equipmentPanel.body,  
                Ext.apply(this.dto,{na: ''})
            );
    
            HPI.ee.Template.advertVehicleDetailsTpl.overwrite(this.vehicleDetailsPanel.body,    
                Ext.apply(this.dto,{na: ''})
            );
    
            this.imageGallery.unhideTabStripItem('preload');
            this.imageGallery.hideTabStripItem(Ext.getCmp('no-photo'));
            Ext.getCmp('preload').show();
    
            if (this.numberImages)
            {
                for (i = 0; i < this.numberImages; i++)
                {
                    this.imageGallery.remove('img-'+i);
                }
                this.imageGallery.remove('zoom-tab');
            }
    
            this.numberImages = this.dto.exchangeImages.list.length;
    
            // cap the max number of images
            if (this.numberImages > 6)
            {
                this.numberImages = 6;
            }
    
            this.images = [];
            this.exchangeImages = [];
            this.thumbImages = [];
            this.mediumImages = [];
    
            if (this.numberImages > 0)
            {
                // build the array of images
                for (i = 0; i < this.numberImages; i++)
                {
                    // different preloader for first image
                    if (i !== 0)
                    {
                        this.images.push('/images/'+this.dto.exchangeImages.list[i].imageId);
                    }
                    this.exchangeImages.push('/images/'+this.dto.exchangeImages.list[i].imageId);
                    this.thumbImages.push('/images/'+this.dto.thumbImages.list[i].imageId);
                    this.mediumImages.push('/images/'+this.dto.mediumImages.list[i].imageId);
                }
    
                this.importImages(this.dto);
            }
            else
            {
                // show awaiting photography image
                this.imageGallery.hideTabStripItem(Ext.getCmp('preload'));
                this.imageGallery.unhideTabStripItem(Ext.getCmp('no-photo'));
                Ext.getCmp('no-photo').show();
                this.imageGallery.setActiveTab('no-photo');
            }
    
            HPI.ee.Template.northAdvertPanelTpl.overwrite(Ext.getCmp("advert-north").body, {vehicle: {
                                    description: this.dto.vehicleModelDescription,
                                    price: this.dto.stockDetails.price,
                                    specialDate: this.dto.stockDetails.specialDisplayDate,
                                    specialCode: this.dto.stockDetails.specialDisplay
                                }});
            
        }
        else
        {
            Ext.getCmp("advert-north").body.dom.innerHTML = "<div><h3>Sorry</h3><p>Requested vehicle is no longer available.</p></div>";
            Ext.getCmp("advert-tabs").hide(); //vehicle detail, equipemnt and tech data
            Ext.getCmp("advert-west-ct").hide(); //image gallary + dealer
        }

        HPI.ee.Template.westAdvertPanelTpl.overwrite(this.westAdvertPanel.body, {
            title: 'Vehicle Details',
            vehicle: {
                custId: this.dto.stockDetails?this.dto.stockDetails.custId:'',
                stockId: this.dto.stockId
            }
        });
        
        this.doPagingToolbar(true);
        
        HPI.ee.Template.advertNavigationPanelTpl.overwrite( Ext.getCmp("advert-navigation").body, 
            Ext.apply(HPI.ee.Template.backFromAdvertConfig, {type: this.dto.isCompareAdvert?"compare":"advert"})
        );
        
        /*
         * The active advert tab is reset to the vehicle details tab when paging through adverts.
         */ 
        Ext.getCmp("advert-tabs").setActiveTab(0);
    },

    importImages : function (dto)
    {
        var that = this;
        var imageLoader = new ImagePreloader(this.exchangeImages, function () {

            that.imageGallery.hideTabStripItem(Ext.getCmp('preload'));

            for (var i=0; i < that.numberImages; i++)
            {
                that.imageGallery.add({
                    html: '<img src="' + that.exchangeImages[i] + '" width="300" height="225"/>',
                    title: i+1,
                    id: 'img-'+i
                });
            }
            that.imageGallery.add({
                html: 'zoom body',
                title: 'zoom',
                id: 'zoom-tab',
                tabCls: 'zoomTabTitle'
            });

            that.imageGallery.hideTabStripItem(Ext.getCmp('no-photo'));
            that.imageGallery.setActiveTab('img-0');
        });

        imageLoader.preload();
    },

    zoomLauncher : function () {

        HPI.ee.zoom.launch({
            thumbImages: this.thumbImages,
            mediumImages: this.mediumImages,
            currentImage: (this.imageGallery.getActiveTab().title - 1),
            title: this.dto.stockDetails.vehicleDescription + ' - ' + HPI.formatNumber(this.dto.stockDetails.price,0,'&pound;')
        });
    }
});

HPI.ee.vehiclePanel = new HPI.ee.VehiclePanel();
/**
 * <pre>
 * Copyright (c) HPI Limited 2009
 *
 * All rights reserved. No part of this work may be reproduced or
 * transmitted, in any form or by any means, or adapted (including for
 * the purposes of error correction) without the written permission of
 * the copyright owner except in accordance with the provisions of the
 * Copyright, Designs and Patents Act 1988 or under the terms of a
 * Licence entered into with the copyright owner.
 *
 * Warning: the doing of an unauthorised act in relation to a copyright
 * work may result in both a civil claim for damages and a criminal
 * prosecution.
 * </pre>
 * <p>
 *
 * </p>
 *
 * @class		HPI.ee.TransactionHandler
 * @author		Dean McGill
 *
 * @namespace  	A generic class that provides transaction recording to the application.
 * @name 		HPI.ee.TransactionHandler
 */

HPI.ee.Transaction = (function () {

	return {
/**
 * Perform the transaction call
 */
		writeTransaction : function (stockId,type)
		{
			// for arrays of stockIds process into URL friendly string
			if (typeof stockId == 'object')
			{
				var tmp = '';
				for (var i = 0 ; i < stockId.length ; i++ )
				{
					if (tmp !== '')
					{
						tmp += ',';
					}
					tmp += stockId[i];
				}
				stockId = tmp;
			}
            else if(typeof stockId == 'number')
            {
                stockId += ""; //its a stock id passed in as a numeric from advert convert to string.
                               //otherwise IE complains with our isBlank method.
            }

            //dont call the transaction if stock id is empty (ie nothing returned in result by refining)
            if(!HPI.StringUtils.isBlank(stockId))
            {
                Ext.Ajax.request({
                    url: HPI.properties.urls.storeData,
                    params: {
                        type: type,
                        stkid: stockId
                    }
                });
            }
		},

/**
 * write transaction for all and single dealer results displayed
 *
 * @param {object} store that holds the list of stock details (which in turn holds the stock id) 
 */
        writeResultTransaction: function(p_store)
        {
            var stockIds = [];
            p_store.each(function () {
                stockIds.push(this.get('stockId'));
            });
            
            this.writeTransaction(stockIds,'multiple');
        }
	}

})();

Ext.apply(HPI.ee.Transaction, new Ext.util.Observable());
/**
 * Viewport layout
 */

/**
 * DEBUG
 * Used to show component borders for layout
 */
HPI.DEBUG = false;

/**
 * Height of the north region
 */
HPI.ee.NORTH_HEIGHT = 50;

/**
 * width of the east region
 */
HPI.ee.EAST_WIDTH = 185;

/**
 * width of the west region
 */
HPI.ee.WEST_WIDTH = 180;

HPI.ee.FULL_WIDTH = 910;
HPI.ee.FULL_HEIGHT = 520;
HPI.ee.MATRIX_WIDTH = 550;
HPI.ee.REFINE_WIDTH = 180;
HPI.ee.BLURB_HEIGHT = 500;
HPI.ee.RESULT_GRID_HEIGHT = 450

/**
 * View constants for controlling the application view
 */

HPI.ee.SEARCH_MATRIX_VIEW = 'search-matrix-view';
HPI.ee.RESULTS_ALL_VIEW = 'results-all-view';
HPI.ee.RESULTS_SINGLE_VIEW = 'results-single-view';
HPI.ee.COMPARE_VIEW = 'compare-view';
HPI.ee.ADVERT_VIEW = 'advert-view';

HPI.ee.ADVERT_PANEL_ID = 'advertTab';

// loading mask
HPI.ee.startmask = {

	maskEl: Ext.get('loading-mask'),
	
	isShowing: true,
	msg: 'Please wait while the application loads',
	statusMsg: Ext.getDom('loading-mask-status'),

	// overide the LoadMask hide method 
    hide: function(){
		this.isShowing = false;
		this.maskEl.shift({
			opacity: 0,
			duration: 2,
			remove: true
		});
    }
};

Ext.onReady(function () {
    
    HPI.params.postcode = HPI.readCookie(HPI.properties.app.postcodeCookieKey, "").toUpperCase();
	Ext.reg('modelmatrix', HPI.ee.ModelMatrix);
	Ext.reg('refineform', HPI.ee.RefineForm);

	HPI.ee.resultsRefine = new HPI.ee.RefineForm({params: HPI.params, postcodeDisabled: true, isUpdateCompleted: false});
	HPI.ee.matrixRefine = new HPI.ee.RefineForm({params: HPI.params, id: 'matrixRefineForm', postcodeDisabled: false});
		
	HPI.ee.defaultBlurb = [
			'<p>Buying a pre-owned car through an official Lotus dealer is a guarantee that you are getting a vehicle of the highest possible quality, with every car subject to the most demanding of inspections.</p>',
			'<p>The vehicle\'s mechanics, electrics, exterior and interior are all tested to our exacting factory standards, with a full mileage and history providing additional peace of mind.</p>',
			'<p>Our unrivalled knowledge and expertise is supported by a 12-month warranty and roadside assistance package, making Lotus the obvious choice when selecting your used vehicle.</p>'
	];

	HPI.ee.matrix = new HPI.ee.ModelMatrix ({
		border: HPI.DEBUG,
		blurbId: 'blurb',
		defaultBlurb: HPI.ee.defaultBlurb.join(''),
		width: HPI.ee.MATRIX_WIDTH
	});

	HPI.ee.results = new HPI.ee.ResultsGrid({
		id: 'resultsGrid',
		store: HPI.ee.DataManager.stores.allDealerStore,
		height: HPI.ee.RESULT_GRID_HEIGHT,
		cm: HPI.ee.AllDealerColumnModel,
		view: new Ext.grid.GridView({
				enableRowBody: true,
				emptyText: 'No vehicles can be found matching your search.',
				getRowClass: function(rec,index,params,store) {
					params.cols = 7;
					params.body = HPI.ee.Template.resultsRowBodyTpl.applyTemplate(Ext.apply(rec.data, {
						resultId: store.reader.jsonData.resultId,
                        isSingleDealer: false
					}));
				}
			}),
		params: HPI.params,
        isLoadComplete: false
	});


	HPI.ee.singleDealerResults = new HPI.ee.ResultsGrid({
		id: 'singleResultsGrid',
		height: HPI.ee.RESULT_GRID_HEIGHT,
		params: {}, // add parameter attributes to this object to apply serach criteria
		store: HPI.ee.DataManager.stores.singleDealerStore,
		cm: HPI.ee.SingleDealerColumnModel,
		view: new Ext.grid.GridView({
			enableRowBody: true,
			emptyText: 'No vehicles can be found matching your search.',
			getRowClass: function(rec,index,params,store) {
				params.cols = 7;
				params.body = HPI.ee.Template.resultsRowBodyTpl.applyTemplate(Ext.apply(rec.data, {
					resultId: store.reader.jsonData.resultId,
                    isSingleDealer: true
				}));
			}
		})
	});

HPI.ee.searchMatrixView = new Ext.Panel({
		id: HPI.ee.SEARCH_MATRIX_VIEW,
		layout: 'border',
		border: false,
		defaults: {border: false},
		items: [{
			region: 'north',
			cls: 'north',
			height: HPI.ee.NORTH_HEIGHT,
			html: HPI.ee.Template.northPanelTpl.apply(HPI.ee.Template.northConfigMatrix)
		},{
			id: 'blurb',
			region: 'west',
			cls: 'blurb-ct',
			width: HPI.ee.WEST_WIDTH,
			html: HPI.ee.defaultBlurb.join('')
		},{	
			region: 'center',
			items: [HPI.ee.matrix]
		},{
			width: HPI.ee.EAST_WIDTH,
			region: 'east',
			cls: 'east',
            margins: {
                top: -20 // move up the panel to go just under the view result button instead of matching the top side with the center panel
            },
			items: [
				HPI.ee.matrixRefine, 
				{
					border: HPI.DEBUG,
					html:  '<ul><li><button class="submit" onMouseOver="HPI.handleButtonHover(this, true)" onMouseOut="HPI.handleButtonHover(this, false)" onclick="'+HPI.ee.Template.northConfigMatrix.navigation[0].action+'">'+HPI.ee.Template.northConfigMatrix.navigation[0].text+'</button></li></ul>'
				}
			]
		}]
	});

	HPI.ee.resultsAllView = new Ext.Panel({
		id: HPI.ee.RESULTS_ALL_VIEW,
		layout: 'border',
		border: HPI.DEBUG,
		items: [{
			region: 'north',
			cls: 'north',
			border: HPI.DEBUG,
			height: HPI.ee.NORTH_HEIGHT,
			width: HPI.ee.FULL_WIDTH,
			html: HPI.ee.Template.northPanelTpl.apply(HPI.ee.Template.northConfigResults)
		},{
			cls: 'results',
			region: 'center',
			border: HPI.DEBUG,
			items: [HPI.ee.results]
		},{
			width: HPI.ee.EAST_WIDTH,
			region: 'east',
			border: HPI.DEBUG,
			items: [HPI.ee.resultsRefine]
		}]
	});

	HPI.ee.compareView = new Ext.Panel({
		id: HPI.ee.COMPARE_VIEW,
		cls: 'compare',
		layout: 'border',
		border: HPI.DEBUG,
		autoScroll: true,
		items: [{
			border: HPI.DEBUG,
			cls: 'north',
			region: 'north',
			id: 'compare-north',
			height: HPI.ee.NORTH_HEIGHT,
			width: HPI.ee.FULL_WIDTH,
			html: HPI.ee.Template.northPanelTpl.apply(HPI.ee.Template.northConfigCompareAllDealer)
		},{
			region: 'center',
			border: HPI.DEBUG,
			items: [new HPI.ee.ComparePanel()]
		}]
	});

	HPI.ee.resultsSingleView = new Ext.Panel({
		id: HPI.ee.RESULTS_SINGLE_VIEW,
		layout: 'border',
		border: HPI.DEBUG,
		items: [{
			region: 'north',
			id: 'singleDealerResults-north',
			cls: 'north',
			border: HPI.DEBUG,
			height: HPI.ee.NORTH_HEIGHT,
			width: HPI.ee.FULL_WIDTH,
			html: HPI.ee.Template.northPanelTpl.apply(HPI.ee.Template.northConfigSingleDealer)
		},{
			cls: 'results',
			id: 'singleDealerResultsCenter',
			region: 'center',
			border: HPI.DEBUG,
			items: [HPI.ee.singleDealerResults]
		},{
			width: HPI.ee.EAST_WIDTH,
			region: 'east',
			border: HPI.DEBUG,
			html: HPI.ee.defaultBlurb
		}] // end of single dealer results items
	});

	HPI.ee.vehiclePanel = new HPI.ee.VehiclePanel();

	HPI.ee.advertView = new Ext.Panel({
		id: HPI.ee.ADVERT_VIEW,
		height: HPI.ee.FULL_HEIGHT,
		border: HPI.DEBUG,
		items: [HPI.ee.vehiclePanel] 
	});
	
	HPI.ee.viewport = new Ext.Viewport({
		id: 'cardLayout',
		defaults: {hideMode: 'offsets'},
		border: HPI.debug,
		layout: 'card',
		activeItem: 0,
		items: [
			HPI.ee.searchMatrixView,
			HPI.ee.resultsAllView,
			HPI.ee.compareView,
			HPI.ee.resultsSingleView,
			HPI.ee.advertView
		]   // end of card layout items
	}); // end of viewport

    //mask that comes on when all dealer results store is being updated
    HPI.ee.resultsMask = new Ext.LoadMask(HPI.ee.resultsAllView.body,{
		msg: 'Updating...',
		msgCls: 'resultsMask x-mask-loading',
		store: HPI.ee.results.store
	});

    //mask that comes on when single dealer results store is being updated
	HPI.ee.singleDealerResultMask = new Ext.LoadMask(HPI.ee.resultsSingleView.body,{
        msg: 'Updating...',
        store: HPI.ee.singleDealerResults.store
    });

    //mask to deal with other processes, such as updating the refine form values or address lookup
	HPI.ee.defaultMask = new Ext.LoadMask(Ext.getBody(),{
		msg: 'Updating...'
	});
    
	HPI.ee.Action.doStoreUpdate(HPI.params, null, true, function(){ HPI.ee.startmask.hide(); });
	HPI.ee.viewport.doLayout();
});
