0

I have an ecommerce site and I am trying to set up shipping zones in the US by state. To do this I have created a drag and drop system where we have 8 shipping zones and you can just drag the states into the appropriate zone.

This is kind of working as expected but I have a few issues:

  1. When you have dragged a state into a zone and drag another state on top of it it gets nested within the state rather than the drop zone, so is there a way that if it gets dropped onto another state it gets added to the parent zone? JS line 9-12

  2. When I try to send this across to my PHP script it is not getting picked up properly. The console.log() before the ajax bit shows the multidimensional array as I want it, but I get the post_set_blank blank response.

For this my PHP script is as follows:

if(isset($_POST['shipping_zone_array']) && $_POST['shipping_zone_array']!=""){
    echo 'session_set';
}else if(isset($_POST['shipping_zone_array'])){
    echo 'post_set_blank';
}else{
    echo 'not_posted';
}

Code:

function drag_start(event) {
	event.dataTransfer.dropEffect = "move";
	event.dataTransfer.setData("text", event.target.getAttribute('id'));
}

function drag_drop(event) {
	event.preventDefault();
	var elem_id = event.dataTransfer.getData("text");
	if(event.target.className == 'states'){
		console.log('in another state');
		event.target.parent.appendChild(document.getElementById(elem_id));
	}else{
		event.target.appendChild(document.getElementById(elem_id));
	}
}

var zone_1 = [];
var zone_2 = [];
var zone_3 = [];
var zone_4 = [];
var zone_5 = [];
var zone_6 = [];
var zone_7 = [];
var zone_8 = [];
var shipping_zone_array = [];

function readDropZone(){
	var shipping_zones = document.getElementsByClassName("shipping_zone");
	for(var i=1; i<=shipping_zones.length; i++){
		var shipping_zone = document.getElementById("shipping_zone_"+i);
		for(var j=1; j<=shipping_zone.children.length; j++){
			alert(shipping_zone.children[j].id);
			if(i==1){
				zone_1.push(shipping_zone.children[j].id);
			}else if(i==2){
				zone_2.push(shipping_zone.children[j].id);
			}else if(i==3){
				zone_3.push(shipping_zone.children[j].id);
			}else if(i==4){
				zone_4.push(shipping_zone.children[j].id);
			}else if(i==5){
				zone_5.push(shipping_zone.children[j].id);
			}else if(i==6){
				zone_6.push(shipping_zone.children[j].id);
			}else if(i==7){
				zone_7.push(shipping_zone.children[j].id);
			}else if(i==8){
				zone_8.push(shipping_zone.children[j].id);
			}
		}
	}
	shipping_zone_array['zone_1'] = zone_1;
	shipping_zone_array['zone_2'] = zone_2;
	shipping_zone_array['zone_3'] = zone_3;
	shipping_zone_array['zone_4'] = zone_4;
	shipping_zone_array['zone_5'] = zone_5;
	shipping_zone_array['zone_6'] = zone_6;
	shipping_zone_array['zone_7'] = zone_7;
	shipping_zone_array['zone_8'] = zone_8;
	
	console.log(shipping_zone_array);
	var formData = new FormData();
	formData.append("shipping_zone_array", shipping_zone_array);
	var xmlhttp = new XMLHttpRequest();
	xmlhttp.onreadystatechange = function(){
		if(this.readyState == 4 && this.status == 200){
			if(this.responseText.includes('session_set')){
				console.log('session_set');
			}else if(this.responseText.includes('post_set_blank')){
				console.log('post_set_blank');
			}else if(this.responseText.includes('not_posted')){
				console.log('not_posted');
			}
		}
	};
	xmlhttp.open("POST", "mypage.php", true);
	xmlhttp.send(formData);
}
.states{
	display:inline-block;
	background-color:#CCC;
	border:1px solid #999;
	border-radius:3px;
	width:100px;
	height:40px;
	margin:5px;
	padding:5px;
	text-align:center;
	vertical-align:middle;
	cursor:move;
}
.shipping_zone{
	display:inline-block;
	background-color:#EEE; 
	border:1px solid #999;
	border-radius:5px;
	width:650px; 
	height:220px;
	margin:5px;
	padding:5px;
	text-align:center;
	vertical-align:middle;
}
<table>
<tr>
	<td>
		<div id="shipping_zone_1" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 1<br /></div>
		<div id="shipping_zone_2" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 2<br /></div>
		<div id="shipping_zone_3" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 3<br /></div>
		<div id="shipping_zone_4" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 4<br /></div>
		<div id="shipping_zone_5" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 5<br /></div>
		<div id="shipping_zone_6" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 6<br /></div>
		<div id="shipping_zone_7" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 7<br /></div>
		<div id="shipping_zone_8" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 8<br /></div>
	</td>
	<td>
		<div id="AL" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Alabama</div>
		<div id="AK" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Alaska</div>
		<div id="AZ" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Arizona</div>
		<div id="AR" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Arkansas</div>
		<div id="CA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">California</div>
		<div id="CO" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Colorado</div>
		<div id="CT" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Connecticut</div>
		<div id="DE" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Delaware</div>
		<div id="FL" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Florida</div>
		<div id="GA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Georgia</div>
		<div id="HI" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Hawaii</div>
		<div id="ID" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Idaho</div>
		<div id="IL" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Illinois</div>
		<div id="IN" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Indiana</div>
		<div id="IA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Iowa</div>
		<div id="KS" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Kansas</div>
		<div id="KY" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Kentucky</div>
		<div id="LA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Louisiana</div>
		<div id="ME" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Maine</div>
		<div id="MD" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Maryland</div>
		<div id="MA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Massachusetts</div>
		<div id="MI" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Michigan</div>
		<div id="MN" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Minnesota</div>
		<div id="MS" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Mississippi</div>
		<div id="MO" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Missouri</div>
		<div id="MT" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Montana</div>
		<div id="NE" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Nebraska</div>
		<div id="NV" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Nevada</div>
		<div id="NH" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">New Hampshire</div>
		<div id="NJ" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">New Jersey</div>
		<div id="NM" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">New Mexico</div>
		<div id="NY" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">New York</div>
		<div id="NC" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">North Carolina</div>
		<div id="ND" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">North Dakota</div>
		<div id="OH" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Ohio</div>
		<div id="OK" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Oklahoma</div>
		<div id="OR" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Oregon</div>
		<div id="PA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Pennsylvania</div>
		<div id="RI" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Rhode Island</div>
		<div id="SC" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">South Carolina</div>
		<div id="SD" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">South Dakota</div>
		<div id="TN" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Tennessee</div>
		<div id="TX" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Texas</div>
		<div id="UT" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Utah</div>
		<div id="VT" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Vermont</div>
		<div id="VA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Virginia</div>
		<div id="WA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Washington</div>
		<div id="WV" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">West Virginia</div>
		<div id="WI" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Wisconsin</div>
		<div id="WY" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Wyoming</div>
	</td>
