/* Application-wide javascript methods for PointCarbon web app */


/* binding window.onload to the initPage method.
to add onload-functionality, just add your method call to the initPage method */
window.onload = initPage;

var onloadFunctions = new Array();

function addOnloadFunction(func) {
    onloadFunctions.push(func);
}


function initPage() {
    for (var i = 0; i < onloadFunctions.length; i++) {
        onloadFunctions[i]();
    }

}

function updatePhoneCountryCode(countryCode) {
    var codes = document.getElementById("userInfoForm:userPhoneCountryCodeSelect");
    var i;
    var found = false;
    for (i = 0; i <codes.options.length; i++) {
        if (codes.options[i].value == countryCode) {
            document.getElementById("userInfoForm:userWorkPhoneCountryCode").value = codes.options[i].text;
            document.getElementById("userInfoForm:userWorkPhoneCountryCodeText").value = codes.options[i].text;
            document.getElementById("userInfoForm:userMobilePhoneCountryCode").value = codes.options[i].text;
            document.getElementById("userInfoForm:userMobilePhoneCountryCodeText").value = codes.options[i].text;
            found = true;
            return;
        }
    }
    if (found == false) {
        document.getElementById("userInfoForm:userWorkPhoneCountryCode").value = "";
        document.getElementById("userInfoForm:userWorkPhoneCountryCodeText").value = "";
        document.getElementById("userInfoForm:userMobilePhoneCountryCode").value = "";
        document.getElementById("userInfoForm:userMobilePhoneCountryCodeText").value = "";
    }

}

function updateInvoicePhoneCountryCode(countryCode) {
    var codes = document.getElementById("invoiceInfoForm:invoicePhoneCountryCodeSelect");
    var i;
    var found = false;
    for (i = 0; i <codes.options.length; i++) {
        if (codes.options[i].value == countryCode) {
            document.getElementById("invoiceInfoForm:invoicePhoneCountryCode").value = codes.options[i].text;
            document.getElementById("invoiceInfoForm:invoicePhoneCountryCodeText").value = codes.options[i].text;
            found = true;
            return;
        }
    }
    if (!found) {
        document.getElementById("invoiceInfoForm:invoicePhoneCountryCode").value = "";
        document.getElementById("invoiceInfoForm:invoicePhoneCountryCodeText").value = "";
    }

}


/* loops through the HTML document for any tags that contain the tooltip="" attribute
  and registers the showTooltip and hideTooltip methods as event listeners for the onmouseover and onmouseout event handlers.
  This means that any assignments to onmouseover and onmouseout for these tags will be overwritten.
*/
function registerTooltips() {
    var bodyElement = document.getElementsByTagName("body")[0];
    if (bodyElement) {
        if (BrowserDetect.browser == "Opera" && (Math.floor(BrowserDetect.version) < 9)) {
            // This script didn't work on Opera 8.52 so we skip it on all pre-9 versions of Opera
        } else {
            registerTooltip(bodyElement);
        }
    }
}

/* recursive function that renders tooltip eventhandlers if the element argument contains a tooltip="" attribute */
function registerTooltip(element) {

    if (element.nodeType == 1 && element.getAttribute("tooltip") != null) {
        //alert("registering tooltip " + element.getAttribute("tooltip") + " for element " + element.nodeName);
        var ttip = "" + element.getAttribute("tooltip");
        element.onmouseover = function(e) {
            showTooltip(ttip, e);
        }
        element.onmouseout = hideTooltip;
    }

    var kids = element.childNodes;
    for (var i = 0; i < kids.length; i++) {
        registerTooltip(kids[i]);
    }
}

/*
  Inserts the tooltipText into the tooltip div,
  positions the div near the mouse position, and displays it
*/
function showTooltip(tooltipText, e) {

    var tooltipContainer = $('tooltipContainer');
    tooltipContainer.innerHTML = "<p>" + tooltipText + "</p>";
    // positioning tooltip relative to the mouse position.
    var mousex = getMouseX(e);
    var mousey = getMouseY(e);
    tooltipContainer.style.left = (mousex + 5) + "px";
    tooltipContainer.style.top = (mousey + 10) + "px";
    Element.show(tooltipContainer);

}

