﻿/*
FlashReplace is developed by Robert Nyman, http://www.robertnyman.com. License and downloads: http://code.google.com/p/flashreplace/
*/
// ---
var FlashReplace = {
    elmToReplace: null,
    flashIsInstalled: null,
    defaultFlashVersion: 7,
    replace: function (elmToReplace, src, id, width, height, version, params) {
        this.elmToReplace = document.getElementById(elmToReplace);
        this.flashIsInstalled = this.checkForFlash(version || this.defaultFlashVersion);
        if (this.elmToReplace && this.flashIsInstalled) {
            var obj = '<object' + ((window.ActiveXObject) ? ' id="' + id + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" data="' + src + '"' : '');
            obj += ' width="' + width + '"';
            obj += ' height="' + height + '"';
            obj += '>';
            var param = '<param';
            param += ' name="movie"';
            param += ' value="' + src + '"';
            param += '>';
            param += '';
            var extraParams = '';
            var extraAttributes = '';
            for (var i in params) {
                extraParams += '<param name="' + i + '" value="' + params[i] + '">';
                extraAttributes += ' ' + i + '="' + params[i] + '"';
            }
            var embed = '<embed id="' + id + '" src="' + src + '" type="application/x-shockwave-flash" width="' + width + '" height="' + height + '"';
            var embedEnd = extraAttributes + '></embed>';
            var objEnd = '</object>';
            this.elmToReplace.innerHTML = obj + param + extraParams + embed + embedEnd + objEnd;
        }
    },

    checkForFlash: function (version) {
        this.flashIsInstalled = false;
        var flash;
        if (window.ActiveXObject) {
            try {
                flash = new ActiveXObject(("ShockwaveFlash.ShockwaveFlash." + version));
                this.flashIsInstalled = true;
            }
            catch (e) {
                // Throws an error if the version isn't available			
            }
        }
        else if (navigator.plugins && navigator.mimeTypes.length > 0) {
            flash = navigator.plugins["Shockwave Flash"];
            if (flash) {
                var flashVersion = navigator.plugins["Shockwave Flash"].description.replace(/.*\s(\d+\.\d+).*/, "$1");
                if (flashVersion >= version) {
                    this.flashIsInstalled = true;
                }
            }
        }
        return this.flashIsInstalled;
    }
};

var Helpers = {
    _NewId: 1,
    /// Script Name: Javascript Cookie Script
    /// Author: Public Domain, with some modifications
    /// Script Source URI: http://techpatterns.com/downloads/javascript_cookies.php
    /// Version 1.1.1
    /// Last Update: 4 October 2007
    ///
    /// <summary>
    /// Method to set a cookie on the client site
    /// only the first 2 parameters are required, the cookie name, the cookie
    /// value. Cookie time is in milliseconds, so the below expires will make the 
    /// number you pass in the Set_Cookie function call the number of days the cookie
    /// lasts, if you want it to be hours or minutes, just get rid of 24 and 60.
    ///
    /// Generally you don't need to worry about domain, path or secure for most applications
    /// so unless you need that, leave those parameters blank in the function call.
    ///
    /// </summary>
    SetCookie: function(name, value, expires, path, domain, secure) {
        // set time, it's in milliseconds
        var today = new Date();
        today.setTime(today.getTime());
        // if the expires variable is set, make the correct expires time, the
        // current script below will set it for x number of days, to make it
        // for hours, delete * 24, for minutes, delete * 60 * 24
        if (expires) {
            expires = expires * 1000 * 60 * 60 * 24;
        }
        //alert( 'today ' + today.toGMTString() );// this is for testing purpose only
        var expires_date = new Date(today.getTime() + (expires));
        //alert('expires ' + expires_date.toGMTString());// this is for testing purposes only

        document.cookie = name + "=" + escape(value) + ((expires) ? ";expires=" + expires_date.toGMTString() : "") + //expires.toGMTString()
        ((path) ? ";path=" + path : "") + ((domain) ? ";domain=" + domain : "") + ((secure) ? ";secure" : "");
    },
    /// <summary>
    /// Method to get a cookie set on the client site
    /// </summary>
    GetCookie: function(check_name) {
        // first we'll split this cookie up into name/value pairs
        // note: document.cookie only returns name=value, not the other components
        var a_all_cookies = document.cookie.split(';');
        var a_temp_cookie = '';
        var cookie_name = '';
        var cookie_value = '';
        var b_cookie_found = false; // set boolean t/f default f

        for (i = 0; i < a_all_cookies.length; i++) {
            // now we'll split apart each name=value pair
            a_temp_cookie = a_all_cookies[i].split('=');

            // and trim left/right whitespace while we're at it
            cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, '');

            // if the extracted name matches passed check_name
            if (cookie_name == check_name) {
                b_cookie_found = true;
                // we need to handle case where cookie has no value but exists (no = sign, that is):
                if (a_temp_cookie.length > 1) {
                    cookie_value = unescape(a_temp_cookie[1].replace(/^\s+|\s+$/g, ''));
                }
                // note that in cases where cookie is initialized but no value, null is returned
                return cookie_value;
                break;
            }
            a_temp_cookie = null;
            cookie_name = '';
        }
        if (!b_cookie_found) {
            return null;
        }
    },
    /// <summary>
    /// Method to delete a cookie on client side
    /// </summary>
    DeleteCookie: function(name, path, domain) {
        if (this.GetCookie(name)) document.cookie = name + "=" + ((path) ? ";path=" + path : "") + ((domain) ? ";domain=" + domain : "") + ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
    },
    /// <summary>
    /// Method to determine if a field is null or empty
    /// </summary>
    IsNullOrEmpty: function(value) {
        if ((value == null) || (value.length == 0)) {
            return true;
        }
        else {
            return false;
        }
    },
    /// <summary>
    /// Method to open a browser to specified url
    /// </summary>
    OpenBrowser: function(Url) {
        var Width = 800;
        var Height = 600;
        var left = (screen.width / 2) - (Width / 2);
        var top = (screen.height / 2) - (Height / 2);
        var newWin = window.open(Url, "Top20Realty", "width=" + Width + ", height=" + Height + ", top=" + top + ", left=" + left + ", location=0, menubar=0, scrollbars=1, resizable=1, status=0, titlebar=0, toolbar=0");
        newWin.focus();

        return false;
    },
    /// <summary>
    /// Method to open a toolwindow to the specified url
    /// </summary>
    OpenToolWindow: function(Id, Url, Width, Height) {
        var left = (screen.width / 2) - (Width / 2);
        var top = (screen.height / 2) - (Height / 2);
        var newWin = window.open(Url, Id, "width=" + Width + ", height=" + Height + ", top=" + top + ", left=" + left + ", location=0, menubar=0, scrollbars=0, resizable=0, status=0, titlebar=0, toolbar=0");
        newWin.focus();
        
        return false;
    },
    /// <summary>
    /// Method to clone an HTML object (like a Div). Appends a number to an id
    /// </summary>    
    /// <param name="id">Element id to search for</param>
    Clone: function(id) {
        var clonedObj = document.getElementById(id).cloneNode(true);
        clonedObj.id += this._NewId;
        this.updateChildren(clonedObj.childNodes);
        //    document.body.appendChild(clonedObj);
        return clonedObj;
    },
    updateChildren: function(cN) {
        for (j in cN) {
            try {
                if (cN[j].id.length > 0) {
                    cN[j].id += this._NewId;
                    this.updateChildren(cN[j].childNodes);
                }
            } catch (e) {
                //continue   
            }
        }
    },
    /// <summary>
    /// Method to add commas (nice format) a number
    /// </summary>
    /// <param name="num">Number to format</param>
    AddCommas: function(num) {
        num += '';
        var x = num.split('.');
        var x1 = x[0];
        var x2 = x.length > 1 ? '.' + x[1] : '';
        var rgx = /(\d+)(\d{3})/;
        while (rgx.test(x1)) {
            x1 = x1.replace(rgx, '$1' + ',' + '$2');
        }
        return x1 + x2;
    },
    Test: function(obj, msg) {
        alert(msg);
        return false;
    }
};

