// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
    var rest = this.slice((to || from) + 1 || this.length);
    this.length = from < 0 ? this.length + from : from;
    return this.push.apply(this, rest);
};

Homes = {

    //valid postcode regular expression
    //from UK Government Data Standards Catalogue, http://www.govtalk.gov.uk/gdsc/html/frames/PostCode.htm
    postCodeRexp: /(^gir\s0aa$)|(^[a-pr-uwyz]((\d{1,2})|([a-hk-y]\d{1,2})|(\d[a-hjks-uw])|([a-hk-y]\d[abehmnprv-y]))\s?\d[abd-hjlnp-uw-z]{2}$)/i,
    /*

TOGGLEAREA makes 1+ areas shown or hidden when a link is clicked, depending on whether the div is currently visible or not
    REQUIRED:
    <a> with class PE_toggleArea(id)
    <div> with class PE_toggle(id)
 
TOGGLEVIEW allows specified content to be displayed and hidden depending on one of a group of links being clicked or an input being checked.
    the visible content area's link has its link removed so it is just a span, when it is no longer the visible area a link is written around it dynamically
    REQUIRED:
    toggling content grouped inside a container element with class PE_toggleView
    FOR LINKS
    toggling text in span element with class PE_toggler(uid)
    FOR INPUTS
    input given class PE_toggler(uid)
    FOR HIDING ALL TOGGLE AREAS
    input or span with class PE_toggler()
    block element wrapping the content to be toggled with class PE_toggle(uid)
    the toggler for the starting toggle view has no link around it, all the other togglers do
    */
    toggleVisibility: function() {
        toggleArea();
        toggleViews();
        function toggleArea() {
            var toggleLinks = Homes.DOM.fuzzyClassName("a", "PE_toggleArea");
            for (var i = 0, j = toggleLinks.length; i < j; i++) {
                var toggleAreaID = Homes.DOM.getPEClassInfo(toggleLinks[i], "PE_toggleArea");
                toggleLinks[i].toggleAreas = Homes.DOM.fuzzyClassName("div", "PE_toggle(" + toggleAreaID + ")");
                toggleLinks[i].allToggleLinks = Homes.DOM.fuzzyClassName("a", "PE_toggleArea(" + toggleAreaID + ")");
                for (var k = 0, m = toggleLinks[i].toggleAreas.length; k < m; k++) {
                    if (toggleLinks[i].toggleAreas[k].className.indexOf("defaultToOpen") != -1) { continue; }
                    hide(toggleLinks[i].toggleAreas[k]);
                }
                toggleLinks[i].onclick = toggleOnOff;
            }
        }
        function toggleViews() {
            var toggleViewContainer = Homes.DOM.getElementsByClassName(document, "*", "PE_toggleView");
            for (var i = 0, j = toggleViewContainer.length; i < j; i++) {
                toggleViewContainer[i].style.display = "block";
                toggleViewContainer[i].style.visibility = "visible";
                var toggles = Homes.DOM.fuzzyClassNameBlock(toggleViewContainer[i], "span", "PE_toggler");
                var toggleInputs = Homes.DOM.fuzzyClassNameBlock(toggleViewContainer[i], "input", "PE_toggler");
                for (var t = 0, u = toggleInputs.length; t < u; t++) {
                    toggles.push(toggleInputs[t]);
                }
                for (var k = 0, m = toggles.length; k < m; k++) {
                    toggles[k].allToggles = toggles;
                    var toggleViewMarker = Homes.DOM.getPEClassInfo(toggles[k], "PE_toggler");
                    var toggleViews = Homes.DOM.fuzzyClassName("*", "PE_toggle(" + toggleViewMarker + ")");
                    if (toggleViewMarker == "") {
                        toggleViews = null;
                    }
                    else if (toggleViews.length == 0) {
                        continue;
                    }
                    else {
                        toggles[k].toggleView = toggleViews[0];
                    }
                    toggles[k].parentNode.toggle = toggles[k];
                    //for spans
                    if (toggles[k].parentNode.tagName.toLowerCase() == "a") {
                        hide(toggles[k].toggleView);
                        toggles[k].parentNode.onclick = toggleBetweenViews;
                    }
                    //for inputs
                    else if (toggles[k].tagName.toLowerCase() == "input") {
                        toggles[k].toggle = toggles[k];
                        if (toggles[k].checked == false) {
                            hide(toggles[k].toggleView);
                        }
                        toggles[k].onclick = toggleBetweenViews;
                    }
                }
            }
        }
        function toggleOnOff() {
            for (var i = 0, j = this.toggleAreas.length; i < j; i++) {
                if (this.toggleAreas[i].className.indexOf("hidden") != -1) {
                    show(this.toggleAreas[i]);
                    for (var k = 0, m = this.allToggleLinks.length; k < m; k++) {
                        this.allToggleLinks[k].className += " toggleShow";
                    }
                }
                else {
                    hide(this.toggleAreas[i]);
                    for (var k = 0, m = this.allToggleLinks.length; k < m; k++) {
                        this.allToggleLinks[k].className = this.allToggleLinks[k].className.replace("toggleShow", "");
                    }
                }
            }
            return false;
        }
        function toggleBetweenViews() {
            if (this.tagName.toLowerCase() == "input") {
                if (this.checked) {
                    show(this.toggle.toggleView);
                }
                else {
                    hide(this.toggle.toggleView);
                }
            }
            else {
                show(this.toggle.toggleView);
                for (var n = 0, p = this.toggle.allToggles.length; n < p; n++) {
                    if (this.toggle.allToggles[n] == this.toggle) {
                        if (this.tagName.toLowerCase() == "a") {
                            this.parentNode.insertBefore(this.toggle, this);
                            this.parentNode.removeChild(this);
                        }
                        continue;
                    }
                    else {
                        hide(this.toggle.allToggles[n].toggleView);
                        if (this.toggle.allToggles[n].parentNode.tagName.toLowerCase() != "a" && this.tagName.toLowerCase() != "input") {
                            var toggleLink = document.createElement("a");
                            toggleLink.href = "#";
                            this.toggle.allToggles[n].parentNode.insertBefore(toggleLink, this.toggle.allToggles[n]);
                            toggleLink.appendChild(this.toggle.allToggles[n]);
                            toggleLink.toggle = this.toggle.allToggles[n];
                            toggleLink.onclick = toggleBetweenViews;
                        }
                    }
                }
                if (this.tagName.toLowerCase() == "a") { return false; }
            }
        }
        function hide(el) {
            if (!el) { return false; }
            if (el.className.indexOf("hidden") == -1) {
                el.className += " hidden";
            }
        }
        function show(el) {
            if (!el) { return false; }
            el.className = el.className.replace("hidden", "");
        }
    },
	/*
    toggleSchoolInfo will show or hide "Information about schools" in the right hand column
    REQUIRED:
    ID of the list item containing the anchor tag of "Info" or "Map" view
	*/
	toggleSchoolInfo: function(selectedTabOptionId){
		if(selectedTabOptionId == "item-map"){
			$(".layoutColumn2 .school").show();
		}
		else if(selectedTabOptionId == "item-info"){
			$(".layoutColumn2 .school").hide();
		}
	},

    /*
    checkAllBoxesOnClick will check or uncheck all inputs with a given classname when clicked
    REQUIRED:
    checkbox with class PE_selectAll
    checkboxes with class PE_subCheckbox that are to be affected
		
	*/
    checkAllBoxesOnClick: function() {
        var subcheckboxes = Homes.DOM.getElementsByClassName(document, "input", "PE_subCheckbox");
        if (subcheckboxes.length == 0) { return; }

        var checkboxes = Homes.DOM.getElementsByClassName(document, "input", "PE_selectAll");
        if (checkboxes.length < 1) { return; }
        var checkbox = checkboxes[0];
        checkbox.inputs = subcheckboxes;
        checkbox.onclick = function() {
            for (var k = 0, m = this.inputs.length; k < m; k++) {
                if (this.inputs[k].disabled == true) { continue; }
                if (this.inputs[k].type == "checkbox") {
                    this.inputs[k].checked = this.checked;
                }
            }
        }
    },
    clearTextArea: function() {
        var textareas = Homes.DOM.fuzzyClassName("textarea", "PE_clear");
        for (var i = 0, j = textareas.length; i < j; i++) {
            var startText = Homes.DOM.getPEClassInfo(textareas[0], "PE_clear");
            textareas[i].startText = startText.replace("_", " ");
            Homes.DOM.addEvent(textareas[i], "focus", clearStartText);
        }
        function clearStartText() {
            if (this.value == this.startText) {
                this.value = "";
            }
        }
    },
    maxLengthTextArea: function() {
        var textareas = Homes.DOM.fuzzyClassName("textarea", "PE_maxLength");
        for (var i = 0, j = textareas.length; i < j; i++) {
            textareas[i].maxLength = Homes.DOM.getPEClassInfo(textareas[0], "PE_maxLength");
            Homes.DOM.addEvent(textareas[i], "keypress", countLength);
        }
        function countLength() {
            if (this.value.length > this.maxLength) {
                this.value = this.value.substring(0, this.maxLength);
            }
        }
    },

    /*
    confirmDelete will throw up a confirm box asking the whether they really want to delete something
    REQUIRED:
    input element with class PE_deleteConfirm
    */
    confirmDelete: function() {
        var deleteButton = Homes.DOM.getElementsByClassName(document, "input", "PE_deleteConfirm");
        for (var i = 0, j = deleteButton.length; i < j; i++) {
            deleteButton[i].onclick = function() {
                //create a box with yes or no links, position over the top above the link, yes and no


                /*var deleteConfirmDiv = document.createElement("div");
                deleteConfirmDiv.className = "lightBox";
                this.parentNode.appendChild(deleteConfirmDiv);
                var deleteQuery = document.createElement("p");
                deleteQuery.appendChild(document.createTextNode("Are you sure you want to delete these item(s)?"));
                deleteConfirmDiv.appendChild(deleteQuery);
                var deleteYes = document.createElement("a");
                deleteYes.href = "#";
                deleteYes.appendChild(document.createTextNode("Yes"));
                deleteConfirmDiv.appendChild(deleteYes);					
                deleteYes.onclick = function(){
                this.parentNode.parentNode.removeChild(this.parentNode);
                return false;
                };
                var deleteNo = document.createElement("a");
                deleteNo.href = "#";
                deleteNo.appendChild(document.createTextNode("No"));
                deleteConfirmDiv.appendChild(deleteNo);
                deleteNo.onclick = function(){
                this.parentNode.parentNode.removeChild(this.parentNode);
                return false;
                };
                return false;*/
                return confirm("Are you sure you want to delete these item(s)?");
            }
        }
    },
    /*
    INPUTHOVERS	
    runs only for IE6 and below, applies hover styles to inputs and other non-a elements
    the addHover function sets up the functionality, it takes an array of inputs as its first argument and an object of styles to apply as its second.
    the styles object consists of style name as the name and an array containing styles to apply.  the first item in the array is the hover state, the second item is the default state to return to.
    style = {'stylename' : ['hoverstyle , 'defaultstyle']}
    e.g. to apply an underline when the user hovers over an element,
    style = {'textDecoration' : ['underline','none']}
		
	*/
    //ALSO function siteInputHovers in site-specific js files triggers these
    InputHovers: {
        init: function() {
            //add new items here

            var inputsLink = Homes.DOM.getElementsByClassName(document, "input", "linkStyle");
            var inputsPoint = Homes.DOM.getElementsByClassName(document, "input", "linkPointer");
            styles = { 'cursor': ['pointer', 'auto'], 'textDecoration': ['underline', 'none'] };
            Homes.InputHovers.addHover(inputsLink, styles);
            Homes.InputHovers.addHover(inputsPoint, styles);
            var altButtons = Homes.DOM.getElementsByClassName(document, "input", "altButton");
            styles = { 'cursor': ['pointer', 'auto'] };
            Homes.InputHovers.addHover(altButtons, styles);
            var userInputs = Homes.DOM.getElementsByClassName(document, "ul", "userFunctions");
            styles = { 'cursor': ['pointer', 'auto'], 'textDecoration': ['underline', 'none'] };
            for (var i = 0, j = userInputs.length; i < j; i++) {
                var inputs = userInputs[i].getElementsByTagName("input");
                Homes.InputHovers.addHover(inputs, styles);
            }
            //end of new items
        },
        addHover: function(inputs, styles) {
            for (var i = 0, j = inputs.length; i < j; i++) {
                inputs[i].styles = styles;
                Homes.DOM.addEvent(inputs[i], "mouseover", Homes.InputHovers.addStyles);
                Homes.DOM.addEvent(inputs[i], "mouseout", Homes.InputHovers.removeStyles);
                Homes.DOM.addEvent(inputs[i], "focus", Homes.InputHovers.addStyles);
                Homes.DOM.addEvent(inputs[i], "blur", Homes.InputHovers.removeStyles);
            }
        },
        addStyles: function() {
            for (var i in this.styles) {
                this.style[i] = this.styles[i][0];
            }
        },
        removeStyles: function() {
            for (var i in this.styles) {
                this.style[i] = this.styles[i][1];
            }
        }
    },
    activateSubmit: function() {
        var submitHolder = Homes.DOM.getElementsByClassName(document, "*", "PE_actions");
        var submitButtons = [];
        for (var i = 0, j = submitHolder.length; i < j; i++) {
            var inputs = submitHolder[i].getElementsByTagName("input");
            //get submit buttons only
            for (var k = 0, m = inputs.length; k < m; k++) {
                if (inputs[k].type === "submit") {
                    submitButtons.push(inputs[k]);
                }
            }
        }
        var inputs = document.getElementsByTagName("input");
        var checkboxes = [];
        for (var i = 0, j = inputs.length; i < j; i++) {
            if (inputs[i].type === "checkbox") {
                checkboxes.push(inputs[i]);
                inputs[i].submitButtons = submitButtons;
                Homes.DOM.addEvent(inputs[i], "click", isActive);
            }
        }
        isActive();
        function isActive() {
            var isChecked = false;


            for (var i = 0, j = checkboxes.length; i < j; i++) {
                if (checkboxes[i].checked === true) {
                    isChecked = true;
                    break;
                }
            }

            for (var i = 0, j = submitButtons.length; i < j; i++) {
                submitButtons[i].disabled = !isChecked;
                if (isChecked === true) {
                    submitButtons[i].className = submitButtons[i].className.replace("disabled", "");
                }
                else {
                    if (submitButtons[i].className.indexOf("disabled") == -1) {
                        submitButtons[i].className += " disabled";
                    }
                }
            }

        }
    },
    //function for flash to call to test if a user's session is still available
    isLoggedIn: function() {
        var xhr = Homes.AJAX.createXMLHttpRequest();
        var url = IS_LOGGED_IN;
        xhr.open("GET", url, true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState != 4) { return false; }
            if (xhr.status != 200) {
                return false;
            }
            var xhrResponse = xhr.responseText.trim().toLowerCase();
            return xhrResponse;
        }
        xhr.send(null);
    },
    /*
    run an ajax call to get a links list of developments by name
    */
    developmentSearch: function() {

        var inputText = Homes.DOM.getElementsByClassName(document, "input", "PE_developmentSearch");
        for (var i = 0, j = inputText.length; i < j; i++) {
            Homes.DOM.addEvent(inputText[i], "keyup", ajaxSearch);
        }
        function ajaxSearch() {
            if (this.value.length < 3) { return false; }
            var xhr = Homes.AJAX.createXMLHttpRequest();
            var url = DEVELOPMENTS_BY_QUICKSEARCH + "&search=" + this.value;
            var trigger = this;
            xhr.open("GET", url, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState != 4) { return false; }
                if (xhr.status != 200) {
                    return false;
                }
                var xhrResponse = xhr.responseXML;
                var devList = createList(xhrResponse);
                var currentList = document.getElementById("devList");
                if (currentList) {
                    currentList.parentNode.removeChild(currentList);
                }
                var triggerLeft = Homes.DOM.getAbsoluteX(trigger);
                var triggerTop = Homes.DOM.getAbsoluteY(trigger);


                devList.style.top = triggerTop + trigger.offsetHeight - 1 + "px";
                devList.style.left = triggerLeft + "px";

                document.body.insertBefore(devList, document.body.firstChild);
                Homes.AJAX.updateBuffer();
            }
            xhr.send(null);
        }
        function createList(xhrResponse) {
            var root = xhrResponse.documentElement;
            if (!root) { return false; }
            var developments = root.getElementsByTagName("development");
            var developmentList = document.createElement("ul");
            developmentList.className = "ajaxLinkList";
            developmentList.id = "devList";
            for (var i = 0, j = developments.length; i < j; i++) {
                var developmentName = developments[i].getElementsByTagName("name");
                if (developmentName.length < 1) { continue; }
                var developmentURL = developments[i].getElementsByTagName("url");
                if (developmentURL.length < 1) { continue; }
                var developmentItem = document.createElement("li");
                var developmentLink = document.createElement("a");
                var developmentText = Homes.DOM.getTextNode(developmentName[0]).nodeValue;
                developmentLink.href = Homes.DOM.getTextNode(developmentURL[0]).nodeValue;
                developmentLink.appendChild(document.createTextNode(developmentText));
                developmentItem.appendChild(developmentLink);
                //done, add to list
                developmentList.appendChild(developmentItem);
            }
            return developmentList;
        }
    },

    /*
    run an ajax call to get a list of town names
    */
    townSearch: function() {

        var inputText = Homes.DOM.getElementsByClassName(document, "input", "PE_townSearch");
        for (var i = 0, j = inputText.length; i < j; i++) {
            Homes.DOM.addEvent(inputText[i], "keyup", ajaxSearch);
        }
        function ajaxSearch() {
            if (this.value.length < 3) { return false; }
            var xhr = Homes.AJAX.createXMLHttpRequest();
            var url = TOWNS_BY_QUICKSEARCH + "?search=" + this.value;
            var trigger = this;
            xhr.open("GET", url, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState != 4) { return false; }
                if (xhr.status != 200) {
                    return false;
                }
                var xhrResponse = xhr.responseXML;
                var townList = createList(xhrResponse);
                var currentList = document.getElementById("townList");
                if (currentList) {
                    currentList.parentNode.removeChild(currentList);
                }
                var triggerLeft = Homes.DOM.getAbsoluteX(trigger);
                var triggerTop = Homes.DOM.getAbsoluteY(trigger);


                townList.style.top = triggerTop + trigger.offsetHeight - 1 + "px";
                townList.style.left = triggerLeft + "px";

                document.body.insertBefore(townList, document.body.firstChild);
                Homes.AJAX.updateBuffer();
            }
            xhr.send(null);
        }
        function createList(xhrResponse) {
            var root = xhrResponse.documentElement;
            if (!root) { return false; }
            var towns = root.getElementsByTagName("town");
            var townList = document.createElement("ul");
            townList.className = "ajaxLinkList";
            townList.id = "townList";
            for (var i = 0, j = towns.length; i < j; i++) {
                var townName = towns[i].getElementsByTagName("name");
                if (townName.length < 1) { continue; }
                var townURL = "#";
                if (townURL.length < 1) { continue; }
                var townItem = document.createElement("li");
                var townLink = document.createElement("a");
                var townText = Homes.DOM.getTextNode(townName[0]).nodeValue;
                townLink.appendChild(document.createTextNode(townText));
                townLink.href = "#";
                townLink.townValue = townText;
                townItem.appendChild(townLink);

                townLink.onclick = function() {
                    var inputText = Homes.DOM.getElementsByClassName(document, "input", "PE_townSearch");
                    inputText[0].value = this.townValue;
                    document.getElementById("townList").style.display = "none";
                    return false;
                };

                //done, add to list
                townList.appendChild(townItem);
            }
            return townList;
        }
    },

    schoolSearch: function() {

        var inputText = Homes.DOM.getElementsByClassName(document, "input", "PE_schoolSearch");
        for (var i = 0, j = inputText.length; i < j; i++) {
            Homes.DOM.addEvent(inputText[i], "keyup", ajaxSearch);
        }
        function ajaxSearch() {
            if (this.value.length < 3) { return false; }
            var xhr = Homes.AJAX.createXMLHttpRequest();
            var url = SCHOOLS_BY_QUICKSEARCH + "?search=" + this.value;
            var trigger = this;
            xhr.open("GET", url, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState != 4) { return false; }
                if (xhr.status != 200) {
                    return false;
                }
                var xhrResponse = xhr.responseXML;
                var schoolList = createList(xhrResponse);
                var currentList = document.getElementById("schoolList");
                if (currentList) {
                    currentList.parentNode.removeChild(currentList);
                }
                var triggerLeft = Homes.DOM.getAbsoluteX(trigger);
                var triggerTop = Homes.DOM.getAbsoluteY(trigger);


                schoolList.style.top = triggerTop + trigger.offsetHeight - 1 + "px";
                schoolList.style.left = triggerLeft + "px";

                document.body.insertBefore(schoolList, document.body.firstChild);
                Homes.AJAX.updateBuffer();
            }
            xhr.send(null);
        }
        function createList(xhrResponse) {
            var root = xhrResponse.documentElement;
            if (!root) { return false; }
            var schools = root.getElementsByTagName("school");
            var schoolList = document.createElement("ul");
            schoolList.className = "ajaxLinkList";
            schoolList.id = "schoolList";
            for (var i = 0, j = schools.length; i < j; i++) {
                var schoolName = schools[i].getElementsByTagName("name");
                if (schoolName.length < 1) { continue; }
                var schoolURL = "#";
                if (schoolURL.length < 1) { continue; }
                var schoolItem = document.createElement("li");
                var schoolLink = document.createElement("a");
                var schoolText = Homes.DOM.getTextNode(schoolName[0]).nodeValue;
                schoolLink.appendChild(document.createTextNode(schoolText));
                schoolLink.href = "#";
                schoolLink.schoolValue = schoolText;
                schoolItem.appendChild(schoolLink);

                schoolLink.onclick = function() {
                    var inputText = Homes.DOM.getElementsByClassName(document, "input", "PE_schoolSearch");
                    inputText[0].value = this.schoolValue;
                    document.getElementById("schoolList").style.display = "none";
                    return false;
                };

                //done, add to list
                schoolList.appendChild(schoolItem);
            }
            return schoolList;
        }
    },

    /*
    GETMYADDRESS
    takes a postcode input, queries it against the paf and returns 1+ streets with town and county for that postcode as XML
    REQUIRED:
    XML data returned with format:
    <addresses>
    <address>
    <address1>street name</address1>
    <town>town or city</town>
    <county>county</county>
    </address>
    </addresses>
    There may be multiple address elements.
	
	input with class PE_postcode for the user input
    submit input with class PE_getMyAddress to trigger the address look-up
	
	input with class PE_address1 for the street name output (address1 taken from PAF schema)
    input with class PE_town for the town output
    input with class PE_county for the county output
	
*/
    getMyAddress: function() {
        var postCodeFields = Homes.DOM.getElementsByClassName(document, "input", "PE_getMyAddress");
        var autoHidePostCodeFields = Homes.DOM.getElementsByClassName(document, "input", "PE_autoHideMyAddress");
        var postCodeDetailsFields = new Array('address1', 'town', 'county');
        var validateAddressOnSubmit = Homes.DOM.getElementsByClassName(document, "input", "PE_validateMyAddress");

        if (postCodeFields.length > 0) {
            Homes.getMyAddress.postCodeField = postCodeFields[0];
            var submitP = document.createElement("p");
            submitP.className = "button getAddress";
            var submitLink = document.createElement("a");
            submitLink.id = "btn_getAddress";
            submitLink.href = "#";
            submitLink.className = "getAddress";
            submitLink.appendChild(document.createTextNode("Get my address"));
            submitLink.onclick = getAddressData;
            submitP.appendChild(submitLink);
            Homes.DOM.insertAfter(submitP, postCodeFields[0]);
            var submitLen = validateAddressOnSubmit.length;
            if (submitLen > 0) {
                for (var i = 0; i < submitLen; i++) {
                    validateAddressOnSubmit[i].onclick = function() {
                        var len = postCodeDetailsFields.length;
                        for (var i = 0; i < len; i++) {
                            var input = Homes.DOM.fuzzyClassName("input", "PE_autofill(" + postCodeDetailsFields[i] + ")");
                            if (input[0].value != "") {
                                getAddressData();
                                break;
                            }
                        }
                    }
                }
            }
        }

        if (autoHidePostCodeFields.length > 0) {
            //hideAddressFields();
        }

        function getAddressData() {
            var errorMsg = document.getElementById("JSerror");
            if (errorMsg) { errorMsg.parentNode.removeChild(errorMsg); }

            if (Homes.postCodeRexp.test(Homes.getMyAddress.postCodeField.value) === false) {
                showError("invalidInput", Homes.getMyAddress.postCodeField);
                return false;
            }

            var xhr = Homes.AJAX.createXMLHttpRequest();
            //var POSTCODE_ADDRESS = "/assets/xml/pcode.xml";//for testing
            var url = POSTCODE_ADDRESS + "?postcode=" + Homes.getMyAddress.postCodeField.value;
            xhr.open("GET", url, true);
            xhr.onreadystatechange = function() {
                var submitBtn = document.getElementById("btn_getAddress");
                var processingImg = Homes.AJAX.processing.getDisplay();
                if (submitBtn.className.indexOf("hidden") == -1) { submitBtn.className += " hidden"; }
                Homes.DOM.insertAfter(processingImg, Homes.getMyAddress.postCodeField);
                if (xhr.readyState != 4) { return false; }
                submitBtn.className = submitBtn.className.replace("hidden", "");
                processingImg.parentNode.removeChild(processingImg);
                if (xhr.status != 200) {
                    showError("ajaxFail", Homes.getMyAddress.postCodeField);
                    return false;
                }
                var xhrResponse = xhr.responseXML;
                extractAddress(xhrResponse);
            }
            xhr.send(null);
            return false;
        }

        function hideAddressFields() {
            var len = postCodeDetailsFields.length;
            for (var i = 0; i < len; i++) {
                var input = Homes.DOM.fuzzyClassName("input", "PE_autofill(" + postCodeDetailsFields[i] + ")");
                if (input[0].value === "")
                    input[0].parentNode.style.display = 'none';
            }

        }

        function showAddressFields() {
            var len = postCodeDetailsFields.length;
            for (var i = 0; i < len; i++) {
                var input = Homes.DOM.fuzzyClassName("input", "PE_autofill(" + postCodeDetailsFields[i] + ")");
                //if(input[0].value != "")
                // input[0].parentNode.childNodes[5].childNodes[1].style.display = 'none';
                input[0].parentNode.style.display = 'block';
                if (input[0].value != "") {
                    parentDiv = input[0].parentNode;
                    errorDiv = Homes.DOM.getElementsByClassName(parentDiv, "span", "error");
                    errorDiv[0].style.display = 'none';
                }
            }

        }

        function extractAddress(xhrResponse) {
            var root = xhrResponse.documentElement;
            if (root.length < 1) { return false; }
            var addresses = root.getElementsByTagName("address");
            //only 1 street, fill the fields.
            if (addresses.length === 1) {
                var oAddress = {};
                var address1 = addresses[0].getElementsByTagName("address1");
                var town = addresses[0].getElementsByTagName("town");
                var county = addresses[0].getElementsByTagName("county");
                oAddress.address1 = (address1.length > 0) ? Homes.DOM.getTextNode(address1[0]).nodeValue.toProperCase() : '';
                oAddress.town = (town.length > 0) ? Homes.DOM.getTextNode(town[0]).nodeValue.toProperCase() : '';
                oAddress.county = (county.length > 0) ? Homes.DOM.getTextNode(county[0]).nodeValue.toProperCase() : '';
                autoFill(oAddress);
                showAddressFields();
            }
            //more than 1 street, present select box that automatically fills the fields.
            else if (addresses.length > 1) {
                var addressSelect = document.getElementById("userAddressOptions");

                if (!addressSelect) {
                    var addressSelect = document.createElement("select");
                    addressSelect.id = "userAddressOptions";
                    addressSelect.className = "getAddress";
                    var addressSelectLabel = document.createElement("label");
                    addressSelectLabel.htmlFor = addressSelectLabel.id;
                    addressSelectLabel.className = "hidden";
                    addressSelectLabel.appendChild(document.createTextNode("Choose your address"));
                    Homes.getMyAddress.postCodeField.parentNode.appendChild(addressSelectLabel);
                    Homes.getMyAddress.postCodeField.parentNode.appendChild(addressSelect);
                }
                addressSelect.size = 5;
                if (addresses.length < addressSelect.size) {
                    addressSelect.size = addresses.length;
                }
                addressSelect.innerHTML = ""; //remove any pre-existing options
                for (var i = 0, j = addresses.length; i < j; i++) {
                    var newOption = document.createElement("option");
                    newOption.value = i;
                    var address1 = addresses[i].getElementsByTagName("address1");
                    var town = addresses[i].getElementsByTagName("town");
                    var county = addresses[i].getElementsByTagName("county");
                    var optionText = "";
                    optionText += (address1.length > 0) ? Homes.DOM.getTextNode(address1[0]).nodeValue : '';
                    optionText += ", ";
                    optionText += (town.length > 0) ? Homes.DOM.getTextNode(town[0]).nodeValue : '';
                    optionText += ", ";
                    optionText += (county.length > 0) ? Homes.DOM.getTextNode(county[0]).nodeValue : '';
                    newOption.innerHTML = optionText.toProperCase();

                    addressSelect.appendChild(newOption);
                }

                Homes.DOM.addEvent(addressSelect, 'change', function() {
                    var optionText = this.options[this.selectedIndex].text;
                    var addressDetails = optionText.split(",");
                    var oAddress = {
                        'address1': addressDetails[0],
                        'town': addressDetails[1],
                        'county': addressDetails[2]
                    };
                    autoFill(oAddress);
                    showAddressFields();
                });
            }
            //no addresses, return error message
            else {
                showError("noAddressReturned", Homes.getMyAddress.postCodeField);
            }
        }

        function autoFill(oAddress) {
            for (var i in oAddress) {
                var input = Homes.DOM.fuzzyClassName("input", "PE_autofill(" + i + ")");
                if (input.length > 0) {
                    input[0].value = oAddress[i];
                }
            }
            Homes.AJAX.updateBuffer(); //accessibility aid - refresh virtual buffer for screenreaders
        }

        function showError(errorType) {
            var errorText = "";
            switch (errorType) {
                case "invalidInput":
                    errorText = "Please enter a valid UK postcode";
                    hideAddressFields();
                    break;
                case "ajaxFail":
                    errorText = "We're sorry, there was a problem getting your address.  Please try again";
                    hideAddressFields();
                    break;
                case "noAddressReturned":
                    errorText = "We're sorry, we cannot find an address for that postcode.  Please fill in the form manually";
                    showAddressFields();
                    break;
                default: //could be any error
                    errorText = "Error. Please try again";
            }
            var errorMsg = document.createElement("span");
            errorMsg.className = "error";
            errorMsg.id = "JSerror";
            errorMsg.appendChild(document.createTextNode(errorText));
            Homes.getMyAddress.postCodeField.parentNode.appendChild(errorMsg);
        }
    },
    /*PNG handling for inline images
    based on supersleight.js
    //NB: leave applyPositioning as false and sort out relative positioning where needed in the IE6 stylesheets.
    //otherwise it causes the pages to break in IE6, especially ward.
    */
    pngHandling: function(wrapper) {
        var supersleight = function() {
            var root = wrapper;
            var applyPositioning = false;
            var shim = '/assets/img/' + CompanyCode + '/css/t.gif';
            var shim_pattern = /t\.gif$/i;
            var fnLoadPngs = function() {
                if (root) { root = document.getElementById(root); } else { root = document; }
                if (!root) { return; }
                for (var i = root.all.length - 1, obj = null; (obj = root.all[i]); i--) {
                    if (obj.currentStyle.backgroundImage.match(/\.png/i) !== null) { bg_fnFixPng(obj); }
                    if (obj.tagName == 'IMG' && obj.src.match(/\.png$/i) !== null) { el_fnFixPng(obj); }

                    if (applyPositioning && (obj.tagName == 'A' || obj.tagName == 'INPUT') && obj.style.position === '') {
                        obj.style.position = 'relative';
                    }
                }
            };
            var bg_fnFixPng = function(obj) {
                var mode = 'scale';
                var bg = obj.currentStyle.backgroundImage;
                var src = bg.substring(5, bg.length - 2);
                if (obj.currentStyle.backgroundRepeat == 'no-repeat') { mode = 'crop'; }
                obj.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', sizingMethod='" + mode + "')";
                obj.style.backgroundImage = 'url(' + shim + ')';
            };
            var el_fnFixPng = function(img) {
                var src = img.src;
                img.style.width = img.width + "px"; img.style.height = img.height + "px";
                img.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', sizingMethod='scale')";
                img.src = shim;
            };

            var addLoadEvent = function(func) {
                var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = func; } else {
                    window.onload = function() {
                        if (oldonload) { oldonload(); }
                        func();
                    };
                }
            }; return { init: function() { addLoadEvent(fnLoadPngs); }, limitTo: function(el) { root = el; }, run: function() { fnLoadPngs(); } };
        } ();
        //apply with IE6 and below only
        /*@cc_on@*/
        /*@if (@_jscript_version <= 5.6)
        supersleight.init();
        /*@end@*/

    },
    /*
    REQUIRED:
    element with class 'brandfont'
    */
    sifr: function() {
        //sifr is inaccessible in IE7 and Gecko 1.9+
        //there's no way to detect zoom mode, so we are left with checking the useragent, generally not preferred practice
        var browser = navigator.userAgent;
        var geckoReg = /rv:(\d+[\.\d]+)\) Gecko/;
        var geckoVersion = geckoReg.exec(browser);
        if (geckoVersion) {
            if (parseFloat(geckoVersion[1], 10) >= 1.9) {
                //remove class added in to html element by sifr regardless of whether it is called or not
                var html = document.getElementsByTagName("html")[0];
                html.className = html.className.replace("sIFR-hasFlash", "");
                return false;
            }
        }
        /*@cc_on@*/
        /*@if (@_jscript_version > 5.6)
			//remove class added in to html element by sifr regardless of whether it is called or not
			var html = document.getElementsByTagName("html")[0];
			html.className = html.className.replace("sIFR-hasFlash","");
			return false;
		/*@end
        @*/
        if (typeof sIFR !== "function") { return; }
        sIFR();
        if (typeof SifrConstants == "undefined") { return; }
        if (!SifrConstants.FILE) { return; }

        //phone number
        sIFR.replaceElement("#companyInformation .brandfont", SifrConstants.FILE, named({ sColor: SifrConstants.HEADERCOLOR, sWmode: 'transparent' }));
        //location file
        if (SifrConstants.LOCATIONFILE) {
            sIFR.replaceElement(".contentHeaderTop>.location", SifrConstants.LOCATIONFILE, named({ sColor: SifrConstants.H1COLOR, sWmode: 'transparent' }));
        }
        //h1
        if (SifrConstants.H1HOMECOLOR) {
            sIFR.replaceElement("#homepage H1.brandfont", SifrConstants.FILE, named({ sColor: SifrConstants.H1HOMECOLOR, nPaddingTop: 0, nPaddingRight: 0, nPaddingBottom: 0, nPaddingLeft: SifrConstants.H1PADDING, sWmode: 'transparent' }));
        }
        sIFR.replaceElement("H1.brandfont", SifrConstants.FILE, named({ sColor: SifrConstants.H1COLOR, nPaddingTop: 0, nPaddingRight: 0, nPaddingBottom: 0, nPaddingLeft: SifrConstants.H1PADDING, sWmode: 'transparent' }));
        //general
        sIFR.replaceElement(".brandfont", SifrConstants.FILE, named({ sColor: SifrConstants.COLOR, sWmode: 'transparent' }));
    },
    //onload event
    addLoadEvent: function(func) {
        var oldonload = window.onload;
        if (typeof window.onload != 'function') {
            window.onload = func;
        } else {
            window.onload = function() {
                oldonload();
                func();
            }
        }
    },
    addUnloadEvent: function(func) {
        var oldonload = window.onunload;
        if (typeof window.onunload != 'function') {
            window.onunload = func;
        } else {
            window.onunload = function() {
                oldonload();
                func();
            }
        }
    }
	
};
/*
GOOGLE MAPS
REQUIRED:
	div with map gmap.  this will be overwritten with the map, so non-js fallback goes inside it
	for each marker
				span with class PE_gmapLocation(fooID) that contains the location data to be geocoded
				optional span with class PE_gmapInfo(fooID) that contains extra data to go into the miniwindow
	if there is a driving directions search
				submit input with class PE_gdriving.  clicking this will trigger a directions request
				text input with class PE_gpostcode where the user enters the postcode to get directions from
				span/input/select with class PE_gdrivingTo that will be the end point of the driving directions
*/
Homes.GoogleMaps = {

    init: function() {
        //set up map
        var mapDiv = document.getElementById("gmap");
        if (!mapDiv) { return false; }
        if (!GBrowserIsCompatible()) { return false; }
        Homes.GoogleMaps.map = new GMap2(mapDiv);
        //get in-page map points
        Homes.GoogleMaps.setIcons();
        Homes.GoogleMaps.setupPointsFromHTML();
        Homes.GoogleMaps.setupPointsFromJSON();
        GEvent.addListener(Homes.GoogleMaps.map, 'zoomend', function() { Homes.GoogleMaps.map.closeInfoWindow(); });
        //set up cluster handling
        var clusterOptions = {
            markers: Homes.GoogleMaps.markers,
            clusterMarkerIcon: Homes.GoogleMaps.clusterIcon,
            clusterMarkerTitle: '%count developments',
            clusterMarkerClick: function(args) {
                zoomLinkAction = function() {
                    Homes.GoogleMaps.map.setCenter(args.clusterMarker.getLatLng(),
                    Homes.GoogleMaps.map.getBoundsZoomLevel(args.clusterMarker.clusterGroupBounds));
                    //delete zoomLinkAction;
                    return false;
                };
                var infoHTML = '<div class="gmapInfo">';
                infoHTML += '<h3>' + args.clusteredMarkers.length + ' developments in this area</h3>\n';
                infoHTML += '<ul>\n';
                var developmentsListItems = (args.clusteredMarkers.length > 20) ? 20 : args.clusteredMarkers.length;
                for (var i = 0, j = developmentsListItems; i < j; i++) {
                    infoHTML += '<li>';
                    infoHTML += '<a href="javascript:Homes.GoogleMaps.cluster.triggerClick(' + args.clusteredMarkers[i].index + ')">' + args.clusteredMarkers[i].heading + '</a>';
                    infoHTML += '</li>\n';
                    if (i === 19) {
                        infoHTML += '<li>';
                        infoHTML += '...';
                        infoHTML += '</li>';
                    }
                }
                infoHTML += '</ul>\n';
                infoHTML += '<p><a href="javascript:void(0)" onclick="zoomLinkAction()">Zoom in</a> to ';
                infoHTML += (args.clusteredMarkers.length > 20) ? "see more" : "show these locations";
                infoHTML += '</p>';
                infoHTML += '</div>';
                //args.clusterMarker.openInfoWindowHtml( infoHTML );
                Homes.GoogleMaps.map.openInfoWindow(args.clusterMarker.getLatLng(), infoHTML);
                //return false;
            }
        };
        Homes.GoogleMaps.cluster = new ClusterMarker(Homes.GoogleMaps.map, clusterOptions);
        Homes.GoogleMaps.cluster.fitMapToMarkers();

        Homes.GoogleMaps.map.addControl(new GMapTypeControl());
        Homes.GoogleMaps.map.addControl(new GLargeMapControl());
        Homes.GoogleMaps.map.addControl(new GScaleControl());
        Homes.GoogleMaps.map.addControl(new GOverviewMapControl());

        //set up directionsTo location
        var directionsTo = Homes.DOM.fuzzyClassName("span", "PE_gdrivingTo");
        if (directionsTo.length === 0) {
            directionsTo = Homes.DOM.fuzzyClassName("select", "PE_gdrivingTo");
        }
        if (directionsTo.length > 0) {
            Homes.GoogleMaps.setupDirections(directionsTo[0]);
        }
        //set up facilities
        var facilitiesCheckbox = Homes.DOM.fuzzyClassName("input", "PE_mapfacilities");
        for (var i = 0, j = facilitiesCheckbox.length; i < j; i++) {
            if (facilitiesCheckbox[i].checked === true) {
                Homes.GoogleMaps.Facilities.getFacilities.call(facilitiesCheckbox[i]);
            }
            Homes.DOM.addEvent(facilitiesCheckbox[i], "click", Homes.GoogleMaps.Facilities.getFacilities);
        }

        //set up school marker
        if (typeof (SchoolDataItem) != 'undefined') {
            var facilitiesTypeSCH = "thisschools";
            var infoHTMLSCH = Homes.GoogleMaps.createInfoHTML(SchoolDataItem[0].vcard);
            var geoLocationSCH = { 'latitude': SchoolDataItem[0].vcard.geo.latitude, 'longitude': SchoolDataItem[0].vcard.geo.longitude };
            var markerSCH = Homes.GoogleMaps.setMarkerNoPush(geoLocationSCH, infoHTMLSCH, facilitiesTypeSCH);
            Homes.GoogleMaps.map.addOverlay(markerSCH);
            Homes.GoogleMaps.map.setCenter(markerSCH.getPoint());
        }
        Homes.GoogleMaps.checkShow();
    },
    checkShow: function() {
		var totalResults = $(".resultsHead .resultsTotal");
		var pagination = $(".resultsHead .pagination");
	
        var boxCheck = $("input#show_map_results:checked").val();
        var boxCheck2 = $("input#show_map_results2:checked").val();
		$(".mapResults").removeClass("hidden");

        if (boxCheck != null || boxCheck2 != null) {
            $('#devResultsList').tabs("search-by-map");
			totalResults.hide();
			pagination.hide();
        }
        else {
            $('#devResultsList').tabs("search-by-info");
        }
		
		//remove results details for map tab
		var listTab = $(".tabs-nav #item-info a");
		var mapTab = $(".tabs-nav #item-map a");
		$(listTab).click(function () {
			totalResults.show();
			pagination.show();
		});
		$(mapTab).click(function () {
			totalResults.hide();
			pagination.hide();
		});
    },
    setupPointsFromHTML: function() {
        var mapPoints = Homes.DOM.fuzzyClassName("span", "PE_gmapPlace");
        for (var i = 0, j = mapPoints.length; i < j; i++) {
            var lat = Homes.DOM.getElementsByClassName(mapPoints[i], "span", "latitude");
            var lng = Homes.DOM.getElementsByClassName(mapPoints[i], "span", "longitude");
            var geoLocation = { 'latitude': lat[0].innerHTML, 'longitude': lng[0].innerHTML };
            var fn = Homes.DOM.getElementsByClassName(mapPoints[i], "span", "fn");
            var street = Homes.DOM.getElementsByClassName(mapPoints[i], "span", "street-address");
            var locality = Homes.DOM.getElementsByClassName(mapPoints[i], "span", "locality");
            var region = Homes.DOM.getElementsByClassName(mapPoints[i], "span", "region");
            var postcode = Homes.DOM.getElementsByClassName(mapPoints[i], "span", "postal-code");
            var info = {
                fn: (fn.length > 0) ? fn[0].innerHTML : null,
                street: (street.length > 0) ? street[0].innerHTML : null,
                locality: (locality.length > 0) ? locality[0].innerHTML : null,
                region: (region.length > 0) ? region[0].innerHTML : null,
                postcode: (postcode.length > 0) ? postcode[0].innerHTML : null
            }
            var infoHTML = Homes.GoogleMaps.createInfoHTML(info);
            var buildingType = "";
            var markerType = Homes.DOM.getElementsByClassName(mapPoints[i], "span", "type");
            if (markerType.length > 0) {
                buildingType = markerType[0].innerHTML;
            }
            info.type = buildingType;
            if (geoLocation.latitude == 0 && geoLocation.longitude == 0) {
                Homes.GoogleMaps.replaceNullLongLat(info.postcode, infoHTML, buildingType);
                return false;
            }
            Homes.GoogleMaps.setMarker(geoLocation, infoHTML, buildingType);
        }
    },
    setupPointsFromJSON: function() {
        var developments = Homes.Developments;
        if (!developments) { return; }
        for (var i = 0, j = developments.length; i < j; i++) {
            createPoint(developments[i]);
        }
        //abstracted in case loop needs further logic applied before making a marker
        function createPoint(development) {
            var geoLocation = { 'latitude': development.vcard.geo.latitude, 'longitude': development.vcard.geo.longitude };
            var info = {
                fn: development.vcard.fn,
                street: development.vcard.adr["street-address"],
                locality: development.vcard.adr.locality,
                region: development.vcard.adr.region,
                postcode: development.vcard.adr["postal-code"],
                url: development.vcard.url,
                imgSrc: development.vcard.photo,
                note: development.vcard.note,
                type: development.vcard.adr.type
            }
            var infoHTML = Homes.GoogleMaps.createInfoHTML(info);
            var buildingType = development.vcard.adr.type;

            if (geoLocation.latitude == 0 && geoLocation.longitude == 0) {
                Homes.GoogleMaps.replaceNullLongLat(info.postcode, infoHTML, buildingType);
                return false;
            }
            Homes.GoogleMaps.setMarker(geoLocation, infoHTML, buildingType);
        }
    },
    replaceNullLongLat: function(postcode, infoHTML, buildingType) {
        var xhr = Homes.AJAX.createXMLHttpRequest();
        //var POSTCODE_ADDRESS = "/assets/xml/pcode.xml";//for testing
        var url = POSTCODE_ADDRESS + "?postcode=" + postcode;
        xhr.open("GET", url, true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState != 4) { return false; }
            if (xhr.status != 200) {
                return false;
            }
            var xhrResponse = xhr.responseXML;
            var root = xhrResponse.documentElement;

            var latitude = root.getElementsByTagName("lat");
            var longitude = root.getElementsByTagName("lon");

            if (latitude.length == 0 || longitude.length == 0) { return false; }
            var geoLocation = {
                'latitude': Homes.DOM.getTextNode(latitude[0]).nodeValue,
                'longitude': Homes.DOM.getTextNode(longitude[0]).nodeValue
            }
            var newMarker = Homes.GoogleMaps.setMarker(geoLocation, infoHTML, buildingType);
            Homes.GoogleMaps.cluster.addMarkers([newMarker]);
            Homes.GoogleMaps.cluster.fitMapToMarkers();
        }
        xhr.send(null);
        return false;
    },
    //takes an object with values set in as properties
    //returns a DOM object
    createInfoHTML: function(info) {
        var infoHTML = document.createElement("div")
        infoHTML.className = "gmapInfo";

        if (info.fn) {
            var infoHead = document.createElement("h3");
            infoHead.appendChild(document.createTextNode(info.fn));
            infoHTML.appendChild(infoHead);
        }
        var infoAddr = document.createElement("p");
        if (info.imgSrc) {
            var img = document.createElement("img");
            img.src = info.imgSrc;
            img.className = "gmapImg";
            if (img.height != 0) {
                if (info.url) {
                    var imgLink = document.createElement("a");
                    imgLink.href = info.url;
                    img.alt = info.fn;
                    imgLink.appendChild(img);
                    infoHTML.appendChild(imgLink);
                }
                else {
                    infoHTML.appendChild(img);
                }
            }
        }
        if (info.type) {
            if (info.type === "future") {
                var infoComingSoon = document.createElement("p");
                infoComingSoon.appendChild(document.createTextNode("Coming soon"));
                infoHTML.appendChild(infoComingSoon);
            }
        }
        if (info.street) { infoAddr.appendChild(document.createTextNode(info.street + ", ")); }
        if (info.locality) { infoAddr.appendChild(document.createTextNode(info.locality + ", ")); }
        if (info.region) { infoAddr.appendChild(document.createTextNode(info.region + ", ")); }
        if (info.postcode) { infoAddr.appendChild(document.createTextNode(info.postcode)); }
        infoHTML.appendChild(infoAddr);

        if (info.note) {
            var infoNote = document.createElement("p");
            infoNote.appendChild(document.createTextNode(info.note));
            infoHTML.appendChild(infoNote);
        }
        if (info.url) {
            var infoURL = document.createElement("p");
            var infoLink = document.createElement("a");
            infoLink.href = info.url;
            infoLink.appendChild(document.createTextNode("View details"));
            infoURL.appendChild(infoLink);
            infoHTML.appendChild(infoURL);
        }

        return infoHTML;
    },
    //	DIRECTIONS

    setupDirections: function(elem) {

        startAddress = function() {
            if (elem.tagName.toLowerCase() == "span") {
                var lat = Homes.DOM.getElementsByClassName(elem, "span", "latitude");
                var lng = Homes.DOM.getElementsByClassName(elem, "span", "longitude");
                addr = lat[0].innerHTML + "," + lng[0].innerHTML;
                startAddress = function() { return addr; }
            }
            else if (elem.tagName.toLowerCase() == "select") {
                addr = elem.options[elem.selectedIndex].value;
            }
            return addr;
        };
        var directionsSearch = Homes.DOM.getElementsByClassName(document, "input", "PE_gdriving");
        for (var i = 0, k = directionsSearch.length; i < k; i++) {
            var postcodeInput = Homes.DOM.getElementsByClassName(document, "input", "PE_gpostcode");
            if (postcodeInput.length > 0) {
                directionsSearch[i].postcodeInput = postcodeInput[0];
            }
            directionsSearch[i].onclick = function() {
                var postcodeInput = this.postcodeInput.value;
                Homes.GoogleMaps.generateDirections(postcodeInput, startAddress());
                return false;
            }
        }
    },
    generateDirections: function(from, to) {
        var directionsDiv = document.getElementById("gdirections");

        if (!directionsDiv) {
            var directionsDiv = document.createElement("div");
            directionsDiv.id = "gdirections";
            var mapDiv = document.getElementById("gmap");
            Homes.DOM.insertAfter(directionsDiv, mapDiv);
            Homes.GoogleMaps.directions = new GDirections(Homes.GoogleMaps.map, directionsDiv);
        }
        Homes.GoogleMaps.directions.load(from + " to " + to);
    },
    //when check a box, go and retrieve the appropriate facilities and display them on the map.
    Facilities: {
        getFacilities: function() {
            var facilitiesType = Homes.DOM.getPEClassInfo(this, "PE_mapfacilities");
            if (this.checked === true) {
                Homes.GoogleMaps.Facilities.showFacilities(facilitiesType);
            }
            else {
                Homes.GoogleMaps.Facilities.hideFacilities(facilitiesType);
            }
        },
        //addoverlay and removeoverlay used as the number of facilities returned should be small, clustering not appropriate
        //if the number becomes large, this should be recoded to use clustering
        showFacilities: function(facilitiesType) {
            if (!Homes.GoogleMaps.Facilities[facilitiesType]) {
                var postcode = Homes.DOM.getElementsByClassName(document, "span", "postal-code");
                if (postcode.length < 1) { return; }
                postcode = Homes.DOM.getTextNode(postcode[0]).nodeValue;
                //postcode = "E1 6RU";//test postcode
                Homes.GoogleMaps.Facilities.ajaxFacilities(facilitiesType, postcode);
            }
            else {
                var bounds = new GLatLngBounds();
                for (var i = 0, j = Homes.GoogleMaps.Facilities[facilitiesType].length; i < j; i++) {
                    var marker = Homes.GoogleMaps.Facilities[facilitiesType][i];
                    Homes.GoogleMaps.map.addOverlay(marker);
                    if (facilitiesType === "Schools")
                        bounds.extend(marker.getPoint());
                }

                //zoom to all the facilities
                if (facilitiesType === "Schools")
                    Homes.GoogleMaps.map.setZoom(Homes.GoogleMaps.map.getBoundsZoomLevel(bounds));
            }
        },
        hideFacilities: function(facilitiesType) {
            if (!Homes.GoogleMaps.Facilities[facilitiesType]) { return; }
            for (var i = 0, j = Homes.GoogleMaps.Facilities[facilitiesType].length; i < j; i++) {
                Homes.GoogleMaps.map.removeOverlay(Homes.GoogleMaps.Facilities[facilitiesType][i]);
            }
        },
        ajaxFacilities: function(facilitiesType, postcode) {
            var xhr = Homes.AJAX.createXMLHttpRequest();

            var url;
            if (facilitiesType == "Schools") {

                url = "/lbi.custom/xml/SchoolsNearDevelopment.aspx?search=" + postcode;
            }
            else {
                url = "/Global/UpMyStreet/" + facilitiesType + "/?postcode=" + postcode;
            }
            xhr.open("GET", url, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState != 4) { return false; }
                if (xhr.status != 200) {
                    return false;
                }
                var xhrResponse = xhr.responseXML;
                var root = xhrResponse.documentElement;
                Homes.GoogleMaps.Facilities.setFacilities(facilitiesType, root);
            }
            xhr.send(null);
            return false;
        },
        //fmn: get all 'item' elems
        //transport: get each type separately
        //schools: get all 'school' elems
        setFacilities: function(facilitiesType, data) {
            Homes.GoogleMaps.Facilities[facilitiesType] = [];
            //SCHOOLS
            if (facilitiesType === "Schools") {

                var facilityItems = data.getElementsByTagName("school");
                for (var i = 0, j = facilityItems.length; i < j; i++) {
                    var searchedSchool = false;
                    var fn = facilityItems[i].getElementsByTagName("name");

                    //alert(fn);

                    if (fn.length > 0) {
                        var info = {};
                        info.fn = Homes.DOM.getTextNode(fn[0]).nodeValue;
                        //	console.log(facilityItems[i].getElementsByTagName("distance")[0].childNodes[0].nodeValue);
                        var lat = facilityItems[i].getElementsByTagName("lat");
                        var lng = facilityItems[i].getElementsByTagName("long");

                        var geoLocation = { 'latitude': Homes.DOM.getTextNode(lat[0]).nodeValue, 'longitude': Homes.DOM.getTextNode(lng[0]).nodeValue };

                        var schooltype = facilityItems[i].getElementsByTagName("type");
                        var distanceElem = facilityItems[i].getElementsByTagName("distance");
                        if (distanceElem[0].childNodes[0].nodeValue == '0 miles') {
                            searchedSchool = true;
                        }
                        info.note = Homes.DOM.getTextNode(schooltype[0]).nodeValue + ", " + Homes.DOM.getTextNode(distanceElem[0]).nodeValue;


                        var infoHTML = Homes.GoogleMaps.createInfoHTML(info);
                        var marker = Homes.GoogleMaps.setMarker(geoLocation, infoHTML, facilitiesType, searchedSchool);
                        Homes.GoogleMaps.Facilities[facilitiesType].push(marker);
                    }
                }

            }

            //                var facilityItems = data.getElementsByTagName("sch_table");
            //                var itemLimit = 3;
            //                var secondaryIDs = [];
            //                for (var i = 0, j = facilityItems.length; i < j; i++) {
            //                    var facilities = facilityItems[i].getElementsByTagName("school");
            //                    var schoolType = facilityItems[i].getAttribute("table_type");
            //                    if (schoolType === "secondary") {
            //                        var secondaries = facilities;
            //                    }
            //                    var maxLoops = (facilities.length < itemLimit) ? facilities.length : itemLimit;

            //                    schoolLoop: for (var k = 0; k < maxLoops; k++) {
            //                        var lat = facilities[k].getElementsByTagName("lat");
            //                        var lng = facilities[k].getElementsByTagName("long");
            //                        if (lat.length < 1) { continue; }
            //                        if (lng.length < 1) { continue; }
            //                        var geoLocation = { 'latitude': Homes.DOM.getTextNode(lat[0]).nodeValue, 'longitude': Homes.DOM.getTextNode(lng[0]).nodeValue };
            //                        var info = {};
            //                        if (schoolType === "primary") {
            //                            info.note = "Primary School";
            //                        }
            //                        else if (schoolType === "secondary") {
            //                            info.note = "Secondary School";
            //                            secondaryIDs.push(facilities[k].getAttribute("sch_id"));
            //                        }
            //                        else if (schoolType === "6th") {
            //                            info.note = "Sixth Form College";
            //                            //caveat: sixth form may also be a secondary, hence looping through all secondaries
            //                            for (var m = 0, n = secondaryIDs.length; m < n; m++) {
            //                                if (secondaryIDs[m] == facilities[k].getAttribute("sch_id")) {
            //                                    continue schoolLoop;
            //                                }
            //                            }
            //                            //this is intensive, but only happens 3 times due to the maxlimit
            //                            for (var p = 0, q = secondaries.length; p < q; p++) {
            //                                if (secondaries[p].getAttribute("sch_id") == facilities[k].getAttribute("sch_id")) {
            //                                    info.note = "Secondary / " + info.note;
            //                                }
            //                            }
            //                        }
            //                        var fn = facilities[k].getElementsByTagName("sch_name");
            //                        if (fn.length > 0) {
            //                            info.fn = Homes.DOM.getTextNode(fn[0]).nodeValue;
            //                        }
            //                        var distanceElem = facilities[k].getElementsByTagName("distance");
            //                        info.note += ", " + Homes.DOM.getTextNode(distanceElem[0]).nodeValue;
            //                        info.note += " " + distanceElem[0].getAttribute("unit");

            //                        var infoHTML = Homes.GoogleMaps.createInfoHTML(info);
            //                        var marker = Homes.GoogleMaps.setMarker(geoLocation, infoHTML, facilitiesType);
            //                        Homes.GoogleMaps.Facilities[facilitiesType].push(marker);
            //                    }
            //                }
            //            }
            /*TRANSPORT*/
            else if (facilitiesType === "Transport") {
                var facilityItems = [];
                facilityItems.push(data.getElementsByTagName("TrainStations")[0]);
                facilityItems.push(data.getElementsByTagName("London_Underground")[0]);
                facilityItems.push(data.getElementsByTagName("Coaches")[0]);
                facilityItems.push(data.getElementsByTagName("Airports")[0]);
                facilityItems.push(data.getElementsByTagName("Ferrys")[0]);

                for (var i = 0, k = facilityItems.length; i < k; i++) {
                    var lat = facilityItems[i].getElementsByTagName("lat");
                    var lng = facilityItems[i].getElementsByTagName("long");
                    if (lat.length < 1) { continue; }
                    if (lng.length < 1) { continue; }
                    var geoLocation = { 'latitude': Homes.DOM.getTextNode(lat[0]).nodeValue, 'longitude': Homes.DOM.getTextNode(lng[0]).nodeValue };
                    var info = {};
                    info.postcode = Homes.DOM.getTextNode(facilityItems[i].getElementsByTagName("postcode")[0]).nodeValue;
                    var distanceElem = facilityItems[i].getElementsByTagName("distance");
                    info.note = Homes.DOM.getTextNode(distanceElem[0]).nodeValue;
                    info.note += " " + distanceElem[0].getAttribute("unit");
                    var addressElem = facilityItems[i].getElementsByTagName("address");
                    if (addressElem.length > 0) {
                        info.street = Homes.DOM.getTextNode(addressElem[0]).nodeValue;
                    }
                    var townElem = facilityItems[i].getElementsByTagName("town");
                    if (townElem.length > 0) {
                        info.locality = Homes.DOM.getTextNode(townElem[0]).nodeValue;
                    }
                    var countyElem = facilityItems[i].getElementsByTagName("county");
                    if (countyElem.length > 0) {
                        info.region = Homes.DOM.getTextNode(countyElem[0]).nodeValue;
                    }
                    info.fn = Homes.DOM.getTextNode(facilityItems[i].getElementsByTagName("name")[0]).nodeValue;
                    switch (facilityItems[i].nodeName) {
                        case "TrainStations":
                            info.fn = "Train station: " + info.fn;
                            break;
                        case "London_Underground":
                            info.fn = "London Underground: " + info.fn;
                            var line = Homes.DOM.getTextNode(facilityItems[i].getElementsByTagName("line")[0]).nodeValue;
                            info.note = line + " line, " + info.note;
                            break;
                        case "Coaches":
                            info.fn = "Coach station: " + info.fn;
                            break;
                        case "Airports":
                            info.fn = "Airport: " + info.fn;
                            break;
                        case "Ferrys":
                            info.fn = "Ferry port: " + info.fn;
                            break;
                    }

                    var infoHTML = Homes.GoogleMaps.createInfoHTML(info);
                    var marker = Homes.GoogleMaps.setMarker(geoLocation, infoHTML, facilitiesType);
                    Homes.GoogleMaps.Facilities[facilitiesType].push(marker);
                }
            }
            /*FMN*/
            else {
                var facilityItems = data.getElementsByTagName("item");
                for (var i = 0, k = facilityItems.length; i < k; i++) {
                    var northing = facilityItems[i].getElementsByTagName("y");
                    var easting = facilityItems[i].getElementsByTagName("x");
                    if (northing.length < 1) { continue; }
                    if (easting.length < 1) { continue; }
                    var geoLocation = Homes.GoogleMaps.convertNorthingEastingToLatLng(Homes.DOM.getTextNode(easting[0]).nodeValue, Homes.DOM.getTextNode(northing[0]).nodeValue);
                    var info = {};
                    info.postcode = Homes.DOM.getTextNode(facilityItems[i].getElementsByTagName("postcode")[0]).nodeValue;
                    var distanceElem = facilityItems[i].getElementsByTagName("distance");
                    info.note = Homes.DOM.getTextNode(distanceElem[0]).nodeValue; //NB distance is different for fmn
                    var addressElem = facilityItems[i].getElementsByTagName("address");
                    if (addressElem.length > 0) {
                        info.street = Homes.DOM.getTextNode(addressElem[0]).nodeValue;
                    }
                    var townElem = facilityItems[i].getElementsByTagName("town");
                    if (townElem.length > 0) {
                        info.locality = Homes.DOM.getTextNode(townElem[0]).nodeValue;
                    }
                    var countyElem = facilityItems[i].getElementsByTagName("county");
                    if (countyElem.length > 0) {
                        info.region = Homes.DOM.getTextNode(countyElem[0]).nodeValue;
                    }
                    info.fn = Homes.DOM.getTextNode(facilityItems[i].getElementsByTagName("name")[0]).nodeValue;

                    var infoHTML = Homes.GoogleMaps.createInfoHTML(info);
                    var marker = Homes.GoogleMaps.setMarker(geoLocation, infoHTML, facilitiesType);
                    Homes.GoogleMaps.Facilities[facilitiesType].push(marker);
                }
            }
            Homes.GoogleMaps.Facilities.showFacilities(facilitiesType);
        }
    },
    //	MARKERS
    markers: [],
    //geolocation expects an object with latitude and longitude
    //infohtml is the html for the popup information window
    //buildingtype is the type of icon to show
    setMarker: function(geoLocation, infoHTML, buildingType, searchedSchool) {
        var geo = new GLatLng(geoLocation.latitude, geoLocation.longitude);
        var h3 = infoHTML.getElementsByTagName("h3");
        var h3Text = "";
        if (h3.length > 0) {
            h3Text = h3[0].innerHTML;
        }
        var markertitle = h3Text;
        if (buildingType === "future") { markertitle = "Coming soon: " + markertitle; }
        function zOrder(marker, b) {
            return GOverlay.getZIndex(marker.getPoint().lat()) + marker.importance * 1000000;
        }
        if (searchedSchool == true) buildingType = 'thisschools';
        var marker = new GMarker(geo, { icon: Homes.GoogleMaps.getIcon(buildingType), title: markertitle, zIndexProcess: zOrder });
        GEvent.addListener(marker, "click", function() {
            this.openInfoWindow(infoHTML);
        });
        if (buildingType === "home")
            marker.importance = 3;
        else
            marker.importance = 1;
        marker.heading = h3Text;
        Homes.GoogleMaps.markers.push(marker);

        return marker;
    },
    setMarkerNoPush: function(geoLocation, infoHTML, buildingType) {
        var geo = new GLatLng(geoLocation.latitude, geoLocation.longitude);
        var h3 = infoHTML.getElementsByTagName("h3");
        var h3Text = "";
        if (h3.length > 0) {
            h3Text = h3[0].innerHTML;
        }
        var markertitle = h3Text;
        if (buildingType === "future") { markertitle = "Coming soon: " + markertitle; }
        function zOrder(marker, b) {
            return GOverlay.getZIndex(marker.getPoint().lat()) + marker.importance * 1000000;
        }
        var marker = new GMarker(geo, { icon: Homes.GoogleMaps.getIcon(buildingType), title: markertitle, zIndexProcess: zOrder });
        GEvent.addListener(marker, "click", function() {
            this.openInfoWindow(infoHTML);
        });
        if (buildingType === "home")
            marker.importance = 3;
        else
            marker.importance = 1;
        marker.heading = h3Text;
        return marker;
    },
    getIcon: function(buildingType) {
        switch (buildingType.toLowerCase()) {
            case "work":
                return Homes.GoogleMaps.officeIcon;
            case "home":
                return Homes.GoogleMaps.houseIcon;
            case "future":
                return Homes.GoogleMaps.futureIcon;
            case "shopping":
                return Homes.GoogleMaps.shoppingIcon;
            case "banks":
                return Homes.GoogleMaps.banksIcon;
            case "parking":
                return Homes.GoogleMaps.parkingIcon;
            case "transport":
                return Homes.GoogleMaps.trainIcon;
            case "schools":
                return Homes.GoogleMaps.schoolIcon;
            case "thisschools":
                return Homes.GoogleMaps.thisSchoolIcon;
            default:
                return "";
        }
    },
    setIcons: function() {
        var baseIcon = new GIcon();
        baseIcon.iconSize = new GSize(29, 30);
        baseIcon.iconAnchor = new GPoint(20, 30);
        baseIcon.infoWindowAnchor = new GPoint(20, 2);
        baseIcon.shadow = '/assets/img/' + CompanyCode + '/css/ico_map_shadow.png';
        baseIcon.shadowSize = new GSize(47, 30);
        baseIcon.printShadow = '';

        Homes.GoogleMaps.houseIcon = new GIcon(baseIcon);
        Homes.GoogleMaps.houseIcon.image = '/assets/img/' + CompanyCode + '/css/ico_map_house.png';
        Homes.GoogleMaps.houseIcon.printImage = '/assets/img/' + CompanyCode + '/css/ico_map_house_print.gif';
        Homes.GoogleMaps.houseIcon.mozPrintImage = Homes.GoogleMaps.houseIcon.printImage;
        Homes.GoogleMaps.futureIcon = new GIcon(baseIcon);
        Homes.GoogleMaps.futureIcon.image = '/assets/img/' + CompanyCode + '/css/ico_map_comingsoon.png';
        Homes.GoogleMaps.futureIcon.printImage = '/assets/img/' + CompanyCode + '/css/ico_map_comingsoon_print.gif';
        Homes.GoogleMaps.futureIcon.mozPrintImage = Homes.GoogleMaps.futureIcon.printImage;
        Homes.GoogleMaps.officeIcon = new GIcon(baseIcon);
        Homes.GoogleMaps.officeIcon.image = '/assets/img/' + CompanyCode + '/css/ico_map_office.png';
        Homes.GoogleMaps.officeIcon.printImage = '/assets/img/' + CompanyCode + '/css/ico_map_office_print.gif';
        Homes.GoogleMaps.officeIcon.mozPrintImage = Homes.GoogleMaps.officeIcon.printImage;
        Homes.GoogleMaps.clusterIcon = new GIcon(baseIcon);
        Homes.GoogleMaps.clusterIcon.image = '/assets/img/' + CompanyCode + '/css/ico_map_cluster.png';
        Homes.GoogleMaps.clusterIcon.printImage = '/assets/img/' + CompanyCode + '/css/ico_map_cluster_print.gif';
        Homes.GoogleMaps.clusterIcon.mozPrintImage = Homes.GoogleMaps.clusterIcon.printImage;
        Homes.GoogleMaps.schoolIcon = new GIcon(baseIcon);
        Homes.GoogleMaps.schoolIcon.image = '/assets/img/' + CompanyCode + '/css/ico_map_school.png';
        Homes.GoogleMaps.schoolIcon.printImage = '/assets/img/' + CompanyCode + '/css/ico_map_school_print.gif';
        Homes.GoogleMaps.schoolIcon.mozPrintImage = Homes.GoogleMaps.schoolIcon.printImage;
        Homes.GoogleMaps.thisSchoolIcon = new GIcon(baseIcon);
        Homes.GoogleMaps.thisSchoolIcon.image = '/assets/img/' + CompanyCode + '/css/ico_map_thisschool.png';
        Homes.GoogleMaps.trainIcon = new GIcon(baseIcon);
        Homes.GoogleMaps.trainIcon.image = '/assets/img/' + CompanyCode + '/css/ico_map_train.png';
        Homes.GoogleMaps.trainIcon.printImage = '/assets/img/' + CompanyCode + '/css/ico_map_train_print.gif';
        Homes.GoogleMaps.trainIcon.mozPrintImage = Homes.GoogleMaps.trainIcon.printImage;
        Homes.GoogleMaps.banksIcon = new GIcon(baseIcon);
        Homes.GoogleMaps.banksIcon.image = '/assets/img/' + CompanyCode + '/css/ico_map_banks.png';
        Homes.GoogleMaps.banksIcon.printImage = '/assets/img/' + CompanyCode + '/css/ico_map_banks_print.gif';
        Homes.GoogleMaps.banksIcon.mozPrintImage = Homes.GoogleMaps.banksIcon.printImage;
        Homes.GoogleMaps.shoppingIcon = new GIcon(baseIcon);
        Homes.GoogleMaps.shoppingIcon.image = '/assets/img/' + CompanyCode + '/css/ico_map_shopping.png';
        Homes.GoogleMaps.shoppingIcon.printImage = '/assets/img/' + CompanyCode + '/css/ico_map_shopping_print.gif';
        Homes.GoogleMaps.shoppingIcon.mozPrintImage = Homes.GoogleMaps.shoppingIcon.printImage;
        Homes.GoogleMaps.parkingIcon = new GIcon(baseIcon);
        Homes.GoogleMaps.parkingIcon.image = '/assets/img/' + CompanyCode + '/css/ico_map_parking.png';
        Homes.GoogleMaps.parkingIcon.printImage = '/assets/img/' + CompanyCode + '/css/ico_map_parking_print.gif';
        Homes.GoogleMaps.parkingIcon.mozPrintImage = Homes.GoogleMaps.parkingIcon.printImage;
    },
    //extracted from http://www.movable-type.co.uk/scripts/latlong-gridref.html © 2005–2008 Chris Veness
    convertNorthingEastingToLatLng: function(easting, northing) {
        var E = easting, N = northing;
        var a = 6377563.396, b = 6356256.910;              // Airy 1830 major & minor semi-axes
        var F0 = 0.9996012717;                             // NatGrid scale factor on central meridian
        var lat0 = 49 * Math.PI / 180, lon0 = -2 * Math.PI / 180;  // NatGrid true origin
        var N0 = -100000, E0 = 400000;                     // northing & easting of true origin, metres
        var e2 = 1 - (b * b) / (a * a);                          // eccentricity squared
        var n = (a - b) / (a + b), n2 = n * n, n3 = n * n * n;
        var lat = lat0, M = 0;
        do {
            lat = (N - N0 - M) / (a * F0) + lat;
            var Ma = (1 + n + (5 / 4) * n2 + (5 / 4) * n3) * (lat - lat0);
            var Mb = (3 * n + 3 * n * n + (21 / 8) * n3) * Math.sin(lat - lat0) * Math.cos(lat + lat0);
            var Mc = ((15 / 8) * n2 + (15 / 8) * n3) * Math.sin(2 * (lat - lat0)) * Math.cos(2 * (lat + lat0));
            var Md = (35 / 24) * n3 * Math.sin(3 * (lat - lat0)) * Math.cos(3 * (lat + lat0));
            M = b * F0 * (Ma - Mb + Mc - Md);                // meridional arc
        } while (N - N0 - M >= 0.00001);  // ie until < 0.01mm

        var cosLat = Math.cos(lat), sinLat = Math.sin(lat);
        var nu = a * F0 / Math.sqrt(1 - e2 * sinLat * sinLat);              // transverse radius of curvature
        var rho = a * F0 * (1 - e2) / Math.pow(1 - e2 * sinLat * sinLat, 1.5);  // meridional radius of curvature
        var eta2 = nu / rho - 1;

        var tanLat = Math.tan(lat);
        var tan2lat = tanLat * tanLat, tan4lat = tan2lat * tan2lat, tan6lat = tan4lat * tan2lat;
        var secLat = 1 / cosLat;
        var nu3 = nu * nu * nu, nu5 = nu3 * nu * nu, nu7 = nu5 * nu * nu;
        var VII = tanLat / (2 * rho * nu);
        var VIII = tanLat / (24 * rho * nu3) * (5 + 3 * tan2lat + eta2 - 9 * tan2lat * eta2);
        var IX = tanLat / (720 * rho * nu5) * (61 + 90 * tan2lat + 45 * tan4lat);
        var X = secLat / nu;
        var XI = secLat / (6 * nu3) * (nu / rho + 2 * tan2lat);
        var XII = secLat / (120 * nu5) * (5 + 28 * tan2lat + 24 * tan4lat);
        var XIIA = secLat / (5040 * nu7) * (61 + 662 * tan2lat + 1320 * tan4lat + 720 * tan6lat);

        var dE = (E - E0), dE2 = dE * dE, dE3 = dE2 * dE, dE4 = dE2 * dE2, dE5 = dE3 * dE2, dE6 = dE4 * dE2, dE7 = dE5 * dE2;
        lat = lat - VII * dE2 + VIII * dE4 - IX * dE6;
        var lon = lon0 + X * dE - XI * dE3 + XII * dE5 - XIIA * dE7;
        return { 'latitude': lat.toDeg(), 'longitude': lon.toDeg() };
    }

}