function hideTooltip() {
    Element.hide('tooltipContainer');
}

function getMouseX(e) {
    return getMousePositionAsArray(e)[0];
}

/* script for retrieving mouse coordinates.
  taken from http://www.quirksmode.org/js/events_properties.html */
function getMousePositionAsArray(e) {
    var posx = 0;
    var posy = 0;
    if (!e) var e = window.event;
    if (e.pageX || e.pageY) {
        posx = e.pageX;
        posy = e.pageY;
    }
    else if (e.clientX || e.clientY) {
        posx = e.clientX + document.body.scrollLeft
                + document.documentElement.scrollLeft;
        posy = e.clientY + document.body.scrollTop
                + document.documentElement.scrollTop;
    }
    return [posx, posy];
}

function getMouseY(e) {
    return getMousePositionAsArray(e)[1];
}


/** code for tabpane component **/
var tabPanesList = new Array();

function tabPanes(tabPaneId) {
    return tabPanesList[$(tabPaneId).id];
}

function addTabPane(tabPaneId, selectedTabId) {
    tabPanesList[tabPaneId] = new TabPane(tabPaneId, selectedTabId);
}


var TabPane = Class.create();
TabPane.prototype = {
    initialize: function(tabPaneId, selectedTabId) {
        this.tabPaneId = tabPaneId;
        this.containerId = tabPaneId + "_container";
        this.selectedTabId = selectedTabId;
    },

    getTabs: function() {
        return $(this.tabPaneId).getElementsByTagName("li");
    },

    tabClicked: function(tabInstance) {
        this.selectedTabId = tabInstance.id;
        var tabsCollection = this.getTabs();
        for (var i = 0; i < tabsCollection.length; i++) {
            if (tabInstance == tabsCollection[i]) {
                tabsCollection[i].className = "tab_selected";
                if ($(tabsCollection[i].id + "_content")) {
                    $(tabsCollection[i].id + "_content").show();
                }
            } else {
                tabsCollection[i].className = "tab";
                if ($(tabsCollection[i].id + "_content")) {
                    $(tabsCollection[i].id + "_content").hide();
                }
            }
        }
    },

    tabHover: function(tabInstance) {
        $(tabInstance.id).className = $(tabInstance.id).className + " tab_hover";
    },

    tabHoverEnd: function(tabInstance) {
        if (tabInstance.id == this.selectedTabId) {
            $(tabInstance).className = "tab_selected";
        } else {
            $(tabInstance).className = "tab";
        }
    }

}

// BrowserDetect script, taken from http://www.quirksmode.org/js/detect.html
var BrowserDetect = {
    init: function () {
        this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
        this.version = this.searchVersion(navigator.userAgent)
                || this.searchVersion(navigator.appVersion)
                || "an unknown version";
        this.OS = this.searchString(this.dataOS) || "an unknown OS";
    },
    searchString: function (data) {
        for (var i = 0; i < data.length; i++) {
            var dataString = data[i].string;
            var dataProp = data[i].prop;
            this.versionSearchString = data[i].versionSearch || data[i].identity;
            if (dataString) {
                if (dataString.indexOf(data[i].subString) != -1)
                    return data[i].identity;
            }
            else if (dataProp)
                return data[i].identity;
        }
    },
    searchVersion: function (dataString) {
        var index = dataString.indexOf(this.versionSearchString);
        if (index == -1) return;
        return parseFloat(dataString.substring(index + this.versionSearchString.length + 1));
    },
    dataBrowser: [
    {     string: navigator.userAgent,
        subString: "OmniWeb",
        versionSearch: "OmniWeb/",
        identity: "OmniWeb"
    },
    {
        string: navigator.vendor,
        subString: "Apple",
        identity: "Safari"
    },
    {
        prop: window.opera,
        identity: "Opera"
    },
    {
        string: navigator.vendor,
        subString: "iCab",
        identity: "iCab"
    },
    {
        string: navigator.vendor,
        subString: "KDE",
        identity: "Konqueror"
    },
    {
        string: navigator.userAgent,
        subString: "Firefox",
        identity: "Firefox"
    },
    {
        string: navigator.vendor,
        subString: "Camino",
        identity: "Camino"
    },
    {        // for newer Netscapes (6+)
        string: navigator.userAgent,
        subString: "Netscape",
        identity: "Netscape"
    },
    {
        string: navigator.userAgent,
        subString: "MSIE",
        identity: "Explorer",
        versionSearch: "MSIE"
    },
    {
        string: navigator.userAgent,
        subString: "Gecko",
        identity: "Mozilla",
        versionSearch: "rv"
    },
    {         // for older Netscapes (4-)
        string: navigator.userAgent,
        subString: "Mozilla",
        identity: "Netscape",
        versionSearch: "Mozilla"
    }
            ],
    dataOS : [
    {
        string: navigator.platform,
        subString: "Win",
        identity: "Windows"
    },
    {
        string: navigator.platform,
        subString: "Mac",
        identity: "Mac"
    },
    {
        string: navigator.platform,
        subString: "Linux",
        identity: "Linux"
    }
            ]

};