var WaitingPage = {
    _WaitState_Timeout: -1,
    _WaitState_NotReady: 0,
    _WaitState_Ready: 1,
    _WaitingTime: 0,
    /// <summary>
    /// Method to keep checking to see if the listings page is ready for viewing
    /// </summary>
    OnPageLoad: function () {
        _WaitingTime = 0;
        this.HookCheckIsReady();
    },
    /// <summary>
    /// Method to setup the hook to check after x secs if data is ready
    /// </summary>
    HookCheckIsReady: function () {
        setTimeout("WaitingPage.CheckIsReady();", 3000);
    },
    /// <summary>
    /// Method to determine if the listings page is ready for viewing. Else keep showing wait
    /// </summary>
    CheckIsReady: function () {
        this._WaitingTime += 3;
        Core.CallPageMethod('IsListingsReady', this.OnSucceeded, this.OnFailed, "WaitingTime", this._WaitingTime);
    },
    /// <summary>
    // gets the ajaxResult. Returns ajaxResult.d is if it is not null, else ajaxResult.
    // System.Web.Extensions v3.5 web services will result in ajaxResult.d while v1.0 will be ajaxResult.
    /// </summary>
    GetResult: function (ajaxResult) {
        return ajaxResult.d == null ? ajaxResult : ajaxResult.d;
    },
    /// <summary>
    /// Method called on ajax success
    /// </summary>
    OnSucceeded: function (result, userContext, methodName) {
        if (WaitingPage.GetResult(result) == WaitingPage._WaitState_NotReady) {
            WaitingPage.HookCheckIsReady();
        }
        else if (WaitingPage.GetResult(result) == WaitingPage._WaitState_Timeout) {
            WaitingPage.SetState(WaitingPage._WaitState_Timeout);
            top.location.replace($('#form1')[0].action);   // this allows us to not put waiting page in the history (for back button)
        }
        else {
            WaitingPage.SetState(WaitingPage._WaitState_Ready);
            top.location.replace($('#form1')[0].action);
        }
    },
    /// <summary>
    /// Method called on ajax failure
    /// </summary>
    OnFailed: function (error, userContext, methodName) {
        // try again
        top.location.href = window.location.href;
    },
    /// <summary>
    /// Method called to set state to fatal 
    /// </summary>
    SetState: function (State) {
        postback = $('#form1')[0].action;
        if (postback.indexOf("&h") > -1) {
            pos = postback.indexOf("&h=");
            ch = postback.charAt(pos + 3);
            $('#form1')[0].action = postback.replace("&h=" + ch, "&h=" + State);
        }
        else {
            $('#form1')[0].action += '&h=' + State;
        }
    }
};

