Wracker Wracker - 4 days ago 6
Javascript Question

Highlighting only the droppable which is hovered or to which item is dropped

What I'd like to do is to set border color to blue for

.droparea
element that contains an
.item
element.

Also there is also a hover effect for the
.droparea
which changes the border color to blue.

So if I move the
.item
element to another
.droparea
it should automatically change border color for the current
.droparea
to blue and change the border of previously used
.droparea
to default color (black).



$(document).ready(function() {
$(".item").draggable({
scroll: false,
revert: 'invalid',
stack: false,
create: function() {
$(this).data('position', $(this).position())
},
cursor: "pointer",
start: function() {
$(this).stop(true, true)
},
drag: function(event, ui) {
$(".droparea").removeClass("highlight");
}
});
$(".droparea").droppable({
accept: ".item",
drop: function(event, ui) {
$(this).addClass("highlight").find("p");
snapToMiddle(ui.draggable, $(this));
}
});
});

function snapToMiddle(dragger, target) {
var topMove = target.position().top - dragger.data('position').top + (target.outerHeight(true) - dragger.outerHeight(true)) / 2;
var leftMove = target.position().left - dragger.data('position').left + (target.outerWidth(true) - dragger.outerWidth(true)) / 2;
dragger.animate({
top: topMove,
left: leftMove
}, {
duration: 200,
easing: 'linear'
});
}

.item {
position: relative;
margin: 0 auto;
width: 100px;
height: 100px;
border: 1px solid red;
}
.droparea {
width: 150px;
height: 150px;
float: left;
margin: 2px;
border: 1px solid #000;
outline: 1px solid transparent
}
.highlight {
border: 1px solid blue
}
.droparea:hover {
border: 1px solid blue
}

<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.js"></script>

<div class="droparea">
<div class="item"></div>
</div>


<div class="droparea"></div>
<div class="droparea"></div>




T J T J
Answer

Few things to note here:

  • jQuery UI draggable only adjusts the style of an element, It does not alter its position in DOM, So the .item will always be the child of first draggable, and since you've specified the CSS :hoverpseudo selector - .droparea:hover, You'll always be hovering the first droppable while dragging since you're hovering it's child.
  • We can fix this issue by setting highlight class on hover using the hoverClass option of draggable, but since you're removing the highlight during drag event, the class set on hover will be immediately removed. So we should not remove the class on drag.
  • Finally, You can use jQuery UI's position() utility method for center aligning the item on drop.

So you can achieve what you're trying to as following:

$(document).ready(function() {
  $(".item").draggable({
    scroll: false,
    revert: 'invalid',
    stack: false,
    cursor: "pointer",
  });
  $(".droparea").droppable({
    accept: ".item",
    hoverClass: "highlight",
    drop: function(event, ui) {
      var $this = $(this);
      $(".highlight").removeClass("highlight");
      $this.addClass("highlight");
      ui.draggable.position({
        my: "center",
        at: "center",
        of: $this,
        using: function(pos) {
          $(this).animate(pos, 200, "linear");
        }
      });
    }
  });
});
.item {
  position: relative;
  margin: 0 auto;
  width: 100px;
  height: 100px;
  border: 1px solid red;
}
.droparea {
  width: 150px;
  height: 150px;
  float: left;
  margin: 2px;
  border: 1px solid #000;
  outline: 1px solid transparent
}
.highlight {
  border: 1px solid blue
}
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.js"></script>

<div class="droparea">
  <div class="item"></div>
</div>

<div class="droparea"></div>
<div class="droparea"></div>


Also, I've to warn you that jQuery UI and CSS float have a bad history, which is evident if you visit bugs.jqueryui.com. You're better of using display:inline-block for this purpose, you can even avoid speciying margin manually.

Comments