BrowserDetect.init();

//===== DataTable ============================================================
var dataTables = [];

function DataTable(id, htmlId) {
    this.id = id;
    this.htmlId = htmlId;
    this.dropdownFilterJQuerySelector = "select#datatable_" + this.htmlId + "_filter_select";
}
DataTable.prototype = {
    baseTableURL: "",
    baseMetaDataURL: "/ChartServer/MetadataServletCached?objectType=TABLE",
    baseInteractiveChartURL: "",

    filterEnabled: false,
    filterType: "",
    filterDefaultValue: "",
    filterDisplayEnabled: false,
    filterMultiSelectEnabled: false,

    alternativeObjectType: "",
    alternativeObjectId: 0,
    useAlternativeDownload: false,
    useAlternativeInteractive: false,

    interactiveChartContainer: 'reportInteractiveChart',
    interactiveChartIframe: 'interactive_chart_iframe',
    staticChartContainer: 'reportMain',
    interactiveChartTitle: 'ia_chart_title',

    linkURL: "",
    linkTooltip: "",

    showFooter: true,
    fadeEnabled: false,
    refreshing: false,

    toString: function () {
        return "DataTable[id:" + this.id + "]";
    },

    getTableURL: function () {
        this.tableURL = this.baseTableURL + this.getFilterQueryString();

        if (this.useAlternativeDownload) {
            this.tableURL += "&alternativedownload=1&alternativeobjecttype=" + this.alternativeObjectType + "&alternativeobjectid=" + this.alternativeObjectId;
        }

        return this.tableURL;
    },

    updateTable: function () {
        if (this.fadeEnabled) {
            jQuery("#datatable_" + this.htmlId).fadeTo("fast", 0.1);
        }

        jQuery.ajax({
            url: this.getTableURL(),
            cache: false,
            htmlId: this.htmlId,
            success: function(html) {
                var table = dataTables[this.htmlId];
                // TODO jquery.load can accept which selector to extract from response, hence no need to to html parsing
                var bodyTag = "<body>";
                var start = html.indexOf(bodyTag);
                if (start > 0) {
                    var end = html.indexOf("</body");
                    if (end > 0) {
                        html = html.substring(start + bodyTag.length, end);
                    }
                }

                html = html.replace(/!Id!/g, this.htmlId);
                jQuery("#datatable_" + this.htmlId).html(html);

                if (table.linkURL) {
                    jQuery("#datatable_" + this.htmlId)
                        .attr("title", table.linkTooltip)
                        .css("cursor", "pointer")
                        .click(function(){ location.href = table.linkURL });
                }

                if (table.fadeEnabled) {
                    jQuery("#datatable_" + this.htmlId).fadeTo("slow", 1.0);
                }

                table.updateFooter();

                if (table.refreshing) {
                    jQuery("#datatable_" + table.htmlId).fadeOut(100).fadeIn(100).fadeOut(200).fadeIn(200).fadeOut(200).fadeIn(200);
                    table.refreshing = false;
                }
            }
        });
    },

    updateFooter: function () {
        var lastUpdated = jQuery.trim(jQuery("#datatable_" + this.htmlId + "_last_updated").text());
        if (lastUpdated != "") {
            jQuery("#datatable_" + this.htmlId + "_last_updated_placeholder").text(lastUpdated);
        }

        var showInfo = jQuery.trim(jQuery("#datatable_" + this.htmlId + "_info").text()) != "";
        var linkParentTD = jQuery("#datatable_" + this.htmlId + "_info_link").parent().eq(0);
        if (showInfo) {
            linkParentTD.show();
        } else {
            linkParentTD.hide();
        }

        this.baseCsvDownloadURL = jQuery.trim(jQuery("#datatable_" + this.htmlId + "_csv_download_url").text());
        jQuery("#datatable_" + this.htmlId + "_csv_download_link")
            .attr("href", this.baseCsvDownloadURL + this.getFilterQueryString() + "&ts=" + new Date().getTime());

        if (this.showFooter) {
            jQuery("#datatable_" + this.htmlId + "_footer").show();
        }
    },

    load: function () {
        if (this.filterEnabled) {
            this.loadMetaData();
        } else {
            this.updateTable();
        }
    },

    refresh: function() {
        this.refreshing = true;
        this.load();
    },

    loadMetaData: function () {
        var metaDataURL = this.baseMetaDataURL + "&id=" + this.id;

        if (this.filterType) {
            metaDataURL += "&filtertype=" + this.filterType;
        }
        var ctrl = this;
        jQuery.ajax({
            url: metaDataURL,
            cache: false,
            dataType: "json",
            htmlId: this.htmlId,
            timeout: 15000,
            success: function (metaData) {
                var table = dataTables[this.htmlId];
                table.applyMetaData(metaData);
                table.updateTable();
            },
            error : function (XMLHttpRequest, textStatus, errorThrown) {
                ctrl.displayErrorMessage();
            }
        });
    },

    displayErrorMessage: function() {
        jQuery("#datatable_" + this.htmlId + "_spinner").hide();
        //jQuery("#datatable_" + this.htmlId + ' div').hide();
        jQuery("#datatable_" + this.htmlId + ' div:first')
                .append(jQuery(document.createElement('span'))
                .css({position:'relative', top:'40%'})
                .html('This table is temporarily unavailable.<br/>' +
                      'We apologize for the inconvenience. Please try refreshing the page or <a href="mailto:appwatch@pointcarbon.com">contact us</a> if the problem persists.'));
    },

    applyMetaData: function (metaData) {
        if (this.filterEnabled && metaData.filter) {
            if (this.filterDisplayEnabled) {
                var filter = '<select id="datatable_' + this.htmlId + '_filter_select"';
                if (this.filterMultiSelectEnabled) {
                    filter += ' multiple="multiple" size="3"';
                }
                filter += ">";

                for (i = 0; i < metaData.filter.options.length; i++) {
                    filter += '<option value="' + metaData.filter.options[i].id + '">' + metaData.filter.options[i].label + "</option>\n";
                }
                filter += "</select>";

                var filterDiv = jQuery("#datatable_" + this.htmlId + "_filter");
                filterDiv.html(filter);
                filterDiv.show();

                var sel = jQuery("select#datatable_" + this.htmlId + "_filter_select");

                if (this.filterDefaultValue) {
                   sel.val(this.filterDefaultValue.split(/\s*,\s*/));
                }
                sel.change(this.filterOnChange);
            }
        }
    },

    // "this" means SELECT object here!
    filterOnChange: function () {
        var htmlId = this.id.match(/\d+/)[0];
        var table = dataTables[htmlId];
        table.fadeEnabled = true;
        table.updateTable();
    },

    // NOTE this function is re-used in DataChart
    getFilterQueryString: function () {
        var value = "";

        if (this.filterEnabled) {
            if (this.filterDisplayEnabled) {
                if (this.filterMultiSelectEnabled) {
                    value = (jQuery(this.dropdownFilterJQuerySelector).val() || []).join(",");
                } else {
                    value = jQuery(this.dropdownFilterJQuerySelector).val() || "";
                }
            } else {
                value = this.filterDefaultValue;
            }
        }

        if (value != "") {
            if (this.filterType == "Geography") {
                value = "&meta-15=" + value;
            }
        }

        return value;
    },

    showInteractiveChart: function () {
        jQuery('#'+this.interactiveChartContainer).attr("class", jQuery('#'+this.staticChartContainer).attr("class"));
        jQuery('#'+this.interactiveChartContainer).show();
        jQuery('#'+this.interactiveChartIframe).attr("src", this.baseInteractiveChartURL + this.getFilterQueryString() + "&ts=" + new Date().getTime());
        jQuery('#'+this.staticChartContainer).hide();
        jQuery('#'+this.interactiveChartTitle).text(this.title);
    }

}

