Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Colour change on dragenter and dragleave not working jquery

When dragging and entering the <div class="upload-cont"> the color changes perfectly from gray to black of border and text and when it comes to the <span class="add-text"> it changes back to gray.

CSS:

.upload-cont{
    cursor:pointer;
    margin-left:130px;
    display:inline-block;
    border:2px dashed #a8a8a8;
    max-width:220px;
    max-height:180px;
    min-width:220px;
    min-height:180px;
    position:relative;
    border-radius:3px;
}
.add-text{
    display:block;
    font-size:10px;
    font-weight:bold;
    color:#999;
    word-wrap:break-word;
    text-align:center;
    width:100px;
    top:37%;
    left:25%;
    position:absolute;
}
.add-text:hover{ color:black; }

HTML:

<div class="upload-cont">
    <span class="add-text">
        Click to add or<br/>
        Drag and drop image here
    </span>
</div>

Jquery:

$(document).ready(function () {
    $(".upload-cont,.add-text").on('dragenter', function (e) {
        $(".upload-cont").css({
            "border": "2px dashed black"
        });
        $(".add-text").css({
            "color": "black"
        });
    });
    $(".upload-cont").on('dragleave', function (e) {
        $(".upload-cont").css("border", "2px dashed #a8a8a8");
        $(".add-text").css({
            "color": "#a8a8a8"
        });
    });
});

What can i do to remain the black color for the border and text when entering <span class="add-text">

Check this jsfiddle: http://jsfiddle.net/rpABs/

Thanks in advance

like image 406
harikrishnan.n0077 Avatar asked Jan 13 '13 05:01

harikrishnan.n0077


3 Answers

Use dragover instead of dragenter since dragleave fires when you enter child elements

$(".upload-cont,.add-text").on('dragover', function (e) {
    $(".upload-cont").css({
        "border": "2px dashed black"
    });
    $(".add-text").css({
        "color": "black"
    });
});
$(".upload-cont").on('dragleave', function (e) {
    $(".upload-cont").css("border", "2px dashed #a8a8a8");
    $(".add-text").css({
        "color": "#a8a8a8"
    });
});

DEMO

like image 150
Musa Avatar answered Oct 24 '22 11:10

Musa


Apparently this problem is more recurrent than I thought since I found at least 5 questions associated with the same topic (and I will answer all related with this issue).

Unlike "mouseover", the events "dragover" and "dragleave" do not consider the child elements as a whole, so each time the mouse passes over any of the children, "dragleave" will be triggered.

Thinking about the upload of files, I created a widget that allows:

  1. Drag and drop desktop files using $ _FILES
  2. Drag and drop to browser images/elements or url using $ _POST and cURL
  3. Attach a device file using button using $ _FILES
  4. Use input to write/paste url images/elements using $ _POST and cURL

enter image description here

The problem: As everything, both form inputs and images, are within DIVs children, "dragleave" was triggered even if it did not leave the dashed line. Using the attribute "pointer-events: none" is not an alternative since methods 3 and 4 need to trigger "onchange" events.

The solution? An overlapping DIV that covers all the drop-container when the mouse enters, and the only one with child elements with "pointer-events: none".

The structure:

  • div #drop-container: main div, keep all togheter
  • div #drop-area: "dragenter" listener and inmediate trigger #drop-pupup
  • div #drop-pupup: at same leval as #drop-area, "dragenter", "dragleave" and "drop" listener

Then, when the mouse enters by dragging an element to #drop-area, inmediatly shows #drop-pupup ahead and successively the events are on this div and not the initial receiver.

enter image description here

Here is the JS/jQuery code. I took the liberty to leave the PoC so do not lose all the time I lost.

jQuery(document).on('dragover', '#drop-area', function(event) {
	event.preventDefault();
	event.stopPropagation();
	jQuery('#drop-popup').css('display','block');
});

jQuery(document).on('dragover dragleave drop', '#drop-popup', function(event) {
	event.preventDefault();
	event.stopPropagation();

	console.log(event.type);

	// layout and drop events
	if ( event.type == 'dragover') {
		jQuery('#drop-popup').css('display','block');
	}
	else {
		jQuery('#drop-popup').css('display','none');
	
		if ( event.type == 'drop' ) {
			// do what you want to do
			// for files: use event.originalEvent.dataTransfer.files
			// for web dragged elements: use event.originalEvent.dataTransfer.getData('Text') and CURL to capture
		}
	}
});
body {
  background: #ffffff;
  margin: 0px;
  font-family: sans-serif;
}

#drop-container {
  margin: 100px 10%; /* for online testing purposes only */
  width: 80%; /* for jsfiddle purposes only */
  display: block;
  float: left;
  overflow: hidden;
  box-sizing: content-box;
  position: relative; /* needed to use absolute on #drop-popup */
  border-radius: 5px;
  text-align: center;
  cursor: default;
  border: 2px dashed #000000;
}

#drop-area {
  display: block;
  float: left;
  padding: 10px;
  width: 100%;
}

#drop-popup {
  display: none;
  box-sizing: content-box;
  position: absolute;
  width: 100%;
  top: 0;
  left: 0;
  background: linear-gradient(to BOTTOM, rgba(245, 245, 245, 1) , rgba(245, 245, 245, 0));
  height: 512px;
  padding: 20px;
  z-index: 20;
}

#drop-popup > p {
   pointer-events: none;
}
<html>
  <head>
    <title>Drag and Drop</title>
  </head>
  <body>

    <div id="drop-container">
      <div id="drop-area">
        <p>Child paragraph content inside drop area saying "drop a file or an image in the dashed area"</p>
        <div>This is a child div No. 1</div>
        <div>This is a child div No. 2</div>
      </div>
      <div id="drop-popup">
        <p>This DIV will cover all childs on main DIV dropover event and current P tag is the only one with CSS "pointer-events: none;"</p>
      </div>
    </div>
    
    <script src="https://code.jquery.com/jquery-3.4.1.min.js" type="text/javascript"></script>
  </body>
<html>

About jQuery "on", use it with the div id inside on, so you can start event triggers starting "uploading box" hidden.

Finally, I preferred to use "dragover" over "dragenter" because it has a small delay (milliseconds) that favors performance (https://developer.mozilla.org/en-US/docs/Web/API/Document/dragover_event).

like image 40
Benjamin Avatar answered Oct 24 '22 09:10

Benjamin


The dragover event fires constantly as you're dragging, so I'm not a fan of that solution. I've written a little library called Dragster that gives me better enter & leave events.

like image 32
Ben Avatar answered Oct 24 '22 11:10

Ben