0

I have a web page with a list stored in an XML file. I need to be able to load the contents (a list of US senators) of the XML file into JSON objects, into an unordered list on the webpage, and have each line item be draggable into one of two drop areas (Democrats and Republicans). When you drag a democrat, it should only drop into the democrats dropping area, and same for republicans. I cannot get the XML list to load, but my code is not complete yet. I need assistance getting the list to load, and making the items in that least each be draggable, and only droppable into their respective dropping area. Here is what I have so far:

<!doctype html>
<html>
<head>
    <title>Assignment 2 Part 2</title>
    <meta charset="utf-8">
    <script src="partyWise.js"></script>
    <link rel="stylesheet" href="styles.css">       
</head>
<body>
    <h1>Time to Vote</h1>
    <p>Drag members to either the Democrats or Republicans list.</p>
    <div id = "polList">
    </div>
    <div id="dems">Democrats:</div>
    <div id="reps">Republicans:</div>
</body>
</html>

JavaScript:

 window.onload = init;

function init() {
polList = document.getElementById("polList");
dems = document.getElementById("dems");
reps = document.getElementById("reps");

polList.ondragStart = dragStartHandler;
polList.ondragend = dragEndHandler;
polList.ondrag = dragHandler;   

}

function dragStartHandler(e) {
e.target.classList.add("dragged");
}

function dragEndHandler(e) {
e.target.classList.remove("dragged");
dems.innerHTML = "Drop Here";
reps.innerHTML = "Drop Here";
}

function dragHandler(e) {
msg.innerHTML = "Dragging " + e.target.id;
}
function loadPols() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        document.getElementById("polList").innerHTML = this.responseText;
    }
};
xhttp.open("GET", "senators", true);
xhttp.send();
}

XML

<senators>
<senator>
    <name>Orrin Hatch</name>
    <party>Republican</party>
</senator>
<senator>
    <name>Chuck Schumer</name>
    <party>Democrat</party>
</senator>
<senator>
    <name>Lisa Murkowski</name>
    <party>Republican</party>
</senator>
<senator>
    <name>Dianne Feinstein</name>
    <party>Democrat</party>
</senator>
<senator>
    <name>John Boozman</name>
    <party>Republican</party>
</senator>
<senator>
    <name>Michael Bennet</name>
    <party>Democrat</party>
</senator>
<senator>
    <name>Joni Ernst</name>
    <party>Republican</party>
</senator>
<senator>
    <name>Elizabeth Warren</name>
    <party>Democrat</party>
</senator>
<senator>
    <name>Roger Wicker</name>
    <party>Republican</party>
</senator>
<senator>
    <name>Al Franken</name>
    <party>Democrat</party>