// ===== DataChart ============================================================

var dataCharts = [];

function DataChart(id, htmlId) {
    this.id = id;
    this.htmlId = htmlId;
    this.dropdownFilterJQuerySelector = "select#datachart_" + this.htmlId + "_filter_select";
    jQuery("#datachart_" + this.htmlId + "_img").load(DataChart.prototype.onImageLoad);
}
DataChart.prototype = {
    baseImageURL: "",
    baseCsvDownloadURL: "",
    baseInteractiveChartURL: "",
    metaDataURL: "",
    title: "",

    filterEnabled: false,
    filterType: "",
    filterDefaultValue: "",
    filterDisplayEnabled: false,
    filterMultiSelectEnabled: false,

    alternativeObjectType: "",
    alternativeObjectId: 0,
    useAlternativeDownload: false,
    useAlternativeInteractive: false,

    interactiveChartContainer: DataTable.prototype.interactiveChartContainer,
    interactiveChartIframe: DataTable.prototype.interactiveChartIframe,
    staticChartContainer: DataTable.prototype.staticChartContainer,
    interactiveChartTitle: DataTable.prototype.interactiveChartTitle,

    linkURL: "",
    linkTooltip: "",

    showFooter: true,
    fadeEnabled: false,
    refreshing: false,

    toString: function () {
        return "DataChart [id:" + this.id + "]";
    },

    updateImage: function () {
        var imageSource = this.baseImageURL + this.getFilterQueryString() + "&ts=" + new Date().getTime();

        if (this.fadeEnabled) {
            jQuery("#datachart_" + this.htmlId + "_img").fadeTo("fast", 0.1,
                function () {
                    var htmlId = this.id.match(/\d+/)[0];
                    var chart = dataCharts[htmlId];
                    jQuery("#datachart_" + htmlId + "_img").attr("src", imageSource);
                }
            );
        } else {
            jQuery("#datachart_" + this.htmlId + "_img").attr("src", imageSource);
        }
    },

    updateCsvDownloadLink: function () {
        jQuery("a#datachart_" + this.htmlId + "_csv_download_link")
            .attr("href", this.baseCsvDownloadURL + this.getFilterQueryString() + "&ts=" + new Date().getTime());
    },

    onImageLoad: function () {
        var htmlId = this.id.match(/\d+/)[0];
        var chart = dataCharts[htmlId];

        jQuery("#datachart_" + htmlId + "_spinner").hide();

        if (chart.fadeEnabled) {
            jQuery("#datachart_" + htmlId + "_img").fadeTo("normal", 1.0);
        } else {
            jQuery("#datachart_" + htmlId + "_img").show();
        }

        if (chart.linkURL) {
            jQuery("#datachart_" + htmlId + "_img")
                .attr("title", chart.linkTooltip)
                .css("cursor", "pointer")
                .click(function(){ location.href = chart.linkURL });
        }

        if (chart.showFooter) {
            jQuery("#datachart_" + htmlId + "_footer").show();
        }

        if (chart.refreshing) {
            jQuery("#datachart_" + chart.htmlId + "_img").fadeOut(100).fadeIn(100).fadeOut(200).fadeIn(200).fadeOut(200).fadeIn(200);
            chart.refreshing = false;
        }
    },

    // "this" means SELECT object here!
    filterOnChange: function () {
        var htmlId = this.id.match(/\d+/)[0];
        var chart = dataCharts[htmlId];
        chart.fadeEnabled = true;
        chart.updateImage();
        chart.updateCsvDownloadLink();
    },

    showInteractiveChart: DataTable.prototype.showInteractiveChart,

    load: function () {
        this.loadMetaData();
    },

    refresh: function() {
        this.refreshing = true;
        this.load();
    },

    loadMetaData: function () {
        var ctrl = this;
        jQuery.ajax({
            url: this.metaDataURL,
            cache: false,
            dataType: "json",
            htmlId: this.htmlId,
            timeout: 15000,
            success: function (metaData) {
                var chart = dataCharts[this.htmlId];
                chart.applyMetaData(metaData);
                chart.updateImage();
                chart.updateCsvDownloadLink();
            },
            error : function (XMLHttpRequest, textStatus, errorThrown) {
                ctrl.displayErrorMessage();
            }
        });
    },


    displayErrorMessage: function() {
        jQuery("#datachart_" + this.htmlId + "_spinner").hide();
        jQuery("#datachart_" + this.htmlId)
                .append(jQuery(document.createElement('span'))
                .css({position:'relative', top:'40%'})
                .html('This chart is temporarily unavailable.<br/>' +
                      'We apologize for the inconvenience. Please try refreshing the page or <a href="mailto:appwatch@pointcarbon.com">contact us</a> if the problem persists.'));
    },

    applyMetaData: function (metaData) {
        jQuery("#datachart_" + this.htmlId + "_timestamp").text(metaData.lastUpdated);

        if (metaData.description != "") {
            jQuery("#datachart_" + this.htmlId + "_info_text").text(metaData.description);
            jQuery("#datachart_" + this.htmlId + "_info_link").parent().eq(0).show();
        }

        if (this.filterEnabled && metaData.filter) {
            if (this.filterDisplayEnabled) {
                var filter = '<select id="datachart_' + this.htmlId + '_filter_select"';
                if (this.filterMultiSelectEnabled) {
                    filter += ' multiple="multiple" size="3"';
                }
                filter += ">";

                for (i = 0; i < metaData.filter.options.length; i++) {
                    filter += '<option value="' + metaData.filter.options[i].id + '">' + metaData.filter.options[i].label + "</option>\n";
                }
                filter += "</select>";

                jQuery("#datachart_" + this.htmlId + "_filter").html(filter).show();

                var sel = jQuery("select#datachart_" + this.htmlId + "_filter_select");

                if (this.filterDefaultValue) {
                   sel.val(this.filterDefaultValue.split(/\s*,\s*/));
                }
                sel.change(this.filterOnChange);
            }
        }
    },

    getFilterQueryString: DataTable.prototype.getFilterQueryString
}

