﻿/// <reference path="jquery-1.4.1-vsdoc.js" />
/// <reference path="adecco.core.js" />
/// <reference path="adecco.jobsearch.js" />
/// <reference path="adecco.jobsearch.JobResultsView.js" />


adecco.PagingManager = function() {
    /*this.DEFAULT_PAGE_SIZE = 10;
    this.numJobsPerPage = 2;
    this._currentPageNumber = 1;
    this.jobs = [];
    this._isInitialized = false;*/
};

//Bug ID :DE3059 Description: Sort BY Name is not working properly in Job Results

if (typeof String.prototype.trim !== 'function') {
    String.prototype.trim = function() {
        return this.replace(/^\s+|\s+$/g, '');
    }
} 


adecco.PagingManager.prototype = {

    DEFAULT_PAGE_SIZE: 10,
    numJobsPerPage: 2,
    _currentPageNumber: 1,
    jobs: [],
    _isInitialized: false,

    initialize: function(numberJobsPerPage, mappingJobs) {
        if (typeof (numberJobsPerPage) === 'string') {
            numberJobsPerPage = parseInt(numberJobsPerPage);

        }
        this.DEFAULT_PAGE_SIZE = 10;
        this.numJobsPerPage = 2;
        this._currentPageNumber = 1;
        this.numJobsPerPage = numberJobsPerPage || this.DEFAULT_PAGE_SIZE;
        this.jobs = mappingJobs;
        this._isInitialized = true;
    },

    getTotalPageNum: function() {
        var pages = 1;
        if (this._isInitialized) {
            if (this.numJobsPerPage === 0) {
                throw { message: 'Division by zero' };
            }

            pages = this.jobs.length / this.numJobsPerPage;
            pages = Math.floor(pages);
            if ((this.jobs.length % this.numJobsPerPage) >= 1) {
                pages++;
            }
        }
        return pages;
    },

    getPagingHtml: function() {
        var totalPages = this.getTotalPageNum();
        var currPage = this.getCurrentPageNumber();
        var totalDisplay = 5;

        // var lastPage = (currPage + 2 <= totalPages) ? currPage + 2 : totalPages;
        //var lastPage = ( 5 - currPage <= totalPages) ? currPage + 4 : lastPage;
        var firstPage = (currPage > 2) ? currPage - 2 : 1;
        var lastPage = (firstPage + 4 >= totalPages) ? totalPages : firstPage + 4;
        var result = '';
        if (currPage > 0) {
            result = "<table style='width:auto' cellspacing='5'><tr>";
            if (currPage != 1) { result += "<td style='text-align: left'><a href='javascript:adecco.jobsearch.mapManager.getPagingManager().prototype.previousPage();'>Prev</a>&nbsp;</td>"; } else { result += "<td>Prev&nbsp;</td>"; }
            for (firstPage; firstPage <= lastPage; firstPage++) {
                if (firstPage == currPage) {
                    result += "<td style='font-weight:bold;'><a href='javascript:adecco.jobsearch.mapManager.getPagingManager().prototype.displayPage(" + firstPage + ")'>" + firstPage + "</a>&nbsp;</td>";
                }
                else {
                    result += "<td><a href='javascript:adecco.jobsearch.mapManager.getPagingManager().prototype.displayPage(" + firstPage + ")'>" + firstPage + "</a>&nbsp;</td>";
                }
            }
            if (currPage != lastPage) { result += "<td style='text-align:right'>&nbsp;<a href='javascript:adecco.jobsearch.mapManager.getPagingManager().prototype.nextPage();'>Next</a></td>"; } else { result += "<td>&nbsp;Next</td>"; }
            result += "</tr></table>";
        }
        return result;

    },

    getCurrentPageNumber: function() {
        return this._currentPageNumber;
    },

    setCurrentPageNumber: function(value) {
        this._currentPageNumber = value;
    },

    getPagingContent: function(pageNumber) {
        var pageJobs = [];

        if (this._isInitialized) {
            var maxJobIndex = pageNumber * this.numJobsPerPage;
            var minJobIndex = maxJobIndex - this.numJobsPerPage;
            for (minJobIndex; minJobIndex < maxJobIndex; minJobIndex++) {
                //alert(minJobIndex + ", " + jobs[minJobIndex]);
                if (this.jobs[minJobIndex]) {
                    pageJobs.push(this.jobs[minJobIndex]);
                }
            }
        }
        return pageJobs;
    },

    displayPage: function(pageNumber) {
        this.setCurrentPageNumber(pageNumber);
        $(".MF_InfoBox_Cluster").html(adecco.jobsearch.mapManager.getContentHtml());
    },

    nextPage: function() {
        this.setCurrentPageNumber(this.getCurrentPageNumber() + 1);
        $(".MF_InfoBox_Cluster").html(adecco.jobsearch.mapManager.getContentHtml());
    },

    previousPage: function() {
        this.setCurrentPageNumber(this.getCurrentPageNumber() - 1);
        $(".MF_InfoBox_Cluster").html(adecco.jobsearch.mapManager.getContentHtml());
    }
};

// -- Define the Job Results View Controller --
adecco.jobsearch.JobResultsViewController = function(container, shareJoblUrl, clientId, payloadSize, pageSize, pageSizeIndex, sortByField, radius, applyJobUrl, UseApplyJobPageUrlFromWebPartProperty) {

    this._DOMElement = container;
    this._results = [];
    this._filteredResults = [];
    this._view = new adecco.jobsearch.JobResultsView(container);
    this._view.setDataSource(this);
    this._view.setDelegate(this);
    this._shareJobUrl = shareJoblUrl;
    this._applyJobUrl = applyJobUrl;
    this._UseApplyJobPageUrlFromWebPartProperty = UseApplyJobPageUrlFromWebPartProperty;
    this._pageSize = pageSize;
    this._pageSizeIndex = pageSizeIndex;
    this._sortByField = sortByField;
    this._radius = radius;
    this._rssQueryParams = [];
    this._clientId = clientId;
    this._payloadSize = payloadSize;

    this.refineSearchController = null;
    if (typeof (adecco.jobsearch.RefineSearchController) !== 'undefined') {
        this.refineSearchController = new adecco.jobsearch.RefineSearchController(this);
        this.refineSearchController.setJobResultsController(this);
    }

    // initialize rss search parameters
    {

        var rssElement = $('#searchresultswebpart_rssbtn');
        var oldParams = rssElement.attr('href');

        this._rssQueryParams = this.getParametersFromQuery(oldParams);
    }
};

adecco.jobsearch.JobResultsViewController.prototype.getParametersFromQuery = function(url) {
    var queryStringList = {};
    if (typeof (url) !== 'undefined') {
        url.match(/\?(.+)$/);
        var params = RegExp.$1;
        var params = params.split("&");

        for (var i = 0; i < params.length; i++) {
            var tmp = params[i].split("=");
            if (tmp[0] && tmp[1])
                queryStringList[tmp[0]] = unescape(tmp[1]);
        }
    }
    return queryStringList;
}

adecco.jobsearch.JobResultsViewController.prototype.getRadius = function() {
    return this._radius;
}

adecco.jobsearch.JobResultsViewController.prototype.getResults = function() {
    return this._results;
}
adecco.jobsearch.JobResultsViewController.prototype.setJobResults = function(results) {
    if (results != this._results) {
        // Copy the Results collection into the local array.
        this._results = results.Results;
      
        adecco.jobsearch.pagingAndSortingManager.initialize([], this._pageSize, this._pageSizeIndex, this._sortByField);
        //this.refineSearchController.filter();

        // Now that we've filtered the jobs we can display them.    
        this.setFilteredResults(results.Results, true);


        //this.notifyResultsChanged()
        log.info('New job results stored.');
    }
}