var Core = {

    _OnLoadFired: false,
    /// <summary>
    /// Method to call a ASP.NET PageMethod
    /// </summary>    
    /// <param name="node">element node to _Toggle from visible to non-visible</param>
    CallPageMethod: function (methodName, onSuccess, onFail) {
        var args = '';
        var l = arguments.length;
        if (l > 3) {
            for (var i = 3; i < l - 1; i += 2) {
                if (args.length != 0) args += ',';
                args += '"' + arguments[i] + '":"' + arguments[i + 1] + '"';
            }
        }
        var loc = window.location.href;
        loc = "PageMethods.aspx";
        $.ajax({ type: "POST", url: loc + "/" + methodName, data: "{" + args + "}", contentType: "application/json; charset=utf-8", dataType: "json", success: onSuccess, fail: onFail });
    },
    /// <summary>
    /// Method to call the ajax function to expand or collapse the panel via animation extender
    /// </summary>    
    /// <param name="node">element node to _Toggle from visible to non-visible</param>
    AnimExpandCollapseArea: function (target, time, startValue, endValue) {
        if (startValue > endValue) {
            $("#" + target).animate({ "height": "-=" + startValue + "px" }, time);
        }
        else {
            $("#" + target).animate({ "height": "+=" + endValue + "px" }, time);
        }
    },
    /// <summary>
    /// Method to initialize state when the Main realty page loads
    /// </summary>
    OnMainPageLoad: function () {
        Search.ToggleSearchArea();
        // Comment: we are not using the Goggle ad banner now. put it back once we get the account
        //        var bannerObj = $get('AdBannerTopID');
        //        bannerObj.style.display = 'none';
        eAgent.SetOptions();
    },
    /// <summary>
    /// Method post back to the server (user wants to Show All Listings)
    /// </summary>
    ShowListings: function (Link) {
        // we're ready to navigate to the main page. Build the SEO friendly search link (show main listings)
        Link.href = Search.BuildSearchLink("all", 0);
        return true;
    },
    /// <summary>
    /// Method post back to the server (user wants to Show Foreclosures)
    /// </summary>
    ShowForeclosures: function (Link) {
        // we're ready to navigate to the main page. Build the SEO friendly search link (show main listings)
        Link.href = Search.BuildSearchLink("foreclosures", 0);
        return true;
    },
    //
    /// <summary>
    /// Method to initialize state when the Listing page loads
    /// </summary>
    OnListingsPageLoad: function () {
        eAgent.SetOptions();
    },
    //
    /// <summary>
    /// Method to initialize state when the Error page loads
    /// </summary>
    OnErrorPageLoad: function () {
        Search.ToggleSearchArea();
        eAgent.SetOptions();
    }
};

