views:

1842

answers:

6

Hello.

Don't let below code scare you away. The question is really simple, only two lines are making trouble:

Why do my code generated a NaN error code? I am trying to substract one variable value from another so position of elements will be correct.

The variables got their value from jQuery position() which is supposed to be integer anyways.

Check the lines these lines:

// For some reason NaN error code gets generated when line below gets executed.
var posTop = Startpos.top - Stoppos.top;
var posLeft = Startpos.left - Stoppos.left;

Complete code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
    <meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
    <title>Drag drop 1</title>
    <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
    <script type="text/javascript" src="js/jquery-ui-1.7.1.custom.min.js"></script>
    <script type="text/javascript">
    $(document).ready(function() {
     var Startpos = new Array;
     var Stoppos = new Array;

     // Make images draggable.
     $(".item").draggable({

      // Elements cannot go outside #container
      containment: 'parent',

      // Make sure the element can only be dropped in a grid.
      grid: [150,150],

      // Find original position of dragged image.
      start: function(event, ui) {

       // Make sure picture always are on top when dragged (z-index).
       $(this).css({'z-index' : '100'});

       // Show start dragged position of image.
       Startpos = $(this).position();
       $("div#start").text("START: \nLeft: "+ Startpos.left + "\nTop: " + Startpos.top);
      },

      // Find position where image is dropped.
      stop: function(event, ui) {

       // Revert to default layer position when dropped (z-index).
       $(this).css({'z-index' : '10'});

       // Show dropped position.
       Stoppos = $(this).position();
       $("div#stop").text("STOP: \nLeft: "+ Stoppos.left + "\nTop: " + Stoppos.top);
      }
     });
     $(".item").droppable({
      drop: function(event, ui) {

       // Dragged image gets swapped with dropped on image.
       var prev_position = "#" + $(this).attr('id');
       // For some reason NaN error code gets generated when line below gets executed.
       var posTop = Startpos.top - Stoppos.top;
       var posLeft = Startpos.left - Stoppos.left;

       // Below variables will work. But unfortunately they
       // doesn't give the correct numbers for the purpose.
       // var posTop = Startpos.top;
       // var posLeft = Startpos.left;

       $(prev_position).css({'top' : posTop, 'left' : posLeft});

       $("div#test").text("Passed variables. Top: " + posTop + " left: " + posLeft);
      }
     });
    });
    </script>
    <style>
    body {

    }
    #container {
     position:relative;
     width:480px;
     border:1px solid #000;
    }
    .item {
     position:relative;
     width:150px;
     height:150px;
     z-index:10;
    }
    </style>
</head>
<body>
    <div id="container">
     <img id="productid_1" src="images/pic1.jpg" class="item" alt="" title="" /><img id="productid_2" src="images/pic2.jpg" class="item" alt="" title="" /><img id="productid_3" src="images/pic3.jpg" class="item" alt="" title="" /><img id="productid_4" src="images/pic4.jpg" class="item" alt="" title="" /><img id="productid_5" src="images/pic5.jpg" class="item" alt="" title="" /><img id="productid_6" src="images/pic6.jpg" class="item" alt="" title="" /><img id="productid_7" src="images/pic7.jpg" class="item" alt="" title="" /><img id="productid_8" src="images/pic8.jpg" class="item" alt="" title="" /><img id="productid_9" src="images/pic9.jpg" class="item" alt="" title="" />
    </div>
    <div style="clear:both;"></div>
    <div id="start">Waiting...</div>
    <div id="stop">Waiting...</div>
    <div id="hover">Waiting...</div>
    <div id="stop2">Waiting...</div>
    <div id="test">Waiting...</div>
</body>
</html>
+1  A: 

As far as I know position() isn't a jQuery function.

Try this instead:

Startpos = $(this).offset();

You should then be able to access the top and left properties.

peirix
Actually you can use position() See link: http://docs.jquery.com/CSS/positionDoes return the position of an element.
Cudos
+2  A: 

The problem is that droppable.drop() is called before draggable.stop(). So your Stoppos is not yet calculated.

One way to deal with this would be to simply track what item is being dragged, and calculate the position for that in droppable.drop(). e.g. (subset of your code), notice the "Dragging" object.