adecco.jobsearch.JobResultsViewController.prototype.continueJobResultsFromHandler = function(payloadIndex, params) {

    var jobSearchService = '/_layouts/AdeccoGroup/WebParts/JobSearch/services/JobSearch.ashx';
    var addparams = [];
    var pageSize = this._pageSize;
    var pageSizeIndex = this._pageSizeIndex;
    var sortByField = this._sortByField;
    var payloadSize = this._payloadSize

    // Add the client id to the parameters for the search parameters passed in
    addparams.push(params);
    addparams.push("&");
    addparams.push("clientId=");
    addparams.push(this._clientId);
    addparams.push("&pdx=");
    addparams.push(payloadIndex);
    addparams.push("&psz=");
    addparams.push(payloadSize);

    $.ajax({
        url: jobSearchService,
        data: addparams.join(''),
        dataType: "json",
        success: function(data) {

            // append results
            adecco.jobsearch.resultsController._results = adecco.jobsearch.resultsController._results.concat(data.Results);

            // Prepare the display of the paging and sorting manager and the job results
            adecco.jobsearch.resultsController.refineSearchController.filter();

            // Continue retrieving results if there are results remaining
            if (payloadIndex * payloadSize < data.TotalNumberOfResults) {
                adecco.jobsearch.resultsController.continueJobResultsFromHandler(payloadIndex + 1, params);
                //var str = (payloadIndex + 1).toString();
                //var str2 = (params).toString();
                //setTimeout('adecco.jobsearch.resultsController.continueJobResultsFromHandler('+str+', "'+str2+'")', 300);
            }

        },
        error: function(XMLHttpRequest) {

            // Hide proper containers
            $(".job-list").hide();
            $(".not-found").hide();
            $(".job-results-part").addClass("has-error");
            $(".loading-container").hide();
        }
    });

}


adecco.jobsearch.JobResultsViewController.prototype.loadJobResultsFromHandler = function(params) {

    var jobSearchService = '/_layouts/AdeccoGroup/WebParts/JobSearch/services/JobSearch.ashx';
    var results;
    var addparams = [];
    var pageSize = this._pageSize;
    var pageSizeIndex = this._pageSizeIndex;
    var sortByField = this._sortByField;
    var payloadSize = this._payloadSize

    // no need to display the search summary if we don't have results to display
    $("#SearchSummaryTable").hide();
    //Bug ID : #DE2351 Closed On : Aug 03,2011
    //Remarks : Hide all containers other than loading-image till the results appear
    $(".not-found").hide();
    $(".job-results-loading-container").show();
    $(".jobResults-holder").hide();
    $(".jobResultToolbarLeft").hide();
    $(".job-list").hide();
    $(".job-results-part").removeClass("has-error");

    // Add the client id to the parameters for the search parameters passed in
    addparams.push(params);
    addparams.push("&");
    addparams.push("clientId=");
    addparams.push(this._clientId);

    // Using the payload size we can utilize the built-in paging abilities of the job search
    // handler to retrieve the result chunks we want
    addparams.push("&pdx=1&psz=");
    addparams.push(payloadSize);

    $.ajax({
        url: jobSearchService,
        data: addparams.join(''),
        dataType: "json",
        success: function(data) {

        if (data.Results != this._results) {
            //Bug ID : #DE2552 Closed On : Aug 02,2011
            //Remarks : Added code to hide other containers if 0 results and show 'No results found text'
            //Bug ID : DE3410 Closed On: 4 Nov : If Code Commented.
//                if (data.TotalNumberOfResults < 1) {
//                    $(".not-found").show();
//                    $(".job-results-loading-container").hide();
//                    $(".jobResults-holder").hide();
//                    $(".jobResultToolbarLeft").hide();
//                    $(".job-list").hide();
//                    $(".job-results-part").removeClass("has-error");
//                    $("#SearchSummaryTable").hide();
//                }
//                else {

                    // Show proper containers
                    $(".loading-container").hide();
                    $(".jobResults-holder").show();
                    $(".jobResultToolbarLeft").show();
                    $(".job-list").show();
                    $(".not-found").hide();
                    $(".job-results-part").removeClass("has-error");
                    $("#SearchSummaryTable").show();

                    // Copy the Results collection into the local array.
                    this._results = data.Results;

                    // Prepare the display of the paging and sorting manager and the job results
                    adecco.jobsearch.pagingAndSortingManager.initialize([], pageSize, pageSizeIndex, sortByField);
                    adecco.jobsearch.resultsController._results = data.Results;
                    adecco.jobsearch.resultsController.refineSearchController.filter();

                    //Bug ID : #DE2178 Closed On : June 06,2011 Remarks : Added code to hide pageSize;
                    if (data.TotalNumberOfResults < parseInt($("#aPageSize2").text()) + 1) {
                        $("#aPageSize3").css('display', 'none');
                        $("#spanPageSize2").css('display', 'none');
                    }
                    if (data.TotalNumberOfResults < parseInt($("#aPageSize1").text()) + 1) {
                        var num = parseInt($("#aPageSize1").text()) + 1;

                        $("#aPageSize2").css('display', 'none');
                        $("#spanPageSize1").css('display', 'none');
                    }
                    if (data.TotalNumberOfResults < parseInt($("#aPageSize1").text())) {
                        $("#divResultsPerPage").css('display', 'none');
                    }

                    // If all the results have not yet been received, make additional calls to retrieve the rest
                    if (payloadSize < data.TotalNumberOfResults) {
                        adecco.jobsearch.resultsController.continueJobResultsFromHandler(2, params);
                    }
               // }

            }
        },
        error: function(XMLHttpRequest) {

            // Hide proper containers
            $(".job-list").hide();
            $(".not-found").hide();
            $(".job-results-part").addClass("has-error");
            $(".job-results-loading-container").hide();            
        }
    });

}

adecco.jobsearch.JobResultsViewController.prototype.getFilteredResults = function() {
    return this._filteredResults;
}

adecco.jobsearch.JobResultsViewController.prototype.setFilteredResults = function(results, update) {
    var webPart = $('.job-results-part');

    log.debug('Setting filtered results (' + results.length + ').');
    this._filteredResults = results;

    // TODO: there's a bug if the array is empty. FIX IT!.

    // Update the Paging & Sorting Manager with the new result set.
    if (typeof (adecco.jobsearch.pagingAndSortingManager) !== 'undefined') {
        adecco.jobsearch.pagingAndSortingManager.updatePagingAndSorting(this._filteredResults);
    }

    // If there are no results, indicate it.

    if (results.length === 0) {
        if (!webPart.hasClass('has-error')) {
            webPart.addClass('no-results');
        }
    } else {
        webPart.removeClass('no-results');
    }

    return this;
}

// Data Source methods for the Job Results View
adecco.jobsearch.JobResultsViewController.prototype.getNumberOfRows = function() {
    return this._filteredResults.length;
}

adecco.jobsearch.JobResultsViewController.prototype.getRowDataAtIndex = function(index) {
    /// <summary>Gets the Job object for a given index.</index>
    return this._filteredResults[index];
}

adecco.jobsearch.JobResultsViewController.prototype.getExtendedProperty = function(job, name) {
    var i;

    if (job && job.ExtendedProperties) {
        for (i = 0; i < job.ExtendedProperties.length; i++) {
            if (job.ExtendedProperties[i].Id === name) {
                return job.ExtendedProperties[i];
            }
        }
    }

    return {};
}

adecco.jobsearch.JobResultsViewController.prototype.getShareJobUrl = function(job) {
    return this._shareJobUrl + '?job-id=' + job.Id;
}

adecco.jobsearch.JobResultsViewController.prototype.getApplyJobUrl = function(job) {
    if (typeof (this._UseApplyJobPageUrlFromWebPartProperty) != 'undefine') {
        if (this._UseApplyJobPageUrlFromWebPartProperty == 'True') {
            var tccode;
            tccode = $('#jobdetailstracingcode').val();
            if (tccode == "") {
                return this._applyJobUrl + '?job-id=' + job.Id;
            }
            else {
                return this._applyJobUrl + '?job-id=' + job.Id + '&tc=' + tccode;
            }
        }
        else {
            return job.JobApplyUri;
        }
    }
    else {
        return this._UseApplyJobPageUrlFromWebPartProperty;
    }
}

