Approach to place results of a php script inside a div (without jQuery)

I am making a system in which you can place plants on a map. I made a pen that shows what the user will see: https://codepen.io/dcslob/pen/vYxBMdp The actual map image is missing, but you will get the point.

If you click one one of these pins

<div id='25' class='specimen size_20' [...] data-species='Agastache mexicana'>a</div>

this div will appear on top of it:

<div id='description'>I should be PHP/mysql generated text!</div>

I'd like to put some text from the database in this div, based on the id of the plant. However, I am unsure about the way to proceed with this. These are my options:

  1. I could preset a separate hidden description div for each species on the map when I generate the page. That would add a lot of data if somebody uses 100+ species on a map. It would be pretty responsive, though.
  2. I could make an ajax request that javascript uses to set the content of the description div whenever it is activated.
  3. One of you has a far more cunning plan.

This is not a request for a copy/paste solution (I wouldn't mind it, though), I'd like an opinion about the direction I should be looking in, preferably with some examples. I am trying to learn as much as possible from this project, which is why I don't want to use libraries if I can do it myself.

I hope this isn't too wordy, I find it hard to be concise about things I am not sure of myself. Thanks in advance!

3 answers

  • answered 2021-05-05 11:12 Alexis

    I guess when you're displaying your pins, you're getting them from somewhere, like a DB, or a JSON file.

    If it's the case, you can display all pins with a foreach instruction.

    foreach ($pins as $p){
      echo "<div id='25' class='specimen size_20' data-species='Agastache mexicana'>a</div>";
      echo "<div id='description'>Description</div>";
    } 
    

    But to make the pop-up appear/disappear, the ID must be unique. With the solution provided above, a conflict is generated (multiple time the same description id). So let's change the code snippet by this one below:

    foreach ($pins as $p){
      echo "<div id='id' class='specimen size_20' data-species='Agastache mexicana'>".$p['name']."</div>";
      echo "<div id='description_id' class='description' >".$p['description']."</div>";
    }
    

    We have to change the JS file to get a proper result.

    document.addEventListener("click", onClick);
    
    function onClick(){
    var className = event.target.className;
    var id = event.target.id;
        
     if( className.includes("specimen") ){   
       var popup   = document.getElementById('description_'+id);  
       var map     = document.getElementById('bordermap');  
       var rect    = map.getBoundingClientRect();
       var x       = event.clientX - rect.left;
       var y       = event.clientY - rect.top;
      
        
        popup.style.display = "grid";     
        popup.style.left = x+"px";            
        popup.style.top  = y+"px"; 
     }   
    }
    

    With this, I'm getting the ID attribute to pass it to the popup, so it can be opened.

    I also added the class description so in the css file, it can be hidden

    Here is a link to try the code: replit: try the code

    So how can you retrieve data ?

    You can use AJAX and then instead of a PHP array, use a JS one. Or you can use PHP as I did.

  • answered 2021-05-05 12:02 MeathCoder

    I would go with option number 2:

    I could make an ajax request that javascript uses to set the content of the description div whenever it is activated.

    If the response is a little slow you can always add a loader wheel so the user knows something is going on behind the scenes.

    Option number 1 is also a fine approach here but less scalable in general for bigger cases. Also a user will unlikely click on every single case (100+ cases) and in a situation like this I prefer to just retrieve what I need when I need it.

  • answered 2021-05-05 19:29 Diederik Slob

    This is the answer to my question, based on the input I got from you fine people.

    I will ignore the description.php file, that's just reading stuff from the database and printing some simple html.

    So clicking one of these divs

    <div id='78' class='specimen size_20' style='top:334px; left:577px; background-color:rgba(238,130,238,0.5); border-color:rgba(238,130,238,1);' data-sp_nm='Agastache mexicana' data-sp_id='5'>a</div>
    

    fires this js function through an event listener (you could probably call it from onClick for testing). The id needed by the db is taken from data-sp_id='5'. The map on which the plants are placed has some padding, hence the mouse position corrections.

    function showDescription( event ){
        
        var species = event.target.getAttribute('data-sp_id');
        var popup   = document.getElementById('description');  
        var map     = document.getElementById('bordermap');  
        var rect    = map.getBoundingClientRect();
        var x       = event.clientX - rect.left;
        var y       = event.clientY - rect.top; 
        var descr   = "";
        var xhr     = new XMLHttpRequest();
        var url     = "../ajax/description.php";
        var params  = "id="+species;  
         
        xhr.open('POST', url, true);
        xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        xhr.send(params);    
        
        xhr.onload = function() {
            // Do whatever with response
            descr               = xhr.responseText;
            popup.innerHTML     = descr;
            popup.style.display = "block";     
            popup.style.left    = x+"px";            
            popup.style.top     = y+"px";  
        } 
    }
    

    which puts the text in

    <div id='description' class='description'></div>
    

    and makes it popup at the right spot. I added some extra code to make the div draggable and close when you click somewhere outside it. Works like a charm, but I am always up for some improvements or comments.