/// <summary>
/// Class that encapsulates the eAgent functionality, to display and edit the eAgent preferences
/// </summary>
var eAgent = {
    _ValidationSucceeded: false,
    _Initialized: 0,
    _Idx: 0,
    _TotalOptions: 5,
    _Reset_ButtonEnabled: true,
    _ResetLink: null,
    _OptionDesc: null,
    _DescSEO: null,
    _PriorityNodes: null,
    _IconNodes: null,
    _IconStyle: null,
    _LinkNodes: null,
    _HelperText: null,

    /// <summary>
    /// Method to initialize the class variables
    /// </summary>
    Initialize: function () {
        this._Initialized = 1;
        this._OptionDesc = new Array();
        this._DescSEO = new Array();
        this._PriorityNodes = new Array();
        this._IconNodes = new Array();
        this._IconStyle = new Array();
        this._LinkNodes = new Array();
        this._HelperText = new Array();
        // associate the desc by the button, so when user clicks on the button we know what the description should be
        this._OptionDesc[0] = 'Best Value (Price per Square Foot)';
        this._OptionDesc[1] = 'Quality of Schools';
        this._OptionDesc[2] = 'Low Crime';
        this._OptionDesc[3] = 'High Income Neighbourhood';
        this._DescSEO[0] = 'BestValue';
        this._DescSEO[1] = 'School';
        this._DescSEO[2] = 'Crime';
        this._DescSEO[3] = 'Income';
        // save a handle to the actual description divs, so we can change them programmatically when user selects specific options
        this._PriorityNodes[0] = $('#eAgentPriority_1');
        this._PriorityNodes[1] = $('#eAgentPriority_2');
        this._PriorityNodes[2] = $('#eAgentPriority_3');
        this._PriorityNodes[3] = $('#eAgentPriority_4');
        // save a handle to the actual icon divs, so we can change them programmatically when user selects specific options
        this._IconNodes[0] = $('#eAgentIcon_Priority1');
        this._IconNodes[1] = $('#eAgentIcon_Priority2');
        this._IconNodes[2] = $('#eAgentIcon_Priority3');
        this._IconNodes[3] = $('#eAgentIcon_Priority4');
        // save a handle to the actual icon styles, so we can change them programmatically when user selects specific options
        this._IconStyle[0] = 'eAgentIconStyle_BestValue';
        this._IconStyle[1] = 'eAgentIconStyle_QualityOfSchools';
        this._IconStyle[2] = 'eAgentIconStyle_CrimeUsAvg';
        this._IconStyle[3] = 'eAgentIconStyle_MedianIncome';
        // get a handle to the button options
        this._LinkNodes[0] = $('#eAgentControl_BestValue');
        this._LinkNodes[1] = $('#eAgentControl_QualityOfSchools');
        this._LinkNodes[2] = $('#eAgentControl_CrimeUsAvg');
        this._LinkNodes[3] = $('#eAgentControl_MedianIncome');
        this._ResetLink = $('#eAgentControl_eAgentReset');
        // provide the idiot user with helper text
        this._HelperText[0] = 'Select in order of importance (AT LEAST ONE)';
        this._HelperText[1] = 'Select SECOND preference (or "Show My Top 20" )';
        this._HelperText[2] = 'Select THIRD preference (or "Show My Top 20")';
        this._HelperText[3] = 'Select FOURTH preference (or "Show My Top 20")';
        this._HelperText[4] = 'Click "Show My Top 20" or RESET';
    },

    /// <summary>
    /// Method to validate the current eAgent settings. If we already have an eAgent, then allow the user to modify (if need)
    /// else user *must* enter eAgent settings
    /// </summary>
    Validate: function (DisplayIFilter) {
        // if there is an iFilter setting then allow to pass
        if (this._ValidationSucceeded) return true;

        // user needs to set up eAgent settings
        if (DisplayIFilter) {
            Search.OpeneAgent();

            // let's validate if we already have an eAgent setting through hidden field
            if (!Helpers.IsNullOrEmpty($('#eAgentControl_iFilterHiddenField').val())) {
                // inform the user that they can update their eAgent settings if they like
                $('#eAgenteComplete').text('The above preferences will be used. Consider updating them as needed.');
                $('#eAgenteComplete').css('display', 'block');
                this._ValidationSucceeded = true;  // we really do have a completed iFilter settings
            }
            return false;
        }
        else {
            // we want to bypass showing the iFilter dialog (presumably because user is clicking through the grid)
            if (!Helpers.IsNullOrEmpty($('#eAgentControl_iFilterHiddenField').val())) {
                return true; // allow user to generate listings and cause a postback, since we have iFilter settings
            }
            else
                return false;
        }
    },

    /// <summary>
    /// Method to get the index in our priority description list, for the button the user clicked
    /// </summary>
    /// <param name="myNode">element button to use to get index of</param>
    geteAgentIdx: function (myNode) {
        var i = 0;
        for (i = 0; i < 4; i++) {
            if (myNode.attr('id') == this._LinkNodes[i].attr('id')) return i;
        }
        return -1;
    },

    /// <summary>
    /// Method to set the button option (to a priority number), update description based on button option pressed
    /// </summary>
    /// <param name="myNode">element button to set preference</param>
    seteAgentPref: function (thisNode) {
        // it's passed as a ref, so get the jquery ref
        var myNode = $('#' + thisNode.id);

        // initialize handles (since DOM is not _Initialized at load, we need to do it here)
        if (!this._Initialized) this.Initialize()

        // if we are done with options, don't let user go on
        if (this._Idx >= this._TotalOptions) return false;
        // get name of button (use it as a key into hash to get the value or description there)  
        if (myNode.text() != '?') return false;

        // get index of what the user clicked
        var optIdx = this.geteAgentIdx(myNode);
        if (optIdx < 0) return false;

        // finally update the UI with the actual iFilter (0-bestvalue, 1-school, 2-crime, 3-income
        eAgent.SeteAgentPrefDirect(optIdx);

        // so we don't do a postback
        return false;
    },

    /// <summary>
    /// Method to set the preference (i.e. update the eAgent with the users preference)
    /// </summary>
    /// <param name="optidx">the actual index to set</param>
    SeteAgentPrefDirect: function (optIdx) {
        // reference the button we're updating        
        var linkNode = this._LinkNodes[optIdx];

        // update our description or what the user has just selected (adding in a priority number)
        this.priorityDescNode = this._PriorityNodes[this._Idx];
        this.priorityDescNode.text((this._Idx + 1) + '. ' + this._OptionDesc[optIdx]);
        this.priorityDescNode.css('display', 'block');

        // update with the correct icon as well
        this.priorityIconNode = this._IconNodes[this._Idx];
        this.priorityIconNode.attr('class', this._IconStyle[optIdx]);
        this.priorityIconNode.css('display', 'block');

        // (since it's 0 based add 1 to it) 
        this._Idx++;

        // give some helper text for this idiot user
        $('#eAgenteAgentSelect').text(this._HelperText[this._Idx]);

        // update button to now give the priority selected (update parent of link, which is a div)
        linkNode.text(this._Idx);
        linkNode.parent().attr('class', 'eAgenteAgentOptionsLink');

        // is the reset disabled? if so then enable
        if (this._Reset_ButtonEnabled == false) {
            this._ResetLink.parent().attr('class', 'eAgentReset');
            this._Reset_ButtonEnabled = true;
        }

        // finally save the setting (for uploading to server)
        if (Helpers.IsNullOrEmpty($('#eAgentControl_iFilterHiddenField').val()))
            $('#eAgentControl_iFilterHiddenField').val(optIdx);
        else
            $('#eAgentControl_iFilterHiddenField').val($('#eAgentControl_iFilterHiddenField').val() + ':' + optIdx);

        // allow user to proceed if needed
        this._ValidationSucceeded = true;
    },

    /// <summary>
    /// Method to reset the eAgent back to the original state
    /// </summary>
    ResetOptions: function () {

        // initialize us
        if (!this._Initialized) {
            this.Initialize();
        }
        else {

            // reset is disabled, exit early
            if (this._Reset_ButtonEnabled == false)
                return false;
        }

        // reset selected buttons start back to 0
        this._Idx = 0;
        // hide all descriptions and icons
        for (var i = 0; i < 4; i++) {
            this._PriorityNodes[i].css('display', 'none');
            this._IconNodes[i].css('display', 'none');

            // reset all buttons back to blank (no number priority) and enable it 
            this._LinkNodes[i].text("?");
            this._LinkNodes[i].parent().attr('class', 'eAgenteAgentOptionsLinkDis');
        }
        // hide finished msg
        $('#eAgenteComplete').css('display', 'none');

        // we need to disable the reset button
        this._ResetLink.parent().attr('class', 'eAgentResetDis');
        this._Reset_ButtonEnabled = false;

        // hide the idiot text
        $('#eAgenteAgentSelect').text(this._HelperText[0]);

        // this is the setting we send to server so reset as well
        $('#eAgentControl_iFilterHiddenField').val('');

        // don't allow user to proceed if (they haven't passed validation)
        this._ValidationSucceeded = false;

        return false; // don't cause a postback
    },

    /// <summary>
    /// Method to set the eAgent options to what user had previously saved (else reset)
    /// </summary>    
    SetOptions: function () {
        // temp save any previous setting (if any)
        var iFilterHiddenFieldValue = $('#eAgentControl_iFilterHiddenField').val();

        // initialize
        eAgent.ResetOptions();

        // does the user have any previous eAgent settings? If so, set it
        if (!Helpers.IsNullOrEmpty(iFilterHiddenFieldValue)) {
            var pref_array = iFilterHiddenFieldValue.split(":");
            var idx = 0;
            while (idx < pref_array.length) {
                eAgent.SeteAgentPrefDirect(pref_array[idx]);
                idx++;
            }
        }

        // force the iFilter to open (by failing validation)
        this._ValidationSucceeded = false;
    },
    /// <summary>
    /// Method to return a SEO friendly iFilter settings
    /// </summary>    
    GetSEOSettings: function () {
        // temp save any previous setting (if any)

        var friendlySEO = "";
        // does the user have any previous eAgent settings? If so, set it
        if (!Helpers.IsNullOrEmpty($('#eAgentControl_iFilterHiddenField').val())) {
            var pref_array = $('#eAgentControl_iFilterHiddenField').val().split(":");
            var idx = 0;
            while (idx < pref_array.length) {
                if (Helpers.IsNullOrEmpty(friendlySEO)) {
                    friendlySEO = eAgent._DescSEO[pref_array[idx]];
                }
                else {
                    friendlySEO = friendlySEO + "-" + eAgent._DescSEO[pref_array[idx]];
                }
                idx++;
            }
        }

        return friendlySEO;
    }
};

