0
votes

I have a polygon on a SVG object made by d3. When clicked on, a 'bootstrap popover' with two buttons opens up. I want to be able to click on the links and transform the polygon (the ultimate goal is to draw a circle on top of the polygon). For now, the main problem is that I cannot select the polygon and change its attributes. Here is my code:

  // create an svg element and append it
  canvas = d3.select("#map")
    .append("svg")
      .attr("width", 500)
      .attr("height", 500)
      .attr("id", "firstFloor");

  // draw polygon
  var coverageAreaIDA1 = 'roomA1';
  var content = '<button id="view" class="btn btn-sm btn-primary view-cam-btn">View Camera</button> <button id="set" class="btn btn-sm btn-primary set-dest-btn">Set Destination</button> <input type="hidden" name="coverage-area-id" value="'+coverageAreaIDA1+'">';
  var polygonA1 = [[65, 215], [65, 250], [140, 250], [140, 215]];
  var roomA1 = canvas.append("polygon")
    .attr("points", polygonA1)
    .attr("class", "coverage-area")
    .attr("id", coverageAreaIDA1)
    .attr("data-toggle", "popover")
    .attr('data-placement', 'top')
    .attr("data-content", content)
    .attr("tabindex", "0")
    .attr("data-trigger", "focus");

I have tried many methods, the closest I've got so far is selecting the button on the popover with its value (which is the same as the polygons id), putting it in a var, and using d3 to select the polygon, like the code below.

function badGuy() {
  $(document).on('click', '.view-cam-btn', function(){
    var coverageAreaID = $(this).nextAll('input').eq(0).val();
    var selection = canvas.select("#" + coverageAreaID).styles("fill", "purple");
    console.log('Selected polygon has ID '+selection.attrs('id'));
    });
}

I know that 'selection' is not empty or null because when I test its truthiness it returns true, but the above console.log returns "Selected polygon has ID [object Object]" and does NOT change polygon's style.

PS: if you're wondering why I'm using attrs instead of attr and styles instead of style, by looking at many questions/answers on StackOverflow, I figured I should add this library

<script src="https://d3js.org/d3-selection-multi.v0.4.min.js"></script>

and use attrs and styles. Before that, console.log was not returning anything.

Edit: Full code: https://codepen.io/navidfalla/pen/xrpzXE

1
I think I can help you but would be appreciated if you can provide your HTML and full JS code. - Fered
Here is the full code: codepen.io/navidfalla/pen/xrpzXE It's hundreds of lines of code, so I tried to make it as simple as possible. but you can see the polygons that I'm talking about on the right, if you click on them there is a popover, and I need to select the buttons inside the popovers. - Navid Falla

1 Answers

1
votes

Thanks for codes.. Well I made some modifications and please try and see if this is what you were looking for :

1 - please change your createPopover method to this :

function createPopover(roomId) {
     var content = '<button id="view" data-room-id="'+roomId+'" class="btn btn-sm btn-primary view-cam-btn">View Camera</button>'+
                   '<button id="set" data-room-id="'+roomId+'" class="btn btn-sm btn-primary set-dest-btn">Set Destination</button> ';
     return content;
}

this allows you to easily get ID of clicked polygon by data-room-id or $(selector).data('roomId');

2 - please change your click event handler on Set Destination button to :

$(document).on('click', '.set-dest-btn', function(){
    //var coverageAreaID = $(this).nextAll('input').eq(0).val();
    //console.log('set dest button has parent ID: '+coverageAreaID);

    var roomId = $(this).data('roomId'); 
    var polygon = d3.select('polygon#'+roomId);
    // do you stuff here with polygon
    polygon.style('fill','white'); 
  });

as you can see you have now access to the polygon.

and for a better understanding of your code I had to clean it a little , you can see if you like it. instead of creating rooms that way I created a method for room creation :

function createRoom(number,polygon){
  var roomId = 'room'+number;
  var content = createPopover(roomId); 
  var room  = canvas.append("polygon")
    .attr("points", polygon)
    .attr("class", "coverage-area")
    .attr("id", roomId)
    .attr("data-toggle", "popover")
    .attr('data-placement', 'top')
    .attr("data-content", content)
    .attr("tabindex", "0")
    .attr("data-trigger", "focus");
    return room;
} 

and then create rooms this way :

// draw polygon over stairwell
  var roomA1 = createRoom('A1',[[65, 215], [65, 250], [140, 250], [140, 215]]);
  var roomA2 = createRoom('A2',[[140, 215], [140, 278], [230, 278], [230, 215]]);
  var roomA3 = createRoom('A3',[[230, 215], [230, 278], [320, 278], [320, 215]]);
  var roomA4 = createRoom('A4',[[320, 215], [320, 278], [400, 278], [400, 215]]);
  var roomA5 = createRoom('A5',[[65, 250], [65, 278], [140, 278], [140, 250]]);
  var roomA6 = createRoom('A6',[[42, 215], [42, 278], [65, 278], [65, 215]]);
  var roomA7 = createRoom('A7',[[332, 120], [332, 215], [355, 215], [355, 120]]);
  var roomA8 = createRoom('A8',[[302, 120], [302, 215], [332, 215], [332, 120]]); 
  var roomA9 = createRoom('A9',[[302, 99], [302, 120], [355, 120], [355, 99]]);
  var roomA9 = createRoom('A10',[[408, 215], [408, 278], [462, 278], [462, 215]]);

please try this and see if this is what you were looking for or I misunderstood :)

Hope it helps