Pretty new to jQuery and JavaScript so please be gentle...
I am working on a POC to create a "column mapping" page where the user is able to drag and drop a list of "column headers" to a grid of new column headers. I need to build an array that I can send back to a SQL database. I have this part (mostly) functioning how I would like.
When the item is dragged from the column list on the left on to the header grid on the right, if the item exists, the code should update/replace the array item at that index. If the item does not exist, it should add the item to the array.
For example: If you drag "First Name" to "Headers" it should be added at index position 0. If you then drag "First Name" to "with" it should remove the "First Name" value at index 0 and add the value at position 1. If you then drag "Last Name" to "with" it should update the array at position 1 with the "Last Name" value.
$(document).ready(() => {
$(function() {
$('.item').draggable({
cursor: "crosshair",
cursorAt: {
left: 5
},
distance: 10,
opacity: 0.75,
revert: true,
snap: ".target",
containment: "window"
});
});
$(function() {
var array = [];
var arraytext = '';
$('.target').droppable({
accept: ".item",
tolerance: 'pointer',
activeClass: 'active',
hoverClass: 'highlight',
drop: function(event, ui) {
var dropped = $(this);
var dragged = $(ui.draggable);
$(function(index, item) {
var test = '';
array.push($(dragged).text());
arraytext = JSON.stringify(array);
test += "Index Value = " + $(dropped).index() + ", Text = " + $(dragged).text() + "<br/>";
$('#test').html(test);
$('#array').text(arraytext);
});
}
});
});
});
#container {
border: solid black 1px;
margin: 0 auto;
height: 800px;
}
#gridview {
border: 2px solid #292da0;
border-radius: 5px;
background-color: #7577a3;
display: grid;
grid-template-columns: repeat(auto-fit, 100px);
grid-template-rows: auto;
margin-left: 105px;
}
.target {
border: 2px solid #1c1c3a;
border-radius: 5px;
background-color: #a7a7ef;
padding: 1em;
}
#flex {
border: 2px solid #292da0;
border-radius: 5px;
width: 100px;
background-color: #7577a3;
display: flex;
flex-flow: column wrap;
justify-content: flex-end;
float: left;
}
.item {
border: 2px solid #1c1c3a;
border-radius: 5px;
background-color: #a7a7ef;
padding: 1em;
}
.active {
background-color: blue;
color: white;
border: 2px solid black;
}
.highlight {
background-color: yellow;
color: black;
border: 2px solid blue;
}
.table {
border: solid black 1px;
width: 86px;
padding: 5px;
}
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
<div id="container">
Test:
<div id="test">
</div>
Array:
<div id="array">
</div>
<div id="gridview">
<div class="target">Headers</div>
<div class="target">with</div>
<div class="target">different</div>
<div class="target">column</div>
<div class="target">names</div>
</div>
<span>
<div id="flex">
<div class="item">First Name</div>
<div class="item">Last Name</div>
<div class="item">Code</div>
<div class="item">Date</div>
<div class="item">Amount</div>
</div>
<table>
<thead>
<tr>
<td class="table">Some</td>
<td class="table">Column</td>
<td class="table">Data</td>
<td class="table">Goes</td>
<td class="table">Here</td>
</tr>
</thead>
<tr>
<td class="table">Other Data</td>
<td class="table">Other Data</td>
<td class="table">Other Data</td>
<td class="table">Other Data</td>
<td class="table">Other Data</td>
</tr>
</table>
</span>
</div>
JSFiddle: https://jsfiddle.net/qxwzcn9w/4/
Eventually I will be sending the index values back to the database so bonus points if you notice any red flags or "gotchas". Thanks!
Personally I would use an object instead of array and use the index as keys for object
var cols ={};
$('.target').droppable({
.....
drop: function(event, ui) {
var txt = $(ui.draggable).text(),
colIdx = $(this).index();
// clear from any prior position
$.each(cols, function(key, val){
if (val === txt){
cols[key] = null
}
});
// add to new position
cols[colIdx] = txt;
}
}).each(function(i){
// add each index as key in cols object
cols[i] = null;
});
If you must have array in back end is simple to map the cols object to array just before submit
DEMO
Simple solution using a for loop to find if an element exists. You could also use $.each()
if you are comfortable with jQuery. You can count the array length by counting the table header columns using $("thead").find("td")
if needed. Then business as usual iterate to see if the element exists, if so remove it, then insert in the appropriate index.
$(function() {
$('.item').draggable({
cursor: "crosshair",
cursorAt: {
left: 5
},
distance: 10,
opacity: 0.75,
revert: true,
snap: ".target",
containment: "window"
});
});
$(function() {
var arraytext = '';
$('.target').droppable({
accept: ".item",
tolerance: 'pointer',
activeClass: 'active',
hoverClass: 'highlight',
drop: function(event, ui) {
var dropped = $(this);
var dragged = $(ui.draggable);
$(function(index, item) {
var test = '';
for(var i = 0; i < array.length; i++)
{
if($(dragged).text() == array[i])
{
array[i] = "";
}
}
array[$(dropped).index()] = $(dragged).text();
arraytext = JSON.stringify(array);
test += "Index Value = " + $(dropped).index() + ", Text = " + $(dragged).text() + "<br/>";
$('#test').html(test);
$('#array').text(arraytext);
});
}
});
});
array.push($(dragged).text());
This line is pushing the dropped column into the array, not updating it.
You should start by initializing an array somewhere with empty values for each column header.
var arr = Array.apply(null, new Array(10)).map(Number.prototype.valueOf,0);
//console.log(arr) Outputs as [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Change the number to the number of columns you have.
To change the value at a given index do:
arr[3]='a new value';
//console.log(arr) Outputs as [0, 0, 0, 'a new value', 0, 0, 0, 0, 0, 0]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With