/*LIGHTBOX
	a lightbox is a box of content that sits above the main area, which is usually faded out
	setting up the tint bg element at init phase works around a obscure IE bug
	REQUIRED:
		class 'PE_lightBox'  (NB case-sensitive) on the div to become a lightbox, this area must also have an id
		class 'PE_lightboxOpen(id_of_lightbox)' on the anchor that triggers the lightbox if triggered by a link
		class 'PE_lightboxIfInvalid(id_of_lightbox)' on the div with the PE_validate() class if the lightbox is triggered by an invalid field (see validate section comments for further details)
*/
Homes.Lightbox = {
	active : 0,
	height: 0,
	init : function(){
		var lightboxes = Homes.DOM.fuzzyClassName("div","PE_lightBox");
		var lightboxLinks = Homes.DOM.fuzzyClassName("a","PE_lightboxOpen");
		for(var i=0,j=lightboxes.length;i<j;i++){
			var lightboxContainer = Homes.DOM.getParentByTagName(lightboxes[0],"form");
			if(!lightboxContainer){lightboxContainer = document.getElementsByTagName('body')[0]};
			lightboxes[i].style.visibility = "visible";  //remove styles from IE foc prevention
			//take out of position in HTML and insert at end of page, necessary for placing above the tinted background in IE

			var lightbox = lightboxes[i].parentNode.removeChild(lightboxes[i]);
			lightboxContainer.appendChild(lightbox);
			
			Homes.Lightbox.hideLightbox(lightbox);
			Homes.Lightbox.addBoxStyles(lightbox);
			Homes.Lightbox.addBoxClose(lightbox);
		}
		Homes.Lightbox.active = 0;
		Homes.Lightbox.setUpTintBg();
		for(var h=0,m=lightboxLinks.length;h<m;h++){
			lightboxLinks[h].className = lightboxLinks[h].className.replace("hidden","");
			lightboxLinks[h].onclick=function(){
				var thisLightbox = document.getElementById(Homes.DOM.getPEClassInfo(this,"PE_lightboxOpen"));
				if(typeof thisLightbox == "undefined"){alert("DEV ERROR: no element with ID specified in link's class");return;}

				Homes.Lightbox.showLightbox(thisLightbox);
				Homes.Lightbox.tintBg();
				return false;
			}
		}
		//lightbox on page load - this should be the last part of init()
		if(location.hash.indexOf("lightbox_") != -1){
			var thisLightbox = document.getElementById(location.hash.replace("#",""));
			if(!thisLightbox){return;}
			Homes.Lightbox.showLightbox(thisLightbox);
			Homes.Lightbox.tintBg();
		}
	},
	/*dynamically creates a lightbox.
	takes either a string or node object for headNode and contentNode and a string for id*/
	create: function(headNode,contentNode,id){
		var lightbox = document.createElement("div");
			lightbox.className = "lightBox PE_lightBox";
			var i=0;
			while(document.getElementById(id)){
				i++;
				var lastUScore = id.lastIndexOf("_");
				var ind = id.substring(lastUScore+1);
				if(parseInt(ind)){
					id = id.substring(0,lastUScore+1) + i;
				}
				else{
					id = id + "_" + i;
				}
			}
			lightbox.id = id;
		var lightboxHead = document.createElement("div");
			lightboxHead.className = "heading";
			if(typeof(headNode) == "string"){
				headNode = document.createTextNode(headNode);
			}
			lightboxHead.appendChild(headNode);
		lightbox.appendChild(lightboxHead);
		var lightboxContent = document.createElement("div");
			lightboxContent.className = "content";
			if(typeof(contentNode) == "string"){
				contentNode = document.createTextNode(contentNode);
			}
			lightboxContent.appendChild(contentNode);
		lightbox.appendChild(lightboxContent);
		document.body.className += " hasJS";
		Homes.Lightbox.hideLightbox(lightbox);
		Homes.Lightbox.addBoxStyles(lightbox);
		Homes.Lightbox.addBoxClose(lightbox);
		var pageDiv = document.getElementById("Page");
		pageDiv.appendChild(lightbox);
		lightbox.style.visibility = "visible";  //remove styles from IE foc prevention
		return lightbox;
	},
	//NB - this section may not be necessary, awaiting design
	addBoxStyles : function(elem_lightbox){
		//middle - take all children of lightbox and put them into the boxRight div
		var boxRight = document.createElement("div");
			boxRight.className = "lightbox-right";
		while(elem_lightbox.childNodes.length > 0){
			boxRight.appendChild(elem_lightbox.firstChild);
		}
		var boxMain = document.createElement("div");
			boxMain.className = "lightbox-main";
			boxMain.appendChild(boxRight);
		elem_lightbox.appendChild(boxMain);
		//top
		var boxTop = document.createElement("div");
			boxTop.className = "lightbox-top"
		var boxTopLeft = document.createElement("div");
			boxTopLeft.className = "lightbox-top-left";
		var boxTopRight = document.createElement("div");
			boxTopRight.className = "lightbox-top-right";
			boxTopLeft.appendChild(boxTopRight);
			boxTopLeft.appendChild(boxTop);
			elem_lightbox.insertBefore(boxTopLeft,elem_lightbox.firstChild);
		//base
		var boxBase = document.createElement("div");
			boxBase.className = "lightbox-base";
		var boxBaseLeft = document.createElement("div");
			boxBaseLeft.className = "lightbox-base-left";
		var boxBaseRight = document.createElement("div");
			boxBaseRight.className = "lightbox-base-right";
			boxBaseLeft.appendChild(boxBaseRight);
			boxBaseLeft.appendChild(boxBase);
			elem_lightbox.appendChild(boxBaseLeft);
	},
	closeLightbox : function(elem_lightbox){
		Homes.Lightbox.rehideLightbox(elem_lightbox);
		Homes.Lightbox.removeTintBg();
		//accessibility aid: refocus on the link or validated field that triggered the lightbox
		var lightboxTrigger = Homes.DOM.fuzzyClassName("a","PE_lightboxOpen(" + elem_lightbox.id + ")")[0];
		if(!lightboxTrigger){
			var lightboxDiv = Homes.DOM.fuzzyClassName("div","PE_lightboxIfInvalid(" + elem_lightbox.id + ")")[0];
			if(lightboxDiv){lightboxTrigger = lightboxDiv.getElementsByTagName("input")[0];}
		}
		if(lightboxTrigger){lightboxTrigger.focus();}
		return false;
	},
	addBoxClose : function(elem_lightbox){
		var closeLinkTxt = document.createTextNode("Close");
		closeLink = document.createElement("a");
			closeLink.href = "#";
			closeLink.id = "close_" + elem_lightbox.id;
			closeLink.className = "closeBtn clearfix";
			closeLink.onclick = function(){
				Homes.Lightbox.closeLightbox(elem_lightbox);
				return false;
			}
		var closeSpan = document.createElement("span");
		closeSpan.appendChild(closeLinkTxt);
		closeLink.appendChild(closeSpan);
		var lightboxHeading = Homes.DOM.getElementsByClassName(elem_lightbox,"*","heading")[0];
		lightboxHeading.insertBefore(closeLink,lightboxHeading.firstChild);
		lightboxHeading.className += " clearfix";
		//accessibility aid: add hidden close at bottom of lightbox
		var closeLinkHidden = document.createElement("a");
			closeLinkHidden.appendChild(document.createTextNode("End of in page popup. Close using this link to return to main content."));
			closeLinkHidden.href = "#";
			closeLinkHidden.className = "hidden";
			closeLinkHidden.onclick = closeLink.onclick;
		elem_lightbox.appendChild(closeLinkHidden);
		elem_lightbox.closeButtons = [closeLink,closeLinkHidden];
		//detect cancel buttons in HTML and use those too
		var cancelLinks = Homes.DOM.fuzzyClassNameBlock(elem_lightbox,"a","PE_closeLightbox");
		for(var i=0;i<cancelLinks.length;i++){
			cancelLinks[i].onclick = closeLink.onclick;
			elem_lightbox.closeButtons.push(cancelLinks[i]);
		}
	},
	setUpTintBg : function(){
		/*@cc_on @*/
		/*@if (@_jscript_version < 5.6)
			return; // impossible in IE5
		/*@end @*/
		var pageDiv = document.getElementsByTagName("form")[0];
		if (pageDiv != undefined)
		{
	    var tint = document.createElement("div");
	    tint.className = "tintedBg";
	    pageDiv.insertBefore(tint,pageDiv.firstChild);
		}
	},
	tintBg : function(){
		if(Homes.Lightbox.hasCSS() == false){return;}
		var tint = Homes.DOM.getElementsByClassName(document,"div","tintedBg")[0];
		if(!tint){return;}
		tint.style.height = "0px";
		var pageDimensions = Homes.DOM.getFullPageDimensions();
		var newWidth = pageDimensions[0];
		var newHeight = pageDimensions[1];
		if(Homes.Lightbox.height > newHeight){
			tint.style.height = Homes.Lightbox.height +"px";
		}
		else{
			tint.style.height = newHeight +"px";
		}
		tint.style.width = newWidth +"px";
	},
	removeTintBg : function(){
		if(Homes.Lightbox.active > 0){return;}
		var tint = Homes.DOM.getElementsByClassName(document,"div","tintedBg")[0];
		if(!tint){return;}
		tint.style.width = "0px";
		tint.style.height = "0px";
	},
	showLightbox : function(elem_lightbox){
		/*@cc_on @*/
		/*@if (@_jscript_version <= 5.6)
			Homes.Lightbox.hideSelects(elem_lightbox); //hide select boxes due to buggy IE6 handling of them
		/*@end @*/
		elem_lightbox.className = elem_lightbox.className.replace(/ hideLightbox/g,"");
		//set the lightbox in the vertical center of the page, account for relatively-positioned parents
		// if the lightbox is bigger than the viewport, set its top to the top of the viewable screen
		var viewPortCenter = Math.round(Homes.DOM.getViewPortHeight() / 2);
		var scrolledTop = Homes.DOM.getScrollTop();
		var userViewCenter = parseInt(viewPortCenter) + parseInt(scrolledTop);
		var lightboxCenter = elem_lightbox.offsetHeight / 2;
		var lightboxRelativeTop = 0;
		var parent = elem_lightbox.parentNode;
		while(parent){
			if(parent.nodeName=="#document"){break;}
			if(Homes.DOM.getStyle(parent,"position") == "relative"){
				lightboxRelativeTop += parent.offsetTop;
			}
			parent = parent.parentNode;
		}
		if(Homes.DOM.getViewPortHeight() < elem_lightbox.offsetHeight){
			elem_lightbox.style.top = scrolledTop - lightboxRelativeTop + "px";
		}
		else{
			elem_lightbox.style.top = userViewCenter - lightboxCenter - lightboxRelativeTop + "px";
		}
		Homes.Lightbox.active++;
		Homes.Lightbox.height = parseInt(elem_lightbox.offsetHeight) + parseInt(elem_lightbox.offsetTop);
		//accessibility aid: send cursor to close button on the lightbox
		var closebtn = document.getElementById("close_" + elem_lightbox.id);
		var hiddenFocusLink = document.getElementById("hiddenFocus_" + elem_lightbox.id);
		if(!hiddenFocusLink){
			var hiddenFocusLink = document.createElement("a");
				hiddenFocusLink.href = "#";
				hiddenFocusLink.onclick = function(){return false;}
				hiddenFocusLink.id = "hiddenFocus_" + elem_lightbox.id;
				hiddenFocusLink.appendChild(document.createTextNode("In page pop-up layer.  Use close links to return to main content."));
			closebtn.parentNode.insertBefore(hiddenFocusLink,closebtn);
		}
		hiddenFocusLink.focus();
		hiddenFocusLink.className = "hidden";
	},
	hideLightbox : function(elem_lightbox){
		/*@cc_on @*/
		/*@if (@_jscript_version <= 5.6)
			Homes.Lightbox.showSelects();
		/*@end @*/
		elem_lightbox.className += " hideLightbox";
		var hiddenFocusLink = document.getElementById("hiddenFocus_" + elem_lightbox.id);
		if(hiddenFocusLink){hiddenFocusLink.className = hiddenFocusLink.className.replace("hidden","");}
	},
	rehideLightbox : function(elem_lightbox){
		Homes.Lightbox.hideLightbox(elem_lightbox);
		Homes.Lightbox.active--;
	},
	//one for set up, one for show/hide
	//hide select boxes due to buggy IE<7 handling of them
	hideSelects : function(){
		var selects = document.getElementsByTagName("select");
		for(var i=0;i<selects.length;i++){
			selects[i].style.visibility = "hidden";
		}
	},
	showSelects : function(){
		var selects = document.getElementsByTagName("select");
		for(var i=0;i<selects.length;i++){
			selects[i].style.visibility = "visible";
		}
	},
	hasCSS : function(){
		var tintedBg = Homes.DOM.getElementsByClassName(document.body,"div","tintedBg")[0];
		if(Homes.DOM.getStyle(tintedBg,"position") != "absolute"){
			return false;
		}
		return true;
	}
};