DataDownload = function (htmlId, objectId, objectType) {
    this.htmlId = htmlId;
    this.objectId = objectId;
    this.objectType = objectType;

    var link = jQuery("#datadownload_" + this.htmlId + "_link");
    link.attr("href", link.attr("href") + "&ts=" + new Date().getTime());
}

DataDownload.prototype.updateMetadata = function () {
    var metadataUrl = "/ChartServer/MetadataServletCached?&objectType=" + this.objectType.toUpperCase() +
        "&id=" + this.objectId +
        (this.date ? "&today=" + this.date : "") +
        "&timezone=" + PCAUser.timeZoneId +
        "&hours=" + PCAUser.hoursNotationId;

    jQuery.ajax({
        url: metadataUrl,
        cache: false,
        dataType: "json",
        dataDownload: this,
        success: function (metadata) {
            if (metadata.lastUpdated) {
                jQuery("#datadownload_" + this.dataDownload.htmlId + "_last_updated").append(metadata.lastUpdated);
            }
        }
    });
}

/* The goal of this hack is to support Tomahawk dataScroller
 * component in FireFox. See PC-1462
 */
function a4jDataScrollerSyncFormSubmitHack (form) {
    if (form.isSubmittingByA4J) {
        return true; // allow A4J to send form
    }

    var idclDetected = false;
    var scrollDetected = false;

    for (var i = 0; i < form.elements.length; i++) {
        var name = form.elements[i].name;
        if (name == form.name + ":_idcl") {
            idclDetected = true;
        } else if (name == form.name + ":scroll_1") {
            scroll1Detected = true;
        }
    }

    // if it looks like data scroller form submit
    if (idclDetected && scroll1Detected && form.action && form.action.indexOf("javascript:") == 0) {
        var params = {};
        params[form.id] = form.id;

        form.isSubmittingByA4J = true;
        A4J.AJAX.SubmitForm('_viewRoot', form.id, {'parameters': params, 'actionUrl': location.pathname } );
        form.isSubmittingByA4J = false;

        return false; // we already sent form
    }

    // allow form submission for non- data scroller requests
    return true;
}