/// <summary>
/// Class that encapsulates the Search functionality
/// </summary>
var Search = {
    _SearchAreaOpen: false,
    _eAgentAreaOpen: false,
    _BottomAreaOpen: false,
    _SearchAreaListOpen: false,

    /// <summary>
    /// Method post back to the server (user wants to generate listings). DisplayIFilter true/false (wheather to show IFilter by default)
    /// DisplayIFilter: true/false - if true then open the iFilter accordian view
    /// ShowTop20Link: object - the dom object for the show top 20 anchor link. Use this to modify the query parameter postback
    /// </summary>
    PerformValidation: function(DisplayIFilter, ShowTop20Link) {
        // if settings are fine (return true) and we can show listings, else user has to enter settings
        if (Search.Validate()) {
            if (eAgent.Validate(DisplayIFilter)) {
                // we're ready to navigate to the main page. Build the SEO friendly search link
                ShowTop20Link.href = Search.BuildSearchLink("all", 1);
                return true;
            }
        }
        return false; // there were validation problems, don't proceed
    },
    /// <summary>
    /// Method to build the SEO friendly search link to navigate to the listings page
    /// </summary>
    BuildSearchLink: function(ActiveGrid, DisplayWaitingPage) {
        // link should look something like this: href = ~/Listings/ca/92782/bestvalue-crime-school-income/sc-1-22-2000-1000-500000-3000000/all/1
        var state = $('#eAgentControl_TextBoxState').val();
        var zipBox = $('#eAgentControl_TextBoxZip');
        var cityBox = $('#eAgentControl_TextBoxCity');
        var zipcity = zipBox.val();
        if (Helpers.IsNullOrEmpty(zipBox.val()))
            zipcity = cityBox.val();

        var type = Search.GetSEOType('#eAgentControl_DropDownListType');
        var age = Search.GetSEOValue('#eAgentControl_DropDownListAge');
        var bedBath = Search.GetSEOValue('#eAgentControl_DropDownListBedBath');
        var sqFoot = Search.GetSEOValue('#eAgentControl_DropDownListSqFoot');
        var lotSize = Search.GetSEOValue('#eAgentControl_DropDownListLotSize');
        var priceFrom = Search.GetSEOValue('#eAgentControl_DropDownListPriceFrom');
        var priceTo = Search.GetSEOValue('#eAgentControl_DropDownListPriceTo');

        // finally build the link
        var link = "Realty-Listings.aspx?s=" + state + "&g=" + zipcity + "&f=" + eAgent.GetSEOSettings() + "&c=" + type + "-" + age + "-" + bedBath + "-" + sqFoot + "-" + lotSize + "-" + priceFrom + "-" + priceTo + "&v=" + ActiveGrid + "&p=1&o=sd&w=" + DisplayWaitingPage;
        return link;
    },
    /// <summary>
    /// Method to extract a SEO (type) value from the control to post back to server in SEO friendly manner
    /// </summary>
    GetSEOType: function(ElemId) {
        var val = '';
        var controlVal = $(ElemId);
        switch (controlVal.val()) {
            case 'Any': val = 'a'; break;
            case 'Single Family': val = 's'; break;
            case 'Condo/Twnhs': val = 'c'; break;
        }
        return val;
    },
    /// <summary>
    /// Method to extract a SEO value from the control to post back to server in SEO friendly manner
    /// </summary>
    GetSEOValue: function(ElemId) {
        var val = '';
        var controlVal = $(ElemId);
        if (controlVal.val() == 'Any')
            val = "a";
        else {

            val = controlVal.val().replace(/\$/g, '');
            val = val.replace(/,/g, '');
            val = val.replace(/ /g, '');
            val = val.replace(/\+/g, '');
            val = val.replace(/\//g, '');
            val = val.replace(/</g, '');
        }
        return val;
    },
    /// <summary>
    /// Method to validate that all search options are correctly set
    /// </summary>
    Validate: function () {
        if (Helpers.IsNullOrEmpty($('#eAgentControl_TextBoxZip').val()) && Helpers.IsNullOrEmpty($('#eAgentControl_TextBoxCity').val()))
            return false;
        return true;
    },

    /// <summary>
    /// Method to open or close the main login panel
    /// </summary>
    ToggleSearchBoxDisplay: function() {
        if (this._SearchAreaListOpen == false) {
            Core.AnimExpandCollapseArea('eAgentControl_SearchListControl_PanelSearchList', 200, 0, 165);
            this._SearchAreaListOpen = true;
        } else {
            Core.AnimExpandCollapseArea('eAgentControl_SearchListControl_PanelSearchList', 200, 165, 0);
            this._SearchAreaListOpen = false;
        }
        return false;
    },

    /// <summary>
    //// Method to close the search list box and open search area (if true)
    /// </summary>
    /// <param name="OpenSearchAreaFlag">what area to open/close</param>
    CloseSearchListAndOpenSearchArea: function(OpenSearchAreaFlag) {
        this.ToggleSearchBoxDisplay();
        if (this.OpenSearchAreaFlag == true) {
            // we want to open search area, so see if search is not already open (then open it)
            if (this._SearchAreaOpen == false) this.ToggleSearchArea();
        }
        return false;
    },

    /// <summary>
    //// Method to open and close the search area
    /// </summary>
    ToggleSearchArea: function() {
        if (this._SearchAreaOpen == false) {
            // open Top and Bottom search panel
            Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentTop', 200, 0, 130);
            if (this._BottomAreaOpen == false) {
                Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentBottom', 200, 0, 50);
                this._BottomAreaOpen = true;
            }
            this._SearchAreaOpen = true;
        } else {
            // open Top and Bottom search panel
            Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentTop', 200, 130, 0);
            Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentBottom', 200, 50, 0);
            if (this._eAgentAreaOpen == true) {
                Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentMidl', 400, 286, 0);
                this._eAgentAreaOpen = false;
            }
            this._SearchAreaOpen = false;
            this._BottomAreaOpen = false;
        }
        return false;
    },

    /// <summary>
    //// Method to open and close the search area
    /// </summary>
    ToggleModifySearchArea: function() {
        if (this._SearchAreaOpen == false) {
            // open Top and Bottom search panel
            Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentTop', 200, 0, 130);
            if (this._BottomAreaOpen == false) {
                Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentBottom', 200, 0, 50);
                this._BottomAreaOpen = true;
            }
            this._SearchAreaOpen = true;
        } else {
            // open Top and Bottom search panel
            Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentTop', 200, 130, 0);
            if (this._eAgentAreaOpen == false) {
                Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentBottom', 200, 50, 0);
                this._BottomAreaOpen = false;
            }
            this._SearchAreaOpen = false;
        }
        return false;
    },

    /// <summary>
    //// Method to open and close the filter area
    /// </summary>
    ToggleModifyFilterArea: function() {
        if (this._eAgentAreaOpen == false) {
            // open midle and Bottom search panel
            Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentMidl', 200, 0, 286);
            if (this._BottomAreaOpen == false) {
                Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentBottom', 200, 0, 50);
                this._BottomAreaOpen = true;
            }
            this._eAgentAreaOpen = true;
            eAgent.Validate(true);
        } else {
            // open midl and Bottom search panel
            Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentMidl', 200, 286, 0);
            if (this._SearchAreaOpen == false) {
                Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentBottom', 200, 50, 0);
                this._BottomAreaOpen = false;
            }
            this._eAgentAreaOpen = false;
        }
        return false;
    },

    /// <summary>
    //// Method to open and close the eAgent preferences
    /// </summary>
    ToggleeAgent: function() {
        if (this._eAgentAreaOpen == false) {
            Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentMidl', 400, 0, 286);
            this._eAgentAreaOpen = true;
            // let's also reset the eAgent 
            eAgent.SetOptions();
        } else {
            Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentMidl', 400, 286, 0);
            this._eAgentAreaOpen = false;
            if (this._SearchAreaOpen == false) {
                Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentBottom', 200, 50, 0);
                this._BottomAreaOpen = false;
            }
        }
        return false;
    },
    /// <summary>
    //// Method to open (do nothing if already open)
    /// </summary>
    OpeneAgent: function() {
        if (this._eAgentAreaOpen == false) {
            Core.AnimExpandCollapseArea('eAgentControl_PaneleAgentMidl', 400, 0, 286);
            this._eAgentAreaOpen = true;
            // let's also set the current eAgent options (else do a reset)
            eAgent.SetOptions();
        }
        return false;
    }
};