强制谷歌InfoWindow重绘自己或刷新其内容

时间:2013-10-24 20:16:53

标签: javascript jquery google-maps-api-3 google-fusion-tables

如何强制谷歌重绘其infoWindow或至少刷新其内容? 我注意到我必须在标记上单击两次才能在infoWindow中出现正确的数据 - 这时我的闭包是罪魁祸首。

    var markers = new Array();
    var allMarkers = new Array();
    var infoWindow = new google.maps.InfoWindow();
    var infoWindows = new Array();

    // IE caches ajax request - need a way to clear cache with each fetch of data
    randomize = function () {
        var randomnumber = Math.floor(Math.random() * 100000);
        return randomnumber;
    }

    function getBeachLocations() {
        // construct query
        var queryURL = "https://www.googleapis.com/fusiontables/v1/query?sql=";
        var queryTail = "&key=apiKey&callback=?";
        var query = "SELECT * FROM BeachTable"; // beach locations tbl
        var queryText = encodeURI(query);

        $.ajax({
            type: "GET",
            url: queryURL + queryText + queryTail,
            cache: false,
            dataType: 'jsonp',
            success: createMarkers,
            error: function () {
                alert("Sorry, no spatial data is available at this time, please check back on a later date.");
            }

        });
    } //end getBeachLocations


    function createMarkers(data) { // =====================create markers

        url = "http://swim.jpg";
        var rows = data['rows'];
        var ecoli_rows;
        var algae_rows;



        for (var m in rows) {

            var ecoli_array = new Array();
            var marker = new google.maps.Marker({
                map: map,
                icon: new google.maps.MarkerImage(url),
                beach_id: rows[m][0],
                beach_name: rows[m][1],
                beach_region: rows[m][2],
                position: new google.maps.LatLng(rows[m][4], rows[m][5]),
                idx: m,
                getHeader: function () {
                    var str = [
                        '<div style="width:650px;">',
                            '<div class="tabs">',
                                '<ul>',
                                    '<li><a href="#tab-1" class="ecoli_tab"><span>E. Coli Data</span></a></li>',
                                    '<li><a href="#tab-2" class="algae_data"><span>Algae Data</span></a></li>',
                                '</ul>',
                                '<div id="tab-1">',
                                '<h1>' + this.beach_name + '</h1>',
                                '<h3>' + this.beach_region + '</h3>'

                    ].join('');
                    return str;
                }, // end getHeader method

                getEcoliData: function () { // begin getEcoliData
                    var obj;
                    obj = getEcoliData(this.beach_id);
                    return obj;
                }, // end getEcoliData method

                afterGetEcoliData: function (data) {

                    var ecoli_rows;
                    var ecoli_rows_str;

                    ecoli_rows = data['rows'];

                    var ecoli_rows_str = [
                        '<table id="ecoli_table " class="data" style="width:500px;">',
                        '<tr>',
                            '<th>Sample Date</th>',
                            '<th>Average E. coli Density <br/> (200 cfu/100 ml)</th>',
                            '<th>Recreational Water Quality Guideline</th>',
                        '</tr>'
                    ].join('');

                    if (typeof ecoli_rows == 'undefined') {
                        ecoli_rows_str = '<p>Sorry no ecoli data currently exists for this beach.</p></div>'
                    } else {

                        for (var i = 0; i < ecoli_rows.length; i++) {
                            //console.log(rows[i]);
                            ecoli_rows_str += '<tr><td>' + formatDate(ecoli_rows[i][2]) + '</td><td>' + checkEcoliCount(ecoli_rows[i][3]) + '</td><td>' + ecoli_rows[i][4] + '</td></tr>';
                        }
                        ecoli_rows_str += '</table>'
                        ecoli_rows_str += '</div>';

                        // remove after test
                        ecoli_rows_str += '<div id="tab-2"><h1>nothing loaded</h1></div></div></div>';
                    } //end if
                    return ecoli_rows_str;
                }, // end outPutEcoliData method

                getAlgaeData: function () { // begin getAlgaeData
                    var obj;

                    var algae_rows_str = [
                          '<div id="tab-2">',
                         '<h1>' + this.beach_name + '</h1>',
                         '<h3>' + this.beach_region + '</h3>',
                         '<table id="algae_table " class="data" style="width:500px;">',
                        '<tr>',
                            '<th>Sample Date</th>',
                            '<th>Algal Toxin Microcystin <br/> (20 ug/L)</th>',
                            '<th>Recreational Water Quality Guideline</th>',
                             '<th>Blue Green Algae Cells <br/>(100,000 cells/ml)</th>',
                            '<th>Recreational Water Quality Guideline</th>',
                        '</tr>'
                    ].join('');

                    obj = getAlgaeData(this.beach_id);
                    return obj;


                }, // end getAlgaeData method

                outPutAlgaeData: function (data) {
                    obj.done(function (data) {
                        algae_rows = data['rows'];
                    }); // end success


                    //console.log(algae_rows);

                    if (typeof algae_rows === 'undefined') {
                        algae_rows_str = [
                             '<div id="tab-2">',
                                 '<h1>' + this.beach_name + '</h1>',
                                 '<h3>' + this.beach_region + '</h3>',
                                '<p>Sorry no algae data exists for this beach.</p>',
                            '</div>',
                            '</div>',
                            '</div>',
                            '</div>'
                        ].join('');
                    } else {

                        for (var i = 0; i < algae_rows.length; i++) {
                            //console.log(rows[i]);
                            algae_rows_str += '<tr><td>' + formatDate(algae_rows[i][2]) + '</td><td>' + checkAlgaeToxinCount(algae_rows[i][3]) + '</td><td>' + algae_rows[i][4] + '</td><td>' + checkAlgaeCount(algae_rows[i][5]) + '</td><td>' + algae_rows[i][6] + '</td></tr>';
                        }
                        algae_rows_str += '</table>'
                        algae_rows_str += '</div></div></div>';
                        //return algae_rows_str;

                    } //end if
                    return algae_rows_str;
                } // end outPutAlgaeData

            });       // ====================end marker

            allMarkers.push(marker); //required for drop down menu

            console.log(marker.beach_id + " "  + marker.beach_name);



             // click event handler
            google.maps.event.addListener(marker, 'click', function () {
                var ajaxObj = this.getEcoliData();
                var marker = this;
                var str;

                // add loading gif
                //infoWindow.setContent('<img src="../img/loading.gif" alt="loading data"/>');

                ajaxObj.done(function (data) {

                    /*
                    str = marker.getHeader() + marker.afterGetEcoliData(data);
                    console.log(str);
                    */

                    infoWindow.setContent(marker.getHeader() + '' + marker.afterGetEcoliData(data));
                    infoWindow.open(map, this);

                    $(".tabs").tabs({ selected: 0 });
                }); // End done
            }); // End click event handler



        } // end for loop foreach marker

        checkAdvisory(); // determine where this needs to be called from.
    } //end function createMarkers

    // format date as January 1, 2013
    function formatDate(num) {
        var d = Date.parse(num).toString('MMMM d, yyyy');
        return d;

    }

    // check ecoli count - anything greater than or equal to 200 cfu/100ml is flagged
    function checkEcoliCount(num) {
        var str;
        num = parseFloat(num);
        if (num >= 200) {
            str = '<span class="ecoliCount_on" style="color:orange"><b>' + num + '</b></span>';
        } else {
            return num;
        }
        return str;
    }

    // check blue green algae count - anything greater than or equal to 100,000 cells/ml is flagged 
    function checkAlgaeCount(num) {
        var str;
        num = parseFloat(num);

        if (num >= 100000) {
            str = '<span class="algaeCount_on" style="color:orange"><b>' + num + '</b></span>';
        } else {
            return num;
        }
        return str;
    }

    // check algae toxin microcystin - anything greater than or equal to 20 ug/L is flagged
    function checkAlgaeToxinCount(num) {
        // why include < ? - ask Cassie
        var str;
        var idx;

        idx = num.indexOf("<");

        num = num.substring(idx + 1);

        num = parseFloat(num);

        if (num >= 20) {
            str = '<span class="algaeToxinCountOn" style="color:orange"><br>' + num + '</b></span>';
        } else {
            return num;
        }
        return str;
    }

    function checkAdvisory() {
        /* add advisory images
        ecoliCount_on
        algaeCount_on
        algaeToxinCountOn
        */
        $(".ecoliCount_on").each(function (i, v) {
            console.log(i, v);
            $(this).css("color", "green");
        });
        $(".algaeCount_on").each(function (i, v) {
            console.log(i, v);
            $(this).css("color", "green");
        });
        $(".algaeToxinCountOn").each(function (i, v) {
            console.log(i, v);
            $(this).css("color", "green");
        });
    }

    function getEcoliData(beach_id) {
        //console.log(beach_id);
        var rows;

        var queryURL = "https://www.googleapis.com/fusiontables/v1/query?sql=";
        var queryTail = '&key=apiKey&callback=?';
        var whereClause = "WHERE 'Beach_ID' = " + beach_id;
        var query = "SELECT * FROM EcoliTable "
        + whereClause + " ORDER BY 'Sample_Date' DESC";


        var queryText = encodeURI(query);

        var ecoli_array = new Array();

        return $.ajax({
            type: "GET",
            url: queryURL + queryText + queryTail,
            cache: false,
            dataType: 'jsonp'
        });
    }

    function getAlgaeData(beach_id) {

        var queryURL = "https://www.googleapis.com/fusiontables/v1/query?sql=";
        var queryTail = '&key=apiKey&callback=?';
        var whereClause = " WHERE 'Beach_ID' = " + beach_id;
        var query = "SELECT * FROM algaeTable "
        + whereClause + " ORDER BY 'Sample_Date' DESC";

        var queryText = encodeURI(query);

        // ecoli request
        return $.ajax({
            type: "GET",
            url: queryURL + queryText + queryTail,
            cache: false,
            dataType: 'jsonp'     
        });
    }


    // create beach locations dropdown
    function createDropDownMenu() {

        var query = 'SELECT Beach_Location, Beach_ID  FROM      beachTable ORDER BY Beach_Location ASC';

        var queryText = encodeURIComponent(query);
        var gvizQuery = new google.visualization.Query(
                                        'http://www.google.com/fusiontables/gvizdata?tq=' + queryText);

        //Send query and draw table with data in response
        gvizQuery.send(function (response) {
            var numRows = response.getDataTable().getNumberOfRows();
            var numCols = response.getDataTable().getNumberOfColumns();

            var name = ['<label style="font-weight:bolder;font-size:16px"> Select a Beach:</label><select id="beach_menu"  style="font-size:16px;" onchange="select_beach(this.options[this.selectedIndex].value);"><option class="defaultopt" value="">--All--</option>'];

            for (var i = 0; i < numRows; i++) {

                var nameValue = response.getDataTable().getValue(i, 0);
                var idValue = response.getDataTable().getValue(i, 1);




                name.push("<option value=" + "'" + idValue + "'" + ">" + nameValue + "</option>");

            }
            name.push('</select>');

            document.getElementById('beach_location_dropdown').innerHTML = name.join('');
        });

    } // end createDropDownMenu Function

    function select_beach(val) {
        $("#beach_menu option[value='" + val + "']").attr('selected', 'selected');
        if (val === "") {
            resetMapExtent();
            displayAllBeaches();
        }
        else {
            update_layer(val)
        }
    } // end select_beach function 

    function resetMapExtent() {
        google.maps.event.trigger(map, "resize");
        map.setCenter(new google.maps.LatLng(53.760861, -98.813876));
        map.setZoom(5);
    } // end resetMapExtent function

    // implement update_layer function
    function update_layer(beach) {
        infoWindow.close();
        for (var z = 0; z < allMarkers.length; z++) {
            if (beach === allMarkers[z].beach_id) {
                allMarkers[z].setVisible(true);
            } else {
                // hide all other markers
                allMarkers[z].setVisible(false);
            }
        }
    } // end update_layer function 

    function displayAllBeaches() {
        infoWindow.close();
        // show all markers
        for (var z = 0; z < allMarkers.length; z++) {
            // hide all markers
            allMarkers[z].setVisible(true);
        }
    } // end displayAllBeaches


    /* start map initialization  */
    function initialize() {


        // map
        latlng = new google.maps.LatLng(49.894634, -97.119141);
        var myOptions = {
            center: latlng,
            zoom: 7,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            zoomControlOptions: {
                style: google.maps.ZoomControlStyle.SMALL
            },
            mapTypeControl: true,
            mapTypeControlOptions: {
                mapTypeIds: [
                                                google.maps.MapTypeId.ROADMAP,
                                                google.maps.MapTypeId.SATELLITE,
                                                google.maps.MapTypeId.HYBRID,
                                                google.maps.MapTypeId.TERRAIN
                                            ],

                style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
            },
            overviewMapControl: true,
            overviewMapControlOptions: {
                opened: true
            }
        };

        map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);


        // invocation begins here
        createDropDownMenu(); // not working now.
        getBeachLocations();




        // legend
        map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(
            document.getElementById('legend'));

        var legend = document.getElementById('legend');
        var swim_icon = "swim.jpg";


        var div = document.createElement('div');
        div.innerHTML = '<h4>Features</h4>' +
                                        '<br/><img src="' + swim_icon + '"> ' + "Beaches";
        legend.appendChild(div);

    } // end initialization function

    $(function () {
        $('.view_normal').live('click', function () {
            $(".container").css("width", "930px").css("margin", "auto");
            $(".onewidecenter").css("width", "930px").css("margin", "auto");
            $("#map_canvas").css("width", "930px").css("margin", "auto");
            google.maps.event.trigger(map, "resize");
            map.setCenter(new google.maps.LatLng(53.760861, -98.813876));
            map.setZoom(5);

        });
        $('.view_full_screen').live('click', function () {
            $(".container").css("width", "100%").css("margin", "auto");
            $(".onewidecenter").css("width", "100%").css("margin", "auto");
            $("#map_canvas").css("width", "100%").css("margin", "auto");
            $(" #dropdown_container").css("width", "100%").css("margin", "auto");
            google.maps.event.trigger(map, "resize");
            map.setCenter(new google.maps.LatLng(53.760861, -98.813876));
            map.setZoom(5);
        });
    }); // end page load

