Search code examples
jquerycssz-indexpositioningfixed

insertAdjacentHTML Inserts After the Parent Container Rather Than After The Div Inside That Container


I have a basic U.S. map. It needs to be fixed position. The state abbreviations are also in fixed positions. A database is queried according to user input. When the results of that query have information relevant to a particular state, I change the class of that state abbreviation that formats a button. My goal is to produce a div holding the information related to that state below the button. My problem is that, rather than appearing after the state abbreviation button, the div appears after the container holding the map. CSS

<style>
    #MapContainer {position:absolute; width:1760px; height:1099px; top:0; left:0; padding:0; z-index:1;}
    .Abr {position:absolute; font-size:18px; font-weight:bold; color:#006393; z-index:100}
    .Active {background:red; padding:6px; color:white; border:1px solid black; border-radius:50%;}
</style>

HTML with PHP (I'll show one state)

<div id="MapContainer">
    <img src="maps/TransUSA-All50-1760x1099.png" style="width:100%" />
    <div class="Abr" id="WA" style="top:100px; left:238px;">WA</div>
    // Database queries follow here after all state names have been defined
    while($Info = i5_fetch_array($Result))
   {
     switch($Info[STATE])
     {
     case "WA":
        echo('<script>$("#WA").addClass("Active"); var Rates = "'.$Info[Rates].'"; var Charges = "'.$Info[Charges].'";</script>');
        break;
     //etc.
    }
</div>

Obviously, I will need to send the variables (Rates, Charges) to the function that creates the display. But that is not my concern at the moment. The purpose of this question is, first of all, getting the div that will hold the data to appear below the state abbreviation button.

jQuery

<script type="text/JavaScript">
    $(".Active").on("click", function()
    {
       this.insertAdjacentHTML("afterend","<div>This is a data Div</div>");
    });
</script>

The result of a click is that the appended div appears at the end of the map container instead of directly after the "WA" abbreviation button.

Example:

<div id="MapContainer">
    <div id="WA">WA</div>
    // Data div should appear here
</div>
// Data div appears here



  ___________________________________________________
    |                                                 |
    |  <div>WA</div>                                  |
    |   <div>Data div should appear here</div>        |
    |                                                 |
    |_________________________________________________|
    <div>Data div appears here instead</div> 
 

I created a fiddle Here But here, rather than appearing below the map block, it appears inside it. Still, of course, not the desired outcome.

Final Outcome For those interested, this was the final outcome, but still with a caveat - Used in this way with fixed positioning, I have failed to find a remedy to the stacking structure, so the info box is overridden by adjoinig state abbreviations.

enter image description here

https://jsfiddle.net/RationalRabbit/rj8g2bqm/87/

My eventual solution to that was to simply take a screenshot of the map with abbreviations in place and use that for the background, removing the abbreviations from the span sections, and adding them in when a state is active. Still, some active buttons overrode the info boxes, which I solved by changing the order they are rendered. I realized then this may have been the solution in the first place, although I haven't tested it. For example, if the abbreviation "ID" had been placed before "OR" in the abbreviation definitions, this may have solved the problem.


Solution

  • Check this below code, added the same in codepen Positioned DIVs for MAP

    $(document).ready(function () {
        $("#WA").addClass("Active");
        $(".Active").on("click", function (e) {
            var $this = $(this), $data = $this.next('.AbrData');
            var ST = "AK"; // You can pull this from the state div along with the data
            if ($data.length == 0) {
                $data = $("<div class='AbrData'></div>").insertAfter($this);
                $data.append('<div id="' + ST + 'Data">This is a data Div</div>');
            }
            else {
                $data.toggle();
            }
        });
    });
    #MapContainer {
        position: absolute;
        width: 700px;
        height: 400px;
        top: 10px left 10px;
        padding: 0;
        z-index: 1;
        border: 2px solid black;
    }
    
    .Abr {
        position: absolute;
        font-size: 18px;
        font-weight: bold;
        color: #006393;
        z-index: 100;
    }
    
    .AbrData {
        position: relative;
        top: 10px;
        font-size: 12px;
        color: blue;
        z-index: 101;
        max-height: 100px;
        overflow: auto;
        border: 1px solid grey;
    }
    
    .Active {
        background: red;
        padding: 6px;
        color: white;
        border: 1px solid black;
        border-radius: 50%;
        cursor: pointer;
    }
    <div id="MapContainer">
        <div class="Abr" style="top:100px; left:238px;">
            <span id="WA">WA</span>
        </div>
        <div class="Abr" style="top:213px; left:207px;">
            <span id="OR">OR</span>
        </div>
        <div class="Abr" style="top:315px; left:550px;">
            <span id="WY">WY</span>
        </div>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    I have merged suggested changes, and the appearing line after toggling data is the border of div.AbrData. I have changed toggle line from so the it toggles div.AbrData instead of it's inside content.

    // Changed this toggle
    $("#"+ST+"Data").toggle();
    
    // To this
    $data.toggle();