Drag the entire parent div with just the handle - javascript

I intend to drag the entire parent div with only the handle attached to its left. See below code snippet, the 30x30 image is my drag handle for now:
var DRAG_CLASS = "beingdragged";
div.ondragstart = function() {
this.classList.add(DRAG_CLASS);
};
div.ondragend = function() {
this.classList.remove(DRAG_CLASS);
};
img {
cursor: move;
float: left;
}
div {
border: 1px solid red;
background: lightblue;
width: 100%;
transform: 0.5s ease;
}
div.beingdragged {
width: 95%;
}
<!DOCTYPE html>
<html>
<body>
<div id="div" draggable="true"><img src="https://placehold.it/30x30">
<p>this is some text</p>
</div>
</body>
</html>
I want the entire div to move along with the cursor as the user moves the cursor around, and as one would expect in a drag operation. However, as you can observe in the output, only the image is being dragged, even though I have set draggable="true" to the entire parent div. The entire parent div stays where it was even though the cursor moves around.
I have added a class DRAG_CLASS to the div, so as you can see, the dragstart and the dragend events are firing correctly.
What then is the issue?

Sure the div is draggable, as you can see when you drag it around somewhere other than the image.
However the image is also, by default, independently draggable. Easy to disable, though, with draggable="false" or the appropriate css rule.
var DRAG_CLASS = "beingdragged";
div.ondragstart = function() {
this.classList.add(DRAG_CLASS);
};
div.ondragend = function() {
this.classList.remove(DRAG_CLASS);
};
img {
cursor: move;
float: left;
}
div {
border: 1px solid red;
background: lightblue;
width: 100%;
transform: 0.5s ease;
}
div.beingdragged {
width: 95%;
}
<!DOCTYPE html>
<html>
<body>
<div id="div" draggable="true"><img draggable="false" src="https://placehold.it/30x30">
<p>this is some text</p>
</div>
</body>
</html>

Related

Resizing one element using jQuery UI changing the position of another

