0

我已经使用此模块的代码创建了一个pastebin,以防有人想要完整的源代码以供参考。

我有一张使用 D3 绘制为 SVG 图形的美国地图。每个路径绑定了多个事件监听器,但只有一个依赖于 jQuery。当地图上发生点击事件时,会创建一个 D3 工具提示

pastebin 的第 39 行

buttonTemplate : "<div id = 'tooltip_template'>" + 
            "<div class = 'county_data'></div>" +
            "<img src = '/static/images/delete.png' width = '28' height = '28' class = 'delete_logo' id = 'close_tooltip' />" +
            "<div id = 'no_client_message'></div>" +
            "<button id = 'add_prospective_market' class = 'tooltip_button'>Prospective Market</button>" +
            "<button id = 'add_market' class = 'tooltip_button'>Market County</button>" +
            "<button id = 'remove_market' class = 'tooltip_button'>Remove Market</button></div>"

作为 HTML DOM 元素。

这三个按钮每个都通过第 73 行的事件委托分配了侦听器:

$("body") 
        .on("click", "#add_market", function(){
            if (thisObj._currentCounty.color != thisObj._fillColors.market)
                marketHandler(0);
            else
                $("#no_client_message").text("Market button has been disabled");
        })
        .on("click", "#add_prospective_market", function(){
            if (thisObj._currentCounty.color != thisObj._fillColors.prospect)
                marketHandler(1);
            else
                $("#no_client_message").text("Prospective market button has been disabled");
        })
        .on("click", "#remove_market", function(){
            marketHandler(2);
        })

我在第 211 行定义了处理函数

//executes ajax post request to add a new client-county relationship.  Type is 0 for
//new market, 1 for new prospective market and 2 for remove this client-county relationship
var marketHandler = function(type){
    $.ajax({
        url : "marketHandler/",
        type : "POST",
        data : {"data" : JSON.stringify({
                            "client" : thisObj._currentClient.id,
                            "county" : thisObj._currentCounty.id,
                            "type" : type
                        })
                },
        dataType : "json",
        success : function(results){
            if (results.success == "true"){

            /*
                console.log("Market handler type: " + type);

                var fillColor = "";

                if (type == 0)
                    fillColor = thisObj._fillColors.market;

                else if (type == 1)
                    fillColor = thisObj._fillColors.prospect;

                else
                    fillColor = thisObj._fillColors.neutral;

                d3.selectAll($("#" + thisObj._currentCounty.id))
                    .style("fill", fillColor);

                closeTooltipHandler();
            */
                //hack to get the fill color change to apply.  There is some conflict going
                //on between the jquery and d3 event handlers.  While the function executes,
                //the change of the fill is not applied on success.
                thisObj._clientSelect.trigger("change");
            } else
                alert(results.message);
        }
    })
}

我的问题是,当 Ajax 函数成功并且满足results.success == "true"条件时,颜色更改通常通过

d3.selectAll($("#" + thisObj._currentCounty.id))
  .style("fill", fillColor);

永远不会应用于地图。相反,我此时唯一的解决方案是在视图的下拉列表中触发更改事件。虽然这可行,但它不必要地复杂,因为它只需要获取冗余数据来执行重新着色操作。

本来以为是嵌套在Ajax函数里面,所以把success函数改成

var fillColor = "";
var colorChange = false;

$.ajax({
  ...
  ...
  success : function(results) {
    if (results.success == "true){
      colorChange = true;

      //get fillColor hex value
    }
  }
});

if (colorChange){
  d3.selectAll($("#" + thisObj._currentCounty.id))
    .style("fill", fillColor);
}

但这也不起作用。

4

1 回答 1

0

正如评论中所建议的那样,这确实是一个范围界定问题,我通过在成功回调中使用匿名函数来解决它。我的成功处理程序现在是

success : function(results){
  if (results.success == "true"){

    if (type == 0)
      fillColor = thisObj._fillColors.market;

    else if (type == 1)
      fillColor = thisObj._fillColors.prospect;

    else
      fillColor = thisObj._fillColors.neutral;

    closeTooltipHandler();

    //need anonymous function to resolve scope issue between D3 and jQuery
    (function(thisObj, fillColor){
      d3.selectAll($("#" + thisObj._currentCounty.id))
        .style("fill", fillColor)
    })(thisObj, fillColor);

  } else
    alert(results.message);
}
于 2013-09-27T12:11:51.320 回答