1

So, I've been warned that some of my past questions have not been well-received, and I'm in danger of being blocked from asking any more. I hope that this question is well-received and that it doesn't result in me being blocked from asking more questions! I'll do my very best to formulate it as a clear and useful question.

What I'm trying to do is create javascript to click-and-drag images into nested lists. I've read HTML Drag and Drop between multiple Unordered Lists and How to drag and drop into an html unordered list, and neither addresses what I'm trying to do.

The images I want to click-and-drag represent items--some items can contain other items while others cannot. For instance, a Single-Barrel Shotgun can contain Shotgun Ammo, but Shotgun Ammo cannot contain anything.

I've created a jsfiddle, https://jsfiddle.net/pjamesnorris25/9f0y8edz/76/, to facilitate some javascript wizard helping me with this. And because I have, I'm not going to post the javascript here unless someone asks me to do so.

My javascript works if you click-and-drag the shotgun to the "Left Shoulder" in the image of the generic person below the "Shotgun Ammo" and "Single-Barrel Shotgun" images in the upper right-hand corner. That is, when you do so, the text "Single Barrel Shotgun" appears below the "Left Shoulder" in a of its own denoted by a box around the text--the box indicates that "Single Barrel Shotgun" is a container into which you can drag other items, in this case, "Shotgun Ammo".

Prior to dragging the "Single-Barrel Shotgun" graphic to the "Left Shoulder" container, my HTML looks like this:

<span id="leftshoulder-span" style="border:black solid 1px; left:387px; height:30px; width:173px; overflow:hidden; position:absolute; top:96px; " ondrop="drop(event)" ondragover="allowDrop(event)"></span>
<ul id="leftshoulder-ul" style="left:387px; position:absolute; top:126px; z-index:101; "></ul>

After dragging the "Single-Barrel Shotgun" to the "Left Shoulder", the HTML looks like this:

<ul id="leftshoulder-ul" style="left:387px; position:absolute; top:126px; z-index:101; ">
  <li id="Single_Barrel_Shotgun_1-li" style="margin-top:2px;">
    <span id="Single_Barrel_Shotgun_1-span" ondrop="drop(event)" ondragover="allowDrop(event)" style="border:1px solid black;">
      <div class="tooltip">
        Single Barrel Shotgun
        <span class="tooltipimage">
          <img src="https://i.postimg.cc/sGCvntKs/Single-Barrel-Shotgun.gif" id="Single_Barrel_Shotgun_1" class="zoom_small card" draggable="true" ondragstart="drag(event)">
        </span>
      </div>
    </span>
    <span id="Single_Barrel_Shotgun_1-contents-span" ondrop="drop(event)" ondragover="allowDrop(event)"></span>
    <ul id="Single_Barrel_Shotgun_1-ul"></ul>
  </li>
</ul>

Which is exactly what I want. But when I drag the "Shotgun Ammo" image to the "Single Barrel Shotgun" text , I get:

<ul id="leftshoulder-ul" style="left:387px; position:absolute; top:126px; z-index:101; ">
  <li id="Single_Barrel_Shotgun_1-li" style="margin-top:2px;">
    <span id="Single_Barrel_Shotgun_1-span" ondrop="drop(event)" ondragover="allowDrop(event)" style="border:1px solid black;">
      <div class="tooltip">
        Single Barrel Shotgun
        <span class="tooltipimage">
          <img src="https://i.postimg.cc/sGCvntKs/Single-Barrel-Shotgun.gif" id="Single_Barrel_Shotgun_1" class="zoom_small card" draggable="true" ondragstart="drag(event)">
        </span>
      </div>
    </span>
    <img id="Shotgun_Shell_4" class="zoom_small card" src="https://i.postimg.cc/N28LZpPT/Shotgun-Shell.gif" draggable="true" ondragstart="drag(event)">
    <span id="Single_Barrel_Shotgun_1-contents-span" ondrop="drop(event)" ondragover="allowDrop(event)"></span>
    <ul id="Single_Barrel_Shotgun_1-ul">
    </ul>
  </li>
</ul>

Note that the <img src="https://i.postimg.cc/sGCvntKs/Single-Barrel-Shotgun.gif" ... is after the </span> closing the <span class="tooltipimage"> and not in an <li> inside <ul id="Single_Barrel_Shotgun_1-ul"></ul>.

That is, what I want is:

<ul id="leftshoulder-ul" style="left:387px; position:absolute; top:126px; z-index:101; ">
  <li id="Single_Barrel_Shotgun_1-li" style="margin-top:2px;">
    <span id="Single_Barrel_Shotgun_1-span" ondrop="drop(event)" ondragover="allowDrop(event)" style="border:1px solid black;">
      <div class="tooltip">
        Single Barrel Shotgun
        <span class="tooltipimage">
          <img src="https://i.postimg.cc/sGCvntKs/Single-Barrel-Shotgun.gif" id="Single_Barrel_Shotgun_1" class="zoom_small card" draggable="true" ondragstart="drag(event)">
        </span>
      </div>
    </span>
    <span id="Single_Barrel_Shotgun_1-contents-span" ondrop="drop(event)" ondragover="allowDrop(event)"></span>
    <ul id="Single_Barrel_Shotgun_1-ul">
      <li id="Shotgun_Shell_4-li" style="margin-top:2px;">
      <div class="tooltip">
        Shotgun Shell
        <span class="tooltipimage">
          <img src="https://i.postimg.cc/sGCvntKs/Shotgun-Shell.gif" id="Shotgun_Shell_4" class="zoom_small card">
        </span>
      </div>
    </ul>
  </li>
</ul>

What's got me flabbergasted is that the javascript that properly places the "Single-Barrel Shotgun" as an unordered list item under the "Left Shoulder" doesn't place the "Shotgun Shell" as an unordered list item under the "Single-Barrel Shotgun" when the HTML for the two has exactly the same structure. That is, the "Left Shoulder" has a uniquely id'd <span> followed by a uniquely id'd <ul>:

<span id="leftshoulder-span" style="border:black solid 1px; left:387px; height:30px; width:173px; overflow:hidden; position:absolute; top:96px; " ondrop="drop(event)" ondragover="allowDrop(event)"></span>
<ul id="leftshoulder-ul" style="left:387px; position:absolute; top:126px; z-index:101; "></ul>

and the "Single Barrel Shotgun" also has a uniquely id'd followed by a uniquely id'd :

    <span id="Single_Barrel_Shotgun_1-contents-span" ondrop="drop(event)" ondragover="allowDrop(event)"></span>
    <ul id="Single_Barrel_Shotgun_1-ul"></ul>

I have built in some error checking alerts--that don't work in jsfiddle for some reason; extra bonus point to anyone who can explain this to me. When I run the code on my machine, I get the following when I first click-and-drag the "Single-Barrel Shotgun" to the "Left Shoulder":

error checking for dragging the Shotgun