I am trying to make resizible and draggable lines out of labels using jQuery UI.
The problem is, if I add two labels and try to resize the first label, it changes the position of the second label (but if I resize the second label it does not change the position of the first label).
How to prevent labels from changing other label's position while resizing..?
HTML:
<div id="main">
<button id="s">add line</button>
</div>
<div id="line" class="hidden">
<label class="dra"></label>
</div>
JS:
function makeline() {
$t = $(".dra", "#line").clone(true).draggable().resizable({
handles: "s, n"
});
$("#main").append($t);
}
$("#s").click(function () {
makeline();
});
CSS:
.dra {
display: block;
background-color:red;
width: 7px;
height: 80px;
border: 1px solid red;
}
.hidden {
display: none;
}
#main {
border: 1px solid black;
width:500px;
height: 300px;
}
UPDATE: Full code in JSFiddle
This is happening because the jQuery UI widgets set the position of element to relative by default, leaving it in the normal flow of the document. You can work around this issue by applying position:absolute for the elements like:
.ui-resizable {
position:absolute !important;
}
This will cause them to stack on top of each other rather than one below another since they aren't in the normal flow anymore. You can easily fix this using the jQuery ui position() utility method as shown below:
$("#s").click(function() {
$t = $("#line .dra").clone(true).draggable().resizable({
handles: "s, n"
})
if ($("#main").find(".dra").length) {
$t.position({
at: "left bottom",
of: "#main .dra:last"
})
};
$("#main").append($t);
});
.dra {
display: block;
background-color: red;
width: 7px;
height: 80px;
border: 1px solid red;
}
.hidden {
display: none;
}
#main {
border: 1px solid black;
width: 500px;
height: 300px;
}
.ui-resizable {
position: absolute !important;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<div class="form-group">
<label>ADD two line and RESIZE THE FIRST LINE it will scroll down the line added after it. NOW add a 3rd line and resize the second line it will scroll down the 3rd line and if you resize the very first line you added it will scroll down the other lines</label>
<div id="main">
<button id="s">add line</button>
</div>
<div id="line" class="hidden">
<label class="dra"></label>
</div>
You can adjust the positioning however you want.
If your label is:
<div class="label">Lorem ipsum</div>
add this CSS:
.label {
white-space: nowrap;
}

How to put img in front of svg tag

I'm using snap.svg
I have index.html
<!Doctype>
<html>
<head>
<title>MAP_TEST</title>
<meta charset="utf-8">
<script type = "text/javascript" src = "JS/jquery.js"></script>
<script type = "text/javascript" src = "JS/init.js"></script>
<script type = "text/javascript" src = "JS/snap.svg.js"></script>
</head>
<body>
<div class="comm_cont">
<div id = "svgborder">
<svg id = 'svgmain'></svg>
</div>
</div>
</body>
</html>
And init.js
$( document ).ready(function() {
var s = Snap("#svgmain");
var g = s.group();
Snap.load("SVGFILES/3k1e-test.svg",function(lf)
{
g.append(lf);
//trying to load picture... Scale button in future
$('<img />', {
src: 'PNG/plus.png',
width: '30px',
height: '30px',
id: 'buttoninrk'
}).appendTo($('.comm_cont'));
//this button must be on picture
//but in front of the picture svg element
//And i can't click the button
});
});
I played with z-indexes of #svgborder and #buttoninkr but it didn't help me.
How to put button in front of svg element?
#buttoninkr, #svgborder
{
position: absolute;
}
#svgborder
{
border:5px solid black;
z-index: 0;
margin-left:auto;
border-radius: 5px;
display: inline-block;
}
#buttoninkr
{
z-index: 1;
}
Added css code with z-indexes.
There is a reason why i'm not using svg buttons instead jquery image button.
Ok, as you can see #svgmain in front of plus.png
http://jsfiddle.net/3wcq9aad/1/
Any ideas?
Solved
#svgborders
{
position: absolute;
background-color: #535364;
border:5px solid black;
z-index: 0;
margin-left:auto;
border-radius: 5px;
display: inline-block;
}
#buttoninrk, #buttondekr, #home_btn
{
position: inherit;
top:0;
margin:10px;
z-index: 1;
}
#buttoninrk
{
right:0px;
}
#buttondekr
{
right:60px
}
EDIT: It wasn't the position of the div that made the difference, but simply adding a width and height. So the original HTML works fine as long as you add a width and height to svgborder in the CSS:
http://jsfiddle.net/3wcq9aad/4/
(Note that sometimes, the position of an element within a document can make a difference to how z-index works.)
If you put the svgborder div before the svg, then z-index will work, but you'll need to know the width and height of your SVG and set it on the svgborder div.
<body>
<div class="comm_cont">
<div id="svgborder"></div>
<svg id='svgmain'></svg>
</div>
</body>
#svgborder
{
z-index: 2;
width:330px;
height:150px;
...
}
Fiddle: http://jsfiddle.net/3wcq9aad/3/
svg does not support z-index
Use element position instead:
$('element').css('position', 'absolute');
Is there a way in jQuery to bring a div to front?

javascript window scroll issue

I am working on javascript scroll. I have following html code
JSFIDDLE
<div class="wrapper">
<div class="red div current"></div>
<div class="blue div"></div>
<div class="green div"></div>
<div class="yellow div"></div>
</div>
In above code I have four div tags red, blue, green and yellow. All of them are position in following css.
html, body {
height: 100%;
}
.wrapper {
overflow: hidden;
height: 100%;
}
.div {
position: relative;
height: 100%;
}
.red {
background: red;
}
.blue {
background: blue;
}
.green {
background: green;
}
.yellow {
background: yellow;
}
In above html and css the red div tag is the current one which means user is seeing the red div tag on the screen. Now what I am trying to do is when user scroll over window once, then the next div tag i.e. blue will be animated and moved to the top and will become visible to the user whereas the red div tag will be behind the blue one. This same process goes for both green and yellow.
The problem is that when user scroll once then the div tag should animate however my current javascript code is keep reading the scroll and animating the div tags one after another. What I want is when user scroll once then scroll should be disabled until the blue div tag is animated. Then scroll should be enabled. Again when user scroll second time, the scroll should disable until the green div tag completes its animation. Same goes for yellow.
How can I achieve above?
Here is my javascript
$(window).on("scroll", function () {
var next = $('.current').next();
var height = next.outerHeight();
next.animate({top: '-=' + height}, 500, function () {
$(this).prev().removeClass('current');
$(this).addClass('current');
});
});
Please have a look on update JsFiddle
$(window).on("scroll", function () {
var next = $('.current').next();
var height = $('.current').outerHeight();
$('.current').prevAll().each(function(){
height += $(this).outerHeight();
});
next.animate({top: '-=' + height}, 500, function () {
$(this).prev().css('top','');
$(this).prev().toggleClass('current');
$(this).toggleClass('current');
});
});
The main reason your example wasn't working as expected is because you were relatively positioning the divs, and not moving them to the correct spot.
Working JSFiddle:
http://jsfiddle.net/seanjohnson08/rVVuc/6/
.wrapper {
overflow: hidden;
height: 100%;
position: relative;
}
.div {
position: absolute;
height: 100%;
width: 100%;
top: 100%;
}
.current{
top: 0;
}
If you are looking for a way to limit the amount of scroll events fired, try throttling: http://benalman.com/projects/jquery-throttle-debounce-plugin/. My solution doesn't require this, because no matter how many times it is firing the scroll event, it only ever tells jquery to animate to top:0, there's no chance of it animating past that.

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
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
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:
Drag and drop desktop files using $ _FILES
Drag and drop to browser images/elements or url using $ _POST and cURL
Attach a device file using button using $ _FILES
Use input to write/paste url images/elements using $ _POST and cURL
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.
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).
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.

