1

I have a map drawn in CorelDRAW that shows the location of some company assets. Each one in shown as a square on the map. My aim is to create an interactive version of the map, where the user can click on a square and be shown more information about the asset.

CorelDRAW allows me to specify a name for each shape. Then, if the diagram is exported as an SVG, the shape names are used for the id attributes.

This gives me a map in SVG format; let's say it looks like this:

<svg width="100" height="100">
    <rect id="firstAsset" x="25" y="50" width="20" height="20" />
    <rect id="secondAsset" x="50" y="15" width="20" height="20" />
</svg>

I want to be able to click on each rectangle and have information displayed about it. A popup would do, such as this example at w3cschools, or a modal box if there's more information to display.

So, I've started by embedding a test svg in an html document. This doesn't mean it will end up on a web server; the file may just end up saved on a SharePoint. Ideally it would end up a single file that can be distributed by email if need be.

Here is what I have so far, using modal boxes: link to js fiddle.

The problem is, the full SVG is going to have dozens more clickable shapes, and if the map is updated in CorelDRAW, I will have to add the onclick() and class attributes to each shape all over again. I need to be able to take information about each asset in some standard format, and then have it automatically added to each asset in the SVG.

I originally envisioned writing a script that would take the SVG file and a file with the information to display. It would search the SVG for id attributes, check for corresponding information to display, and if so make the element clickable to display that information. This is where I'm stuck. Do I need to write a separate program just to maintain this map? Or could this be done using javascript in the document itself?

To recap, I have:

  • An automatically generated SVG with id attributes against each asset
  • I will have some information about each asset, which I can put in html format

and I want to be able to click on an asset on the map and show the information about it.

P.S. I'm new to html and javascript.

William
  • 191
  • 8
  • You dont' have to attach events individually. You can simply do that by querying the dom elements and attaching the events via js directly. – Aslam May 24 '17 at 10:42
  • 2
    Please try not to learn from w3schools. (BTW that's one of the worst tooltip example I've seen in my life (ya, BTW it's called **tooltip**) - it's not modular reusable... terrible overall.) – Roko C. Buljan May 24 '17 at 10:45

3 Answers3

0

This code example might help you a bit to get started.

var rect = document.querySelectorAll('rect');

rect.forEach(item=>{  
  item.addEventListener('click', tooltip);
});

function tooltip(){
  console.log(this.id);
}
Aslam
  • 9,204
  • 4
  • 35
  • 51
  • I've adopted your suggestion and [updated the js fiddle](https://jsfiddle.net/William_Foulkes/10cux7vy/8/).The issue is that – William May 24 '17 at 12:17
  • 1
    ...currently it adds an event listener to every rectangle indiscriminately, and colours and mouseover effect are lost. Can I attach classes (for the stylesheet) in the same way, and can I do it selectively to shapes by id attribute? – William May 24 '17 at 12:25
  • I think I've found the [answer to that.](https://stackoverflow.com/questions/507138/how-do-i-add-a-class-to-a-given-element) Thanks. – William May 24 '17 at 12:32
0

I have tweaked your fiddle a little please look

  $(function () {
    $( "#redButtons,#blueButtons" ).on( "click", "rect", function() {
       //alert(this.id);
       $( "#theInfo" ).html(data[this.id]);
       $( "#modal" ).show();
       event.stopPropagation();
    });

  $( "#close,body" ).on( "click", function() {
       $( "#modal" ).hide();
    });
})

I believe jQuery will help some. jsFiddle somehow support it, but you can embed jquery if you want a single file, or link it from separate file or internet.

Victor K.
  • 25
  • 7
0

The solution I have is in this js fiddle. It uses pure javascript, and the svg can be pasted in unmodified from the graphics application.

Data about each asset is stored in div tags like this:

  <!--Information about each asset, that is added to the modal before it's displayed -->
  <div id="html_asset1" class="hiddenInfo" data-asset="asset1" data-category="redCategory">
    <p>This is some information about asset one.</p>
  </div>

The id attribute has to be the same as the corresponding shape in the svg prepended with "html_". The class "hiddenInfo" hides the data. There are two custom attributes. The first is the id attribute of the corresponding shape. The second is just a the name of a class that will be applied to the shape to set the colour.

I then have a little javascript that gets each div element like the above, and uses the custom attributes I just mentioned to turn the corresponding shapes into buttons:

var hiddenInfo = document.getElementsByClassName('hiddenInfo');
var eachAsset;
for (i = 0; i < hiddenInfo.length; i++) {
  eachAsset = document.getElementById(hiddenInfo[i].dataset.asset);
  eachAsset.className.baseVal += " button " + hiddenInfo[i].dataset.category;
  eachAsset.addEventListener('click', displayModal);
}

When any button is clicked, the contents of the modal window is set to the hidden information:

//Populate the information in the modal and then make it visible
function displayModal() {
  var hiddenHTMLid = "html_" + this.id
  //use the hidden HTML to populate the modal
  document.getElementById("theInfo").innerHTML = document.getElementById(hiddenHTMLid).innerHTML;
  modal.style.display = "block";
}

Overall it works nicely and keeps the data separate from how it is displayed, which I like.

Thanks for the help.

William
  • 191
  • 8