我已经包含了上面的示例代码。请特别注意我的点击事件处理程序。一如既往,非常感谢有关如何最好地解决这个问题的建议。

提前致谢, 迈克尔

2 个答案:

答案 0 :(得分:2)

jQuery AJAX方法是异步的。这意味着:

obj.success(function (data) {
  ecoli_rows = data['rows'];
}); // end sucess

立即返回,但在ajax请求完成之前,回调函数不会运行。

这意味着:

infoWindow.setContent(this.getHeader() + '' +
    this.getEcoliData() + '' + this.getAlgaeData());
infoWindow.open(map, this); //ajax callback hasn't fired here

在ajax请求完成之前打开包含内容的信息窗口。

要纠正,您可能会这样做:

在marker.getEcoliData中:

obj = getEcoliData(this.beach_id);
return obj;
// move processing below this point to new method

在点击事件处理程序中:

google.maps.event.addListener(marker, 'click', function () {
  var ajaxObj = this.getEcoliData();
  var marker = this;
  ajaxObj.done(function() {
    infoWindow.setContent(marker.getHeader() + '' +
        marker.afterGetEcoliData() + '' +
        this.getAlgaeData());
    infoWindow.open(map, this);
    $(".tabs").tabs({ selected: 0 });
  });

由于您发生了两次异步调用,因此这不是一个完整的解决方案。你可以链接它们,或设置某种计数器以确保只在两者都完成时才执行回调。

更好的方法是立即用某种信息打开信息窗口,告诉用户正在加载数据。然后在请求完成后,您只需再次更新infowindow内容(使用内容元素的句柄)以显示返回的数据。

答案 1 :(得分:0)

感谢您的帮助。我设法让这个按预期工作。事实证明,我必须重新构建标记类,以便不再返回两个ajax请求。