</tr>
</table>

<center>
<button onclick="readDropZone()">Get Object Data</button>
</center>

8
  • Ok so never mind the first part I just had the wrong syntax parent instead of parentElement Commented Feb 15, 2019 at 11:15
  • 1
    Does the data show up in the POST request in the network tab of the browser? Aka, is the problem on the PHP or the JS side? Commented Feb 15, 2019 at 11:23
  • @Shilly thanks for your comment, hadn't even checked there, it's being posted blank in the console, so it appears to be a JS issue. But like I said the console.log() before the request shows what I want to send. Commented Feb 15, 2019 at 11:27
  • Do I need to serialize the array or something to send it as a post? Commented Feb 15, 2019 at 11:35
  • 1
    Maybe. I would not use a FormData() but just stringify the array into JSON and then send the JSON string. But both methods should work, so there's something going wrong with that part I think. Hence I asked what the network tab shows. If you see an empty body, there's something going wrong with the FormData(), if the network request shows the correct body, something like shipping_zone_array=[{"key":"val"}]&type=multipart/form-data, then the issue is with your PHP. Commented Feb 15, 2019 at 12:43

1 Answer 1

1

Your shipping zones HTML <div id="shipping_zone_1" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 1<br /></div> also contains a <br> tag.

When you loop over the children, for(var j=1; j<=shipping_zone.children.length; j++) {, you also encounter the <br> tag inside the children collection.

When you then ask for the id of that <br> tag, you get an error, since they do not have an id. The result is that your arrays stay empty.

So either filter out the nodes that aren't <div> tags or use a different array creation method.

I would use a simple function that immediately selects the correct tags - and only the correct tags, nothing else - by using querySelector() looking for all elements with the class .states inside the zone element, instead of getElementById() the zone and then loop the children.

function drag_start(event) {
  event.dataTransfer.dropEffect = "move";
  event.dataTransfer.setData("text", event.target.getAttribute('id'));
}

function drag_drop(event) {
  event.preventDefault();
  var elem_id = event.dataTransfer.getData("text");
  if(event.target.className == 'states'){
    console.log('in another state');
    event.target.parentElement.appendChild(document.getElementById(elem_id));
  }else{
    event.target.appendChild(document.getElementById(elem_id));
  }
}
function get_states( zone_selector ) {
  return Array
    .from( document.querySelectorAll( `${ zone_selector } > .states`))
    .map( state => state.id );
}
function readDropZone(){
  var shippping_zones_object = {
    "shipping_zone_1": get_states( '#shipping_zone_1' ),
    "shipping_zone_2": get_states( '#shipping_zone_2' ),
    "shipping_zone_3": get_states( '#shipping_zone_3' ),
    "shipping_zone_4": get_states( '#shipping_zone_4' ),
    "shipping_zone_5": get_states( '#shipping_zone_5' ),
    "shipping_zone_6": get_states( '#shipping_zone_6' ),
    "shipping_zone_7": get_states( '#shipping_zone_7' ),
    "shipping_zone_8": get_states( '#shipping_zone_8' )
  };
  console.log( shippping_zones_object );
  // Continue with AJAX.
}
.states{
    display:inline-block;
    background-color:#CCC;
    border:1px solid #999;
    border-radius:3px;
    x-width:100px;
    x-height:40px;
    margin:5px;
    padding:5px;
    text-align:center;
    vertical-align:middle;
    cursor:move;
  }
  .shipping_zone{
    display:inline-block;
    background-color:#EEE; 
    border:1px solid #999;
    border-radius:5px;
    x-width:650px; 
    x-height:220px;
    margin:5px;
    padding:5px;
    text-align:center;
    vertical-align:middle;
  }
<table>
  <tr>
    <td>
    <div id="shipping_zone_1" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 1<br /></div>
    <div id="shipping_zone_2" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 2<br /></div>
    <div id="shipping_zone_3" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 3<br /></div>
    <div id="shipping_zone_4" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 4<br /></div>
    <div id="shipping_zone_5" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 5<br /></div>
    <div id="shipping_zone_6" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 6<br /></div>
    <div id="shipping_zone_7" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 7<br /></div>
    <div id="shipping_zone_8" class="shipping_zone" ondragenter="return false" ondrop="drag_drop(event)" ondragover="return false" ondragleave="return false" >Zone 8<br /></div>
    </td>
    <td>
    <div id="AL" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Alabama</div>
    <div id="AK" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Alaska</div>
    <div id="AZ" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Arizona</div>
    <div id="AR" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Arkansas</div>
    <div id="CA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">California</div>
    <div id="CO" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Colorado</div>
    <div id="CT" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Connecticut</div>
    <div id="DE" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Delaware</div>
    <div id="FL" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Florida</div>
    <div id="GA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Georgia</div>
    <div id="HI" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Hawaii</div>
    <div id="ID" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Idaho</div>
    <div id="IL" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Illinois</div>
    <div id="IN" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Indiana</div>
    <div id="IA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Iowa</div>
    <div id="KS" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Kansas</div>
    <div id="KY" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Kentucky</div>
    <div id="LA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Louisiana</div>
    <div id="ME" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Maine</div>
    <div id="MD" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Maryland</div>
    <div id="MA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Massachusetts</div>
    <div id="MI" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Michigan</div>
    <div id="MN" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Minnesota</div>
    <div id="MS" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Mississippi</div>
    <div id="MO" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Missouri</div>
    <div id="MT" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Montana</div>
    <div id="NE" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Nebraska</div>
    <div id="NV" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Nevada</div>
    <div id="NH" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">New Hampshire</div>
    <div id="NJ" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">New Jersey</div>
    <div id="NM" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">New Mexico</div>
    <div id="NY" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">New York</div>
    <div id="NC" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">North Carolina</div>
    <div id="ND" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">North Dakota</div>
    <div id="OH" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Ohio</div>
    <div id="OK" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Oklahoma</div>
    <div id="OR" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Oregon</div>
    <div id="PA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Pennsylvania</div>
    <div id="RI" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Rhode Island</div>
    <div id="SC" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">South Carolina</div>
    <div id="SD" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">South Dakota</div>
    <div id="TN" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Tennessee</div>
    <div id="TX" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Texas</div>
    <div id="UT" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Utah</div>
    <div id="VT" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Vermont</div>
    <div id="VA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Virginia</div>
    <div id="WA" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Washington</div>
    <div id="WV" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">West Virginia</div>
    <div id="WI" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Wisconsin</div>
    <div id="WY" class="states" draggable="true" ondragstart="drag_start(event)" ondragend="return false">Wyoming</div>
    </td>
  </tr>
</table>
<button onclick="readDropZone()">Get Object Data</button>

PS: If you still want to do the two for-loops, .children only gives me the BR tags. You need .childNodes inside your for-loops if you want to do it this way.

PPS: If you set shipping_zone_array['zone_1'] = zone_1;, you technically want an object with arrays as proeprties, instead of a multidimentional array. So either change the name or use the correct syntax.

Multi array would be:

[
 [ "IL", "MI" ],
 [],
 [],
 [],
 [],
 [],
 [],
 []
]

Object would be:

{
  "zone_1': [ "IL", "MI" ],
  "zone_2': [ "IL", "MI" ],
  "zone_3': [ "IL", "MI" ],
  "zone_4': [ "IL", "MI" ],
  "zone_5': [ "IL", "MI" ],
  "zone_6': [ "IL", "MI" ],
  "zone_7': [ "IL', "MI" ],
  "zone_8': [ "IL", "MI" ]
}
Sign up to request clarification or add additional context in comments.

2 Comments

I tried this and I just get a blank object shipping_zone_array: [object Object] I don't think this is the case as my array is right in the console when I log it, the <br> tag is always first so my loop starts at 1, the <br> tag would be shipping_zone.children['0']
Then you have to JSON.stringify() the object before sending it with AJAX. There is also a textnode before the <br>, so depending on if you use .children or .childNodes, you have to starts at 2 instead of 1. Anyways, good luck then.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.