Google Map API - 无法删除for循环中的标记

时间:2013-09-30 13:15:58

标签: javascript google-maps google-maps-api-3 for-loop

我使用JSON数据填充了Google地图,我有一个复选框来选择要在地图上显示的数据类别。 当我点击复选框时,它通过Ajax调用一个新的JSON数据,当我取消选中一个框时,它会循环显示所有标记的数组,并删除所有未选中类别的标记。

它大部分时间都有效,但有时标记会消失并再次出现。似乎他们仍然在阵列或其他东西......

$( "input[type=checkbox]" ).change(function() {
        var data ='';
        var checkbox = $(this);
        var checkboxVal = $(this).val();
        console.log('click');

        if (checkbox.is(':checked')) {
            $('.loader').show();

            $("input:checkbox[name=poi_categories]:checked").each(function() {
                data = data + checkboxVal + ',';
                $.ajax({
                    type: "POST",
                    url: window.location.pathname,
                    data: "categorie=" + data,
                    success:function(response){

                        json = JSON.parse(response);

                        for (var i = 0; i < json.length; i++) {
                            createMarker(json[i], data);
                        }
                        $('.loader').hide();
                    }
                });
            });
        } else {

            for (var i in markersArray) {
                if ( markersArray[i] != undefined) {
                    if( null == markersArray[i].cat || markersArray[i].cat == checkboxVal) {
                        markersArray[i].setMap(null);
                        delete(markersArray[i]);
                    }
                }
            }
        } 
    });

我很确定在最后一个for循环中有一个错误,但我看不出...

编辑:

以下是整个Js代码:http://jsfiddle.net/5bMQm/

3 个答案:

答案 0 :(得分:1)

编辑:我理解你现在要做的事情。

for (var i = 0, l = markersArray.length; i < l; i++) {
  if ( markersArray[i] != undefined) {
    if( null == markersArray[i].cat || markersArray[i].cat == checkboxVal) {
      markersArray[i].setMap(null);
      markersArray.splice(i, 1);
      i--; l--;
    }
  }
}

答案 1 :(得分:1)

完全误解了。每次用户单击复选框时,您都会多次执行此操作 - 这也是您要从markersArray中删除从地图中删除的标记的原因。

认为我找到了潜在的问题。

你有

createMarker(json[i], data);

但仅

function createMarker(marker) {

你设置

cat : marker.img

但与

比较
markersArray[i].cat == checkboxVal

你假设(我猜)应该包含

var checkboxVal = $(this).val();
..
data = data + checkboxVal + ',';

但永远不会! 数据/复选框永远不会分配给您的标记!


for (var i in markersArray) {
    if ( markersArray[i] != undefined) {
        if( null == markersArray[i].cat || markersArray[i].cat == checkboxVal) {
            markersArray[i].setMap(null);
            markersArray[i] = undefined; // <---
        }
    }
}
//cleanup
for (var i=markersArray.length;i>0;i--) {
    if (markersArray[i]==undefined]) {
        markersArray.splice(i, 1);
    }
}

答案 2 :(得分:0)

它大部分时间都有效,但有时标记会消失并再次出现。似乎他们仍然在数组或其他东西

当所有内容按预期工作时,您的代码正如预期的那样对我有用。

但是问题(假设您的服务器端脚本的返回响应总是正确的):

你不能指望AJAX响应按照它们发出的顺序到达(有时单个请求可能会有很大的延迟)。它可以是例如发生在你身上。

  1. 点击一个框进行检查
  2. 再次点击该框取消选中
  3. 当响应按相反顺序到达时,您将创建标记,尽管当前未选中该框。

    可能的解决方案:(但有一个更好的解决方案,见下文)

    createMarker

    的开头添加额外检查
    if(!$('input[type="checkbox"][name="poi_categories"][value="'+marker.img+'"]').is(':checked'))return;
    

    另一个问题:您的脚本中似乎有一个reduntant部分,

    $("input:checkbox[name=poi_categories]:checked").each(function() {
      /*ajax-code*/
    });
    

    这对我没有任何意义,假设您已选中5个复选框,而最后点击的复选框的值为例如“酒店”,您将发送categories=hotel,hotel,hotel,hotel,hotel,我认为您的服务器端脚本不会返回任何标记。您根本不需要遍历已检查的标记。

    这应该足够了:

    if (checkbox.is(':checked')) {
                    $('.loader').show();
    
                        $.ajax({
                            type: "POST",
                            url: window.location.pathname,
                            data: "categorie=" + checkboxVal,
                            success:function(response){
    
                                json = JSON.parse(response);
    
                                for (var i = 0; i < json.length; i++) {
                                    createMarker(json[i], data);
                                }
    
                                $('.loader').hide();
                            }
                        });
    
                }
    

    这是避免重大问题的更好解决方案的一个好点。不是在创建标记之前检查复选框的checked属性,而是最好中止最近的请求:

        var checkbox = $(this);
        var checkboxVal = $(this).val();
        console.log('click');
        //if there has been a recent request, abort it
        if(checkbox.data('xhr')){
            checkbox.data('xhr').abort();console.log('recent request aborted');
        }
        if (checkbox.is(':checked')) {
            $('.loader').show();
    
                data = data + checkboxVal + ',';
                //store the jqXhr within the checkbox-data
                //to be able to abort it later
                checkbox.data('xhr',$.ajax({
                    type: "POST",
                    url: window.location.pathname,
                    data: "categorie=" + checkboxVal,
                    success:function(response){
    
                        json = JSON.parse(response);
    
                        for (var i = 0; i < json.length; i++) {
                            createMarker(json[i], data);
                        }
    
                        $('.loader').hide();
                    }
                }));
    
        } else {/* your code*/}