which tells me that the javascript is correctly identifying the <span> to which the "Single-Barrel Shotgun" is being dragged, i.e., the leftshoulder-span, the code knows the id of the "Single-Barrel Shotgun" being dropped into the leftshoulder <ul> is "Single_Barrel_Shotgun_1" (the "_1" indicates that this is the first of the "Single-Barrel Shotgun"'s that can be dragged, and that the item is a "Single Barrel Shotgun".

But when I click-and-drag the "Shotgun Ammo", the error checking alert I get is:

error checking for dragging the Shotgun Ammo

which, because the eve.target.id tells me that the code doesn't recognize that it should be putting the "Shotgun Ammo" as the first <li> in the <ul id="Single_Barrel_Shotgun_1-ul">.

So my question is: how do I modify my javascript so that when I click-and-drag the "Shotgun Ammo" to the "Single Barrel Shotgun" it appears as an unordered list item under the "Single Barrel Shotgun"? Or put differently, why is eve.target.id in my error checking alert blank when I click-and-drag the "Shotgun Ammo" to the "Single Barrel Shotgun"?

P. James Norris
  • 158
  • 2
  • 14

1 Answers1

0

So, I'm not sure if my reasoning is correct here, but I think the reason my javascript wasn't working was that it was looking for the id for the inner-most span to which I was trying to drag the "Shotgun Shell", i.e.:

<span class="tooltipimage">

for which there was no id.

So, I wrote my javascript to add an id to every div and span daughter of id="Single_Barrel_Shotgun_1-span" like so:

    <span id="Single_Barrel_Shotgun_1-span" ondrop="drop(event)" ondragover="allowDrop(event)" style="border:1px solid black;">
      <div id="Single_Barrel_Shotgun_1-tooltip" class="tooltip">
        Single Barrel Shotgun
        <span id="Single_Barrel_Shotgun_1-tooltipimage" class="tooltipimage">
          <img src="https://i.postimg.cc/sGCvntKs/Single-Barrel-Shotgun.gif" id="Single_Barrel_Shotgun_1" class="zoom_small card" draggable="true" ondragstart="drag(event)">
        </span>
      </div>
    </span>

And, lo and behold, the "Shotgun Shell" now appears as an unordered list item under the "Shotgun" the way I want it to.

The javascript that does the trick is:

        function addContentsSpan(str_possession)
        {
            var str_item = str_possession.replace(/[0-9]/g, "").replace(/_/g, " ").slice(0, -(" ".length));
            var str_possession_li = str_possession + "-li";
            var str_possession_span = str_possession + "-span";

            var ele_span = document.getElementById(str_possession_span);
            ele_span.setAttribute("id", str_possession_span);
            ele_span.setAttribute("ondrop", "drop(event)");
            ele_span.setAttribute("ondragover", "allowDrop(event)");
            ele_span.setAttribute("style", "border:1px solid black;");
            var ele_li = document.getElementById(str_possession_li);

            var ele_ul = document.createElement("ul");
            ele_ul.setAttribute("id", (str_possession + "-ul"));
            ele_li.appendChild(ele_ul);
            
        } // function addContentsSpan(str_possession_li)

        function allowDrop(eve) { eve.preventDefault(); }
        
        function drag(eve) 
        { 
            eve.dataTransfer.setData("text", eve.target.id);
            console.log(eve.target.id);
        }
        
        function drop(eve) 
        {
            bool_debug = false;

            // identify the item being moved
            var str_possession = eve.dataTransfer.getData("text");
            var str_container = eve.dataTransfer.setData("text", eve.target.id);
            var str_item = str_possession.replace(/_/g, " ").replace(/[0-9]/g, "").slice(0, -(" ".length));
                
            // drop the item in the container           
            if (eve.target.id.slice(-("-tooltip").length) == "-tooltip") { eve.target.id = eve.target.id.slice(0, -("-tooltip").length) + "-span"; }

            var str_item_parent = eve.target.id.slice(0, -("-span").length) + "-ul";
            
            var str_location = eve.target.id.slice(0, -("-span").length) + "-ul";
            var ele_location = document.getElementById(str_location);

            eve.preventDefault();
            eve.target.appendChild(document.getElementById(str_possession));

            var ele_li = document.createElement("li");
            ele_li.setAttribute("id", (str_possession + "-li"));
            ele_li.setAttribute("style", "margin-top:2px;");
            ele_location.appendChild(ele_li);

            var ele_divTooltip = document.createElement("div");
            ele_divTooltip.setAttribute("class", "tooltip");
            ele_divTooltip.setAttribute("id", (str_possession + "-tooltip"));

            var ele_spanDrop = document.createElement("span");
            ele_spanDrop.setAttribute("id", (str_possession + "-span"));
            ele_li.appendChild(ele_spanDrop);

            ele_divTooltip.textContent = str_item;
            ele_spanDrop.appendChild(ele_divTooltip);

            var ele_spanTooltipImage = document.createElement("span");
            ele_spanTooltipImage.setAttribute("id", str_possession + "-tooltipimage");
            ele_spanTooltipImage.setAttribute("class", "tooltipimage");
            ele_divTooltip.appendChild(ele_spanTooltipImage);

            var ele_image = document.createElement("img");
            ele_image.setAttribute("src", ("img/cards/items/" + str_item + ".gif"));
            ele_image.setAttribute("id", str_possession);
            ele_image.setAttribute("class", "zoom_small card");
            ele_image.setAttribute("draggable", "true");
            ele_image.setAttribute("ondragstart", "drag(event)");
            ele_spanTooltipImage.appendChild(ele_image);
            
            // remove the item from "Possessions"
            document.getElementById(str_possession).remove()
            
            // remove item from previous container
            if (bool_debug) { alert("line " + 1366 + ":\n" + "str_item_parent = " + str_item_parent + "\n" + "possession list element = " + str_possession + "-li"); }
            if (str_item_parent.slice(-("-ul")) == "-ul") { document.getElementById(str_item_parent).removeChild(str_possession + "-li"); }
                        
            // update the Solo_Possession table with the new item
            str_target_id = eve.target.id;
            if (bool_debug) { alert("line " + 1371 +": str_target_id = \"" + str_target_id + "\"\n" + "str_possession = " + str_possession); }
            
            insertItem(str_possession);
            
            if (arr_space[str_item]['space'] > 0) { addContentsSpan(str_possession); }
            
            eve.dataTransfer.clearData();
                    
        } // function drop(eve)
P. James Norris
  • 158
  • 2
  • 14