I'm having issues to highlight the drop zone (defined with dropZone directive) when the dragged element is above it.
I've tried to use CSS:
.highlight {
background-color: rgba(0, 255, 0, 0.2);
}
.highlight:hover {
background-color: rgba(0, 255, 0, 0.5);
}
But this doesn't work because I'm dragging an element so the hover
is on the draggable element.
Here is the code:
var app = angular.module("myApp", []);
app.directive("dragCopy", function($http, $compile, $document) {
return {
restrict: 'A',
link: function($scope, $element) {
$element.on("mousedown", function($event) {
$event.preventDefault();
var newNode = $compile('<div class="dragFile" draggable-file>drag</div>')($scope);
newNode.children("#title").text($element.parent().text());
angular.element($document[0].body).append(newNode);
newNode.css({
top: $event.pageY - (newNode.prop("offsetHeight") * 0.9) + "px",
left: $event.pageX - (newNode.prop("offsetWidth") / 2) + "px",
});
newNode.triggerHandler("mousedown");
});
}
}
});
app.factory("dragDropService", function() {
var object = {
dropZoneList: [],
highlightList: [],
register: function(element) {
object.dropZoneList.push(element);
},
highlightDropZones: function() {
for (var i in object.dropZoneList) {
var element = object.dropZoneList[i].append('<div class="highlight"></div>');
var childrens = element.children();
object.highlightList.push(childrens[childrens.length - 1]);
}
},
resetDropZones: function() {
for (var i in object.highlightList) {
object.highlightList[i].remove();
}
}
};
return object;
});
app.directive("dropZone", function(dragDropService) {
return {
restrict: 'A',
link: function($scope, $element) {
dragDropService.register($element);
}
};
});
app.directive("draggableFile", function($document, dragDropService) {
return {
restrict: 'A',
link: function($scope, $element) {
var startX = 0,
startY = 0;
var x, y;
$element.on("mousedown", function($event) {
dragDropService.highlightDropZones();
startX = $element.prop("offsetWidth") / 2;
startY = $element.prop("offsetHeight") * 0.9;
$document.on("mousemove", mousemove);
$document.on("mouseup", mouseup);
});
function mousemove($event) {
y = $event.pageY - startY;
x = $event.pageX - startX;
$element.css({
top: y + "px",
left: x + "px"
});
}
function mouseup() {
$document.off("mousemove", mousemove);
$document.off("mouseup", mouseup);
$element.remove();
console.log(document.elementFromPoint(x, y));
dragDropService.resetDropZones();
}
}
}
});
.itemDrag {
cursor: pointer;
border: 3px solid #81CFE0;
border-radius: 50%;
font-size: 40px;
color: #81CFE0;
padding: 5px;
background-color: rgba(255, 255, 255, 0.5);
}
#receiver {
position: absolute;
left: 50%;
right: 0;
top: 0;
bottom: 0;
}
.dragFile {
position: absolute;
border: 1px solid #81CFE0;
border-radius: 5px;
background-color: rgba(129, 207, 224, 0.5);
cursor: pointer;
}
.highlight {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
color: #00FF00;
border: 3px dashed #00FF00;
border-radius: 5px;
text-align: center;
font-weight: bold;
text-shadow: 0px 0px 2px black;
background-color: rgba(0, 255, 0, 0.2);
}
.highlight:before {
content: "Add content to terminal";
}
.highlight:hover {
background-color: rgba(0, 255, 0, 0.5);
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div class="itemDrag fa fa-hand-pointer-o" drag-copy></div>
<div id="receiver" drop-zone></div>
</div>
Is it possible only using CSS ?
I found a solution to my problem. Thanks to your answers, I found another way through.
I'm listening to the mousemove
event on the dropZone
directive. This way if the mouse moves inside the drop zone it will trigger and add the style.
Here is the working code:
var app = angular.module("myApp", []);
app.directive("dragCopy", function($http, $compile, $document) {
return {
restrict: 'A',
link: function($scope, $element) {
$element.on("mousedown", function($event) {
$event.preventDefault();
var newNode = $compile('<div class="dragFile" draggable-file>drag</div>')($scope);
newNode.children("#title").text($element.parent().text());
angular.element($document[0].body).append(newNode);
newNode.css({
top: $event.pageY - (newNode.prop("offsetHeight") * 0.5) + "px",
left: $event.pageX - (newNode.prop("offsetWidth") / 2) + "px",
});
newNode.triggerHandler("mousedown");
});
}
}
});
app.factory("dragDropService", function() {
var object = {
dropZoneList: [],
callbackList: [],
highlightList: [],
register: function(element, callback) {
object.dropZoneList.push(element);
object.callbackList.push(callback);
},
highlightDropZones: function() {
for (var i in object.dropZoneList) {
object.dropZoneList[i].append('<div class="highlight"></div>');
var childrens = object.dropZoneList[i].children();
object.highlightList.push(childrens[childrens.length - 1]);
object.callbackList[i]();
}
},
resetDropZones: function() {
for (var i in object.highlightList) {
object.callbackList[i]();
object.highlightList[i].remove();
}
object.highlightList = [];
}
};
return object;
});
app.directive("dropZone", function($document, dragDropService) {
return {
restrict: 'A',
link: function($scope, $element) {
var highlighted = false;
function toggleHover() {
if (highlighted) {
$document.off("mousemove", mousemove);
highlighted = false;
} else {
$document.on("mousemove", mousemove);
highlighted = true;
}
}
function mousemove($event) {
x = $event.pageX;
y = $event.pageY;
elementBounding = $element[0].getBoundingClientRect();
console.log("in");
if (x > elementBounding.left && x < elementBounding.right && y > elementBounding.top && y < elementBounding.bottom) {
angular.element($element.children()[$element.children().length - 1]).addClass("droppable");
} else {
angular.element($element.children()[$element.children().length - 1]).removeClass("droppable");
}
}
dragDropService.register($element, toggleHover);
}
};
});
app.directive("draggableFile", function($document, dragDropService) {
return {
restrict: 'A',
link: function($scope, $element) {
var startX = 0,
startY = 0;
var x, y;
$element.on("mousedown", function($event) {
dragDropService.highlightDropZones();
startX = $element.prop("offsetWidth") / 2;
startY = $element.prop("offsetHeight") * 0.5;
$document.on("mousemove", mousemove);
$document.on("mouseup", mouseup);
});
function mousemove($event) {
x = $event.pageX - startX;
y = $event.pageY - startY;
$element.css({
left: x + "px",
top: y + "px"
});
}
function mouseup() {
$document.off("mousemove", mousemove);
$document.off("mouseup", mouseup);
$element.remove();
console.log(document.elementFromPoint(x, y));
dragDropService.resetDropZones();
}
}
};
});
.itemDrag {
cursor: pointer;
border: 3px solid #81CFE0;
border-radius: 50%;
font-size: 40px;
color: #81CFE0;
padding: 5px;
background-color: rgba(255, 255, 255, 0.5);
}
#receiver1 {
position: absolute;
left: 50%;
right: 0;
top: 0;
bottom: 50%;
}
#receiver2 {
position: absolute;
left: 50%;
right: 0;
top: 50%;
bottom: 0;
}
.dragFile {
position: absolute;
border: 1px solid #81CFE0;
border-radius: 5px;
background-color: rgba(129, 207, 224, 0.5);
cursor: pointer;
}
.highlight {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
color: #00FF00;
border: 3px dashed #00FF00;
border-radius: 5px;
text-align: center;
font-weight: bold;
text-shadow: 0px 0px 2px black;
background-color: rgba(0, 255, 0, 0.2);
}
.highlight:before {
content: "Add content to terminal";
}
.highlight.droppable {
background-color: rgba(0, 255, 0, 0.5);
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div class="itemDrag fa fa-hand-pointer-o" drag-copy></div>
<div id="receiver1" drop-zone></div>
<div id="receiver2" drop-zone></div>
</div>
You can use document.elementFromPoint to identify the element the cursor is on. Now you just have to verify that it has the 'highlight' class.
btw - If you'll use translate to move the element image, the document.elementFromPoint will have better results, because the dragged element won't interfere.
function mousemove($event) {
y = $event.pageY - startY;
x = $event.pageX - startX;
var dropElement = document.elementFromPoint(x, y);
console.log(dropElement.classList.contains('highlight'));
$element.css({
top : y + "px",
left : x + "px"
});
}
Is it possible only using CSS ?
The truth is, it is up to the browser to decide if an element is hovered or not. So if he says NO, then I'm not sure if CSS would be enough if :hover
or :active
won't be triggered in the first place.
Anyway, this is one more JS solution using Angular's built-in behaviors :
Add this to your CSS :
.hovered {
background-color: rgba(0, 255, 0, 0.5);
cursor: pointer;
z-index: 999;
}
Then use mouseenter and mouseleave behaviors inside your dropZone directive like so :
app.directive("dropZone", function(dragDropService) {
return {
restrict: 'A',
link: function($scope, $element) {
dragDropService.register($element);
$element.bind("mouseenter", function(e){
// if mouse's button is not clicked then we are not dragging
if(e.buttons == 1 || e.buttons == 3){
$element.addClass('hovered');
}
});
$element.bind("mouseleave", function(){
$element.removeClass('hovered');
});
}
};
});
This Snippet shows how it works :
var app = angular.module("myApp", []);
app.directive("dragCopy", function($http, $compile, $document) {
return {
restrict: 'A',
link: function($scope, $element) {
$element.on("mousedown", function($event) {
$event.preventDefault();
var newNode = $compile('<div class="dragFile" draggable-file>drag</div>')($scope);
newNode.children("#title").text($element.parent().text());
angular.element($document[0].body).append(newNode);
newNode.css({
top: $event.pageY - (newNode.prop("offsetHeight") * 0.9) + "px",
left: $event.pageX - (newNode.prop("offsetWidth") / 2) + "px",
});
newNode.triggerHandler("mousedown");
});
}
}
});
app.factory("dragDropService", function() {
var object = {
dropZoneList: [],
highlightList: [],
register: function(element) {
object.dropZoneList.push(element);
},
highlightDropZones: function() {
for (var i in object.dropZoneList) {
var element = object.dropZoneList[i].append('<div class="highlight"></div>');
var childrens = element.children();
object.highlightList.push(childrens[childrens.length - 1]);
}
},
resetDropZones: function() {
for (var i in object.highlightList) {
object.highlightList[i].remove();
}
}
};
return object;
});
app.directive("dropZone", function(dragDropService) {
return {
restrict: 'A',
link: function($scope, $element) {
dragDropService.register($element);
$element.bind("mouseenter", function(e){
if(e.buttons == 1 || e.buttons == 3){
$element.addClass('hovered');
}
});
$element.bind("mouseleave", function(){
$element.removeClass('hovered');
});
}
};
});
app.directive("draggableFile", function($document, dragDropService) {
return {
restrict: 'A',
link: function($scope, $element) {
var startX = 0,
startY = 0;
var x, y;
$element.on("mousedown", function($event) {
dragDropService.highlightDropZones();
startX = $element.prop("offsetWidth") / 2;
startY = $element.prop("offsetHeight") * 0.9;
$document.on("mousemove", mousemove);
$document.on("mouseup", mouseup);
});
function mousemove($event) {
y = $event.pageY - startY;
x = $event.pageX - startX;
$element.css({
top: y + "px",
left: x + "px"
});
}
function mouseup() {
$document.off("mousemove", mousemove);
$document.off("mouseup", mouseup);
$element.remove();
console.log(document.elementFromPoint(x, y));
dragDropService.resetDropZones();
}
}
}
});
.itemDrag {
cursor: pointer;
border: 3px solid #81CFE0;
border-radius: 50%;
font-size: 40px;
color: #81CFE0;
padding: 5px;
background-color: rgba(255, 255, 255, 0.5);
}
#receiver {
position: absolute;
left: 50%;
right: 0;
top: 0;
bottom: 0;
}
.dragFile {
position: absolute;
border: 1px solid #81CFE0;
border-radius: 5px;
background-color: rgba(129, 207, 224, 0.5);
cursor: pointer;
}
.highlight {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
color: #00FF00;
border: 3px dashed #00FF00;
border-radius: 5px;
text-align: center;
font-weight: bold;
text-shadow: 0px 0px 2px black;
background-color: rgba(0, 255, 0, 0.2);
}
.highlight:before {
content: "Add content to terminal";
}
.hovered {
background-color: rgba(0, 255, 0, 0.5);
cursor: pointer;
z-index: 999;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div class="itemDrag fa fa-hand-pointer-o" drag-copy></div>
<div id="receiver" drop-zone></div>
</div>
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