/*
PRINT PAGE
	buttons to trigger the print dialog for the user to print the page.  these are hidden with CSS and re-displayed with javascript so that non-js users don't see a button they cannot use.
REQUIRED:
	<a> or <input> with class 'print' on it
*/
Homes.Print = {
	setLinks : function(){
		var printLinks = Homes.DOM.getElementsByClassName(document,"a","PE_print");
		for(var i=0,j=printLinks.length;i<j;i++){
			if(window.print){printLinks[i].style.display = "block";}
			printLinks[i].onclick = Homes.Print.printpage;

		}
	},
	printpage : function(){
		window.print();
		return false;
	}
};
Homes.Popup = {
	setLinks : function(){
		var popupLinks = Homes.DOM.fuzzyClassName("a","PE_popup");
		for(var i=0,j=popupLinks.length;i<j;i++){
			var dimensions = Homes.DOM.getPEClassInfo(popupLinks[i],"PE_popup");
			var aDim = dimensions.split(",");
			popupLinks[i].winWidth = aDim[0];
			popupLinks[i].winHeight = aDim[1];
			Home.DOM.addEvent(popupLinks[i],'click',Homes.Popup.openWin);
		}
	},
	openWin : function(){
		window.open(this.href,this.href,'width='+this.winWidth+'height='+this.winHeight+"resizeable=true,scrollbars=true")
	}
};
/*Generic AJAX functions*/
/* XML DATA REQUEST AND MANIPULATION FUNCTIONS */