</senator>
</senators>
user121168
  • 41
  • 10
  • At which browser are you trying JavaScript? Are you trying to load a file using `XMLHttpRequest()` at `file:` protocol? No unordered list appears at `HTML` or is created at JavaScript at Question? – guest271314 Jul 18 '17 at 03:29
  • I'm using Chrome. The list is being pulled from an XML file, per the question, and my code shows XMLHttpRequest() in it. – user121168 Jul 18 '17 at 03:34
  • See [Jquery load() only working in firefox?](https://stackoverflow.com/questions/32996001/jquery-load-only-working-in-firefox/), [Read local XML with JS](https://stackoverflow.com/questions/41279589/read-local-xml-with-js) – guest271314 Jul 18 '17 at 03:39
  • That helps with getting the xml file to load, but that is only step 1 of multiple steps I can't get to work. Anyone know how I can make this work? – user121168 Jul 18 '17 at 03:47
  • Not sure what you mean? What is the issue once `XML` file is successfully retrieved? – guest271314 Jul 18 '17 at 03:49
  • Did you read the entire question? – user121168 Jul 18 '17 at 03:57
  • Yes. Though we have little to work with by way of the actual text of the question itself. Loading the `XML` at Chrome, Chromium portion of inquiry should be resolved by previous links. That leaves us with what code that you have tried to solve the remainder of the inquiry. And where you are unable to proceed. See https://stackoverflow.com/help/mcve – guest271314 Jul 18 '17 at 04:00
  • My question tells you what I need to do. The code I posted is an unsuccessful attempt at it. Not sure what "little to work with" you mean. I need to pull data from an XML file, make the items JSON objects that can be dragged, and ensure each is only droppable into the right section on the page. That is where I am unable to proceed. I thought that was what my question said. – user121168 Jul 18 '17 at 04:04
  • Yes, what have you tried to solve that specific part of your Question? – guest271314 Jul 18 '17 at 04:05
  • With all due respect, you say you read my question, but clearly you did not. It tells you what I need to do, what I tried, and there is code that shows you exactly what I have already done. I have seen far more constructive discussion with far less to work with. – user121168 Jul 18 '17 at 04:11

1 Answers1

0

You can set a data-* attribute at <li> elements where parent element <ul> has .className set to id of element where element should be dropped. at dragstart event set event.dataTransfer to text of element .tagName and data-* attribute.

At drop event get event.dataTransfer, query document for element. If element .className is equal to event.target.id, append <li> to <ul> having id matching dragged element .parentElement .className, else call event.preventDefault() which should not permit element to be dropped at event.target.

const xml = `<senators>
<senator>
    <name>a</name>
    <party>true</party>
</senator>
<senator>
    <name>b</name>
    <party>false</party>
</senator>
<senator>
    <name>c</name>
    <party>true</party>
</senator>
<senator>
    <name>d</name>
    <party>false</party>
</senator>
<senator>
    <name>e</name>
    <party>true</party>
</senator>
<senator>
    <name>f</name>
    <party>false</party>
</senator>
<senator>
    <name>g</name>
    <party>true</party>
</senator>
<senator>
    <name>h</name>
    <party>false</party>
</senator>
<senator>
    <name>i</name>
    <party>true</party>
</senator>
<senator>
    <name>j</name>
    <party>false</party>
</senator>
</senators>`;

const TRUE_OR_FALSE = bool => !new Function(`return ${bool}`)();

let template = document.createElement("template");

template.innerHTML = xml;

let nodes = template.content.firstElementChild.children;

for (let {children} of Array.from(nodes)) {
  let node = Array.from(children);
  let [n, p] = [node.find(({tagName}) => tagName === "NAME")
               , node.find(({tagName}) => tagName === "PARTY")];
  let [text, bool] = [n.textContent, p.textContent];
  let [ul] = document.getElementsByClassName(bool);
  ul.innerHTML += `<li data-${bool}="${ul.children.length}">${text}</li>`;
}

const trueOrFalse = document.querySelectorAll("ul:not([id])");

const drop = document.querySelectorAll("#true, #false");

trueOrFalse.forEach(function(el) {
  el.childNodes.forEach(function(li) {
    if (li.tagName === "LI") {
      li.draggable = true;
      el.ondragstart = function(e) {
        let data = e.target.dataset;
        let [key] = Object.keys(data);
        let prop = data[key];
        let selector = e.target.tagName
                       + "[data-" + key + "=\"" + prop + "\"]";
        e.dataTransfer.setData("text/plain", selector);
        e.dropEffect = "move";
      }
    }
  });
});

drop.forEach(function(el) {

  el.ondragover = function(e) {
    e.preventDefault();
    e.dataTransfer.dropEffect = "move";
  }

  el.ondrop = function(e) {
    let selector = e.dataTransfer.getData("text");
    let li = document.querySelector(selector);
    let bool = li.parentElement.className;
    if (bool === e.target.id) {
      e.target.appendChild(li);
    } else {
      alert(`${bool} !== ${TRUE_OR_FALSE(bool)}`);
      e.preventDefault();
    }
  }
  
});
#true,
#false {
  width: 100px;
  height: 100px;
  border: 2px dotted green;
  padding: 4px;
  list-style: none;
}

#true:before {
  content: "true";
  color: blue;
  font-style: italic;
  font-weight: bold;
}

#false:before {
  content: "false";
  color: orange;
  font-style: italic;
  font-weight: bold;
}
<ul class="true">
</ul>

<ul class="false">
</ul>

<ul id="true"></ul>
<ul id="false"></ul>
guest271314
  • 1
  • 15
  • 104
  • 177