adecco.jobsearch.JobResultsViewController.prototype.getJobDetailsUrl = function(job) {
    return $('#jobdetailspageurl').val() + '?job-id=' + job.Id;
}

adecco.jobsearch.JobResultsViewController.prototype.getRssQueryParams = function() {
    return this._rssQueryParams;
}

// Delegate methods for the Job Results View
adecco.jobsearch.JobResultsViewController.prototype.didToggleShortList = function(sender, job) {
    /// <summary>Occurs when a job has been toggled for shortlisting</summary>
    ///<param name="sender">The element that triggered the event</param>
    
    var jobId, listManager = adecco.jobsearch.ShortListManager;

    if (sender) {
        $(sender).toggleClass('off');
    }

    if (job) {
        if (typeof (job) === 'string') {
            jobId = job;
        } else {
            // Assume job is the Job object.
            jobId = job.Id;
        }

        log.debug('Shortlist toggle of Job ID "' + jobId + '"');

        if (listManager.isShortListed(jobId)) {
            listManager.removeJob(jobId);
        } else {
            listManager.addJob(jobId);
        }
    }
}

adecco.jobsearch.JobResultsViewController.prototype.updateRssLinkWithFilters = function(filters) {
    var params = [""];
    // var jobSearchService = '/_layouts/AdeccoGroup/WebParts/JobSearch/services/JobResultsFeed.ashx';
    var rssLink = $('#searchresultswebpart_rssbtn');
    var oldParams = rssLink.attr('href');
    var CurrentParam = oldParams.split("?");
    var jobSearchService = CurrentParam[0];

    var qs = new Array();
    var rssQuery = jQuery.extend({}, this._rssQueryParams);

    params.push(jobSearchService);
    params.push("?");
    if (rssLink.length > 0) {

        // iterate through filters and update querystring parameters that will
        $.each(filters, function(intIndex, objValue) {

            if (objValue.range) {
                rssQuery[objValue.querystringParam + "Min"] = objValue.range[0];

                if (objValue.hasOwnProperty('includeUnknown')) {
                    //rssQuery[objValue.querystringparam + "Unknown"] = objValue.includeUnknown;
                }

                if (objValue.range[1] != Infinity) {
                    rssQuery[objValue.querystringParam] = objValue.range[1];
                }
            }
            else {
                rssQuery[objValue.querystringParam] = objValue.value;
            }
        });

        $.each(rssQuery, function(intIndex, objValue) {
            params.push(intIndex);
            params.push("=");
            params.push(objValue);
            params.push("&");
        });

        var fparam = params.join('');
        if (fparam.length > 0) {
            fparam = fparam.substring(0, fparam.length - 1);

            rssLink.attr('href', fparam);
        }
    }
}

adecco.jobsearch.JobResultsViewController.prototype.updateHistoryForFilters = function(filters) {
    // TODO: Set cookie to the value of the filters. Later, this can be replaced with URL modification.
    var i, aFilter,
    params = [],
    serializedFilters;


    for (i = 0; i < filters.length; i++) {
        aFilter = filters[i];

        if (aFilter.range) {
            // Filter is a slider.

            // Add lower bound value.
            params.push(aFilter.querystringparam + '-lo');
            params.push('=');
            params.push(aFilter.range[0]);

            params.push('&');

            // Add higher bound value.
            params.push(aFilter.querystringparam + '-hi');
            params.push('=');
            params.push(aFilter.range[1]);
        } else {
            // Filter is a slider
            params.push(aFilter.querystringparam);
            params.push('=');
            params.push(aFilter.value);
        }

        params.push('&');
    }

    // "Serialize" filters into a string.
    var serializedFilters = params.join('');

    // Store string in cookie.
    adecco.setCookie('lastJobSearch', serializedFilters, 90);
}

adecco.jobsearch.JobResultsViewController.prototype.filtersDidChange = function(sender, filters) {
    
    this.updateRssLinkWithFilters(filters);
    this.updateHistoryForFilters(filters);
}

// -------------------------- Paging and Sorting Manager Start --------------------------


// TO DO:
// - Change getExtendedPropertyIndex() to call only once instead of for each job