MyPoint={
    onAddButtonClick: function (myPointId) {
        myPointId = myPointId.replace(/\./g,'\\\.');
        jQuery('#mypoint_spinner_add_' + myPointId).show();
    },
    onAddComplete: function (myPointId) {
        myPointId = myPointId.replace(/\./g,'\\\.');
        jQuery('#mypoint_spinner_add_' + myPointId).hide();
        jQuery('#add_btn_' + myPointId).attr('src', '/images/icons/add_to_my_point_faded.gif');
        jQuery('#add_btn_' + myPointId).parent('a').eq(0).attr('onclick','return false');
    },
    onRemoveButtonClick: function (myPointId) {
        myPointId = myPointId.replace(/\./g,'\\\.');
        jQuery('#mypoint_spinner_remove_' + myPointId).show();
    },
    onRemoveComplete: function (myPointId) {
        myPointId = myPointId.replace(/\./g,'\\\.');
        jQuery('#' + myPointId).hide('normal');
    }
}


// heartbeat to keep user session alive
jQuery(document).ready(function() {
    // the sessions are also maintained for anonymous users
    // if (jQuery('span[id=username]').length > 0)
    Heartbeat = {
        period : 2, // minutes between hearbeat pulses
        lifetime: 240, // maximum minutes to keep beating if the user stays on the same page

        startTime : new Date().getTime(),

        scheduledCallback : function() {
            // we use post to prevent caching in IE
            jQuery.post("/beat", function(response) {
                //console.log("Heartbeat: " + response);
                var caption, text;
                switch (response) {
                    case 'OK':
                        Heartbeat.scheduleNextIfNeeded();
                        break;
                    case 'NOT_LOGGED_IN':
                        if (Heartbeat.isUserLoggedIn()) {
                            caption = "Your session has expired";
                            text = 'Please try to <a href="#" onclick="location.reload();">log in</a> again.';
                            Heartbeat.displayWarning(caption, text);
                        } else {
                            Heartbeat.scheduleNextIfNeeded();
                        }
                        break;
                    case 'HIJACKED':
                        if (Heartbeat.isUserLoggedIn()) {
                            caption = "Warning: you're already logged in another browser";
                            text = 'Would you like to <a href="/hijackLogin.faces">takeover</a> your session?';
                            Heartbeat.displayWarning(caption, text);
                        } else {
                            Heartbeat.scheduleNextIfNeeded();
                        }
                        break;
                }
            });
        },

        scheduleNextIfNeeded : function() {
            var currentTime = new Date().getTime();
            //console.log("Current time " + new Date(currentTime).toUTCString() + " scheduling next beat " + new Date(currentTime + Heartbeat.period * 60000).toUTCString());
            //console.log("Will beat until " + new Date(Heartbeat.startTime + Heartbeat.lifetime * 60000).toUTCString());
            if (currentTime <= Heartbeat.startTime + Heartbeat.lifetime * 60000) {
                setTimeout(Heartbeat.scheduledCallback, Heartbeat.period * 60000);
            }
        },

        displayWarning : function(caption, text) {
            if (typeof tb_show == 'function') {
                jQuery('<div style="display: none;" id="heartbeat_warning"><div class="pad5">' + text + '</div></div>').appendTo('body');
                var url = "#TB_inline?height=50&width=400&inlineId=heartbeat_warning";
                tb_show(caption, url, null);
            } else {
                // degrade if TB is not available
                alert(caption);
            }
        },

        isUserLoggedIn : function() {
            return jQuery('span[id=username]').length > 0;
        }
    };

    Heartbeat.scheduleNextIfNeeded();
});