$(document).ready(function() {
        var Startpos = new Array;
        var Stoppos = new Array;
        var Dragging = null;

        // Make images draggable.
        $(".item").draggable({

                // Elements cannot go outside #container
                containment: 'parent',

                // Make sure the element can only be dropped in a grid.
                grid: [150,150],

                // Find original position of dragged image.
                start: function(event, ui) {
                        Dragging=this;
                        // Make sure picture always are on top when dragged (z-index).
                        $(this).css({'z-index' : '100'});

                        // Show start dragged position of image.
                        Startpos = $(this).position();
                        $("div#start").text("START: \nLeft: "+ Startpos.left + "\nTop: " + Startpos.top);
                },

                // Find position where image is dropped.
                stop: function(event, ui) {
                        // Revert to default layer position when dropped (z-index).
                        $(this).css({'z-index' : '10'});

                        // Show dropped position.
                        Stoppos = $(this).position();
                        $("div#stop").text("STOP: \nLeft: "+ Stoppos.left + "\nTop: " + Stoppos.top);
                        Dragging=null;
                }
        });

However, there are probably several other legitimate ways around this.

larson4
I also wonder-- what's the point of initializing Stoppos and Startpos to an array? Why not just leave them uninitialized or setting =null ?
larson4
Hmmm... What puzzles me is that replacing:var posTop = Startpos.top - Stoppos.top;var posLeft = Startpos.left - Stoppos.left;With:var posTop = Startpos.top;var posLeft = Startpos.left;Will work even though the numbers are not what I wan't.
Cudos
initializing Stoppos and Startpos makes them available in the global scope. But I'm new to global variables in javascript. Just tried something that seemed to work.
Cudos
A: 

are you sure that these are the lines causing the problem? -

can you please confirm that "var posTop = Startpos.top - Stoppos.top; "

returns a valid Integer/Double value to posTop? I was coding on one of my projects last week and had the same NaN problem, i tried to Parse the value to Integer and it worked.

Because you are making a mathematical calculation, try parsing the values into Double/Int before you subtract them,

Sometimes, the solution is pretty simple and we tend to over complicate it.

If Parsing does not work, it could be that you are not passing in the right value from the array. Try something like Startpos[0].Top

Hope this helps, Good luck!

Mponnada
I tried the parseInt() with no luck: var posTop = parseInt(Startpos.top - Stoppos.top); or var posTop = parseInt(Startpos.top) - parseInt(Stoppos.top);
Cudos
A: 

Either Startpos or Stoppos are still just an empty array when you come perform this calculation.

Try setting them to a suitable default instead (0, 0), as this may make it easier to track down what is going astray.

rikh
A: 

What puzzles me is that this works:

replace:

var posTop = Startpos.top - Stoppos.top;
var posLeft = Startpos.left - Stoppos.left;

With:

var posTop = Startpos.top;
var posLeft = Startpos.left;

Will work even though the numbers are not what I want. It seems a simples substraction is invalid for some reason.

Cudos
Arnis L.
Yes they are. The problem is elsewhere.
Cudos
A: 

Thanks for the help guys :)

Found the problem.

Stoppos = $(this).position();

Should not be in:

$(".item").draggable({
stop: function(event, ui) {

But instead in:

$(".item").droppable({
drop: function(event, ui) {

Complete code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
    <meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
    <title>Drag drop 1</title>
    <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
    <script type="text/javascript" src="js/jquery-ui-1.7.1.custom.min.js"></script>
    <script type="text/javascript">
    $(document).ready(function() {
     var Startpos = null;
     var Stoppos = null;

     // Make images draggable.
     $(".item").draggable({

      // Elements cannot go outside #container
      containment: 'parent',

      // Make sure the element can only be dropped in a grid.
      grid: [150,150],

      // Find original position of dragged image.
      start: function(event, ui) {

       // Make sure picture always are on top when dragged (z-index).
       $(this).css({'z-index' : '100'});

       // Show start dragged position of image.
       Startpos = $(this).position();
       $("div#start").text("START: \nLeft: "+ Startpos.left + "\nTop: " + Startpos.top);
      },

      // Find position where image is dropped.
      stop: function(event, ui) {

       // Revert to default layer position when dropped (z-index).
       $(this).css({'z-index' : '10'});
      }
     });
     $(".item").droppable({
      drop: function(event, ui) {

       // Dragged image gets swapped with dropped on image.
       var prev_position = "#" + $(this).attr('id');
       Stoppos = $(this).position();
       var posTop = Startpos.top - Stoppos.top;
       var posLeft = Startpos.left - Stoppos.left;
       $(prev_position).css({'top' : posTop, 'left' : posLeft});

       // Test window
       $("div#stop").text("STOP: \nLeft: "+ Stoppos.left + "\nTop: " + Stoppos.top);
       $("div#test").text("Passed variables. Top: " + posTop + " left: " + posLeft);
      }
     });
    });
    </script>
    <style>
    body {

    }
    #container {
     position:relative;
     width:480px;
     border:1px solid #000;
    }
    .item {
     position:relative;
     width:150px;
     height:150px;
     z-index:10;
    }
    </style>
</head>
<body>
    <div id="container">
     <img id="productid_1" src="images/pic1.jpg" class="item" alt="" title="" /><img id="productid_2" src="images/pic2.jpg" class="item" alt="" title="" /><img id="productid_3" src="images/pic3.jpg" class="item" alt="" title="" /><img id="productid_4" src="images/pic4.jpg" class="item" alt="" title="" /><img id="productid_5" src="images/pic5.jpg" class="item" alt="" title="" /><img id="productid_6" src="images/pic6.jpg" class="item" alt="" title="" /><img id="productid_7" src="images/pic7.jpg" class="item" alt="" title="" /><img id="productid_8" src="images/pic8.jpg" class="item" alt="" title="" /><img id="productid_9" src="images/pic9.jpg" class="item" alt="" title="" />
    </div>
    <div style="clear:both;"></div>
    <div id="start">Waiting...</div>
    <div id="stop">Waiting...</div>
    <div id="hover">Waiting...</div>
    <div id="stop2">Waiting...</div>
    <div id="test">Waiting...</div>
</body>
</html>

Now I just have to figure out how to get the placements of the images right when they have been moved more than one time. It seems that position:relative is automatically added to draggables and make trouble in calculating the positions :(

Cudos