function PagingAndSortingManager() {
    /// <summary>
    /// Manages the Paging and Sorting for the View List section of Job Results.
    /// </summary>
    this.results = null;
    this.currentIndex = null;
    this.pageSize = null;
    this.pageSizeIndex = null; // Used to identify which link has been clicked for styling purposes
    this.pageIndex = null;
    this.currentPageSize = null;
    this.totalNumResults = null;
    this.pageIndexHtml = null;
    this.sortByField = null;
    this.reverseOrder = null;
    this.firstTime = null;

    this.initialize = function(results, pageSize, pageSizeIndex, sortByField) {
        /// <summary>
        /// Initializes the Paging and Sorting Manager.
        /// </summary>
        /// <param name="results">The array containting all job results</param>
        /// <param name="pageSize">The current page size</param>
        /// <param name="pageSizeIndex">The current page size index</param>
        /// <param name="sortByField">The default sort by field</param>

        this.firstTime = true;
        this.reverseOrder = false;
        this.currentIndex = 0;
        this.pageSize = pageSize;
        this.pageSizeIndex = pageSizeIndex;
        this.pageIndex = 0;
        this.sortByField = sortByField;
        this.totalNumResults = results.length;
        this.currentPageSize = this.totalNumResults > this.pageSize ? this.pageSize : this.totalNumResults;
        this.pageIndexHtml = null;
        this.results = results;
        this.refreshPageIndexing();

        // This is no longer necessary
        this.sort(this.sortByField, "false");
    }

    this.updatePagingAndSorting = function(results) {
        this.results = results;
        this.totalNumResults = results.length;
        this.refreshPageIndexing();
        this.sort(this.sortByField, "true");
    }

    this.updateCurrentPageSize = function() {
        /// <summary>
        /// Checks to see if the current page size should be changed if there are less items to display
        /// than the current page size. (i.e. if it is displaying the last page).
        /// </summary>

        if ((this.currentIndex + this.pageSize) > this.totalNumResults) {
            this.currentPageSize = this.totalNumResults - this.currentIndex;
        }
        else {
            this.currentPageSize = this.pageSize;
        }
    }

    this.showNext = function() {
        /// <summary>
        /// Shows next page of results
        /// </summary>

        if (typeof (this.pageSize) === "string") {
            this.pageSize = parseInt(this.pageSize);
        }
        
        if (typeof (this.currentIndex) === "string") {
            this.currentIndex = parseInt(this.currentIndex);
        }

        if ((this.currentIndex + this.pageSize) < this.totalNumResults) {
            this.changeToPage(this.pageIndex + 1);
        }
    }

    this.showPrev = function() {
        /// <summary>
        /// Shows previous page of results
        /// </summary>

        if (typeof (this.pageSize) === "string") {
            this.pageSize = parseInt(this.pageSize);
        }
        
        if (typeof (this.currentIndex) === "string") {
            this.currentIndex = parseInt(this.currentIndex);
        }

        if ((this.currentIndex - this.pageSize) >= 0) {
            this.changeToPage(this.pageIndex - 1);
        }
    }

    this.changePageSize = function(paras) {
        //pageSize, pageSizeIndex
        /// <summary>
        /// Changes the page size
        /// </summary>
        /// <param name="paras">page size#;pageSizeIndex</param>

        var tempSplit = paras.split("#;");
        pageSize = tempSplit[0];
        pageSizeIndex = tempSplit[1];

        this.pageSizeIndex = pageSizeIndex;
        this.pageSize = pageSize;
        this.currentPageSize = this.totalNumResults > this.pageSize ? this.pageSize : this.totalNumResults;
        this.pageIndexHtml = null;
        this.refreshPageIndexing();
        this.pageIndex = 0;
        this.changeToPage(this.pageIndex);
    }

    this.refreshPageIndexing = function() {
        /// <summary>
        /// Refreshes the page indexing control at the bottom of the page showing the number of pages
        /// there are and the Next/Prev links.
        /// </summary>

        var numOfPages = Math.ceil(this.totalNumResults / this.pageSize);
        if (numOfPages === 1) {
            $("#divPagination").css('display', 'none');
            $("#divPaginationFooter").css('display', 'none');
        }
        else {
            this.buildPageIndexingHtml(numOfPages);
            $("#dropDownPageIndex").empty();
            $("#dropDownPageIndex").append(this.pageIndexHtml);

            $("#dropDownPageIndexFooter").empty();
            $("#dropDownPageIndexFooter").append(this.pageIndexHtml);

            $("#divPagination").css('display', '');
            $("#divPaginationFooter").css('display', '');
        }
    }

    this.buildPageIndexingHtml = function(numOfPages) {
        /// <summary>
        /// Builds the html for the page indexing control
        /// </summary>
        /// <param name="numOfPages">The number of pages to display.</param>

        var pageIndexHtmlBuilder = new Array();
        var pageBuffer = 10;
        var currPagesDisplayed = Math.floor(this.pageIndex / pageBuffer);
        var beginPages = (pageBuffer * currPagesDisplayed);
        for (var i = 0; i < numOfPages; i++) {
            pageIndexHtmlBuilder.push("<option value=\""+(i)+"\">"+(i + 1)+"</option>");
        }

        this.pageIndexHtml = pageIndexHtmlBuilder.join('');
    }

    this.changeToPage = function(page) {
        /// <summary>
        /// Changes to the page indicated.
        /// </summary>
        /// <param name="page">The page to change to.</param>
        var numOfPages = Math.ceil(this.totalNumResults / this.pageSize);

        $("#dropDownPageIndex").val(page);

        $("#dropDownPageIndexFooter").val(page);
        
        var intPageIndex = this.pageIndex;

        if (typeof (page) === "string") {
            this.pageIndex = parseInt(page);
        }
        else {
            this.pageIndex = page;
        }

        intPageIndex = this.pageIndex;
        
        if (intPageIndex === (numOfPages - 1))
        { $('.nextLink').hide(); }
        else
        { $('.nextLink').show(); }

        if (intPageIndex === 0)
        { $('.prevLink').hide(); }
        else
        { $('.prevLink').show(); }
        
        this.currentIndex = this.pageIndex * this.pageSize;
        
        if (typeof (this.currentIndex) === "string") {
            var currentIndex = parseInt(this.currentIndex);
        } else{
            var currentIndex = this.currentIndex;
        }
        if (typeof (this.pageSize) === "string") {
            var pageSize = parseInt(this.pageSize);
        } else{
            var pageSize = this.pageSize;
        }
        
        if(this.totalNumResults < (currentIndex + pageSize))
        {
            var endIndex = this.totalNumResults;
        } else {
            var endIndex =(currentIndex + pageSize);
        }

        document.getElementById('shownResultsIndex').innerHTML = (this.currentIndex + 1) + " - " + endIndex;
        document.getElementById('shownResultsIndexFooter').innerHTML = (this.currentIndex + 1) + " - " + endIndex;
        

        adecco.jobsearch.pagingAndSortingManager.updateCurrentPageSize();
        //		//adecco.jobsearch.resultsController.setFilteredResults( = this.results;
        adecco.jobsearch.resultsController._view.setNeedsDisplay();

        //this.refreshPageIndexing();
    }

    this.sort = function(paras) {
        /// <summary>
        /// Sorts the results based on the sortByField
        /// </summary>
        /// <param name="paras">sortByField#;update#;</param>

        // If user is clicking on the same sort field, reverse the order.

        var tempSplit = paras.split("#;");
        sortByField = tempSplit[0];
        update = tempSplit[1];
        reverse = tempSplit[2];

        if (update === undefined) {
            update = true;
        }

        if (reverse !== undefined) {
            if (reverse == "1") {
                this.reverseOrder = true;
            } else {
                this.reverseOrder = false;
            }
        }

        this.sortByField = sortByField;

        // Handle to the correct sort function based on sort field.
        var compSortFunc = this.getCompareFunction();

        // Returns the correct sort function based on field and whether order should be reveresed.
        var sortFunc = function(job1, job2) {
            var r = adecco.jobsearch.pagingAndSortingManager.reverseOrder ? compSortFunc(job2, job1) : compSortFunc(job1, job2);
            return r;
        }
        this.results.sort(sortFunc);
        this.changeToPage(0);
    }

    this.getCompareFunction = function() {
        /// <summary>
        /// Gets the corresponding compare function to sort the results based on sort field.
        /// </summary>
        /// <returns>The result of the corresponding compare function.</returns>

        switch (this.sortByField) {
            case "DatePosted":
                return this.compareDateValues;
            case "Salary":
                return this.compareSalaryValues;
            case "ContractType":
                return this.compareContractTypeValues;
            case "Name":
                return this.compareNameValues;
        }
    }

    this.compareDateValues = function(job1, job2) {
        /// <summary>
        /// Gets the date fields from two given jobs and converts them to proper date type for comparison.
        /// Both dates are then passed into the base compare function.
        /// Assuming Posting Date cannot be empty.
        /// </summary>
        /// <param name="job1">The first job to compare.</param>
        /// <param name="job2">The second job to compare.</param>
        /// <returns>The result of the base compare function.</returns>

        var index1 = adecco.jobsearch.pagingAndSortingManager.getExtendedPropertyIndex("FormattedPostingDate", job1);
        var index2 = adecco.jobsearch.pagingAndSortingManager.getExtendedPropertyIndex("FormattedPostingDate", job2)
        
        var date1 = null;
        var date2 = null;
        
        //Bug ID : #DE2077 Date Sort Issue; Remarks : Added code to read the date format and sort the date accordingly.
        if(typeof resultDateFormat != 'undefined' && typeof resultDateSeparator != 'undefined')
        {
            var arrDate1 = job1.ExtendedProperties[index1].DisplayValue.split(resultDateSeparator);
            var arrDate2 = job2.ExtendedProperties[index2].DisplayValue.split(resultDateSeparator);
            
            switch(resultDateFormat.toLowerCase())
            {
                case "mdy":
                    date1 = new Date(arrDate1[2],arrDate1[0]-1,arrDate1[1]);
                    date2 = new Date(arrDate2[2],arrDate2[0]-1,arrDate2[1]);
                    break;
                
                case "dmy":
                    date1 = new Date(arrDate1[2],arrDate1[1]-1,arrDate1[0]);
                    date2 = new Date(arrDate2[2],arrDate2[1]-1,arrDate2[0]);
                    break;
                    
                case "ymd":
                    date1 = new Date(arrDate1[0],arrDate1[1]-1,arrDate1[2]);
                    date2 = new Date(arrDate2[0],arrDate2[1]-1,arrDate2[2]);
                    break;
            }
        }
        else //Old Code
        {
            date1 = new Date(job1.ExtendedProperties[index1].DisplayValue.replace(/\./g, "/"));
            date2 = new Date(job2.ExtendedProperties[index2].DisplayValue.replace(/\./g, "/"));
        }
        // Dates are reversed because default order is descending
        return adecco.jobsearch.pagingAndSortingManager.compareValues(date2, date1);
    }

    this.compareSalaryValues = function(job1, job2) {
        /// <summary>
        /// Gets the salary fields from two given jobs. Both dates are then passed into the base
        /// compare function.
        /// </summary>
        /// <param name="job1">The first job to compare.</param>
        /// <param name="job2">The second job to compare.</param>
        /// <returns>The result of the base compare function.</returns>

        //var index1 = adecco.jobsearch.pagingAndSortingManager.getExtendedPropertyIndex("Salary", job1)
        //var index2 = adecco.jobsearch.pagingAndSortingManager.getExtendedPropertyIndex("Salary", job2)
        //var salary1 = job1.ExtendedProperties[index1].Value;
        //var salary2 = job2.ExtendedProperties[index2].Value;

        var salary1 = "";
        var salary2 = "";
        var emptyJob;

        if (job1.Salary && job1.Salary.Amount) {
            salary1 = job1.Salary.Amount;
        }

        if (job2.Salary && job2.Salary.Amount) {
            salary2 = job2.Salary.Amount;
        }

        // If salary information cannot be found, mark it as an emptyJob
        if ((salary1 === "" || salary1 === null) && (salary2 === "" || salary2 === null)) {
            emptyJob = "both";
        }
        else if (salary1 === null || salary1 === "") {
            emptyJob = "job1";
        }
        else if (salary2 === null || salary2 === "") {
            emptyJob = "job2";
        }
        return adecco.jobsearch.pagingAndSortingManager.compareValues(salary1, salary2, emptyJob);
    }

    this.compareContractTypeValues = function(job1, job2) {
        /// <summary>
        /// Gets the job type fields from two given jobs. Both types are then passed into the base
        /// compare function.
        /// </summary>
        /// <param name="job1">The first job to compare.</param>
        /// <param name="job2">The second job to compare.</param>
        /// <returns>The result of the base compare function.</returns>

        //var index1 = adecco.jobsearch.pagingAndSortingManager.getExtendedPropertyIndex("Type", job1)
        //var index2 = adecco.jobsearch.pagingAndSortingManager.getExtendedPropertyIndex("Type", job2)
        //var type1 = job1.ExtendedProperties[index1].Value;
        //var type2 = job2.ExtendedProperties[index2].Value;

        var contractType1 = "";
        var contractType2 = "";
        var emptyJob;

        if (job1.ContractType && job1.ContractType.Value) {
            contractType1 = job1.ContractType.Value;
        }

        if (job2.ContractType && job2.ContractType.Value) {
            contractType2 = job2.ContractType.Value;
        }

        // If type information cannot be found, mark it as an emptyJob
        if ((contractType1 === "" || contractType1 === null) && (contractType2 === "" || contractType2 === null)) {
            emptyJob = "both";
        }
        else if (contractType1 === null || contractType1 === "") {
            emptyJob = "job1";
        }
        else if (contractType2 === null || contractType2 === "") {
            emptyJob = "job2";
        }
        return adecco.jobsearch.pagingAndSortingManager.compareValues(contractType1, contractType2, emptyJob);
    }

    this.compareNameValues = function(job1, job2) {
        /// <summary>
        /// Gets the job title fields from two given jobs. Both titles are then passed into the base
        /// compare function.
        /// </summary>
        /// <param name="job1">The first job to compare.</param>
        /// <param name="job2">The second job to compare.</param>
        /// <returns>The result of the base compare function.</returns>

        var name1 = job1.Title;
        var name2 = job2.Title;
        var emptyJob;

        // If title information cannot be found, mark it as an emptyJob
        if ((name1 === "" || name1 === null) && (name2 === "" || name2 === null)) {
            emptyJob = "both";
        }
        else if (name1 === null || name1 === "") {
            emptyJob = "job1";
        }
        else if (name2 === null || name2 === "") {
            emptyJob = "job2";
        }

        //Bug ID :DE3059 Description: Sort BY Name is not working properly in Job Results
        return adecco.jobsearch.pagingAndSortingManager.compareValues(String(name1).toUpperCase().trim(), String(name2).toUpperCase().trim(), emptyJob);
        
                
    }

    this.compareValues = function(job1, job2, emptyJob) {
        /// <summary>
        /// The base compare function.
        /// </summary>
        /// <param name="job1">The first job to compare.</param>
        /// <param name="job2">The second job to compare.</param>
        /// <param name="emptyJob">The emptyJob, if there is one.</param>
        /// <returns>1 if job1 should come before job2
        ///			 -1 if job1 should come after job2
        ///			 0 if both jobs are the same</returns>

        // If there is an empty job, force it to show at bottom of list no matter what sorting order.
        if (emptyJob) {
            if (this.reverseOrder) {
                if (emptyJob === "job1") {
                    return -1;
                }
                else if (emptyJob === "job2") {
                    return 1;
                }
                return 0;
            }
            else {
                if (emptyJob === "job1") {
                    return 1;
                }
                else if (emptyJob === "job2") {
                    return -1;
                }
                return 0;
            }
        }
        else {
            if (job1 > job2)
                return 1;
            if (job1 < job2)
                return -1;
            return 0;
        }
    }

    this.getExtendedPropertyIndex = function(extPropId, job) {
        /// <summary>
        /// Gets the index of an extended property.
        /// </summary>
        /// <param name="extPropId">The extended property Id.</param>
        /// <param name="job">The job to search for the extended property.</param>
        /// <returns>The index of the extended property, if found. -1 if not found.</returns>

        var i;
        for (i = 0; i < job.ExtendedProperties.length; i++) {
            if (job.ExtendedProperties[i].Id === extPropId) {
                return i;
            }
        }
        return -1;
    }
}