The drag doesn't work when it has a siblings img in IE

I'm trying to make a drag box with a sibling img and the 'move-obj' can be dragged.It runs correctly in other browser but IE(8,9,10). In IE, just while you hover the border can you drag the 'move-obj', but if you remove the tag 'img' it work correctly.I found that if I add a background-color to the 'move-obj',it will run correctly too, but it isn't what I want. Can somebody give me some advice?Here is the codepen
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.wrap{
position: relative;
width: 100%;
height: 100%;
background-color: #f0f0f0;
padding: 10%;
}
.wrap-inside{
position: relative;
width: 500px;
height: 500px;
border: 1px solid #ddd;
}
.move-obj{
cursor: move;
position: absolute;
width: 100px;
height: 100px;
border: 1px solid blue;
}
.bg{
width: 500px;
height: 500px;
position: absolute;
}
</style>
</head>
<body>
<div class="wrap">
<img class="bg" src="https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcTE2qkLv64zdI4z5uIbE1oSMmI0AiQcbwbhAYAyI0cF2Dwg88tb" alt="">
<div class="wrap-inside">
<div class="move-obj"></div>
</div>
</div>
</body>
</html>
If I understand you correctly if and only if you are hovering over the mov-obj div you want to be able to move around the https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcTE2qkLv64zdI4z5uIbE1oSMmI0AiQcbwbhAYAyI0cF2Dwg88tb image, right?
If this is what you want, look into either using jQuery and selecting the div on a hover event
$(.mov-obj).hover(function(event) {
//change the x and y coordinates of the image dynamically here of the image
//you can use the event.pageX and event.pageY (I think) to get how much/many pixels have been moved since the hover happened
}
or you can use pure JavaScript
document.getElementsByClassName("mov-obj").addEventListener("mouseenter", function( event ) {
//do something to change the img position dynamically
}, false);
//also do it for the mouseleave event
document.getElementsByClassName("mov-obj").addEventListener("mouseleave", function( event ) {
//do something to change the img position dynamically
}, false);
maybe set a flag letting you know that the mouseenter has happened, but not the mouseleave event
and then if and only if the mouse is inside the div add a click event to the div
while the click is pressed and the mouseleave event hasn't been triggered dynamically relocate the image depending on how much the mouse pointer has moved
(you can add a click event like this fyi)
document.getElementsByClassName("mov-obj").addEventListener("click", function( event ) {
//do something to change the img position dynamically
}, false);
or with jQuery
$(.mov-obj).click(function(event) {
//do something
}
hope this helps
Edit, just paste this code into a browser and try it out:
Note: this only works if you don't move the mouse outside of the div's width and height that you are wanting to move. I'll let you figure out how to fix that part if the mouse goes outside the div what happens
<DOCTYPE html>
<html>
<head>
</head>
<body>
<style>
#div1 {
border: 2px orange solid;
width: 500px;
height: 500px;
}
#div2 {
border: 2px purple solid;
width: 250px;
height: 250px;
position: absolute;
}
</style>
<div id="div1">
<div id="div2">
</div>
</div>
<script type="text/javascript">
// add event listeners to div
var div2 = document.getElementById("div2");
div2.addEventListener("mousedown", getOriginalPosition, false);
div2.addEventListener("mouseup", changeLocation, false);
var helperX;
var helperY;
function getOriginalPosition(event) {
//use these to help with the calculation later
helperX = event.offsetX;
helperY = event.offsetY;
}
var end_xPosition;
var end_yPosition;
function changeLocation(event) {
end_xPosition = event.pageX;
end_yPosition = event.pageY;
div2.style.left = end_xPosition - helperX;
div2.style.top = end_yPosition - helperY;
}
</script>
</body>
</html>

Categories