// returns a cross-browser XMLHTTPRequest object
Homes.AJAX = {
	createXMLHttpRequest : function() {
		try { return new XMLHttpRequest(); } catch(e) {}
		try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
		try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
		alert("XMLHttpRequest not supported");
		return null;
	},
	processing : {
		getDisplay : function(){
			var processingImg = document.getElementById("ajax_wait");
			if(!processingImg){
				var processingImg = document.createElement("img");
				processingImg.src="/assets/img/"+CompanyCode+"/css/ajax-loader.gif";
				processingImg.alt="Please wait, processing your request.";
				processingImg.id="ajax_wait";
			}
			return processingImg;
		}
	},
//accessibility hack: updates the value of a hidden field to trigger a buffer refresh. called in the functions that are run when an AJAX call has returned data or error
	updateBuffer : function(){
		var bufferReset = document.getElementById("bufferReset");
		if(!bufferReset){
			var bufferReset = document.createElement("input");
			bufferReset.type="hidden";
			bufferReset.name="bufferReset";
			bufferReset.value=1;
			bufferReset.id="bufferReset";
			document.body.appendChild(bufferReset);
		}
		bufferReset.value++;
	}
}
/*Generic DOM functions*/
Homes.DOM = {
    getElementsByClassName: function(oElm, strTagName, strClassName) {
        var arrElements = (strTagName == "*" && oElm.all) ? oElm.all : oElm.getElementsByTagName(strTagName);
        var arrReturnElements = [];
        strClassName = strClassName.replace(/\-/g, "\\-");
        var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
        var oElement;
        for (var i = 0; i < arrElements.length; i++) {
            oElement = arrElements[i];
            if (oRegExp.test(oElement.className)) {
                arrReturnElements.push(oElement);
            }
        }
        return (arrReturnElements);
    },

    getParentByTagName: function(el, tagName) {
        var parent = el.parentNode;
        while (tagName.toLowerCase() != parent.nodeName.toLowerCase()) {
            parent = parent.parentNode;
            if (!parent || parent.nodeName == "#document") { return false; }
        }
        return parent;
    },
    //returns the first parent node of oElm that has strClassName in its class attribute
    //classname is 'fuzzy'
    getParentByClassName: function(oElm, strClassName) {
        var parent = oElm.parentNode;
        while (parent.className.indexOf(strClassName) == -1) {
            parent = parent.parentNode;
            if (!parent || parent.nodeName == "#document") { return false; }
        }
        return parent;
    },
    //returns the first sibling node it finds with the matching class name in a given direction
    //requires element, class name to find and previous or next as direction to search in
    getFirstSiblingByClassName: function(elem, strClassName, direction) {
        var sibling = elem[direction + 'Sibling'];
        while (sibling) {
            if (sibling.nodeType != 1) { sibling = sibling.previousSibling; continue; }
            if (sibling.className.indexOf(strClassName) != -1) {
                return sibling;
            }
            sibling = sibling[direction + 'Sibling'];
        }
        return false;
    },

    //finds the elements in oElm's block that has a specified attribute with a specified value
    //CAVEAT: IE6 and below has patchy support for class attribute, don't use for that
    getByAttribute: function(oElm, strTagName, attribName, attribValue) {
        var sEls = oElm.getElementsByTagName(strTagName);
        var aElms = [];
        for (var s = 0; s < sEls.length; s++) {
            if (sEls[s].getAttribute(attribName) == attribValue) {
                aElms.push(sEls[s]);
            }
        }
        return aElms;
    },
    fuzzyClassName: function(tag, fClass) {
        var el = (tag == "*" && document.all) ? document.all : document.getElementsByTagName(tag);
        var o = [];
        for (var i = 0; i < el.length; i++) {
            if (el[i].className.indexOf(fClass) != -1) {
                o.push(el[i]);
            }
        }
        return o;
    },
    //as fuzzyClassName, but restriced to self and children of a specific DOM object
    fuzzyClassNameBlock: function(block, tag, fClass) {
        var el = (tag == "*" && block.all) ? block.all : block.getElementsByTagName(tag);

        var o = [];
        for (var i = 0; i < el.length; i++) {
            if (el[i].className.indexOf(fClass) != -1) {
                o.push(el[i]);
            }
        }
        if (block.className.indexOf(fClass) != -1) {
            o.push(block);
        }
        return o;
    },
    //get the contents between ( and ) marks attached to a classname that starts with a given marker
    getPEClassInfo: function(el, marker) {
        var fullClass = el.className;
        var info = fullClass.substring(fullClass.indexOf(marker + "(") + marker.length + 1);
        info = info.substring(0, info.indexOf(")"));
        return info;
    },

    //takes an object and a string of key-value pairs seperated by commas
    //adds the key-value pairs as expandos to the object
    getPEHash: function(el, str) {
        var arr = str.split(",");
        for (var i = 0; i < arr.length; i++) {
            var keyVal = arr[i].split("=");
            el[keyVal[0]] = keyVal[1];
        }
    },

    //handle cross-browser reading of CSS-set styles
    getStyle: function(el, stylename) {
        if (el.style[stylename]) {
            return el.style[stylename];
        }
        else if (el.currentStyle) {
            //handle IE's style-name to styleName convention
            if (stylename.indexOf("-") != -1 && !el.currentStyle[stylename]) {
                //get 1st char after -, uppercase, rem -
                var preHyphen = stylename.substr(0, stylename.indexOf("-"));
                var postHyphenFirstLetter = stylename.substr(stylename.indexOf("-") + 1, 1).toUpperCase();
                var postHyphenRemainder = stylename.substr(stylename.indexOf("-") + 2);
                stylename = preHyphen + postHyphenFirstLetter + postHyphenRemainder;
            }
            return el.currentStyle[stylename];
        }
        else if (document.defaultView && document.defaultView.getComputedStyle) {
            return document.defaultView.getComputedStyle(el, null).getPropertyValue(stylename);
        }
        else { return false; }
    },
    //handle cross-browser viewport height
    getViewPortHeight: function() {
        if (window.innerHeight) {
            return window.innerHeight;
        }
        else if (document.documentElement && document.documentElement.clientHeight) {
            return document.documentElement.clientHeight;
        }
        else if (document.body) {
            return document.body.clientHeight;
        }
        else { return false; }
    },
    //handle cross-browser viewport width
    getViewPortWidth: function() {
        if (window.innerWidth) {
            return window.innerWidth;
        }
        else if (document.documentElement && document.documentElement.clientWidth) {
            return document.documentElement.clientWidth;
        }
        else if (document.body) {
            return document.body.clientWidth;
        }
        else { return false; }
    },
    //find and compare viewport and body heights and widths. return the largest of each dimension in array
    getFullPageDimensions: function() {
        var newHeight = Homes.DOM.getViewPortHeight();
        var newWidth = Homes.DOM.getViewPortWidth();
        /*compare with body */
        if (newWidth < document.body.clientWidth) {
            newWidth = document.body.clientWidth;
            newWidth += parseInt(Homes.DOM.getStyle(document.body, "margin-left"), 10) + parseInt(Homes.DOM.getStyle(document.body, "margin-right"), 10);
        }
        if (newHeight < document.body.clientHeight) {
            newHeight = document.body.clientHeight;
            newHeight += parseInt(Homes.DOM.getStyle(document.body, "margin-top"), 10) + parseInt(Homes.DOM.getStyle(document.body, "margin-bottom"), 10);
            if (window.innerWidth && window.innerWidth > document.body.scrollWidth) { newWidth -= 17; } //handle Firefox bug where it counts the scrollbar too for scrolling pages
        }
        else if (newHeight < document.body.scrollHeight) {//quirksmode handling
            newHeight = document.body.scrollHeight;
        }

        return [newWidth, newHeight];
    },
    //handle cross-browser retrieval of how far user has scrolled down
    getScrollTop: function() {
        if (window.pageYOffset) {
            return window.pageYOffset;
        }
        else if (document.documentElement && document.documentElement.scrollTop) {
            return document.documentElement.scrollTop;
        }
        else if (document.body) {
            return document.body.scrollTop;
        }
        else { return false; }
    },
    // returns an absolute x position of the given element object 'o'.
    getAbsoluteX: function(o) {
        oLeft = o.offsetLeft;
        while (o.offsetParent !== null) {
            oParent = o.offsetParent;
            oLeft += oParent.offsetLeft;
            o = oParent;
        }
        return oLeft;
    },
    // returns an absolute y position of the given element object 'o'.
    getAbsoluteY: function(o) {
        oTop = o.offsetTop;
        while (o.offsetParent !== null) {
            oParent = o.offsetParent;
            oTop += oParent.offsetTop;
            o = oParent;
        }
        return oTop;
    },
    //returns an x position from the nearest relative parent to element object 'o'
    getRelativeX: function(o) {
        oLeft = o.offsetLeft;
        while (o.offsetParent !== null && Homes.DOM.getStyle(o.offsetParent, "position") != "relative") {
            oParent = o.offsetParent;
            oLeft += oParent.offsetLeft;
            o = oParent;
        }
        return oLeft;
    },
    //returns a y position from the nearest relative parent to element object 'o'
    getRelativeY: function(o) {
        oTop = o.offsetTop;
        while (o.offsetParent !== null && Homes.DOM.getStyle(o.offsetParent, "position") != "relative") {
            oParent = o.offsetParent;
            oTop += oParent.offsetTop;
            o = oParent;
        }
        return oTop;
    },
    //get the first text node or CDATA section of a given element
    getTextNode: function(elem) {
        var children = elem.childNodes;
        for (var i = 0; i < children.length; i++) {
            if (children[i].nodeType == 3 || children[i].nodeType == 4) {
                return children[i];
            }
        }
        return false;
    },
    insertAfter: function(newElem, elem) {
        if (elem.nextSibling) {
            elem.parentNode.insertBefore(newElem, elem.nextSibling);
        }
        else {
            elem.parentNode.appendChild(newElem);
        }
    },
    //handle cross-browser adding events
    addEvent: function(obj, evt, fn) {
        if (document.addEventListener) {
            Homes.DOM.addEvent = function(obj, evt, fn) {
                obj.addEventListener(evt, fn, false);
            };
        }
        else if (document.attachEvent) {
            Homes.DOM.addEvent = function(obj, evt, fn) {
                obj["e" + evt + fn] = fn;
                obj[evt + fn] = function() { obj["e" + evt + fn](window.event); };
                obj.attachEvent("on" + evt, obj[evt + fn]);
            };
        }
        else {
            return false;
        }
        Homes.DOM.addEvent(obj, evt, fn);
    },
    stopIEContentFlash: function() {
        if (document.all) { document.write("<style>.lightBox {visibility:hidden;}</style>"); } // stop foc in IE
    },
    initiated: false,
    init: function() {
        //prevent being run several times
        if (Homes.DOM.initiated) { return; }
        Homes.DOM.initiated = true;
        document.body.className += " hasJS";
        Homes.pngHandling();
        Homes.clearTextArea();
        Homes.maxLengthTextArea();
        Homes.toggleVisibility();
        Homes.checkAllBoxesOnClick();
        Homes.confirmDelete();
        /*@cc_on@*/
        /*@if (@_jscript_version <= 5.6)
        Homes.InputHovers.init();
        /*@end@*/
        Homes.activateSubmit();
        Homes.getMyAddress();
        Homes.Print.setLinks();
        Homes.Popup.setLinks();
        Homes.Lightbox.init();
        Homes.developmentSearch();
        Homes.townSearch();
        Homes.schoolSearch();
        Homes.sifr();
        Homes.toggleSchoolInfo($(".tabs-nav .tabs-selected").attr("id"));

        //Create tabs - throughout site
        if ($("div#searchcontainer").length > 0) {
            $('div#searchcontainer').tabs();


            var regexsbs = new RegExp('sbs=true','i');
            var url = window.location.search;
            var match = regexsbs.exec(url)
            if (match != null) {
                $("#searchcontainer ul.tabs-nav li").removeClass("tabs-selected");
                $("#item-nearbyschool").addClass("tabs-selected");
                $("#searchcontainer .tabs-container").addClass("tabs-hide");
                $("#search-by-nearbyschool").removeClass("tabs-hide");
            } 
            /*var url = window.location.search;
            var firstSplit = url.split("sbs=")[1];
            if (firstSplit != null) {
            var sbs = firstSplit.split("&")[0];
            if (sbs == "true") {
            $('div#searchcontainer').triggerTab(3);
            $("#searchcontainer ul.tabs-nav li").removeClass("tabs-selected");
            $("#item-nearbyschool").addClass("tabs-selected");
            $("#searchcontainer .tabs-container").addClass("tabs-hide");
            $("#search-by-nearbyschool").removeClass("tabs-hide");
            }
            }*/
        }
        if ($("#container-1").length > 0) {
            $('#container-1').tabs();
        }
        if (('#devResultsList').length > 0) {
            $('#devResultsList').tabs();
        }
        // setup click listener to tabbing menu to remove any suggested entries
        if ($("ul.tabs-nav li a").length > 0) {
            $("ul.tabs-nav li a").click(function() {
                Homes.toggleSchoolInfo($(this).parent().attr("id"))
                $("ul.ajaxLinkList").remove();
            });
        }


        //Homes.DOM.addEvent(inputs[i], "click", isActive);		
    },
    /*doesn't work
    addDomReady : function(func) {
    if(Homes.DOM.initiated === true){func();return;}//init has already run
    var oldInit = Homes.DOM.init;
    if (typeof Homes.DOM.init != 'function') {
    Homes.DOM.init = func;	
    } else {
    Homes.DOM.init = function() {
    oldInit();
    func();
    }
    }
    },*/
    setUpDOMReady: function() {
        if (!/Opera/i.test(navigator.userAgent)) {

            if (document.addEventListener) { document.addEventListener("DOMContentLoaded", Homes.DOM.init, null); }
        } else {
            G_wk = setInterval(function() { if (document.getElementsByTagName("form")[0]) { clearInterval(G_wk); delete G_wk; Homes.DOM.init(); } }, 1000);

        }
        if (/WebKit/i.test(navigator.userAgent)) { G_wk = setInterval(function() { if (/loaded|complete/.test(document.readyState)) { clearInterval(G_wk); delete G_wk; Homes.DOM.init(); return; } }, 50); }
        /* DO NOT REMOVE THIS SECTION - IE CONDITIONAL COMPILATION */
        /*@cc_on@*/
        /*@if (@_win32)
        document.write("<script id=el_ie defer src=/assets/js/blank.js><\/script>"); var script = document.getElementById("el_ie"); script.onreadystatechange = function() {
            if (this.readyState == "complete") { Homes.DOM.init(); return; }
        }
        /*@end@*/
        /* IE CONDITIONAL COMPILATION ENDS */
        //failsafe
        window.onload = Homes.DOM.init;
        /* - */
    }
};
/*End Generic DOM functions*/
// -------------------------------- 