adecco.jobsearch.pagingAndSortingManager = new PagingAndSortingManager();


// -------------------------- Paging and Sorting Manager End --------------------------


// -------------------------- Map Manager Start ---------------------------------------


function MapManager() {
    /// <summary>
    /// Manages the static map popups in the job results list and the job details page. Also manages
    /// the dynamic map in the Job Results section.
    /// </summary>
    this.myStaticMap = null;
    this.myDynamicMap = null;
    this.data = null;
    this.maxLatitude = null;
    this.minLongitude = null;
    this.minLatitude = null;
    this.maxLongitude = null;
    this.maxTitleLength = 25;
    this.maxDescriptionLength = 170;
    this.maxZoomLevel = 19;
    this.isDataWithNoLocation = false;
    this.staticMapZoomLevel = 13;

    this.initialize = function(options) {
        /// <summary>
        /// Initializes the Map Manager.
        /// </summary>
        /// <param name="options">Various options to initialize.
        ///		maxTitleLength:			The maximum infobox title length in characters
        ///		maxDescriptionLength:	The maximum infobox description length in characters
        ///		maxZoomLevel:			The maximum zoom level allowed in the Map View.
        ///		staticMapZoomLevel:		Zoom Level for static map popup.
        /// </param>

        if (options.maxTitleLength) {
            this.maxTitleLength = options.maxTitleLength;
        }
        if (options.maxDescriptionLength) {
            this.maxDescriptionLength = options.maxDescriptionLength;
        }
        if (options.maxZoomLevel) {
            this.maxZoomLevel = options.maxZoomLevel;
        }
        if (options.staticMapZoomLevel) {
            this.staticMapZoomLevel = options.staticMapZoomLevel;
        }
    }

    this.getPagingManager = function() {
        return this.pagingManager;
    }

    this.loadMapFlyout = function(e, jobTitle, location, latlong, topOffset, leftOffset, fullInfoURL) {
        /// <summary>
        /// Loads the static map fly out in the job details page and the job results page.
        /// </summary>
        /// <param name="e">The object that was clicked.</param>
        /// <param name="jobTitle">The title of the job.</param>
        /// <param name="location">The location of the job.</param>
        /// <param name="latlong">The Latitude and Longitude of the job.</param>
        /// <param name="topOffset">The top offset to where the pointer of the infobox should appear.</param>
        /// <param name="leftOffset">The left offset to where the pointer of the infobox should appear</param>
        /// <param name="fullInfoURL">The url linking to the job details page.</param>

        //Display full info link if a value to link to is passed
        var showDetailsLink = (fullInfoURL && fullInfoURL != '') ? true : false;
        //var title = Maps.Utilities.TruncateString(jobTitle, adecco.jobsearch.mapManager.maxTitleLength);
        var title = jobTitle;
        var fullInfoText = $("#fullInfoText").val();

        if (showDetailsLink) {
            //$('#MapFlyoutFullInfoUrl').click(function() { window.location = fullInfoURL; });
            $('#MapFlyoutFullInfoUrl').css("display", "");

            //$('#MapFlyoutJobTitle').click(function() { window.location = fullInfoURL; });
            $('#MapFlyoutJobTitle').css("cursor", "pointer");

            // Create links to the job details page. One for job title and one for full info.
            var jobTitlelink = "<a class ='job-title-static-map' href='" + fullInfoURL + "' target='" + $("#jobdetailstarget").val() + "'>" + title + "</a>";

            var fullInfolink = "<a class ='full-info-static-map' href='" + fullInfoURL + "' target='" + $("#jobdetailstarget").val() + "'>" + fullInfoText + "</a>";

            // Check to see if the job title link has already been added (user has clicked on one of the map links already).
            // If it exists, remove old link and insert new one. Otherwise just insert new one.
            // Only job title link is checked, assumed the full info link is the same.
            if ($('.job-title-static-map')) {
                $('.job-title-static-map').remove();
                $('.full-info-static-map').remove();

                $(jobTitlelink).appendTo('#MapFlyoutJobTitle');
                $(fullInfolink).prependTo('#MapFlyoutFullInfoUrl');
            }
            else {
                $(jobTitlelink).appendTo('#MapFlyoutJobTitle');
                $(fullInfolink).prependTo('#MapFlyoutFullInfoUrl');
            }
        }
        else {   //Hide full info link otherwise
            $('#MapFlyoutFullInfoUrl').css("display", "none");
            topOffset += 25;

            // This is for the job details page where there is no link. Only add text for the job title.
            $('#MapFlyoutJobTitle').text(title);
        }

        //offset the map flyout so that it appears above the link that was clicked
        //May need to adjust in order to align arrow with link.
        $('#MapFlyoutContainer').css("top", (Maps.Utilities.CalculateOffsetTop(e) - $('#MapFlyoutContainer').height() + topOffset) + "px");
        $('#MapFlyoutContainer').css("left", Maps.Utilities.CalculateOffsetLeft(e) + leftOffset + "px");

        $('#MapFlyoutJobLocation').text(location);

        //Display the link
        $('#MapFlyoutContainer').css("display", "");

        //Load the map control if needed
        if (this.myStaticMap == null) {
            this.myStaticMap = $('#MyStaticMap').MapFactory({
                mapAPI: Maps.MapAPI.Bing,
                center: latlong,
                zoomLevel: this.staticMapZoomLevel,
                mapStyle: Maps.MapStyle.Road,
                enableClustering: false,
                credentials: "AvdCxDwGP1vNG4HDcY4IlGIew_NpTvbkc4fDNMztWJK2JSj6la_a8G5cN3ofSmFo",               //Add in Bing Maps Application Key here
                fixed: true,
                onMapLoaded: function() { adecco.jobsearch.mapManager.addPushpin(latlong); }
            });
        }
        else {  //Center the map and add the pushpin
            this.myStaticMap.SetCenter(latlong);
            adecco.jobsearch.mapManager.addPushpin(latlong);
        }
    }

    this.addPushpin = function(latlong) {
        /// <summary>
        /// Adds pushins on the static map popup.
        /// </summary>
        /// <param name="latlong">The Latitude and Longitude of the job location.</param>

        //Clear all exisiting pushpins
        this.myStaticMap.Clear();

        //create custom pushpin
        var pin = new Maps.Pushpin(latlong);
        pin.CustomHTML = "<div class='MapSprite customPushpin'>&nbsp;</div>";
        this.myStaticMap.AddPins(pin);
        //Bug ID : #DE2072 Closed On : July 22,2011 Remarks : change cursor Pointer to default - user will not see option to click.
        $('.VEAPI_Pushpin').css("cursor", "default");
    }

    this.loadMapView = function() {
        /// <summary>
        /// Loads the dynamic map in View Map section of job results.
        /// </summary>

        // Make width of map the same width as web part.
        var webPartWidth = $(".job-results-part").width();
        $('#MyDynamicMap').css("width", webPartWidth - 20);

        //Load the map control if needed
        if (this.myDynamicMap == null) {
            this.myDynamicMap = $('#MyDynamicMap').MapFactory({
                mapAPI: Maps.MapAPI.Bing,
                maxZoomLevel: this.maxZoomLevel,
                mapStyle: Maps.MapStyle.Road,
                canShowInfoBox: true,
                enableClustering: true,
                credentials: "AvdCxDwGP1vNG4HDcY4IlGIew_NpTvbkc4fDNMztWJK2JSj6la_a8G5cN3ofSmFo",               //Add in Bing Maps Application Key here
                fixed: false,
                onMapLoaded: function() { adecco.jobsearch.mapManager.loadMapViewCallback(); }
            });
        }
        else {  //Center the map and add the pushpin
            //			this.myDynamicMap.SetCenter(latlong);
            //			adecco.jobsearch.mapManager.addPushpin(latlong);
        }
    }

    this.loadMapViewCallback = function() {
        /// <summary>
        /// Call back function after the dynamic map gets loaded.
        /// </summary>

        if (this.myDynamicMap.ClusterAlgorithm != null) {
            //Create a single shape callback function to generate a non-clustered pushpin
            this.myDynamicMap.ClusterAlgorithm.SetSingleShapeCallback(function(data) {
                var pin = new Maps.Pushpin(data.LatLong);
                //pin.CustomHTML = "<div class='MapSprite customPushpin'>" + data.length + "</div>";
                pin.CustomHTML = "<div class='MapSprite clusteredPushpin'>1</div>";
                return pin;
            });

            //Create clustered shape callback function to generate a clustered pushpin
            this.myDynamicMap.ClusterAlgorithm.SetClusteredShapeCallback(function(data, latlong) {
                var pin = new Maps.Pushpin(latlong);
                pin.CustomHTML = "<div class='MapSprite clusteredPushpin'>" + data.length + "</div>";
                return pin;
            });
        }

        if (this.myDynamicMap.InfoboxControl != null) {    //Create infobox content builder
            this.myDynamicMap.InfoboxControl.SetInfoboxContentBuilder(function(data) {
                var content;
                if (data != null) {
                    if (data.length != null && data.length > 0) {
                        //Bug ID : #DE2056 Closed On : June 13,2011 Remarks : Commented below code and called createClusteredPushpinInfobox for both templates to be same (i.e. single as well as multiple records)
                        content = adecco.jobsearch.mapManager.createClusteredPushpinInfobox(data);
                        //                        if (data.length == 1) {    //Single data object, get rid of array
                        //                            data = data[0];
                        //                        }
                        //                        else {	//Create clustered infobox
                        //                            content = adecco.jobsearch.mapManager.createClusteredPushpinInfobox(data);
                        //                        }
                    }

                    if (data.length == null)   //Generate infobox for single data object
                    {
                        content = adecco.jobsearch.mapManager.createSinglePushpinInfobox(data);
                    }
                }
                return content;
            });
        }
        this.addData();
        this.addMissingJobsNotification();
    }

    this.createSinglePushpinInfobox = function(data) {
        /// <summary>
        /// Creates the infobox for single pushpin
        /// </summary>
        /// <param name="data">The job that is being displayed.</param>

        var contentBuilder = [];
        var contentTemplate;
        var content;
        var resourceStrings = adecco.jobsearch.resourceStrings;

        contentBuilder.push("<div class='MF_InfoBox_Single'>");
        contentBuilder.push("<div class='MF_Infobox_JobTitle job-title'><a href='%(detailsUrl)s' target='%(target)s'>", Maps.Utilities.TruncateString(data.Title, adecco.jobsearch.mapManager.maxTitleLength), "</a>");
        contentBuilder.push("<img src='/_layouts/AdeccoGroup/WebParts/JobSearch/images/transparentIcon.gif' class='MapSprite MF_CloseBtn' onclick=\"$('#", adecco.jobsearch.mapManager.myDynamicMap.GetID(), "_Infobox').css('display', 'none');\" alt=''/>");
        contentBuilder.push("</div>");

        contentBuilder.push("<ul class='MF_InfoBox_Single_Properties'>");
        contentBuilder.push("<li class='jsSpriteMap toggle-shortlistMap %(off)s' onclick='adecco.jobsearch.resultsController.didToggleShortList(this, \"%(jobId)s\");'><a class='toggle-shortlistMap' href='javascript:void(0)'><img src='/_layouts/AdeccoGroup/WebParts/JobSearch/images/blank.gif' alt=''/></a></li>");
        contentBuilder.push("<li class='MF_Infobox_SmallText job-salary'>%(salary)s</li>");
        contentBuilder.push("<li class='MF_Infobox_SmallText job-type'>%(type)s</li>");
        contentBuilder.push("<li class='last MF_Infobox_SmallText job-postDate'>%(date)s</li>");
        contentBuilder.push("</ul>");

        contentBuilder.push("<div class='MF_Infobox_Description job-descr'>" + Maps.Utilities.TruncateString(data.Description, adecco.jobsearch.mapManager.maxDescriptionLength) + "</div>");

        contentBuilder.push("<div class='MF_Infobox_FullInfoDiv'>&nbsp;<a href='%(detailsUrl)s' target='%(target)s' class='MF_Infobox_FullInfoURL'>%(text_fullInfo)s&nbsp;<img src='/_layouts/AdeccoGroup/WebParts/JobSearch/images/transparentIcon.gif' class='MapSprite MF_Chevron' alt=''/></a></div>");
        contentBuilder.push("</div>");

        var contentTemplate = contentBuilder.join('');

        var content = $.sprintf(contentTemplate, {
            'jobId': data.Id,
            'detailsUrl': adecco.jobsearch.resultsController.getJobDetailsUrl(data),
            'title': data.Title,
            'description': data.Description,
            'date': adecco.jobsearch.resultsController.getExtendedProperty(data, 'FormattedPostingDate').DisplayValue,
            'salary': adecco.jobsearch.resultsController.getExtendedProperty(data, 'Salary').DisplayValue || '',
            'type': data.ContractType.DisplayValue || '',
            'text_fullInfo': $("#fullInfoText").val(),
            'shareJobUrl': adecco.jobsearch.resultsController.getShareJobUrl(data),
            'applyJobUrl': adecco.jobsearch.resultsController.getApplyJobUrl(data),
            'off': adecco.jobsearch.ShortListManager.isShortListed(data.Id) ? "" : "off",
            'target': $("#jobdetailstarget").val()
        });
        return content;
    }

    this.getContentHtml = function() {
        var content = "";
        var resourceStrings = adecco.jobsearch.resourceStrings;
        var pagingHtml = "";
        var contentBuilder = [];
        var data = [];
        var contentTemplate;
        var curPageNo = this.pagingManager.prototype.getCurrentPageNumber();

        /*contentBuilder.push("<div class='MF_Infobox_JobTitle job-title'>%(jobTitle)s");
        //contentBuilder.push("<img src='/_layouts/AdeccoGroup/WebParts/JobSearch/images/transparentIcon.gif' class='MapSprite MF_CloseBtn' onclick=\"$('#", adecco.jobsearch.mapManager.myDynamicMap.GetID(), "_Infobox').css('display', 'none');\" alt=''/>");
        contentBuilder.push("</div>");

	    contentBuilder.push("<ul class='MF_InfoBox_Single_Properties'>");
        contentBuilder.push("<li class='jsSprite toggle-shortlist %(off)s' onclick='adecco.jobsearch.resultsController.didToggleShortList(this, \"%(jobId)s\");'><a href='javascript:void(0)'><img src='/_layouts/AdeccoGroup/WebParts/JobSearch/images/blank.gif' alt=''/></a></li>");
        contentBuilder.push("<li class='MF_Infobox_SmallText job-salary'>%(salary)s</li>");
        contentBuilder.push("<li class='MF_Infobox_SmallText job-type'>%(type)s</li>");
        contentBuilder.push("<li class='last MF_Infobox_SmallText job-postDate'>%(date)s</li>");
        contentBuilder.push("</ul>");

	    contentBuilder.push("<div class='MF_Infobox_Description job-descr'>%(jobDescription)s</div>");

	    contentBuilder.push("<div>&nbsp;<a href='%(detailsUrl)s' class='MF_Infobox_FullInfoURL'>%(text_fullInfo)s&nbsp;<img src='/_layouts/AdeccoGroup/WebParts/JobSearch/images/transparentIcon.gif' class='MapSprite MF_Chevron' alt=''/></a></div>");
        //contentBuilder.push("</div>");
        */

        pagingHtml = this.pagingManager.prototype.getPagingHtml();

        data = this.pagingManager.prototype.getPagingContent(this.pagingManager.prototype.getCurrentPageNumber());
        //var contentTemplate = contentBuilder.join('');
        var controls = "<DIV class='controls' sizcache='1' sizset='2'><ul>" +
	                    "<li class='jsSpriteMap toggle-shortlistMap %(off)s' onclick='adecco.jobsearch.resultsController.didToggleShortList(this, \"%(jobId)s\");'><a class='toggle-shortlistMap' href='javascript:void(0)'>" +
	                        "<img src='/_layouts/AdeccoGroup/WebParts/JobSearch/images/blank.gif' alt=''/></a></li><LI class='jsSprite email' sizcache='0' sizset='3'>" +
                            "<A href='%(shareJobUrl)s' onclick='$(this).modal({width:560, height:360}).open(); return false;'>" +
                            "<IMG alt='' src='/_layouts/AdeccoGroup/WebParts/JobSearch/images/blank.gif' />" +
                            "</A></LI><LI class='details' sizcache='0' sizset='4'>" +
                            "<A href='" + $('#jobdetailspageurl').val() + "?job-id=%(Id)s' target='" + $("#jobdetailstarget").val() + "'>%(text_fullInfo)s &gt;&gt;</A></LI></UL></DIV>";

        var contentTemplate = "<div class ='MF_InfoBox_Cluster' style='width:350px; text-align:left'>" +
                                "<div class='first job-entry'>" +
                                "<div><a class='job-title' href='" + $('#jobdetailspageurl').val() + "?job-id=%(Id)s' target='" + $("#jobdetailstarget").val() + "'>" +
                                "%(Title)s&nbsp;<span style='font-size: smaller; font-weight:normal'><span style='font-style:italic'>in</span> %(City)s %(State)s</span>" +
                                "</a>" +
                                "<div class='job-descr' style='margin-top: 8px;'>%(Description)s</div>" + controls + "</div></div></div>";
        $(data).each(function() {
            /*content += $.sprintf(contentTemplate, {
            'jobId': this.Id,
            'jobTitle': Maps.Utilities.TruncateString(this.Title, adecco.jobsearch.mapManager.maxTitleLength),
            'jobDescription': Maps.Utilities.TruncateString(this.Description, adecco.jobsearch.mapManager.maxDescriptionLength),
            'detailsUrl': adecco.jobsearch.resultsController.getJobDetailsUrl(this),
            'title': this.Title,
            'description': this.Description,
            'date': adecco.jobsearch.resultsController.getExtendedProperty(this, 'FormattedPostingDate').DisplayValue,
            'salary': adecco.jobsearch.resultsController.getExtendedProperty(this, 'Salary').DisplayValue || '',
            'type': this.ContractType.DisplayValue || '',
            'text_fullInfo': resourceStrings['JobResults_FullInfoText'],
            'shareJobUrl': adecco.jobsearch.resultsController.getShareJobUrl(this),
            'off': adecco.jobsearch.ShortListManager.isShortListed(this.Id) ? "" : "off"*/
            content += $.sprintf(contentTemplate, {
                'Id': this.Id,
                'Title': this.Title,
                'Description': this.Description,
                'State': (this.Address.ProvinceOrState != null && this.Address.ProvinceOrState != "") ? ", " + this.Address.ProvinceOrState : "",
                'City': this.Address.City,
                'off': adecco.jobsearch.ShortListManager.isShortListed(this.Id) ? "" : "off",
                'shareJobUrl': adecco.jobsearch.resultsController.getShareJobUrl(this),
                'applyJobUrl': adecco.jobsearch.resultsController.getApplyJobUrl(this),
                'jobId': this.Id,
                'text_fullInfo': $("#fullInfoText").val()
            });
        });
        newcontent = "<div class='MF_InfoBox_Cluster'><div style='margin-right: 0; margin-left:auto; text-align:right'>" +
                            "<img src='/_layouts/AdeccoGroup/WebParts/JobSearch/images/transparentIcon.gif' class='MapSprite MF_CloseBtn' onclick=\"$('#" +
                            adecco.jobsearch.mapManager.myDynamicMap.GetID() +
                            "_Infobox').css('display', 'none');\" alt=''/></div>" + content;

        if (data.length > 1 || curPageNo > 1) //if more than 1 records then show pager; 1 record was earlier generated through createSinglePushpinInfobox method
        {
            newcontent += "<span style='font-size: 8px'>" + pagingHtml + "</span></div>";
        }
        return newcontent;
    }

    this.createClusteredPushpinInfobox = function(data) {

        this.pagingManager = adecco.PagingManager;
        this.pagingManager.prototype.initialize($(".mapClusteredPageSize").val(), data);
        return this.getContentHtml();

    }

    this.addData = function() {
        /// <summary>
        /// Adds the pushpins to the map
        /// </summary>

        if (this.myDynamicMap !== null) {
            var results = adecco.jobsearch.resultsController.getFilteredResults();
            this.data = [];
            var boundingBox = null;
            var dataCount = 0;

            // Add Maps.LatLong to each job result if it exists.
            for (var i = 0; i < results.length; i++) {
                if (results[i].Address && results[i].Address.Location) {
                    this.data.push(results[i]);
                    this.data[dataCount].LatLong = new Maps.LatLong(this.data[dataCount].Address.Location.Latitude, this.data[dataCount].Address.Location.Longitude);
                    dataCount++;
                }
                else {
                    this.isDataWithNoLocation = true;
                }
            }

            this.calculateBoundingBox();
            boundingBox = new Maps.BoundingBox(new Maps.LatLong(this.maxLatitude, this.minLongitude), new Maps.LatLong(this.minLatitude, this.maxLongitude));

            adecco.jobsearch.mapManager.myDynamicMap.SetMapView(boundingBox);
            adecco.jobsearch.mapManager.myDynamicMap.ClusterAlgorithm.SetData(this.data);
        }
    }

    this.calculateBoundingBox = function() {
        /// <summary>
        /// Calculates a bounding box encompassing all job locations.
        /// </summary>

        // Initialize min/max LatLongs

        if (this.data.length > 0) {

            var padding = 0.01;
            this.minLatitude = this.data[0].LatLong.Latitude;
            this.minLongitude = this.data[0].LatLong.Longitude;
            this.maxLatitude = this.data[0].LatLong.Latitude;
            this.maxLongitude = this.data[0].LatLong.Longitude;

            for (var i = 0; i < this.data.length; i++) {
                if (this.data[i].LatLong.Latitude < this.minLatitude) {
                    this.minLatitude = this.data[i].LatLong.Latitude;
                }
                if (this.data[i].LatLong.Latitude > this.maxLatitude) {
                    this.maxLatitude = this.data[i].LatLong.Latitude;
                }
                if (this.data[i].LatLong.Longitude < this.minLongitude) {
                    this.minLongitude = this.data[i].LatLong.Longitude;
                }
                if (this.data[i].LatLong.Longitude > this.maxLongitude) {
                    this.maxLongitude = this.data[i].LatLong.Longitude;
                }
            }

            // Add some padding around the bounding box so that all pushpins are in center of map
            this.minLatitude -= padding;
            this.maxLatitude += padding;
            this.minLongitude -= padding;
            this.maxLongitude += padding;
        }
    }

    this.addMissingJobsNotification = function() {
        /// <summary>
        /// Shows the missing jobs notification at the bottom of the map.
        /// </summary>

        if (this.isDataWithNoLocation) {
            $("#divMissingJobsNote").css("display", "block");
        }
    }

    this.closeMissingJobsNotification = function() {
        /// <summary>
        /// Hides the missing jobs notification at the bottom of the map.
        /// </summary>

        $("#divMissingJobsNote").css("display", "none");
    }

    //Example of how to handle a click on the see jobs button in the clustered infobox
    this.seeJobs = function(GridKey) {
        if (adecco.jobsearch.mapManager.myDynamicMap.ClusterAlgorithm != null) {
            //Get all data in Grid cell
            var data = adecco.jobsearch.mapManager.myDynamicMap.ClusterAlgorithm.GetDataByGridKey(GridKey, true);

            alert("GridKey: " + GridKey + " Data Set Size: " + data.length);
        }
    }
}

