0

Problem Overview:

I am creating circular div elements to serve as location markers on a map. My code reads the total number of rows from a database table and executes a loop to create that number of div elements, assigning each a div id using data returned from the database. Each div element is appended to a single div class (marker_mother). All of this works perfectly, resulting in a row of circular div elements on the page.

The next step is to make each individual div element draggable. I am using the .each() jQuery method to loop through all div elements in the class (marker_mother) and set them to draggable using the Draggable interaction from the jQuery UI. I have been using the following Stack Overflow Q&A as a reference: jQuery to loop through elements with the same class. However, all my attempts result in the class being set to draggable and not the individual divs. This means that all divs respond as a unified whole when dragged.


Code:

var total_units = "";

$(document).ready(function() {

  // Triggers PHP script to return number of table rows from DB

  $('#get_rows').click(function() {
    $.get('get_coords.php', function(data) {
      total_units = data;
      console.log(data);
    });
  });

  // Posts row number to DB and returns query data (eg. id and colour)
  // Uses returned data in construction of circular div elements

  $('#create_divs').click(function() {
    for (i = 0; i < total_units; i++) {
      $.ajax({
        type: 'POST',
        url: 'get_row.php',
        dataType: 'html',
        data: {
          row: i
        },
        success: function(response) {
          var jsonData = JSON.parse(response);
          jQuery('<div/>', {
            id: jsonData.id,
            css: {
              "position": "relative",
              "top": "200",
              "left": "100",
              "border-radius": "50%",
              "width": "100px",
              "height": "100px",
              "background": "jsonData.colour",
              "font-size": "20px",
              "text-align": "center",
              "line-height": "100px",
              "cursor": "move",
              "z-index": "100"
            },
            href: 'http://127.0.0.1/' + jsonData.id + '.html',
            text: jsonData.id
          }).appendTo('.marker_mother');
          console.log(response);
        }
      });
    }
  });

  // Assigns top&left positions of dragged div to variables
  // Code to store coords in db will be added later

  var coordinates = function(element) {
    element = $(element);
    var top = element.position().top;
    var left = element.position().left;
  }

  // Loops through divs and makes each draggable

  $('.marker_mother').each(function(index, item) {
    $(item).draggable({
      start: function() {
        coordinates(item);
      },
      stop: function() {
        coordinates(item);
      }
    });
  });
});
/* CSS to define characteristics for the marker div class */

.marker_mother {
  position: relative;
  top: 0;
  left: 0;
  border-radius: 50%;
  width: 50px;
  height: 50px;
  font-size: 10px;
  text-align: center;
  color: black;
  line-height: 50px;
  cursor: move;
  z-index: 100;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>

As mentioned in the overview, I have tried multiple implementations of the .each() function to make the divs draggable (including referring to the DOM object and $(this)). All attempts result in the class (marker_mother) being set to draggable and not the individual divs. I feel there must be something simple I am missing here.

Any ideas or suggestions would be greatly appreciated.

Edit:

HTML markup for the created divs end up looking as follows:

<div class="marker_mother ui-draggable ui-draggable-handle"> == $0
  <div id="0001" href="http://127.0.0.1/0001.html" style="position: relative; border-radius: 50%; width: 100px; height: 100px; background: lime; font-size: 20px; text-align: center; line-height: 100px; cursor: move; z-index: 100;">0001</div>
  <div id="0002" href="http://127.0.0.1/0002.html" style="position: relative; border-radius: 50%; width: 100px; height: 100px; background: lime; font-size: 20px; text-align: center; line-height: 100px; cursor: move; z-index: 100;">0002</div>
  <div id="0003" href="http://127.0.0.1/0003.html" style="position: relative; border-radius: 50%; width: 100px; height: 100px; background: lime; font-size: 20px; text-align: center; line-height: 100px; cursor: move; z-index: 100;">0003</div>
</div>

Solution:

haydenwagner provided the solution in an answer below.

$('.marker_mother div').each(function(index, item) {
Community
  • 1
  • 1
mycognosist
  • 133
  • 1
  • 1
  • 7

2 Answers2

0

To me it looks like you are affecting the marker_mother element instead of its children (the divs that you appended).

Try changing this code:

$('.marker_mother').each(function(index, item) {

to this:

$('.marker_mother div').each(function(index, item) {

so that the elements that you are making draggable in the each function are the divs inside the .marker_mother element.

If this works then you can add a '.marker' or '.'marker-draggable' class to these divs so that your selection can be more explicit (with the code above, all divs inside the '.marker_mother' will become draggable). This may not be necessary if you are only appending draggable elements to the '.marker_mother' element.

haydenwagner
  • 546
  • 2
  • 6
  • 15
  • I'm afraid it doesn't work. Any other ideas? Your suggestion regarding the '.marker-draggable' class is a good one. In my case though, all divs in the '.marker_mother' class will be draggable. – mycognosist Jan 19 '17 at 14:20
  • can you make a codepen or fiddle that reproduces your problem? I think your problem has to do with which elements you are selecting to make draggable. As I said above, '$('.marker_mother').each' will make each marker_mother draggable (not what you want, because marker_mother is the container). You need to select the children of marker mother to make draggable--I tried to do this in the answer above, but it is hard to know exactly what the selector should be without seeing a live example of your code. – haydenwagner Jan 19 '17 at 15:21
  • Here is a fiddle with the changed code: https://jsfiddle.net/dL2fnws8/8/ – mycognosist Jan 20 '17 at 09:43
  • Here this is your fiddle edited: https://jsfiddle.net/oua3Lud1/19/ -- As you can see you want the selector as 'marker_mother div' so that they are the draggable elements. I passed $(this) instead of $(item) to the coordinates function because that was giving me an error in your fiddle (I think the 'item' var was left over from when you were using the each() method) – haydenwagner Jan 20 '17 at 14:54
  • Awesome, thank you! I got it working. I appreciate you sticking with me. I was trying to implement the code in a script with other functions and it wasn't executing. I then tied the execution of the function to a button with onclick() and was able to get it working. – mycognosist Jan 23 '17 at 16:23
0

The issue is that you looping through all elements with the class marker_mother instead of the children. But in this case you don't need the $.each() loop here.

Just tweak your selector and draggable can handle the rest:

// Assigns top&left positions of dragged div to variables
  // Code to store coords in db will be added later

  var coordinates = function(element) {
    var top = element.position().top;
    var left = element.position().left;
  }

  // Loops through divs and makes each draggable


  $('.marker_mother div').draggable({
    start: function() {
      coordinates($(this));
    },
    stop: function() {
      coordinates($(this));
    }
  });

Example

empiric
  • 7,825
  • 7
  • 37
  • 48
  • Thanks for the input @empiric but your code isn't working for me. Once I make the changes none of the divs are draggable. – mycognosist Jan 19 '17 at 14:19
  • @mycognosist you might be missing something. Can you provide an example with the changed code? In fact I used the code provided by you to make my changes and it works in the example. – empiric Jan 19 '17 at 15:44
  • Here is a fiddle with the changed code: https://jsfiddle.net/dL2fnws8/8/ – mycognosist Jan 20 '17 at 09:43