/*IE5.0 ARRAY PROTOTYPE PUSH*/
if(typeof Array.prototype.push=="undefined"){
	Array.prototype.push=function(item){
		return this[this.length] = item;
	};
}

//convert a string so that the start of each word has a capital letter and the rest is lower case, so all words are displayed as proper nouns
//regular expression extracts each bit of the string that has a word boundary at the beginning and end and runs the anonymous function on it
String.prototype.toProperCase = function(){
	var returnedString = this.replace(/\b.+?\b/g,function(word){
		return word.substring(0,1).toUpperCase() + word.substring(1).toLowerCase();
	});
	return returnedString;
};
//trim spaces from the end of a string
String.prototype.trim = function(){
	return this.replace(/^\s+|\s+$/g, "");
};

// extend Number object with methods for converting degrees
Number.prototype.toDeg = function() {  // convert radians to degrees (signed)
  return this * 180 / Math.PI;
}

//validateDate : function(source, clientside_arguments)
//{
////  if (clientside_arguments.Value % 2 == 0 )
////  {
////     clientside_arguments.IsValid=true;
////  }
////  else {clientside_arguments.IsValid=false};

//  clientside_arguments.IsValid = false;
//}

/*ON DOM READY FUNCTIONS*/
Homes.DOM.stopIEContentFlash();
Homes.DOM.setUpDOMReady();
/*END ON DOM READY FUNCTIONS*/
/*ON LOAD FUNCTIONS*/
Homes.addLoadEvent(Homes.GoogleMaps.init);
/*
Homes.addLoadEvent(function() {
	 var selectedTab = $('#searchcontainer').activeTab();
});
*/
//Homes.addLoadEvent(Site.siteInputHovers);
/*UNLOAD FUNCTIONS*/
if(typeof GUnload == "function"){Homes.addUnloadEvent(GUnload);}//unload googlemaps