adecco.jobsearch.mapManager = new MapManager();


// -------------------------- Map Manager End ---------------------------------------


adecco.jobsearch.JobResultsViewController.showListView = function(control, viewList) {
    /// <summary>
    /// Shows the List View and hides the Map View.
    /// </summary>
    
    if(viewList === undefined)
    {
        this.setClassName(control, "active");
    }
    else 
    {
        this.setViewListStyles("active");
    }

    $('#divPagination').css("display", "block");
    $('#divPaginationFooter').css("display", "block");
    $('#divListView').css("display", "block");
    $('#jobDetailToolbarLeft').css("display", "block");
    $('#divMapView').css("display", "none");

    // Hide any open infoboxes, if applicable
    if (adecco.jobsearch.mapManager.myDynamicMap !== null) {
        $('#' + adecco.jobsearch.mapManager.myDynamicMap.GetID() + '_Infobox').css('display', 'none');
    }
}

adecco.jobsearch.JobResultsViewController.showMapView = function(control) {
    /// <summary>
    /// Shows the Map View and hides the List View.
    /// </summary>

    this.setClassName(control, "active");

    $('#divPagination').css("display", "none");
    $('#divPaginationFooter').css("display", "none");
    $('#divListView').css("display", "none");
    $('#jobDetailToolbarLeft').css("display", "none");
    $('#divMapView').css("display", "block");
    adecco.jobsearch.mapManager.loadMapView();
}

adecco.jobsearch.JobResultsViewController.setClassName = function(control, className) {
   
    /*   Set active className */
    var ul = control.parentNode.parentNode;

    for (var i = 0; i < ul.childNodes.length; i++) {
        // ul.childNodes[i].setAttribute("class", "");
        //changed above line for bug ID 3467
        ul.childNodes[i].className = "";
    }

    //control.parentNode.setAttribute("class", className);
    //changed above line for bug ID 3467
    control.parentNode.className = className;

    /*  End Set active className */
}

adecco.jobsearch.JobResultsViewController.setViewListStyles = function(className) {
    /*   Set active className */
    var ul = document.getElementById('jobResults-view-options-container').childNodes[0];

    for (var i = 0; i < ul.childNodes.length; i++) {
        try {
            //ul.childNodes[i].setAttribute("class", "");
            //changed above line for bug ID 3467
            ul.childNodes[i].className = "";
        }
        catch (e) {
        }
    }
    try {
        // ul.childNodes[0].setAttribute("class", className);
        //changed above line for bug ID 3467
        ul.childNodes[0].className = className;
    }
    catch (e) {
    }

    /*  End Set active className */
}

